pax_global_header00006660000000000000000000000064145656670570014537gustar00rootroot0000000000000052 comment=f2a61c2eb58ccd666e34abfdb0fd7049ea073194 RenderKit-ospray-f2a61c2/000077500000000000000000000000001456566705700153475ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/.clang-format000066400000000000000000000055131456566705700177260ustar00rootroot00000000000000--- Language: Cpp # BasedOnStyle: Google AccessModifierOffset: -1 AlignAfterOpenBracket: DontAlign AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: false #EscapedNewlineAlignmentStyle: Right AlignEscapedNewlines: Right AlignOperands: false AlignTrailingComments: false AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: Empty #AllowShortLambdasOnASingleLine: Empty AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: true AlwaysBreakTemplateDeclarations: true BinPackArguments: false BinPackParameters: false BraceWrapping: AfterClass: true AfterControlStatement: false AfterEnum: true AfterFunction: true AfterNamespace: false AfterStruct: true AfterUnion: true BeforeCatch: false BeforeElse: false IndentBraces: false SplitEmptyFunction: false BreakBeforeBinaryOperators: NonAssignment BreakBeforeBraces: Custom BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false #BreakConstructorInitializersStyle: BeforeComma BreakStringLiterals: false ColumnLimit: 80 CommentPragmas: '^ IWYU pragma:' ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true DerivePointerAlignment: false DisableFormat: false ExperimentalAutoDetectBinPacking: false FixNamespaceComments: true ForEachMacros: [ foreach, foreach_active, foreach_tiled, foreach_unique, cdo, cfor, cif, cwhile ] IncludeCategories: - Regex: '^<.*\.i?h>' Priority: 1 - Regex: '^<.*' Priority: 2 - Regex: '.*' Priority: 3 IncludeIsMainRegex: '([-_](test|unittest))?$' IndentCaseLabels: false IndentWidth: 2 IndentWrappedFunctionNames: false KeepEmptyLinesAtTheStartOfBlocks: false MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: None PenaltyBreakBeforeFirstCallParameter: 1 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 200 #PPDirectiveIndentStyle: AfterHash PointerAlignment: Right ReflowComments: true SortIncludes: true SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true SpaceBeforeParens: ControlStatements SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInAngles: false SpacesInContainerLiterals: false SpacesInCStyleCastParentheses: false SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Cpp11 TabWidth: 2 UseTab: Never ... RenderKit-ospray-f2a61c2/.gitattributes000066400000000000000000000001051456566705700202360ustar00rootroot00000000000000*.rc text working-tree-encoding=UTF-16LE-BOM eol=CRLF *.patch eol=lf RenderKit-ospray-f2a61c2/.github/000077500000000000000000000000001456566705700167075ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/.github/workflows/000077500000000000000000000000001456566705700207445ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/.github/workflows/baseline.yml000066400000000000000000000035601456566705700232550ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 name: Baseline on: workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true permissions: read-all jobs: ### BUILD JOBS ### build-ubuntu2004-gcc: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: ubuntu:20.04 cmd: | scripts/build/linux.sh -G Ninja -DBUILD_GLFW=OFF -DBUILD_OSPRAY_MODULE_MULTIDEVICE=ON artifact-out: build-ubuntu2004-gcc artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt ### Benchmarks ### generate-ci-baseline-avx2: needs: build-ubuntu2004-gcc uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: ubuntu:20.04 runs-on: '"avx2"' cmd: | export LD_LIBRARY_PATH=$GITHUB_WORKSPACE/build/install/ospray/lib:$LD_LIBRARY_PATH export PATH=$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH scripts/tests/generate_baseline.sh artifact-in: build-ubuntu2004-gcc artifact-out: generate-ci-baseline-avx2 artifact-path: generated_test_images generate-ci-baseline-avx512skx: needs: build-ubuntu2004-gcc uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: ubuntu:20.04 cmd: | export LD_LIBRARY_PATH=$GITHUB_WORKSPACE/build/install/ospray/lib:$LD_LIBRARY_PATH export PATH=$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH scripts/tests/generate_baseline.sh artifact-in: build-ubuntu2004-gcc artifact-out: generate-ci-baseline-avx512skx artifact-path: generated_test_images RenderKit-ospray-f2a61c2/.github/workflows/benchmark.yml000066400000000000000000000060421456566705700234230ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 name: Benchmark on: schedule: - cron: '30 0 * * *' workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true permissions: read-all jobs: ### BUILD JOBS ### build-linux: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: rockylinux:8.7 env-from-files: .github/workflows/dpcpp.env cmd: | module load cmake/3.25.3 module load mpi/mpich-x86_64 export CC=clang export CXX=clang++ scripts/build/linux.sh -DBUILD_GPU_SUPPORT=ON artifact-out: build-linux artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt ### Benchmarks ### benchmark-x8280-1: needs: build-linux uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/perf.yml@main secrets: inherit with: runs-on: '"vis-perf-x8280-1"' setup-benny: true cmd: | scripts/tests/run-benchmarks.sh artifact-in: build-linux benchmark-x8380-1: needs: build-linux uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/perf.yml@main secrets: inherit with: runs-on: '"vis-perf-x8380-1"' setup-benny: true cmd: | scripts/tests/run-benchmarks.sh artifact-in: build-linux benchmark-a-1: needs: build-linux uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/perf.yml@main secrets: inherit with: runs-on: '"vis-perf-a3970x-1"' setup-benny: true cmd: | scripts/tests/run-benchmarks.sh artifact-in: build-linux benchmark-adl-1: needs: build-linux uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/perf.yml@main secrets: inherit with: runs-on: '"vis-perf-i9-12900k-1"' setup-benny: true cmd: | scripts/tests/run-benchmarks.sh artifact-in: build-linux benchmark-dg2: needs: build-linux uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: image: ubuntu:22.04 env-from-files: .github/workflows/gfx-ubuntu22.env options: --device=/dev/dri:/dev/dri runs-on: '"vis-perf-dg2-01"' setup-benny: true cmd: | scripts/tests/run-benchmarks.sh GPU artifact-in: build-linux benchmark-pvc: needs: build-linux uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: image: ubuntu:22.04 env-from-files: .github/workflows/gfx-ubuntu22.env options: --device=/dev/dri:/dev/dri runs-on: '"vis-perf-spr-pvc-01"' setup-benny: true cmd: | scripts/tests/run-benchmarks.sh GPU artifact-in: build-linux RenderKit-ospray-f2a61c2/.github/workflows/ci.linux.gpu.yml000066400000000000000000000234301456566705700240140ustar00rootroot00000000000000## Copyright 2022 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 name: CI Linux GPU on: push: workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true permissions: read-all jobs: ### BUILD JOBS ### ubu22-mpi-dpcpp-build: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: ubuntu:22.04 env-from-files: .github/workflows/dpcpp.env cmd: | module load cmake/3.25.3 export CC=clang export CXX=clang++ scripts/build/linux.sh -G Ninja -DBUILD_GLFW=OFF -DBUILD_GPU_SUPPORT=ON -DBUILD_OSPRAY_MODULE_MPI=ON -DBUILD_OSPRAY_MODULE_MULTIDEVICE=ON artifact-out: build-ubuntu2204-mpi-dpcpp artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt ubu22-mpi-icx-build: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: ubuntu:22.04 env-from-files: .github/workflows/icx-linux.env .github/workflows/gfx-ubuntu22.env # OIDN AOT needs ocloc cmd: | module load cmake/3.25.3 scripts/build/linux.sh -G Ninja -DBUILD_GLFW=OFF -DBUILD_GPU_SUPPORT=ON -DBUILD_OSPRAY_MODULE_MPI=ON -DBUILD_OSPRAY_MODULE_MULTIDEVICE=ON -DBUILD_EMBREE_FROM_SOURCE=ON -DBUILD_OIDN_FROM_SOURCE=ON artifact-out: build-ubuntu2204-mpi-icx artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt suse-icx-build: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: opensuse/leap:15.3 env-from-files: .github/workflows/icx-linux.env cmd: | module load cmake/3.25.3 scripts/build/linux.sh -DBUILD_GPU_SUPPORT=ON -DBUILD_EMBREE_FROM_SOURCE=ON rocky8-mpich-dpcpp-build: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: rockylinux:8.7 env-from-files: .github/workflows/dpcpp.env cmd: | module load cmake/3.25.3 module load mpi/mpich-x86_64 export CC=clang export CXX=clang++ scripts/build/linux.sh -DBUILD_GPU_SUPPORT=ON -DBUILD_OSPRAY_MODULE_MPI=ON -DBUILD_OSPRAY_MODULE_MULTIDEVICE=ON artifact-out: build-rocky8-mpich-dpcpp artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt ### TEST JOBS ### dpcpp-dg2-ubu22-test: needs: ubu22-mpi-dpcpp-build uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: timeout-minutes: 100 image: ubuntu:22.04 env-from-files: .github/workflows/gfx-ubuntu22.env options: --device=/dev/dri:/dev/dri runs-on: '"dg2"' artifact-in: build-ubuntu2204-mpi-dpcpp artifact-out: test-ubuntu2204-dpcpp-dg2 artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true cmd: | module load cmake/3.25.3 export PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_gpu_tests.sh "$GITHUB_WORKSPACE" dpcpp-pvc-ubu22-test: needs: ubu22-mpi-dpcpp-build uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: timeout-minutes: 100 image: ubuntu:22.04 env-from-files: .github/workflows/gfx-ubuntu22.env options: --device=/dev/dri:/dev/dri runs-on: '"pvc"' artifact-in: build-ubuntu2204-mpi-dpcpp artifact-out: test-ubuntu2204-dpcpp-pvc artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true cmd: | module load cmake/3.25.3 export PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_gpu_tests.sh "$GITHUB_WORKSPACE" mpi-dpcpp-pvc-ubu22-test: needs: ubu22-mpi-dpcpp-build uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: timeout-minutes: 100 image: ubuntu:22.04 env-from-files: .github/workflows/gfx-ubuntu22.env options: --device=/dev/dri:/dev/dri runs-on: '"pvc"' artifact-in: build-ubuntu2204-mpi-dpcpp artifact-out: test-ubuntu2204-mpi-dpcpp-pvc artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true cmd: | module load cmake/3.25.3 export PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" OMPI_ALLOW_RUN_AS_ROOT=1 OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 scripts/tests/run_gpu_tests.sh "$GITHUB_WORKSPACE" SKIP_GPU TEST_MPI multidev-dpcpp-pvc-ubu22-test: needs: ubu22-mpi-dpcpp-build uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: timeout-minutes: 100 image: ubuntu:22.04 env-from-files: .github/workflows/gfx-ubuntu22.env options: --device=/dev/dri:/dev/dri runs-on: '"pvc"' artifact-in: build-ubuntu2204-mpi-dpcpp artifact-out: test-ubuntu2204-multidev-dpcpp-pvc artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true cmd: | module load cmake/3.25.3 export PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_gpu_tests.sh "$GITHUB_WORKSPACE" SKIP_GPU TEST_MULTIDEVICE icx-dg2-ubu22-test: needs: ubu22-mpi-icx-build uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: timeout-minutes: 100 image: ubuntu:22.04 env-from-files: .github/workflows/icx-linux.env .github/workflows/gfx-ubuntu22.env options: --device=/dev/dri:/dev/dri runs-on: '"dg2"' artifact-in: build-ubuntu2204-mpi-icx artifact-out: test-ubuntu2204-icx-dg2 artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true cmd: | export PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_gpu_tests.sh "$GITHUB_WORKSPACE" mpi-icx-dg2-ubu22-test: needs: ubu22-mpi-icx-build uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: timeout-minutes: 100 image: ubuntu:22.04 env-from-files: .github/workflows/icx-linux.env .github/workflows/gfx-ubuntu22.env options: --device=/dev/dri:/dev/dri runs-on: '"dg2"' artifact-in: build-ubuntu2204-mpi-icx artifact-out: test-ubuntu2204-mpi-icx-dg2 artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true cmd: | export PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" OMPI_ALLOW_RUN_AS_ROOT=1 OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 scripts/tests/run_gpu_tests.sh "$GITHUB_WORKSPACE" SKIP_GPU TEST_MPI icx-pvc-ubu22-test: needs: ubu22-mpi-icx-build uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: timeout-minutes: 100 image: ubuntu:22.04 env-from-files: .github/workflows/icx-linux.env .github/workflows/gfx-ubuntu22.env options: --device=/dev/dri:/dev/dri runs-on: '"pvc"' artifact-in: build-ubuntu2204-mpi-icx artifact-out: test-ubuntu2204-icx-pvc artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true cmd: | export PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_gpu_tests.sh "$GITHUB_WORKSPACE" mpi-icx-pvc-ubu22-test: needs: ubu22-mpi-icx-build uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: timeout-minutes: 100 image: ubuntu:22.04 env-from-files: .github/workflows/icx-linux.env .github/workflows/gfx-ubuntu22.env options: --device=/dev/dri:/dev/dri runs-on: '"pvc"' artifact-in: build-ubuntu2204-mpi-icx artifact-out: test-ubuntu2204-mpi-icx-pvc artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true cmd: | export PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" OMPI_ALLOW_RUN_AS_ROOT=1 OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 scripts/tests/run_gpu_tests.sh "$GITHUB_WORKSPACE" SKIP_GPU TEST_MPI multidev-icx-pvc-ubu22-test: needs: ubu22-mpi-icx-build uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: timeout-minutes: 100 image: ubuntu:22.04 env-from-files: .github/workflows/icx-linux.env .github/workflows/gfx-ubuntu22.env options: --device=/dev/dri:/dev/dri runs-on: '"pvc"' artifact-in: build-ubuntu2204-mpi-icx artifact-out: test-ubuntu2204-multidev-icx-pvc artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true cmd: | export PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_gpu_tests.sh "$GITHUB_WORKSPACE" SKIP_GPU TEST_MULTIDEVICE RenderKit-ospray-f2a61c2/.github/workflows/ci.linux.yml000066400000000000000000000437621456566705700232340ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 name: CI Linux on: push: workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true permissions: read-all jobs: ### BUILD JOBS ### build-arch-clang: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: ospray/docker-images:arch cmd: | export CC=clang export CXX=clang++ scripts/build/linux.sh -G Ninja -DBUILD_GLFW=OFF build-arch-clang-extras: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: ospray/docker-images:arch cmd: | export CC=clang export CXX=clang++ scripts/build/linux.sh -G Ninja -DBUILD_GLFW=OFF -DBUILD_OSPRAY_CI_EXTRAS=ON -DBUILD_OSPRAY_MODULE_MPI=ON -DBUILD_OSPRAY_MODULE_MULTIDEVICE=ON build-arch-gcc: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: ospray/docker-images:arch cmd: | scripts/build/linux.sh -G Ninja -DBUILD_GLFW=OFF build-arch-gcc-extras: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: ospray/docker-images:arch cmd: | scripts/build/linux.sh -G Ninja -DBUILD_GLFW=OFF -DBUILD_OSPRAY_CI_EXTRAS=ON build-centos7-gcc: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: centos:7 cmd: | scripts/build/linux.sh -DBUILD_EMBREE_FROM_SOURCE=ON -DBUILD_OIDN=OFF -DBUILD_ISA_AVX512=OFF -DTBB_VERSION=2021.9.0 artifact-out: build-centos7-gcc artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt # TODO: Update to newer ICC compiler? # build-centos7-icc: # uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main # secrets: inherit # with: # force-delete: true # guarantees .gitattributes are respected in working dir # image: centos:7-devenv # cmd: | # module load cmake # module load intel # export CC=icc # export CXX=icpc # scripts/build/linux.sh # TODO: Update to newer ICC compiler? # build-centos7-icc15: # uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main # secrets: inherit # with: # force-delete: true # guarantees .gitattributes are respected in working dir # image: centos:7-devenv # cmd: | # module load cmake # module load intel/2015 # export CC=icc # export CXX=icpc # scripts/build/linux.sh build-centos7-icx: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: centos:7 cmd: | module load cmake module load intel/2022.1 export CC=icx export CXX=icpx export CXXFLAGS="-fhonor-infinities -fhonor-nans" export CFLAGS=$CXXFLAGS export LDFLAGS="-static-intel" scripts/build/linux.sh -DBUILD_EMBREE_FROM_SOURCE=ON -DBUILD_OIDN=OFF -DTBB_VERSION=2021.9.0 artifact-out: build-centos7-icx artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt build-centos7-mpi-impi: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: centos:7 cmd: | module load cmake module load impi/2021.6 scripts/build/linux.sh -DBUILD_EMBREE_FROM_SOURCE=ON -DBUILD_OIDN=OFF -DBUILD_OSPRAY_MODULE_MPI=ON -DBUILD_ISA_AVX512=OFF -DTBB_VERSION=2021.9.0 build-centos7-mpi-mpich: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: centos:7 cmd: | module load cmake module load mpi/mpich-x86_64 scripts/build/linux.sh -DBUILD_EMBREE_FROM_SOURCE=ON -DBUILD_OIDN=OFF -DBUILD_OSPRAY_MODULE_MPI=ON -DBUILD_ISA_AVX512=OFF -DTBB_VERSION=2021.9.0 artifact-out: build-centos7-mpi-mpich artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt build-centos7-mpi-openmpi: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: centos:7 cmd: | module load cmake module load mpi/openmpi-x86_64 scripts/build/linux.sh -DBUILD_EMBREE_FROM_SOURCE=ON -DBUILD_OIDN=OFF -DBUILD_OSPRAY_MODULE_MPI=ON -DBUILD_ISA_AVX512=OFF -DTBB_VERSION=2021.9.0 build-centos8: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: centos:8 cmd: | scripts/build/linux.sh -G Ninja artifact-out: build-centos8 artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt build-centos8-mpi-mpich: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: centos:8 cmd: | module load mpi/mpich-x86_64 scripts/build/linux.sh -DBUILD_OSPRAY_MODULE_MPI=ON build-centos8-mpi-openmpi: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: centos:8 cmd: | module load mpi/openmpi-x86_64 scripts/build/linux.sh -DBUILD_OSPRAY_MODULE_MPI=ON build-rocky8-oidn-mpi: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: rockylinux:8.7 cmd: | module load cmake/3.15.2 module load mpi/mpich-x86_64 scripts/build/linux.sh -DBUILD_OSPRAY_MODULE_MPI=ON artifact-out: build-rocky8-oidn-mpi artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt build-linux-debug: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: ospray/docker-images:arch cmd: | export CFLAGS=-fsanitize=address export CXXFLAGS=-fsanitize=address export LDFLAGS=-fsanitize=address scripts/build/linux.sh -G Ninja -DBUILD_GLFW=OFF -DCMAKE_BUILD_TYPE=Debug -DBUILD_OIDN=OFF artifact-out: build-linux-debug artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt build/install/embree build-ubuntu1804-gcc: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: ubuntu:18.04 cmd: | scripts/build/linux.sh -G Ninja -DBUILD_GLFW=OFF artifact-out: build-ubuntu1804-gcc artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt build-ubuntu2004-gcc: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: ubuntu:20.04 cmd: | scripts/build/linux.sh -G Ninja -DBUILD_GLFW=OFF -DBUILD_OSPRAY_MODULE_MULTIDEVICE=ON artifact-out: build-ubuntu2004-gcc artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt build-ubuntu2204-oidn-mpi: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: ubuntu:22.04 cmd: | scripts/build/linux.sh -DBUILD_OSPRAY_MODULE_MPI=ON artifact-out: build-ubuntu2204-oidn-mpi artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt build-ubuntu2204-arm: secrets: inherit uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/perf.yml@main with: runs-on: '[ "Linux", "ARM64" ]' cmd: | scripts/build/linux.sh -DBUILD_GLFW=OFF -DBUILD_TBB_FROM_SOURCE=ON -DBUILD_EMBREE_FROM_SOURCE=ON -DBUILD_OIDN_FROM_SOURCE=ON artifact-out: build-ubuntu2204-arm artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt ### TEST JOBS ### test-centos7-gcc-avx2: needs: build-centos7-gcc uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: centos:7 cmd: | PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$GITHUB_WORKSPACE" AVX2 artifact-in: build-centos7-gcc artifact-out: test-centos7-gcc-avx2 artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true test-centos7-gcc-mpi-mpich-avx2: needs: build-centos7-mpi-mpich uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: centos:7 cmd: | module load cmake module load mpi/mpich-x86_64 PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$GITHUB_WORKSPACE" AVX2 TEST_MPI artifact-in: build-centos7-mpi-mpich artifact-out: test-centos7-gcc-mpi-mpich-avx2 artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true test-centos7-icx-avx2: needs: build-centos7-icx uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: centos:7 runs-on: '"avx2"' cmd: | PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$GITHUB_WORKSPACE" AVX2 artifact-in: build-centos7-icx artifact-out: test-centos7-icx-avx2 artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true test-centos7-icx-avx512skx: needs: build-centos7-icx uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: centos:7 runs-on: '"avx512"' cmd: | PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$GITHUB_WORKSPACE" AVX512SKX artifact-in: build-centos7-icx artifact-out: test-centos7-icx-avx512skx artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true test-centos8-avx512skx: needs: build-centos8 uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: centos:8 runs-on: '"avx512"' cmd: | PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$GITHUB_WORKSPACE" AVX512SKX artifact-in: build-centos8 artifact-out: test-centos8-avx512skx artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true test-rocky8-oidn-mpi-avx512skx: needs: build-rocky8-oidn-mpi uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: rockylinux:8.7 runs-on: '"avx512"' cmd: | module load cmake/3.15.2 module load mpi/mpich-x86_64 export OIDN_DEFAULT_DEVICE=cpu PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$GITHUB_WORKSPACE" AVX512SKX TEST_MPI artifact-in: build-rocky8-oidn-mpi artifact-out: test-rocky8-oidn-mpi-avx512skx artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true test-find-ospray: needs: build-centos7-gcc uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: centos:7 cmd: | module load cmake mkdir buildtut cd buildtut cmake -D ospray_DIR=`echo $GITHUB_WORKSPACE/build/install/ospray/lib/cmake/ospray-*` ../apps/ospTutorial/ospTutorialFindospray cmake --build . artifact-in: build-centos7-gcc test-ubuntu1804-gcc-avx512skx: needs: build-ubuntu1804-gcc uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: ubuntu:18.04 runs-on: '"avx512"' cmd: | PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$GITHUB_WORKSPACE" AVX512SKX artifact-in: build-ubuntu1804-gcc artifact-out: test-ubuntu1804-gcc-avx512skx artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true test-ubuntu2004-gcc-avx2: needs: build-ubuntu2004-gcc uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: ubuntu:20.04 runs-on: '"avx2"' cmd: | PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$GITHUB_WORKSPACE" AVX2 artifact-in: build-ubuntu2004-gcc artifact-out: test-ubuntu2004-gcc-avx2 artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true test-ubuntu2004-gcc-avx512skx: needs: build-ubuntu2004-gcc uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: ubuntu:20.04 runs-on: '"avx512"' cmd: | PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$GITHUB_WORKSPACE" AVX512SKX TEST_MULTIDEVICE artifact-in: build-ubuntu2004-gcc artifact-out: test-ubuntu2004-gcc-avx512skx artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true test-ubuntu2204-oidn-mpi-avx2-dg2: needs: build-ubuntu2204-oidn-mpi uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: image: ubuntu:22.04 env-from-files: .github/workflows/dpcpp.env .github/workflows/gfx-ubuntu22.env submodules: true options: --device=/dev/dri:/dev/dri runs-on: '"dg2"' cmd: | export PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" export OIDN_DEFAULT_DEVICE=sycl export OIDN_VERBOSE=2 mkdir build_regression_tests cd build_regression_tests cmake -D OSPRAY_TEST_ISA=AVX2 $GITHUB_WORKSPACE/test_image_data cmake --build . --target ospray_test_data ospTestSuite --baseline-dir=regression_test_baseline --gtest_filter="DenoiserOp.DenoiserOp" OMPI_ALLOW_RUN_AS_ROOT=1 OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 mpiexec -np 1 ospTestSuite --baseline-dir=regression_test_baseline --gtest_filter="DenoiserOp.DenoiserOp" --osp:load-modules=mpi_offload --osp:device=mpiOffload : -np 2 ospray_mpi_worker artifact-in: build-ubuntu2204-oidn-mpi test-ubuntu2204-arm: needs: build-ubuntu2204-arm uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/perf.yml@main with: runs-on: '[ "Linux", "ARM64" ]' cmd: | PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$GITHUB_WORKSPACE" AVX512SKX artifact-in: build-ubuntu2204-arm artifact-out: test-ubuntu2204-arm artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* #artifact-on-failure: true test-tutorials: needs: build-centos7-gcc uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: centos:7 cmd: scripts/tests/run_tutorials.sh artifact-in: build-centos7-gcc sanitize-linux-debug: needs: build-linux-debug uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: ospray/docker-images:arch cmd: | export LSAN_OPTIONS="suppressions=$GITHUB_WORKSPACE/scripts/tests/sanitize_ignore.txt" export PATH=$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH export LD_LIBRARY_PATH=$GITHUB_WORKSPACE/build/install/embree/lib:$GITHUB_WORKSPACE/build/install/ospray/lib:$LD_LIBRARY_PATH export TBB_ENABLE_SANITIZERS=1 export ASAN_OPTIONS=intercept_tls_get_addr=0 # WA https://github.com/google/sanitizers/issues/1322 scripts/tests/run_tests.sh $GITHUB_WORKSPACE AVX512SKX build/install/ospray/bin/ospBenchmark --benchmark_min_time=0s artifact-in: build-linux-debug RenderKit-ospray-f2a61c2/.github/workflows/ci.macos.yml000066400000000000000000000066471456566705700232000ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 name: CI MacOS on: push: workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true permissions: read-all jobs: ### BUILD JOBS ### build-osx-clang: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir runs-on: '["x86_64", "build"]' cmd: | scripts/build/macosx.sh -DBUILD_OSPRAY_MODULE_MULTIDEVICE=ON artifact-out: build-osx-clang artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt build-osx-arm: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir runs-on: '["arm", "build"]' cmd: | scripts/build/macosx.sh -DBUILD_TBB_FROM_SOURCE=ON artifact-out: build-osx-arm artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt build-osx-x64-on-arm: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir runs-on: '["arm", "build"]' cmd: | scripts/build/macosx.sh -DCMAKE_TOOLCHAIN_FILE=../scripts/superbuild/toolchains/macos-rosetta.cmake -DBUILD_TBB_FROM_SOURCE=ON -DBUILD_EMBREE_FROM_SOURCE=ON -DBUILD_OIDN_FROM_SOURCE=ON -DBUILD_ISA_AVX=OFF -DBUILD_ISA_AVX2=OFF -DBUILD_ISA_AVX512=OFF artifact-out: build-osx-x64 artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt ### TEST JOBS ### test-osx-clang: needs: build-osx-clang uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main with: runs-on: '["x86_64", "avx2", "build"]' cmd: | export PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$GITHUB_WORKSPACE" AVX2 TEST_MULTIDEVICE artifact-in: build-osx-clang artifact-out: test-osx-clang artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true test-osx-arm: needs: build-osx-arm uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main with: runs-on: '["arm", "build"]' cmd: | export PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$GITHUB_WORKSPACE" AVX512SKX artifact-in: build-osx-arm artifact-out: test-osx-arm artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true test-osx-x64-on-arm: needs: build-osx-x64-on-arm uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main with: runs-on: '["arm", "build"]' cmd: | export PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$GITHUB_WORKSPACE" AVX512SKX artifact-in: build-osx-x64 artifact-out: test-osx-x64 artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true RenderKit-ospray-f2a61c2/.github/workflows/ci.windows.gpu.yml000066400000000000000000000115761456566705700243570ustar00rootroot00000000000000## Copyright 2023 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 name: CI Windows GPU on: push: workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true permissions: read-all jobs: ### BUILD JOBS ### dpcpp-build: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows_gpu.yml@main secrets: inherit with: force-delete: true runs-on: '["build", "mpi"]' env-from-files: .github/workflows/dpcpp.env cmd: | $env:SYCL_BUNDLE_ROOT = $env:DPCPP_ROOT # disable warnings which lead to excessively large log files $env:CXXFLAGS = '-w' $env:CFLAGS = '-w' scripts\build\win.ps1 -G Ninja -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_C_COMPILER=clang-cl -DBUILD_GPU_SUPPORT=ON -DBUILD_OSPRAY_MODULE_MPI=ON artifact-out: build-windows-dpcpp artifact-path: build/install/ospray build/CMakeCache.txt build/ospray/build/CMakeCache.txt icx-build: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows_gpu.yml@main secrets: inherit with: force-delete: true runs-on: '["build", "mpi"]' env-from-files: .github/workflows/icx-windows.env ocloc-version: 77a13ae6-6100-4ddc-b069-0086ff44730c/ocloc_win_101.5082 cmd: | # disable warnings which lead to excessively large log files $env:CXXFLAGS = '-w' $env:CFLAGS = '-w' scripts\build\win.ps1 -G Ninja -DCMAKE_CXX_COMPILER=icx -DCMAKE_C_COMPILER=icx -DBUILD_GPU_SUPPORT=ON -DBUILD_OSPRAY_MODULE_MPI=ON -DBUILD_EMBREE_FROM_SOURCE=ON -DBUILD_OIDN_FROM_SOURCE=ON artifact-out: build-windows-icx artifact-path: build/install/ospray build/CMakeCache.txt build/ospray/build/CMakeCache.txt ### TEST JOBS ### dpcpp-test: needs: dpcpp-build uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows_gpu.yml@main secrets: inherit with: timeout-minutes: 100 runs-on: '"dg2"' env-from-files: .github/workflows/gfx-windows.env cmd: | $env:Path += ";$env:GITHUB_WORKSPACE\build\install\ospray\bin" scripts\tests\run_gpu_tests.ps1 "$env:GITHUB_WORKSPACE" artifact-in: build-windows-dpcpp artifact-out: test-windows-dpcpp artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true mpi-dpcpp-test: needs: dpcpp-build uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows_gpu.yml@main secrets: inherit with: timeout-minutes: 100 runs-on: '["dg2"]' # FIXME, "mpi" env-from-files: .github/workflows/gfx-windows.env cmd: | $env:Path += ";C:\Program Files (x86)\Intel\oneAPI\mpi\latest\libfabric\bin\utils;C:\Program Files (x86)\Intel\oneAPI\mpi\latest\libfabric\bin;C:\Program Files (x86)\Intel\oneAPI\mpi\latest\bin\release;C:\Program Files (x86)\Intel\oneAPI\mpi\latest\bin" $env:Path += ";$env:GITHUB_WORKSPACE\build\install\ospray\bin" scripts\tests\run_gpu_tests.ps1 "$env:GITHUB_WORKSPACE" SKIP_GPU TEST_MPI artifact-in: build-windows-dpcpp artifact-out: test-windows-dpcpp-mpi artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true icx-test: needs: icx-build uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows_gpu.yml@main secrets: inherit with: timeout-minutes: 100 runs-on: '"dg2"' env-from-files: .github/workflows/icx-windows.env .github/workflows/gfx-windows.env cmd: | $env:Path += ";$env:GITHUB_WORKSPACE\build\install\ospray\bin" scripts\tests\run_gpu_tests.ps1 "$env:GITHUB_WORKSPACE" artifact-in: build-windows-icx artifact-out: test-windows-icx artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true mpi-icx-test: needs: icx-build uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows_gpu.yml@main secrets: inherit with: timeout-minutes: 100 runs-on: '["dg2"]' # FIXME, "mpi" env-from-files: .github/workflows/icx-windows.env .github/workflows/gfx-windows.env cmd: | $env:Path += ";C:\Program Files (x86)\Intel\oneAPI\mpi\latest\libfabric\bin\utils;C:\Program Files (x86)\Intel\oneAPI\mpi\latest\libfabric\bin;C:\Program Files (x86)\Intel\oneAPI\mpi\latest\bin\release;C:\Program Files (x86)\Intel\oneAPI\mpi\latest\bin" $env:Path += ";$env:GITHUB_WORKSPACE\build\install\ospray\bin" scripts\tests\run_gpu_tests.ps1 "$env:GITHUB_WORKSPACE" SKIP_GPU TEST_MPI artifact-in: build-windows-icx artifact-out: test-windows-icx-mpi artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true RenderKit-ospray-f2a61c2/.github/workflows/ci.windows.yml000066400000000000000000000111231456566705700235510ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 name: CI Windows on: push: workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true permissions: read-all jobs: ### BUILD JOBS ### build-windows-msvc15: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir cmd: | scripts\build\win.ps1 -G "Visual Studio 15 2017 Win64" artifact-out: build-windows-msvc15 artifact-path: build/install/ospray build/CMakeCache.txt build/ospray/build/CMakeCache.txt build-windows-msvc16-mpi_and_md: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir runs-on: '["build", "mpi"]' cmd: | scripts\build\win.ps1 -G "Visual Studio 16 2019" -DBUILD_OSPRAY_MODULE_MPI=ON -DBUILD_OSPRAY_MODULE_MULTIDEVICE=ON artifact-out: build-windows-msvc16-mpi_and_md artifact-path: build/install/ospray build/CMakeCache.txt build/ospray/build/CMakeCache.txt build-windows-msvc17: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir cmd: | scripts\build\win.ps1 -G "Visual Studio 17 2022" artifact-out: build-windows-msvc17 artifact-path: build/install/ospray build/CMakeCache.txt build/ospray/build/CMakeCache.txt ### TEST JOBS ### test-windows-msvc15-avx2: needs: build-windows-msvc15 uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main with: runs-on: '"avx2"' cmd: | $env:Path += ";$env:GITHUB_WORKSPACE\build\install\ospray\bin" scripts\tests\run_tests.ps1 "$env:GITHUB_WORKSPACE" AVX2 artifact-in: build-windows-msvc15 artifact-out: test-windows-msvc15-avx2 artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true test-windows-msvc15-avx512skx: needs: build-windows-msvc15 uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main with: runs-on: '"avx512"' cmd: | $env:Path += ";$env:GITHUB_WORKSPACE\build\install\ospray\bin" scripts\tests\run_tests.ps1 "$env:GITHUB_WORKSPACE" AVX512SKX artifact-in: build-windows-msvc15 artifact-out: test-windows-msvc15-avx512 artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true test-windows-msvc16-avx2: needs: build-windows-msvc16-mpi_and_md uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main with: runs-on: '["avx2", "mpi"]' cmd: | $env:Path += ";$env:GITHUB_WORKSPACE\build\install\ospray\bin" scripts\tests\run_tests.ps1 "$env:GITHUB_WORKSPACE" AVX2 TEST_MULTIDEVICE TEST_MPI artifact-in: build-windows-msvc16-mpi_and_md artifact-out: test-windows-msvc16-mpi_and_md-avx2 artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true test-windows-msvc16-avx512skx: needs: build-windows-msvc16-mpi_and_md uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main with: runs-on: '["avx512", "mpi"]' cmd: | $env:Path += ";$env:GITHUB_WORKSPACE\build\install\ospray\bin" echo $env:Path scripts\tests\run_tests.ps1 "$env:GITHUB_WORKSPACE" AVX512SKX TEST_MULTIDEVICE TEST_MPI artifact-in: build-windows-msvc16-mpi_and_md artifact-out: test-windows-msvc16-mpi_and_md-avx512skx artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true test-windows-msvc17: needs: build-windows-msvc17 uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main with: runs-on: '"avx512"' cmd: | $env:Path += ";$env:GITHUB_WORKSPACE\build\install\ospray\bin" scripts\tests\run_tests.ps1 "$env:GITHUB_WORKSPACE" AVX512SKX artifact-in: build-windows-msvc17 artifact-out: test-windows-msvc17-avx512 artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true RenderKit-ospray-f2a61c2/.github/workflows/dpcpp.env000066400000000000000000000000571456566705700225660ustar00rootroot00000000000000DPCPP_VERSION=intel-llvm/nightly-2023-10-26-rk RenderKit-ospray-f2a61c2/.github/workflows/gfx-ubuntu22.env000066400000000000000000000000401456566705700237200ustar00rootroot00000000000000GFX_DRIVER_VERSION=linux-latest RenderKit-ospray-f2a61c2/.github/workflows/gfx-windows.env000066400000000000000000000000441456566705700237300ustar00rootroot00000000000000GFX_DRIVER_VERSION=windows-101.5186 RenderKit-ospray-f2a61c2/.github/workflows/icx-linux.env000066400000000000000000000000331456566705700233720ustar00rootroot00000000000000DPCPP_VERSION=intel/2024.0 RenderKit-ospray-f2a61c2/.github/workflows/icx-windows.env000066400000000000000000000000551456566705700237310ustar00rootroot00000000000000DPCPP_VERSION=icx/compiler_ppkg-rel/20240201 RenderKit-ospray-f2a61c2/.github/workflows/release.yml000066400000000000000000000474061456566705700231220ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 name: Release on: push: branches: - devel - '**release**' - master workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true permissions: read-all jobs: ### DOC JOBS ### pdf: secrets: inherit uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: force-delete: true image: ospray/docker-images:docu submodules: true cmd: | cd doc git clone --depth 1 -b release-2.12.x https://${RENDERKIT_GITHUB_TOKEN}@github.com/intel-innersource/documentation.graphics.renderkit.ospray-website.git ospray-doc make pdf make checklinks artifact-out: pdf artifact-path: readme.pdf ### BUILD JOBS ### release-linux: needs: pdf uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir image: rockylinux:8.7 env-from-files: .github/workflows/dpcpp.env cmd: | module load cmake/3.25.3 module load mpi/mpich-x86_64 export CC=clang export CXX=clang++ scripts/release/linux.sh cp build_release/*.gz $STORAGE_PATH/packages/renderkit/ || true artifact-in: pdf artifact-out: release-linux artifact-path: build_release/*.gz release-linux-arm: needs: pdf uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/perf.yml@main secrets: inherit with: runs-on: '[ "Linux", "ARM64" ]' env-from-files: .github/workflows/dpcpp.env cmd: | scripts/release/linux.sh -DBUILD_GLFW=OFF -DBUILD_TBB_FROM_SOURCE=ON -DBUILD_EMBREE_FROM_SOURCE=ON -DBUILD_OIDN_FROM_SOURCE=ON cp build_release/*.gz $STORAGE_PATH/packages/renderkit/ || true artifact-in: pdf artifact-out: release-linux-arm artifact-path: build_release/*.gz release-osx: needs: pdf secrets: inherit uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main with: force-delete: true # guarantees .gitattributes are respected in working dir runs-on: '["sign", "x86_64"]' cmd: | export CC=clang export CXX=clang++ scripts/release/macosx.sh cp build_release/*.zip $STORAGE_PATH/packages/renderkit/ || true artifact-in: pdf artifact-out: release-osx artifact-path: build_release/*.zip release-osx-arm: needs: pdf secrets: inherit uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main with: force-delete: true # guarantees .gitattributes are respected in working dir runs-on: '["arm", "build"]' cmd: | scripts/release/macosx.sh -DBUILD_TBB_FROM_SOURCE=ON cp build_release/*.zip $STORAGE_PATH/packages/renderkit/ || true artifact-in: pdf artifact-out: release-osx-arm artifact-path: build_release/*.zip release-windows: needs: pdf uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows_gpu.yml@main secrets: inherit with: force-delete: true # guarantees .gitattributes are respected in working dir runs-on: '["build", "mpi"]' env-from-files: .github/workflows/dpcpp.env cmd: | $env:SYCL_BUNDLE_ROOT = $env:DPCPP_ROOT # disable warnings which lead to excessively large log files $env:CXXFLAGS = '-w' $env:CFLAGS = '-w' $exitCode = 0 # keep job status to properly fail scripts\release\win.ps1 -G Ninja -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_C_COMPILER=clang-cl if ($LastExitCode) { $exitCode++ } & $env:SIGN_FILE_WINDOWS ospray*.msi if ($LastExitCode) { $exitCode++ } cp (Get-ChildItem *.zip | Select-Object -Expand FullName) $env:STORAGE_PATH/packages/renderkit/ cp (Get-ChildItem *.msi | Select-Object -Expand FullName) $env:STORAGE_PATH/packages/renderkit/ exit $exitCode artifact-in: pdf artifact-out: release-windows artifact-path: "build_release/ospray*.zip build_release/ospray*.msi" ### SCAN JOBS ### static-analysis: secrets: inherit uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/static_analysis.yml@main with: coverity: true project: OSPRay prebuild: > module load impi/latest && echo "Configure dependencies" && cmake -L -S scripts/superbuild -B build_deps -DBUILD_DEPENDENCIES_ONLY=ON -DBUILD_EMBREE_FROM_SOURCE=ON -DBUILD_OIDN_FROM_SOURCE=ON -DBUILD_OSPRAY_MODULE_MPI=ON -DINSTALL_IN_SEPARATE_DIRECTORIES=OFF -DBUILD_ISA_AVX512=OFF && echo "Build dependencies" && cmake --build build_deps && INSTALL_DIR=$(pwd)/build_deps/install && export CMAKE_PREFIX_PATH=${INSTALL_DIR} && echo "Configure OSPRay" && cmake -L -S . -B build -DTBB_ROOT=$INSTALL_DIR -DOSPRAY_MODULE_DENOISER=ON -DOSPRAY_MODULE_BILINEAR_PATCH=ON -DOSPRAY_MODULE_MPI=ON && echo "Done: Configure OSPRay" build: cmake --build build binary-analysis: needs: - release-linux - release-osx - release-windows secrets: inherit uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/binary_analysis.yml@main with: project: ospray artifact-in-linux: release-linux artifact-in-macos: release-osx artifact-in-windows: release-windows path: build_release/ospray-* binary-analysis-arm: needs: - release-linux-arm - release-osx-arm secrets: inherit uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/binary_analysis.yml@main with: project: ospray artifact-in-linux: release-linux-arm artifact-in-macos: release-osx-arm path: build_release/ospray-* antivirus-scan: needs: - release-linux - release-osx - release-windows secrets: inherit uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/antivirus_scan.yml@main with: project: ospray artifact-in-linux: release-linux artifact-in-macos: release-osx artifact-in-windows: release-windows path: build_release/ospray-* antivirus-scan-arm: needs: - release-linux-arm - release-osx-arm secrets: inherit uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/antivirus_scan.yml@main with: project: ospray artifact-in-linux: release-linux-arm artifact-in-macos: release-osx-arm path: build_release/ospray-* ### TEST JOBS ### test-rocky-cpu: needs: release-linux uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: rockylinux:8.7 cmd: | module load cmake/3.15.2 tar -xzf build_release/*.gz export PATH=$GITHUB_WORKSPACE/$(ls -d1 ./ospray-*/bin):$PATH scripts/tests/run_tests.sh $GITHUB_WORKSPACE AVX512SKX artifact-in: release-linux test-rocky-mpi-cpu: needs: release-linux uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: rockylinux:8.7 cmd: | module load cmake/3.15.2 module load mpi/mpich-x86_64 tar -xzf build_release/*.gz export PATH=$GITHUB_WORKSPACE/$(ls -d1 ./ospray-*/bin):$PATH scripts/tests/run_tests.sh $GITHUB_WORKSPACE AVX512SKX SKIP_CPU TEST_MPI artifact-in: release-linux test-ubuntu-oidnsycl: needs: release-linux uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main secrets: inherit with: timeout-minutes: 100 image: ubuntu:22.04 env-from-files: .github/workflows/gfx-ubuntu22.env options: --device=/dev/dri:/dev/dri runs-on: '"dg2"' cmd: | module load cmake/3.15.2 tar -xzf build_release/*.gz export PATH=$GITHUB_WORKSPACE/$(ls -d1 ./ospray-*/bin):$PATH export OIDN_DEFAULT_DEVICE=sycl export OIDN_VERBOSE=2 mkdir build_regression_tests cd build_regression_tests cmake -G Ninja -D OSPRAY_TEST_ISA=AVX2 $GITHUB_WORKSPACE/test_image_data cmake --build . --target ospray_test_data ospTestSuite --baseline-dir=regression_test_baseline --gtest_filter="DenoiserOp.DenoiserOp" artifact-in: release-linux test-ubuntu-cpu: needs: release-linux uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: ubuntu:22.04 cmd: | tar -xzf build_release/*.gz export OIDN_VERBOSE=2 export PATH=$GITHUB_WORKSPACE/$(ls -d1 ./ospray-*/bin):$PATH scripts/tests/run_tests.sh $GITHUB_WORKSPACE AVX512SKX artifact-in: release-linux test-ubuntu-mpi-cpu: needs: release-linux uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: ubuntu:22.04 cmd: | tar -xzf build_release/*.gz update-alternatives --set mpi-x86_64-linux-gnu /usr/include/x86_64-linux-gnu/mpich update-alternatives --set mpirun /usr/bin/mpirun.mpich OSPDIR=$GITHUB_WORKSPACE/$(ls -d1 ./ospray-*/) ln -s /usr/lib/x86_64-linux-gnu/libmpich.so.12 $OSPDIR/lib/libmpi.so.12 # XXX find better way ln -s /usr/lib/x86_64-linux-gnu/libmpichcxx.so.12 $OSPDIR/lib/libmpicxx.so.12 export OIDN_VERBOSE=2 export PATH=$OSPDIR/bin:$PATH scripts/tests/run_tests.sh $GITHUB_WORKSPACE AVX512SKX SKIP_CPU TEST_MPI artifact-in: release-linux test-ubuntu-dg2: needs: release-linux uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main with: timeout-minutes: 100 image: ubuntu:22.04 runs-on: '"dg2"' env-from-files: .github/workflows/gfx-ubuntu22.env options: --device=/dev/dri:/dev/dri cmd: | tar -xzf build_release/*.gz export PATH=$GITHUB_WORKSPACE/$(ls -d1 ./ospray-*/bin):$PATH scripts/tests/run_gpu_tests.sh $GITHUB_WORKSPACE artifact-in: release-linux test-ubuntu-mpi-dg2: needs: release-linux uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main with: timeout-minutes: 100 image: ubuntu:22.04 runs-on: '"dg2"' env-from-files: .github/workflows/gfx-ubuntu22.env options: --device=/dev/dri:/dev/dri cmd: | tar -xzf build_release/*.gz update-alternatives --set mpi-x86_64-linux-gnu /usr/include/x86_64-linux-gnu/mpich update-alternatives --set mpirun /usr/bin/mpirun.mpich OSPDIR=$GITHUB_WORKSPACE/$(ls -d1 ./ospray-*/) ln -s /usr/lib/x86_64-linux-gnu/libmpich.so.12 $OSPDIR/lib/libmpi.so.12 # XXX find better way ln -s /usr/lib/x86_64-linux-gnu/libmpichcxx.so.12 $OSPDIR/lib/libmpicxx.so.12 export OIDN_VERBOSE=2 export PATH=$OSPDIR/bin:$PATH scripts/tests/run_gpu_tests.sh $GITHUB_WORKSPACE SKIP_GPU TEST_MPI artifact-in: release-linux test-ubuntu-pvc: needs: release-linux uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main with: timeout-minutes: 100 image: ubuntu:22.04 runs-on: '"pvc"' env-from-files: .github/workflows/gfx-ubuntu22.env options: --device=/dev/dri:/dev/dri cmd: | tar -xzf build_release/*.gz export PATH=$GITHUB_WORKSPACE/$(ls -d1 ./ospray-*/bin):$PATH scripts/tests/run_gpu_tests.sh $GITHUB_WORKSPACE artifact-in: release-linux test-ubuntu-mpi-pvc: needs: release-linux uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker_gpu.yml@main with: timeout-minutes: 100 image: ubuntu:22.04 runs-on: '"pvc"' env-from-files: .github/workflows/gfx-ubuntu22.env options: --device=/dev/dri:/dev/dri cmd: | tar -xzf build_release/*.gz update-alternatives --set mpi-x86_64-linux-gnu /usr/include/x86_64-linux-gnu/mpich update-alternatives --set mpirun /usr/bin/mpirun.mpich OSPDIR=$GITHUB_WORKSPACE/$(ls -d1 ./ospray-*/) ln -s /usr/lib/x86_64-linux-gnu/libmpich.so.12 $OSPDIR/lib/libmpi.so.12 # XXX find better way ln -s /usr/lib/x86_64-linux-gnu/libmpichcxx.so.12 $OSPDIR/lib/libmpicxx.so.12 export OIDN_VERBOSE=2 export PATH=$OSPDIR/bin:$PATH scripts/tests/run_gpu_tests.sh $GITHUB_WORKSPACE SKIP_GPU TEST_MPI artifact-in: release-linux test-ubuntu-cpu-arm: needs: release-linux-arm uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/perf.yml@main with: runs-on: '[ "Linux", "ARM64" ]' cmd: | tar -xzf build_release/*.gz export OIDN_VERBOSE=2 export PATH=$GITHUB_WORKSPACE/$(ls -d1 ./ospray-*/bin):$PATH scripts/tests/run_tests.sh $GITHUB_WORKSPACE AVX512SKX artifact-in: release-linux-arm test-ubuntu-mpi-cpu-arm: needs: release-linux-arm uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/perf.yml@main with: runs-on: '[ "Linux", "ARM64" ]' cmd: | tar -xzf build_release/*.gz export OIDN_VERBOSE=2 export PATH=$GITHUB_WORKSPACE/$(ls -d1 ./ospray-*/bin):$PATH scripts/tests/run_tests.sh $GITHUB_WORKSPACE AVX512SKX SKIP_CPU TEST_MPI artifact-in: release-linux-arm test-osx-avx2: needs: release-osx uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main with: runs-on: '["x86_64", "build", "avx2"]' cmd: | unzip build_release/*.zip export PATH=$GITHUB_WORKSPACE/$(ls -d1 ./ospray-*/bin):$PATH scripts/tests/run_tests.sh $GITHUB_WORKSPACE AVX2 artifact-in: release-osx test-osx-avx512: needs: release-osx uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main with: runs-on: '["x86_64", "build", "avx512"]' cmd: | unzip build_release/*.zip export PATH=$GITHUB_WORKSPACE/$(ls -d1 ./ospray-*/bin):$PATH scripts/tests/run_tests.sh $GITHUB_WORKSPACE AVX512SKX artifact-in: release-osx test-osx-arm: needs: release-osx-arm uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main with: runs-on: '["arm", "build"]' cmd: | unzip build_release/*.zip export PATH=$GITHUB_WORKSPACE/$(ls -d1 ./ospray-*/bin):$PATH scripts/tests/run_tests.sh $GITHUB_WORKSPACE AVX512SKX artifact-in: release-osx-arm test-osx-signing: needs: release-osx uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main secrets: inherit with: runs-on: '["sign", "x86_64" ]' cmd: | unzip build_release/*.zip sign-path-verify: ospray-* artifact-in: release-osx test-osx-signing-arm: needs: release-osx-arm uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/macos.yml@main secrets: inherit with: runs-on: '"arm"' cmd: | unzip build_release/*.zip sign-path-verify: ospray-* artifact-in: release-osx-arm test-windows-signing: needs: release-windows uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main with: cmd: | $exitCode = 0 # keep job status to properly fail Expand-Archive build_release/*.zip -DestinationPath . if ($LastExitCode) { $exitCode++ } $msiFile = (Get-ChildItem build_release/*.msi | Select-Object -Expand FullName) Start-Process msiexec "/a $msiFile /qn TARGETDIR=$env:GITHUB_WORKSPACE" -Wait if ($LastExitCode) { $exitCode++ } # compare whether files in bin folder of archives are identical Get-ChildItem "ospray-*\bin\*" | Select-Object -Expand Name | % { if ((Get-FileHash "Intel\OSPRay*\bin\$_").hash -ne (Get-FileHash "ospray-*\bin\$_").hash) { $exitCode++ } } & $env:SIGN_FILE_WINDOWS -t build_release\*.msi (Get-ChildItem "Intel\OSPRay*\bin\*" | Select-Object -Expand FullName) if ($LastExitCode) { $exitCode++ } exit $exitCode artifact-in: release-windows test-windows-cpu: needs: release-windows uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main with: runs-on: '"avx512"' cmd: | Expand-Archive build_release/*.zip -DestinationPath . $env:Path += ";" + (Get-ChildItem ospray-*\bin | Select-Object -Expand FullName) scripts\tests\run_tests.ps1 $env:GITHUB_WORKSPACE AVX512SKX artifact-in: release-windows test-windows-mpi-cpu: needs: release-windows uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main with: runs-on: '["avx512", "mpi"]' cmd: | Expand-Archive build_release/*.zip -DestinationPath . $env:Path += ";" + (Get-ChildItem ospray-*\bin | Select-Object -Expand FullName) scripts\tests\run_tests.ps1 $env:GITHUB_WORKSPACE AVX512SKX SKIP_CPU TEST_MPI artifact-in: release-windows test-windows-oidnsycl: needs: release-windows uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows_gpu.yml@main secrets: inherit with: timeout-minutes: 100 runs-on: '"dg2"' force-delete: true env-from-files: .github/workflows/gfx-windows.env cmd: | Expand-Archive build_release/*.zip -DestinationPath . $env:Path += ";" + (Get-ChildItem ospray-*\bin | Select-Object -Expand FullName) $env:OIDN_DEFAULT_DEVICE="sycl" $env:OIDN_VERBOSE="2" md build_regression_tests cd build_regression_tests cmake -G Ninja -D OSPRAY_TEST_ISA=AVX2 $env:GITHUB_WORKSPACE\test_image_data cmake --build . --config Release --target ospray_test_data ospTestSuite.exe --baseline-dir=regression_test_baseline --gtest_filter="DenoiserOp.DenoiserOp" artifact-in: release-windows test-windows-dg2: needs: release-windows uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows_gpu.yml@main with: timeout-minutes: 100 runs-on: '"dg2"' env-from-files: .github/workflows/gfx-windows.env cmd: | $env:Path += ";C:\Program Files (x86)\Intel\oneAPI\mpi\latest\libfabric\bin\utils;C:\Program Files (x86)\Intel\oneAPI\mpi\latest\libfabric\bin;C:\Program Files (x86)\Intel\oneAPI\mpi\latest\bin\release;C:\Program Files (x86)\Intel\oneAPI\mpi\latest\bin" Expand-Archive build_release/*.zip -DestinationPath . $env:Path += ";" + (Get-ChildItem ospray-*\bin | Select-Object -Expand FullName) scripts\tests\run_gpu_tests.ps1 $env:GITHUB_WORKSPACE artifact-in: release-windows test-windows-mpi-dg2: needs: release-windows uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows_gpu.yml@main with: timeout-minutes: 100 runs-on: '"dg2"' # FIXME: mpi env-from-files: .github/workflows/gfx-windows.env cmd: | $env:Path += ";C:\Program Files (x86)\Intel\oneAPI\mpi\latest\libfabric\bin\utils;C:\Program Files (x86)\Intel\oneAPI\mpi\latest\libfabric\bin;C:\Program Files (x86)\Intel\oneAPI\mpi\latest\bin\release;C:\Program Files (x86)\Intel\oneAPI\mpi\latest\bin" Expand-Archive build_release/*.zip -DestinationPath . $env:Path += ";" + (Get-ChildItem ospray-*\bin | Select-Object -Expand FullName) scripts\tests\run_gpu_tests.ps1 $env:GITHUB_WORKSPACE SKIP_GPU TEST_MPI artifact-in: release-windows RenderKit-ospray-f2a61c2/.github/workflows/scheduled.yml000066400000000000000000000103621456566705700234310ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 name: Scheduled on: schedule: - cron: '30 0 * * *' workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true permissions: read-all jobs: ### BUILD JOBS ### build-arch-clang-devel: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: image: ospray/docker-images:arch cmd: | export CC=clang export CXX=clang++ scripts/build/linux.sh -G Ninja -DBUILD_GLFW=OFF -DBUILD_OSPRAY_CI_EXTRAS=ON -DBUILD_ISPCRT_FROM_SOURCE=ON -DISPCRT_BRANCH=devel -DBUILD_EMBREE_FROM_SOURCE=ON -DEMBREE_VERSION=devel -DBUILD_OIDN_FROM_SOURCE=ON -DOIDN_VERSION=devel -DOPENVKL_VERSION=devel -DRKCOMMON_VERSION=devel build-linux-debug-all: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main secrets: inherit with: image: ospray/docker-images:arch cmd: | export CC=clang export CXX=clang++ scripts/build/linux.sh -G Ninja -DCMAKE_BUILD_TYPE=Debug -DDEPENDENCIES_BUILD_TYPE=Debug -DBUILD_GLFW=OFF -DBUILD_OSPRAY_CI_EXTRAS=ON -DBUILD_ISPCRT_FROM_SOURCE=ON -DBUILD_EMBREE_FROM_SOURCE=ON -DBUILD_OIDN=OFF -DBUILD_OSPRAY_MODULE_MPI=ON -DBUILD_OSPRAY_MODULE_MULTIDEVICE=ON artifact-out: build-linux-debug-all artifact-path: build/install/ospray build/CMakeCache.txt build/*/build/CMakeCache.txt # build-mpi-cluster: # with: # runs-on: '["Cluster", "build"]' # script: # - module load cmake # - module load impi # - module load gnu # - scripts/build/linux.sh -DBUILD_OSPRAY_MODULE_MPI=ON -DOSPRAY_BUILD_GLM=OFF -DBUILD_OSPRAY_MODULE_MULTIDEVICE=ON # <<: *build_artifacts build-windows-debug-all: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main secrets: inherit with: runs-on: '["build", "NAS", "mpi"]' cmd: | scripts\build\win.ps1 -G "Visual Studio 17 2022" -buildType Debug -DBUILD_OSPRAY_CI_EXTRAS=ON -DBUILD_ISPCRT_FROM_SOURCE=ON -DBUILD_EMBREE_FROM_SOURCE=ON -DBUILD_ISA_AVX512=OFF -DBUILD_OIDN=OFF -DBUILD_OSPRAY_MODULE_MPI=ON -DBUILD_OSPRAY_MODULE_MULTIDEVICE=ON artifact-out: build-windows-debug-all artifact-path: build/install/ospray build/CMakeCache.txt build/ospray/build/CMakeCache.txt build-windows-no-volume: uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main secrets: inherit with: cmd: | scripts\build\win.ps1 -G "Visual Studio 17 2022" -DBUILD_ISA_AVX=OFF -DOSPRAY_BUILD_ISA=AVX2 -DBUILD_OPENVKL=OFF ### TEST JOBS ### test-linux-debug-all: needs: build-linux-debug-all uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/docker.yml@main with: image: ospray/docker-images:arch runs-on: '"avx512"' cmd: | PATH="$GITHUB_WORKSPACE/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$GITHUB_WORKSPACE" AVX512SKX artifact-in: build-linux-debug-all artifact-out: test-linux-debug-all artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true # test-mpi-cluster: # <<: *test_job_unix_avx512skx # tags: [cluster] # script: # - module load impi # - module load gnu # - LD_LIBRARY_PATH="$CI_PROJECT_DIR/build/install/ospray/lib:$LD_LIBRARY_PATH" PATH="$CI_PROJECT_DIR/build/install/ospray/bin:$PATH" scripts/tests/run_tests.sh "$CI_PROJECT_DIR" AVX512SKX TEST_MPI TEST_MULTIDEVICE # env: # needs: build-mpi-cluster # needs: ${{ env.needs }} test-windows-debug-all: needs: build-windows-debug-all uses: intel-innersource/libraries.devops.renderkit.workflows/.github/workflows/windows.yml@main with: runs-on: '"avx2"' cmd: | $env:Path += ";$env:GITHUB_WORKSPACE\build\install\ospray\bin" scripts\tests\run_tests.ps1 "$env:GITHUB_WORKSPACE" AVX2 artifact-in: build-windows-debug-all artifact-out: test-windows-debug-all-avx2 artifact-path: build_regression_tests/tests*.xml build_regression_tests/failed* artifact-on-failure: true RenderKit-ospray-f2a61c2/.gitignore000066400000000000000000000006301456566705700173360ustar00rootroot00000000000000*~ *# bin *.user* /build* install* *.sw? tags .ycm_extra_conf.pyc *.autosave *DS_Store* *.gz *.rpm *.zip *.bak *.patch .vscode deps tbb embree ispc ./ospray-doc readme.pdf !/modules /modules/* !/modules/cpu !/modules/denoiser !/modules/mpi !/modules/multiDevice !/modules/pluggableGeometryExample !/modules/simdGeometryExample *.vim .idea/ premake.local.* cmake-build*/ .clangd compile_commands.json .cache/ RenderKit-ospray-f2a61c2/.gitmodules000066400000000000000000000000001456566705700175120ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/CHANGELOG.md000066400000000000000000001766731456566705700172040ustar00rootroot00000000000000Version History --------------- ### Changes in v3.1.0: - Principled and Luminous materials support emissive textures - Add native support for disc and oriented disc geometry - Add support for mirror repeat and clamp to edge texture wrap modes - GPU device now also supports motion blur - Improve noise in reflections of ThinGlass - Improve adaptive accumulation: working with GPU, fix correlations - Fix indirectly seen albedo and normal buffer - Fix artifacts when using specular texture for Principled - Fixes for PixelFilter - Parameter was ignored (always using the default Gaussian) - Avoid a shift/misalignment within the pixel for first sample - Fix empty image on Windows when `focusDistance=0` - Fix missing SDK headers for `ISPCDevice*` - The new minimum versions of dependencies: - Embree v4.3.1 - Open VKL v2.0.1 - Open Image Denoise v2.2 (better quality with fine details, support AArch64 CPU on Linux) - ISPCRT v1.23.0 (uses environment variable `ISPCRT_GPU_DRIVER` to select GPU to run on when multiple (i)GPUs are present) - rkcommon v1.13.0 (fixes crash using GPU and emissive geometry) ### Changes in v3.0.0: - Beta support for Intel Xe GPUs (Intel Arcâ„¢ GPUs a Intel Data Center GPU Flex and Max Series), exploiting ray tracing hardware support. Implementation is based on the [SYCL](https://www.khronos.org/sycl/) cross-platform programming language implemented by [Intel oneAPI Data Parallel C++ (DPC++)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/data-parallel-c-plus-plus.html). Note that the following features are not implemented yet or are not working correctly on the new `gpu` device: - Multiple volumes in the scene - Clipping - Motion blur - Subdivision surfaces - Progress reporting via `ospGetProgress` or canceling the frame via `ospCancel` - Picking via `ospPick` - Adaptive accumulation via `OSP_FB_VARIANCE` and `varianceThreshold` - Framebuffer channels `OSP_FB_ID_*` (id buffers) - Experimental support for shared device-only data, works only for `structuredRegular` volume - Further known issues - Some delay on start-up or when changing the scene, because kernel code is JIT compiled and specialized. JIT compilation can be cached by setting environment variable `SYCL_CACHE_PERSISTENT=1`, then consecutive starts or rendering the same scene configuration is without delay - For some combination of compiler, GPU driver and scene the rendered images might show artifacts (e.g., vertical lines or small blocks) - Multidevice does not support `OSPImageOperation`s for denoising or tone mapping - Add implicit indexing for `mesh` geometry - Add support for transferring ownership of temporary buffers: `ospNewSharedData` accepts an optional deleter callback - Optimizations for MPI module, supported by new integrated performance tracing framework - Optimize `scivis` gradient shading - Main thread does not set FTZ/DAZ anymore for denormals handling - Compute intersection epsilon for Mesh to avoid rendering artifacts due to self-intersection - Fix energy conservation of Pricipled material under certain parameter combinations - Fix `denoiser` to not wipe the alpha channel - Fix crash in HDRI light - Fix link order for Debug build on Windows - The new minimum versions of dependencies: - Embree v4.3.0 - Open VKL v2.0.0 - Open Image Denoise v2.1.0 - ISPC v1.21.1 - rkcommon v1.12.0 - Breaking API changes - Renamed `OSP_TEXTURE_FILTER_BILINEAR` to `OSP_TEXTURE_FILTER_LINEAR ` and `OSP_VOLUME_FILTER_TRI[LINEAR|CUBIC]` to `OSP_VOLUME_FILTER_[LINEAR|CUBIC]` - Most enums now use storage type `uint32` - `gridSpacing` of spherical regular volume defaults to full sphere - Remove deprecated parameters and API calls - error callback signatures without user pointer - first argument of `ospNewMaterial` - module name `ispc`; use `cpu` - `volume` texture and `isosurface` geometry: `volumetricModel`; use `OSPVolume volume` - Transfer function `vec2f valueRange`; use `box1f value` - `hdri` and `sun-sky` lights: `intensityQuantity` `OSP_INTENSITY_QUANTITY_RADIANCE` - `spot` light with `intensityDistribution`: `intensityQuantity` other than `OSP_INTENSITY_QUANTITY_SCALE` ### Changes in v2.12.0: - Support denoising on the GPU with OIDN 2.0, which is the new minimum version. The `denoiser` now uses HDR mode - New parameter `maxScatteringEvents` for the `pathtracer` which limits the number of non-specular (i.e., diffuse and glossy) bounces - Optimized dynamic load balancing for MPI devices - Fix crash when using small image resolution and many MPI ranks - Fix crash in `pathtracer` when `lightSamples > 0` but there are lights in the scene - Fix transparent shadows with too high `minContribution` setting - The new minimum version for ISPC is v1.20.0 - Release binaries on Linux are built on Rocky 8 ### Changes in v2.11.0: - Support single ISPC target on Windows - OSPRay's superbuild can now be provided a CMake toolchain file for cross-compilation - Add support for double pumped NEON instruction on ARM64 - Reduce the memory overhead of the `mpiOffload` device and resolve memory and `MPI_Comm` handle leaks - Support for volume rendering (and thus the dependency to Open VKL) can now be compile-time controlled via CMake variable `OSPRAY_ENABLE_VOLUMES` - OSPRay's MPI modules have been split up and renamed, the `mpiOffload` device is now in the `mpi_offload` module, while the `mpiDistributed` device is now in the `mpi_distributed_cpu` module - Add native support for spheres via Embree, which requires the positions and radius of the spheres to be interleaved in memory; if this is not the case, OSPRay will internally create a copy of the data - Fix `dynamicScene` flag on World and Group to influence BVH quality again: default is now "high", which should improve rendering performance, depending on the scene; and "low" when `dynamicScene` is enabled (improving BVH build performance) - Fix a crash in `pathtracer` when there are no lights - Fix a data corruption bug when setting string parameters for objects in the `mpiOffload` device - Various documentation fixes - OSPRay now has a new dependency, which is ISPC Run Time (ISPCRT) in minimum 1.19.0 version - Adapt to Embree v4.0.0 API changes, which is thus the new minimum version; additionally, the new minimum version for Open VKL is v1.3.2 and for ISPC v1.19.0 - Removed support of MSVC14.0 (Visual Studio 2015) and the second generation Intel Xeon Phi processor (codename Knights Landing) ### Changes in v2.10.0: - Add support for primitive, object, and instance ID buffers as framebuffer channels - Support face-varying attributes for Mesh and Subdivision geometry - Replace CMake variable `OSPRAY_PIXELS_PER_JOB` by `OSPRAY_RENDER_TASK_SIZE`; variance tracking for adaptive accumulation is now per task instead of per tile, allowing for more granular adaptation - OSPRay now requires minimum Open VKL v1.3.0 to bring the following improvements: - VDB volumes added support for contiguous data layouts, which can provide improved performance (`nodesPackedDense`, `nodesPackedTile` parameters) - Particle volumes are more memory efficiency and improved performance - OSPRay now requires minimum ISPC v1.18.0 for Open VKL and to include a fix for parallel dispatch of uniform function pointers - MPI Offload: resolve object life time tracking issue that would result in framebuffer and data info being release too early, leading to a crash - Fix crash with OpenMPI due to argument handling - Fix clipping when rays are parallel to clipping planes - Fix missing SDK headers from CPU and MPI module - Deprecated the `vec2f valueRange` parameter of the `piecewiseLinear` transfer function, use `box1f value` instead ### Changes in v2.9.0: - Add support for multi-segment deformation motion blur for `mesh` geometry - OSPRay now requires minimum Open VKL v1.2.0 to bring the following improvements: - Structured regular volumes support for cell-centered data via the `cellCentered` parameter (vertex-centered remains the default) - Particle volumes ignore particles with zero radius - Add support for dynamic load balancing in MPI Offload device - Support for photometric lights (e.g., IES or EULUMDAT) also for `sphere` and `quad` lights. When setting `intensityDistribution`, other values for `intensityQuantity` than `OSP_INTENSITY_QUANTITY_SCALE` are deprecated - Changed CMake variables for enabling app categories: - `OSPRAY_ENABLE_APPS_BENCHMARK` replaces `OSPRAY_APPS_BENCHMARK` - `OSPRAY_ENABLE_APPS_EXAMPLES` replaces `OSPRAY_APPS_EXAMPLES` - `OSPRAY_ENABLE_APPS_TUTORIALS` replaces `OSPRAY_APPS_TUTORIALS` - `OSPRAY_ENABLE_APPS_TESTING` replaces `OSPRAY_APPS_TESTING` - Improve sampling of quad lights in the `pathtracer` (solid angle instead of area) - Instances can now have the group object rebound via a parameter - Fix leaking framebuffers in the MPI Offload device - Resolve possible race condition in assigning IDs to distributed objects in the MPI device - Move ISPC module to `modules/` folder and renamed the module to `cpu` - Minimum version of rkcommon is 1.9.0, which brings the following improvements: - Add detection of Intel oneAPI DPC++/C++ compiler - Fix memory leak ### Changes in v2.8.0: - Lights can be now part of `OSPGroup` and thus instanced like geometries and volumes and thus lights also support motion blur (with the path tracer) - Add cylinder light (with solid area sampling) - Add support for rolling shutter of cameras - Add support for quaternion motion blur for instance and camera to allow for smoothly interpolated rotations - Fix illumination from emissive quad meshes ### Changes in v2.7.1: - Use Open VKL v1.0.1 to fix sporadic slowdowns when rendering structured regular and VDB volumes with the SciVis renderer - Fix CMake variables and logic - Fix crash when `transferfunction.opacity = 0` - Fix bug in MPI data-parallel rendering that caused rendering to hang - Workaround dynamic linking issue on Windows in MPI distributed rendering - Correctly initialize `renderFrame` progress - Improved performance of data-parallel rendering for scenes with a large number of regions - Expanded camera model support of the data-parallel renderer, data-parallel rendering can now use all the camera models supported by the SciVis renderer - Clarify documentation and error messages ### Changes in v2.7.0: - Add support for transformation and camera motion blur (with the path tracer) via `shutter` parameter of the camera and `motion.transform` array and `time` parameter of the instance and camera - OSPRay can now be built for ARM64 CPUs with NEON (e.g., Apple M1) using the superbuild. Thus, new minimum versions are for ISPC 1.16.0, for Embree 3.13.1 and for rkcommon 1.7.0 - OSPRay now requires minimum Open VKL v1.0.0 to bring the following improvements: - Configurable `background` values for all volume types (default `NaN`), defining region outside the volume domain - Better default sampling rate for scaled VDB volumes, improved robustness - Structured regular volumes now support tricubic filtering and more accurate gradient computations as well as more robust isosurfaces - The multidevice module contains a new OSPRay device implementation that delegates work to any number of subdevices. This is an experimental feature in this release but we invite feedback - SciVis Renderer now ignores normal/albedo/depth hits on surfaces that are fully transmissive (material `d = 0`) - Changed the behavior of background rendering in SciVis renderer to more closely reflect that of the path tracer: Background hits are rendered in background color in the albedo buffer and black in the normal buffer - The SciVis renderer does not compute depth of field (DoF) anymore, as this effect does not align with the SciVis renderer definition and exposed artifacts - Fixed crash on exit when using the MPI device - Fixed rendering of depth buffer in the example application - The first argument to material constructor `ospNewMaterial`, i.e., `renderer_type`, is now deprecated and will be removed in a future release. AO and SciVis renderers still assume "obj" like behavior for all material types - Deprecated the `xfm` parameter of the instance, use `transform` instead - Dependencies Google Benchmark, GoggleTest, and Snappy moved out-of-source to superbuild ExternalProjects ### Changes in v2.6.0: - Added new `intensityQuantity` type `OSP_INTENSITY_QUANTITY_SCALE` for the `hdri` and `sunSky` light source. For the future this is the only supported quantity for these lights, the value `OSP_INTENSITY_QUANTITY_RADIANCE` is deprecated. When `OSP_INTENSITY_QUANTITY_SCALE` is used for `sunSky` the default value of `intensity` is `0.025` to match the old behavior - The MPI module is included in the releases packages. An [MPICH-ABI](https://www.mpich.org/abi/) compatible build is provided for Linux that can be run with the Intel oneAPI HPC Toolki, MPICH, and other MPICH-ABI compatible MPI distributions. The Windows release is built against MPI provided in the Intel oneAPI HPC Toolkit - OSPRay now requires minimum Open VKL v0.13.0 to bring the following improvements: - Support half precision float (fp16) voxel data in structured volumes (regular and spherical) and VDB volume - Supporting tricubic filtering via `VKL_FILTER_TRICUBIC` filter for VDB volume - Fixed artifacts for isosurfaces of unstructured volumes - Performance improvements for isosurfaces when multiple isovalues are selected - Better, adaptive sampling of AMR volumes - The `mpiOffload` and `mpiDistributed` devices now support picking. Picking in the distributed device will return the globally closest object on the rank that owns that object. Other ranks will report no hit - Messages issued from ISPC code use the same reporting path as the C++ code, thus now the whole OSPRay console output can be consistently filtered with log levels - Open VKL and Embree internal errors are now correctly mapped to their corresponding OSPRay errors - Fix behavior of committing the framebuffer in distributed rendering to match that of local rendering ### Changes in v2.5.0: - Add native support for cones or cylinders with curves geometry of type `OSP_DISJOINT`, requiring minimum version 3.12.0 of Embree - Replaced OSPRay's internal implementation of round linear curves by Embree's native implementation. Internal surfaces at joints are now correctly removed, leading to higher quality renderings with transparency, at the cost of intersection performance - SciVis renderer improvements: - Colored transparency, colored shadows - Light sources are visible including HDRI Light environment map - The MPI module is now distributed as part of OSPRay in the modules directory - The socket-based communication layer has been removed - Add `intensityQuantity` parameter to light sources to control the interpretation and conversion of the `intensity` into a radiative quantity - OSPRay now requires minimum Open VKL v0.12.0 to bring the following improvements: - Better default sampling rate for scaled volumes, improving performance - Higher robustness for axis-aligned rays - Removed limit on the number of volumes (both overlapped and separate) that a ray can intersect while rendering. Now it is limited by available memory only. - Move to OIDN v1.3.0 to bring the following improvements: - Improved denoising quality (sharpness of fine details, fewer noisy artifacts) - Slightly improved performance and lower memory consumption - Both geometric and volumetric models can now have their child geometry/volume objects rebound using an object parameter - Fix light leaking artifacts at poles of HDRI (and Sun-Sky) light - Add sRGB conversion to `ospExamples` such that the color of the widget for `backgroundColor` actually matches - Dropping support for MSVC14, new minimum compiler on Windows is MSVC15 (Visual Studio 2017) ### Changes in v2.4.0: - The `pathtracer` optionally allows for alpha blending even if the background is seen through refractive objects like glass, by enabling `backgroundRefraction` - OSPRay now requires minimum Open VKL v0.11.0 to bring the following improvements: - Improved rendering performance of VDB volumes - Added support for configurable iterator depth via the `maxIteratorDepth` parameters for unstructured and particle volumes, improved performance - Added support for filter modes for structured volumes (regular and spherical) - Expose parameter `horizonExtension` of Sun-sky light, which extends the sky dome by stretching the horizon over the lower hemisphere - Optimize handling of geometry lights by the `pathtracer` - The optional `denoiser` image operation now respects frame cancellation, requiring Intel® Open Image Denoise with minimum version 1.2.3 - Fixed normals of (transformed) isosurfaces - Robust calculation of normals of `boxes` geometry - Clipping geometry is now working correctly with `map_maxDepth` renderer parameter - Using materials in a renderer with a mismatched `renderer_type` no longer causes crashes while rendering - Significant improvements have been made to loading performance in the MPI Offload device. Applications which make large numbers of API calls or create many smaller geometries or volumes should see substantial load time improvements. - MPI module compacts strided data arrays on the app rank before sending ### Changes in v2.3.0: - Re-add SciVis renderer features (the previous version is still available as `ao` renderer) - Lights are regarded, and thus the OBJ material terms `ks` and `ns` have effect again - Hard shadows are enabled via the `shadows` parameter - The control of ambient occlusion changed: - The `aoIntensity` parameter is replaced by the combined intensity of ambient lights in the `World` - The effect range is controlled via `aoDistance` - Added support for data arrays with a stride between voxels in volumes - Application thread waiting for finished image via `ospWait` participates in rendering, increasing CPU utilization; via rkcommon v1.5.0 - Added `ospray_cpp` compatibility headers for C++ wrappers to understand rkcommon and glm short vector types - For rkcommon, include `ospray/ospray_cpp/ext/rkcommon.h` - For glm, include `ospray/ospray_cpp/ext/glm.h` - Note in debug builds some compilers will not optimize out type trait definitions. This will require users to manually instantiate the glm definitions in one translation unit within the application using `#define OSPRAY_GLM_DEFINITIONS` before including `ext/glm.h`: see `ospTutorialGLM` as an example - Changed parameters to `volume` texture: it now directly accepts the `volume` and the `transferFunction` - Fixed many memory leaks - Handle `NaN` during volume sampling, which led to bounding boxes being visible for some volumes and settings - Depth is now "accumulated" as well, using the minimum - Fix shading for multiple modes of the `debug` renderer - New minimum ISPC version is 1.14.1 ### Changes in v2.2.0: - Support for texture transformation in SciVis OBJ material - Add transformations for volume textures; volume texture lookups are now with local object coordinates (not world coordinates anymore) - Changed behavior: if solely a texture is given, then the default value of the corresponding parameter is *not* multiplied - Support for better antialiasing using a set of different pixel filters (e.g, box, Gaussian, ...). The size of the pixel filter is defined by the used filter type. Previously OSPRay implicitly used a box filter with a size of 1, for better results the default filter is now `OSP_PIXELFILTER_GAUSS` - Support stereo3d mode for panoramic camera - Add new camera `stereoMode` `OSP_STEREO_TOP_BOTTOM` (with left eye at top half of the image) - Added support for random light sampling to the `pathtracer`, the number of sampled light sources per path vertex is defined by the `lightSamples` parameter - Support ring light by extending spot with `innerRadius` - Fixed nonphysical behavior of the `spot` and `sphere` light sources - for area lights (when `radius > 0`) surfaces close to the light will be darker - the `spot` now has an angular falloff, such that a disk light is a proper lambertian area light, which leads to darker regions perpendicular to its direction (thus barely visible with a typically small `openingAngle`) - Support for Open VKL v0.10.0 and its new sampler object API, thus this is now the required minimum version - Added support for particle and VDB volumes - Move from `ospcommon` to `rkcommon` v1.4.2 - New minimum ISPC version is 1.10.0 - Status and error callbacks now support a user pointer - Enabled C++ wrappers (`ospray_cpp`) to work with non-rkcommon math types - Note that while the C API remains the same, the C++ wrappers will require some application updates to account for these changes - MPI module improved parallelism of framebuffer compression & decompression when collecting the final framebuffer to the head rank. This provides a substantial performance improvement when using just a few ranks or large framebuffers (both in pixel count or channel count). - The MPI module will now default to setting thread affinity off, if no option is selected. This improves thread usage and core assignment of threads in most cases, where no specific options are provided to the MPI runtime. - Fix bug where `ospGetCurrentDevice` would crash if used before `ospInit` - Allow `NULL` handles to be passed to `ospDeviceRetain` and `ospDeviceRelease` - ISPC generated headers containing the exported functions for OSPRay's ISPC types and functions are now distributed with the SDK - Add CarPaint `flakeColor` parameter, defaults to current Aluminium - Fixed Debug build (which were producing different images) - The path tracer now also regards the renderer materialist when creating geometry lights - Fix bug where OSPObject handles where not translated to worker-local pointers when committing an OSPData in the MPIOffloadDevice. - MPI module: Fix handling of `OSP_STRING` parameters ### Changes in v2.1.1: - CarPaint material obeys `coat` weight parameter - Correct depth buffer values with SciVis renderer - Adaptions to Embree v3.10.0 - The Linux binary release finds `ospcommon` again ### Changes in v2.1.0: - New clipping geometries feature that allows clipping any scene (geometry and volumes); all OSPRay geometry types can by used as clipping geometry - Inverted clipping is supported via new `invertNormals` parameter of `GeometricModel` - Currently there is a fixed upper limit (64) of how many clipping geometries can be nested - When clipping with curves geometry (any basis except linear) some rendering artifacts may appear - New plane geometry defined via plane equation and optional bounding box - Sun-sky light based on physical model of HoÅ¡ek-Wilkie - Support for photometric lights (e.g., IES or EULUMDAT) - Add new `ospGetTaskDuration` API call to query execution time of asynchronous tasks - Support for 16bit (unsigned short) textures - Add static `cpp::Device::current` method as a C++ wrapper equivalent to `ospGetCurrentDevice` - Generalized `cpp::Device` parameter setting to match other handle types - Passing `NULL` to `ospRelease` is not reported as error anymore - Fix computation of strides for `OSPData` - Fix transparency in `scivis` renderer - Add missing C++ wrapper for `ospGetVariance` - Proper demonstration of `ospGetVariance` in `ospTutorialAsync` - Fix handling of `--osp:device-params` to process and set all passed arguments first before committing the device, to ensure it is committed in a valid state - Object factory functions are now registered during module initialization via the appropriate `registerType` function - MPI module: Use flush bcasts to allow us to use non-owning views for data transfer. Note that shared `ospData` with strides is currently transmitted as whole - Fix issue with OSPRay ignoring tasking system thread count settings - Fix issue where OSPRay always loaded the ISPC module, even if not required - Fixes for MPI module - Fix member variable type for bcast - Fix incorrect data size computation in `offload` device - Fix large data chunking support for MPI Bcast - OSPRay now requires minimum Open VKL v0.9.0 ### Changes in v2.0.1: - Fix bug where Embree user-defined geometries were not indexed correctly in the scene, which now requires Embree v3.8.0+ - Fix crash when the path tracer encounters geometric models that do not have a material - Fix crash when some path tracer materials generated `NULL` bsdfs - Fix bug where `ospGetBounds` returned incorrect values - Fix missing symbol in denoiser module - Fix missing symbol exports on Windows for all OSPRay built modules - Add the option to specify a single color for geometric models - The `scivis` renderer now respects the opacity component of `color` on geometric models - Fix various inconsistent handling of framebuffer alpha between renderers - `ospGetCurrentDevice` now increments the ref count of the returned `OSPDevice` handle, so applications will need to release the handle when finished by using `ospDeviceRelease` accordingly - Added denoiser to `ospExamples` app - Added `module_mpi` to superbuild (disabled by default) - The superbuild now will emit a CMake error when using any 32-bit CMake generator, as 32-bit builds are not supported ### Changes in v2.0.0: - New major revision of OSPRay brings API breaking improvements over v1.x. See [doc/ospray2_porting_guide.md] for a deeper description of migrating from v1.x to v2.0 and the latest [API documentation](README.md#ospray-api) - `ospRenderFrame` now takes all participating objects as function parameters instead of setting some as renderer params - `ospRenderFrame` is now asynchronous, where the task is managed through a returned `OSPFuture` handle - The hierarchy of objects in a scene are now more granular to aid in scene construction flexibility and reduce potential object duplication - Type-specific parameter setting functions have been consolidated into a single `ospSetParam` API call - C++ wrappers found in `ospray_cpp.h` now automatically track handle lifetimes, therefore applications using them do not need to use `ospRelease` (or the new `ospRetain`) with them: see usage example in `apps/tutorials/ospTutorial.cpp` - Unused parameters are reported as status messages when `logLevel` is at least `warning` (most easily set by enabling OSPRay debug on initialization) - New utility library which adds functions to help with new API migration and reduction of boilerplate code - Use `ospray_util.h` to access these additional functions - All utility functions are implemented in terms of the core API found in `ospray.h`, therefore they are compatible with any device backend - Introduction of new Intel® Open Volume Kernel Library (Open VKL) for greatly enhanced volume sampling and rendering features and performance - Added direct support for Intel® Open Image Denoise as an optional module, which adds a `denoiser` type to `ospNewImageOperation` - OSPRay now requires minimum Embree v3.7.0 - New CMake superbuild available to build both OSPRay's dependencies and OSPRay itself - Found in `scripts/superbuild` - See documentation for more details and example usage - The `ospcommon` library now lives as a stand alone repository and is required to build OSPRay - The MPI module is now a separate repository, which also contains all MPI distributed rendering documentation - Log levels are now controlled with enums and named strings (where applicable) - A new flag was also introduced which turns all `OSP_LOG_WARNING` messages into errors, which are submitted to the error callback instead of the message callback - Any unused parameters an object ignores now emit a warning message - New support for volumes in the `pathtracer` - Several parameters are available for performance/quality trade-offs for both photorealistic and scientific visualization use cases - Simplification of the SciVis renderer - Fixed AO lighting and simple ray marched volume rendering for ease of use and performance - Overlapping volumes are now supported in both the `pathtracer` and `scivis` renderers - New API call for querying the bounds of objects (`OSPWorld`, `OSPInstance`, and `OSPGroup`) - Lights now exist as a parameter to the world instead of the renderer - Removal of `slices` geometry. Instead, any geometry with volume texture can be used for slicing - Introduction of new `boxes` geometry type - Expansion of information returned by `ospPick` - Addition of API to query version information at runtime - Curves now supports both, per vertex varying radii as in `vec4f[] vertex.position_radius` and constant radius for the geometry with `float radius`. It uses `OSP_ROUND` type and `OSP_LINEAR` basis by default to create the connected segments of constant radius. For per vertex varying radii curves it uses Embree curves. - Add new Embree curve type `OSP_CATMULL_ROM` for curves - Minimum required Embree version is now 3.7.0 - Removal of `cylinders` and `streamlines` geometry, use `curves` instead - Triangle mesh and Quad mesh are superseded by the `mesh` geometry - Applications need to use the various error reporting methods to check whether the creation (via `ospNew...`) of objects failed; a returned `NULL` is not a special handle anymore to signify an error - Changed module init methods to facilitate version checking: `extern "C" OSPError ospray_module_init_(int16_t versionMajor, int16_t versionMinor, int16_t versionPatch)` - The `map_backplate` texture is supported in all renderers and does not hide lights in infinity (like the HDRI light) anymore; explicitly make lights in`visible` if this is needed - Changed the computation of variance for adaptive accumulation to be independent of `TILE_SIZE`, thus `varianceThreshold` needs to be adapted if using a different `TILE_SIZE` than default 64 - `OSPGeometricModel` now has the option to index a renderer-global material list that lives on the renderer, allowing scenes to avoid renderer-specific materials - Object type names and parameters all now follow the camel-case convention - New `ospExamples` app which consolidates previous interactive apps into one - New `ospBenchmark` app which implements a runnable benchmark suite - Known issues: - ISPC v1.11.0 and Embree v3.6.0 are both incompatible with OSPRay and should be avoided (OSPRay should catch this during CMake configure) - MPI module - The MPI module is now provided separately from the main OSPRay repository - Users can now extend OSPRay with custom distributed renderers and compositing operations, by extending `ospray::mpi::DistributedRenderer` and the `ospray::mpi::TileOperation`, respectively. See the `ospray::mpi::DistributedRaycastRenderer` for an example to start from. - The MPI Offload device can now communicate over sockets, allowing for remote rendering on clusters in the listen/connect mode - Data and commands are now sent asynchronously to the MPI workers in the Offload device, overlapping better with application work. The number of data copies performed has also been significantly reduced, and should improve load times - The MPI Distributed device will now infer the rank's local data bounds based on the volumes and geometry specified if no bounding boxes are specified - When specifying custom bounds on each rank IDs are no longer required, and ranks sharing data will be determined by finding any specifying the same bounding boxes. This will also be done if no bounds are specified, allowing automatic image and hybrid parallel rendering. - The MPI Distributed device can now be used for image-parallel rendering (e.g., same as offload), where now each application can load data in parallel. See the `ospMPIDistributedTutorialReplicatedData` for an example. ### Changes in v1.8.5: - Fix float precision cornercase (`NaN`s) in sphere light sampling - Fix CMake bug that assumed `.git` was a directory, which is not true when using OSPRay as a git submodule - Fix CMake warning - Fix `DLL_EXPORT` issue with `ospray_testing` helper library on Windows ### Changes in v1.8.4: - Add location of `libospray` to paths searched to find modules ### Changes in v1.8.3: - Fix bug where parameters set by `ospSet1b()` were being ignored - Fix bug in box intersection tests possibly creating `NaN`s - Fix issue with client applications calling `find_package(ospray)` more than once - Fix bug in cylinder intersection when ray and cylinder are perpendicular - Fix rare crash in path tracer / MultiBSDF ### Changes in v1.8.2: - CMake bug fix where external users of OSPRay needed CMake newer than version 3.1 - Fix incorrect propagation of tasking system flags from an OSPRay install - Fix inconsistency between supported environment variables and command line parameters passed to `ospInit()` - Missing variables were `OSPRAY_LOAD_MODULES` and `OSPRAY_DEFAULT_DEVICE` ### Changes in v1.8.1: - CMake bug fix to remove full paths to dependencies in packages ### Changes in v1.8.0: - This will be the last minor revision of OSPRay. Future development effort in the `devel` branch will be dedicated to v2.0 API changes and may break existing v1.x applications. - This will also be the last version of OSPRay to include `ospray_sg` and the Example Viewer. Users which depend on these should instead use the separate OSPRay Studio project, where `ospray_sg` will be migrated. - We will continue to support patch releases of v1.8.x in case of any reported bugs - Refactored CMake to use newer CMake concepts - All targets are now exported in OSPRay installs and can be consumed by client projects with associated includes, libraries, and definitions - OSPRay now requires CMake v3.1 to build - See documentation for more details - Added new minimal tutorial apps to replace the more complex Example Viewer - Added new "`subdivision`" geometry type to support subdivision surfaces - Added support for texture formats `L8`, `LA8` (gamma-encoded luminance), and `RA8` (linear two component). Note that the enum `OSP_TEXTURE_FORMAT_INVALID` changed its value, thus recompilation may be necessary. - Automatic epsilon handling, which removes the "`epsilon`" parameter on all renderers - Normals in framebuffer channel `OSP_FB_NORMAL` are now in world-space - Added support for Intel® Open Image Denoise to the Example Viewer - This same integration will soon be ported to OSPRay Studio - Fixed artifacts for scaled instances of spheres, cylinders and streamlines - Improvements to precision of intersections with cylinders and streamlines - Fixed Quadlight: the emitting side is now indeed in direction `edge1`×`edge2` ### Changes in v1.7.3: - Make sure a "`default`" device can always be created - Fixed `ospNewTexture2D` (completely implementing old behavior) - Cleanup any shared object handles from the OS created from `ospLoadModule()` ### Changes in v1.7.2: - Fixed issue in `mpi_offload` device where `ospRelease` would sometimes not correctly free objects - Fixed issue in `ospray_sg` where structured volumes would not properly release the underlying OSPRay object handles ### Changes in v1.7.1: - Fixed issue where the `Principled` material would sometimes show up incorrectly as black - Fixed issue where some headers were missing from install packages ### Changes in v1.7.0: - Generalized texture interface to support more than classic 2D image textures, thus `OSPTexture2D` and `ospNewTexture2D` are now deprecated, use the new API call `ospNewTexture("texture2d")` instead - Added new `volume` texture type to visualize volume data on arbitrary geometry placed inside the volume - Added new framebuffer channels `OSP_FB_NORMAL` and `OSP_FB_ALBEDO` - Applications can get information about the progress of rendering the current frame, and optionally cancel it, by registering a callback function via `ospSetProgressFunc()` - Lights are not tied to the renderer type, so a new function `ospNewLight3()` was introduced to implement this. Please convert all uses of `ospNewLight()` and/or `ospNewLight2()` to `ospNewLight3()` - Added sheenTint parameter to Principled material - Added baseNormal parameter to Principled material - Added low-discrepancy sampling to path tracer - The `spp` parameter on the renderer no longer supports values less than 1, instead applications should render to a separate, lower resolution framebuffer during interaction to achieve the same behavior ### Changes in v1.6.1: - Many bug fixes - Quad mesh interpolation and sampling - Normal mapping in path tracer materials - Memory corruption with partly emitting mesh lights - Logic for setting thread affinity ### Changes in v1.6.0: - Updated ispc device to use Embree3 (minimum required Embree version is 3.1) - Added new `ospShutdown()` API function to aid in correctness and determinism of OSPRay API cleanup - Added "`Principled`" and "`CarPaint"` materials to the path tracer - Improved flexibility of the tone mapper - Improvements to unstructured volume - Support for wedges (in addition to tets and hexes) - Support for implicit isosurface geometry - Support for cell-centered data (as an alternative to per-vertex data) - Added an option to precompute normals, providing a memory/performance trade-off for applications - Implemented "`quads`" geometry type to handle quads directly - Implemented the ability to set "void" cell values in all volume types: when `NaN` is present as a volume's cell value the volume sample will be ignored by the SciVis renderer - Fixed support for color strides which were not multiples of `sizeof(float)` - Added support for RGBA8 color format to spheres, which can be set by specifying the "`color_format`" parameter as `OSP_UCHAR4`, or passing the "`color`" array through an `OSPData` of type `OSP_UCHAR4`. - Added ability to configure Embree scene flags via `OSPModel` parameters - `ospFreeFrameBuffer()` has been deprecated in favor of using `ospRelease()` to free framebuffer handles - Fixed memory leak caused by incorrect parameter reference counts in ispc device - Fixed occasional crashes in the `mpi_offload` device on shutdown - Various improvements to sample apps and `ospray_sg` - Added new `generator` nodes, allowing the ability to inject programmatically generated scene data (only C++ for now) - Bug fixes and improvements to enhance stability and usability ### Changes in v1.5.0: - Unstructured tetrahedral volume now generalized to also support hexahedral data, now called `unstructured_volume` - New function for creating materials (`ospNewMaterial2()`) which takes the renderer type string, not a renderer instance (the old version is now deprecated) - New `tonemapper` PixelOp for tone mapping final frames - Streamlines now support per-vertex radii and smooth interpolation - `ospray_sg` headers are now installed alongside the SDK - Core OSPRay ispc device now implemented as a module - Devices which implement the public API are no longer required to link the dependencies to core OSPRay (e.g., Embree v2.x) - By default, `ospInit()` will load the ispc module if a device was not created via `--osp:mpi` or `--osp:device:[name]` - MPI devices can now accept an existing world communicator instead of always creating their own - Added ability to control ISPC specific optimization flags via CMake options. See the various `ISPC_FLAGS_*` variables to control which flags get used - Enhancements to sample applications - `ospray_sg` (and thus `ospExampleViewer`/`ospBenchmark`) can now be extended with new scene data importers via modules or the SDK - Updated `ospTutorial` examples to properly call `ospRelease()` - New options in the `ospExampleViewer` GUI to showcase new features (sRGB framebuffers, tone mapping, etc.) - General bug fixes - Fixes to geometries with multiple emissive materials - Improvements to precision of ray-sphere intersections ### Changes in v1.4.3: - Several bug fixes - Fixed potential issue with static initialization order - Correct compiler flags for `Debug` config - Spheres `postIntersect` shading is now 64-bit safer ### Changes in v1.4.2: - Several cleanups and bug fixes - Fixed memory leak where the Embree BVH was never released when an `OSPModel` was released - Fixed a crash when API logging was enabled in certain situations - Fixed a crash in MPI mode when creating lights without a renderer - Fixed an issue with camera lens samples not initialized when `spp` <= 0 - Fixed an issue in `ospExampleViewer` when specifying multiple data files - The C99 tutorial is now indicated as the default; the C++ wrappers do not change the semantics of the API (memory management) so the C99 version should be considered first when learning the API ### Changes in v1.4.1: - Several cleanups and bug fixes - Improved precision of ray intersection with streamlines, spheres, and cylinder geometries - Fixed address overflow in framebuffer, in practice image size is now limited only by available memory - Fixed several deadlocks and race conditions - Fix shadow computation in SciVis renderer, objects behind light sources do not occlude anymore - No more image jittering with MPI rendering when no accumulation buffer is used - Improved path tracer materials - Additionally support RGB `eta`/`k` for Metal - Added Alloy material, a "metal" with textured color - Minimum required Embree version is now v2.15 ### Changes in v1.4.0: - New adaptive mesh refinement (AMR) and unstructured tetrahedral volume types - Dynamic load balancing is now implemented for the `mpi_offload` device - Many improvements and fixes to the available path tracer materials - Specular lobe of OBJMaterial uses Blinn-Phong for more realistic highlights - Metal accepts spectral samples of complex refraction index - ThinGlass behaves consistent to Glass and can texture attenuation color - Added Russian roulette termination to path tracer - SciVis OBJMaterial accepts texture coordinate transformations - Applications can now access depth information in MPI distributed uses of OSPRay (both `mpi_offload` and `mpi_distributed` devices) - Many robustness fixes for both the `mpi_offload` and `mpi_distributed` devices through improvements to the `mpi_common` and `mpi_maml` infrastructure libraries - Major sample app cleanups - `ospray_sg` library is the new basis for building apps, which is a scene graph implementation - Old (unused) libraries have been removed: miniSG, command line, importer, loaders, and scripting - Some removed functionality (such as scripting) may be reintroduced in the new infrastructure later, though most features have remained and have been improved - Optional improved texture loading has been transitioned from ImageMagick to OpenImageIO - Many cleanups, bug fixes, and improvements to `ospray_common` and other support libraries - This will be the last release in which we support MSVC12 (Visual Studio 2013). Future releases will require VS2015 or newer ### Changes in v1.3.1: - Improved robustness of OSPRay CMake `find_package` config - Fixed bugs related to CMake configuration when using the OSPRay SDK from an install - Fixed issue with Embree library when installing with `OSPRAY_INSTALL_DEPENDENCIES` enabled ### Changes in v1.3.0: - New MPI distributed device to support MPI distributed applications using OSPRay collectively for "in-situ" rendering (currently in "alpha") - Enabled via new `mpi_distributed` device type - Currently only supports `raycast` renderer, other renderers will be supported in the future - All API calls are expected to be exactly replicated (object instances and parameters) except scene data (geometries and volumes) - The original MPI device is now called the `mpi_offload` device to differentiate between the two implementations - Support of Intel® AVX-512 for next generation Intel® Xeon® processor (codename Skylake), thus new minimum ISPC version is 1.9.1 - Thread affinity of OSPRay's tasking system can now be controlled via either device parameter `setAffinity`, or command line parameter `osp:setaffinity`, or environment variable `OSPRAY_SET_AFFINITY` - Changed behavior of the background color in the SciVis renderer: `bgColor` now includes alpha and is always blended (no `backgroundEnabled` anymore). To disable the background do not set `bgColor`, or set it to transparent black (0, 0, 0, 0) - Geometries "`spheres`" and "`cylinders`" now support texture coordinates - The GLUT- and Qt-based demo viewer applications have been replaced by an example viewer with minimal dependencies - Building the sample applications now requires GCC 4.9 (previously 4.8) for features used in the C++ standard library; OSPRay itself can still be built with GCC 4.8 - The new example viewer based on `ospray::sg` (called `ospExampleViewerSg`) is the single application we are consolidating to, `ospExampleViewer` will remain only as a deprecated viewer for compatibility with the old `ospGlutViewer` application - Deprecated `ospCreateDevice()`; use `ospNewDevice()` instead - Improved error handling - Various API functions now return an `OSPError` value - `ospDeviceSetStatusFunc()` replaces the deprecated `ospDeviceSetErrorMsgFunc()` - New API functions to query the last error (`ospDeviceGetLastErrorCode()` and `ospDeviceGetLastErrorMsg()`) or to register an error callback with `ospDeviceSetErrorFunc()` - Fixed bug where exceptions could leak to C applications ### Changes in v1.2.1: - Various bug fixes related to MPI distributed rendering, ISPC issues on Windows, and other build related issues ### Changes in v1.2.0: - Added support for volumes with voxelType `short` (16-bit signed integers). Applications need to recompile, because `OSPDataType` has been re-enumerated - Removed SciVis renderer parameter `aoWeight`, the intensity (and now color as well) of AO is controlled via "`ambient`" lights. If `aoSamples` is zero (the default) then ambient lights cause ambient illumination (without occlusion) - New SciVis renderer parameter `aoTransparencyEnabled`, controlling whether object transparency is respected when computing ambient occlusion (disabled by default, as it is considerable slower) - Implement normal mapping for SciVis renderer - Support of emissive (and illuminating) geometries in the path tracer via new material "`Luminous`" - Lights can optionally made invisible by using the new parameter `isVisible` (only relevant for path tracer) - OSPRay Devices are now extendable through modules and the SDK - Devices can be created and set current, creating an alternative method for initializing the API - New API functions for committing parameters on Devices - Removed support for the first generation Intel® Xeon Phiâ„¢ coprocessor (codename Knights Corner) - Other minor improvements, updates, and bug fixes - Updated Embree required version to v2.13.0 for added features and performance - New API function `ospDeviceSetErrorMsgFunc()` to specify a callback for handling message outputs from OSPRay - Added ability to remove user set parameter values with new `ospRemoveParam()` API function - The MPI device is now provided via a module, removing the need for having separately compiled versions of OSPRay with and without MPI - OSPRay build dependencies now only get installed if `OSPRAY_INSTALL_DEPENDENCIES` CMake variable is enabled ### Changes in v1.1.2: - Various bug fixes related to normalization, epsilons and debug messages ### Changes in v1.1.1: - Fixed support of first generation Intel Xeon Phi coprocessor (codename Knights Corner) and the COI device - Fix normalization bug that caused rendering artifacts ### Changes in v1.1.0: - New "scivis" renderer features - Single sided lighting (enabled by default) - Many new volume rendering specific features - Adaptive sampling to help improve the correctness of rendering high-frequency volume data - Pre-integration of transfer function for higher fidelity images - Ambient occlusion - Volumes can cast shadows - Smooth shading in volumes - Single shading point option for accelerated shading - Added preliminary support for adaptive accumulation in the MPI device - Camera specific features - Initial support for stereo rendering with the perspective camera - Option `architectural` in perspective camera, rectifying vertical edges to appear parallel - Rendering a subsection of the full view with `imageStart`/`imageEnd` supported by all cameras - This will be our last release supporting the first generation Intel Xeon Phi coprocessor (codename Knights Corner) - Future major and minor releases will be upgraded to the latest version of Embree, which no longer supports Knights Corner - Depending on user feedback, patch releases are still made to fix bugs - Enhanced output statistics in `ospBenchmark` application - Many fixes to the OSPRay SDK - Improved CMake detection of compile-time enabled features - Now distribute OSPRay configuration and ISPC CMake macros - Improved SDK support on Windows - OSPRay library can now be compiled with `-Wall` and `-Wextra` enabled - Tested with GCC v5.3.1 and Clang v3.8 - Sample applications and modules have not been fixed yet, thus applications which build OSPRay as a CMake subproject should disable them with `-DOSPRAY_ENABLE_APPS=OFF` and `-DOSPRAY_ENABLE_MODULES=OFF` - Minor bug fixes, improvements, and cleanups - Regard shading normal when bump mapping - Fix internal CMake naming inconsistencies in macros - Fix missing API calls in C++ wrapper classes - Fix crashes on MIC - Fix thread count initialization bug with TBB - CMake optimizations for faster configuration times - Enhanced support for scripting in both `ospGlutViewer` and `ospBenchmark` applications ### Changes in v1.0.0: - New OSPRay SDK - OSPRay internal headers are now installed, enabling applications to extend OSPRay from a binary install - CMake macros for OSPRay and ISPC configuration now a part of binary releases - CMake clients use them by calling `include(${OSPRAY_USE_FILE})` in their CMake code after calling `find_package(ospray)` - New OSPRay C++ wrapper classes - These act as a thin layer on top of OSPRay object handles, where multiple wrappers will share the same underlying handle when assigned, copied, or moved - New OSPRay objects are only created when a class instance is explicitly constructed - C++ users are encouraged to use these over the `ospray.h` API - Complete rework of sample applications - New shared code for parsing the `commandline` - Save/load of transfer functions now handled through a separate library which does not depend on Qt - Added `ospCvtParaViewTfcn` utility, which enables `ospVolumeViewer` to load color maps from ParaView - GLUT based sample viewer updates - Rename of `ospModelViewer` to `ospGlutViewer` - GLUT viewer now supports volume rendering - Command mode with preliminary scripting capabilities, enabled by pressing '`:`' key (not available when using Intel C++ Compiler (icc)) - Enhanced support of sample applications on Windows - New minimum ISPC version is 1.9.0 - Support of Intel® AVX-512 for second generation Intel Xeon Phi processor (codename Knights Landing) is now a part of the `OSPRAY_BUILD_ISA` CMake build configuration - Compiling AVX-512 requires icc to be enabled as a build option - Enhanced error messages when `ospLoadModule()` fails - Added `OSP_FB_RGBA32F` support in the `DistributedFrameBuffer` - Updated Glass shader in the path tracer - Many miscellaneous cleanups, bug fixes, and improvements ### Changes in v0.10.1: - Fixed support of first generation Intel Xeon Phi coprocessor (codename Knights Corner) - Restored missing implementation of `ospRemoveVolume()` ### Changes in v0.10.0: - Added new tasking options: `Cilk`, `Internal`, and `Debug` - Provides more ways for OSPRay to interact with calling application tasking systems - `Cilk`: Use Intel® Cilkâ„¢ Plus language extensions (icc only) - `Internal`: Use hand written OSPRay tasking system - `Debug`: All tasks are run in serial (useful for debugging) - In most cases, Intel Threading Building Blocks (Intel `TBB`) remains the fastest option - Added support for adaptive accumulation and stopping - `ospRenderFrame` now returns an estimation of the variance in the rendered image if the framebuffer was created with the `OSP_FB_VARIANCE` channel - If the renderer parameter `varianceThreshold` is set, progressive refinement concentrates on regions of the image with a variance higher than this threshold - Added support for volumes with voxelType `ushort` (16-bit unsigned integers) - `OSPTexture2D` now supports sRGB formats -- actually most images are stored in sRGB. As a consequence the API call `ospNewTexture2D()` needed to change to accept the new `OSPTextureFormat` parameter - Similarly, OSPRay's framebuffer types now also distinguishes between linear and sRGB 8-bit formats. The new types are `OSP_FB_NONE`, `OSP_FB_RGBA8`, `OSP_FB_SRGBA`, and `OSP_FB_RGBA32F` - Changed "scivis" renderer parameter defaults - All shading (AO + shadows) must be explicitly enabled - OSPRay can now use a newer, pre-installed Embree enabled by the new `OSPRAY_USE_EXTERNAL_EMBREE` CMake option - New `ospcommon` library used to separately provide math types and OS abstractions for both OSPRay and sample applications - Removes extra dependencies on internal Embree math types and utility functions - `ospray.h` header is now C99 compatible - Removed loaders module, functionality remains inside of `ospVolumeViewer` - Many miscellaneous cleanups, bug fixes, and improvements - Fixed data distributed volume rendering bugs when using less blocks than workers - Fixes to CMake `find_package()` config - Fix bug in `GhostBlockBrickVolume` when using `double`s - Various robustness changes made in CMake to make it easier to compile OSPRay ### Changes in v0.9.1: - Volume rendering now integrated into the "scivis" renderer - Volumes are rendered in the same way the "dvr" volume renderer renders them - Ambient occlusion works with implicit isosurfaces, with a known visual quality/performance trade-off - Intel Xeon Phi coprocessor (codename Knights Corner) COI device and build infrastructure restored (volume rendering is known to still be broken) - New support for CPack built OSPRay binary redistributable packages - Added support for HDRI lighting in path tracer - Added `ospRemoveVolume()` API call - Added ability to render a subsection of the full view into the entire framebuffer in the perspective camera - Many miscellaneous cleanups, bug fixes, and improvements - The depthbuffer is now correctly populated by in the "scivis" renderer - Updated default renderer to be "ao1" in ospModelViewer - Trianglemesh `postIntersect` shading is now 64-bit safe - Texture2D has been reworked, with many improvements and bug fixes - Fixed bug where MPI device would freeze while rendering frames with Intel TBB - Updates to CMake with better error messages when Intel TBB is missing ### Changes in v0.9.0: The OSPRay v0.9.0 release adds significant new features as well as API changes. - Experimental support for data-distributed MPI-parallel volume rendering - New SciVis-focused renderer ("raytracer" or "scivis") combining functionality of "obj" and "ao" renderers - Ambient occlusion is quite flexible: dynamic number of samples, maximum ray distance, and weight - Updated Embree version to v2.7.1 with native support for Intel AVX-512 for triangle mesh surface rendering on the Intel Xeon Phi processor (codename Knights Landing) - OSPRay now uses C++11 features, requiring up to date compiler and standard library versions (GCC v4.8.0) - Optimization of volume sampling resulting in volume rendering speedups of up to 1.5× - Updates to path tracer - Reworked material system - Added texture transformations and colored transparency in OBJ material - Support for alpha and depth components of framebuffer - Added thinlens camera, i.e., support for depth of field - Tasking system has been updated to use Intel Threading Building Blocks (Intel TBB) - The `ospGet*()` API calls have been deprecated and will be removed in a subsequent release ### Changes in v0.8.3: - Enhancements and optimizations to path tracer - Soft shadows (light sources: sphere, cone, extended spot, quad) - Transparent shadows - Normal mapping (OBJ material) - Volume rendering enhancements - Expanded material support - Support for multiple lights - Support for double precision volumes - Added `ospSampleVolume()` API call to support limited probing of volume values - New features to support compositing externally rendered content with OSPRay-rendered content - Renderers support early ray termination through a maximum depth parameter - New OpenGL utility module to convert between OSPRay and OpenGL depth values - Added panoramic and orthographic camera types - Proper CMake-based installation of OSPRay and CMake `find_package()` support for use in external projects - Experimental Windows support - Deprecated `ospNewTriangleMesh()`; use `ospNewGeometry("triangles")` instead - Bug fixes and cleanups throughout the codebase ### Changes in v0.8.2: - Initial support for Intel AVX-512 and the Intel Xeon Phi processor (codename Knights Landing) - Performance improvements to the volume renderer - Incorporated implicit slices and isosurfaces of volumes as core geometry types - Added support for multiple disjoint volumes to the volume renderer - Improved performance of `ospSetRegion()`, reducing volume load times - Improved large data handling for the `shared_structured_volume` and `block_bricked_volume` volume types - Added support for DDS horizon data to the seismic module - Initial support in the Qt viewer for volume rendering - Updated to ISPC 1.8.2 - Various bug fixes, cleanups and documentation updates throughout the codebase ### Changes in v0.8.1: - The volume renderer and volume viewer can now be run MPI parallel (data replicated) using the `--osp:mpi` command line option - Improved performance of volume grid accelerator generation, reducing load times for large volumes - The volume renderer and volume viewer now properly handle multiple isosurfaces - Added small example tutorial demonstrating how to use OSPRay - Several fixes to support older versions of GCC - Bug fixes to `ospSetRegion()` implementation for arbitrarily shaped regions and setting large volumes in a single call - Bug fix for geometries with invalid bounds; fixes streamline and sphere rendering in some scenes - Fixed bug in depth buffer generation ### Changes in v0.8.0: - Incorporated early version of a new Qt-based viewer to eventually unify (and replace) the existing simpler GLUT-based viewers - Added new path tracing renderer (`ospray/render/pathtracer`), roughly based on the Embree sample path tracer - Added new features to the volume renderer - Gradient shading (lighting) - Implicit isosurfacing - Progressive refinement - Support for regular grids, specified with the `gridOrigin` and `gridSpacing` parameters - New `shared_structured_volume` volume type that allows voxel data to be provided by applications through a shared data buffer - New API call to set (sub-)regions of volume data (`ospSetRegion()`) - Added a subsampling-mode, enabled with a negative `spp` parameter; the first frame after scene changes is rendered with reduced resolution, increasing interactivity - Added multi-target ISA support: OSPRay will now select the appropriate ISA at runtime - Added support for the Stanford SEP file format to the seismic module - Added `--osp:numthreads ` command line option to restrict the number of threads OSPRay creates - Various bug fixes, cleanups and documentation updates throughout the codebase ### Changes in v0.7.2: - Build fixes for older versions of GCC and Clang - Fixed time series support in ospVolumeViewer - Corrected memory management for shared data buffers - Updated to ISPC 1.8.1 - Resolved issue in XML parser RenderKit-ospray-f2a61c2/CMakeLists.txt000066400000000000000000000032601456566705700201100ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 cmake_minimum_required(VERSION 3.1) ############################################################## # Language setup ############################################################## set(CMAKE_DISABLE_SOURCE_CHANGES ON) set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_POSITION_INDEPENDENT_CODE ON) ############################################################## # Establish project ############################################################## include(cmake/ospray_version.cmake) project(OSPRay VERSION ${OSPRAY_VERSION} LANGUAGES C CXX) ############################################################## # CMake modules and macro files ############################################################## list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ${PROJECT_SOURCE_DIR}/cmake/compiler ) include(ospray_macros) include(ospray_options) include(package) if (OSPRAY_INSTALL_DEPENDENCIES) include(ospray_redistribute_deps) endif() ############################################################## # Add library and executable targets ############################################################## ## Main OSPRay library ## add_subdirectory(ospray) ## Modules ## add_subdirectory(modules) ## OSPRay sample apps ## add_subdirectory(apps) ## Regression test images target ## add_subdirectory(test_image_data) ## Clang-format target ## if (OSPRAY_ENABLE_TARGET_CLANGFORMAT) include(clang-format) endif() # Must be last include(CPack) RenderKit-ospray-f2a61c2/LICENSE.txt000066400000000000000000000236371456566705700172050ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. RenderKit-ospray-f2a61c2/README.md000066400000000000000000006603031456566705700166360ustar00rootroot00000000000000OSPRay ====== This is release v3.1.0 of Intel® OSPRay. For changes and new features see the [changelog](CHANGELOG.md). Visit http://www.ospray.org for more information. OSPRay Overview =============== Intel® OSPRay is an **o**pen source, **s**calable, and **p**ortable **ray** tracing engine for high-performance, high-fidelity visualization on Intel Architecture CPUs, Intel Xe GPUs, and ARM64 CPUs. OSPRay is part of the [Intel oneAPI Rendering Toolkit](https://software.intel.com/en-us/rendering-framework) and is released under the permissive [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0). The purpose of OSPRay is to provide an open, powerful, and easy-to-use rendering library that allows one to easily build applications that use ray tracing based rendering for interactive applications (including both surface- and volume-based visualizations). OSPRay runs on anything from laptops, to workstations, to compute nodes in HPC systems. OSPRay internally builds on top of Intel [Embree](https://www.embree.org/), Intel [Open VKL](https://www.openvkl.org/), and Intel [Open Image Denoise](https://openimagedenoise.github.io/). The CPU implementation is based on Intel [ISPC (Implicit SPMD Program Compiler)](https://ispc.github.io/) and fully exploits modern instruction sets like Intel SSE4, AVX, AVX2, AVX-512 and NEON to achieve high rendering performance. Hence, a CPU with support for at least SSE4.1 is required to run OSPRay on x86_64 architectures, or a CPU with support for NEON is required to run OSPRay on ARM64 architectures. OSPRay’s GPU implementation (beta status) is based on the [SYCL](https://www.khronos.org/sycl/) cross-platform programming language implemented by [Intel oneAPI Data Parallel C++ (DPC++)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/data-parallel-c-plus-plus.html) and currently supports Intel Arcâ„¢ GPUs on Linux and Windows, and Intel Data Center GPU Flex and Max Series on Linux, exploiting ray tracing hardware support. OSPRay Support and Contact -------------------------- OSPRay is under active development, and though we do our best to guarantee stable release versions a certain number of bugs, as-yet-missing features, inconsistencies, or any other issues are still possible. For any such requests or findings please use [OSPRay’s GitHub Issue Tracker](https://github.com/ospray/OSPRay/issues) (or, if you should happen to have a fix for it, you can also send us a pull request). To receive release announcements simply [“Watch†the OSPRay repository](https://github.com/ospray/OSPRay) on GitHub. Building and Finding OSPRay =========================== The latest OSPRay sources are always available at the [OSPRay GitHub repository](http://github.com/ospray/ospray). The default `master` branch should always point to the latest bugfix release. Prerequisites ------------- OSPRay currently supports Linux, Mac OS X, and Windows. In addition, before you can build OSPRay you need the following prerequisites: - You can clone the latest OSPRay sources via: ``` sh git clone https://github.com/ospray/ospray.git ``` - To build OSPRay you need [CMake](http://www.cmake.org), any form of C++11 compiler (we recommend using GCC, but also support Clang, MSVC, and [Intel® C++ Compiler (icc)](https://software.intel.com/en-us/c-compilers)), and standard Linux development tools. - Additionally you require a copy of the [Intel® Implicit SPMD Program Compiler (ISPC)](http://ispc.github.io), version 1.23.0 or later. Please obtain a release of ISPC from the [ISPC downloads page](https://ispc.github.io/downloads.html). If ISPC is not found by CMake its location can be hinted with the variable `ispcrt_DIR`. - OSPRay builds on top of the [Intel oneAPI Rendering Toolkit common library (rkcommon)](https://www.github.com/ospray/rkcommon). The library provides abstractions for tasking, aligned memory allocation, vector math types, among others. For users who also need to build rkcommon, we recommend the default the Intel [Threading Building Blocks (TBB)](https://www.threadingbuildingblocks.org/) as tasking system for performance and flexibility reasons. TBB must be built from source when targeting ARM CPUs, or can be built from source as part of the [superbuild](#cmake-superbuild). Alternatively you can set CMake variable `RKCOMMON_TASKING_SYSTEM` to `OpenMP` or `Internal`. - OSPRay also heavily uses Intel [Embree](https://www.embree.org/), installing version 4.3.1 or newer is required. If Embree is not found by CMake its location can be hinted with the variable `embree_DIR`. - OSPRay supports volume rendering (enabled by default via `OSPRAY_ENABLE_VOLUMES`), which heavily uses Intel [Open VKL](https://www.openvkl.org/), version 2.0.1 or newer is required. If Open VKL is not found by CMake its location can be hinted with the variable `openvkl_DIR`, or disable `OSPRAY_ENABLE_VOLUMES`. - OSPRay also provides an optional module implementing the `denoiser` image operation, which is enabled by `OSPRAY_MODULE_DENOISER`. This module requires Intel [Open Image Denoise](https://openimagedenoise.github.io/) in version 2.2.0 or newer. You may need to hint the location of the library with the CMake variable `OpenImageDenoise_DIR`. - For the optional MPI modules (enabled by `OSPRAY_MODULE_MPI`), which provide the `mpiOffload` and `mpiDistributed` devices, you need an MPI library and [Google Snappy](https://github.com/google/snappy). - The optional example application, the test suit and benchmarks need some version of OpenGL and GLFW as well as [GoogleTest](https://github.com/google/googletest) and [Google Benchmark](https://github.com/google/benchmark/) Depending on your Linux distribution you can install these dependencies using `yum` or `apt-get`. Some of these packages might already be installed or might have slightly different names. Type the following to install the dependencies using `yum`: ``` sh sudo yum install cmake.x86_64 sudo yum install tbb.x86_64 tbb-devel.x86_64 ``` Type the following to install the dependencies using `apt-get`: ``` sh sudo apt-get install cmake-curses-gui sudo apt-get install libtbb-dev ``` Under Mac OS X these dependencies can be installed using [MacPorts](http://www.macports.org/): ``` sh sudo port install cmake tbb ``` Under Windows please directly use the appropriate installers for [CMake](https://cmake.org/download/), [TBB](https://github.com/oneapi-src/oneTBB/releases), [ISPC](https://ispc.github.io/downloads.html) (for your Visual Studio version) and [Embree](https://github.com/embree/embree/releases/). ### Additional Prerequisites for GPU Build To build OSPRay’s GPU module you need - a SYCL compiler, either the open source [oneAPI DPC++ Compiler 2023-10-26](https://github.com/intel/llvm/releases/tag/nightly-2023-10-26) or the latest [Intel oneAPI DPC++/C++ Compiler](https://www.intel.com/content/www/us/en/developer/articles/tool/oneapi-standalone-components.html#dpcpp-cpp) - a recent [CMake](http://www.cmake.org), version 3.25.3 or higher - the [oneAPI Level Zero Loader v1.12.0](https://github.com/oneapi-src/level-zero/releases/tag/v1.12.0) development packages - On Linux Ubuntu 22.04 there are prebuilt packages available for this: `level-zero-devel` and `level-zero` - Other Linux distributions require building these packages from source - On Windows, you can use the single package `level-zero__win-sdk`; note you will need to set the environment variable `LEVEL_ZERO_ROOT` to the location of the SDK CMake Superbuild ---------------- For convenience, OSPRay provides a CMake Superbuild script which will pull down OSPRay’s dependencies and build OSPRay itself. By default, the result is an install directory, with each dependency in its own directory. Run with: ``` sh mkdir build cd build cmake [/scripts/superbuild] cmake --build . ``` On Windows make sure to select a 64bit generator, e.g. ``` sh cmake -G "Visual Studio 17 2022" [/scripts/superbuild] ``` The resulting `install` directory (or the one set with `CMAKE_INSTALL_PREFIX`) will have everything in it, with one subdirectory per dependency. CMake options to note (all have sensible defaults): CMAKE_INSTALL_PREFIX will be the root directory where everything gets installed. BUILD_JOBS sets the number given to `make -j` for parallel builds. INSTALL_IN_SEPARATE_DIRECTORIES toggles installation of all libraries in separate or the same directory. BUILD_OPENVKL whether to enable volume rendering via Open VKL BUILD_EMBREE_FROM_SOURCE set to OFF will download a pre-built version of Embree. BUILD_OIDN_FROM_SOURCE set to OFF will download a pre-built version of Open Image Denoise. OIDN_VERSION determines which version of Open Image Denoise to pull down. BUILD_OSPRAY_MODULE_MPI set to ON to build OSPRay’s MPI module for data-replicated and distributed parallel rendering on multiple nodes. BUILD_GPU_SUPPORT enables beta GPU support, fetching the SYCL variants of the dependencies and builds `OSPRAY_MODULE_GPU` BUILD_TBB_FROM_SOURCE set to ON to build TBB from source (required for ARM support). The default setting is OFF. For the full set of options, run: ``` sh ccmake [/scripts/superbuild] ``` or ``` sh cmake-gui [/scripts/superbuild] ``` ### Cross-Compilation with the Superbuild The superbuild can be passed a [CMake Toolchain file](https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html) to configure for cross-compilation. This is done by passing the toolchain file when running cmake. When cross compiling it is also likely that you’ll want to build TBB and Embree from source to ensure they’re built for the correct target, rather than the target the Github binaries are built for. It may also be necessary to disable specific ISAs for the target by passing `BUILD_ISA_=OFF` as well. ``` sh mkdir build cd build cmake --toolchain [toolchain_file.cmake] [path/to/this/directory] -DBUILD_TBB_FROM_SOURCE=ON \ -DBUILD_EMBREE_FROM_SOURCE=ON \ ``` While OSPRay supports ARM natively, it may be desirable to cross-compile it for `x86_64` to run in Rosetta depending on the application integrating OSPRay. This can be done using the toolchain file `toolchains/macos-rosetta.cmake`, and by disabling all non-SSE ISAs when building. This can also be done by launching an `x86_64` bash shell and then compiling as usual in this environment, which will cause the compilation chain to target `x86_64`. The `BUILD_ISA_=OFF` flags should be passed to disable all ISAs besides SSE4 for Rosetta: ``` sh arch -x86_64 bash mkdir build cd build cmake [path/to/this/directory] -DBUILD_TBB_FROM_SOURCE=ON \ -DBUILD_EMBREE_FROM_SOURCE=ON \ -DBUILD_ISA_AVX=OFF \ -DBUILD_ISA_AVX2=OFF \ -DBUILD_ISA_AVX512=OFF \ ``` Standard CMake Build -------------------- ### Compiling OSPRay on Linux and Mac OS X Assuming the above requisites are all fulfilled, building OSPRay through CMake is easy: - Create a build directory, and go into it ``` sh mkdir ospray/build cd ospray/build ``` (We do recommend having separate build directories for different configurations such as release, debug, etc.). - The compiler CMake will use will default to whatever the `CC` and `CXX` environment variables point to. Should you want to specify a different compiler, run cmake manually while specifying the desired compiler. The default compiler on most linux machines is `gcc`, but it can be pointed to `clang` instead by executing the following: ``` sh cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang .. ``` CMake will now use Clang instead of GCC. If you are OK with using the default compiler on your system, then simply skip this step. Note that the compiler variables cannot be changed after the first `cmake` or `ccmake` run. - Open the CMake configuration dialog ``` sh ccmake .. ``` - Make sure to properly set build mode and enable the components you need, etc.; then type ’c’onfigure and ’g’enerate. When back on the command prompt, build it using ``` sh make ``` - You should now have `libospray.[so,dylib]` as well as a set of [example applications](#tutorials). ### Compiling OSPRay on Windows On Windows using the CMake GUI (`cmake-gui.exe`) is the most convenient way to configure OSPRay and to create the Visual Studio solution files: - Browse to the OSPRay sources and specify a build directory (if it does not exist yet CMake will create it). - Click “Configure†and select as generator the Visual Studio version you have; OSPRay needs “Visual Studio 15 2017 Win64†or newer, 32 bit builds are not supported, e.g., “Visual Studio 17 2022â€. - If the configuration fails because some dependencies could not be found then follow the instructions given in the error message, e.g., set the variable `embree_DIR` to the folder where Embree was installed and `openvkl_DIR` to where Open VKL was installed. - Optionally change the default build options, and then click “Generate†to create the solution and project files in the build directory. - Open the generated `OSPRay.sln` in Visual Studio, select the build configuration and compile the project. Alternatively, OSPRay can also be built without any GUI, entirely on the console. In the Visual Studio command prompt type: ``` sh cd path\to\ospray mkdir build cd build cmake -G "Visual Studio 17 2022" [-D VARIABLE=value] .. cmake --build . --config Release ``` Use `-D` to set variables for CMake, e.g., the path to Embree with “`-D embree_DIR=\path\to\embree`â€. You can also build only some projects with the `--target` switch. Additional parameters after “`--`†will be passed to `msbuild`. For example, to build in parallel only the OSPRay library without the example applications use ``` sh cmake --build . --config Release --target ospray -- /m ``` Finding an OSPRay Install with CMake ------------------------------------ Client applications using OSPRay can find it with CMake’s `find_package()` command. For example, ``` sh find_package(ospray 3.0.0 REQUIRED) ``` finds OSPRay via OSPRay’s configuration file `osprayConfig.cmake`[^1]. Once found, the following is all that is required to use OSPRay: ``` sh target_link_libraries(${client_target} ospray::ospray) ``` This will automatically propagate all required include paths, linked libraries, and compiler definitions to the client CMake target (either an executable or library). Advanced users may want to link to additional targets which are exported in OSPRay’s CMake config, which includes all installed modules. All targets built with OSPRay are exported in the `ospray::` namespace, therefore all targets locally used in the OSPRay source tree can be accessed from an install. For example, `ospray_module_cpu` can be consumed directly via the `ospray::ospray_module_cpu` target. All targets have their libraries, includes, and definitions attached to them for public consumption (please [report bugs](#ospray-support-and-contact) if this is broken!). Documentation ============= The following [API documentation](https://www.ospray.org/OSPRay_readme.pdf "OSPRay Documentation") of OSPRay can also be found as a [pdf document](https://www.ospray.org/OSPRay_readme.pdf "OSPRay Documentation"). For a deeper explanation of the concepts, design, features and performance of OSPRay also have a look at the IEEE Vis 2016 paper “[OSPRay – A CPU Ray Tracing Framework for Scientific Visualization](https://www.ospray.org/talks/IEEEVis2016_OSPRay_paper.pdf)†(49MB, or get the [smaller version](https://www.ospray.org/talks/IEEEVis2016_OSPRay_paper_small.pdf) 1.8MB). The [slides of the talk](https://www.ospray.org/talks/IEEEVis2016_OSPRay_talk.pdf) (5.2MB) are also available. OSPRay API ========== To access the OSPRay API you first need to include the OSPRay header ``` cpp #include "ospray/ospray.h" ``` where the API is compatible with C99 and C++. Initialization and Shutdown --------------------------- To use the API, OSPRay must be initialized with a “deviceâ€. A device is the object which implements the API. Creating and initializing a device can be done in either of two ways: command line arguments using `ospInit` or manually instantiating a device and setting parameters on it. ### Command Line Arguments The first is to do so by giving OSPRay the command line from `main()` by calling ``` cpp OSPError ospInit(int *argc, const char **argv); ``` OSPRay parses (and removes) its known command line parameters from your application’s `main` function. For an example see the [tutorial](#osptutorial). For possible error codes see section [Error Handling and Status Messages](#error-handling-and-status-messages). It is important to note that the arguments passed to `ospInit` are processed in order they are listed. The following parameters (which are prefixed by convention with “`--osp:`â€) are understood: | Parameter | Description | |:--------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `--osp:debug` | enables various extra checks and debug output, and disables multi-threading | | `--osp:num-threads=` | use `n` threads instead of per default using all detected hardware threads | | `--osp:log-level=` | set logging level; valid values (in order of severity) are `none`, `error`, `warning`, `info`, and `debug` | | `--osp:warn-as-error` | send `warning` and `error` messages through the error callback, otherwise send `warning` messages through the message callback; must have sufficient `logLevel` to enable warnings | | `--osp:verbose` | shortcut for `--osp:log-level=info` and enable debug output on `cout`, error output on `cerr` | | `--osp:vv` | shortcut for `--osp:log-level=debug` and enable debug output on `cout`, error output on `cerr` | | `--osp:load-modules=[,...]` | load one or more modules during initialization; equivalent to calling `ospLoadModule(name)` | | `--osp:log-output=` | convenience for setting where status messages go; valid values for `dst` are `cerr` and `cout` | | `--osp:error-output=` | convenience for setting where error messages go; valid values for `dst` are `cerr` and `cout` | | `--osp:device=` | use `name` as the type of device for OSPRay to create; e.g., `--osp:device=cpu` gives you the default `cpu` device; Note if the device to be used is defined in a module, remember to pass `--osp:load-modules=` first | | `--osp:set-affinity=` | if `1`, bind software threads to hardware threads; `0` disables binding; default is `0` | | `--osp:device-params=:[,...]` | set one or more other device parameters; equivalent to calling `ospDeviceSet*(param, value)` | Command line parameters accepted by OSPRay’s `ospInit`. ### Manual Device Instantiation The second method of initialization is to explicitly create the device and possibly set parameters. This method looks almost identical to how other [objects](#objects) are created and used by OSPRay (described in later sections). The first step is to create the device with ``` cpp OSPDevice ospNewDevice(const char *type); ``` where the `type` string maps to a specific device implementation. OSPRay always provides the “`cpu`†device, which maps to a fast, local CPU implementation. Other devices can also be added through additional modules, such as distributed MPI device implementations. See next Chapter for details. Once a device is created, you can call ``` cpp void ospDeviceSetParam(OSPObject, const char *id, OSPDataType type, const void *mem); ``` to set parameters on the device. The semantics of setting parameters is exactly the same as `ospSetParam`, which is documented below in the [parameters](#parameters) section. The following parameters can be set on all devices: | Type | Name | Description | |:-------|:------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | int | numThreads | number of threads which OSPRay should use | | uint | logLevel | logging level; valid values (in order of severity) are `OSP_LOG_NONE`, `OSP_LOG_ERROR`, `OSP_LOG_WARNING`, `OSP_LOG_INFO`, and `OSP_LOG_DEBUG` | | string | logOutput | convenience for setting where status messages go; valid values are `cerr` and `cout` | | string | errorOutput | convenience for setting where error messages go; valid values are `cerr` and `cout` | | bool | debug | set debug mode; equivalent to `logLevel=debug` and `numThreads=1` | | bool | warnAsError | send `warning` and `error` messages through the error callback, otherwise send `warning` messages through the message callback; must have sufficient `logLevel` to enable warnings | | bool | setAffinity | bind software threads to hardware threads if set to 1; 0 disables binding omitting the parameter will let OSPRay choose | Parameters shared by all devices. Once parameters are set on the created device, the device must be committed with ``` cpp void ospDeviceCommit(OSPDevice); ``` To use the newly committed device, you must call ``` cpp void ospSetCurrentDevice(OSPDevice); ``` This then sets the given device as the object which will respond to all other OSPRay API calls. Device handle lifetimes are managed with two calls, the first which increments the internal reference count to the given `OSPDevice` ``` cpp void ospDeviceRetain(OSPDevice) ``` and the second which decrements the reference count ``` cpp void ospDeviceRelease(OSPDevice) ``` Users can change parameters on the device after initialization (from either method above), by calling ``` cpp OSPDevice ospGetCurrentDevice(); ``` This function returns the handle to the device currently used to respond to OSPRay API calls, where users can set/change parameters and recommit the device. If changes are made to the device that is already set as the current device, it does not need to be set as current again. Note this API call will increment the ref count of the returned device handle, so applications must use `ospDeviceRelease` when finished using the handle to avoid leaking the underlying device object. If there is no current device set, this will return an invalid `NULL` handle. When a device is created, its reference count is initially `1`. When a device is set as the current device, it internally has its reference count incremented. Note that `ospDeviceRetain` and `ospDeviceRelease` should only be used with reference counts that the application tracks: removing reference held by the current set device should be handled by `ospShutdown`. Thus, `ospDeviceRelease` should only decrement the reference counts that come from `ospNewDevice`, `ospGetCurrentDevice`, and the number of explicit calls to `ospDeviceRetain`. OSPRay allows applications to query runtime properties of a device in order to do enhanced validation of what device was loaded at runtime. The following function can be used to get these device-specific properties (attributes about the device, not parameter values) ``` cpp int64_t ospDeviceGetProperty(OSPDevice, OSPDeviceProperty); ``` It returns an integer value of the queried property and the following properties can be provided as parameter: ``` cpp OSP_DEVICE_VERSION OSP_DEVICE_VERSION_MAJOR OSP_DEVICE_VERSION_MINOR OSP_DEVICE_VERSION_PATCH OSP_DEVICE_SO_VERSION ``` ### Environment Variables OSPRay’s generic device parameters can be overridden via environment variables for easy changes to OSPRay’s behavior without needing to change the application (variables are prefixed by convention with “`OSPRAY_`â€): | Variable | Description | |:---------------------|:-----------------------------------------------------------------------------------------------------------| | OSPRAY_NUM_THREADS | equivalent to `--osp:num-threads` | | OSPRAY_LOG_LEVEL | equivalent to `--osp:log-level` | | OSPRAY_LOG_OUTPUT | equivalent to `--osp:log-output` | | OSPRAY_ERROR_OUTPUT | equivalent to `--osp:error-output` | | OSPRAY_DEBUG | equivalent to `--osp:debug` | | OSPRAY_WARN_AS_ERROR | equivalent to `--osp:warn-as-error` | | OSPRAY_SET_AFFINITY | equivalent to `--osp:set-affinity` | | OSPRAY_LOAD_MODULES | equivalent to `--osp:load-modules`, can be a comma separated list of modules which will be loaded in order | | OSPRAY_DEVICE | equivalent to `--osp:device:` | Environment variables interpreted by OSPRay. Note that these environment variables take precedence over values specified through `ospInit` or manually set device parameters. ### Error Handling and Status Messages The following errors are currently used by OSPRay: | Name | Description | |:----------------------|:-----------------------------------------------------------------------------| | OSP_NO_ERROR | no error occurred | | OSP_UNKNOWN_ERROR | an unknown error occurred | | OSP_INVALID_ARGUMENT | an invalid argument was specified | | OSP_INVALID_OPERATION | the operation is not allowed for the specified object | | OSP_OUT_OF_MEMORY | there is not enough memory to execute the command | | OSP_UNSUPPORTED_CPU | the CPU is not supported (minimum ISA is SSE4.1 on x86_64 and NEON on ARM64) | | OSP_VERSION_MISMATCH | a module could not be loaded due to mismatching version | Possible error codes, i.e., valid named constants of type `OSPError`. These error codes are either directly return by some API functions, or are recorded to be later queried by the application via ``` cpp OSPError ospDeviceGetLastErrorCode(OSPDevice); ``` A more descriptive error message can be queried by calling ``` cpp const char* ospDeviceGetLastErrorMsg(OSPDevice); ``` Alternatively, the application can also register a callback function of type ``` cpp typedef void (*OSPErrorCallback)(void *userData, OSPError, const char* errorDetails); ``` via ``` cpp void ospDeviceSetErrorCallback(OSPDevice, OSPErrorCallback, void *userData); ``` to get notified when errors occur. Applications may be interested in messages which OSPRay emits, whether for debugging or logging events. Applications can call ``` cpp void ospDeviceSetStatusCallback(OSPDevice, OSPStatusCallback, void *userData); ``` in order to register a callback function of type ``` cpp typedef void (*OSPStatusCallback)(void *userData, const char* messageText); ``` which OSPRay will use to emit status messages. By default, OSPRay uses a callback which does nothing, so any output desired by an application will require that a callback is provided. Note that callbacks for C++ `std::cout` and `std::cerr` can be alternatively set through `ospInit` or the `OSPRAY_LOG_OUTPUT` environment variable. Applications can clear either callback by passing `NULL` instead of an actual function pointer. ### Loading OSPRay Extensions at Runtime OSPRay’s functionality can be extended via plugins (which we call “modulesâ€), which are implemented in shared libraries. To load module `name` from `libospray_module_.so` (on Linux and Mac OS X) or `ospray_module_.dll` (on Windows) use ``` cpp OSPError ospLoadModule(const char *name); ``` Modules are searched in OS-dependent paths. `ospLoadModule` returns `OSP_NO_ERROR` if the plugin could be successfully loaded. ### Shutting Down OSPRay When the application is finished using OSPRay (typically on application exit), the OSPRay API should be finalized with ``` cpp void ospShutdown(); ``` This API call ensures that the current device is cleaned up appropriately. Due to static object allocation having non-deterministic ordering, it is recommended that applications call `ospShutdown` before the calling application process terminates. Objects ------- All entities of OSPRay (the [renderer](#renderers), [volumes](#volumes), [geometries](#geometries), [lights](#lights), [cameras](#cameras), …) are a logical specialization of `OSPObject` and share common mechanism to deal with parameters and lifetime. An important aspect of object parameters is that parameters do not get passed to objects immediately. Instead, parameters are not visible at all to objects until they get explicitly committed to a given object via a call to ``` cpp void ospCommit(OSPObject); ``` at which time all previously additions or changes to parameters are visible at the same time. If a user wants to change the state of an existing object (e.g., to change the origin of an already existing camera) it is perfectly valid to do so, as long as the changed parameters are recommitted. The commit semantic allow for batching up multiple small changes, and specifies exactly when changes to objects will occur. This can impact performance and consistency for devices crossing a PCI bus or across a network. Note that OSPRay uses reference counting to manage the lifetime of all objects, so one cannot explicitly “delete†any object. Instead, to indicate that the application does not need and does not access the given object anymore, call ``` cpp void ospRelease(OSPObject); ``` This decreases its reference count and if the count reaches `0` the object will automatically get deleted. Passing `NULL` is not an error. Note that every handle returned via the API needs to be released when the object is no longer needed, to avoid memory leaks. Sometimes applications may want to have more than one reference to an object, where it is desirable for the application to increment the reference count of an object. This is done with ``` cpp void ospRetain(OSPObject); ``` It is important to note that this is only necessary if the application wants to call `ospRelease` on an object more than once: objects which contain other objects as parameters internally increment/decrement ref counts and should not be explicitly done by the application. ### Parameters Parameters allow to configure the behavior of and to pass data to objects. However, objects do *not* have an explicit interface for reasons of high flexibility and a more stable compile-time API. Instead, parameters are passed separately to objects in an arbitrary order, and unknown parameters will simply be ignored (though a warning message will be posted). The following function allows adding various types of parameters with name `id` to a given object: ``` cpp void ospSetParam(OSPObject, const char *id, OSPDataType type, const void *mem); ``` The valid parameter names for all `OSPObject`s and what types are valid are discussed in future sections. Note that `mem` must always be a pointer *to* the object, otherwise accidental type casting can occur. This is especially true for pointer types (`OSP_VOID_PTR` and `OSPObject` handles), as they will implicitly cast to `void *`, but be incorrectly interpreted. To help with some of these issues, there also exist variants of `ospSetParam` for specific types, such as `ospSetInt` and `ospSetVec3f` in the OSPRay utility library (found in `ospray_util.h`). Note that half precision float parameters `OSP_HALF, OSP_VEC[234]H` are not supported. Users can also remove parameters that have been explicitly set from `ospSetParam`. Any parameters which have been removed will go back to their default value during the next commit unless a new parameter was set after the parameter was removed. To remove a parameter, use ``` cpp void ospRemoveParam(OSPObject, const char *id); ``` ### Data OSPRay consumes data arrays from the application using a specific object type, `OSPData`. There are several components to describing a data array: element type, 1/2/3 dimensional striding, and whether the array is shared with the application or copied into opaque, OSPRay-owned memory. Shared data arrays require that the application’s array memory outlives the lifetime of the created `OSPData`, as OSPRay is referring to application memory. Where this is not preferable, applications use opaque arrays to allow the `OSPData` to own the lifetime of the array memory. However, opaque arrays dictate the cost of copying data into it, which should be kept in mind. Thus, the most efficient way to specify a data array from the application is to created a shared data array, which is done with ``` cpp OSPData ospNewSharedData(const void *sharedData, OSPDataType, uint64_t numItems1, int64_t byteStride1 = 0, uint64_t numItems2 = 1, int64_t byteStride2 = 0, uint64_t numItems3 = 1, int64_t byteStride3 = 0, OSPDeleterCallback = NULL, void *userData = NULL); ``` The call returns an `OSPData` handle to the created array. The calling program guarantees that the `sharedData` pointer will remain valid for the duration that this data array is being used. The number of elements `numItems` must be positive (there cannot be an empty data object). The data is arranged in three dimensions, with specializations to two or one dimension (if some `numItems` are 1). The distance between consecutive elements (per dimension) is given in bytes with `byteStride` and can also be negative. If `byteStride` is zero it will be determined automatically (e.g., as `sizeof(type)`). Strides do not need to be ordered, i.e., `byteStride2` can be smaller than `byteStride1`, which is equivalent to a transpose. However, if the stride should be calculated, then an ordering in dimensions is assumed to disambiguate, i.e., `byteStride1 < byteStride2 < byteStride3`. An application can pass ownership of shared data to OSPRay (for example, when it temporarily created a modified version of its data only to make it compatible with OSPRay) by providing a deleter function that OSPRay will call whenever the time comes to deallocate the shared buffer. The deleter function has the following signature: ``` cpp typedef void (*OSPDeleterCallback)(const void *userData, const void *sharedData); ``` where `sharedData` will receive the address of the buffer and `userData` will receive whatever additional state the function needs to perform the deletion (both provided to `ospNewSharedData` when sharing the data with OSPRay). The enum type `OSPDataType` describes the different element types that can be represented in OSPRay; valid constants are listed in the table below. | Type / Name | Description | |:-----------------------------|:---------------------------------------------------------------------------------------------| | OSP_DEVICE | API device object reference | | OSP_DATA | data reference | | OSP_OBJECT | generic object reference | | OSP_CAMERA | camera object reference | | OSP_FRAMEBUFFER | framebuffer object reference | | OSP_LIGHT | light object reference | | OSP_MATERIAL | material object reference | | OSP_TEXTURE | texture object reference | | OSP_RENDERER | renderer object reference | | OSP_WORLD | world object reference | | OSP_GEOMETRY | geometry object reference | | OSP_VOLUME | volume object reference | | OSP_TRANSFER_FUNCTION | transfer function object reference | | OSP_IMAGE_OPERATION | image operation object reference | | OSP_STRING | C-style zero-terminated character string | | OSP_CHAR, OSP_VEC\[234\]C | 8 bit signed character scalar and \[234\]-element vector | | OSP_UCHAR, OSP_VEC\[234\]UC | 8 bit unsigned character scalar and \[234\]-element vector | | OSP_SHORT, OSP_VEC\[234\]S | 16 bit unsigned integer scalar and \[234\]-element vector | | OSP_USHORT, OSP_VEC\[234\]US | 16 bit unsigned integer scalar and \[234\]-element vector | | OSP_INT, OSP_VEC\[234\]I | 32 bit signed integer scalar and \[234\]-element vector | | OSP_UINT, OSP_VEC\[234\]UI | 32 bit unsigned integer scalar and \[234\]-element vector | | OSP_LONG, OSP_VEC\[234\]L | 64 bit signed integer scalar and \[234\]-element vector | | OSP_ULONG, OSP_VEC\[234\]UL | 64 bit unsigned integer scalar and \[234\]-element vector | | OSP_HALF, OSP_VEC\[234\]H | 16 bit half precision floating-point scalar and \[234\]-element vector (IEEE 754 `binary16`) | | OSP_FLOAT, OSP_VEC\[234\]F | 32 bit single precision floating-point scalar and \[234\]-element vector | | OSP_DOUBLE, OSP_VEC\[234\]D | 64 bit double precision floating-point scalar and \[234\]-element vector | | OSP_BOX\[1234\]I | 32 bit integer box (lower + upper bounds) | | OSP_BOX\[1234\]F | 32 bit single precision floating-point box (lower + upper bounds) | | OSP_LINEAR\[23\]F | 32 bit single precision floating-point linear transform (\[23\] vectors) | | OSP_AFFINE\[23\]F | 32 bit single precision floating-point affine transform (linear transform plus translation) | | OSP_QUATF | 32 bit single precision floating-point quaternion, in $(i, j, k, w)$ layout | | OSP_VOID_PTR | raw memory address (only found in module extensions) | Valid named constants for `OSPDataType`. If the elements of the array are handles to objects, then their reference counter is incremented. An opaque `OSPData` with memory allocated by OSPRay is created with ``` cpp OSPData ospNewData(OSPDataType, uint64_t numItems1, uint64_t numItems2 = 1, uint64_t numItems3 = 1); ``` To allow for (partial) copies or updates of data arrays use ``` cpp void ospCopyData(const OSPData source, OSPData destination, uint64_t destinationIndex1 = 0, uint64_t destinationIndex2 = 0, uint64_t destinationIndex3 = 0); ``` which will copy the whole[^2] content of the `source` array into `destination` at the given location `destinationIndex`. The `OSPDataType`s of the data objects must match. The region to be copied must be valid inside the destination, i.e., in all dimensions, `destinationIndex + sourceSize <= destinationSize`. The affected region `[destinationIndex, destinationIndex + sourceSize)` is marked as dirty, which may be used by OSPRay to only process or update that sub-region (e.g., updating an acceleration structure). If the destination array is shared with OSPData by the application (created with `ospNewSharedData`), then - the source array must be shared as well (thus `ospCopyData` cannot be used to read opaque data) - if source and destination memory overlaps (aliasing), then behavior is undefined - except if source and destination regions are identical (including matching strides), which can be used by application to mark that region as dirty (instead of the whole `OSPData`) To add a data array as parameter named `id` to another object call also use ``` cpp void ospSetObject(OSPObject, const char *id, OSPData); ``` Volumes ------- Volumes are volumetric data sets with discretely sampled values in 3D space, typically a 3D scalar field. To create a new volume object of given type `type` use ``` cpp OSPVolume ospNewVolume(const char *type); ``` Note that OSPRay’s implementation forwards `type` directly to Open VKL, allowing new Open VKL volume types to be usable within OSPRay without the need to change (or even recompile) OSPRay. ### Structured Regular Volume Structured volumes only need to store the values of the samples, because their addresses in memory can be easily computed from a 3D position. A common type of structured volumes are regular grids. Structured regular volumes are created by passing the type string “`structuredRegular`†to `ospNewVolume`. Structured volumes are represented through an `OSPData` 3D array `data` (which may or may not be shared with the application). The voxel data must be laid out in xyz-order[^3] and can be compact (best for performance) or can have a stride between voxels, specified through the `byteStride1` parameter when creating the `OSPData`. Only 1D strides are supported, additional strides between scanlines (2D, `byteStride2`) and slices (3D, `byteStride3`) are not. The parameters understood by structured volumes are summarized in the table below. | Type | Name | Default | Description | |:--------|:---------------|---------------------------:|:--------------------------------------------------------------------------------------------------------------------| | vec3f | gridOrigin | $(0, 0, 0)$ | origin of the grid in object-space | | vec3f | gridSpacing | $(1, 1, 1)$ | size of the grid cells in object-space | | OSPData | data | | the actual voxel 3D [data](#data) | | bool | cellCentered | false | whether the data is provided per cell (as opposed to per vertex) | | uint | filter | `OSP_VOLUME_FILTER_LINEAR` | filter used for reconstructing the field, also allowed is `OSP_VOLUME_FILTER_NEAREST` and `OSP_VOLUME_FILTER_CUBIC` | | uint | gradientFilter | same as `filter` | filter used during gradient computations | | float | background | `NaN` | value that is used when sampling an undefined region outside the volume domain | Configuration parameters for structured regular volumes. The size of the volume is inferred from the size of the 3D array `data`, as is the type of the voxel values (currently supported are: `OSP_UCHAR`, `OSP_SHORT`, `OSP_USHORT`, `OSP_HALF`, `OSP_FLOAT`, and `OSP_DOUBLE`). Data can be provided either per cell or per vertex (the default), selectable via the `cellCentered` parameter (which will also affect the computed bounding box). ### Structured Spherical Volume Structured spherical volumes are also supported, which are created by passing a type string of “`structuredSpherical`†to `ospNewVolume`. The grid dimensions and parameters are defined in terms of radial distance $r$, inclination angle $\theta$, and azimuthal angle $\phi$, conforming with the ISO convention for spherical coordinate systems. The coordinate system and parameters understood by structured spherical volumes are summarized below.
Coordinate system of structured spherical volumes.
| Type | Name | Default | Description | |:--------|:---------------|----------------------------:|:----------------------------------------------------------------------------------------------------------------| | vec3f | gridOrigin | $(0, 0, 0)$ | origin of the grid in units of $(r, \theta, \phi)$; angles in degrees | | vec3f | gridSpacing | $(1, 180/dim.y, 360/dim.z)$ | size of the grid cells in units of $(r, \theta, \phi)$, per default covering the full sphere; angles in degrees | | OSPData | data | | the actual voxel 3D [data](#data) | | uint | filter | `OSP_VOLUME_FILTER_LINEAR` | filter used for reconstructing the field, also allowed is `OSP_VOLUME_FILTER_NEAREST` | | uint | gradientFilter | same as `filter` | filter used during gradient computations | | float | background | `NaN` | value that is used when sampling an undefined region outside the volume domain | Configuration parameters for structured spherical volumes. The dimensions $(r, \theta, \phi)$ of the volume are inferred from the size of the 3D array `data`, as is the type of the voxel values (currently supported are: `OSP_UCHAR`, `OSP_SHORT`, `OSP_USHORT`, `OSP_HALF`, `OSP_FLOAT`, and `OSP_DOUBLE`). These grid parameters support flexible specification of spheres, hemispheres, spherical shells, spherical wedges, and so forth. The grid extents (computed as `[gridOrigin, gridOrigin + (dimensions - 1) * gridSpacing]`) however must be constrained such that: - $r \geq 0$ - $0 \leq \theta \leq 180$ - $0 \leq \phi \leq 360$ ### Adaptive Mesh Refinement (AMR) Volume OSPRay currently supports block-structured (Berger-Colella) AMR volumes. Volumes are specified as a list of blocks, which exist at levels of refinement in potentially overlapping regions. Blocks exist in a tree structure, with coarser refinement level blocks containing finer blocks. The cell width is equal for all blocks at the same refinement level, though blocks at a coarser level have a larger cell width than finer levels. There can be any number of refinement levels and any number of blocks at any level of refinement. An AMR volume type is created by passing the type string “`amr`†to `ospNewVolume`. Blocks are defined by three parameters: their bounds, the refinement level in which they reside, and the scalar data contained within each block. Note that cell widths are defined *per refinement level*, not per block. | Type | Name | Default | Description | |:------------|:-------------|------------------:|:-----------------------------------------------------------------------------------------------------------------------| | uint | method | `OSP_AMR_CURRENT` | `OSPAMRMethod` sampling method. Supported methods are: | | | | | `OSP_AMR_CURRENT` | | | | | `OSP_AMR_FINEST` | | | | | `OSP_AMR_OCTANT` | | float\[\] | cellWidth | NULL | array of each level’s cell width | | box3i\[\] | block.bounds | NULL | [data](#data) array of grid sizes (in voxels) for each AMR block | | int\[\] | block.level | NULL | array of each block’s refinement level | | OSPData\[\] | block.data | NULL | [data](#data) array of OSPData containing the actual scalar voxel data, only `OSP_FLOAT` is supported as `OSPDataType` | | vec3f | gridOrigin | $(0, 0, 0)$ | origin of the grid | | vec3f | gridSpacing | $(1, 1, 1)$ | size of the grid cells | | float | background | `NaN` | value that is used when sampling an undefined region outside the volume domain | Configuration parameters for AMR volumes. Lastly, note that the `gridOrigin` and `gridSpacing` parameters act just like the structured volume equivalent, but they only modify the root (coarsest level) of refinement. In particular, OSPRay’s / Open VKL’s AMR implementation was designed to cover Berger-Colella \[1\] and Chombo \[2\] AMR data. The `method` parameter above determines the interpolation method used when sampling the volume. OSP_AMR_CURRENT finds the finest refinement level at that cell and interpolates through this “current†level OSP_AMR_FINEST will interpolate at the closest existing cell in the volume-wide finest refinement level regardless of the sample cell’s level OSP_AMR_OCTANT interpolates through all available refinement levels at that cell. This method avoids discontinuities at refinement level boundaries at the cost of performance Details and more information can be found in the publication for the implementation \[3\]. 1. M.J. Berger and P. Colella, “Local adaptive mesh refinement for shock hydrodynamics.†Journal of Computational Physics 82.1 (1989): 64-84. DOI: 10.1016/0021-9991(89)90035-1 2. M. Adams, P. Colella, D.T. Graves, J.N. Johnson, N.D. Keen, T.J. Ligocki, D.F. Martin. P.W. McCorquodale, D. Modiano. P.O. Schwartz, T.D. Sternberg, and B. Van Straalen, “Chombo Software Package for AMR Applications – Design Documentâ€, Lawrence Berkeley National Laboratory Technical Report LBNL-6616E. 3. I. Wald, C. Brownlee, W. Usher, and A. Knoll, “CPU volume rendering of adaptive mesh refinement dataâ€. SIGGRAPH Asia 2017 Symposium on Visualization – SA ’17, 18(8), 1–8. DOI: 10.1145/3139295.3139305 ### Unstructured Volume Unstructured volumes can have their topology and geometry freely defined. Geometry can be composed of tetrahedral, hexahedral, wedge or pyramid cell types. The data format used is compatible with VTK and consists of multiple arrays: vertex positions and values, vertex indices, cell start indices, cell types, and cell values. An unstructured volume type is created by passing the type string “`unstructured`†to `ospNewVolume`. Sampled cell values can be specified either per-vertex (`vertex.data`) or per-cell (`cell.data`). If both arrays are set, `cell.data` takes precedence. Similar to a mesh, each cell is formed by a group of indices into the vertices. For each vertex, the corresponding (by array index) data value will be used for sampling when rendering, if specified. The index order for a tetrahedron is the same as `VTK_TETRA`: bottom triangle counterclockwise, then the top vertex. For hexahedral cells, each hexahedron is formed by a group of eight indices into the vertices and data values. Vertex ordering is the same as `VTK_HEXAHEDRON`: four bottom vertices counterclockwise, then top four counterclockwise. For wedge cells, each wedge is formed by a group of six indices into the vertices and data values. Vertex ordering is the same as `VTK_WEDGE`: three bottom vertices counterclockwise, then top three counterclockwise. For pyramid cells, each cell is formed by a group of five indices into the vertices and data values. Vertex ordering is the same as `VTK_PYRAMID`: four bottom vertices counterclockwise, then the top vertex. To maintain VTK data compatibility, the `index` array may be specified with cell sizes interleaved with vertex indices in the following format: $n, id_1, ..., id_n, m, id_1, ..., id_m$. This alternative `index` array layout can be enabled through the `indexPrefixed` flag (in which case, the `cell.type` parameter must be omitted). | Type | Name | Default | Description | |:------------------------|:-------------------|--------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------| | vec3f\[\] | vertex.position | | [data](#data) array of vertex positions | | float\[\] | vertex.data | | [data](#data) array of vertex data values to be sampled | | uint32\[\] / uint64\[\] | index | | [data](#data) array of indices (into the vertex array(s)) that form cells | | bool | indexPrefixed | false | indicates that the `index` array is compatible to VTK, where the indices of each cell are prefixed with the number of vertices | | uint32\[\] / uint64\[\] | cell.index | | [data](#data) array of locations (into the index array), specifying the first index of each cell | | float\[\] | cell.data | | [data](#data) array of cell data values to be sampled | | uint8\[\] | cell.type | | [data](#data) array of cell types (VTK compatible), only set if `indexPrefixed = false` false. Supported types are: | | | | | `OSP_TETRAHEDRON` | | | | | `OSP_HEXAHEDRON` | | | | | `OSP_WEDGE` | | | | | `OSP_PYRAMID` | | bool | hexIterative | false | hexahedron interpolation method, defaults to fast non-iterative version which could have rendering inaccuracies may appear if hex is not parallelepiped | | bool | precomputedNormals | false | whether to accelerate by precomputing, at a cost of 12 bytes/face | | float | background | `NaN` | value that is used when sampling an undefined region outside the volume domain | Configuration parameters for unstructured volumes. ### VDB Volume VDB volumes implement a data structure that is very similar to the data structure outlined in Museth \[1\], they are created by passing the type string “`vdb`†to `ospNewVolume`. The data structure is a hierarchical regular grid at its core: Nodes are regular grids, and each grid cell may either store a constant value (this is called a tile), or child pointers. Nodes in VDB trees are wide: Nodes on the first level have a resolution of 323 voxels, on the next level 163, and on the leaf level 83 voxels. All nodes on a given level have the same resolution. This makes it easy to find the node containing a coordinate using shift operations (see \[1\]). VDB leaf nodes are implicit in OSPRay / Open VKL: they are stored as pointers to user-provided data.
Topology of VDB volumes.
VDB volumes interpret input data as constant cells (which are then potentially filtered). This is in contrast to `structuredRegular` volumes, which have a vertex-centered interpretation. The VDB implementation in OSPRay / Open VKL follows the following goals: - Efficient data structure traversal on vector architectures. - Enable the use of industry-standard `.vdb` files created through the OpenVDB library. - Compatibility with OpenVDB on a leaf data level, so that `.vdb` file may be loaded with minimal overhead. VDB volumes have the following parameters: | Type | Name | Description | |:------------|:-----------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | int | maxSamplingDepth | do not descend further than to this depth during sampling, the maximum value and the default is 3 | | uint32\[\] | node.level | level on which each input node exists, may be 1, 2 or 3 (levels are counted from the root level = 0 down) | | vec3i\[\] | node.origin | the node origin index (per input node) | | OSPData\[\] | node.data | [data](#data) arrays with the node data (per input node). Nodes that are tiles are expected to have single-item arrays. Leaf-nodes with grid data expected to have compact 3D arrays in zyx layout (z changes most quickly) with the correct number of voxels for the `level`. Only `OSP_FLOAT` is supported as field `OSPDataType`. | | OSPData | nodesPackedDense | optionally provided instead of `node.data`, a single array of all dense node data in a contiguous zyx layout, provided in the same order as the corresponding `node.*` parameters | | OSPData | nodesPackedTile | optionally provided instead of `node.data`, a single array of all tile node data in a contiguous layout, provided in the same order as the corresponding `node.*` parameters | | uint32\[\] | node.format | for each input node, whether it is of format `OSP_VOLUME_FORMAT_DENSE_ZYX` (and thus stored in `nodesPackedDense`), or `OSP_VOLUME_FORMAT_TILE` (stored in `nodesPackedTile`) | | uint | filter | filter used for reconstructing the field, default is `OSP_VOLUME_FILTER_LINEAR`, alternatively `OSP_VOLUME_FILTER_NEAREST`, or `OSP_VOLUME_FILTER_CUBIC`. | | uint | gradientFilter | filter used for reconstructing the field during gradient computations, default same as `filter` | | float | background | value that is used when sampling an undefined region outside the volume domain, default `NaN` | Configuration parameters for VDB volumes. The `nodesPackedDense` and `nodesPackedTile` together with `node.format` parameters may be provided instead of `node.data`; this packed data layout may provide better performance. 1. Museth, K. VDB: High-Resolution Sparse Volumes with Dynamic Topology. ACM Transactions on Graphics 32(3), 2013. DOI: 10.1145/2487228.2487235 ### Particle Volume Particle volumes consist of a set of points in space. Each point has a position, a radius, and a weight typically associated with an attribute. Particle volumes are created by passing the type string “`particle`†to `ospNewVolume`. A radial basis function defines the contribution of that particle. Currently, we use the Gaussian radial basis function $$\phi(P) = w \exp\left(-\frac{(P - p)^2}{2 r^2}\right),$$ where $P$ is the particle position, $p$ is the sample position, $r$ is the radius and $w$ is the weight. At each sample, the scalar field value is then computed as the sum of each radial basis function $\phi$, for each particle that overlaps it. The OSPRay / Open VKL implementation is similar to direct evaluation of samples in Reda et al. \[2\]. It uses an Embree-built BVH with a custom traversal, similar to the method in \[1\]. | Type | Name | Default | Description | |:----------|:------------------------|--------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | vec3f\[\] | particle.position | | [data](#data) array of particle positions | | float\[\] | particle.radius | | [data](#data) array of particle radii | | float\[\] | particle.weight | NULL | optional [data](#data) array of particle weights, specifying the height of the kernel. | | float | radiusSupportFactor | 3.0 | The multiplier of the particle radius required for support. Larger radii ensure smooth results at the cost of performance. In the Gaussian kernel, the radius is one standard deviation ($\sigma$), so a value of 3 corresponds to $3 \sigma$. | | float | clampMaxCumulativeValue | 0 | The maximum cumulative value possible, set by user. All cumulative values will be clamped to this, and further traversal (RBF summation) of particle contributions will halt when this value is reached. A value of zero or less turns this off. | | bool | estimateValueRanges | true | Enable heuristic estimation of value ranges which are used in internal acceleration structures as well as for determining the volume’s overall value range. When set to `false`, the user *must* specify `clampMaxCumulativeValue`, and all value ranges will be assumed \[0–`clampMaxCumulativeValue`\]. Disabling this switch may improve volume commit time, but will make volume rendering less efficient. | Configuration parameters for particle volumes. 1. A. Knoll, I. Wald, P. Navratil, A. Bowen, K. Reda, M.E., Papka, and K. Gaither, “RBF Volume Ray Casting on Multicore and Manycore CPUsâ€, 2014, Computer Graphics Forum, 33: 71–80. doi:10.1111/cgf.12363 2. K. Reda, A. Knoll, K. Nomura, M. E. Papka, A. E. Johnson and J. Leigh, “Visualizing large-scale atomistic simulations in ultra-resolution immersive environmentsâ€, 2013 IEEE Symposium on Large-Scale Data Analysis and Visualization (LDAV), Atlanta, GA, 2013, pp. 59–65. ### Transfer Function Transfer functions map the scalar values of volumes to color and opacity and thus they can be used to visually emphasize certain features of the volume. To create a new transfer function of given type `type` use ``` cpp OSPTransferFunction ospNewTransferFunction(const char *type); ``` The returned handle can be assigned to a volumetric model (described below) as parameter “`transferFunction`†using `ospSetObject`. One type of transfer function that is supported by OSPRay is the linear transfer function, which interpolates between given equidistant colors and opacities. It is create by passing the string “`piecewiseLinear`†to `ospNewTransferFunction` and it is controlled by these parameters: | Type | Name | Description | |:----------|:--------|:----------------------------------------------| | vec3f\[\] | color | [data](#data) array of colors (linear RGB) | | float\[\] | opacity | [data](#data) array of opacities | | box1f | value | domain (scalar range) this function maps from | Parameters accepted by the linear transfer function. The arrays `color` and `opacity` can be of different length. ### VolumetricModels Volumes in OSPRay are given volume rendering appearance information through VolumetricModels. This decouples the physical representation of the volume (and possible acceleration structures it contains) to rendering-specific parameters (where more than one set may exist concurrently). To create a volume instance, call ``` cpp OSPVolumetricModel ospNewVolumetricModel(OSPVolume); ``` The passed volume can be `NULL` as long as the volume to be used is passed as a parameter. If both a volume is specified on object creation and as a parameter, the parameter value is used. If the parameter value is later removed, the volume object passed on object creation is again used. | Type | Name | Default | Description | |:--------------------|:-----------------|--------:|:-------------------------------------------------------------------------------------------------------------------------------------| | OSPVolume | volume | | optional [volume](#volumes) object this model references | | OSPTransferFunction | transferFunction | | [transfer function](#transfer-function) to use | | float | densityScale | 1.0 | makes volumes uniformly thinner or thicker | | float | anisotropy | 0.0 | anisotropy of the (Henyey-Greenstein) phase function in \[-1–1\] ([path tracer](#path-tracer) only), default to isotropic scattering | | uint32 | id | -1u | optional user ID, for [framebuffer](#framebuffer) channel `OSP_FB_ID_OBJECT` | Parameters understood by VolumetricModel. Geometries ---------- Geometries in OSPRay are objects that describe intersectable surfaces. To create a new geometry object of given type `type` use ``` cpp OSPGeometry ospNewGeometry(const char *type); ``` Note that in the current implementation geometries are limited to a maximum of 232 primitives. ### Mesh A mesh consisting of either triangles or quads is created by calling `ospNewGeometry` with type string “`mesh`â€. Once created, a mesh recognizes the following parameters: | Type | Name | Description | |:------------------------|:-----------------------|:---------------------------------------------------------------------------------------------------------------------| | vec3f\[\] | vertex.position | [data](#data) array of vertex positions, overridden by `motion.*` arrays | | vec3f\[\] | normal | [data](#data) array of face-varying normals, overridden by `motion.*` arrays | | vec3f\[\] | vertex.normal | [data](#data) array of vertex-varying normals, overridden by `motion.*` arrays | | vec4f\[\] / vec3f\[\] | color | [data](#data) array of face-varying colors (linear RGBA/RGB) | | vec4f\[\] / vec3f\[\] | vertex.color | [data](#data) array of vertex-varying colors (linear RGBA/RGB) | | vec2f\[\] | texcoord | [data](#data) array of face-varying texture coordinates | | vec2f\[\] | vertex.texcoord | [data](#data) array of vertex-varying texture coordinates | | vec3ui\[\] / vec4ui\[\] | index | [data](#data) array of (either triangle or quad) indices (into the vertex array(s)) | | bool | quadSoup | when no explicit `index` is given, indicates whether to assume a ‘soup’ of quads instead of triangles, default false | | vec3f\[\]\[\] | motion.vertex.position | [data](#data) array of vertex position arrays (uniformly distributed keys for deformation motion blur) | | vec3f\[\]\[\] | motion.normal | [data](#data) array of face-varying normal arrays (uniformly distributed keys for deformation motion blur) | | vec3f\[\]\[\] | motion.vertex.normal | [data](#data) array of vertex-varying normal arrays (uniformly distributed keys for deformation motion blur) | | box1f | time | time associated with first and last key in `motion.*` arrays (for deformation motion blur), default \[0, 1\] | Parameters defining a mesh geometry. The data type of index arrays differentiates between the underlying geometry, triangles are used for a index with `vec3ui` type and quads for `vec4ui` type. Quads are internally handled as a pair of two triangles, thus mixing triangles and quads is supported by encoding some triangle as a quad with the last two vertex indices being identical (`w=z`). The `vertex.position` array is mandatory to create a valid mesh. The `index` array is optional. If none is provided, a ‘triangle soup’ is assumed, i.e., each three consecutive vertices form one triangle; unless the boolean `quadSoup` is set to true, then a ‘quad soup’ is assumed i.e., each four subsequent vertices form one quad. If the size of the `vertex.position` array is not a multiple of three for triangles or four for quads, the remainder vertices are ignored. ### Subdivision A mesh consisting of subdivision surfaces, created by specifying a geometry of type “`subdivision`â€. Once created, a subdivision recognizes the following parameters: | Type | Name | Description | |:----------|:--------------------|:----------------------------------------------------------------------------------------------------------------------| | vec3f\[\] | vertex.position | [data](#data) array of vertex positions | | vec4f\[\] | color | optional [data](#data) array of face-varying colors (linear RGBA) | | vec4f\[\] | vertex.color | optional [data](#data) array of vertex-varying colors (linear RGBA) | | vec2f\[\] | texcoord | optional [data](#data) array of vertex-varying texture coordinates | | vec2f\[\] | vertex.texcoord | optional [data](#data) array of vertex-varying texture coordinates | | float | level | global level of tessellation, default 5 | | uint\[\] | index | [data](#data) array of indices (into the vertex array(s)) | | float\[\] | index.level | optional [data](#data) array of per-edge levels of tessellation, overrides global level | | uint\[\] | face | optional [data](#data) array holding the number of indices/edges (3 to 15) per face, defaults to 4 (a pure quad mesh) | | vec2i\[\] | edgeCrease.index | optional [data](#data) array of edge crease indices | | float\[\] | edgeCrease.weight | optional [data](#data) array of edge crease weights | | uint\[\] | vertexCrease.index | optional [data](#data) array of vertex crease indices | | float\[\] | vertexCrease.weight | optional [data](#data) array of vertex crease weights | | uint | mode | `OSPSubdivisionMode` subdivision edge boundary mode, supported modes are: | | | | `OSP_SUBDIVISION_NO_BOUNDARY` | | | | `OSP_SUBDIVISION_SMOOTH_BOUNDARY` (default) | | | | `OSP_SUBDIVISION_PIN_CORNERS` | | | | `OSP_SUBDIVISION_PIN_BOUNDARY` | | | | `OSP_SUBDIVISION_PIN_ALL` | Parameters defining a Subdivision geometry. The `vertex` and `index` arrays are mandatory to create a valid subdivision surface. If no `face` array is present then a pure quad mesh is assumed (the number of indices must be a multiple of 4). Optionally supported are edge and vertex creases. ### Spheres A geometry consisting of individual spheres, each of which can have an own radius, is created by calling `ospNewGeometry` with type string “`sphere`â€. The spheres will not be tessellated but rendered procedurally and are thus perfectly round. To allow a variety of sphere representations in the application this geometry allows a flexible way of specifying the data of center position and radius within a [data](#data) array: | Type | Name | Default | Description | |:----------|:----------------|--------:|:--------------------------------------------------------------------------| | vec3f\[\] | sphere.position | | [data](#data) array of center positions | | float\[\] | sphere.radius | NULL | optional [data](#data) array of the per-sphere radius | | vec3f\[\] | sphere.normal | NULL | optional [data](#data) array of normals (only for “oriented discâ€) | | vec2f\[\] | sphere.texcoord | NULL | optional [data](#data) array of texture coordinates (constant per sphere) | | float | radius | 0.01 | default radius for all spheres (if `sphere.radius` is not set) | | uint | type | | `OSPSphereType` for rendering the sphere. Supported types are: | | | | | `OSP_SPHERE` (default) | | | | | `OSP_DISC` | | | | | `OSP_ORIENTED_DISC` | Parameters defining a spheres geometry. ### Curves A geometry consisting of multiple curves is created by calling `ospNewGeometry` with type string “`curve`â€. The parameters defining this geometry are listed in the table below. | Type | Name | Description | |:-----------|:-----------------------|:---------------------------------------------------------------------------------| | vec4f\[\] | vertex.position_radius | [data](#data) array of vertex position and per-vertex radius | | vec2f\[\] | vertex.texcoord | [data](#data) array of per-vertex texture coordinates | | vec4f\[\] | vertex.color | [data](#data) array of corresponding vertex colors (linear RGBA) | | vec3f\[\] | vertex.normal | [data](#data) array of curve normals (only for “ribbon†curves) | | vec4f\[\] | vertex.tangent | [data](#data) array of curve tangents (only for “hermite†curves) | | uint32\[\] | index | [data](#data) array of indices to the first vertex or tangent of a curve segment | | uint | type | `OSPCurveType` for rendering the curve. Supported types are: | | | | `OSP_FLAT` | | | | `OSP_ROUND` | | | | `OSP_RIBBON` | | | | `OSP_DISJOINT` | | uint | basis | `OSPCurveBasis` for defining the curve. Supported bases are: | | | | `OSP_LINEAR` | | | | `OSP_BEZIER` | | | | `OSP_BSPLINE` | | | | `OSP_HERMITE` | | | | `OSP_CATMULL_ROM` | Parameters defining a curves geometry. Positions in `vertex.position_radius` parameter supports per-vertex varying radii with data type `vec4f[]` and instantiate Embree curves internally for the relevant type/basis mapping. The following section describes the properties of different curve basis’ and how they use the data provided in data buffers: OSP_LINEAR The indices point to the first of 2 consecutive control points in the vertex buffer. The first control point is the start and the second control point the end of the line segment. The curve goes through all control points listed in the vertex buffer. OSP_BEZIER The indices point to the first of 4 consecutive control points in the vertex buffer. The first control point represents the start point of the curve, and the 4th control point the end point of the curve. The Bézier basis is interpolating, thus the curve does go exactly through the first and fourth control vertex. OSP_BSPLINE The indices point to the first of 4 consecutive control points in the vertex buffer. This basis is not interpolating, thus the curve does in general not go through any of the control points directly. Using this basis, 3 control points can be shared for two continuous neighboring curve segments, e.g., the curves $(p0, p1, p2, p3)$ and $(p1, p2, p3, p4)$ are C1 continuous. This feature make this basis a good choice to construct continuous multi-segment curves, as memory consumption can be kept minimal. OSP_HERMITE It is necessary to have both vertex buffer and tangent buffer for using this basis. The indices point to the first of 2 consecutive points in the vertex buffer, and the first of 2 consecutive tangents in the tangent buffer. This basis is interpolating, thus does exactly go through the first and second control point, and the first order derivative at the begin and end matches exactly the value specified in the tangent buffer. When connecting two segments continuously, the end point and tangent of the previous segment can be shared. OSP_CATMULL_ROM The indices point to the first of 4 consecutive control points in the vertex buffer. If $(p0, p1, p2, p3)$ represent the points then this basis goes through $p1$ and $p2$, with tangents as $(p2-p0)/2$ and $(p3-p1)/2$. The following section describes the properties of different curve types’ and how they define the geometry of a curve: OSP_FLAT This type enables faster rendering as the curve is rendered as a connected sequence of ray facing quads. OSP_ROUND This type enables rendering a real geometric surface for the curve which allows closeup views. This mode renders a sweep surface by sweeping a varying radius circle tangential along the curve. OSP_RIBBON The type enables normal orientation of the curve and requires a normal buffer be specified along with vertex buffer. The curve is rendered as a flat band whose center approximately follows the provided vertex buffer and whose normal orientation approximately follows the provided normal buffer. Not supported for basis `OSP_LINEAR`. OSP_DISJOINT Only supported for basis `OSP_LINEAR`; the segments are open and not connected at the joints, i.e., the curve segments are either individual cones or cylinders. ### Boxes OSPRay can directly render axis-aligned bounding boxes without the need to convert them to quads or triangles. To do so create a boxes geometry by calling `ospNewGeometry` with type string “`box`â€. | Type | Name | Description | |:----------|:-----|:-----------------------------| | box3f\[\] | box | [data](#data) array of boxes | Parameters defining a boxes geometry. ### Planes OSPRay can directly render planes defined by plane equation coefficients in its implicit form $ax + by + cz + d = 0$. By default planes are infinite but their extents can be limited by defining optional bounding boxes. A planes geometry can be created by calling `ospNewGeometry` with type string “`plane`â€. | Type | Name | Description | |:----------|:-------------------|:---------------------------------------------------------| | vec4f\[\] | plane.coefficients | [data](#data) array of plane coefficients $(a, b, c, d)$ | | box3f\[\] | plane.bounds | optional [data](#data) array of bounding boxes | Parameters defining a planes geometry. ### Isosurfaces OSPRay can directly render multiple isosurfaces of a volume without first tessellating them. To do so create an isosurfaces geometry by calling `ospNewGeometry` with type string “`isosurface`â€. The appearance information of the surfaces is set through the Geometric Model. Per-isosurface colors can be set by passing per-primitive colors to the Geometric Model, in order of the isosurface array. | Type | Name | Description | |:----------|:---------|:---------------------------------------------------| | float | isovalue | single isovalues | | float\[\] | isovalue | [data](#data) array of isovalues | | OSPVolume | volume | handle of the [Volume](#volumes) to be isosurfaced | Parameters defining an isosurfaces geometry. ### GeometricModels Geometries are matched with surface appearance information through GeometricModels. These take a geometry, which defines the surface representation, and applies either full-object or per-primitive color and material information. To create a geometric model, call ``` cpp OSPGeometricModel ospNewGeometricModel(OSPGeometry); ``` The passed geometry can be `NULL` as long as the geometry to be used is passed as a parameter. If both a geometry is specified on object creation and as a parameter, the parameter value is used. If the parameter value is later removed, the geometry object passed on object creation is again used. Color and material are fetched with the primitive ID of the hit (clamped to the valid range, thus a single color or material is fine), or mapped first via the `index` array (if present). All parameters are optional, however, some renderers (notably the [path tracer](#path-tracer)) require a material to be set. Materials are either handles of `OSPMaterial`, or indices into the `material` array on the [renderer](#renderers), which allows to build a [world](#world) which can be used by different types of renderers. An `invertNormals` flag allows to invert (shading) normal vectors of the rendered geometry. That is particularly useful for clipping. By changing normal vectors orientation one can control whether inside or outside of the clipping geometry is being removed. For example, a clipping geometry with normals oriented outside clips everything what’s inside. | Type | Name | Description | |:----------------------------------------------------|:--------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------| | OSPGeometry | geometry | optional [geometry](#geometries) object this model references | | OSPMaterial / OSPMaterial\[\] / uint32 / uint32\[\] | material | optional ([data](#data) array of per-primitive) [material](#materials), may be an index into the `material` parameter on the renderer (if it exists) | | vec4f / vec4f\[\] | color | optional ([data](#data) array of per-primitive) color assigned to the geometry (linear RGBA) | | uint8\[\] | index | optional [data](#data) array of per-primitive indices into `color` and `material` | | bool | invertNormals | inverts all shading normals (Ns), default false | | uint32 | id | optional user ID, for [framebuffer](#framebuffer) channel `OSP_FB_ID_OBJECT`, default -1u | Parameters understood by GeometricModel. Lights ------ To create a new light source of given type `type` use ``` cpp OSPLight ospNewLight(const char *type); ``` All light sources accept the following parameters: | Type | Name | Default | Description | |:------|:------------------|--------:|:----------------------------------------------------------------------------------------------------------------------------------| | vec3f | color | white | color of the light (linear RGB) | | float | intensity | 1 | intensity of the light (a factor) | | uint | intensityQuantity | | `OSPIntensityQuantity` to set the radiometric quantity represented by `intensity`. The default value depends on the light source. | | bool | visible | true | whether the light can be directly seen | Parameters accepted by all lights. In OSPRay the `intensity` parameter of a light source can correspond to different types of radiometric quantities. The type of the value represented by a light’s `intensity` parameter is set using `intensityQuantity`, which accepts values from the enum type `OSPIntensityQuantity`. The supported types of `OSPIntensityQuantity` differ between the different light sources (see documentation of each specific light source). | Name | Description | |:----------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------| | OSP_INTENSITY_QUANTITY_POWER | the overall amount of light energy emitted by the light source into the scene, unit is W | | OSP_INTENSITY_QUANTITY_INTENSITY | the overall amount of light emitted by the light in a given direction, unit is W/sr | | OSP_INTENSITY_QUANTITY_RADIANCE | the amount of light emitted by a point on the light source in a given direction, unit is W/sr/m2 | | OSP_INTENSITY_QUANTITY_IRRADIANCE | the amount of light arriving at a surface point, assuming the light is oriented towards to the surface, unit is W/m2 | | OSP_INTENSITY_QUANTITY_SCALE | a linear scaling factor for light sources with a built-in quantity (e.g., `HDRI`, or `sunSky`, or when using `intensityDistribution`). | Types of radiometric quantities used to interpret a light’s `intensity` parameter. ### Photometric Lights Measured light sources (IES, EULUMDAT, …) are supported by the `sphere`, `spot`, and `quad` lights when setting an `intensityDistribution` [data](#data) array to modulate the intensity per direction. The mapping is using the C-γ coordinate system (see also below figure): the values of the first (or only) dimension of `intensityDistribution` are uniformly mapped to γ in \[0–π\]; the first intensity value to 0, the last value to Ï€, thus at least two values need to be present. ![C-γ coordinate system for the mapping of `intensityDistribution` with photometric lights.](https://ospray.github.io/images/c-gamma_coords.png) If the array has a second dimension then the intensities are not rotational symmetric around the main direction (where angle γ is zero), but are accordingly mapped to the C-halfplanes in \[0–2Ï€\]; the first “row†of values to 0 and 2Ï€, the other rows such that they have uniform distance to its neighbors. The orientation of the C0-plane is specified via `c0`. | Type | Name | Description | |:----------|:----------------------|:----------------------------------------------------------------------------------------------------------------------------------------------| | float\[\] | intensityDistribution | luminous intensity distribution for photometric lights; can be 2D for asymmetric illumination; values are assumed to be uniformly distributed | | vec3f | c0 | orientation, i.e., direction of the C0-(half)plane (only needed if illumination via `intensityDistribution` is asymmetric) | Special parameters for photometric lights. When using an `intensityDistribution` then the default and only valid value for `intensityQuantity` is `OSP_INTENSITY_QUANTITY_SCALE`. The following light types are supported by most OSPRay renderers. ### Directional Light / Distant Light The distant light (or traditionally the directional light) is thought to be far away (outside of the scene), thus its light arrives (almost) as parallel rays. It is created by passing the type string “`distant`†to `ospNewLight`. The distant light supports `OSP_INTENSITY_QUANTITY_RADIANCE` and `OSP_INTENSITY_QUANTITY_IRRADIANCE` (default) as `intensityQuantity` parameter value. In addition to the [general parameters](#lights) understood by all lights the distant light supports the following special parameters: | Type | Name | Default | Description | |:------|:----------------|------------:|:---------------------------------------------| | vec3f | direction | $(0, 0, 1)$ | main emission direction of the distant light | | float | angularDiameter | 0 | apparent size (angle in degree) of the light | Special parameters accepted by the distant light. Setting the angular diameter to a value greater than zero will result in soft shadows when the renderer uses stochastic sampling (like the [path tracer](#path-tracer)). For instance, the apparent size of the sun is about 0.53°. ### Point Light / Sphere Light The sphere light (or the special case point light) is a light emitting uniformly in all directions from the surface toward the outside. It does not emit any light toward the inside of the sphere. It is created by passing the type string “`sphere`†to `ospNewLight`. The point light supports only `OSP_INTENSITY_QUANTITY_SCALE` when `intensityDistribution` is set, or otherwise `OSP_INTENSITY_QUANTITY_POWER`, `OSP_INTENSITY_QUANTITY_INTENSITY` (then default) and `OSP_INTENSITY_QUANTITY_RADIANCE` as `intensityQuantity` parameter value. In addition to the [general parameters](#lights) understood by all lights and the [photometric parameters](#photometric-lights) the sphere light supports the following special parameters: | Type | Name | Default | Description | |:------|:----------|------------:|:--------------------------------------------| | vec3f | position | $(0, 0, 0)$ | the center of the sphere light | | float | radius | 0 | the size of the sphere light | | vec3f | direction | $(0, 0, 1)$ | main orientation of `intensityDistribution` | Special parameters accepted by the sphere light. Setting the radius to a value greater than zero will result in soft shadows when the renderer uses stochastic sampling (like the [path tracer](#path-tracer)). ### Spotlight / Ring Light The spotlight is a light emitting into a cone of directions. It is created by passing the type string “`spot`†to `ospNewLight`. The spotlight supports only `OSP_INTENSITY_QUANTITY_SCALE` when `intensityDistribution` is set, or otherwise `OSP_INTENSITY_QUANTITY_POWER`, `OSP_INTENSITY_QUANTITY_INTENSITY` (then default) and `OSP_INTENSITY_QUANTITY_RADIANCE` as `intensityQuantity` parameter value. In addition to the [general parameters](#lights) understood by all lights and the [photometric parameters](#photometric-lights) the spotlight supports the special parameters listed in the table. | Type | Name | Default | Description | |:------|:--------------|------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | vec3f | position | $(0, 0, 0)$ | the center of the spotlight | | vec3f | direction | $(0, 0, 1)$ | main emission direction of the spot | | float | openingAngle | 180 | full opening angle (in degree) of the spot; outside of this cone is no illumination | | float | penumbraAngle | 5 | size (angle in degree) of the “penumbraâ€, the region between the rim (of the illumination cone) and full intensity of the spot; should be smaller than half of `openingAngle` | | float | radius | 0 | the size of the spotlight, the radius of a disk with normal `direction` | | float | innerRadius | 0 | in combination with `radius` turns the disk into a ring | Special parameters accepted by the spotlight. ![Angles used by the spotlight.](https://ospray.github.io/images/spot_light.png) Setting the radius to a value greater than zero will result in soft shadows when the renderer uses stochastic sampling (like the [path tracer](#path-tracer)). Additionally setting the inner radius will result in a ring instead of a disk emitting the light. ### Quad Light The quad[^4] light is a planar, procedural area light source emitting uniformly on one side into the half-space. It is created by passing the type string “`quad`†to `ospNewLight`. The quad light supports only `OSP_INTENSITY_QUANTITY_SCALE` when `intensityDistribution` is set, or otherwise `OSP_INTENSITY_QUANTITY_POWER`, `OSP_INTENSITY_QUANTITY_INTENSITY` and `OSP_INTENSITY_QUANTITY_RADIANCE` (then default) as `intensityQuantity` parameter. In addition to the [general parameters](#lights) understood by all lights and the [photometric parameters](#photometric-lights) the quad light supports the following special parameters: | Type | Name | Default | Description | |:------|:---------|------------:|:-----------------------------------------| | vec3f | position | $(0, 0, 0)$ | position of one vertex of the quad light | | vec3f | edge1 | $(1, 0, 0)$ | vector to one adjacent vertex | | vec3f | edge2 | $(0, 1, 0)$ | vector to the other adjacent vertex | Special parameters accepted by the quad light. ![Defining a quad light which emits toward the reader.](https://ospray.github.io/images/quad_light.png) The emission side is determined by the cross product of `edge1`×`edge2`. which is also the main emission direction for `intensityDistribution`. Note that only renderers that use stochastic sampling (like the path tracer) will compute soft shadows from the quad light. Other renderers will just sample the center of the quad light, which results in hard shadows. ### Cylinder Light The cylinder light is a cylinderical, procedural area light source emitting uniformly outwardly into the space beyond the boundary. It is created by passing the type string “`cylinder`†to `ospNewLight`. The cylinder light supports `OSP_INTENSITY_QUANTITY_POWER`, `OSP_INTENSITY_QUANTITY_INTENSITY` and `OSP_INTENSITY_QUANTITY_RADIANCE` (default) as `intensityQuantity` parameter. In addition to the [general parameters](#lights) understood by all lights the cylinder light supports the following special parameters: | Type | Name | Default | Description | |:------|:----------|------------:|:--------------------------------------| | vec3f | position0 | $(0, 0, 0)$ | position of the start of the cylinder | | vec3f | position1 | $(0, 0, 1)$ | position of the end of the cylinder | | float | radius | 1 | radius of the cylinder | Special parameters accepted by the cylinder light. Note that only renderers that use stochastic sampling (like the path tracer) will compute soft shadows from the cylinder light. Other renderers will just sample the closest point on the cylinder light, which results in hard shadows. ### HDRI Light The HDRI light is a textured light source surrounding the scene and illuminating it from infinity. It is created by passing the type string “`hdri`†to `ospNewLight`. The values of the HDRI correspond to radiance and therefore the HDRI light only accepts `OSP_INTENSITY_QUANTITY_SCALE` as `intensityQuantity` parameter value. In addition to the [general parameters](#lights) the HDRI light supports the following special parameters: | Type | Name | Default | Description | |:-----------|:----------|------------:|:-----------------------------------------------------------------------------------------------------------------| | vec3f | up | $(0, 1, 0)$ | up direction of the light | | vec3f | direction | $(0, 0, 1)$ | direction to which the center of the texture will be mapped to (analog to [panoramic camera](#panoramic-camera)) | | OSPTexture | map | | environment map in latitude / longitude format | Special parameters accepted by the HDRI light. ![Orientation and Mapping of an HDRI Light.](https://ospray.github.io/images/hdri_light.png) Note that the [SciVis renderer](#scivis-renderer) only shows the HDRI light in the background (like an environment map) without computing illumination of the scene. ### Ambient Light The ambient light surrounds the scene and illuminates it from infinity with constant radiance (determined by combining the [parameters `color` and `intensity`](#lights)). It is created by passing the type string “`ambient`†to `ospNewLight`. The ambient light supports `OSP_INTENSITY_QUANTITY_RADIANCE` and `OSP_INTENSITY_QUANTITY_IRRADIANCE` (default) as `intensityQuantity` parameter value. Note that the [SciVis renderer](#scivis-renderer) uses ambient lights to control the color and intensity of the computed ambient occlusion (AO). ### Sun-Sky Light The sun-sky light is a combination of a `distant` light for the sun and a procedural `hdri` light for the sky. It is created by passing the type string “`sunSky`†to `ospNewLight`. The sun-sky light surrounds the scene and illuminates it from infinity and can be used for rendering outdoor scenes. The radiance values are calculated using the HoÅ¡ek-Wilkie sky model and solar radiance function. The underlying model of the sun-sky light returns radiance values and therefore the light only accepts `OSP_INTENSITY_QUANTITY_SCALE` as `intensityQuantity` parameter value. To rescale the returned radiance of the sky model the default value for the `intensity` parameter is set to `0.025`. In addition to the [general parameters](#lights) the following special parameters are supported: | Type | Name | Default | Description | |:------|:-----------------|-------------:|:-----------------------------------------------------------------------------------------------------| | vec3f | up | $(0, 1, 0)$ | zenith of sky | | vec3f | direction | $(0, -1, 0)$ | main emission direction of the sun | | float | turbidity | 3 | atmospheric turbidity due to particles, in \[1–10\] | | float | albedo | 0.3 | ground reflectance, in \[0–1\] | | float | horizonExtension | 0.01 | extend the sky dome by stretching the horizon, fraction of the lower hemisphere to cover, in \[0–1\] | Special parameters accepted by the `sunSky` light. The lowest elevation for the sun is restricted to the horizon. Note that the [SciVis renderer](#scivis-renderer) only computes illumination from the sun (yet the sky is still shown in the background, like an environment map). ### Emissive Objects The [path tracer](#path-tracer) will consider illumination by [geometries](#geometries) which have a light emitting material assigned (for example the [Luminous](#luminous) or [Principled](#principled) material). Materials --------- Materials describe how light interacts with surfaces, they give objects their distinctive look. To create a new material of given type `type` call ``` cpp OSPMaterial ospNewMaterial(const char *material_type); ``` The returned handle can then be used to assign the material to a given geometry with ``` cpp void ospSetObject(OSPGeometricModel, "material", OSPMaterial); ``` ### OBJ Material The OBJ material is the workhorse material supported by both the [SciVis renderer](#scivis-renderer) and the [path tracer](#path-tracer) (the [Ambient Occlusion renderer](#ambient-occlusion-renderer) only uses the `kd` and `d` parameter). It offers widely used common properties like diffuse and specular reflection and is based on the [MTL material format](http://paulbourke.net/dataformats/mtl/) of Lightwave’s OBJ scene files. To create an OBJ material pass the type string “`obj`†to `ospNewMaterial`. Its main parameters are | Type | Name | Default | Description | |:-----------|:---------|----------:|:------------------------------------------------------------| | vec3f | kd | white 0.8 | diffuse color (linear RGB) | | vec3f | ks | black | specular color (linear RGB) | | float | ns | 10 | shininess (Phong exponent), usually in \[2–104\] | | float | d | opaque | opacity | | vec3f | tf | black | transparency filter color (linear RGB) | | OSPTexture | map_bump | NULL | normal map | Main parameters of the OBJ material. In particular when using the path tracer it is important to adhere to the principle of energy conservation, i.e., that the amount of light reflected by a surface is not larger than the light arriving. Therefore the path tracer issues a warning and renormalizes the color parameters if the sum of `kd`, `ks`, and `tf` is larger than one in any color channel. Similarly important to mention is that almost all materials of the real world reflect at most only about 80% of the incoming light. So even for a white sheet of paper or white wall paint do better not set `kd` larger than 0.8; otherwise rendering times are unnecessary long and the contrast in the final images is low (for example, the corners of a white room would hardly be discernible, as can be seen in the figure below).
Comparison of diffuse rooms with 100% reflecting white paint (left) and realistic 80% reflecting white paint (right), which leads to higher overall contrast. Note that exposure has been adjusted to achieve similar brightness levels.
If present, the color component of [geometries](#geometries) is also used for the diffuse color `kd` and the alpha component is also used for the opacity `d`. Normal mapping can simulate small geometric features via the texture `map_bump`. The normals $n$ in the normal map are with respect to the local tangential shading coordinate system and are encoded as $½(n+1)$, thus a texel $(0.5, 0.5, 1)$[^5] represents the unperturbed shading normal $(0, 0, 1)$. Because of this encoding an sRGB gamma [texture](#texture) format is ignored and normals are always fetched as linear from a normal map. Note that the orientation of normal maps is important for a visually consistent look: by convention OSPRay uses a coordinate system with the origin in the lower left corner; thus a convexity will look green toward the top of the texture image (see also the example image of a normal map). If this is not the case flip the normal map vertically or invert its green channel.
Normal map representing an exalted square pyramidal frustum.
Note that `tf` colored transparency is implemented in the SciVis and the path tracer but normal mapping with `map_bump` is currently supported in the path tracer only. All parameters (except `tf`) can be textured by passing a [texture](#texture) handle, prefixed with “`map_`â€. The fetched texels are multiplied by the respective parameter value. If only the texture is given (but not the corresponding parameter), only the texture is used (the default value of the parameter is *not* multiplied). The color textures `map_kd` and `map_ks` are typically in one of the sRGB gamma encoded formats, whereas textures `map_ns` and `map_d` are usually in a linear format (and only the first component is used). Additionally, all textures support [texture transformations](#texture-transformations).
Rendering of a OBJ material with wood textures.
### Principled The Principled material is the most complex material offered by the [path tracer](#path-tracer), which is capable of producing a wide variety of materials (e.g., plastic, metal, wood, glass) by combining multiple different layers and lobes. It uses the GGX microfacet distribution with approximate multiple scattering for dielectrics and metals, uses the Oren-Nayar model for diffuse reflection, and is energy conserving. To create a Principled material, pass the type string “`principled`†to `ospNewMaterial`. Its parameters are listed in the table below. | Type | Name | Default | Description | |:------|:------------------|----------:|:------------------------------------------------------------------------------------------------------------------------| | vec3f | baseColor | white 0.8 | base reflectivity (diffuse and/or metallic, linear RGB) | | vec3f | edgeColor | white | edge tint (metallic only, linear RGB) | | float | metallic | 0 | mix between dielectric (diffuse and/or specular) and metallic (specular only with complex IOR) in \[0–1\] | | float | diffuse | 1 | diffuse reflection weight in \[0–1\] | | float | specular | 1 | specular reflection/transmission weight in \[0–1\] | | float | ior | 1 | dielectric index of refraction | | float | transmission | 0 | specular transmission weight in \[0–1\] | | vec3f | transmissionColor | white | attenuated color due to transmission (Beer’s law, linear RGB) | | float | transmissionDepth | 1 | distance at which color attenuation is equal to transmissionColor | | float | roughness | 0 | diffuse and specular roughness in \[0–1\], 0 is perfectly smooth | | float | anisotropy | 0 | amount of specular anisotropy in \[0–1\] | | float | rotation | 0 | rotation of the direction of anisotropy in \[0–1\], 1 is going full circle | | float | normal | 1 | default normal map/scale for all layers | | float | baseNormal | 1 | base normal map/scale (overrides default normal) | | bool | thin | false | flag specifying whether the material is thin or solid | | float | thickness | 1 | thickness of the material (thin only), affects the amount of color attenuation due to specular transmission | | float | backlight | 0 | amount of diffuse transmission (thin only) in \[0–2\], 1 is 50% reflection and 50% transmission, 2 is transmission only | | float | coat | 0 | clear coat layer weight in \[0–1\] | | float | coatIor | 1.5 | clear coat index of refraction | | vec3f | coatColor | white | clear coat color tint (linear RGB) | | float | coatThickness | 1 | clear coat thickness, affects the amount of color attenuation | | float | coatRoughness | 0 | clear coat roughness in \[0–1\], 0 is perfectly smooth | | float | coatNormal | 1 | clear coat normal map/scale (overrides default normal) | | float | sheen | 0 | sheen layer weight in \[0–1\] | | vec3f | sheenColor | white | sheen color tint (linear RGB) | | float | sheenTint | 0 | how much sheen is tinted from sheenColor toward baseColor | | float | sheenRoughness | 0.2 | sheen roughness in \[0–1\], 0 is perfectly smooth | | float | opacity | 1 | cut-out opacity/transparency, 1 is fully opaque | | vec3f | emissiveColor | black | color (and intensity) of the emitted light | Parameters of the Principled material. All parameters can be textured by passing a [texture](#texture) handle, prefixed with “`map_`†(e.g., “`map_baseColor`â€). [texture transformations](#texture-transformations) are supported as well.
Rendering of a Principled coated brushed metal material with textured anisotropic rotation and a dust layer (sheen) on top.
### CarPaint The CarPaint material is a specialized version of the Principled material for rendering different types of car paints. To create a CarPaint material, pass the type string “`carPaint`†to `ospNewMaterial`. Its parameters are listed in the table below. | Type | Name | Default | Description | |:------|:----------------|----------:|:-----------------------------------------------------------------------------------------------------------------------| | vec3f | baseColor | white 0.8 | diffuse base reflectivity (linear RGB) | | float | roughness | 0 | diffuse roughness in \[0–1\], 0 is perfectly smooth | | float | normal | 1 | normal map/scale | | vec3f | flakeColor | Aluminium | color of metallic flakes (linear RGB) | | float | flakeDensity | 0 | density of metallic flakes in \[0–1\], 0 disables flakes, 1 fully covers the surface with flakes | | float | flakeScale | 100 | scale of the flake structure, higher values increase the amount of flakes | | float | flakeSpread | 0.3 | flake spread in \[0–1\] | | float | flakeJitter | 0.75 | flake randomness in \[0–1\] | | float | flakeRoughness | 0.3 | flake roughness in \[0–1\], 0 is perfectly smooth | | float | coat | 1 | clear coat layer weight in \[0–1\] | | float | coatIor | 1.5 | clear coat index of refraction | | vec3f | coatColor | white | clear coat color tint (linear RGB) | | float | coatThickness | 1 | clear coat thickness, affects the amount of color attenuation | | float | coatRoughness | 0 | clear coat roughness in \[0–1\], 0 is perfectly smooth | | float | coatNormal | 1 | clear coat normal map/scale | | vec3f | flipflopColor | white | reflectivity of coated flakes at grazing angle, used together with coatColor produces a pearlescent paint (linear RGB) | | float | flipflopFalloff | 1 | flip flop color falloff, 1 disables the flip flop effect | Parameters of the CarPaint material. All parameters can be textured by passing a [texture](#texture) handle, prefixed with “`map_`†(e.g., “`map_baseColor`â€). [texture transformations](#texture-transformations) are supported as well.
Rendering of a pearlescent CarPaint material.
### Metal The [path tracer](#path-tracer) offers a physical metal, supporting changing roughness and realistic color shifts at edges. To create a Metal material pass the type string “`metal`†to `ospNewMaterial`. Its parameters are | Type | Name | Default | Description | |:----------|:----------|----------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------| | vec3f\[\] | ior | Aluminium | [data](#data) array of spectral samples of complex refractive index, each entry in the form (wavelength, eta, k), ordered by wavelength (which is in nm) | | vec3f | eta | | RGB complex refractive index, real part | | vec3f | k | | RGB complex refractive index, imaginary part | | float | roughness | 0.1 | roughness in \[0–1\], 0 is perfect mirror | Parameters of the Metal material. The main appearance (mostly the color) of the Metal material is controlled by the physical parameters `eta` and `k`, the wavelength-dependent, complex index of refraction. These coefficients are quite counter-intuitive but can be found in [published measurements](https://refractiveindex.info/). For accuracy the index of refraction can be given as an array of spectral samples in `ior`, each sample a triplet of wavelength (in nm), eta, and k, ordered monotonically increasing by wavelength; OSPRay will then calculate the Fresnel in the spectral domain. Alternatively, `eta` and `k` can also be specified as approximated RGB coefficients; some examples are given in below table. | Metal | eta | k | |:--------------|:---------------------:|:---------------:| | Ag, Silver | (0.051, 0.043, 0.041) | (5.3, 3.6, 2.3) | | Al, Aluminium | (1.5, 0.98, 0.6) | (7.6, 6.6, 5.4) | | Au, Gold | (0.07, 0.37, 1.5) | (3.7, 2.3, 1.7) | | Cr, Chromium | (3.2, 3.1, 2.3) | (3.3, 3.3, 3.1) | | Cu, Copper | (0.1, 0.8, 1.1) | (3.5, 2.5, 2.4) | Index of refraction of selected metals as approximated RGB coefficients, based on data from https://refractiveindex.info/. The `roughness` parameter controls the variation of microfacets and thus how polished the metal will look. The roughness can be modified by a [texture](#texture) `map_roughness` ([texture transformations](#texture-transformations) are supported as well) to create notable edging effects.
Rendering of golden Metal material with textured roughness.
### Alloy The [path tracer](#path-tracer) offers an alloy material, which behaves similar to [Metal](#metal), but allows for more intuitive and flexible control of the color. To create an Alloy material pass the type string “`alloy`†to `ospNewMaterial`. Its parameters are | Type | Name | Default | Description | |:------|:----------|----------:|:--------------------------------------------------------| | vec3f | color | white 0.9 | reflectivity at normal incidence (0 degree, linear RGB) | | vec3f | edgeColor | white | reflectivity at grazing angle (90 degree, linear RGB) | | float | roughness | 0.1 | roughness, in \[0–1\], 0 is perfect mirror | Parameters of the Alloy material. The main appearance of the Alloy material is controlled by the parameter `color`, while `edgeColor` influences the tint of reflections when seen at grazing angles (for real metals this is always 100% white). If present, the color component of [geometries](#geometries) is also used for reflectivity at normal incidence `color`. As in [Metal](#metal) the `roughness` parameter controls the variation of microfacets and thus how polished the alloy will look. All parameters can be textured by passing a [texture](#texture) handle, prefixed with “`map_`â€; [texture transformations](#texture-transformations) are supported as well.
Rendering of a fictional Alloy material with textured color.
### Glass The [path tracer](#path-tracer) offers a realistic a glass material, supporting refraction and volumetric attenuation (i.e., the transparency color varies with the geometric thickness). To create a Glass material pass the type string “`glass`†to `ospNewMaterial`. Its parameters are | Type | Name | Default | Description | |:------|:--------------------|--------:|:------------------------------------------------| | float | eta | 1.5 | index of refraction | | vec3f | attenuationColor | white | resulting color due to attenuation (linear RGB) | | float | attenuationDistance | 1 | distance affecting attenuation | Parameters of the Glass material. For convenience, the rather counter-intuitive physical attenuation coefficients will be calculated from the user inputs in such a way, that the `attenuationColor` will be the result when white light traveled through a glass of thickness `attenuationDistance`.
Rendering of a Glass material with orange attenuation.
### ThinGlass The [path tracer](#path-tracer) offers a thin glass material useful for objects with just a single surface, most prominently windows. It models a thin, transparent slab, i.e., it behaves as if a second, virtual surface is parallel to the real geometric surface. The implementation accounts for multiple internal reflections between the interfaces (including attenuation), but neglects parallax effects due to its (virtual) thickness. To create a such a thin glass material pass the type string “`thinGlass`†to `ospNewMaterial`. Its parameters are | Type | Name | Default | Description | |:------|:--------------------|--------:|:------------------------------------------------| | float | eta | 1.5 | index of refraction | | vec3f | attenuationColor | white | resulting color due to attenuation (linear RGB) | | float | attenuationDistance | 1 | distance affecting attenuation | | float | thickness | 1 | virtual thickness | Parameters of the ThinGlass material. For convenience the attenuation is controlled the same way as with the [Glass](#glass) material. Additionally, the color due to attenuation can be modulated with a [texture](#texture) `map_attenuationColor` ([texture transformations](#texture-transformations) are supported as well). If present, the color component of [geometries](#geometries) is also used for the attenuation color. The `thickness` parameter sets the (virtual) thickness and allows for easy exchange of parameters with the (real) [Glass](#glass) material; internally just the ratio between `attenuationDistance` and `thickness` is used to calculate the resulting attenuation and thus the material appearance.
Rendering of a ThinGlass material with red attenuation.
Example image of a colored window made with textured attenuation of the ThinGlass material.
### MetallicPaint The [path tracer](#path-tracer) offers a metallic paint material, consisting of a base coat with optional flakes and a clear coat. To create a MetallicPaint material pass the type string “`metallicPaint`†to `ospNewMaterial`. Its parameters are listed in the table below. | Type | Name | Default | Description | |:------|:------------|----------:|:--------------------------------------| | vec3f | baseColor | white 0.8 | color of base coat (linear RGB) | | float | flakeAmount | 0.3 | amount of flakes, in \[0–1\] | | vec3f | flakeColor | Aluminium | color of metallic flakes (linear RGB) | | float | flakeSpread | 0.5 | spread of flakes, in \[0–1\] | | float | eta | 1.5 | index of refraction of clear coat | Parameters of the MetallicPaint material. The color of the base coat `baseColor` can be textured by a [texture](#texture) `map_baseColor`, which also supports [texture transformations](#texture-transformations). If present, the color component of [geometries](#geometries) is also used for the color of the base coat. Parameter `flakeAmount` controls the proportion of flakes in the base coat, so when setting it to 1 the `baseColor` will not be visible. The shininess of the metallic component is governed by `flakeSpread`, which controls the variation of the orientation of the flakes, similar to the `roughness` parameter of [Metal](#metal). Note that the effect of the metallic flakes is currently only computed on average, thus individual flakes are not visible.
Rendering of a MetallicPaint material.
### Luminous The [path tracer](#path-tracer) supports the Luminous material which emits light uniformly in all directions and which can thus be used to turn any geometric object into a light source. It is created by passing the type string “`luminous`†to `ospNewMaterial`. The amount of constant radiance that is emitted is determined by combining the general parameters of lights: [`color` and `intensity`](#lights) (which essentially means that parameter `intensityQuantity` is not needed because it is always `OSP_INTENSITY_QUANTITY_RADIANCE`). | Type | Name | Default | Description | |:------|:-------------|--------:|:----------------------------------------| | vec3f | color | white | color of the emitted light (linear RGB) | | float | intensity | 1 | intensity of the light (a factor) | | float | transparency | 1 | material transparency | Parameters accepted by the Luminous material. The emission can be textured by passing a `map_color` [texture](#texture) handle, [texture transformations](#texture-transformations) are supported as well.
Rendering of a yellow Luminous material.
Texture ------- OSPRay currently implements two texture types (`texture2d` and `volume`) and is open for extension to other types by applications. More types may be added in future releases. To create a new texture use ``` cpp OSPTexture ospNewTexture(const char *type); ``` ### Texture2D The `texture2d` texture type implements an image-based texture, where its parameters are as follows | Type | Name | Description | |:--------------|:---------|:------------------------------------------------------------------------------------| | uint | format | `OSPTextureFormat` for the texture | | uint | filter | default `OSP_TEXTURE_FILTER_LINEAR`, alternatively `OSP_TEXTURE_FILTER_NEAREST` | | OSPData | data | the actual texel 2D [data](#data) | | uint / vec2ui | wrapMode | `OSPTextureWrapMode` for the texture coordinates s and t; supported wrap modes are: | | | | `OSP_TEXTURE_WRAP_REPEAT` (default) | | | | `OSP_TEXTURE_WRAP_MIRRORED_REPEAT` | | | | `OSP_TEXTURE_WRAP_CLAMP_TO_EDGE` | Parameters of `texture2d` texture type. The supported texture formats for `texture2d` are: | Name | Description | |:--------------------|:---------------------------------------------------------------------------| | OSP_TEXTURE_RGBA8 | 8 bit \[0–255\] linear components red, green, blue, alpha | | OSP_TEXTURE_SRGBA | 8 bit sRGB gamma encoded color components, and linear alpha | | OSP_TEXTURE_RGBA32F | 32 bit float components red, green, blue, alpha | | OSP_TEXTURE_RGB8 | 8 bit \[0–255\] linear components red, green, blue | | OSP_TEXTURE_SRGB | 8 bit sRGB gamma encoded components red, green, blue | | OSP_TEXTURE_RGB32F | 32 bit float components red, green, blue | | OSP_TEXTURE_R8 | 8 bit \[0–255\] linear single component red | | OSP_TEXTURE_RA8 | 8 bit \[0–255\] linear two components red, alpha | | OSP_TEXTURE_L8 | 8 bit \[0–255\] gamma encoded luminance (replicated into red, green, blue) | | OSP_TEXTURE_LA8 | 8 bit \[0–255\] gamma encoded luminance, and linear alpha | | OSP_TEXTURE_R32F | 32 bit float single component red | | OSP_TEXTURE_RGBA16 | 16 bit \[0–65535\] linear components red, green, blue, alpha | | OSP_TEXTURE_RGB16 | 16 bit \[0–65535\] linear components red, green, blue | | OSP_TEXTURE_RA16 | 16 bit \[0–65535\] linear two components red, alpha | | OSP_TEXTURE_R16 | 16 bit \[0–65535\] linear single component red | Supported texture formats by `texture2d`, i.e., valid constants of type `OSPTextureFormat`. The size of the texture is inferred from the size of the 2D array `data`, which also needs have a compatible type to `format`. The texel data in `data` starts with the texels in the lower left corner of the texture image, like in OpenGL. Per default a texture fetch is filtered by performing bi-linear interpolation of the nearest 2×2 texels; if instead fetching only the nearest texel is desired (i.e., no filtering) then pass the `OSP_TEXTURE_FILTER_NEAREST` flag. Texturing with `texture2d` image textures requires [geometries](#geometries) with texture coordinates, e.g., a [mesh](#mesh) with `vertex.texcoord` provided. ### Volume Texture The `volume` texture type implements texture lookups based on 3D object coordinates of the surface hit point on the associated geometry. If the given hit point is within the attached volume, the volume is sampled and classified with the transfer function attached to the volume. This implements the ability to visualize volume values (as colored by a transfer function) on arbitrary surfaces inside the volume (as opposed to an isosurface showing a particular value in the volume). Its parameters are as follows | Type | Name | Description | |:--------------------|:-----------------|:------------------------------------------------------------| | OSPVolume | volume | [Volume](#volumes) used to generate color lookups | | OSPTransferFunction | transferFunction | [transfer function](#transfer-function) applied to `volume` | Parameters of `volume` texture type. TextureVolume can be used for implementing slicing of volumes with any geometry type. It enables coloring of the slicing geometry with a different transfer function than that of the sliced volume. ### Texture Transformations All materials with textures also offer to manipulate the placement of these textures with the help of texture transformations. If so, this convention shall be used: the following parameters are prefixed with “`texture_name.*`â€). | Type | Name | Description | |:---------|:------------|:-------------------------------------------------| | linear2f | transform | linear transformation (rotation, scale) | | float | rotation | angle in degree, counterclockwise, around center | | vec2f | scale | enlarge texture, relative to center $(0.5, 0.5)$ | | vec2f | translation | move texture in positive direction (right/up) | Parameters to define 2D texture coordinate transformations. Above parameters are combined into a single `affine2d` transformation matrix and the transformations are applied in the given order. Rotation, scale and translation are interpreted “texture centricâ€, i.e., their effect seen by an user are relative to the texture (although the transformations are applied to the texture coordinates). | Type | Name | Description | |:---------|:----------|:---------------------------------------------------------| | affine3f | transform | linear transformation (rotation, scale) plus translation | Parameter to define 3D volume texture transformations. Similarly, volume texture placement can also be modified by an `affine3f` transformation matrix. Cameras ------- To create a new camera of given type `type` use ``` cpp OSPCamera ospNewCamera(const char *type); ``` All cameras accept these parameters: | Type | Name | Default | Description | |:-------------|:-----------------------|---------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------| | vec3f | position | $(0, 0, 0)$ | position of the camera | | vec3f | direction | $(0, 0, 1)$ | main viewing direction of the camera | | vec3f | up | $(0, 1, 0)$ | up direction of the camera | | affine3f | transform | identity | additional world-space transform, overridden by `motion.*` arrays | | float | nearClip | 10-6 | near clipping distance | | vec2f | imageStart | $(0, 0)$ | start of image region (lower left corner) | | vec2f | imageEnd | $(1, 1)$ | end of image region (upper right corner) | | affine3f\[\] | motion.transform | | additional uniformly distributed world-space transforms | | vec3f\[\] | motion.scale | | additional uniformly distributed world-space scale, overridden by `motion.transform` | | vec3f\[\] | motion.pivot | | additional uniformly distributed world-space translation which is applied before `motion.rotation` (i.e., the rotation center), overridden by `motion.transform` | | quatf\[\] | motion.rotation | | additional uniformly distributed world-space quaternion rotation, overridden by `motion.transform` | | vec3f\[\] | motion.translation | | additional uniformly distributed world-space translation, overridden by `motion.transform` | | box1f | time | \[0, 1\] | time associated with first and last key in `motion.*` arrays | | box1f | shutter | \[0.5, 0.5\] | start and end of shutter time (for motion blur), in \[0, 1\] | | uint | shutterType | `OSP_SHUTTER_GLOBAL` | `OSPShutterType` for motion blur, also allowed are: | | | | | `OSP_SHUTTER_ROLLING_RIGHT` | | | | | `OSP_SHUTTER_ROLLING_LEFT` | | | | | `OSP_SHUTTER_ROLLING_DOWN` | | | | | `OSP_SHUTTER_ROLLING_UP` | | float | rollingShutterDuration | 0 | for a rolling shutter (see `shutterType`) the “open†time per line, in \[0, `shutter`.upper-`shutter`.lower\] | Parameters accepted by all cameras. The camera is placed and oriented in the world with `position`, `direction` and `up`. Additionally, an extra transformation `transform` can be specified, which will only be applied to 3D vectors (i.e., `position`, `direction` and `up`), but does *not* affect any sizes (e.g., `nearClip`, `apertureRadius`, or `height`). The same holds for the array of transformations `motion.transform` to achieve camera motion blur (in combination with `time` and `shutter`). OSPRay uses a right-handed coordinate system. The region of the camera sensor that is rendered to the image can be specified in normalized screen-space coordinates with `imageStart` (lower left corner) and `imageEnd` (upper right corner). This can be used, for example, to crop the image, to achieve asymmetrical view frusta, or to horizontally flip the image to view scenes which are specified in a left-handed coordinate system. Note that values outside the default range of \[0–1\] are valid, which is useful to easily realize overscan or film gate, or to emulate a shifted sensor. ### Perspective Camera The perspective camera implements a simple thin lens camera for perspective rendering, supporting optionally depth of field and stereo rendering (with the [path tracer](#path-tracer)). It is created by passing the type string “`perspective`†to `ospNewCamera`. In addition to the [general parameters](#cameras) understood by all cameras the perspective camera supports the special parameters listed in the table below. | Type | Name | Default | Description | |:------|:-----------------------|------------------:|:-----------------------------------------------------------------------| | float | fovy | 60 | the field of view (angle in degree) of the frame’s height | | float | aspect | 1 | ratio of width by height of the frame (and image region) | | float | apertureRadius | 0 | size of the aperture, controls the depth of field | | float | focusDistance | 1 | distance at where the image is sharpest when depth of field is enabled | | bool | architectural | false | vertical edges are projected to be parallel | | uint | stereoMode | `OSP_STEREO_NONE` | `OSPStereoMode` for stereo rendering, also allowed are: | | | | | `OSP_STEREO_LEFT` | | | | | `OSP_STEREO_RIGHT` | | | | | `OSP_STEREO_SIDE_BY_SIDE` | | | | | `OSP_STEREO_TOP_BOTTOM` (left eye at top half) | | float | interpupillaryDistance | 0.0635 | distance between left and right eye when stereo is enabled | Additional parameters accepted by the perspective camera. Note that when computing the `aspect` ratio a potentially set image region (using `imageStart` & `imageEnd`) needs to be regarded as well. In architectural photography it is often desired for aesthetic reasons to display the vertical edges of buildings or walls vertically in the image as well, regardless of how the camera is tilted. Enabling the `architectural` mode achieves this by internally leveling the camera parallel to the ground (based on the `up` direction) and then shifting the lens such that the objects in direction `dir` are centered in the image. If finer control of the lens shift is needed use `imageStart` & `imageEnd`. Because the camera is now effectively leveled its image plane and thus the plane of focus is oriented parallel to the front of buildings, the whole façade appears sharp, as can be seen in the example images below. The resolution of the [framebuffer](#framebuffer) is not altered by `imageStart`/`imageEnd`.
Example image created with the perspective camera, featuring depth of field.
Enabling the architectural flag corrects the perspective projection distortion, resulting in parallel vertical edges.
Example 3D stereo image using stereoMode = OSP_STEREO_SIDE_BY_SIDE.
### Orthographic Camera The orthographic camera implements a simple camera with orthographic projection, without support for depth. It is created by passing the type string “`orthographic`†to `ospNewCamera`. In addition to the [general parameters](#cameras) understood by all cameras the orthographic camera supports the following special parameters: | Type | Name | Description | |:------|:-------|:------------------------------------------------------------| | float | height | size of the camera’s image plane in y, in world coordinates | | float | aspect | ratio of width by height of the frame | Additional parameters accepted by the orthographic camera. For convenience the size of the camera sensor, and thus the extent of the scene that is captured in the image, can be controlled with the `height` parameter. The same effect can be achieved with `imageStart` and `imageEnd`, and both methods can be combined. In any case, the `aspect` ratio needs to be set accordingly to get an undistorted image.
Example image created with the orthographic camera.
### Panoramic Camera The panoramic camera implements a simple camera with support for stereo rendering. It captures the complete surrounding with a latitude / longitude mapping and thus the rendered images should best have a ratio of 2:1. A panoramic camera is created by passing the type string “`panoramic`†to `ospNewCamera`. It is placed and oriented in the scene by using the [general parameters](#cameras) understood by all cameras. | Type | Name | Description | |:------|:-----------------------|:---------------------------------------------------------------------------| | uint | stereoMode | `OSPStereoMode` for stereo rendering, possible values are: | | | | `OSP_STEREO_NONE` (default) | | | | `OSP_STEREO_LEFT` | | | | `OSP_STEREO_RIGHT` | | | | `OSP_STEREO_SIDE_BY_SIDE` | | | | `OSP_STEREO_TOP_BOTTOM` (left eye at top half) | | float | interpupillaryDistance | distance between left and right eye when stereo is enabled, default 0.0635 | Additional parameters accepted by the panoramic camera.
Latitude / longitude map created with the panoramic camera.
Scene Hierarchy --------------- ### Groups Groups in OSPRay represent collections of GeometricModels, VolumetricModels and Lights which share a common local-space coordinate system. To create a group call ``` cpp OSPGroup ospNewGroup(); ``` Groups take arrays of geometric models, volumetric models, clipping geometric models and lights, but they are all optional. In other words, there is no need to create empty arrays if there are no geometries, volumes or lights in the group. By adding `OSPGeometricModel`s to the `clippingGeometry` array a clipping geometry feature is enabled. Geometries assigned to this parameter will be used as clipping geometries. Any supported geometry can be used for clipping[^6], the only requirement is that it has to distinctly partition space into clipping and non-clipping one. The use of clipping geometry that is not closed or infinite could result in rendering artifacts. User can decide which part of space is clipped by changing shading normals orientation with the `invertNormals` flag of the [GeometricModel](#geometricmodels). All geometries and volumes assigned to `geometry` or `volume` will be clipped. All clipping geometries from all groups and [Instances](#instances) will be combined together – a union of these areas will be applied to all other objects in the [world](#world). | Type | Name | Default | Description | |:-----------------------|:-----------------|--------:|:-------------------------------------------------------------------------------------------------------------------------------------| | OSPGeometricModel\[\] | geometry | NULL | [data](#data) array of [GeometricModels](#geometricmodels) | | OSPVolumetricModel\[\] | volume | NULL | [data](#data) array of [VolumetricModels](#volumetricmodels) | | OSPGeometricModel\[\] | clippingGeometry | NULL | [data](#data) array of [GeometricModels](#geometricmodels) used for clipping | | OSPLight\[\] | light | NULL | [data](#data) array of [lights](#lights) | | bool | dynamicScene | false | tell Embree to use faster BVH build (slower ray traversal), otherwise optimized for faster ray traversal (slightly slower BVH build) | | bool | compactMode | false | tell Embree to use a more compact BVH in memory by trading ray traversal performance | | bool | robustMode | false | tell Embree to enable more robust ray intersection code paths (slightly slower) | Parameters understood by groups. ### Instances Instances in OSPRay represent a single group’s placement into the world via a transform. To create and instance call ``` cpp OSPInstance ospNewInstance(OSPGroup); ``` The passed group can be `NULL` as long as the group to be instanced is passed as a parameter. If both a group is specified on object creation and as a parameter, the parameter value is used. If the parameter value is later removed, the group object passed on object creation is again used. | Type | Name | Default | Description | |:-------------|:-------------------|---------:|:------------------------------------------------------------------------------------------------------------------------------------------------------| | OSPGroup | group | | optional [group](#groups) object to be instanced | | affine3f | transform | identity | world-space transform for all attached geometries and volumes, overridden by `motion.*` arrays | | affine3f\[\] | motion.transform | | uniformly distributed world-space transforms | | vec3f\[\] | motion.scale | | uniformly distributed world-space scale, overridden by `motion.transform` | | vec3f\[\] | motion.pivot | | uniformly distributed world-space translation which is applied before `motion.rotation` (i.e., the rotation center), overridden by `motion.transform` | | quatf\[\] | motion.rotation | | uniformly distributed world-space quaternion rotation, overridden by `motion.transform` | | vec3f\[\] | motion.translation | | uniformly distributed world-space translation, overridden by `motion.transform` | | box1f | time | \[0, 1\] | time associated with first and last key in `motion.*` arrays (for motion blur) | | uint32 | id | -1u | optional user ID, for [framebuffer](#framebuffer) channel `OSP_FB_ID_INSTANCE` | Parameters understood by instances. ### World Worlds are a container of scene data represented by [instances](#instances). To create an (empty) world call ``` cpp OSPWorld ospNewWorld(); ``` Objects are placed in the world through an array of instances. Similar to [groups](#groups), the array of instances is optional: there is no need to create empty arrays if there are no instances (though there will be nothing to render). Applications can query the world (axis-aligned) bounding box after the world has been committed. To get this information, call ``` cpp OSPBounds ospGetBounds(OSPObject); ``` The result is returned in the provided `OSPBounds`[^7] struct: ``` cpp typedef struct { float lower[3]; float upper[3]; } OSPBounds; ``` This call can also take `OSPGroup` and `OSPInstance` as well: all other object types will return an empty bounding box. Finally, Worlds can be configured with parameters for making various feature/performance trade-offs (similar to groups). | Type | Name | Default | Description | |:----------------|:-------------|--------:|:-------------------------------------------------------------------------------------------------------------------------------------| | OSPInstance\[\] | instance | NULL | [data](#data) array with handles of the [instances](#instances) | | OSPLight\[\] | light | NULL | [data](#data) array with handles of the [lights](#lights) | | bool | dynamicScene | false | tell Embree to use faster BVH build (slower ray traversal), otherwise optimized for faster ray traversal (slightly slower BVH build) | | bool | compactMode | false | tell Embree to use a more compact BVH in memory by trading ray traversal performance | | bool | robustMode | false | tell Embree to enable more robust ray intersection code paths (slightly slower) | Parameters understood by worlds. Renderers --------- A renderer is the central object for rendering in OSPRay. Different renderers implement different features and support different materials. To create a new renderer of given type `type` use ``` cpp OSPRenderer ospNewRenderer(const char *type); ``` General parameters of all renderers are | Type | Name | Default | Description | |:----------------------|:------------------|------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------| | int | pixelSamples | 1 | samples per pixel | | int | maxPathLength | 20 | maximum ray recursion depth | | float | minContribution | 0.001 | sample contributions below this value will be neglected to speedup rendering | | float | varianceThreshold | 0 | threshold for adaptive accumulation | | float / vec3f / vec4f | backgroundColor | black, transparent | background color and alpha (linear A/RGB/RGBA), if no `map_backplate` is set | | OSPTexture | map_backplate | | optional [texture](#texture) image used as background (use texture type `texture2d`) | | OSPTexture | map_maxDepth | | optional screen-sized float [texture](#texture) with maximum far distance per pixel (use texture type `texture2d`) | | OSPMaterial\[\] | material | | optional [data](#data) array of [materials](#materials) which can be indexed by a [GeometricModel](#geometricmodels)’s `material` parameter | | uint | pixelFilter | `OSP_PIXELFILTER_GAUSS` | `OSPPixelFilterType` to select the pixel filter used by the renderer for antialiasing. Possible pixel filters are listed below. | Parameters understood by all renderers. OSPRay’s renderers support a feature called adaptive accumulation, which accelerates progressive [rendering](#rendering) by stopping the rendering and refinement of image regions that have an estimated variance below the `varianceThreshold`. This feature requires a [framebuffer](#framebuffer) with an `OSP_FB_VARIANCE` channel. Per default the background of the rendered image will be transparent black, i.e., the alpha channel holds the opacity of the rendered objects. This eases transparency-aware blending of the image with an arbitrary background image by the application. The parameter `backgroundColor` or `map_backplate` can be used to already blend with a constant background color or backplate texture, respectively, (and alpha) during rendering. OSPRay renderers support depth composition with images of other renderers, for example to incorporate help geometries of a 3D UI that were rendered with OpenGL. The screen-sized [texture](#texture) `map_maxDepth` must have format `OSP_TEXTURE_R32F` and flag `OSP_TEXTURE_FILTER_NEAREST`. The fetched values are used to limit the distance of primary rays, thus objects of other renderers can hide objects rendered by OSPRay. OSPRay supports antialiasing in image space by using pixel filters, which are centered around the center of a pixel. The size $w×w$ of the filter depends on the selected filter type. The types of supported pixel filters are defined by the `OSPPixelFilterType` enum and can be set using the `pixelFilter` parameter. | Name | Description | |:--------------------------------|:--------------------------------------------------------------------------------------------------------------| | OSP_PIXELFILTER_POINT | a point filter only samples the center of the pixel, therefore the filter width is $w = 0$ | | OSP_PIXELFILTER_BOX | a uniform box filter with a width of $w = 1$ | | OSP_PIXELFILTER_GAUSS | a truncated, smooth Gaussian filter with a standard deviation of $\sigma = 0.5$ and a filter width of $w = 3$ | | OSP_PIXELFILTER_MITCHELL | the Mitchell-Netravali filter with a width of $w = 4$ | | OSP_PIXELFILTER_BLACKMAN_HARRIS | the Blackman-Harris filter with a width of $w = 3$ | Pixel filter types supported by OSPRay for antialiasing in image space. ### SciVis Renderer The SciVis renderer is a fast ray tracer for scientific visualization which supports volume rendering and ambient occlusion (AO). It is created by passing the type string “`scivis`†to `ospNewRenderer`. In addition to the [general parameters](#renderer) understood by all renderers, the SciVis renderer supports the following parameters: | Type | Name | Default | Description | |:------|:-------------------|----------------:|:------------------------------------------------------------------------------------------------------------------------| | bool | shadows | false | whether to compute (hard) shadows | | int | aoSamples | 0 | number of rays per sample to compute ambient occlusion | | float | aoDistance | 1020 | maximum distance to consider for ambient occlusion | | float | volumeSamplingRate | 1 | sampling rate for volumes | | bool | visibleLights | false | whether light sources are potentially visible (as in the [path tracer](#path-tracer), regarding each light’s `visible`) | Special parameters understood by the SciVis renderer. Note that the intensity (and color) of AO is deduced from an [ambient light](#ambient-light) in the `lights` array.[^8] If `aoSamples` is zero (the default) then ambient lights cause ambient illumination (without occlusion). ### Ambient Occlusion Renderer This renderer supports only a subset of the features of the [SciVis renderer](#scivis-renderer) to gain performance. As the name suggest its main shading method is ambient occlusion (AO), [lights](#lights) are *not* considered at all. Volume rendering is supported. The Ambient Occlusion renderer is created by passing the type string “`ao`†to `ospNewRenderer`. In addition to the [general parameters](#renderer) understood by all renderers the following parameters are supported as well: | Type | Name | Default | Description | |:------|:-------------------|----------------:|:-------------------------------------------------------| | int | aoSamples | 1 | number of rays per sample to compute ambient occlusion | | float | aoDistance | 1020 | maximum distance to consider for ambient occlusion | | float | aoIntensity | 1 | ambient occlusion strength | | float | volumeSamplingRate | 1 | sampling rate for volumes | Special parameters understood by the Ambient Occlusion renderer. ### Path Tracer The path tracer supports soft shadows, indirect illumination and realistic materials. This renderer is created by passing the type string “`pathtracer`†to `ospNewRenderer`. In addition to the [general parameters](#renderer) understood by all renderers the path tracer supports the following special parameters: | Type | Name | Default | Description | |:------|:---------------------|--------:|:------------------------------------------------------------------------------------------| | int | lightSamples | all | number of random light samples per path vertex, per default all light sources are sampled | | int | roulettePathLength | 5 | ray recursion depth at which to start Russian roulette termination | | int | maxScatteringEvents | 20 | maximum number of non-specular (i.e., diffuse and glossy) bounces | | float | maxContribution | ∞ | samples are clamped to this value before they are accumulated into the framebuffer | | bool | backgroundRefraction | false | allow for alpha blending even if background is seen through refractive objects like glass | Special parameters understood by the path tracer. The path tracer requires that [materials](#materials) are assigned to [geometries](#geometries), otherwise surfaces are treated as completely black. The path tracer supports [volumes](#volumes) with multiple scattering. The scattering albedo can be specified using the [transfer function](#transfer-function). Extinction is assumed to be spectrally constant. Framebuffer ----------- The framebuffer holds the rendered 2D image (and optionally auxiliary information associated with pixels). To create a new framebuffer object of given size `size` (in pixels), color format, and channels use ``` cpp OSPFrameBuffer ospNewFrameBuffer(int size_x, int size_y, OSPFrameBufferFormat format = OSP_FB_SRGBA, uint32_t frameBufferChannels = OSP_FB_COLOR); ``` The parameter `format` describes the format the color buffer has *on the host*, and the format that `ospMapFrameBuffer` will eventually return. Valid values are: | Name | Description | |:---------------|:------------------------------------------------------------| | OSP_FB_NONE | framebuffer will not be mapped by the application | | OSP_FB_RGBA8 | 8 bit \[0–255\] linear component red, green, blue, alpha | | OSP_FB_SRGBA | 8 bit sRGB gamma encoded color components, and linear alpha | | OSP_FB_RGBA32F | 32 bit float components red, green, blue, alpha | Supported color formats of the framebuffer that can be passed to `ospNewFrameBuffer`, i.e., valid constants of type `OSPFrameBufferFormat`. The parameter `frameBufferChannels` specifies which channels the framebuffer holds, and can be combined together by bitwise OR from the values of `OSPFrameBufferChannel` listed in the table below. | Name | Description | |:--------------------|:-------------------------------------------------------------------------------------------------------------------------------------------| | OSP_FB_COLOR | RGB color including alpha | | OSP_FB_DEPTH | euclidean distance to the camera (*not* to the image plane), as linear 32 bit float; for multiple samples per pixel their minimum is taken | | OSP_FB_ACCUM | accumulation buffer for progressive refinement | | OSP_FB_VARIANCE | for estimation of the current noise level if OSP_FB_ACCUM is also present, see [rendering](#rendering) | | OSP_FB_NORMAL | accumulated world-space normal of the first non-specular hit, as vec3f | | OSP_FB_ALBEDO | accumulated material albedo (color without illumination) at the first hit, as vec3f | | OSP_FB_ID_PRIMITIVE | primitive index of the first hit, as uint32 | | OSP_FB_ID_OBJECT | geometric/volumetric model `id`, if specified, or index in [group](#groups) of first hit, as uint32 | | OSP_FB_ID_INSTANCE | user defined [instance](#instances) `id`, if specified, or instance index of first hit, as uint32 | Framebuffer channels constants (of type `OSPFrameBufferChannel`), naming optional information the framebuffer can store. These values can be combined by bitwise OR when passed to `ospNewFrameBuffer`. If a certain channel value is *not* specified, the given buffer channel will not be present. Note that OSPRay makes a clear distinction between the *external* format of the framebuffer and the internal one: The external format is the format the user specifies in the `format` parameter; it specifies what color format OSPRay will eventually *return* the framebuffer to the application (when calling `ospMapFrameBuffer`): no matter what OSPRay uses internally, it will simply return a 2D array of pixels of that format, with possibly all kinds of reformatting, compression/decompression, etc., going on in-between the generation of the *internal* framebuffer and the mapping of the externally visible one. In particular, `OSP_FB_NONE` is a perfectly valid pixel format for a framebuffer that an application will never map. For example, an application driving a display wall may well generate an intermediate framebuffer and eventually transfer its pixel to the individual displays using an `OSPImageOperation` [image operation](#image-operation). The application can map the given channel of a framebuffer – and thus access the stored pixel information – via ``` cpp const void *ospMapFrameBuffer(OSPFrameBuffer, OSPFrameBufferChannel = OSP_FB_COLOR); ``` Note that `OSP_FB_ACCUM` or `OSP_FB_VARIANCE` cannot be mapped. The origin of the screen coordinate system in OSPRay is the lower left corner (as in OpenGL), thus the first pixel addressed by the returned pointer is the lower left pixel of the image. A previously mapped channel of a framebuffer can be unmapped by passing the received pointer `mapped` to ``` cpp void ospUnmapFrameBuffer(const void *mapped, OSPFrameBuffer); ``` The individual channels of a framebuffer can be cleared with ``` cpp void ospResetAccumulation(OSPFrameBuffer); ``` This function will clear *all* accumulating buffers (`OSP_FB_VARIANCE`, `OSP_FB_NORMAL`, and `OSP_FB_ALBEDO`, if present) and resets the accumulation counter `accumID`. It is unspecified if the existing color and depth buffers are physically cleared when `ospResetAccumulation` is called. If `OSP_FB_VARIANCE` is specified, an estimate of the variance of the last accumulated frame can be queried with ``` cpp float ospGetVariance(OSPFrameBuffer); ``` Note this value is only updated after synchronizing with `OSP_FRAME_FINISHED`, as further described in [asynchronous rendering](#asynchronous-rendering). The estimated variance can be used by the application as a quality indicator and thus to decide whether to stop or to continue progressive rendering. The framebuffer takes a list of pixel operations to be applied to the image in sequence as an `OSPData`. The pixel operations will be run in the order they are in the array. | Type | Name | Description | |:----------------------|:---------------|:-------------------------------------| | OSPImageOperation\[\] | imageOperation | ordered sequence of image operations | Parameters accepted by the framebuffer. ### Image Operation Image operations are functions that are applied to every pixel of a frame. Examples include post-processing, filtering, blending, tone mapping, or sending tiles to a display wall. To create a new pixel operation of given type `type` use ``` cpp OSPImageOperation ospNewImageOperation(const char *type); ``` #### Tone Mapper The tone mapper is a pixel operation which implements a generic filmic tone mapping operator. Using the default parameters it approximates the Academy Color Encoding System (ACES). The tone mapper is created by passing the type string “`tonemapper`†to `ospNewImageOperation`. The tone mapping curve can be customized using the parameters listed in the table below. | Type | Name | Default | Description | |:------|:----------|--------:|:-------------------------------------------------------------------------| | float | exposure | 1.0 | amount of light per unit area | | float | contrast | 1.6773 | contrast (toe of the curve); typically is in \[1–2\] | | float | shoulder | 0.9714 | highlight compression (shoulder of the curve); typically is in \[0.9–1\] | | float | midIn | 0.18 | mid-level anchor input; default is 18% gray | | float | midOut | 0.18 | mid-level anchor output; default is 18% gray | | float | hdrMax | 11.0785 | maximum HDR input that is not clipped | | bool | acesColor | true | apply the ACES color transforms | Parameters accepted by the tone mapper. To use the popular “Uncharted 2†filmic tone mapping curve instead, set the parameters to the values listed in the table below. | Name | Value | |:----------|:-------| | contrast | 1.1759 | | shoulder | 0.9746 | | midIn | 0.18 | | midOut | 0.18 | | hdrMax | 6.3704 | | acesColor | false | Filmic tone mapping curve parameters. Note that the curve includes an exposure bias to match 18% middle gray. #### Denoiser OSPRay comes with a module that adds support for Intel® Open Image Denoise (OIDN). This is provided as an optional module as it creates an additional project dependency at compile time. The module implements a “`denoiser`†frame operation, which denoises the entire frame before the frame is completed. OIDN will automatically select the fastest device, using a GPU when available. The device selection be overridden by the environment variable `OIDN_DEFAULT_DEVICE`, possible values are `cpu`, `sycl`, `cuda`, `hip`, or a physical device ID Rendering --------- ### Asynchronous Rendering Rendering is by default asynchronous (non-blocking), and is done by combining a framebuffer, renderer, camera, and world. What to render and how to render it depends on the renderer’s parameters. If the framebuffer supports accumulation (i.e., it was created with `OSP_FB_ACCUM`) then successive calls to `ospRenderFrame` will progressively refine the rendered image. To start an render task, use ``` cpp OSPFuture ospRenderFrame(OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld); ``` This returns an `OSPFuture` handle, which can be used to synchronize with the application, cancel, or query for progress of the running task. When `ospRenderFrame` is called, there is no guarantee when the associated task will begin execution. Progress of a running frame can be queried with the following API function ``` cpp float ospGetProgress(OSPFuture); ``` This returns the approximated progress of the task in \[0-1\]. Applications can cancel a currently running asynchronous operation via ``` cpp void ospCancel(OSPFuture); ``` Applications can wait on the result of an asynchronous operation, or choose to only synchronize with a specific event. To synchronize with an `OSPFuture` use ``` cpp void ospWait(OSPFuture, OSPSyncEvent = OSP_TASK_FINISHED); ``` The following are values which can be synchronized with the application | Name | Description | |:--------------------|:------------------------------------------------------------------------------------------------------------------------------------------------| | OSP_NONE_FINISHED | Do not wait for anything to be finished (immediately return from `ospWait`) | | OSP_WORLD_COMMITTED | Wait for the world to be committed (not yet implemented) | | OSP_WORLD_RENDERED | Wait for the world to be rendered, but not post-processing operations (Pixel/Tile/Frame Op) | | OSP_FRAME_FINISHED | Wait for all rendering operations to complete | | OSP_TASK_FINISHED | Wait on full completion of the task associated with the future. The underlying task may involve one or more of the above synchronization events | Supported events that can be passed to `ospWait`. Currently only rendering can be invoked asynchronously. However, future releases of OSPRay may add more asynchronous versions of API calls (and thus return `OSPFuture`). Applications can query whether particular events are complete with ``` cpp int ospIsReady(OSPFuture, OSPSyncEvent = OSP_TASK_FINISHED); ``` As the given running task runs (as tracked by the `OSPFuture`), applications can query a boolean \[0, 1\] result if the passed event has been completed. Applications can query how long an async task ran with ``` cpp float ospGetTaskDuration(OSPFuture); ``` This returns the wall clock execution time of the task in seconds. If the task is still running, this will block until the task is completed. This is useful for applications to query exactly how long an asynchronous task executed without the overhead of measuring both task execution + synchronization by the calling application. ### Synchronous Rendering For convenience in certain use cases, `ospray_util.h` provides a synchronous version of `ospRenderFrame`: ``` cpp float ospRenderFrameBlocking(OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld); ``` This version is the equivalent of: ``` cpp ospRenderFrame ospWait(f, OSP_TASK_FINISHED) return ospGetVariance(fb) ``` This version is closest to `ospRenderFrame` from OSPRay v1.x. ### Rendering and ospCommit The use of either `ospRenderFrame` or `ospRenderFrameBlocking` requires that all objects in the scene being rendered have been committed before rendering occurs. If a call to `ospCommit` happens while a frame is rendered, the result is undefined behavior and should be avoided. ### Picking To get the world-space position of the geometry (if any) seen at \[0–1\] normalized screen-space pixel coordinates `screenPos_x` and `screenPos_y` use ``` cpp void ospPick(OSPPickResult *, OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld, float screenPos_x, float screenPos_y); ``` The result is returned in the provided `OSPPickResult` struct: ``` cpp typedef struct { int hasHit; float worldPosition[3]; OSPInstance instance; OSPGeometricModel model; uint32_t primID; } OSPPickResult; ``` Note that `ospPick` considers exactly the same camera of the given renderer that is used to render an image, thus matching results can be expected. If the camera supports depth of field then the center of the lens and thus the center of the circle of confusion is used for picking. Note that the caller needs to `ospRelease` the `instance` and `model` handles of `OSPPickResult` once the information is not needed anymore. Modules and Devices =================== CPU --- The CPU module is implicitly loaded and the `cpu` device is automatically used if no other options are specified. GPU (Beta) ---------- To use the GPU for rendering load the `gpu` module and select the `gpu` device: ``` sh ./ospExamples --osp:load-modules=gpu --osp:device=gpu ``` or via explicit device creation by the application: ``` cpp ospLoadModule("gpu"); OSPDevice dev = ospNewDevice("gpu"); ospDeviceCommit(dev); ospSetCurrentDevice(dev); ``` | Type | Name | Description | |:--------|:------------|:-------------------| | void \* | syclContext | SYCL context | | void \* | syclDevice | SYCL device | | void \* | zeContext | Level Zero context | | void \* | zeDevice | Level Zero device | Parameters specific to the `gpu` device. Applications can either set their SYCL context and device or their Level Zero context and device, to share device memory with OSPRay or to control which device should be used (e.g., in case multiple GPUs are present). If neither parameter is set, the `gpu` device will automatically create a context internally and select a GPU (that selection can be influenced via environment variable `ONEAPI_DEVICE_SELECTOR`). Compile times for just in time compilation (JIT compilation) can be large. To resolve this issue we recommend enabling persistent JIT compilation caching inside your application before the SYCL device is created, by setting environment variables `SYCL_CACHE_PERSISTENT=1` (and optionally `SYCL_CACHE_DIR=` to some proper directory where the JIT cache should get stored). To reduce GPU memory allocation overhead when rendering scenes with many objects (geometries, instances, etc.), memory pooling should be enabled by setting the environment variable `ISPCRT_MEM_POOL=1`. ### Known Issues The following features are not implemented yet or are not working correctly on the GPU device: - Multiple volumes in the scene - Clipping - Motion blur - Subdivision surfaces - Progress reporting via `ospGetProgress` or canceling the frame via `ospCancel` - Picking via `ospPick` - Adaptive accumulation via `OSP_FB_VARIANCE` and `varianceThreshold` - Framebuffer channels `OSP_FB_ID_*` (id buffers) - Experimental support for shared device-only data, works only for `structuredRegular` volume There will be some delay on start-up as the kernel code is JIT compiled for the device, and similar pauses when changing the scene configuration, because the kernel specialized and re-compiled. For some combination of compiler, GPU driver and scene the rendered images might show artifacts (e.g., vertical lines or small blocks). Distributed Rendering with MPI ------------------------------ The purpose of OSPRay’s MPI modules is to provide distributed rendering capabilities for OSPRay. The modules enables image- and data-parallel rendering across HPC clusters using MPI, allowing applications to transparently distribute rendering work, or to render data sets which are too large to fit in memory on a single machine. OSPRay provides multiple MPI modules that expose different distributed rendering capabilities. The `mpi_offload` module provides image-parallel rendering through the `mpiOffload` device; it enables OSPRay applications written for local rendering to be replicated across multiple nodes to distribute the rendering work without code changes. And the `mpi_distributed_cpu` and `mpi_distributed_gpu` modules provides data-parallel rendering through the `mpiDistributed` device, which allows MPI distributed applications to use OSPRay for distributed rendering. Each rank using the `mpiDistributed` device can render an independent piece of a global data set, or perform hybrid rendering where ranks partially or completely share data. The `mpiDistributed` device’s image-parallel rendering support can be used to accelerate data loading for image-parallel applications, where all ranks load the same data from a shared disk and then perform image-parallel rendering on the replicated data, as if the `mpiOffload` device where being used. ### MPI Offload Rendering The `mpiOffload` device can be used to distribute image rendering tasks across a cluster without requiring modifications to the application itself. Existing applications using OSPRay for local rendering simply be passed command line arguments to load the module and indicate that the `mpiOffload` device should be used for image-parallel rendering. To load the module, pass `--osp:load-modules=mpi_offload`, to select the MPIOffloadDevice, pass `--osp:device=mpiOffload`. For example, the `ospExamples` application can be run as: ``` sh mpirun -n ./ospExamples --osp:load-modules=mpi_offload --osp:device=mpiOffload ``` and will automatically distribute the image rendering tasks among the corresponding `N` nodes. Note that in this configuration rank 0 will act as a master/application rank, and will run the user application code but not perform rendering locally. Thus, a minimum of 2 ranks are required, one master to run the application and one worker to perform the rendering. Running with 3 ranks for example would now distribute half the image rendering work to rank 1 and half to rank 2. If more control is required over the placement of ranks to nodes, or you want to run a worker rank on the master node as well you can run the application and the `ospray_mpi_worker` program through MPI’s MPMD mode. The `ospray_mpi_worker` will load the MPI module and select the offload device by default. ``` sh mpirun -n 1 ./ospExamples --osp:load-modules=mpi_offload --osp:device=mpiOffload \ : -n ./ospray_mpi_worker ``` If initializing the `mpiOffload` device manually, or passing parameters through the command line, the following parameters can be set: | Type | Name | Default | Description | |:-------|:------------------------|--------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | string | mpiMode | mpi | The mode to communicate with the worker ranks. `mpi` will assume you are launching the application and workers in the same mpi command (or split launch command). `mpi` is the only supported mode | | uint | maxCommandBufferEntries | 8192 | Set the max number of commands to buffer before submitting the command buffer to the workers | | uint | commandBufferSize | 512 MiB | Set the max command buffer size to allow. Units are in MiB. Max size is 1.8 GiB | | uint | maxInlineDataSize | 32 MiB | Set the max size of an OSPData which can be inline’d into the command buffer instead of being sent separately. Max size is half the commandBufferSize. Units are in MiB | Parameters specific to the `mpiOffload` device. The `maxCommandBufferEntries`, `commandBufferSize`, and `maxInlineDataSize` can also be set via the environment variables: `OSPRAY_MPI_MAX_COMMAND_BUFFER_ENTRIES`, `OSPRAY_MPI_COMMAND_BUFFER_SIZE`, and `OSPRAY_MPI_MAX_INLINE_DATA_SIZE`, respectively. The `mpiOffload` device uses a dynamic load balancer by default. If you wish to use a static load balancer you can do so by setting the `OSPRAY_STATIC_BALANCER` environment variable to 1. For the worker ranks to create GPU devices instead of the default CPU devices set the environment variable `OSPRAY_MPI_DISTRIBUTED_GPU`, e.g., ``` sh export OSPRAY_MPI_DISTRIBUTED_GPU=1 ``` or ``` sh mpiexec -genv OSPRAY_MPI_DISTRIBUTED_GPU 1 \ -n 1 ./ospExamples --osp:load-modules=mpi_offload --osp:device=mpiOffload \ : -n 2 ./ospray_mpi_worker ``` The `mpiOffload` device does not support multiple init/shutdown cycles. Thus, to run `ospBenchmark` for this device make sure to exclude the init/shutdown test by passing `--benchmark_filter=-ospInit_ospShutdown` through the command line. ### MPI Distributed Rendering While MPI Offload rendering is used to transparently distribute rendering work without requiring modification to the application, MPI Distributed rendering is targeted at use of OSPRay within MPI-parallel applications. The MPI distributed device can be selected by loading the `mpi_distributed_cpu` module for CPU rendering or `mpi_distributed_gpu` for GPU rendering, and manually creating and using an instance of the `mpiDistributed` device, for example: ``` cpp ospLoadModule("mpi_distributed_cpu"); OSPDevice mpiDevice = ospNewDevice("mpiDistributed"); ospDeviceCommit(mpiDevice); ospSetCurrentDevice(mpiDevice); ``` Your application can either initialize MPI before-hand, ensuring that `MPI_THREAD_SERIALIZED` or higher is supported, or allow the device to initialize MPI on commit. Thread multiple support is required if your application will make MPI calls while rendering asynchronously with OSPRay. When using the distributed device each rank can specify independent local data using the OSPRay API, as if rendering locally. However, when calling `ospRenderFrameAsync` the ranks will work collectively to render the data. The distributed device supports both image-parallel, where the data is replicated, and data-parallel, where the data is distributed, rendering modes. The `mpiDistributed` device will by default use each rank in `MPI_COMM_WORLD` as a render worker; however, it can also take a specific MPI communicator to use as the world communicator. Only those ranks in the specified communicator will participate in rendering. | Type | Name | Default | Description | |:--------|:------------------|---------------:|:--------------------------------------------------------------------------| | void \* | worldCommunicator | MPI_COMM_WORLD | The MPI communicator which the OSPRay workers should treat as their world | Parameters specific to the `mpiDistributed` device. | Type | Name | Default | Description | |:----------|:-------|--------:|:-------------------------------------------------------------------------------------| | box3f\[\] | region | NULL | A list of bounding boxes which bound the owned local data to be rendered by the rank | Parameters specific to the distributed `OSPWorld`. | Type | Name | Default | Description | |:------|:-------------------|----------------:|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | int | aoSamples | 0 | The number of AO samples to take per-pixel | | float | aoDistance | 1020 | The AO ray length to use. Note that if the AO ray would have crossed a rank boundary and ghost geometry is not available, there will be visible artifacts in the shading | | float | volumeSamplingRate | 1 | sampling rate for volumes | Parameters specific to the `mpiRaycast` renderer. #### Image Parallel Rendering in the MPI Distributed Device If all ranks specify exactly the same data, the distributed device can be used for image-parallel rendering. This works identical to the offload device, except that the MPI-aware application is able to load data in parallel on each rank rather than loading on the master and shipping data out to the workers. When a parallel file system is available, this can improve data load times. Image-parallel rendering is selected by specifying the same data on each rank, and using any of the existing local renderers (e.g., `scivis`, `pathtracer`). See [ospMPIDistribTutorialReplicated](https://github.com/ospray/ospray/blob/master/modules/mpi/tutorials/ospMPIDistribTutorialReplicated.cpp) for an example. #### Data Parallel Rendering in the MPI Distributed Device The MPI Distributed device also supports data-parallel rendering with sort-last compositing. Each rank can specify a different piece of data, as long as the bounding boxes of each rank’s data are non-overlapping. The rest of the scene setup is similar to local rendering; however, for distributed rendering only the `mpiRaycast` renderer is supported. This renderer implements a subset of the `scivis` rendering features which are suitable for implementation in a distributed environment. By default the aggregate bounding box of the instances in the local world will be used as the bounds of that rank’s data. However, when using ghost zones for volume interpolation, geometry or ambient occlusion, each rank’s data can overlap. To clip these non-owned overlap regions out a set of regions (the `region` parameter) can pass as a parameter to the `OSPWorld` being rendered. Each rank can specify one or more non-overlapping `box3f`’s which bound the portions of its local data which it is responsible for rendering. See the [ospMPIDistribTutorialVolume](https://github.com/ospray/ospray/blob/master/modules/mpi/tutorials/ospMPIDistribTutorialVolume.cpp) for an example. Finally, the MPI distributed device also supports hybrid-parallel rendering, where multiple ranks can share a single piece of data. For each shared piece of data the rendering work will be assigned image-parallel among the ranks. Partially-shared regions are determined by finding those ranks specifying data with the same bounds (matching regions) and merging them. See the [ospMPIDistribTutorialPartialRepl](https://github.com/ospray/ospray/blob/master/modules/mpi/tutorials/ospMPIDistribTutorialPartialRepl.cpp) for an example. #### Picking on Distributed Data in the MPI Distributed Device Calling `ospPick` in the distributed device will find and return the closest global object at the screen position on the rank that owns that object. The other ranks will report no hit. Picking in the distributed device takes into account data clipping applied through the `regions` parameter to avoid picking ghost data. ### Interaction with User Modules The MPI Offload rendering mode trivially supports user modules, with the caveat that attempting to share data directly with the application (e.g., passing a `void *` or other tricks to the module) will not work in a distributed environment. Instead, use the `ospNewSharedData` API to share data from the application with OSPRay, which will in turn be copied over the network to the workers. The MPI Distributed device also supports user modules, as all that is required for compositing the distributed data are the bounds of each rank’s local data. MultiDevice ----------- The multidevice module is an experimental OSPRay device type that renders images by delegating off pixel tiles to a number of internal delegate OSPRay devices. If you wish to try it set the `OSPRAY_NUM_SUBDEVICES` environmental variable to the number of subdevices you want to create and tell OSPRay to both load the `multidevice_cpu` extension and create a multidevice for rendering instead of the default CPU device. One example in a bash like shell is as follows: ``` sh OSPRAY_NUM_SUBDEVICES=6 ./ospTutorial --osp:load-modules=multidevice_cpu --osp:device=multidevice ``` Note that the multidevice currently does not support `OSPImageOperation`s for denoising nor tone mapping. Tutorials ========= ospTutorial ----------- A minimal working example demonstrating how to use OSPRay can be found at [`apps/tutorials/ospTutorial.c`](https://github.com/ospray/ospray/blob/master/apps/ospTutorial/ospTutorial.c)[^9]. An example of building `ospTutorial.c` with CMake can be found in [`apps/tutorials/ospTutorialFindospray/`](https://github.com/ospray/ospray/tree/master/apps/ospTutorial/ospTutorialFindospray). To build the tutorial on Linux, build it in a build directory with ``` sh gcc -std=c99 ../apps/ospTutorial/ospTutorial.c \ -I ../ospray/include -L . -lospray -Wl,-rpath,. -o ospTutorial ``` On Windows build it can be build manually in a “build_directory\\\$Configuration†directory with ``` sh cl ..\..\apps\ospTutorial\ospTutorial.c -I ..\..\ospray\include -I ..\.. ospray.lib ``` Running `ospTutorial` will create two images of two triangles, rendered with the Scientific Visualization renderer with full Ambient Occlusion. The first image `firstFrame.ppm` shows the result after one call to `ospRenderFrame` – jagged edges and noise in the shadow can be seen. Calling `ospRenderFrame` multiple times enables progressive refinement, resulting in antialiased edges and converged shadows, shown after ten frames in the second image `accumulatedFrames.ppm`. ![First frame.](https://ospray.github.io/images/tutorial_firstframe.png) ![After accumulating ten frames.](https://ospray.github.io/images/tutorial_accumulatedframe.png) ospExamples ----------- Apart from tutorials, `OSPRay` comes with a C++ app called [`ospExamples`](https://github.com/ospray/ospray/tree/master/apps/ospExamples) which is an elaborate easy-to-use tutorial, with a single interface to try various `OSPRay` features. It is aimed at providing users with multiple simple scenes composed of basic geometry types, lights, volumes etc. to get started with OSPRay quickly. `ospExamples` app runs a `GLFWOSPRayWindow` instance that manages instances of the camera, framebuffer, renderer and other OSPRay objects necessary to render an interactive scene. The scene is rendered on a `GLFW` window with an `imgui` GUI controls panel for the user to manipulate the scene at runtime. The application is located in [`apps/ospExamples/`](https://github.com/ospray/ospray/tree/master/apps/ospExamples) directory and can be built with CMake. It can be run from the build directory via: ./ospExamples The command line parameter is optional however.
ospExamples application with default boxes scene.
### Scenes Different scenes can be selected from the `scenes` dropdown and each scene corresponds to an instance of a special `detail::Builder` struct. Example builders are located in [`apps/common/ospray_testing/builders/`](https://github.com/ospray/ospray/tree/master/apps/common/ospray_testing/builders). These builders provide a usage guide for the OSPRay scene hierarchy and OSPRay API in the form of `cpp` wrappers. They instantiate and manage objects for the specific scene like `cpp::Geometry`, `cpp::Volume`, `cpp::Light` etc. The `detail::Builder` base struct is mostly responsible for setting up OSPRay `world` and objects common in all scenes (for example lighting and ground plane), which can be conveniently overridden in the derived builders. ### Renderer This app comes with four [renderer](#renderers) options: `scivis`, `pathtracer`, `ao` and `debug`. The app provides some common rendering controls like `pixelSamples` and other more specific to the renderer type like `aoSamples` for the `scivis` and `ao` renderer or `maxPathLength` for the `pathtracer`. The sun-sky lighting can be used in a sample scene by enabling the `renderSunSky` option of the `pathtracer` renderer. It allows the user to change `turbidity` and `sunDirection`.
Rendering an evening sky with the renderSunSky option.
ospMPIDistribTutorial --------------------- A minimal working example demonstrating how to use OSPRay for rendering distributed data can be found at [`modules/mpi/tutorials/ospMPIDistribTutorial.c`](https://github.com/ospray/ospray/blob/master/modules/mpi/tutorials/ospMPIDistribTutorial.c)[^10]. The compilation process via CMake is the similar to [`apps/tutorials/ospTutorialFindospray/`](https://github.com/ospray/ospray/tree/master/apps/ospTutorial/ospTutorialFindospray), with the addition of finding and linking MPI. To build the tutorial on Linux, build it in a build directory with ``` sh mpicc -std=c99 ../modules/mpi/tutorials/ospMPIDistribTutorial.c \ -I ../ospray/include -L . -lospray -Wl,-rpath,. -o ospMPIDistribTutorial ``` On Windows build it can be build manually in a “build_directory\\\$Configuration†directory with ``` sh cl ..\..\modules\mpi\tutorials\ospMPIDistribTutorial.c -I ..\..\ospray\include -I ..\.. ospray.lib ``` The MPI module does not need to be linked explicitly, as it is loaded as a module at runtime.
The first frame output by the ospMPIDistribTutorial or C++ tutorial with 4 ranks.
The accumulated frame output by the ospMPIDistribTutorial or C++ tutorial with 4 ranks.
ospMPIDistribTutorialSpheres and ospMPIDistribTutorialVolume ------------------------------------------------------------ The spheres and volume distributed tutorials are built as part of the MPI tutorials when building OSPRay with the MPI module and tutorials enabled. These tutorials demonstrate using OSPRay to render distributed data sets where each rank owns some subregion of the data, and displaying the output in an interactive window. The domain is distributed in a grid among the processes, each of which will generate a subset of the data corresponding to its subdomain. In `ospMPIDistribTutorialSpheres`, each process generates a set of spheres within its assigned domain. The spheres are colored from dark to light blue, where lighter colors correspond to higher ranks.
Running ospMPIDistribTutorialSpheres on 4 ranks.
In `ospMPIDistribTutorialVolume`, each process generates a subbrick of volume data, which is colored by its rank.
Running ospMPIDistribTutorialVolume on 4 ranks.
ospMPIDistribTutorialPartialRepl -------------------------------- The partially replicated MPI tutorial demonstrates how to use OSPRay’s distributed rendering capabilities to render data sets that are partially replicated among the processes. Each pair of ranks generates the same volume brick, allowing them to subdivide the rendering workload between themselves. For example, when run with two ranks, each will generate the same brick and be responsible for rendering half of the image tiles it projects to. When run with four ranks, the pairs of ranks 0,1 and 2,3 will generate the same data and divide the rendering workload for that data among themselves. The image work subdivision happens automatically, based on which ranks specify the same bounding box for their data, as demonstrated in the tutorial. The partially replicated distribution is useful to support load-balanced rendering of data sets that are too large to be fully replicated among the processes, but are small enough to be partially replicated among them. ospMPIDistribTutorialReplicated ------------------------------- The replicated MPI tutorial demonstrates how OSPRay’s distributed rendering capabilities can be used to render data sets that are fully replicated among the ranks with advanced illumination effects. In this case, although the processes are run MPI parallel, each rank specifies the exact same data. OSPRay’s MPI parallel renderer will detect that the data is replicated in this case and use the same image-parallel rendering algorithms employed in the MPI offload rendering configuration to render the data. This image-parallel rendering algorithm supports all rendering configurations that are used in local rendering, e.g., path tracing, to provide high-quality images. The replicated MPI tutorial supports the same scenes and parameters as the [`ospExamples`](#ospexamples) app described above. This mode can be useful when high-quality rendering is desired and it is possible to copy the entire data set on to each rank, or to accelerate loading of a large model by leveraging a parallel file system. [^1]: This file is usually in `${install_location}/[lib|lib64]/cmake/ospray-${version}/`. If CMake does not find it automatically, then specify its location in variable `ospray_DIR` (either an environment variable or CMake variable). [^2]: The number of items to be copied is defined by the size of the source array. [^3]: For consecutive memory addresses the x-index of the corresponding voxel changes the quickest. [^4]: actually a parallelogram [^5]: respectively $(127, 127, 255)$ for 8 bit textures and $(32767, 32767, 65535)$ for 16 bit textures [^6]: including spheres, boxes, infinite planes, closed meshes, closed subdivisions and curves [^7]: `OSPBounds` has essentially the same layout as the `OSP_BOX3F` [`OSPDataType`](#data). [^8]: If there are multiple ambient lights then their contribution is added. [^9]: A C++ version that uses the C++ convenience wrappers of OSPRay’s C99 API via [`include/ospray/ospray_cpp.h`](https://github.com/ospray/ospray/blob/master/ospray/include/ospray/ospray_cpp.h) is available at [`apps/tutorials/ospTutorial.cpp`](https://github.com/ospray/ospray/blob/master/apps/ospTutorial/ospTutorial.cpp). [^10]: A C++ version that uses the C++ convenience wrappers of OSPRay’s C99 API via [`include/ospray/ospray_cpp.h`](https://github.com/ospray/ospray/blob/master/ospray/include/ospray/ospray_cpp.h) is available at [`modules/mpi/tutorials/ospMPIDistribTutorial.cpp`](https://github.com/ospray/ospray/blob/master/modules/mpi/tutorials/ospMPIDistribTutorial.cpp). RenderKit-ospray-f2a61c2/SECURITY.md000066400000000000000000000010101456566705700171300ustar00rootroot00000000000000Security Policy =============== Intel is committed to rapidly addressing security vulnerabilities affecting our customers and providing clear guidance on the solution, impact, severity and mitigation. Reporting a Vulnerability ------------------------- Please [report any security vulnerabilities][guidelines] in this project utilizing the [guidelines here][guidelines]. [guidelines]: https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html "Vulnerability Handling Guidelines" RenderKit-ospray-f2a61c2/STYLEGUIDE.md000066400000000000000000000157771456566705700173700ustar00rootroot00000000000000OSPRay Style Guide ================== This document discusses the project's expectations on C++ and ISPC style. In general, the items discussed are meant to be a guide and not be overly strict. However, deviations from this document should be supported with technical reasoning. This document is relatively simple and meant as a "quick overview" of expecations for OSPRay. A more complete set of guidelines for all of C++ can be found in the [ISO C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md). Documentation ------------- In general, comments in code should describe "why" not "what". Code documentation should be in terms of C++ style single-line comments or multi-line C style comments. Avoid Doxygen-style code documentation, this is deprecated. When adding or updating public API definitions, update the corresponding `doc/api.md` documentation as part of your merge request. This keeps our documentation always current, and minimizes the need for audits at release time. Markdown files (`.md`) should use a 72 column limit for running text, exceptions are URLs or example code (i.e. preformatted sections in backticks). General Code Goals ------------------ In all code, the overall goal is to make interfaces "easy to use correctly" and "difficult to use incorrectly". Some characteristics that make code better are: - Keep reasoning as local as possible - Descriptive names - Short functions - Single functions/abstractions for repetitive concepts (less copy/paste) - Compile errors over runtime errors We have a number of small, single-purpose abstractions in `rkcommon` that aide in the above goals. It is expected for contributions to first try and use those constructs before implementing their own. Lastly, it is expected that code is formatted using the provided `.clang-format` config found in the root of the repository, e.g. by running `git-clang-format` (which also avoids changes which are only due to formatting). Consider to pre-format very long strings using C++11 raw string literals. NOTE: Both C++ and ISPC files can be formatted with clang-format. Naming conventions for public API --------------------------------- - Prefer enums over string parameters. - Parameter and object names are camelCase (e.g. `metallicPaint`) - Parameter names are singular, even if it is an array (e.g. `index`, `material`) - Data belonging together like the members of an array of structs, which are passed as struct of arrays, have a common prefix. For example `vertex.color` and `vertex.normals` - Switches (bools) name just what they switch, e.g. `shadows` (not `shadowsEnabled` nor `enableShadows`, nor `useShadows`) C++ Usage Guidelines -------------------- C++ is a big language, so the following are things that we prefer to see in OSPRay: ### Memory Management, Object Lifetimes, and Pointers - For collections, prefer STL containers over C arrays, specifically `std::vector` and `rkcommon::containers::AlignedVector`. - Prefer smart pointers to manage memory over raw `new` and `delete`. - Prefer the usage of `std::unique_ptr` to manage heap objects, until memory lifetimes must be managed by more than one observer. - Prefer constructing smart pointers with `rkcommon::make_unique<>` and `std::make_shared<>` over using `new`. - Avoid globals and `std::shared_ptr` that cross translation units. - Prefer global scope variables to be marked `static`. - Prefer functions to access global data in another translation unit over marking them as `extern`. - Keep raw pointer usage local, either in a function or in a single cpp file. - Prefer the usage of references over pointers for cases where `nullptr` is not a valid value. - Prefer using `rkcommon::utility::OnScopeExit` to robustly cleanup non-trivial objects in a function. - Avoid constructing `static` data that requires initialization ordering with other `static` data. ### Designing Types (classes/structs) - Define empty default constructors with `= default;`, not with an empty `{}`. - Use the `virtual` keyword only to mark that child classes are expected to override, not that the function is overriding a parent method. - Always use the `override` keyword where appropriate. - Prefer to write `const` functions by default. - Prefer implementing inline member functions below the definition of the class or struct. This makes classes easier to read by avoiding unnecessary implementation details when reading the class interface. - Implement `begin()` and `end()` iterators for types which abstract collections. - Consider whether the type should be move-only (ex: `std::unique_ptr`) or copyable. - Prefer `= delete;` syntax to delete constructors over marking them `private`. - Prefer giving all applicable member values inlined default values. - Only populate values in constructor initialization if the value is different than the default or is being set by a constructor parameter. - Only mark methods as `virtual` if the class is intended to be in an inheritance hierarchy. - Always implement a `virtual` destructor, even if it's `= default;`. ### Loops, STL Algorithms, and Threading - Prefer the usage of an algorithm call over implementing a raw loop. - Prefer making multi-STL algorithm functions their own function with a name. - Prefer using `rkcommon::tasking` constructs instead of raw threads. - Prefer range-based for loops over indexing for loops where possible. - Avoid shared mutable state in parallel code (requires synchronization). - Capture type preference for lambda functions should be `[]` → `[&]` → `[=]`. ### Templates - Prefer to constrain template types to only relevant types using `static_assert()` and type traits. - Use `std::forward` when passing universal references (`T&&`) to other templates. - Only use SFINAE when necessary, and try to keep its usage as simple as possible. ISPC Usage ---------- The following are concerns specific to ISPC: - Prefer using `uniform` variables. The point of ISPC is to have varying data, but uniform values are more efficient than replicated varying values. - Avoid writing unnecessary `uniform` and `varying` keywords. Examples: ``` {.cpp} varying float f; // 'varying' is redundant, variables are varying by default uniform float *p; // 'uniform' is redundant, pointers point to uniform by default ``` - Prefer omitting `uniform`/`varying` qualifiers for structs. Only apply them if they need to be consistently the same for both `uniform` and `varying` instances of the struct. ### OSPRay ISPCDevice Specific Design Choices - Prefer to use Embree C API bindings over ISPC where possible. - Prefer to throw exceptions when an object is found to be invalid during `commit()`. - Prefer setting ISPC-side values in a single `set()` call over many single value setting functions. - Minimize the number of alias names given to both object types and parameters. RenderKit-ospray-f2a61c2/apps/000077500000000000000000000000001456566705700163125ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/CMakeLists.txt000066400000000000000000000012671456566705700210600ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 cmake_dependent_option( OSPRAY_APPS_ENABLE_GLM "Build ospray_cpp glm tests/tutorial" OFF "OSPRAY_ENABLE_APPS_TESTING OR OSPRAY_ENABLE_APPS_TUTORIALS" OFF ) # Find GLM here for both ospTutorialGLM and ospTestSuite if (OSPRAY_APPS_ENABLE_GLM) find_package(glm REQUIRED) if(TARGET glm::glm) set(GLM_TARGET glm::glm) else() set(GLM_TARGET glm) endif() endif() if (OSPRAY_ENABLE_APPS_EXAMPLES) # prefer libGL over libOpenGl for better compatibility with SWR set(OpenGL_GL_PREFERENCE "LEGACY") find_package(OpenGL 3 REQUIRED) find_package(glfw3 REQUIRED) endif() add_all_subdirectories() RenderKit-ospray-f2a61c2/apps/common/000077500000000000000000000000001456566705700176025ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/common/CMakeLists.txt000066400000000000000000000003561456566705700223460ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 if (NOT OSPRAY_ENABLE_APPS_BENCHMARK AND NOT OSPRAY_ENABLE_APPS_EXAMPLES AND NOT OSPRAY_ENABLE_APPS_TESTING) return() endif() add_all_subdirectories() RenderKit-ospray-f2a61c2/apps/common/arcball_camera/000077500000000000000000000000001456566705700225125ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/common/arcball_camera/ArcballCamera.cpp000066400000000000000000000061601456566705700256720ustar00rootroot00000000000000// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ArcballCamera.h" ArcballCamera::ArcballCamera(const rkcommon::math::box3f &worldBounds, const rkcommon::math::vec2i &windowSize) : zoomSpeed(1), invWindowSize( rkcommon::math::vec2f(1.0) / rkcommon::math::vec2f(windowSize)), centerTranslation(rkcommon::math::one), translation(rkcommon::math::one), rotation(rkcommon::math::one) { rkcommon::math::vec3f diag = worldBounds.size(); zoomSpeed = rkcommon::math::max(length(diag) / 150.0, 0.001); diag = rkcommon::math::max(diag, rkcommon::math::vec3f(0.3f * length(diag))); centerTranslation = rkcommon::math::AffineSpace3f::translate(-worldBounds.center()); translation = rkcommon::math::AffineSpace3f::translate( rkcommon::math::vec3f(0, 0, length(diag))); updateCamera(); } void ArcballCamera::rotate( const rkcommon::math::vec2f &from, const rkcommon::math::vec2f &to) { rotation = screenToArcball(to) * screenToArcball(from) * rotation; updateCamera(); } void ArcballCamera::zoom(float amount) { amount *= zoomSpeed; translation = rkcommon::math::AffineSpace3f::translate( rkcommon::math::vec3f(0, 0, amount)) * translation; updateCamera(); } void ArcballCamera::pan(const rkcommon::math::vec2f &delta) { const rkcommon::math::vec3f t = rkcommon::math::vec3f( -delta.x * invWindowSize.x, delta.y * invWindowSize.y, 0); const rkcommon::math::vec3f worldt = translation.p.z * xfmVector(invCamera, t); centerTranslation = rkcommon::math::AffineSpace3f::translate(worldt) * centerTranslation; updateCamera(); } rkcommon::math::vec3f ArcballCamera::eyePos() const { return xfmPoint(invCamera, rkcommon::math::vec3f(0, 0, 1)); } rkcommon::math::vec3f ArcballCamera::center() const { return -centerTranslation.p; } rkcommon::math::vec3f ArcballCamera::lookDir() const { return xfmVector(invCamera, rkcommon::math::vec3f(0, 0, 1)); } rkcommon::math::vec3f ArcballCamera::upDir() const { return xfmVector(invCamera, rkcommon::math::vec3f(0, 1, 0)); } rkcommon::math::AffineSpace3f ArcballCamera::transform() const { return invCamera; } void ArcballCamera::updateCamera() { const rkcommon::math::AffineSpace3f rot = rkcommon::math::LinearSpace3f(rotation); const rkcommon::math::AffineSpace3f camera = translation * rot * centerTranslation; invCamera = rcp(camera); } void ArcballCamera::setRotation(rkcommon::math::quatf q) { rotation = q; updateCamera(); } void ArcballCamera::updateWindowSize(const rkcommon::math::vec2i &windowSize) { invWindowSize = rkcommon::math::vec2f(1) / rkcommon::math::vec2f(windowSize); } rkcommon::math::quatf ArcballCamera::screenToArcball( const rkcommon::math::vec2f &p) { const float dist = dot(p, p); // If we're on/in the sphere return the point on it if (dist <= 1.f) { return rkcommon::math::quatf(0, p.x, p.y, std::sqrt(1.f - dist)); } else { // otherwise we project the point onto the sphere const rkcommon::math::vec2f unitDir = normalize(p); return rkcommon::math::quatf(0, unitDir.x, unitDir.y, 0); } } RenderKit-ospray-f2a61c2/apps/common/arcball_camera/ArcballCamera.h000066400000000000000000000022421456566705700253340ustar00rootroot00000000000000// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/AffineSpace.h" class ArcballCamera { public: ArcballCamera(const rkcommon::math::box3f &worldBounds, const rkcommon::math::vec2i &windowSize); // All mouse positions passed should be in [-1, 1] normalized screen coords void rotate( const rkcommon::math::vec2f &from, const rkcommon::math::vec2f &to); void zoom(float amount); void pan(const rkcommon::math::vec2f &delta); rkcommon::math::vec3f eyePos() const; rkcommon::math::vec3f center() const; rkcommon::math::vec3f lookDir() const; rkcommon::math::vec3f upDir() const; rkcommon::math::AffineSpace3f transform() const; void setRotation(rkcommon::math::quatf); void updateWindowSize(const rkcommon::math::vec2i &windowSize); protected: void updateCamera(); // Project the point in [-1, 1] screen space onto the arcball sphere rkcommon::math::quatf screenToArcball(const rkcommon::math::vec2f &p); float zoomSpeed; rkcommon::math::vec2f invWindowSize; rkcommon::math::AffineSpace3f centerTranslation, translation, invCamera; rkcommon::math::quatf rotation; }; RenderKit-ospray-f2a61c2/apps/common/arcball_camera/CMakeLists.txt000066400000000000000000000004201456566705700252460ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 add_library(arcball_camera STATIC ArcballCamera.cpp) target_link_libraries(arcball_camera PUBLIC rkcommon::rkcommon) target_include_directories(arcball_camera INTERFACE ${CMAKE_CURRENT_LIST_DIR}) RenderKit-ospray-f2a61c2/apps/common/external/000077500000000000000000000000001456566705700214245ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/common/external/CMakeLists.txt000066400000000000000000000003201456566705700241570ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ospray_disable_compiler_warnings() if (OSPRAY_ENABLE_APPS_EXAMPLES) add_subdirectory(imgui) endif() add_subdirectory(stb_image) RenderKit-ospray-f2a61c2/apps/common/external/imgui/000077500000000000000000000000001456566705700225365ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/common/external/imgui/CMakeLists.txt000066400000000000000000000010321456566705700252720ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ospray_disable_compiler_warnings() add_library(ospray_imgui SHARED imgui.cpp imgui_draw.cpp imgui_tables.cpp imgui_widgets.cpp imgui_impl_opengl3.cpp imgui_impl_glfw.cpp ) target_link_libraries(ospray_imgui PUBLIC glfw ${OPENGL_LIBRARIES} rkcommon::rkcommon ) ospray_install_library(ospray_imgui apps) target_include_directories( ospray_imgui INTERFACE $ PRIVATE ${CMAKE_CURRENT_LIST_DIR} ) RenderKit-ospray-f2a61c2/apps/common/external/imgui/imconfig.h000066400000000000000000000246711456566705700245140ustar00rootroot00000000000000//----------------------------------------------------------------------------- // DEAR IMGUI COMPILE-TIME OPTIONS // Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure. // You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions. //----------------------------------------------------------------------------- // A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it) // B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template. //----------------------------------------------------------------------------- // You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp // files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures. // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. // Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using. //----------------------------------------------------------------------------- #pragma once //---- Define assertion handler. Defaults to calling assert(). // If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement. //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows // Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. #ifdef _WIN32 # ifdef ospray_imgui_EXPORTS # define IMGUI_API __declspec(dllexport) # else # define IMGUI_API __declspec(dllimport) # endif #else # define IMGUI_API #endif // DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. //#define IMGUI_API __declspec( dllexport ) //#define IMGUI_API __declspec( dllimport ) //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names. #define IMGUI_DISABLE_OBSOLETE_FUNCTIONS //#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87+ disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This is automatically done by IMGUI_DISABLE_OBSOLETE_FUNCTIONS. //---- Disable all of Dear ImGui or don't implement standard windows/tools. // It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp. //#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty. #define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. #define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIDStackToolWindow() will be empty. //---- Don't implement some functions to reduce linkage requirements. //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) //#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW) //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a) //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME). //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. #define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies) //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). //#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available //---- Include imgui_user.h at the end of imgui.h as a convenience // May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included. //#define IMGUI_INCLUDE_IMGUI_USER_H //#define IMGUI_USER_H_FILENAME "my_folder/my_imgui_user.h" //---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another) //#define IMGUI_USE_BGRA_PACKED_COLOR //---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...) //#define IMGUI_USE_WCHAR32 //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version // By default the embedded implementations are declared static and not available outside of Dear ImGui sources files. //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" //#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if IMGUI_USE_STB_SPRINTF is defined. //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION //#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION // only disabled if IMGUI_USE_STB_SPRINTF is defined. //---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) // Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h. //#define IMGUI_USE_STB_SPRINTF //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). // On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'. //#define IMGUI_ENABLE_FREETYPE //---- Use FreeType+lunasvg library to render OpenType SVG fonts (SVGinOT) // Requires lunasvg headers to be available in the include path + program to be linked with the lunasvg library (not provided). // Only works in combination with IMGUI_ENABLE_FREETYPE. // (implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement) //#define IMGUI_ENABLE_FREETYPE_LUNASVG //---- Use stb_truetype to build and rasterize the font atlas (default) // The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend. //#define IMGUI_ENABLE_STB_TRUETYPE //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. // This will be inlined as part of ImVec2 and ImVec4 class declarations. /* #define IM_VEC2_CLASS_EXTRA \ constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \ operator MyVec2() const { return MyVec2(x,y); } #define IM_VEC4_CLASS_EXTRA \ constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \ operator MyVec4() const { return MyVec4(x,y,z,w); } */ //---- ...Or use Dear ImGui's own very basic math operators. //#define IMGUI_DEFINE_MATH_OPERATORS //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer. // Read about ImGuiBackendFlags_RendererHasVtxOffset for details. //#define ImDrawIdx unsigned int //---- Override ImDrawCallback signature (will need to modify renderer backends accordingly) //struct ImDrawList; //struct ImDrawCmd; //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); //#define ImDrawCallback MyImDrawCallback //---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase) // (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.) //#define IM_DEBUG_BREAK IM_ASSERT(0) //#define IM_DEBUG_BREAK __debugbreak() //---- Debug Tools: Enable slower asserts //#define IMGUI_DEBUG_PARANOID //---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files) /* namespace ImGui { void MyFunction(const char* name, MyMatrix44* mtx); } */ RenderKit-ospray-f2a61c2/apps/common/external/imgui/imgui.cpp000066400000000000000000030404141456566705700243620ustar00rootroot00000000000000// dear imgui, v1.90.3 // (main code and documentation) // Help: // - See links below. // - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that. // - Read top of imgui.cpp for more details, links and comments. // Resources: // - FAQ https://dearimgui.com/faq // - Getting Started https://dearimgui.com/getting-started // - Homepage https://github.com/ocornut/imgui // - Releases & changelog https://github.com/ocornut/imgui/releases // - Gallery https://github.com/ocornut/imgui/issues/6897 (please post your screenshots/video there!) // - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there) // - Glossary https://github.com/ocornut/imgui/wiki/Glossary // - Issues & support https://github.com/ocornut/imgui/issues // - Tests & Automation https://github.com/ocornut/imgui_test_engine // For first-time users having issues compiling/linking/running/loading fonts: // please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above. // Everything else should be asked in 'Issues'! We are building a database of cross-linked knowledge there. // Copyright (c) 2014-2024 Omar Cornut // Developed by Omar Cornut and every direct or indirect contributors to the GitHub. // See LICENSE.txt for copyright and licensing details (standard MIT License). // This library is free but needs your support to sustain development and maintenance. // Businesses: you can support continued development via B2B invoiced technical support, maintenance and sponsoring contracts. // PLEASE reach out at omar AT dearimgui DOT com. See https://github.com/ocornut/imgui/wiki/Sponsors // Businesses: you can also purchase licenses for the Dear ImGui Automation/Test Engine. // It is recommended that you don't modify imgui.cpp! It will become difficult for you to update the library. // Note that 'ImGui::' being a namespace, you can add functions into the namespace from your own source files, without // modifying imgui.h or imgui.cpp. You may include imgui_internal.h to access internal data structures, but it doesn't // come with any guarantee of forward compatibility. Discussing your changes on the GitHub Issue Tracker may lead you // to a better solution or official support for them. /* Index of this file: DOCUMENTATION - MISSION STATEMENT - CONTROLS GUIDE - PROGRAMMER GUIDE - READ FIRST - HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI - GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE - HOW A SIMPLE APPLICATION MAY LOOK LIKE - HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE - API BREAKING CHANGES (read me when you update!) - FREQUENTLY ASKED QUESTIONS (FAQ) - Read all answers online: https://www.dearimgui.com/faq, or in docs/FAQ.md (with a Markdown viewer) CODE (search for "[SECTION]" in the code to find them) // [SECTION] INCLUDES // [SECTION] FORWARD DECLARATIONS // [SECTION] CONTEXT AND MEMORY ALLOCATORS // [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO) // [SECTION] MISC HELPERS/UTILITIES (Geometry functions) // [SECTION] MISC HELPERS/UTILITIES (String, Format, Hash functions) // [SECTION] MISC HELPERS/UTILITIES (File functions) // [SECTION] MISC HELPERS/UTILITIES (ImText* functions) // [SECTION] MISC HELPERS/UTILITIES (Color functions) // [SECTION] ImGuiStorage // [SECTION] ImGuiTextFilter // [SECTION] ImGuiTextBuffer, ImGuiTextIndex // [SECTION] ImGuiListClipper // [SECTION] STYLING // [SECTION] RENDER HELPERS // [SECTION] INITIALIZATION, SHUTDOWN // [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!) // [SECTION] INPUTS // [SECTION] ERROR CHECKING // [SECTION] ITEM SUBMISSION // [SECTION] LAYOUT // [SECTION] SCROLLING // [SECTION] TOOLTIPS // [SECTION] POPUPS // [SECTION] KEYBOARD/GAMEPAD NAVIGATION // [SECTION] DRAG AND DROP // [SECTION] LOGGING/CAPTURING // [SECTION] SETTINGS // [SECTION] LOCALIZATION // [SECTION] VIEWPORTS, PLATFORM WINDOWS // [SECTION] PLATFORM DEPENDENT HELPERS // [SECTION] METRICS/DEBUGGER WINDOW // [SECTION] DEBUG LOG WINDOW // [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, ID STACK TOOL) */ //----------------------------------------------------------------------------- // DOCUMENTATION //----------------------------------------------------------------------------- /* MISSION STATEMENT ================= - Easy to use to create code-driven and data-driven tools. - Easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools. - Easy to hack and improve. - Minimize setup and maintenance. - Minimize state storage on user side. - Minimize state synchronization. - Portable, minimize dependencies, run on target (consoles, phones, etc.). - Efficient runtime and memory consumption. Designed primarily for developers and content-creators, not the typical end-user! Some of the current weaknesses (which we aim to address in the future) includes: - Doesn't look fancy. - Limited layout features, intricate layouts are typically crafted in code. CONTROLS GUIDE ============== - MOUSE CONTROLS - Mouse wheel: Scroll vertically. - SHIFT+Mouse wheel: Scroll horizontally. - Click [X]: Close a window, available when 'bool* p_open' is passed to ImGui::Begin(). - Click ^, Double-Click title: Collapse window. - Drag on corner/border: Resize window (double-click to auto fit window to its contents). - Drag on any empty space: Move window (unless io.ConfigWindowsMoveFromTitleBarOnly = true). - Left-click outside popup: Close popup stack (right-click over underlying popup: Partially close popup stack). - TEXT EDITOR - Hold SHIFT or Drag Mouse: Select text. - CTRL+Left/Right: Word jump. - CTRL+Shift+Left/Right: Select words. - CTRL+A or Double-Click: Select All. - CTRL+X, CTRL+C, CTRL+V: Use OS clipboard. - CTRL+Z, CTRL+Y: Undo, Redo. - ESCAPE: Revert text to its original value. - On OSX, controls are automatically adjusted to match standard OSX text editing shortcuts and behaviors. - KEYBOARD CONTROLS - Basic: - Tab, SHIFT+Tab Cycle through text editable fields. - CTRL+Tab, CTRL+Shift+Tab Cycle through windows. - CTRL+Click Input text into a Slider or Drag widget. - Extended features with `io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard`: - Tab, SHIFT+Tab: Cycle through every items. - Arrow keys Move through items using directional navigation. Tweak value. - Arrow keys + Alt, Shift Tweak slower, tweak faster (when using arrow keys). - Enter Activate item (prefer text input when possible). - Space Activate item (prefer tweaking with arrows when possible). - Escape Deactivate item, leave child window, close popup. - Page Up, Page Down Previous page, next page. - Home, End Scroll to top, scroll to bottom. - Alt Toggle between scrolling layer and menu layer. - CTRL+Tab then Ctrl+Arrows Move window. Hold SHIFT to resize instead of moving. - Output when ImGuiConfigFlags_NavEnableKeyboard set, - io.WantCaptureKeyboard flag is set when keyboard is claimed. - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. - io.NavVisible: true when the navigation cursor is visible (usually goes to back false when mouse is used). - GAMEPAD CONTROLS - Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. - Particularly useful to use Dear ImGui on a console system (e.g. PlayStation, Switch, Xbox) without a mouse! - Download controller mapping PNG/PSD at http://dearimgui.com/controls_sheets - Backend support: backend needs to: - Set 'io.BackendFlags |= ImGuiBackendFlags_HasGamepad' + call io.AddKeyEvent/AddKeyAnalogEvent() with ImGuiKey_Gamepad_XXX keys. - For analog values (0.0f to 1.0f), backend is responsible to handling a dead-zone and rescaling inputs accordingly. Backend code will probably need to transform your raw inputs (such as e.g. remapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, etc.). - BEFORE 1.87, BACKENDS USED TO WRITE TO io.NavInputs[]. This is now obsolete. Please call io functions instead! - If you need to share inputs between your game and the Dear ImGui interface, the easiest approach is to go all-or-nothing, with a buttons combo to toggle the target. Please reach out if you think the game vs navigation input sharing could be improved. - REMOTE INPUTS SHARING & MOUSE EMULATION - PS4/PS5 users: Consider emulating a mouse cursor with DualShock touch pad or a spare analog stick as a mouse-emulation fallback. - Consoles/Tablet/Phone users: Consider using a Synergy 1.x server (on your PC) + run examples/libs/synergy/uSynergy.c (on your console/tablet/phone app) in order to share your PC mouse/keyboard. - See https://github.com/ocornut/imgui/wiki/Useful-Extensions#remoting for other remoting solutions. - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiConfigFlags_NavEnableSetMousePos flag. Enabling ImGuiConfigFlags_NavEnableSetMousePos + ImGuiBackendFlags_HasSetMousePos instructs Dear ImGui to move your mouse cursor along with navigation movements. When enabled, the NewFrame() function may alter 'io.MousePos' and set 'io.WantSetMousePos' to notify you that it wants the mouse cursor to be moved. When that happens your backend NEEDS to move the OS or underlying mouse cursor on the next frame. Some of the backends in examples/ do that. (If you set the NavEnableSetMousePos flag but don't honor 'io.WantSetMousePos' properly, Dear ImGui will misbehave as it will see your mouse moving back & forth!) (In a setup when you may not have easy control over the mouse cursor, e.g. uSynergy.c doesn't expose moving remote mouse cursor, you may want to set a boolean to ignore your other external mouse positions until the external source is moved again.) PROGRAMMER GUIDE ================ READ FIRST ---------- - Remember to check the wonderful Wiki (https://github.com/ocornut/imgui/wiki) - Your code creates the UI every frame of your application loop, if your code doesn't run the UI is gone! The UI can be highly dynamic, there are no construction or destruction steps, less superfluous data retention on your side, less state duplication, less state synchronization, fewer bugs. - Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features. Or browse https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html for interactive web version. - The library is designed to be built from sources. Avoid pre-compiled binaries and packaged versions. See imconfig.h to configure your build. - Dear ImGui is an implementation of the IMGUI paradigm (immediate-mode graphical user interface, a term coined by Casey Muratori). You can learn about IMGUI principles at http://www.johno.se/book/imgui.html, http://mollyrocket.com/861 & more links in Wiki. - Dear ImGui is a "single pass" rasterizing implementation of the IMGUI paradigm, aimed at ease of use and high-performances. For every application frame, your UI code will be called only once. This is in contrast to e.g. Unity's implementation of an IMGUI, where the UI code is called multiple times ("multiple passes") from a single entry point. There are pros and cons to both approaches. - Our origin is on the top-left. In axis aligned bounding boxes, Min = top-left, Max = bottom-right. - Please make sure you have asserts enabled (IM_ASSERT redirects to assert() by default, but can be redirected). If you get an assert, read the messages and comments around the assert. - This codebase aims to be highly optimized: - A typical idle frame should never call malloc/free. - We rely on a maximum of constant-time or O(N) algorithms. Limiting searches/scans as much as possible. - We put particular energy in making sure performances are decent with typical "Debug" build settings as well. Which mean we tend to avoid over-relying on "zero-cost abstraction" as they aren't zero-cost at all. - This codebase aims to be both highly opinionated and highly flexible: - This code works because of the things it choose to solve or not solve. - C++: this is a pragmatic C-ish codebase: we don't use fancy C++ features, we don't include C++ headers, and ImGui:: is a namespace. We rarely use member functions (and when we did, I am mostly regretting it now). This is to increase compatibility, increase maintainability and facilitate use from other languages. - C++: ImVec2/ImVec4 do not expose math operators by default, because it is expected that you use your own math types. See FAQ "How can I use my own math types instead of ImVec2/ImVec4?" for details about setting up imconfig.h for that. We can can optionally export math operators for ImVec2/ImVec4 using IMGUI_DEFINE_MATH_OPERATORS, which we use internally. - C++: pay attention that ImVector<> manipulates plain-old-data and does not honor construction/destruction (so don't use ImVector in your code or at our own risk!). - Building: We don't use nor mandate a build system for the main library. This is in an effort to ensure that it works in the real world aka with any esoteric build setup. This is also because providing a build system for the main library would be of little-value. The build problems are almost never coming from the main library but from specific backends. HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI ---------------------------------------------- - Update submodule or copy/overwrite every file. - About imconfig.h: - You may modify your copy of imconfig.h, in this case don't overwrite it. - or you may locally branch to modify imconfig.h and merge/rebase latest. - or you may '#define IMGUI_USER_CONFIG "my_config_file.h"' globally from your build system to specify a custom path for your imconfig.h file and instead not have to modify the default one. - Overwrite all the sources files except for imconfig.h (if you have modified your copy of imconfig.h) - Or maintain your own branch where you have imconfig.h modified as a top-most commit which you can regularly rebase over "master". - You can also use '#define IMGUI_USER_CONFIG "my_config_file.h" to redirect configuration to your own file. - Read the "API BREAKING CHANGES" section (below). This is where we list occasional API breaking changes. If a function/type has been renamed / or marked obsolete, try to fix the name in your code before it is permanently removed from the public API. If you have a problem with a missing function/symbols, search for its name in the code, there will likely be a comment about it. Please report any issue to the GitHub page! - To find out usage of old API, you can add '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' in your configuration file. - Try to keep your copy of Dear ImGui reasonably up to date! GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE --------------------------------------------------------------- - See https://github.com/ocornut/imgui/wiki/Getting-Started. - Run and study the examples and demo in imgui_demo.cpp to get acquainted with the library. - In the majority of cases you should be able to use unmodified backends files available in the backends/ folder. - Add the Dear ImGui source files + selected backend source files to your projects or using your preferred build system. It is recommended you build and statically link the .cpp files as part of your project and NOT as a shared library (DLL). - You can later customize the imconfig.h file to tweak some compile-time behavior, such as integrating Dear ImGui types with your own maths types. - When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them. - Dear ImGui never touches or knows about your GPU state. The only function that knows about GPU is the draw function that you provide. Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases of your own application. All rendering information is stored into command-lists that you will retrieve after calling ImGui::Render(). - Refer to the backends and demo applications in the examples/ folder for instruction on how to setup your code. - If you are running over a standard OS with a common graphics API, you should be able to use unmodified imgui_impl_*** files from the examples/ folder. HOW A SIMPLE APPLICATION MAY LOOK LIKE -------------------------------------- EXHIBIT 1: USING THE EXAMPLE BACKENDS (= imgui_impl_XXX.cpp files from the backends/ folder). The sub-folders in examples/ contain examples applications following this structure. // Application init: create a dear imgui context, setup some options, load fonts ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); // TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls. // TODO: Fill optional fields of the io structure later. // TODO: Load TTF/OTF fonts if you don't want to use the default font. // Initialize helper Platform and Renderer backends (here we are using imgui_impl_win32.cpp and imgui_impl_dx11.cpp) ImGui_ImplWin32_Init(hwnd); ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext); // Application main loop while (true) { // Feed inputs to dear imgui, start new frame ImGui_ImplDX11_NewFrame(); ImGui_ImplWin32_NewFrame(); ImGui::NewFrame(); // Any application code here ImGui::Text("Hello, world!"); // Render dear imgui into screen ImGui::Render(); ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); g_pSwapChain->Present(1, 0); } // Shutdown ImGui_ImplDX11_Shutdown(); ImGui_ImplWin32_Shutdown(); ImGui::DestroyContext(); EXHIBIT 2: IMPLEMENTING CUSTOM BACKEND / CUSTOM ENGINE // Application init: create a dear imgui context, setup some options, load fonts ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); // TODO: Set optional io.ConfigFlags values, e.g. 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard' to enable keyboard controls. // TODO: Fill optional fields of the io structure later. // TODO: Load TTF/OTF fonts if you don't want to use the default font. // Build and load the texture atlas into a texture // (In the examples/ app this is usually done within the ImGui_ImplXXX_Init() function from one of the demo Renderer) int width, height; unsigned char* pixels = nullptr; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // At this point you've got the texture data and you need to upload that to your graphic system: // After we have created the texture, store its pointer/identifier (_in whichever format your engine uses_) in 'io.Fonts->TexID'. // This will be passed back to your via the renderer. Basically ImTextureID == void*. Read FAQ for details about ImTextureID. MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA32) io.Fonts->SetTexID((void*)texture); // Application main loop while (true) { // Setup low-level inputs, e.g. on Win32: calling GetKeyboardState(), or write to those fields from your Windows message handlers, etc. // (In the examples/ app this is usually done within the ImGui_ImplXXX_NewFrame() function from one of the demo Platform Backends) io.DeltaTime = 1.0f/60.0f; // set the time elapsed since the previous frame (in seconds) io.DisplaySize.x = 1920.0f; // set the current display width io.DisplaySize.y = 1280.0f; // set the current display height here io.AddMousePosEvent(mouse_x, mouse_y); // update mouse position io.AddMouseButtonEvent(0, mouse_b[0]); // update mouse button states io.AddMouseButtonEvent(1, mouse_b[1]); // update mouse button states // Call NewFrame(), after this point you can use ImGui::* functions anytime // (So you want to try calling NewFrame() as early as you can in your main loop to be able to use Dear ImGui everywhere) ImGui::NewFrame(); // Most of your application code here ImGui::Text("Hello, world!"); MyGameUpdate(); // may use any Dear ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End(); MyGameRender(); // may use any Dear ImGui functions as well! // Render dear imgui, swap buffers // (You want to try calling EndFrame/Render as late as you can, to be able to use Dear ImGui in your own game rendering code) ImGui::EndFrame(); ImGui::Render(); ImDrawData* draw_data = ImGui::GetDrawData(); MyImGuiRenderFunction(draw_data); SwapBuffers(); } // Shutdown ImGui::DestroyContext(); To decide whether to dispatch mouse/keyboard inputs to Dear ImGui to the rest of your application, you should read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags! Please read the FAQ entry "How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application?" about this. HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE --------------------------------------------- The backends in impl_impl_XXX.cpp files contain many working implementations of a rendering function. void MyImGuiRenderFunction(ImDrawData* draw_data) { // TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled // TODO: Setup texture sampling state: sample with bilinear filtering (NOT point/nearest filtering). Use 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines;' to allow point/nearest filtering. // TODO: Setup viewport covering draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize // TODO: Setup orthographic projection matrix cover draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize // TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragment shader sample color from 1 texture, multiply by vertex color. ImVec2 clip_off = draw_data->DisplayPos; for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; // vertex buffer generated by Dear ImGui const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; // index buffer generated by Dear ImGui for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; if (pcmd->UserCallback) { pcmd->UserCallback(cmd_list, pcmd); } else { // Project scissor/clipping rectangles into framebuffer space ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y); ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y); if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) continue; // We are using scissoring to clip some objects. All low-level graphics API should support it. // - If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches // (some elements visible outside their bounds) but you can fix that once everything else works! // - Clipping coordinates are provided in imgui coordinates space: // - For a given viewport, draw_data->DisplayPos == viewport->Pos and draw_data->DisplaySize == viewport->Size // - In a single viewport application, draw_data->DisplayPos == (0,0) and draw_data->DisplaySize == io.DisplaySize, but always use GetMainViewport()->Pos/Size instead of hardcoding those values. // - In the interest of supporting multi-viewport applications (see 'docking' branch on github), // always subtract draw_data->DisplayPos from clipping bounds to convert them to your viewport space. // - Note that pcmd->ClipRect contains Min+Max bounds. Some graphics API may use Min+Max, other may use Min+Size (size being Max-Min) MyEngineSetScissor(clip_min.x, clip_min.y, clip_max.x, clip_max.y); // The texture for the draw call is specified by pcmd->GetTexID(). // The vast majority of draw calls will use the Dear ImGui texture atlas, which value you have set yourself during initialization. MyEngineBindTexture((MyTexture*)pcmd->GetTexID()); // Render 'pcmd->ElemCount/3' indexed triangles. // By default the indices ImDrawIdx are 16-bit, you can change them to 32-bit in imconfig.h if your engine doesn't support 16-bit indices. MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset, vtx_buffer, pcmd->VtxOffset); } } } } API BREAKING CHANGES ==================== Occasionally introducing changes that are breaking the API. We try to make the breakage minor and easy to fix. Below is a change-log of API breaking changes only. If you are using one of the functions listed, expect to have to fix some code. When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. - 2024/01/15 (1.90.2) - commented out obsolete ImGuiIO::ImeWindowHandle marked obsolete in 1.87, favor of writing to 'void* ImGuiViewport::PlatformHandleRaw'. - 2023/12/19 (1.90.1) - commented out obsolete ImGuiKey_KeyPadEnter redirection to ImGuiKey_KeypadEnter. - 2023/11/06 (1.90.1) - removed CalcListClipping() marked obsolete in 1.86. Prefer using ImGuiListClipper which can return non-contiguous ranges. - 2023/11/05 (1.90.1) - imgui_freetype: commented out ImGuiFreeType::BuildFontAtlas() obsoleted in 1.81. prefer using #define IMGUI_ENABLE_FREETYPE or see commented code for manual calls. - 2023/11/05 (1.90.1) - internals,columns: commented out legacy ImGuiColumnsFlags_XXX symbols redirecting to ImGuiOldColumnsFlags_XXX, obsoleted from imgui_internal.h in 1.80. - 2023/11/09 (1.90.0) - removed IM_OFFSETOF() macro in favor of using offsetof() available in C++11. Kept redirection define (will obsolete). - 2023/11/07 (1.90.0) - removed BeginChildFrame()/EndChildFrame() in favor of using BeginChild() with the ImGuiChildFlags_FrameStyle flag. kept inline redirection function (will obsolete). those functions were merely PushStyle/PopStyle helpers, the removal isn't so much motivated by needing to add the feature in BeginChild(), but by the necessity to avoid BeginChildFrame() signature mismatching BeginChild() signature and features. - 2023/11/02 (1.90.0) - BeginChild: upgraded 'bool border = true' parameter to 'ImGuiChildFlags flags' type, added ImGuiChildFlags_Border equivalent. As with our prior "bool-to-flags" API updates, the ImGuiChildFlags_Border value is guaranteed to be == true forever to ensure a smoother transition, meaning all existing calls will still work. - old: BeginChild("Name", size, true) - new: BeginChild("Name", size, ImGuiChildFlags_Border) - old: BeginChild("Name", size, false) - new: BeginChild("Name", size) or BeginChild("Name", 0) or BeginChild("Name", size, ImGuiChildFlags_None) - 2023/11/02 (1.90.0) - BeginChild: added child-flag ImGuiChildFlags_AlwaysUseWindowPadding as a replacement for the window-flag ImGuiWindowFlags_AlwaysUseWindowPadding: the feature only ever made sense for BeginChild() anyhow. - old: BeginChild("Name", size, 0, ImGuiWindowFlags_AlwaysUseWindowPadding); - new: BeginChild("Name", size, ImGuiChildFlags_AlwaysUseWindowPadding, 0); - 2023/09/27 (1.90.0) - io: removed io.MetricsActiveAllocations introduced in 1.63. Same as 'g.DebugMemAllocCount - g.DebugMemFreeCount' (still displayed in Metrics, unlikely to be accessed by end-user). - 2023/09/26 (1.90.0) - debug tools: Renamed ShowStackToolWindow() ("Stack Tool") to ShowIDStackToolWindow() ("ID Stack Tool"), as earlier name was misleading. Kept inline redirection function. (#4631) - 2023/09/15 (1.90.0) - ListBox, Combo: changed signature of "name getter" callback in old one-liner ListBox()/Combo() apis. kept inline redirection function (will obsolete). - old: bool Combo(const char* label, int* current_item, bool (*getter)(void* user_data, int idx, const char** out_text), ...) - new: bool Combo(const char* label, int* current_item, const char* (*getter)(void* user_data, int idx), ...); - old: bool ListBox(const char* label, int* current_item, bool (*getting)(void* user_data, int idx, const char** out_text), ...); - new: bool ListBox(const char* label, int* current_item, const char* (*getter)(void* user_data, int idx), ...); - 2023/09/08 (1.90.0) - commented out obsolete redirecting functions: - GetWindowContentRegionWidth() -> use GetWindowContentRegionMax().x - GetWindowContentRegionMin().x. Consider that generally 'GetContentRegionAvail().x' is more useful. - ImDrawCornerFlags_XXX -> use ImDrawFlags_RoundCornersXXX flags. Read 1.82 Changelog for details + grep commented names in sources. - commented out runtime support for hardcoded ~0 or 0x01..0x0F rounding flags values for AddRect()/AddRectFilled()/PathRect()/AddImageRounded() -> use ImDrawFlags_RoundCornersXXX flags. Read 1.82 Changelog for details - 2023/08/25 (1.89.9) - clipper: Renamed IncludeRangeByIndices() (also called ForceDisplayRangeByIndices() before 1.89.6) to IncludeItemsByIndex(). Kept inline redirection function. Sorry! - 2023/07/12 (1.89.8) - ImDrawData: CmdLists now owned, changed from ImDrawList** to ImVector. Majority of users shouldn't be affected, but you cannot compare to NULL nor reassign manually anymore. Instead use AddDrawList(). (#6406, #4879, #1878) - 2023/06/28 (1.89.7) - overlapping items: obsoleted 'SetItemAllowOverlap()' (called after item) in favor of calling 'SetNextItemAllowOverlap()' (called before item). 'SetItemAllowOverlap()' didn't and couldn't work reliably since 1.89 (2022-11-15). - 2023/06/28 (1.89.7) - overlapping items: renamed 'ImGuiTreeNodeFlags_AllowItemOverlap' to 'ImGuiTreeNodeFlags_AllowOverlap', 'ImGuiSelectableFlags_AllowItemOverlap' to 'ImGuiSelectableFlags_AllowOverlap'. Kept redirecting enums (will obsolete). - 2023/06/28 (1.89.7) - overlapping items: IsItemHovered() now by default return false when querying an item using AllowOverlap mode which is being overlapped. Use ImGuiHoveredFlags_AllowWhenOverlappedByItem to revert to old behavior. - 2023/06/28 (1.89.7) - overlapping items: Selectable and TreeNode don't allow overlap when active so overlapping widgets won't appear as hovered. While this fixes a common small visual issue, it also means that calling IsItemHovered() after a non-reactive elements - e.g. Text() - overlapping an active one may fail if you don't use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem). (#6610) - 2023/06/20 (1.89.7) - moved io.HoverDelayShort/io.HoverDelayNormal to style.HoverDelayShort/style.HoverDelayNormal. As the fields were added in 1.89 and expected to be left unchanged by most users, or only tweaked once during app initialization, we are exceptionally accepting the breakage. - 2023/05/30 (1.89.6) - backends: renamed "imgui_impl_sdlrenderer.cpp" to "imgui_impl_sdlrenderer2.cpp" and "imgui_impl_sdlrenderer.h" to "imgui_impl_sdlrenderer2.h". This is in prevision for the future release of SDL3. - 2023/05/22 (1.89.6) - listbox: commented out obsolete/redirecting functions that were marked obsolete more than two years ago: - ListBoxHeader() -> use BeginListBox() (note how two variants of ListBoxHeader() existed. Check commented versions in imgui.h for reference) - ListBoxFooter() -> use EndListBox() - 2023/05/15 (1.89.6) - clipper: commented out obsolete redirection constructor 'ImGuiListClipper(int items_count, float items_height = -1.0f)' that was marked obsolete in 1.79. Use default constructor + clipper.Begin(). - 2023/05/15 (1.89.6) - clipper: renamed ImGuiListClipper::ForceDisplayRangeByIndices() to ImGuiListClipper::IncludeRangeByIndices(). - 2023/03/14 (1.89.4) - commented out redirecting enums/functions names that were marked obsolete two years ago: - ImGuiSliderFlags_ClampOnInput -> use ImGuiSliderFlags_AlwaysClamp - ImGuiInputTextFlags_AlwaysInsertMode -> use ImGuiInputTextFlags_AlwaysOverwrite - ImDrawList::AddBezierCurve() -> use ImDrawList::AddBezierCubic() - ImDrawList::PathBezierCurveTo() -> use ImDrawList::PathBezierCubicCurveTo() - 2023/03/09 (1.89.4) - renamed PushAllowKeyboardFocus()/PopAllowKeyboardFocus() to PushTabStop()/PopTabStop(). Kept inline redirection functions (will obsolete). - 2023/03/09 (1.89.4) - tooltips: Added 'bool' return value to BeginTooltip() for API consistency. Please only submit contents and call EndTooltip() if BeginTooltip() returns true. In reality the function will _currently_ always return true, but further changes down the line may change this, best to clarify API sooner. - 2023/02/15 (1.89.4) - moved the optional "courtesy maths operators" implementation from imgui_internal.h in imgui.h. Even though we encourage using your own maths types and operators by setting up IM_VEC2_CLASS_EXTRA, it has been frequently requested by people to use our own. We had an opt-in define which was previously fulfilled in imgui_internal.h. It is now fulfilled in imgui.h. (#6164) - OK: #define IMGUI_DEFINE_MATH_OPERATORS / #include "imgui.h" / #include "imgui_internal.h" - Error: #include "imgui.h" / #define IMGUI_DEFINE_MATH_OPERATORS / #include "imgui_internal.h" - 2023/02/07 (1.89.3) - backends: renamed "imgui_impl_sdl.cpp" to "imgui_impl_sdl2.cpp" and "imgui_impl_sdl.h" to "imgui_impl_sdl2.h". (#6146) This is in prevision for the future release of SDL3. - 2022/10/26 (1.89) - commented out redirecting OpenPopupContextItem() which was briefly the name of OpenPopupOnItemClick() from 1.77 to 1.79. - 2022/10/12 (1.89) - removed runtime patching of invalid "%f"/"%0.f" format strings for DragInt()/SliderInt(). This was obsoleted in 1.61 (May 2018). See 1.61 changelog for details. - 2022/09/26 (1.89) - renamed and merged keyboard modifiers key enums and flags into a same set. Kept inline redirection enums (will obsolete). - ImGuiKey_ModCtrl and ImGuiModFlags_Ctrl -> ImGuiMod_Ctrl - ImGuiKey_ModShift and ImGuiModFlags_Shift -> ImGuiMod_Shift - ImGuiKey_ModAlt and ImGuiModFlags_Alt -> ImGuiMod_Alt - ImGuiKey_ModSuper and ImGuiModFlags_Super -> ImGuiMod_Super the ImGuiKey_ModXXX were introduced in 1.87 and mostly used by backends. the ImGuiModFlags_XXX have been exposed in imgui.h but not really used by any public api only by third-party extensions. exceptionally commenting out the older ImGuiKeyModFlags_XXX names ahead of obsolescence schedule to reduce confusion and because they were not meant to be used anyway. - 2022/09/20 (1.89) - ImGuiKey is now a typed enum, allowing ImGuiKey_XXX symbols to be named in debuggers. this will require uses of legacy backend-dependent indices to be casted, e.g. - with imgui_impl_glfw: IsKeyPressed(GLFW_KEY_A) -> IsKeyPressed((ImGuiKey)GLFW_KEY_A); - with imgui_impl_win32: IsKeyPressed('A') -> IsKeyPressed((ImGuiKey)'A') - etc. However if you are upgrading code you might well use the better, backend-agnostic IsKeyPressed(ImGuiKey_A) now! - 2022/09/12 (1.89) - removed the bizarre legacy default argument for 'TreePush(const void* ptr = NULL)', always pass a pointer value explicitly. NULL/nullptr is ok but require cast, e.g. TreePush((void*)nullptr); - 2022/09/05 (1.89) - commented out redirecting functions/enums names that were marked obsolete in 1.77 and 1.78 (June 2020): - DragScalar(), DragScalarN(), DragFloat(), DragFloat2(), DragFloat3(), DragFloat4(): For old signatures ending with (..., const char* format, float power = 1.0f) -> use (..., format ImGuiSliderFlags_Logarithmic) if power != 1.0f. - SliderScalar(), SliderScalarN(), SliderFloat(), SliderFloat2(), SliderFloat3(), SliderFloat4(): For old signatures ending with (..., const char* format, float power = 1.0f) -> use (..., format ImGuiSliderFlags_Logarithmic) if power != 1.0f. - BeginPopupContextWindow(const char*, ImGuiMouseButton, bool) -> use BeginPopupContextWindow(const char*, ImGuiPopupFlags) - 2022/09/02 (1.89) - obsoleted using SetCursorPos()/SetCursorScreenPos() to extend parent window/cell boundaries. this relates to when moving the cursor position beyond current boundaries WITHOUT submitting an item. - previously this would make the window content size ~200x200: Begin(...) + SetCursorScreenPos(GetCursorScreenPos() + ImVec2(200,200)) + End(); - instead, please submit an item: Begin(...) + SetCursorScreenPos(GetCursorScreenPos() + ImVec2(200,200)) + Dummy(ImVec2(0,0)) + End(); - alternative: Begin(...) + Dummy(ImVec2(200,200)) + End(); - content size is now only extended when submitting an item! - with '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' this will now be detected and assert. - without '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' this will silently be fixed until we obsolete it. - 2022/08/03 (1.89) - changed signature of ImageButton() function. Kept redirection function (will obsolete). - added 'const char* str_id' parameter + removed 'int frame_padding = -1' parameter. - old signature: bool ImageButton(ImTextureID tex_id, ImVec2 size, ImVec2 uv0 = ImVec2(0,0), ImVec2 uv1 = ImVec2(1,1), int frame_padding = -1, ImVec4 bg_col = ImVec4(0,0,0,0), ImVec4 tint_col = ImVec4(1,1,1,1)); - used the ImTextureID value to create an ID. This was inconsistent with other functions, led to ID conflicts, and caused problems with engines using transient ImTextureID values. - had a FramePadding override which was inconsistent with other functions and made the already-long signature even longer. - new signature: bool ImageButton(const char* str_id, ImTextureID tex_id, ImVec2 size, ImVec2 uv0 = ImVec2(0,0), ImVec2 uv1 = ImVec2(1,1), ImVec4 bg_col = ImVec4(0,0,0,0), ImVec4 tint_col = ImVec4(1,1,1,1)); - requires an explicit identifier. You may still use e.g. PushID() calls and then pass an empty identifier. - always uses style.FramePadding for padding, to be consistent with other buttons. You may use PushStyleVar() to alter this. - 2022/07/08 (1.89) - inputs: removed io.NavInputs[] and ImGuiNavInput enum (following 1.87 changes). - Official backends from 1.87+ -> no issue. - Official backends from 1.60 to 1.86 -> will build and convert gamepad inputs, unless IMGUI_DISABLE_OBSOLETE_KEYIO is defined. Need updating! - Custom backends not writing to io.NavInputs[] -> no issue. - Custom backends writing to io.NavInputs[] -> will build and convert gamepad inputs, unless IMGUI_DISABLE_OBSOLETE_KEYIO is defined. Need fixing! - TL;DR: Backends should call io.AddKeyEvent()/io.AddKeyAnalogEvent() with ImGuiKey_GamepadXXX values instead of filling io.NavInput[]. - 2022/06/15 (1.88) - renamed IMGUI_DISABLE_METRICS_WINDOW to IMGUI_DISABLE_DEBUG_TOOLS for correctness. kept support for old define (will obsolete). - 2022/05/03 (1.88) - backends: osx: removed ImGui_ImplOSX_HandleEvent() from backend API in favor of backend automatically handling event capture. All ImGui_ImplOSX_HandleEvent() calls should be removed as they are now unnecessary. - 2022/04/05 (1.88) - inputs: renamed ImGuiKeyModFlags to ImGuiModFlags. Kept inline redirection enums (will obsolete). This was never used in public API functions but technically present in imgui.h and ImGuiIO. - 2022/01/20 (1.87) - inputs: reworded gamepad IO. - Backend writing to io.NavInputs[] -> backend should call io.AddKeyEvent()/io.AddKeyAnalogEvent() with ImGuiKey_GamepadXXX values. - 2022/01/19 (1.87) - sliders, drags: removed support for legacy arithmetic operators (+,+-,*,/) when inputing text. This doesn't break any api/code but a feature that used to be accessible by end-users (which seemingly no one used). - 2022/01/17 (1.87) - inputs: reworked mouse IO. - Backend writing to io.MousePos -> backend should call io.AddMousePosEvent() - Backend writing to io.MouseDown[] -> backend should call io.AddMouseButtonEvent() - Backend writing to io.MouseWheel -> backend should call io.AddMouseWheelEvent() - Backend writing to io.MouseHoveredViewport -> backend should call io.AddMouseViewportEvent() [Docking branch w/ multi-viewports only] note: for all calls to IO new functions, the Dear ImGui context should be bound/current. read https://github.com/ocornut/imgui/issues/4921 for details. - 2022/01/10 (1.87) - inputs: reworked keyboard IO. Removed io.KeyMap[], io.KeysDown[] in favor of calling io.AddKeyEvent(). Removed GetKeyIndex(), now unecessary. All IsKeyXXX() functions now take ImGuiKey values. All features are still functional until IMGUI_DISABLE_OBSOLETE_KEYIO is defined. Read Changelog and Release Notes for details. - IsKeyPressed(MY_NATIVE_KEY_XXX) -> use IsKeyPressed(ImGuiKey_XXX) - IsKeyPressed(GetKeyIndex(ImGuiKey_XXX)) -> use IsKeyPressed(ImGuiKey_XXX) - Backend writing to io.KeyMap[],io.KeysDown[] -> backend should call io.AddKeyEvent() (+ call io.SetKeyEventNativeData() if you want legacy user code to stil function with legacy key codes). - Backend writing to io.KeyCtrl, io.KeyShift.. -> backend should call io.AddKeyEvent() with ImGuiMod_XXX values. *IF YOU PULLED CODE BETWEEN 2021/01/10 and 2021/01/27: We used to have a io.AddKeyModsEvent() function which was now replaced by io.AddKeyEvent() with ImGuiMod_XXX values.* - one case won't work with backward compatibility: if your custom backend used ImGuiKey as mock native indices (e.g. "io.KeyMap[ImGuiKey_A] = ImGuiKey_A") because those values are now larger than the legacy KeyDown[] array. Will assert. - inputs: added ImGuiKey_ModCtrl/ImGuiKey_ModShift/ImGuiKey_ModAlt/ImGuiKey_ModSuper values to submit keyboard modifiers using io.AddKeyEvent(), instead of writing directly to io.KeyCtrl, io.KeyShift, io.KeyAlt, io.KeySuper. - 2022/01/05 (1.87) - inputs: renamed ImGuiKey_KeyPadEnter to ImGuiKey_KeypadEnter to align with new symbols. Kept redirection enum. - 2022/01/05 (1.87) - removed io.ImeSetInputScreenPosFn() in favor of more flexible io.SetPlatformImeDataFn(). Removed 'void* io.ImeWindowHandle' in favor of writing to 'void* ImGuiViewport::PlatformHandleRaw'. - 2022/01/01 (1.87) - commented out redirecting functions/enums names that were marked obsolete in 1.69, 1.70, 1.71, 1.72 (March-July 2019) - ImGui::SetNextTreeNodeOpen() -> use ImGui::SetNextItemOpen() - ImGui::GetContentRegionAvailWidth() -> use ImGui::GetContentRegionAvail().x - ImGui::TreeAdvanceToLabelPos() -> use ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetTreeNodeToLabelSpacing()); - ImFontAtlas::CustomRect -> use ImFontAtlasCustomRect - ImGuiColorEditFlags_RGB/HSV/HEX -> use ImGuiColorEditFlags_DisplayRGB/HSV/Hex - 2021/12/20 (1.86) - backends: removed obsolete Marmalade backend (imgui_impl_marmalade.cpp) + example. Find last supported version at https://github.com/ocornut/imgui/wiki/Bindings - 2021/11/04 (1.86) - removed CalcListClipping() function. Prefer using ImGuiListClipper which can return non-contiguous ranges. Please open an issue if you think you really need this function. - 2021/08/23 (1.85) - removed GetWindowContentRegionWidth() function. keep inline redirection helper. can use 'GetWindowContentRegionMax().x - GetWindowContentRegionMin().x' instead for generally 'GetContentRegionAvail().x' is more useful. - 2021/07/26 (1.84) - commented out redirecting functions/enums names that were marked obsolete in 1.67 and 1.69 (March 2019): - ImGui::GetOverlayDrawList() -> use ImGui::GetForegroundDrawList() - ImFont::GlyphRangesBuilder -> use ImFontGlyphRangesBuilder - 2021/05/19 (1.83) - backends: obsoleted direct access to ImDrawCmd::TextureId in favor of calling ImDrawCmd::GetTexID(). - if you are using official backends from the source tree: you have nothing to do. - if you have copied old backend code or using your own: change access to draw_cmd->TextureId to draw_cmd->GetTexID(). - 2021/03/12 (1.82) - upgraded ImDrawList::AddRect(), AddRectFilled(), PathRect() to use ImDrawFlags instead of ImDrawCornersFlags. - ImDrawCornerFlags_TopLeft -> use ImDrawFlags_RoundCornersTopLeft - ImDrawCornerFlags_BotRight -> use ImDrawFlags_RoundCornersBottomRight - ImDrawCornerFlags_None -> use ImDrawFlags_RoundCornersNone etc. flags now sanely defaults to 0 instead of 0x0F, consistent with all other flags in the API. breaking: the default with rounding > 0.0f is now "round all corners" vs old implicit "round no corners": - rounding == 0.0f + flags == 0 --> meant no rounding --> unchanged (common use) - rounding > 0.0f + flags != 0 --> meant rounding --> unchanged (common use) - rounding == 0.0f + flags != 0 --> meant no rounding --> unchanged (unlikely use) - rounding > 0.0f + flags == 0 --> meant no rounding --> BREAKING (unlikely use): will now round all corners --> use ImDrawFlags_RoundCornersNone or rounding == 0.0f. this ONLY matters for hard coded use of 0 + rounding > 0.0f. Use of named ImDrawFlags_RoundCornersNone (new) or ImDrawCornerFlags_None (old) are ok. the old ImDrawCornersFlags used awkward default values of ~0 or 0xF (4 lower bits set) to signify "round all corners" and we sometimes encouraged using them as shortcuts. legacy path still support use of hard coded ~0 or any value from 0x1 or 0xF. They will behave the same with legacy paths enabled (will assert otherwise). - 2021/03/11 (1.82) - removed redirecting functions/enums names that were marked obsolete in 1.66 (September 2018): - ImGui::SetScrollHere() -> use ImGui::SetScrollHereY() - 2021/03/11 (1.82) - clarified that ImDrawList::PathArcTo(), ImDrawList::PathArcToFast() won't render with radius < 0.0f. Previously it sorts of accidentally worked but would generally lead to counter-clockwise paths and have an effect on anti-aliasing. - 2021/03/10 (1.82) - upgraded ImDrawList::AddPolyline() and PathStroke() "bool closed" parameter to "ImDrawFlags flags". The matching ImDrawFlags_Closed value is guaranteed to always stay == 1 in the future. - 2021/02/22 (1.82) - (*undone in 1.84*) win32+mingw: Re-enabled IME functions by default even under MinGW. In July 2016, issue #738 had me incorrectly disable those default functions for MinGW. MinGW users should: either link with -limm32, either set their imconfig file with '#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS'. - 2021/02/17 (1.82) - renamed rarely used style.CircleSegmentMaxError (old default = 1.60f) to style.CircleTessellationMaxError (new default = 0.30f) as the meaning of the value changed. - 2021/02/03 (1.81) - renamed ListBoxHeader(const char* label, ImVec2 size) to BeginListBox(). Kept inline redirection function (will obsolete). - removed ListBoxHeader(const char* label, int items_count, int height_in_items = -1) in favor of specifying size. Kept inline redirection function (will obsolete). - renamed ListBoxFooter() to EndListBox(). Kept inline redirection function (will obsolete). - 2021/01/26 (1.81) - removed ImGuiFreeType::BuildFontAtlas(). Kept inline redirection function. Prefer using '#define IMGUI_ENABLE_FREETYPE', but there's a runtime selection path available too. The shared extra flags parameters (very rarely used) are now stored in ImFontAtlas::FontBuilderFlags. - renamed ImFontConfig::RasterizerFlags (used by FreeType) to ImFontConfig::FontBuilderFlags. - renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API. - 2020/10/12 (1.80) - removed redirecting functions/enums that were marked obsolete in 1.63 (August 2018): - ImGui::IsItemDeactivatedAfterChange() -> use ImGui::IsItemDeactivatedAfterEdit(). - ImGuiCol_ModalWindowDarkening -> use ImGuiCol_ModalWindowDimBg - ImGuiInputTextCallback -> use ImGuiTextEditCallback - ImGuiInputTextCallbackData -> use ImGuiTextEditCallbackData - 2020/12/21 (1.80) - renamed ImDrawList::AddBezierCurve() to AddBezierCubic(), and PathBezierCurveTo() to PathBezierCubicCurveTo(). Kept inline redirection function (will obsolete). - 2020/12/04 (1.80) - added imgui_tables.cpp file! Manually constructed project files will need the new file added! - 2020/11/18 (1.80) - renamed undocumented/internals ImGuiColumnsFlags_* to ImGuiOldColumnFlags_* in prevision of incoming Tables API. - 2020/11/03 (1.80) - renamed io.ConfigWindowsMemoryCompactTimer to io.ConfigMemoryCompactTimer as the feature will apply to other data structures - 2020/10/14 (1.80) - backends: moved all backends files (imgui_impl_XXXX.cpp, imgui_impl_XXXX.h) from examples/ to backends/. - 2020/10/12 (1.80) - removed redirecting functions/enums that were marked obsolete in 1.60 (April 2018): - io.RenderDrawListsFn pointer -> use ImGui::GetDrawData() value and call the render function of your backend - ImGui::IsAnyWindowFocused() -> use ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow) - ImGui::IsAnyWindowHovered() -> use ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow) - ImGuiStyleVar_Count_ -> use ImGuiStyleVar_COUNT - ImGuiMouseCursor_Count_ -> use ImGuiMouseCursor_COUNT - removed redirecting functions names that were marked obsolete in 1.61 (May 2018): - InputFloat (... int decimal_precision ...) -> use InputFloat (... const char* format ...) with format = "%.Xf" where X is your value for decimal_precision. - same for InputFloat2()/InputFloat3()/InputFloat4() variants taking a `int decimal_precision` parameter. - 2020/10/05 (1.79) - removed ImGuiListClipper: Renamed constructor parameters which created an ambiguous alternative to using the ImGuiListClipper::Begin() function, with misleading edge cases (note: imgui_memory_editor <0.40 from imgui_club/ used this old clipper API. Update your copy if needed). - 2020/09/25 (1.79) - renamed ImGuiSliderFlags_ClampOnInput to ImGuiSliderFlags_AlwaysClamp. Kept redirection enum (will obsolete sooner because previous name was added recently). - 2020/09/25 (1.79) - renamed style.TabMinWidthForUnselectedCloseButton to style.TabMinWidthForCloseButton. - 2020/09/21 (1.79) - renamed OpenPopupContextItem() back to OpenPopupOnItemClick(), reverting the change from 1.77. For varieties of reason this is more self-explanatory. - 2020/09/21 (1.79) - removed return value from OpenPopupOnItemClick() - returned true on mouse release on an item - because it is inconsistent with other popup APIs and makes others misleading. It's also and unnecessary: you can use IsWindowAppearing() after BeginPopup() for a similar result. - 2020/09/17 (1.79) - removed ImFont::DisplayOffset in favor of ImFontConfig::GlyphOffset. DisplayOffset was applied after scaling and not very meaningful/useful outside of being needed by the default ProggyClean font. If you scaled this value after calling AddFontDefault(), this is now done automatically. It was also getting in the way of better font scaling, so let's get rid of it now! - 2020/08/17 (1.78) - obsoleted use of the trailing 'float power=1.0f' parameter for DragFloat(), DragFloat2(), DragFloat3(), DragFloat4(), DragFloatRange2(), DragScalar(), DragScalarN(), SliderFloat(), SliderFloat2(), SliderFloat3(), SliderFloat4(), SliderScalar(), SliderScalarN(), VSliderFloat() and VSliderScalar(). replaced the 'float power=1.0f' argument with integer-based flags defaulting to 0 (as with all our flags). worked out a backward-compatibility scheme so hopefully most C++ codebase should not be affected. in short, when calling those functions: - if you omitted the 'power' parameter (likely!), you are not affected. - if you set the 'power' parameter to 1.0f (same as previous default value): 1/ your compiler may warn on float>int conversion, 2/ everything else will work. 3/ you can replace the 1.0f value with 0 to fix the warning, and be technically correct. - if you set the 'power' parameter to >1.0f (to enable non-linear editing): 1/ your compiler may warn on float>int conversion, 2/ code will assert at runtime, 3/ in case asserts are disabled, the code will not crash and enable the _Logarithmic flag. 4/ you can replace the >1.0f value with ImGuiSliderFlags_Logarithmic to fix the warning/assert and get a _similar_ effect as previous uses of power >1.0f. see https://github.com/ocornut/imgui/issues/3361 for all details. kept inline redirection functions (will obsolete) apart for: DragFloatRange2(), VSliderFloat(), VSliderScalar(). For those three the 'float power=1.0f' version was removed directly as they were most unlikely ever used. for shared code, you can version check at compile-time with `#if IMGUI_VERSION_NUM >= 17704`. - obsoleted use of v_min > v_max in DragInt, DragFloat, DragScalar to lock edits (introduced in 1.73, was not demoed nor documented very), will be replaced by a more generic ReadOnly feature. You may use the ImGuiSliderFlags_ReadOnly internal flag in the meantime. - 2020/06/23 (1.77) - removed BeginPopupContextWindow(const char*, int mouse_button, bool also_over_items) in favor of BeginPopupContextWindow(const char*, ImGuiPopupFlags flags) with ImGuiPopupFlags_NoOverItems. - 2020/06/15 (1.77) - renamed OpenPopupOnItemClick() to OpenPopupContextItem(). Kept inline redirection function (will obsolete). [NOTE: THIS WAS REVERTED IN 1.79] - 2020/06/15 (1.77) - removed CalcItemRectClosestPoint() entry point which was made obsolete and asserting in December 2017. - 2020/04/23 (1.77) - removed unnecessary ID (first arg) of ImFontAtlas::AddCustomRectRegular(). - 2020/01/22 (1.75) - ImDrawList::AddCircle()/AddCircleFilled() functions don't accept negative radius any more. - 2019/12/17 (1.75) - [undid this change in 1.76] made Columns() limited to 64 columns by asserting above that limit. While the current code technically supports it, future code may not so we're putting the restriction ahead. - 2019/12/13 (1.75) - [imgui_internal.h] changed ImRect() default constructor initializes all fields to 0.0f instead of (FLT_MAX,FLT_MAX,-FLT_MAX,-FLT_MAX). If you used ImRect::Add() to create bounding boxes by adding multiple points into it, you may need to fix your initial value. - 2019/12/08 (1.75) - removed redirecting functions/enums that were marked obsolete in 1.53 (December 2017): - ShowTestWindow() -> use ShowDemoWindow() - IsRootWindowFocused() -> use IsWindowFocused(ImGuiFocusedFlags_RootWindow) - IsRootWindowOrAnyChildFocused() -> use IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) - SetNextWindowContentWidth(w) -> use SetNextWindowContentSize(ImVec2(w, 0.0f) - GetItemsLineHeightWithSpacing() -> use GetFrameHeightWithSpacing() - ImGuiCol_ChildWindowBg -> use ImGuiCol_ChildBg - ImGuiStyleVar_ChildWindowRounding -> use ImGuiStyleVar_ChildRounding - ImGuiTreeNodeFlags_AllowOverlapMode -> use ImGuiTreeNodeFlags_AllowItemOverlap - IMGUI_DISABLE_TEST_WINDOWS -> use IMGUI_DISABLE_DEMO_WINDOWS - 2019/12/08 (1.75) - obsoleted calling ImDrawList::PrimReserve() with a negative count (which was vaguely documented and rarely if ever used). Instead, we added an explicit PrimUnreserve() API. - 2019/12/06 (1.75) - removed implicit default parameter to IsMouseDragging(int button = 0) to be consistent with other mouse functions (none of the other functions have it). - 2019/11/21 (1.74) - ImFontAtlas::AddCustomRectRegular() now requires an ID larger than 0x110000 (instead of 0x10000) to conform with supporting Unicode planes 1-16 in a future update. ID below 0x110000 will now assert. - 2019/11/19 (1.74) - renamed IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS to IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS for consistency. - 2019/11/19 (1.74) - renamed IMGUI_DISABLE_MATH_FUNCTIONS to IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS for consistency. - 2019/10/22 (1.74) - removed redirecting functions/enums that were marked obsolete in 1.52 (October 2017): - Begin() [old 5 args version] -> use Begin() [3 args], use SetNextWindowSize() SetNextWindowBgAlpha() if needed - IsRootWindowOrAnyChildHovered() -> use IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows) - AlignFirstTextHeightToWidgets() -> use AlignTextToFramePadding() - SetNextWindowPosCenter() -> use SetNextWindowPos() with a pivot of (0.5f, 0.5f) - ImFont::Glyph -> use ImFontGlyph - 2019/10/14 (1.74) - inputs: Fixed a miscalculation in the keyboard/mouse "typematic" repeat delay/rate calculation, used by keys and e.g. repeating mouse buttons as well as the GetKeyPressedAmount() function. if you were using a non-default value for io.KeyRepeatRate (previous default was 0.250), you can add +io.KeyRepeatDelay to it to compensate for the fix. The function was triggering on: 0.0 and (delay+rate*N) where (N>=1). Fixed formula responds to (N>=0). Effectively it made io.KeyRepeatRate behave like it was set to (io.KeyRepeatRate + io.KeyRepeatDelay). If you never altered io.KeyRepeatRate nor used GetKeyPressedAmount() this won't affect you. - 2019/07/15 (1.72) - removed TreeAdvanceToLabelPos() which is rarely used and only does SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()). Kept redirection function (will obsolete). - 2019/07/12 (1.72) - renamed ImFontAtlas::CustomRect to ImFontAtlasCustomRect. Kept redirection typedef (will obsolete). - 2019/06/14 (1.72) - removed redirecting functions/enums names that were marked obsolete in 1.51 (June 2017): ImGuiCol_Column*, ImGuiSetCond_*, IsItemHoveredRect(), IsPosHoveringAnyWindow(), IsMouseHoveringAnyWindow(), IsMouseHoveringWindow(), IMGUI_ONCE_UPON_A_FRAME. Grep this log for details and new names, or see how they were implemented until 1.71. - 2019/06/07 (1.71) - rendering of child window outer decorations (bg color, border, scrollbars) is now performed as part of the parent window. If you have overlapping child windows in a same parent, and relied on their relative z-order to be mapped to their submission order, this will affect your rendering. This optimization is disabled if the parent window has no visual output, because it appears to be the most common situation leading to the creation of overlapping child windows. Please reach out if you are affected. - 2019/05/13 (1.71) - renamed SetNextTreeNodeOpen() to SetNextItemOpen(). Kept inline redirection function (will obsolete). - 2019/05/11 (1.71) - changed io.AddInputCharacter(unsigned short c) signature to io.AddInputCharacter(unsigned int c). - 2019/04/29 (1.70) - improved ImDrawList thick strokes (>1.0f) preserving correct thickness up to 90 degrees angles (e.g. rectangles). If you have custom rendering using thick lines, they will appear thicker now. - 2019/04/29 (1.70) - removed GetContentRegionAvailWidth(), use GetContentRegionAvail().x instead. Kept inline redirection function (will obsolete). - 2019/03/04 (1.69) - renamed GetOverlayDrawList() to GetForegroundDrawList(). Kept redirection function (will obsolete). - 2019/02/26 (1.69) - renamed ImGuiColorEditFlags_RGB/ImGuiColorEditFlags_HSV/ImGuiColorEditFlags_HEX to ImGuiColorEditFlags_DisplayRGB/ImGuiColorEditFlags_DisplayHSV/ImGuiColorEditFlags_DisplayHex. Kept redirection enums (will obsolete). - 2019/02/14 (1.68) - made it illegal/assert when io.DisplayTime == 0.0f (with an exception for the first frame). If for some reason your time step calculation gives you a zero value, replace it with an arbitrarily small value! - 2019/02/01 (1.68) - removed io.DisplayVisibleMin/DisplayVisibleMax (which were marked obsolete and removed from viewport/docking branch already). - 2019/01/06 (1.67) - renamed io.InputCharacters[], marked internal as was always intended. Please don't access directly, and use AddInputCharacter() instead! - 2019/01/06 (1.67) - renamed ImFontAtlas::GlyphRangesBuilder to ImFontGlyphRangesBuilder. Kept redirection typedef (will obsolete). - 2018/12/20 (1.67) - made it illegal to call Begin("") with an empty string. This somehow half-worked before but had various undesirable side-effects. - 2018/12/10 (1.67) - renamed io.ConfigResizeWindowsFromEdges to io.ConfigWindowsResizeFromEdges as we are doing a large pass on configuration flags. - 2018/10/12 (1.66) - renamed misc/stl/imgui_stl.* to misc/cpp/imgui_stdlib.* in prevision for other C++ helper files. - 2018/09/28 (1.66) - renamed SetScrollHere() to SetScrollHereY(). Kept redirection function (will obsolete). - 2018/09/06 (1.65) - renamed stb_truetype.h to imstb_truetype.h, stb_textedit.h to imstb_textedit.h, and stb_rect_pack.h to imstb_rectpack.h. If you were conveniently using the imgui copy of those STB headers in your project you will have to update your include paths. - 2018/09/05 (1.65) - renamed io.OptCursorBlink/io.ConfigCursorBlink to io.ConfigInputTextCursorBlink. (#1427) - 2018/08/31 (1.64) - added imgui_widgets.cpp file, extracted and moved widgets code out of imgui.cpp into imgui_widgets.cpp. Re-ordered some of the code remaining in imgui.cpp. NONE OF THE FUNCTIONS HAVE CHANGED. THE CODE IS SEMANTICALLY 100% IDENTICAL, BUT _EVERY_ FUNCTION HAS BEEN MOVED. Because of this, any local modifications to imgui.cpp will likely conflict when you update. Read docs/CHANGELOG.txt for suggestions. - 2018/08/22 (1.63) - renamed IsItemDeactivatedAfterChange() to IsItemDeactivatedAfterEdit() for consistency with new IsItemEdited() API. Kept redirection function (will obsolete soonish as IsItemDeactivatedAfterChange() is very recent). - 2018/08/21 (1.63) - renamed ImGuiTextEditCallback to ImGuiInputTextCallback, ImGuiTextEditCallbackData to ImGuiInputTextCallbackData for consistency. Kept redirection types (will obsolete). - 2018/08/21 (1.63) - removed ImGuiInputTextCallbackData::ReadOnly since it is a duplication of (ImGuiInputTextCallbackData::Flags & ImGuiInputTextFlags_ReadOnly). - 2018/08/01 (1.63) - removed per-window ImGuiWindowFlags_ResizeFromAnySide beta flag in favor of a global io.ConfigResizeWindowsFromEdges [update 1.67 renamed to ConfigWindowsResizeFromEdges] to enable the feature. - 2018/08/01 (1.63) - renamed io.OptCursorBlink to io.ConfigCursorBlink [-> io.ConfigInputTextCursorBlink in 1.65], io.OptMacOSXBehaviors to ConfigMacOSXBehaviors for consistency. - 2018/07/22 (1.63) - changed ImGui::GetTime() return value from float to double to avoid accumulating floating point imprecisions over time. - 2018/07/08 (1.63) - style: renamed ImGuiCol_ModalWindowDarkening to ImGuiCol_ModalWindowDimBg for consistency with other features. Kept redirection enum (will obsolete). - 2018/06/08 (1.62) - examples: the imgui_impl_XXX files have been split to separate platform (Win32, GLFW, SDL2, etc.) from renderer (DX11, OpenGL, Vulkan, etc.). old backends will still work as is, however prefer using the separated backends as they will be updated to support multi-viewports. when adopting new backends follow the main.cpp code of your preferred examples/ folder to know which functions to call. in particular, note that old backends called ImGui::NewFrame() at the end of their ImGui_ImplXXXX_NewFrame() function. - 2018/06/06 (1.62) - renamed GetGlyphRangesChinese() to GetGlyphRangesChineseFull() to distinguish other variants and discourage using the full set. - 2018/06/06 (1.62) - TreeNodeEx()/TreeNodeBehavior(): the ImGuiTreeNodeFlags_CollapsingHeader helper now include the ImGuiTreeNodeFlags_NoTreePushOnOpen flag. See Changelog for details. - 2018/05/03 (1.61) - DragInt(): the default compile-time format string has been changed from "%.0f" to "%d", as we are not using integers internally any more. If you used DragInt() with custom format strings, make sure you change them to use %d or an integer-compatible format. To honor backward-compatibility, the DragInt() code will currently parse and modify format strings to replace %*f with %d, giving time to users to upgrade their code. If you have IMGUI_DISABLE_OBSOLETE_FUNCTIONS enabled, the code will instead assert! You may run a reg-exp search on your codebase for e.g. "DragInt.*%f" to help you find them. - 2018/04/28 (1.61) - obsoleted InputFloat() functions taking an optional "int decimal_precision" in favor of an equivalent and more flexible "const char* format", consistent with other functions. Kept redirection functions (will obsolete). - 2018/04/09 (1.61) - IM_DELETE() helper function added in 1.60 doesn't clear the input _pointer_ reference, more consistent with expectation and allows passing r-value. - 2018/03/20 (1.60) - renamed io.WantMoveMouse to io.WantSetMousePos for consistency and ease of understanding (was added in 1.52, _not_ used by core and only honored by some backend ahead of merging the Nav branch). - 2018/03/12 (1.60) - removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered as the closing cross uses regular button colors now. - 2018/03/08 (1.60) - changed ImFont::DisplayOffset.y to default to 0 instead of +1. Fixed rounding of Ascent/Descent to match TrueType renderer. If you were adding or subtracting to ImFont::DisplayOffset check if your fonts are correctly aligned vertically. - 2018/03/03 (1.60) - renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums. - 2018/02/18 (1.60) - BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is not really usable in many situations at the moment. - 2018/02/16 (1.60) - obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). Use ImGui::GetDrawData() to retrieve the ImDrawData* to display. - 2018/02/07 (1.60) - reorganized context handling to be more explicit, - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. - removed Shutdown() function, as DestroyContext() serve this purpose. - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwise CreateContext() will create its own font atlas instance. - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts. - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts. - 2018/01/31 (1.60) - moved sample TTF files from extra_fonts/ to misc/fonts/. If you loaded files directly from the imgui repo you may need to update your paths. - 2018/01/11 (1.60) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete). - 2018/01/11 (1.60) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete). - 2018/01/03 (1.60) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. - 2017/12/29 (1.60) - removed CalcItemRectClosestPoint() which was weird and not really used by anyone except demo code. If you need it it's easy to replicate on your side. - 2017/12/24 (1.53) - renamed the emblematic ShowTestWindow() function to ShowDemoWindow(). Kept redirection function (will obsolete). - 2017/12/21 (1.53) - ImDrawList: renamed style.AntiAliasedShapes to style.AntiAliasedFill for consistency and as a way to explicitly break code that manipulate those flag at runtime. You can now manipulate ImDrawList::Flags - 2017/12/21 (1.53) - ImDrawList: removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Prefer manipulating ImDrawList::Flags if you need to toggle them during the frame. - 2017/12/14 (1.53) - using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set. - 2017/12/13 (1.53) - renamed GetItemsLineHeightWithSpacing() to GetFrameHeightWithSpacing(). Kept redirection function (will obsolete). - 2017/12/13 (1.53) - obsoleted IsRootWindowFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Kept redirection function (will obsolete). - obsoleted IsRootWindowOrAnyChildFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows). Kept redirection function (will obsolete). - 2017/12/12 (1.53) - renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. Kept redirection enum (will obsolete). - 2017/12/10 (1.53) - removed SetNextWindowContentWidth(), prefer using SetNextWindowContentSize(). Kept redirection function (will obsolete). - 2017/11/27 (1.53) - renamed ImGuiTextBuffer::append() helper to appendf(), appendv() to appendfv(). If you copied the 'Log' demo in your code, it uses appendv() so that needs to be renamed. - 2017/11/18 (1.53) - Style, Begin: removed ImGuiWindowFlags_ShowBorders window flag. Borders are now fully set up in the ImGuiStyle structure (see e.g. style.FrameBorderSize, style.WindowBorderSize). Use ImGui::ShowStyleEditor() to look them up. Please note that the style system will keep evolving (hopefully stabilizing in Q1 2018), and so custom styles will probably subtly break over time. It is recommended you use the StyleColorsClassic(), StyleColorsDark(), StyleColorsLight() functions. - 2017/11/18 (1.53) - Style: removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency. - 2017/11/18 (1.53) - Style: renamed ImGuiCol_ChildWindowBg to ImGuiCol_ChildBg. - 2017/11/18 (1.53) - Style: renamed style.ChildWindowRounding to style.ChildRounding, ImGuiStyleVar_ChildWindowRounding to ImGuiStyleVar_ChildRounding. - 2017/11/02 (1.53) - obsoleted IsRootWindowOrAnyChildHovered() in favor of using IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); - 2017/10/24 (1.52) - renamed IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS to IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS for consistency. - 2017/10/20 (1.52) - changed IsWindowHovered() default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it. - 2017/10/20 (1.52) - marked IsItemHoveredRect()/IsMouseHoveringWindow() as obsolete, in favor of using the newly introduced flags for IsItemHovered() and IsWindowHovered(). See https://github.com/ocornut/imgui/issues/1382 for details. removed the IsItemRectHovered()/IsWindowRectHovered() names introduced in 1.51 since they were merely more consistent names for the two functions we are now obsoleting. IsItemHoveredRect() --> IsItemHovered(ImGuiHoveredFlags_RectOnly) IsMouseHoveringAnyWindow() --> IsWindowHovered(ImGuiHoveredFlags_AnyWindow) IsMouseHoveringWindow() --> IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) [weird, old behavior] - 2017/10/17 (1.52) - marked the old 5-parameters version of Begin() as obsolete (still available). Use SetNextWindowSize()+Begin() instead! - 2017/10/11 (1.52) - renamed AlignFirstTextHeightToWidgets() to AlignTextToFramePadding(). Kept inline redirection function (will obsolete). - 2017/09/26 (1.52) - renamed ImFont::Glyph to ImFontGlyph. Kept redirection typedef (will obsolete). - 2017/09/25 (1.52) - removed SetNextWindowPosCenter() because SetNextWindowPos() now has the optional pivot information to do the same and more. Kept redirection function (will obsolete). - 2017/08/25 (1.52) - io.MousePos needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing. Previously ImVec2(-1,-1) was enough but we now accept negative mouse coordinates. In your backend if you need to support unavailable mouse, make sure to replace "io.MousePos = ImVec2(-1,-1)" with "io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX)". - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). -> (1.52) use IsItemHovered(ImGuiHoveredFlags_RectOnly)! - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete). - renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete). - 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency. - 2017/08/20 (1.51) - added PushStyleColor(ImGuiCol idx, ImU32 col) overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix. - 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame type. - 2017/08/15 (1.51) - changed parameter order for BeginPopupContextWindow() from (const char*,int buttons,bool also_over_items) to (const char*,int buttons,bool also_over_items). Note that most calls relied on default parameters completely. - 2017/08/13 (1.51) - renamed ImGuiCol_Column to ImGuiCol_Separator, ImGuiCol_ColumnHovered to ImGuiCol_SeparatorHovered, ImGuiCol_ColumnActive to ImGuiCol_SeparatorActive. Kept redirection enums (will obsolete). - 2017/08/11 (1.51) - renamed ImGuiSetCond_Always to ImGuiCond_Always, ImGuiSetCond_Once to ImGuiCond_Once, ImGuiSetCond_FirstUseEver to ImGuiCond_FirstUseEver, ImGuiSetCond_Appearing to ImGuiCond_Appearing. Kept redirection enums (will obsolete). - 2017/08/09 (1.51) - removed ValueColor() helpers, they are equivalent to calling Text(label) + SameLine() + ColorButton(). - 2017/08/08 (1.51) - removed ColorEditMode() and ImGuiColorEditMode in favor of ImGuiColorEditFlags and parameters to the various Color*() functions. The SetColorEditOptions() allows to initialize default but the user can still change them with right-click context menu. - changed prototype of 'ColorEdit4(const char* label, float col[4], bool show_alpha = true)' to 'ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0)', where passing flags = 0x01 is a safe no-op (hello dodgy backward compatibility!). - check and run the demo window, under "Color/Picker Widgets", to understand the various new options. - changed prototype of rarely used 'ColorButton(ImVec4 col, bool small_height = false, bool outline_border = true)' to 'ColorButton(const char* desc_id, ImVec4 col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0, 0))' - 2017/07/20 (1.51) - removed IsPosHoveringAnyWindow(ImVec2), which was partly broken and misleading. ASSERT + redirect user to io.WantCaptureMouse - 2017/05/26 (1.50) - removed ImFontConfig::MergeGlyphCenterV in favor of a more multipurpose ImFontConfig::GlyphOffset. - 2017/05/01 (1.50) - renamed ImDrawList::PathFill() (rarely used directly) to ImDrawList::PathFillConvex() for clarity. - 2016/11/06 (1.50) - BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple times to a same child from different locations of the stack id. If that's the case, generate an id with GetID() and use it instead of passing string to BeginChild(). - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass io.ClipboardUserData to it. - 2016/09/25 (1.50) - style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc. - 2016/07/30 (1.50) - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully, breakage should be minimal. - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore. If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you, otherwise if <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar. This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color: ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col) { float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a; return ImVec4((win_bg_col.x * win_bg_col.w + title_bg_col.x) * k, (win_bg_col.y * win_bg_col.w + title_bg_col.y) * k, (win_bg_col.z * win_bg_col.w + title_bg_col.z) * k, new_a); } If this is confusing, pick the RGB value from title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color. - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext(). - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection. - 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the "default_open = true" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen). - 2016/04/26 (1.49) - changed ImDrawList::PushClipRect(ImVec4 rect) to ImDrawList::PushClipRect(Imvec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false). Note that higher-level ImGui::PushClipRect() is preferable because it will clip at logic/widget level, whereas ImDrawList::PushClipRect() only affect your renderer. - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref GitHub issue #337). - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337) - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete). - 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert. - 2016/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. if you had manual pixel-perfect alignment in place it might affect you. - 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis. - 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete. - 2015/08/29 (1.45) - with the addition of horizontal scrollbar we made various fixes to inconsistencies with dealing with cursor position. GetCursorPos()/SetCursorPos() functions now include the scrolled amount. It shouldn't affect the majority of users, but take note that SetCursorPosX(100.0f) puts you at +100 from the starting x position which may include scrolling, not at +100 from the window left side. GetContentRegionMax()/GetWindowContentRegionMin()/GetWindowContentRegionMax() functions allow include the scrolled amount. Typically those were used in cases where no scrolling would happen so it may not be a problem, but watch out! - 2015/08/29 (1.45) - renamed style.ScrollbarWidth to style.ScrollbarSize - 2015/08/05 (1.44) - split imgui.cpp into extra files: imgui_demo.cpp imgui_draw.cpp imgui_internal.h that you need to add to your project. - 2015/07/18 (1.44) - fixed angles in ImDrawList::PathArcTo(), PathArcToFast() (introduced in 1.43) being off by an extra PI for no justifiable reason - 2015/07/14 (1.43) - add new ImFontAtlas::AddFont() API. For the old AddFont***, moved the 'font_no' parameter of ImFontAtlas::AddFont** functions to the ImFontConfig structure. you need to render your textured triangles with bilinear filtering to benefit from sub-pixel positioning of text. - 2015/07/08 (1.43) - switched rendering data to use indexed rendering. this is saving a fair amount of CPU/GPU and enables us to get anti-aliasing for a marginal cost. this necessary change will break your rendering function! the fix should be very easy. sorry for that :( - if you are using a vanilla copy of one of the imgui_impl_XXX.cpp provided in the example, you just need to update your copy and you can ignore the rest. - the signature of the io.RenderDrawListsFn handler has changed! old: ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count) new: ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data). parameters: 'cmd_lists' becomes 'draw_data->CmdLists', 'cmd_lists_count' becomes 'draw_data->CmdListsCount' ImDrawList: 'commands' becomes 'CmdBuffer', 'vtx_buffer' becomes 'VtxBuffer', 'IdxBuffer' is new. ImDrawCmd: 'vtx_count' becomes 'ElemCount', 'clip_rect' becomes 'ClipRect', 'user_callback' becomes 'UserCallback', 'texture_id' becomes 'TextureId'. - each ImDrawList now contains both a vertex buffer and an index buffer. For each command, render ElemCount/3 triangles using indices from the index buffer. - if you REALLY cannot render indexed primitives, you can call the draw_data->DeIndexAllBuffers() method to de-index the buffers. This is slow and a waste of CPU/GPU. Prefer using indexed rendering! - refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. please upgrade! - 2015/07/10 (1.43) - changed SameLine() parameters from int to float. - 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete). - 2015/07/02 (1.42) - renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion along with other scrolling functions, because positions (e.g. cursor position) are not equivalent to scrolling amount. - 2015/06/14 (1.41) - changed ImageButton() default bg_col parameter from (0,0,0,1) (black) to (0,0,0,0) (transparent) - makes a difference when texture have transparence - 2015/06/14 (1.41) - changed Selectable() API from (label, selected, size) to (label, selected, flags, size). Size override should have been rarely used. Sorry! - 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will obsolete). - 2015/05/31 (1.40) - renamed IsRectClipped() to IsRectVisible() for consistency. Note that return value is opposite! Kept inline redirection function (will obsolete). - 2015/05/27 (1.40) - removed the third 'repeat_if_held' parameter from Button() - sorry! it was rarely used and inconsistent. Use PushButtonRepeat(true) / PopButtonRepeat() to enable repeat on desired buttons. - 2015/05/11 (1.40) - changed BeginPopup() API, takes a string identifier instead of a bool. ImGui needs to manage the open/closed state of popups. Call OpenPopup() to actually set the "open" state of a popup. BeginPopup() returns true if the popup is opened. - 2015/05/03 (1.40) - removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same). - 2015/04/13 (1.38) - renamed IsClipped() to IsRectClipped(). Kept inline redirection function until 1.50. - 2015/04/09 (1.38) - renamed ImDrawList::AddArc() to ImDrawList::AddArcFast() for compatibility with future API - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive. - 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or Inputfloat() instead. - 2015/03/17 (1.36) - renamed GetItemBoxMin()/GetItemBoxMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function until 1.50. - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function until 1.50. - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth (casing) - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function until 1.50. - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once. - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now. - 2015/02/10 (1.32) - renamed GetItemWidth() to CalcItemWidth() to clarify its evolving behavior - 2015/02/08 (1.31) - renamed GetTextLineSpacing() to GetTextLineHeightWithSpacing() - 2015/02/01 (1.31) - removed IO.MemReallocFn (unused) - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions. - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader. - 2015/01/11 (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels. - old: const void* png_data; unsigned int png_size; ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); [..Upload texture to GPU..]; - new: unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); [..Upload texture to GPU..]; io.Fonts->SetTexID(YourTexIdentifier); you now have more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs. It is now recommended that you sample the font texture with bilinear interpolation. - 2015/01/11 (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to call io.Fonts->SetTexID() - 2015/01/11 (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix) - 2015/01/11 (1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets - 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, ImGuiSetCondition_FirstUseEver) - 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, FontFallbackGlyph) - 2014/11/26 (1.17) - reworked syntax of IMGUI_ONCE_UPON_A_FRAME helper macro to increase compiler compatibility - 2014/11/07 (1.15) - renamed IsHovered() to IsItemHovered() - 2014/10/02 (1.14) - renamed IMGUI_INCLUDE_IMGUI_USER_CPP to IMGUI_INCLUDE_IMGUI_USER_INL and imgui_user.cpp to imgui_user.inl (more IDE friendly) - 2014/09/25 (1.13) - removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for simplicity) - 2014/09/24 (1.12) - renamed SetFontScale() to SetWindowFontScale() - 2014/09/24 (1.12) - moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn - 2014/08/30 (1.09) - removed IO.FontHeight (now computed automatically) - 2014/08/30 (1.09) - moved IMGUI_FONT_TEX_UV_FOR_WHITE preprocessor define to IO.FontTexUvForWhite - 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes FREQUENTLY ASKED QUESTIONS (FAQ) ================================ Read all answers online: https://www.dearimgui.com/faq or https://github.com/ocornut/imgui/blob/master/docs/FAQ.md (same url) Read all answers locally (with a text editor or ideally a Markdown viewer): docs/FAQ.md Some answers are copied down here to facilitate searching in code. Q&A: Basics =========== Q: Where is the documentation? A: This library is poorly documented at the moment and expects the user to be acquainted with C/C++. - Run the examples/ applications and explore them. - Read Getting Started (https://github.com/ocornut/imgui/wiki/Getting-Started) guide. - See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function. - The demo covers most features of Dear ImGui, so you can read the code and see its output. - See documentation and comments at the top of imgui.cpp + effectively imgui.h. - 20+ standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ folder to explain how to integrate Dear ImGui with your own engine/application. - The Wiki (https://github.com/ocornut/imgui/wiki) has many resources and links. - The Glossary (https://github.com/ocornut/imgui/wiki/Glossary) page also may be useful. - Your programming IDE is your friend, find the type or function declaration to find comments associated with it. Q: What is this library called? Q: Which version should I get? >> This library is called "Dear ImGui", please don't call it "ImGui" :) >> See https://www.dearimgui.com/faq for details. Q&A: Integration ================ Q: How to get started? A: Read https://github.com/ocornut/imgui/wiki/Getting-Started. Read 'PROGRAMMER GUIDE' above. Read examples/README.txt. Q: How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application? A: You should read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags! >> See https://www.dearimgui.com/faq for a fully detailed answer. You really want to read this. Q. How can I enable keyboard or gamepad controls? Q: How can I use this on a machine without mouse, keyboard or screen? (input share, remote display) Q: I integrated Dear ImGui in my engine and little squares are showing instead of text... Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around... Q: I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries... >> See https://www.dearimgui.com/faq Q&A: Usage ---------- Q: About the ID Stack system.. - Why is my widget not reacting when I click on it? - How can I have widgets with an empty label? - How can I have multiple widgets with the same label? - How can I have multiple windows with the same label? Q: How can I display an image? What is ImTextureID, how does it work? Q: How can I use my own math types instead of ImVec2? Q: How can I interact with standard C++ types (such as std::string and std::vector)? Q: How can I display custom shapes? (using low-level ImDrawList API) >> See https://www.dearimgui.com/faq Q&A: Fonts, Text ================ Q: How should I handle DPI in my application? Q: How can I load a different font than the default? Q: How can I easily use icons in my application? Q: How can I load multiple fonts? Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic? >> See https://www.dearimgui.com/faq and https://github.com/ocornut/imgui/edit/master/docs/FONTS.md Q&A: Concerns ============= Q: Who uses Dear ImGui? Q: Can you create elaborate/serious tools with Dear ImGui? Q: Can you reskin the look of Dear ImGui? Q: Why using C++ (as opposed to C)? >> See https://www.dearimgui.com/faq Q&A: Community ============== Q: How can I help? A: - Businesses: please reach out to "omar AT dearimgui DOT com" if you work in a place using Dear ImGui! We can discuss ways for your company to fund development via invoiced technical support, maintenance or sponsoring contacts. This is among the most useful thing you can do for Dear ImGui. With increased funding, we sustain and grow work on this project. Also see https://github.com/ocornut/imgui/wiki/Sponsors - Businesses: you can also purchase licenses for the Dear ImGui Automation/Test Engine. - If you are experienced with Dear ImGui and C++, look at the GitHub issues, look at the Wiki, and see how you want to help and can help! - Disclose your usage of Dear ImGui via a dev blog post, a tweet, a screenshot, a mention somewhere etc. You may post screenshot or links in the gallery threads. Visuals are ideal as they inspire other programmers. But even without visuals, disclosing your use of dear imgui helps the library grow credibility, and help other teams and programmers with taking decisions. - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues (on GitHub or privately). */ //------------------------------------------------------------------------- // [SECTION] INCLUDES //------------------------------------------------------------------------- #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif #include "imgui.h" #ifndef IMGUI_DISABLE #include "imgui_internal.h" // System includes #include // vsnprintf, sscanf, printf #include // intptr_t // [Windows] On non-Visual Studio compilers, we default to IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS unless explicitly enabled #if defined(_WIN32) && !defined(_MSC_VER) && !defined(IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) #define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS #endif // [Windows] OS specific includes (optional) #if defined(_WIN32) && defined(IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) #define IMGUI_DISABLE_WIN32_FUNCTIONS #endif #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #ifndef NOMINMAX #define NOMINMAX #endif #ifndef __MINGW32__ #include // _wfopen, OpenClipboard #else #include #endif #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) // UWP doesn't have all Win32 functions #define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS #define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS #endif #endif // [Apple] OS specific includes #if defined(__APPLE__) #include #endif // Visual Studio warnings #ifdef _MSC_VER #pragma warning (disable: 4127) // condition expression is constant #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later #pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types #endif #pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to an 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2). #pragma warning (disable: 26495) // [Static Analyzer] Variable 'XXX' is uninitialized. Always initialize a member variable (type.6). #pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). #endif // Clang/GCC warnings with -Weverything #if defined(__clang__) #if __has_warning("-Wunknown-warning-option") #pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great! #endif #pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' #pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse. #pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok. #pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code. #pragma clang diagnostic ignored "-Wexit-time-destructors" // warning: declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals. #pragma clang diagnostic ignored "-Wglobal-constructors" // warning: declaration requires a global destructor // similar to above, not sure what the exact difference is. #pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness #pragma clang diagnostic ignored "-Wformat-pedantic" // warning: format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would lead to casting every %p arg to void*. probably enabled by -pedantic. #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning: cast to 'void *' from smaller integer type 'int' #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0 #pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision #elif defined(__GNUC__) // We disable -Wpragmas because GCC doesn't provide a has_warning equivalent and some forks/patches may not follow the warning/version association. #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size #pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*' #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked #pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #endif // Debug options #define IMGUI_DEBUG_NAV_SCORING 0 // Display navigation scoring preview when hovering items. Display last moving direction matches when holding CTRL #define IMGUI_DEBUG_NAV_RECTS 0 // Display the reference navigation rectangle for each window // When using CTRL+TAB (or Gamepad Square+L/R) we delay the visual a little in order to reduce visual noise doing a fast switch. static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f; // Time before the highlight and screen dimming starts fading in static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear static const float NAV_ACTIVATE_HIGHLIGHT_TIMER = 0.10f; // Time to highlight an item activated by a shortcut. // Window resizing from edges (when io.ConfigWindowsResizeFromEdges = true and ImGuiBackendFlags_HasMouseCursors is set in io.BackendFlags by backend) static const float WINDOWS_HOVER_PADDING = 4.0f; // Extend outside window for hovering/resizing (maxxed with TouchPadding) and inside windows for borders. Affect FindHoveredWindow(). static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f; // Reduce visual noise by only highlighting the border after a certain time. static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER = 0.70f; // Lock scrolled window (so it doesn't pick child windows that are scrolling through) for a certain time, unless mouse moved. // Tooltip offset static const ImVec2 TOOLTIP_DEFAULT_OFFSET = ImVec2(16, 10); // Multiplied by g.Style.MouseCursorScale //------------------------------------------------------------------------- // [SECTION] FORWARD DECLARATIONS //------------------------------------------------------------------------- static void SetCurrentWindow(ImGuiWindow* window); static void FindHoveredWindow(); static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags); static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window); static void AddWindowToSortBuffer(ImVector* out_sorted_windows, ImGuiWindow* window); // Settings static void WindowSettingsHandler_ClearAll(ImGuiContext*, ImGuiSettingsHandler*); static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name); static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line); static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSettingsHandler*); static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf); // Platform Dependents default implementation for IO functions static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx); static void SetClipboardTextFn_DefaultImpl(void* user_data_ctx, const char* text); static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatformImeData* data); namespace ImGui { // Navigation static void NavUpdate(); static void NavUpdateWindowing(); static void NavUpdateWindowingOverlay(); static void NavUpdateCancelRequest(); static void NavUpdateCreateMoveRequest(); static void NavUpdateCreateTabbingRequest(); static float NavUpdatePageUpPageDown(); static inline void NavUpdateAnyRequestFlag(); static void NavUpdateCreateWrappingRequest(); static void NavEndFrame(); static bool NavScoreItem(ImGuiNavItemData* result); static void NavApplyItemToResult(ImGuiNavItemData* result); static void NavProcessItem(); static void NavProcessItemForTabbingRequest(ImGuiID id, ImGuiItemFlags item_flags, ImGuiNavMoveFlags move_flags); static ImVec2 NavCalcPreferredRefPos(); static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window); static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window); static void NavRestoreLayer(ImGuiNavLayer layer); static int FindWindowFocusIndex(ImGuiWindow* window); // Error Checking and Debug Tools static void ErrorCheckNewFrameSanityChecks(); static void ErrorCheckEndFrameSanityChecks(); static void UpdateDebugToolItemPicker(); static void UpdateDebugToolStackQueries(); static void UpdateDebugToolFlashStyleColor(); // Inputs static void UpdateKeyboardInputs(); static void UpdateMouseInputs(); static void UpdateMouseWheel(); static void UpdateKeyRoutingTable(ImGuiKeyRoutingTable* rt); // Misc static void UpdateSettings(); static int UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_hovered, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4], const ImRect& visibility_rect); static void RenderWindowOuterBorders(ImGuiWindow* window); static void RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, bool handle_borders_and_resize_grips, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size); static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open); static void RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col); static void RenderDimmedBackgrounds(); // Viewports const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using an arbitrary constant instead of e.g. ImHashStr("ViewportDefault", 0); so it's easier to spot in the debugger. The exact value doesn't matter. static void UpdateViewportsNewFrame(); } //----------------------------------------------------------------------------- // [SECTION] CONTEXT AND MEMORY ALLOCATORS //----------------------------------------------------------------------------- // DLL users: // - Heaps and globals are not shared across DLL boundaries! // - You will need to call SetCurrentContext() + SetAllocatorFunctions() for each static/DLL boundary you are calling from. // - Same applies for hot-reloading mechanisms that are reliant on reloading DLL (note that many hot-reloading mechanisms work without DLL). // - Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. // - Confused? In a debugger: add GImGui to your watch window and notice how its value changes depending on your current location (which DLL boundary you are in). // Current context pointer. Implicitly used by all Dear ImGui functions. Always assumed to be != NULL. // - ImGui::CreateContext() will automatically set this pointer if it is NULL. // Change to a different context by calling ImGui::SetCurrentContext(). // - Important: Dear ImGui functions are not thread-safe because of this pointer. // If you want thread-safety to allow N threads to access N different contexts: // - Change this variable to use thread local storage so each thread can refer to a different context, in your imconfig.h: // struct ImGuiContext; // extern thread_local ImGuiContext* MyImGuiTLS; // #define GImGui MyImGuiTLS // And then define MyImGuiTLS in one of your cpp files. Note that thread_local is a C++11 keyword, earlier C++ uses compiler-specific keyword. // - Future development aims to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586 // - If you need a finite number of contexts, you may compile and use multiple instances of the ImGui code from a different namespace. // - DLL users: read comments above. #ifndef GImGui ImGuiContext* GImGui = NULL; #endif // Memory Allocator functions. Use SetAllocatorFunctions() to change them. // - You probably don't want to modify that mid-program, and if you use global/static e.g. ImVector<> instances you may need to keep them accessible during program destruction. // - DLL users: read comments above. #ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS static void* MallocWrapper(size_t size, void* user_data) { IM_UNUSED(user_data); return malloc(size); } static void FreeWrapper(void* ptr, void* user_data) { IM_UNUSED(user_data); free(ptr); } #else static void* MallocWrapper(size_t size, void* user_data) { IM_UNUSED(user_data); IM_UNUSED(size); IM_ASSERT(0); return NULL; } static void FreeWrapper(void* ptr, void* user_data) { IM_UNUSED(user_data); IM_UNUSED(ptr); IM_ASSERT(0); } #endif static ImGuiMemAllocFunc GImAllocatorAllocFunc = MallocWrapper; static ImGuiMemFreeFunc GImAllocatorFreeFunc = FreeWrapper; static void* GImAllocatorUserData = NULL; //----------------------------------------------------------------------------- // [SECTION] USER FACING STRUCTURES (ImGuiStyle, ImGuiIO) //----------------------------------------------------------------------------- ImGuiStyle::ImGuiStyle() { Alpha = 1.0f; // Global alpha applies to everything in Dear ImGui. DisabledAlpha = 0.60f; // Additional alpha multiplier applied by BeginDisabled(). Multiply over current value of Alpha. WindowPadding = ImVec2(8,8); // Padding within a window WindowRounding = 0.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended. WindowBorderSize = 1.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested. WindowMinSize = ImVec2(32,32); // Minimum window size WindowTitleAlign = ImVec2(0.0f,0.5f);// Alignment for title bar text WindowMenuButtonPosition= ImGuiDir_Left; // Position of the collapsing/docking button in the title bar (left/right). Defaults to ImGuiDir_Left. ChildRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows ChildBorderSize = 1.0f; // Thickness of border around child windows. Generally set to 0.0f or 1.0f. Other values not well tested. PopupRounding = 0.0f; // Radius of popup window corners rounding. Set to 0.0f to have rectangular child windows PopupBorderSize = 1.0f; // Thickness of border around popup or tooltip windows. Generally set to 0.0f or 1.0f. Other values not well tested. FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets) FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets). FrameBorderSize = 0.0f; // Thickness of border around frames. Generally set to 0.0f or 1.0f. Other values not well tested. ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) CellPadding = ImVec2(4,2); // Padding within a table cell. CellPadding.y may be altered between different rows. TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1). ScrollbarSize = 14.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar GrabMinSize = 12.0f; // Minimum width/height of a grab box for slider/scrollbar GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. LogSliderDeadzone = 4.0f; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero. TabRounding = 4.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs. TabBorderSize = 0.0f; // Thickness of border around tabs. TabMinWidthForCloseButton = 0.0f; // Minimum width for close button to appear on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected. TabBarBorderSize = 1.0f; // Thickness of tab-bar separator, which takes on the tab active color to denote focus. TableAngledHeadersAngle = 35.0f * (IM_PI / 180.0f); // Angle of angled headers (supported values range from -50 degrees to +50 degrees). ColorButtonPosition = ImGuiDir_Right; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right. ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text. SelectableTextAlign = ImVec2(0.0f,0.0f);// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line. SeparatorTextBorderSize = 3.0f; // Thickkness of border in SeparatorText() SeparatorTextAlign = ImVec2(0.0f,0.5f);// Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center). SeparatorTextPadding = ImVec2(20.0f,3.f);// Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y. DisplayWindowPadding = ImVec2(19,19); // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows. DisplaySafeAreaPadding = ImVec2(3,3); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. MouseCursorScale = 1.0f; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later. AntiAliasedLines = true; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. AntiAliasedLinesUseTex = true; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). AntiAliasedFill = true; // Enable anti-aliased filled shapes (rounded rectangles, circles, etc.). CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. CircleTessellationMaxError = 0.30f; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry. // Behaviors HoverStationaryDelay = 0.15f; // Delay for IsItemHovered(ImGuiHoveredFlags_Stationary). Time required to consider mouse stationary. HoverDelayShort = 0.15f; // Delay for IsItemHovered(ImGuiHoveredFlags_DelayShort). Usually used along with HoverStationaryDelay. HoverDelayNormal = 0.40f; // Delay for IsItemHovered(ImGuiHoveredFlags_DelayNormal). " HoverFlagsForTooltipMouse = ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_AllowWhenDisabled; // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using mouse. HoverFlagsForTooltipNav = ImGuiHoveredFlags_NoSharedDelay | ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_AllowWhenDisabled; // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using keyboard/gamepad. // Default theme ImGui::StyleColorsDark(this); } // To scale your entire UI (e.g. if you want your app to use High DPI or generally be DPI aware) you may use this helper function. Scaling the fonts is done separately and is up to you. // Important: This operation is lossy because we round all sizes to integer. If you need to change your scale multiples, call this over a freshly initialized ImGuiStyle structure rather than scaling multiple times. void ImGuiStyle::ScaleAllSizes(float scale_factor) { WindowPadding = ImTrunc(WindowPadding * scale_factor); WindowRounding = ImTrunc(WindowRounding * scale_factor); WindowMinSize = ImTrunc(WindowMinSize * scale_factor); ChildRounding = ImTrunc(ChildRounding * scale_factor); PopupRounding = ImTrunc(PopupRounding * scale_factor); FramePadding = ImTrunc(FramePadding * scale_factor); FrameRounding = ImTrunc(FrameRounding * scale_factor); ItemSpacing = ImTrunc(ItemSpacing * scale_factor); ItemInnerSpacing = ImTrunc(ItemInnerSpacing * scale_factor); CellPadding = ImTrunc(CellPadding * scale_factor); TouchExtraPadding = ImTrunc(TouchExtraPadding * scale_factor); IndentSpacing = ImTrunc(IndentSpacing * scale_factor); ColumnsMinSpacing = ImTrunc(ColumnsMinSpacing * scale_factor); ScrollbarSize = ImTrunc(ScrollbarSize * scale_factor); ScrollbarRounding = ImTrunc(ScrollbarRounding * scale_factor); GrabMinSize = ImTrunc(GrabMinSize * scale_factor); GrabRounding = ImTrunc(GrabRounding * scale_factor); LogSliderDeadzone = ImTrunc(LogSliderDeadzone * scale_factor); TabRounding = ImTrunc(TabRounding * scale_factor); TabMinWidthForCloseButton = (TabMinWidthForCloseButton != FLT_MAX) ? ImTrunc(TabMinWidthForCloseButton * scale_factor) : FLT_MAX; SeparatorTextPadding = ImTrunc(SeparatorTextPadding * scale_factor); DisplayWindowPadding = ImTrunc(DisplayWindowPadding * scale_factor); DisplaySafeAreaPadding = ImTrunc(DisplaySafeAreaPadding * scale_factor); MouseCursorScale = ImTrunc(MouseCursorScale * scale_factor); } ImGuiIO::ImGuiIO() { // Most fields are initialized with zero memset(this, 0, sizeof(*this)); IM_STATIC_ASSERT(IM_ARRAYSIZE(ImGuiIO::MouseDown) == ImGuiMouseButton_COUNT && IM_ARRAYSIZE(ImGuiIO::MouseClicked) == ImGuiMouseButton_COUNT); // Settings ConfigFlags = ImGuiConfigFlags_None; BackendFlags = ImGuiBackendFlags_None; DisplaySize = ImVec2(-1.0f, -1.0f); DeltaTime = 1.0f / 60.0f; IniSavingRate = 5.0f; IniFilename = "imgui.ini"; // Important: "imgui.ini" is relative to current working dir, most apps will want to lock this to an absolute path (e.g. same path as executables). LogFilename = "imgui_log.txt"; #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO for (int i = 0; i < ImGuiKey_COUNT; i++) KeyMap[i] = -1; #endif UserData = NULL; Fonts = NULL; FontGlobalScale = 1.0f; FontDefault = NULL; FontAllowUserScaling = false; DisplayFramebufferScale = ImVec2(1.0f, 1.0f); MouseDoubleClickTime = 0.30f; MouseDoubleClickMaxDist = 6.0f; MouseDragThreshold = 6.0f; KeyRepeatDelay = 0.275f; KeyRepeatRate = 0.050f; // Miscellaneous options MouseDrawCursor = false; #ifdef __APPLE__ ConfigMacOSXBehaviors = true; // Set Mac OS X style defaults based on __APPLE__ compile time flag #else ConfigMacOSXBehaviors = false; #endif ConfigInputTrickleEventQueue = true; ConfigInputTextCursorBlink = true; ConfigInputTextEnterKeepActive = false; ConfigDragClickToInputText = false; ConfigWindowsResizeFromEdges = true; ConfigWindowsMoveFromTitleBarOnly = false; ConfigMemoryCompactTimer = 60.0f; ConfigDebugBeginReturnValueOnce = false; ConfigDebugBeginReturnValueLoop = false; // Platform Functions // Note: Initialize() will setup default clipboard/ime handlers. BackendPlatformName = BackendRendererName = NULL; BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL; PlatformLocaleDecimalPoint = '.'; // Input (NB: we already have memset zero the entire structure!) MousePos = ImVec2(-FLT_MAX, -FLT_MAX); MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX); MouseSource = ImGuiMouseSource_Mouse; for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f; for (int i = 0; i < IM_ARRAYSIZE(KeysData); i++) { KeysData[i].DownDuration = KeysData[i].DownDurationPrev = -1.0f; } AppAcceptingEvents = true; BackendUsingLegacyKeyArrays = (ImS8)-1; BackendUsingLegacyNavInputArray = true; // assume using legacy array until proven wrong } // Pass in translated ASCII characters for text input. // - with glfw you can get those from the callback set in glfwSetCharCallback() // - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message // FIXME: Should in theory be called "AddCharacterEvent()" to be consistent with new API void ImGuiIO::AddInputCharacter(unsigned int c) { IM_ASSERT(Ctx != NULL); ImGuiContext& g = *Ctx; if (c == 0 || !AppAcceptingEvents) return; ImGuiInputEvent e; e.Type = ImGuiInputEventType_Text; e.Source = ImGuiInputSource_Keyboard; e.EventId = g.InputEventsNextEventId++; e.Text.Char = c; g.InputEventsQueue.push_back(e); } // UTF16 strings use surrogate pairs to encode codepoints >= 0x10000, so // we should save the high surrogate. void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c) { if ((c == 0 && InputQueueSurrogate == 0) || !AppAcceptingEvents) return; if ((c & 0xFC00) == 0xD800) // High surrogate, must save { if (InputQueueSurrogate != 0) AddInputCharacter(IM_UNICODE_CODEPOINT_INVALID); InputQueueSurrogate = c; return; } ImWchar cp = c; if (InputQueueSurrogate != 0) { if ((c & 0xFC00) != 0xDC00) // Invalid low surrogate { AddInputCharacter(IM_UNICODE_CODEPOINT_INVALID); } else { #if IM_UNICODE_CODEPOINT_MAX == 0xFFFF cp = IM_UNICODE_CODEPOINT_INVALID; // Codepoint will not fit in ImWchar #else cp = (ImWchar)(((InputQueueSurrogate - 0xD800) << 10) + (c - 0xDC00) + 0x10000); #endif } InputQueueSurrogate = 0; } AddInputCharacter((unsigned)cp); } void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars) { if (!AppAcceptingEvents) return; while (*utf8_chars != 0) { unsigned int c = 0; utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL); AddInputCharacter(c); } } // Clear all incoming events. void ImGuiIO::ClearEventsQueue() { IM_ASSERT(Ctx != NULL); ImGuiContext& g = *Ctx; g.InputEventsQueue.clear(); } // Clear current keyboard/mouse/gamepad state + current frame text input buffer. Equivalent to releasing all keys/buttons. void ImGuiIO::ClearInputKeys() { #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO memset(KeysDown, 0, sizeof(KeysDown)); #endif for (int n = 0; n < IM_ARRAYSIZE(KeysData); n++) { KeysData[n].Down = false; KeysData[n].DownDuration = -1.0f; KeysData[n].DownDurationPrev = -1.0f; } KeyCtrl = KeyShift = KeyAlt = KeySuper = false; KeyMods = ImGuiMod_None; MousePos = ImVec2(-FLT_MAX, -FLT_MAX); for (int n = 0; n < IM_ARRAYSIZE(MouseDown); n++) { MouseDown[n] = false; MouseDownDuration[n] = MouseDownDurationPrev[n] = -1.0f; } MouseWheel = MouseWheelH = 0.0f; InputQueueCharacters.resize(0); // Behavior of old ClearInputCharacters(). } // Removed this as it is ambiguous/misleading and generally incorrect to use with the existence of a higher-level input queue. // Current frame character buffer is now also cleared by ClearInputKeys(). #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS void ImGuiIO::ClearInputCharacters() { InputQueueCharacters.resize(0); } #endif static ImGuiInputEvent* FindLatestInputEvent(ImGuiContext* ctx, ImGuiInputEventType type, int arg = -1) { ImGuiContext& g = *ctx; for (int n = g.InputEventsQueue.Size - 1; n >= 0; n--) { ImGuiInputEvent* e = &g.InputEventsQueue[n]; if (e->Type != type) continue; if (type == ImGuiInputEventType_Key && e->Key.Key != arg) continue; if (type == ImGuiInputEventType_MouseButton && e->MouseButton.Button != arg) continue; return e; } return NULL; } // Queue a new key down/up event. // - ImGuiKey key: Translated key (as in, generally ImGuiKey_A matches the key end-user would use to emit an 'A' character) // - bool down: Is the key down? use false to signify a key release. // - float analog_value: 0.0f..1.0f // IMPORTANT: THIS FUNCTION AND OTHER "ADD" GRABS THE CONTEXT FROM OUR INSTANCE. // WE NEED TO ENSURE THAT ALL FUNCTION CALLS ARE FULLFILLING THIS, WHICH IS WHY GetKeyData() HAS AN EXPLICIT CONTEXT. void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key, bool down, float analog_value) { //if (e->Down) { IMGUI_DEBUG_LOG_IO("AddKeyEvent() Key='%s' %d, NativeKeycode = %d, NativeScancode = %d\n", ImGui::GetKeyName(e->Key), e->Down, e->NativeKeycode, e->NativeScancode); } IM_ASSERT(Ctx != NULL); if (key == ImGuiKey_None || !AppAcceptingEvents) return; ImGuiContext& g = *Ctx; IM_ASSERT(ImGui::IsNamedKeyOrModKey(key)); // Backend needs to pass a valid ImGuiKey_ constant. 0..511 values are legacy native key codes which are not accepted by this API. IM_ASSERT(ImGui::IsAliasKey(key) == false); // Backend cannot submit ImGuiKey_MouseXXX values they are automatically inferred from AddMouseXXX() events. IM_ASSERT(key != ImGuiMod_Shortcut); // We could easily support the translation here but it seems saner to not accept it (TestEngine perform a translation itself) // Verify that backend isn't mixing up using new io.AddKeyEvent() api and old io.KeysDown[] + io.KeyMap[] data. #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO IM_ASSERT((BackendUsingLegacyKeyArrays == -1 || BackendUsingLegacyKeyArrays == 0) && "Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!"); if (BackendUsingLegacyKeyArrays == -1) for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++) IM_ASSERT(KeyMap[n] == -1 && "Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!"); BackendUsingLegacyKeyArrays = 0; #endif if (ImGui::IsGamepadKey(key)) BackendUsingLegacyNavInputArray = false; // Filter duplicate (in particular: key mods and gamepad analog values are commonly spammed) const ImGuiInputEvent* latest_event = FindLatestInputEvent(&g, ImGuiInputEventType_Key, (int)key); const ImGuiKeyData* key_data = ImGui::GetKeyData(&g, key); const bool latest_key_down = latest_event ? latest_event->Key.Down : key_data->Down; const float latest_key_analog = latest_event ? latest_event->Key.AnalogValue : key_data->AnalogValue; if (latest_key_down == down && latest_key_analog == analog_value) return; // Add event ImGuiInputEvent e; e.Type = ImGuiInputEventType_Key; e.Source = ImGui::IsGamepadKey(key) ? ImGuiInputSource_Gamepad : ImGuiInputSource_Keyboard; e.EventId = g.InputEventsNextEventId++; e.Key.Key = key; e.Key.Down = down; e.Key.AnalogValue = analog_value; g.InputEventsQueue.push_back(e); } void ImGuiIO::AddKeyEvent(ImGuiKey key, bool down) { if (!AppAcceptingEvents) return; AddKeyAnalogEvent(key, down, down ? 1.0f : 0.0f); } // [Optional] Call after AddKeyEvent(). // Specify native keycode, scancode + Specify index for legacy <1.87 IsKeyXXX() functions with native indices. // If you are writing a backend in 2022 or don't use IsKeyXXX() with native values that are not ImGuiKey values, you can avoid calling this. void ImGuiIO::SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native_scancode, int native_legacy_index) { if (key == ImGuiKey_None) return; IM_ASSERT(ImGui::IsNamedKey(key)); // >= 512 IM_ASSERT(native_legacy_index == -1 || ImGui::IsLegacyKey((ImGuiKey)native_legacy_index)); // >= 0 && <= 511 IM_UNUSED(native_keycode); // Yet unused IM_UNUSED(native_scancode); // Yet unused // Build native->imgui map so old user code can still call key functions with native 0..511 values. #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO const int legacy_key = (native_legacy_index != -1) ? native_legacy_index : native_keycode; if (!ImGui::IsLegacyKey((ImGuiKey)legacy_key)) return; KeyMap[legacy_key] = key; KeyMap[key] = legacy_key; #else IM_UNUSED(key); IM_UNUSED(native_legacy_index); #endif } // Set master flag for accepting key/mouse/text events (default to true). Useful if you have native dialog boxes that are interrupting your application loop/refresh, and you want to disable events being queued while your app is frozen. void ImGuiIO::SetAppAcceptingEvents(bool accepting_events) { AppAcceptingEvents = accepting_events; } // Queue a mouse move event void ImGuiIO::AddMousePosEvent(float x, float y) { IM_ASSERT(Ctx != NULL); ImGuiContext& g = *Ctx; if (!AppAcceptingEvents) return; // Apply same flooring as UpdateMouseInputs() ImVec2 pos((x > -FLT_MAX) ? ImFloor(x) : x, (y > -FLT_MAX) ? ImFloor(y) : y); // Filter duplicate const ImGuiInputEvent* latest_event = FindLatestInputEvent(&g, ImGuiInputEventType_MousePos); const ImVec2 latest_pos = latest_event ? ImVec2(latest_event->MousePos.PosX, latest_event->MousePos.PosY) : g.IO.MousePos; if (latest_pos.x == pos.x && latest_pos.y == pos.y) return; ImGuiInputEvent e; e.Type = ImGuiInputEventType_MousePos; e.Source = ImGuiInputSource_Mouse; e.EventId = g.InputEventsNextEventId++; e.MousePos.PosX = pos.x; e.MousePos.PosY = pos.y; e.MousePos.MouseSource = g.InputEventsNextMouseSource; g.InputEventsQueue.push_back(e); } void ImGuiIO::AddMouseButtonEvent(int mouse_button, bool down) { IM_ASSERT(Ctx != NULL); ImGuiContext& g = *Ctx; IM_ASSERT(mouse_button >= 0 && mouse_button < ImGuiMouseButton_COUNT); if (!AppAcceptingEvents) return; // Filter duplicate const ImGuiInputEvent* latest_event = FindLatestInputEvent(&g, ImGuiInputEventType_MouseButton, (int)mouse_button); const bool latest_button_down = latest_event ? latest_event->MouseButton.Down : g.IO.MouseDown[mouse_button]; if (latest_button_down == down) return; ImGuiInputEvent e; e.Type = ImGuiInputEventType_MouseButton; e.Source = ImGuiInputSource_Mouse; e.EventId = g.InputEventsNextEventId++; e.MouseButton.Button = mouse_button; e.MouseButton.Down = down; e.MouseButton.MouseSource = g.InputEventsNextMouseSource; g.InputEventsQueue.push_back(e); } // Queue a mouse wheel event (some mouse/API may only have a Y component) void ImGuiIO::AddMouseWheelEvent(float wheel_x, float wheel_y) { IM_ASSERT(Ctx != NULL); ImGuiContext& g = *Ctx; // Filter duplicate (unlike most events, wheel values are relative and easy to filter) if (!AppAcceptingEvents || (wheel_x == 0.0f && wheel_y == 0.0f)) return; ImGuiInputEvent e; e.Type = ImGuiInputEventType_MouseWheel; e.Source = ImGuiInputSource_Mouse; e.EventId = g.InputEventsNextEventId++; e.MouseWheel.WheelX = wheel_x; e.MouseWheel.WheelY = wheel_y; e.MouseWheel.MouseSource = g.InputEventsNextMouseSource; g.InputEventsQueue.push_back(e); } // This is not a real event, the data is latched in order to be stored in actual Mouse events. // This is so that duplicate events (e.g. Windows sending extraneous WM_MOUSEMOVE) gets filtered and are not leading to actual source changes. void ImGuiIO::AddMouseSourceEvent(ImGuiMouseSource source) { IM_ASSERT(Ctx != NULL); ImGuiContext& g = *Ctx; g.InputEventsNextMouseSource = source; } void ImGuiIO::AddFocusEvent(bool focused) { IM_ASSERT(Ctx != NULL); ImGuiContext& g = *Ctx; // Filter duplicate const ImGuiInputEvent* latest_event = FindLatestInputEvent(&g, ImGuiInputEventType_Focus); const bool latest_focused = latest_event ? latest_event->AppFocused.Focused : !g.IO.AppFocusLost; if (latest_focused == focused || (ConfigDebugIgnoreFocusLoss && !focused)) return; ImGuiInputEvent e; e.Type = ImGuiInputEventType_Focus; e.EventId = g.InputEventsNextEventId++; e.AppFocused.Focused = focused; g.InputEventsQueue.push_back(e); } //----------------------------------------------------------------------------- // [SECTION] MISC HELPERS/UTILITIES (Geometry functions) //----------------------------------------------------------------------------- ImVec2 ImBezierCubicClosestPoint(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, int num_segments) { IM_ASSERT(num_segments > 0); // Use ImBezierCubicClosestPointCasteljau() ImVec2 p_last = p1; ImVec2 p_closest; float p_closest_dist2 = FLT_MAX; float t_step = 1.0f / (float)num_segments; for (int i_step = 1; i_step <= num_segments; i_step++) { ImVec2 p_current = ImBezierCubicCalc(p1, p2, p3, p4, t_step * i_step); ImVec2 p_line = ImLineClosestPoint(p_last, p_current, p); float dist2 = ImLengthSqr(p - p_line); if (dist2 < p_closest_dist2) { p_closest = p_line; p_closest_dist2 = dist2; } p_last = p_current; } return p_closest; } // Closely mimics PathBezierToCasteljau() in imgui_draw.cpp static void ImBezierCubicClosestPointCasteljauStep(const ImVec2& p, ImVec2& p_closest, ImVec2& p_last, float& p_closest_dist2, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float tess_tol, int level) { float dx = x4 - x1; float dy = y4 - y1; float d2 = ((x2 - x4) * dy - (y2 - y4) * dx); float d3 = ((x3 - x4) * dy - (y3 - y4) * dx); d2 = (d2 >= 0) ? d2 : -d2; d3 = (d3 >= 0) ? d3 : -d3; if ((d2 + d3) * (d2 + d3) < tess_tol * (dx * dx + dy * dy)) { ImVec2 p_current(x4, y4); ImVec2 p_line = ImLineClosestPoint(p_last, p_current, p); float dist2 = ImLengthSqr(p - p_line); if (dist2 < p_closest_dist2) { p_closest = p_line; p_closest_dist2 = dist2; } p_last = p_current; } else if (level < 10) { float x12 = (x1 + x2)*0.5f, y12 = (y1 + y2)*0.5f; float x23 = (x2 + x3)*0.5f, y23 = (y2 + y3)*0.5f; float x34 = (x3 + x4)*0.5f, y34 = (y3 + y4)*0.5f; float x123 = (x12 + x23)*0.5f, y123 = (y12 + y23)*0.5f; float x234 = (x23 + x34)*0.5f, y234 = (y23 + y34)*0.5f; float x1234 = (x123 + x234)*0.5f, y1234 = (y123 + y234)*0.5f; ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1, y1, x12, y12, x123, y123, x1234, y1234, tess_tol, level + 1); ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, x1234, y1234, x234, y234, x34, y34, x4, y4, tess_tol, level + 1); } } // tess_tol is generally the same value you would find in ImGui::GetStyle().CurveTessellationTol // Because those ImXXX functions are lower-level than ImGui:: we cannot access this value automatically. ImVec2 ImBezierCubicClosestPointCasteljau(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, float tess_tol) { IM_ASSERT(tess_tol > 0.0f); ImVec2 p_last = p1; ImVec2 p_closest; float p_closest_dist2 = FLT_MAX; ImBezierCubicClosestPointCasteljauStep(p, p_closest, p_last, p_closest_dist2, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, tess_tol, 0); return p_closest; } ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p) { ImVec2 ap = p - a; ImVec2 ab_dir = b - a; float dot = ap.x * ab_dir.x + ap.y * ab_dir.y; if (dot < 0.0f) return a; float ab_len_sqr = ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y; if (dot > ab_len_sqr) return b; return a + ab_dir * dot / ab_len_sqr; } bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p) { bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f; bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f; bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f; return ((b1 == b2) && (b2 == b3)); } void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w) { ImVec2 v0 = b - a; ImVec2 v1 = c - a; ImVec2 v2 = p - a; const float denom = v0.x * v1.y - v1.x * v0.y; out_v = (v2.x * v1.y - v1.x * v2.y) / denom; out_w = (v0.x * v2.y - v2.x * v0.y) / denom; out_u = 1.0f - out_v - out_w; } ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p) { ImVec2 proj_ab = ImLineClosestPoint(a, b, p); ImVec2 proj_bc = ImLineClosestPoint(b, c, p); ImVec2 proj_ca = ImLineClosestPoint(c, a, p); float dist2_ab = ImLengthSqr(p - proj_ab); float dist2_bc = ImLengthSqr(p - proj_bc); float dist2_ca = ImLengthSqr(p - proj_ca); float m = ImMin(dist2_ab, ImMin(dist2_bc, dist2_ca)); if (m == dist2_ab) return proj_ab; if (m == dist2_bc) return proj_bc; return proj_ca; } //----------------------------------------------------------------------------- // [SECTION] MISC HELPERS/UTILITIES (String, Format, Hash functions) //----------------------------------------------------------------------------- // Consider using _stricmp/_strnicmp under Windows or strcasecmp/strncasecmp. We don't actually use either ImStricmp/ImStrnicmp in the codebase any more. int ImStricmp(const char* str1, const char* str2) { int d; while ((d = ImToUpper(*str2) - ImToUpper(*str1)) == 0 && *str1) { str1++; str2++; } return d; } int ImStrnicmp(const char* str1, const char* str2, size_t count) { int d = 0; while (count > 0 && (d = ImToUpper(*str2) - ImToUpper(*str1)) == 0 && *str1) { str1++; str2++; count--; } return d; } void ImStrncpy(char* dst, const char* src, size_t count) { if (count < 1) return; if (count > 1) strncpy(dst, src, count - 1); dst[count - 1] = 0; } char* ImStrdup(const char* str) { size_t len = strlen(str); void* buf = IM_ALLOC(len + 1); return (char*)memcpy(buf, (const void*)str, len + 1); } char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* src) { size_t dst_buf_size = p_dst_size ? *p_dst_size : strlen(dst) + 1; size_t src_size = strlen(src) + 1; if (dst_buf_size < src_size) { IM_FREE(dst); dst = (char*)IM_ALLOC(src_size); if (p_dst_size) *p_dst_size = src_size; } return (char*)memcpy(dst, (const void*)src, src_size); } const char* ImStrchrRange(const char* str, const char* str_end, char c) { const char* p = (const char*)memchr(str, (int)c, str_end - str); return p; } int ImStrlenW(const ImWchar* str) { //return (int)wcslen((const wchar_t*)str); // FIXME-OPT: Could use this when wchar_t are 16-bit int n = 0; while (*str++) n++; return n; } // Find end-of-line. Return pointer will point to either first \n, either str_end. const char* ImStreolRange(const char* str, const char* str_end) { const char* p = (const char*)memchr(str, '\n', str_end - str); return p ? p : str_end; } const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line { while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n') buf_mid_line--; return buf_mid_line; } const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end) { if (!needle_end) needle_end = needle + strlen(needle); const char un0 = (char)ImToUpper(*needle); while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end)) { if (ImToUpper(*haystack) == un0) { const char* b = needle + 1; for (const char* a = haystack + 1; b < needle_end; a++, b++) if (ImToUpper(*a) != ImToUpper(*b)) break; if (b == needle_end) return haystack; } haystack++; } return NULL; } // Trim str by offsetting contents when there's leading data + writing a \0 at the trailing position. We use this in situation where the cost is negligible. void ImStrTrimBlanks(char* buf) { char* p = buf; while (p[0] == ' ' || p[0] == '\t') // Leading blanks p++; char* p_start = p; while (*p != 0) // Find end of string p++; while (p > p_start && (p[-1] == ' ' || p[-1] == '\t')) // Trailing blanks p--; if (p_start != buf) // Copy memory if we had leading blanks memmove(buf, p_start, p - p_start); buf[p - p_start] = 0; // Zero terminate } const char* ImStrSkipBlank(const char* str) { while (str[0] == ' ' || str[0] == '\t') str++; return str; } // A) MSVC version appears to return -1 on overflow, whereas glibc appears to return total count (which may be >= buf_size). // Ideally we would test for only one of those limits at runtime depending on the behavior the vsnprintf(), but trying to deduct it at compile time sounds like a pandora can of worm. // B) When buf==NULL vsnprintf() will return the output size. #ifndef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // We support stb_sprintf which is much faster (see: https://github.com/nothings/stb/blob/master/stb_sprintf.h) // You may set IMGUI_USE_STB_SPRINTF to use our default wrapper, or set IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // and setup the wrapper yourself. (FIXME-OPT: Some of our high-level operations such as ImGuiTextBuffer::appendfv() are // designed using two-passes worst case, which probably could be improved using the stbsp_vsprintfcb() function.) #ifdef IMGUI_USE_STB_SPRINTF #ifndef IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION #define STB_SPRINTF_IMPLEMENTATION #endif #ifdef IMGUI_STB_SPRINTF_FILENAME #include IMGUI_STB_SPRINTF_FILENAME #else #include "stb_sprintf.h" #endif #endif // #ifdef IMGUI_USE_STB_SPRINTF #if defined(_MSC_VER) && !defined(vsnprintf) #define vsnprintf _vsnprintf #endif int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) { va_list args; va_start(args, fmt); #ifdef IMGUI_USE_STB_SPRINTF int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args); #else int w = vsnprintf(buf, buf_size, fmt, args); #endif va_end(args); if (buf == NULL) return w; if (w == -1 || w >= (int)buf_size) w = (int)buf_size - 1; buf[w] = 0; return w; } int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args) { #ifdef IMGUI_USE_STB_SPRINTF int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args); #else int w = vsnprintf(buf, buf_size, fmt, args); #endif if (buf == NULL) return w; if (w == -1 || w >= (int)buf_size) w = (int)buf_size - 1; buf[w] = 0; return w; } #endif // #ifdef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS void ImFormatStringToTempBuffer(const char** out_buf, const char** out_buf_end, const char* fmt, ...) { va_list args; va_start(args, fmt); ImFormatStringToTempBufferV(out_buf, out_buf_end, fmt, args); va_end(args); } void ImFormatStringToTempBufferV(const char** out_buf, const char** out_buf_end, const char* fmt, va_list args) { ImGuiContext& g = *GImGui; if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0) { const char* buf = va_arg(args, const char*); // Skip formatting when using "%s" if (buf == NULL) buf = "(null)"; *out_buf = buf; if (out_buf_end) { *out_buf_end = buf + strlen(buf); } } else if (fmt[0] == '%' && fmt[1] == '.' && fmt[2] == '*' && fmt[3] == 's' && fmt[4] == 0) { int buf_len = va_arg(args, int); // Skip formatting when using "%.*s" const char* buf = va_arg(args, const char*); if (buf == NULL) { buf = "(null)"; buf_len = ImMin(buf_len, 6); } *out_buf = buf; *out_buf_end = buf + buf_len; // Disallow not passing 'out_buf_end' here. User is expected to use it. } else { int buf_len = ImFormatStringV(g.TempBuffer.Data, g.TempBuffer.Size, fmt, args); *out_buf = g.TempBuffer.Data; if (out_buf_end) { *out_buf_end = g.TempBuffer.Data + buf_len; } } } // CRC32 needs a 1KB lookup table (not cache friendly) // Although the code to generate the table is simple and shorter than the table itself, using a const table allows us to easily: // - avoid an unnecessary branch/memory tap, - keep the ImHashXXX functions usable by static constructors, - make it thread-safe. static const ImU32 GCrc32LookupTable[256] = { 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91, 0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5, 0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59, 0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D, 0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01, 0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65, 0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9, 0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD, 0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1, 0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5, 0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79, 0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D, 0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21, 0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45, 0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9, 0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D, }; // Known size hash // It is ok to call ImHashData on a string with known length but the ### operator won't be supported. // FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements. ImGuiID ImHashData(const void* data_p, size_t data_size, ImGuiID seed) { ImU32 crc = ~seed; const unsigned char* data = (const unsigned char*)data_p; const ImU32* crc32_lut = GCrc32LookupTable; while (data_size-- != 0) crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *data++]; return ~crc; } // Zero-terminated string hash, with support for ### to reset back to seed value // We support a syntax of "label###id" where only "###id" is included in the hash, and only "label" gets displayed. // Because this syntax is rarely used we are optimizing for the common case. // - If we reach ### in the string we discard the hash so far and reset to the seed. // - We don't do 'current += 2; continue;' after handling ### to keep the code smaller/faster (measured ~10% diff in Debug build) // FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements. ImGuiID ImHashStr(const char* data_p, size_t data_size, ImGuiID seed) { seed = ~seed; ImU32 crc = seed; const unsigned char* data = (const unsigned char*)data_p; const ImU32* crc32_lut = GCrc32LookupTable; if (data_size != 0) { while (data_size-- != 0) { unsigned char c = *data++; if (c == '#' && data_size >= 2 && data[0] == '#' && data[1] == '#') crc = seed; crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c]; } } else { while (unsigned char c = *data++) { if (c == '#' && data[0] == '#' && data[1] == '#') crc = seed; crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c]; } } return ~crc; } //----------------------------------------------------------------------------- // [SECTION] MISC HELPERS/UTILITIES (File functions) //----------------------------------------------------------------------------- // Default file functions #ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS ImFileHandle ImFileOpen(const char* filename, const char* mode) { #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(__CYGWIN__) && !defined(__GNUC__) // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. // Previously we used ImTextCountCharsFromUtf8/ImTextStrFromUtf8 here but we now need to support ImWchar16 and ImWchar32! const int filename_wsize = ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0); const int mode_wsize = ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0); // Use stack buffer if possible, otherwise heap buffer. Sizes include zero terminator. // We don't rely on current ImGuiContext as this is implied to be a helper function which doesn't depend on it (see #7314). wchar_t local_temp_stack[FILENAME_MAX]; ImVector local_temp_heap; if (filename_wsize + mode_wsize > IM_ARRAYSIZE(local_temp_stack)) local_temp_heap.resize(filename_wsize + mode_wsize); wchar_t* filename_wbuf = local_temp_heap.Data ? local_temp_heap.Data : local_temp_stack; wchar_t* mode_wbuf = filename_wbuf + filename_wsize; ::MultiByteToWideChar(CP_UTF8, 0, filename, -1, filename_wbuf, filename_wsize); ::MultiByteToWideChar(CP_UTF8, 0, mode, -1, mode_wbuf, mode_wsize); return ::_wfopen(filename_wbuf, mode_wbuf); #else return fopen(filename, mode); #endif } // We should in theory be using fseeko()/ftello() with off_t and _fseeki64()/_ftelli64() with __int64, waiting for the PR that does that in a very portable pre-C++11 zero-warnings way. bool ImFileClose(ImFileHandle f) { return fclose(f) == 0; } ImU64 ImFileGetSize(ImFileHandle f) { long off = 0, sz = 0; return ((off = ftell(f)) != -1 && !fseek(f, 0, SEEK_END) && (sz = ftell(f)) != -1 && !fseek(f, off, SEEK_SET)) ? (ImU64)sz : (ImU64)-1; } ImU64 ImFileRead(void* data, ImU64 sz, ImU64 count, ImFileHandle f) { return fread(data, (size_t)sz, (size_t)count, f); } ImU64 ImFileWrite(const void* data, ImU64 sz, ImU64 count, ImFileHandle f) { return fwrite(data, (size_t)sz, (size_t)count, f); } #endif // #ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Helper: Load file content into memory // Memory allocated with IM_ALLOC(), must be freed by user using IM_FREE() == ImGui::MemFree() // This can't really be used with "rt" because fseek size won't match read size. void* ImFileLoadToMemory(const char* filename, const char* mode, size_t* out_file_size, int padding_bytes) { IM_ASSERT(filename && mode); if (out_file_size) *out_file_size = 0; ImFileHandle f; if ((f = ImFileOpen(filename, mode)) == NULL) return NULL; size_t file_size = (size_t)ImFileGetSize(f); if (file_size == (size_t)-1) { ImFileClose(f); return NULL; } void* file_data = IM_ALLOC(file_size + padding_bytes); if (file_data == NULL) { ImFileClose(f); return NULL; } if (ImFileRead(file_data, 1, file_size, f) != file_size) { ImFileClose(f); IM_FREE(file_data); return NULL; } if (padding_bytes > 0) memset((void*)(((char*)file_data) + file_size), 0, (size_t)padding_bytes); ImFileClose(f); if (out_file_size) *out_file_size = file_size; return file_data; } //----------------------------------------------------------------------------- // [SECTION] MISC HELPERS/UTILITIES (ImText* functions) //----------------------------------------------------------------------------- IM_MSVC_RUNTIME_CHECKS_OFF // Convert UTF-8 to 32-bit character, process single character input. // A nearly-branchless UTF-8 decoder, based on work of Christopher Wellons (https://github.com/skeeto/branchless-utf8). // We handle UTF-8 decoding error by skipping forward. int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end) { static const char lengths[32] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0 }; static const int masks[] = { 0x00, 0x7f, 0x1f, 0x0f, 0x07 }; static const uint32_t mins[] = { 0x400000, 0, 0x80, 0x800, 0x10000 }; static const int shiftc[] = { 0, 18, 12, 6, 0 }; static const int shifte[] = { 0, 6, 4, 2, 0 }; int len = lengths[*(const unsigned char*)in_text >> 3]; int wanted = len + (len ? 0 : 1); if (in_text_end == NULL) in_text_end = in_text + wanted; // Max length, nulls will be taken into account. // Copy at most 'len' bytes, stop copying at 0 or past in_text_end. Branch predictor does a good job here, // so it is fast even with excessive branching. unsigned char s[4]; s[0] = in_text + 0 < in_text_end ? in_text[0] : 0; s[1] = in_text + 1 < in_text_end ? in_text[1] : 0; s[2] = in_text + 2 < in_text_end ? in_text[2] : 0; s[3] = in_text + 3 < in_text_end ? in_text[3] : 0; // Assume a four-byte character and load four bytes. Unused bits are shifted out. *out_char = (uint32_t)(s[0] & masks[len]) << 18; *out_char |= (uint32_t)(s[1] & 0x3f) << 12; *out_char |= (uint32_t)(s[2] & 0x3f) << 6; *out_char |= (uint32_t)(s[3] & 0x3f) << 0; *out_char >>= shiftc[len]; // Accumulate the various error conditions. int e = 0; e = (*out_char < mins[len]) << 6; // non-canonical encoding e |= ((*out_char >> 11) == 0x1b) << 7; // surrogate half? e |= (*out_char > IM_UNICODE_CODEPOINT_MAX) << 8; // out of range? e |= (s[1] & 0xc0) >> 2; e |= (s[2] & 0xc0) >> 4; e |= (s[3] ) >> 6; e ^= 0x2a; // top two bits of each tail byte correct? e >>= shifte[len]; if (e) { // No bytes are consumed when *in_text == 0 || in_text == in_text_end. // One byte is consumed in case of invalid first byte of in_text. // All available bytes (at most `len` bytes) are consumed on incomplete/invalid second to last bytes. // Invalid or incomplete input may consume less bytes than wanted, therefore every byte has to be inspected in s. wanted = ImMin(wanted, !!s[0] + !!s[1] + !!s[2] + !!s[3]); *out_char = IM_UNICODE_CODEPOINT_INVALID; } return wanted; } int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining) { ImWchar* buf_out = buf; ImWchar* buf_end = buf + buf_size; while (buf_out < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text) { unsigned int c; in_text += ImTextCharFromUtf8(&c, in_text, in_text_end); *buf_out++ = (ImWchar)c; } *buf_out = 0; if (in_text_remaining) *in_text_remaining = in_text; return (int)(buf_out - buf); } int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end) { int char_count = 0; while ((!in_text_end || in_text < in_text_end) && *in_text) { unsigned int c; in_text += ImTextCharFromUtf8(&c, in_text, in_text_end); char_count++; } return char_count; } // Based on stb_to_utf8() from github.com/nothings/stb/ static inline int ImTextCharToUtf8_inline(char* buf, int buf_size, unsigned int c) { if (c < 0x80) { buf[0] = (char)c; return 1; } if (c < 0x800) { if (buf_size < 2) return 0; buf[0] = (char)(0xc0 + (c >> 6)); buf[1] = (char)(0x80 + (c & 0x3f)); return 2; } if (c < 0x10000) { if (buf_size < 3) return 0; buf[0] = (char)(0xe0 + (c >> 12)); buf[1] = (char)(0x80 + ((c >> 6) & 0x3f)); buf[2] = (char)(0x80 + ((c ) & 0x3f)); return 3; } if (c <= 0x10FFFF) { if (buf_size < 4) return 0; buf[0] = (char)(0xf0 + (c >> 18)); buf[1] = (char)(0x80 + ((c >> 12) & 0x3f)); buf[2] = (char)(0x80 + ((c >> 6) & 0x3f)); buf[3] = (char)(0x80 + ((c ) & 0x3f)); return 4; } // Invalid code point, the max unicode is 0x10FFFF return 0; } const char* ImTextCharToUtf8(char out_buf[5], unsigned int c) { int count = ImTextCharToUtf8_inline(out_buf, 5, c); out_buf[count] = 0; return out_buf; } // Not optimal but we very rarely use this function. int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end) { unsigned int unused = 0; return ImTextCharFromUtf8(&unused, in_text, in_text_end); } static inline int ImTextCountUtf8BytesFromChar(unsigned int c) { if (c < 0x80) return 1; if (c < 0x800) return 2; if (c < 0x10000) return 3; if (c <= 0x10FFFF) return 4; return 3; } int ImTextStrToUtf8(char* out_buf, int out_buf_size, const ImWchar* in_text, const ImWchar* in_text_end) { char* buf_p = out_buf; const char* buf_end = out_buf + out_buf_size; while (buf_p < buf_end - 1 && (!in_text_end || in_text < in_text_end) && *in_text) { unsigned int c = (unsigned int)(*in_text++); if (c < 0x80) *buf_p++ = (char)c; else buf_p += ImTextCharToUtf8_inline(buf_p, (int)(buf_end - buf_p - 1), c); } *buf_p = 0; return (int)(buf_p - out_buf); } int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end) { int bytes_count = 0; while ((!in_text_end || in_text < in_text_end) && *in_text) { unsigned int c = (unsigned int)(*in_text++); if (c < 0x80) bytes_count++; else bytes_count += ImTextCountUtf8BytesFromChar(c); } return bytes_count; } const char* ImTextFindPreviousUtf8Codepoint(const char* in_text_start, const char* in_text_curr) { while (in_text_curr > in_text_start) { in_text_curr--; if ((*in_text_curr & 0xC0) != 0x80) return in_text_curr; } return in_text_start; } IM_MSVC_RUNTIME_CHECKS_RESTORE //----------------------------------------------------------------------------- // [SECTION] MISC HELPERS/UTILITIES (Color functions) // Note: The Convert functions are early design which are not consistent with other API. //----------------------------------------------------------------------------- IMGUI_API ImU32 ImAlphaBlendColors(ImU32 col_a, ImU32 col_b) { float t = ((col_b >> IM_COL32_A_SHIFT) & 0xFF) / 255.f; int r = ImLerp((int)(col_a >> IM_COL32_R_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_R_SHIFT) & 0xFF, t); int g = ImLerp((int)(col_a >> IM_COL32_G_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_G_SHIFT) & 0xFF, t); int b = ImLerp((int)(col_a >> IM_COL32_B_SHIFT) & 0xFF, (int)(col_b >> IM_COL32_B_SHIFT) & 0xFF, t); return IM_COL32(r, g, b, 0xFF); } ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in) { float s = 1.0f / 255.0f; return ImVec4( ((in >> IM_COL32_R_SHIFT) & 0xFF) * s, ((in >> IM_COL32_G_SHIFT) & 0xFF) * s, ((in >> IM_COL32_B_SHIFT) & 0xFF) * s, ((in >> IM_COL32_A_SHIFT) & 0xFF) * s); } ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in) { ImU32 out; out = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT; out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT; out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT; out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT; return out; } // Convert rgb floats ([0-1],[0-1],[0-1]) to hsv floats ([0-1],[0-1],[0-1]), from Foley & van Dam p592 // Optimized http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv void ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v) { float K = 0.f; if (g < b) { ImSwap(g, b); K = -1.f; } if (r < g) { ImSwap(r, g); K = -2.f / 6.f - K; } const float chroma = r - (g < b ? g : b); out_h = ImFabs(K + (g - b) / (6.f * chroma + 1e-20f)); out_s = chroma / (r + 1e-20f); out_v = r; } // Convert hsv floats ([0-1],[0-1],[0-1]) to rgb floats ([0-1],[0-1],[0-1]), from Foley & van Dam p593 // also http://en.wikipedia.org/wiki/HSL_and_HSV void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b) { if (s == 0.0f) { // gray out_r = out_g = out_b = v; return; } h = ImFmod(h, 1.0f) / (60.0f / 360.0f); int i = (int)h; float f = h - (float)i; float p = v * (1.0f - s); float q = v * (1.0f - s * f); float t = v * (1.0f - s * (1.0f - f)); switch (i) { case 0: out_r = v; out_g = t; out_b = p; break; case 1: out_r = q; out_g = v; out_b = p; break; case 2: out_r = p; out_g = v; out_b = t; break; case 3: out_r = p; out_g = q; out_b = v; break; case 4: out_r = t; out_g = p; out_b = v; break; case 5: default: out_r = v; out_g = p; out_b = q; break; } } //----------------------------------------------------------------------------- // [SECTION] ImGuiStorage // Helper: Key->value storage //----------------------------------------------------------------------------- // std::lower_bound but without the bullshit static ImGuiStorage::ImGuiStoragePair* LowerBound(ImVector& data, ImGuiID key) { ImGuiStorage::ImGuiStoragePair* first = data.Data; ImGuiStorage::ImGuiStoragePair* last = data.Data + data.Size; size_t count = (size_t)(last - first); while (count > 0) { size_t count2 = count >> 1; ImGuiStorage::ImGuiStoragePair* mid = first + count2; if (mid->key < key) { first = ++mid; count -= count2 + 1; } else { count = count2; } } return first; } // For quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once. void ImGuiStorage::BuildSortByKey() { struct StaticFunc { static int IMGUI_CDECL PairComparerByID(const void* lhs, const void* rhs) { // We can't just do a subtraction because qsort uses signed integers and subtracting our ID doesn't play well with that. if (((const ImGuiStoragePair*)lhs)->key > ((const ImGuiStoragePair*)rhs)->key) return +1; if (((const ImGuiStoragePair*)lhs)->key < ((const ImGuiStoragePair*)rhs)->key) return -1; return 0; } }; ImQsort(Data.Data, (size_t)Data.Size, sizeof(ImGuiStoragePair), StaticFunc::PairComparerByID); } int ImGuiStorage::GetInt(ImGuiID key, int default_val) const { ImGuiStoragePair* it = LowerBound(const_cast&>(Data), key); if (it == Data.end() || it->key != key) return default_val; return it->val_i; } bool ImGuiStorage::GetBool(ImGuiID key, bool default_val) const { return GetInt(key, default_val ? 1 : 0) != 0; } float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const { ImGuiStoragePair* it = LowerBound(const_cast&>(Data), key); if (it == Data.end() || it->key != key) return default_val; return it->val_f; } void* ImGuiStorage::GetVoidPtr(ImGuiID key) const { ImGuiStoragePair* it = LowerBound(const_cast&>(Data), key); if (it == Data.end() || it->key != key) return NULL; return it->val_p; } // References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer. int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val) { ImGuiStoragePair* it = LowerBound(Data, key); if (it == Data.end() || it->key != key) it = Data.insert(it, ImGuiStoragePair(key, default_val)); return &it->val_i; } bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val) { return (bool*)GetIntRef(key, default_val ? 1 : 0); } float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val) { ImGuiStoragePair* it = LowerBound(Data, key); if (it == Data.end() || it->key != key) it = Data.insert(it, ImGuiStoragePair(key, default_val)); return &it->val_f; } void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val) { ImGuiStoragePair* it = LowerBound(Data, key); if (it == Data.end() || it->key != key) it = Data.insert(it, ImGuiStoragePair(key, default_val)); return &it->val_p; } // FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on explicit interaction (maximum one a frame) void ImGuiStorage::SetInt(ImGuiID key, int val) { ImGuiStoragePair* it = LowerBound(Data, key); if (it == Data.end() || it->key != key) Data.insert(it, ImGuiStoragePair(key, val)); else it->val_i = val; } void ImGuiStorage::SetBool(ImGuiID key, bool val) { SetInt(key, val ? 1 : 0); } void ImGuiStorage::SetFloat(ImGuiID key, float val) { ImGuiStoragePair* it = LowerBound(Data, key); if (it == Data.end() || it->key != key) Data.insert(it, ImGuiStoragePair(key, val)); else it->val_f = val; } void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val) { ImGuiStoragePair* it = LowerBound(Data, key); if (it == Data.end() || it->key != key) Data.insert(it, ImGuiStoragePair(key, val)); else it->val_p = val; } void ImGuiStorage::SetAllInt(int v) { for (int i = 0; i < Data.Size; i++) Data[i].val_i = v; } //----------------------------------------------------------------------------- // [SECTION] ImGuiTextFilter //----------------------------------------------------------------------------- // Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) //-V1077 { InputBuf[0] = 0; CountGrep = 0; if (default_filter) { ImStrncpy(InputBuf, default_filter, IM_ARRAYSIZE(InputBuf)); Build(); } } bool ImGuiTextFilter::Draw(const char* label, float width) { if (width != 0.0f) ImGui::SetNextItemWidth(width); bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf)); if (value_changed) Build(); return value_changed; } void ImGuiTextFilter::ImGuiTextRange::split(char separator, ImVector* out) const { out->resize(0); const char* wb = b; const char* we = wb; while (we < e) { if (*we == separator) { out->push_back(ImGuiTextRange(wb, we)); wb = we + 1; } we++; } if (wb != we) out->push_back(ImGuiTextRange(wb, we)); } void ImGuiTextFilter::Build() { Filters.resize(0); ImGuiTextRange input_range(InputBuf, InputBuf + strlen(InputBuf)); input_range.split(',', &Filters); CountGrep = 0; for (ImGuiTextRange& f : Filters) { while (f.b < f.e && ImCharIsBlankA(f.b[0])) f.b++; while (f.e > f.b && ImCharIsBlankA(f.e[-1])) f.e--; if (f.empty()) continue; if (f.b[0] != '-') CountGrep += 1; } } bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const { if (Filters.empty()) return true; if (text == NULL) text = ""; for (const ImGuiTextRange& f : Filters) { if (f.empty()) continue; if (f.b[0] == '-') { // Subtract if (ImStristr(text, text_end, f.b + 1, f.e) != NULL) return false; } else { // Grep if (ImStristr(text, text_end, f.b, f.e) != NULL) return true; } } // Implicit * grep if (CountGrep == 0) return true; return false; } //----------------------------------------------------------------------------- // [SECTION] ImGuiTextBuffer, ImGuiTextIndex //----------------------------------------------------------------------------- // On some platform vsnprintf() takes va_list by reference and modifies it. // va_copy is the 'correct' way to copy a va_list but Visual Studio prior to 2013 doesn't have it. #ifndef va_copy #if defined(__GNUC__) || defined(__clang__) #define va_copy(dest, src) __builtin_va_copy(dest, src) #else #define va_copy(dest, src) (dest = src) #endif #endif char ImGuiTextBuffer::EmptyString[1] = { 0 }; void ImGuiTextBuffer::append(const char* str, const char* str_end) { int len = str_end ? (int)(str_end - str) : (int)strlen(str); // Add zero-terminator the first time const int write_off = (Buf.Size != 0) ? Buf.Size : 1; const int needed_sz = write_off + len; if (write_off + len >= Buf.Capacity) { int new_capacity = Buf.Capacity * 2; Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity); } Buf.resize(needed_sz); memcpy(&Buf[write_off - 1], str, (size_t)len); Buf[write_off - 1 + len] = 0; } void ImGuiTextBuffer::appendf(const char* fmt, ...) { va_list args; va_start(args, fmt); appendfv(fmt, args); va_end(args); } // Helper: Text buffer for logging/accumulating text void ImGuiTextBuffer::appendfv(const char* fmt, va_list args) { va_list args_copy; va_copy(args_copy, args); int len = ImFormatStringV(NULL, 0, fmt, args); // FIXME-OPT: could do a first pass write attempt, likely successful on first pass. if (len <= 0) { va_end(args_copy); return; } // Add zero-terminator the first time const int write_off = (Buf.Size != 0) ? Buf.Size : 1; const int needed_sz = write_off + len; if (write_off + len >= Buf.Capacity) { int new_capacity = Buf.Capacity * 2; Buf.reserve(needed_sz > new_capacity ? needed_sz : new_capacity); } Buf.resize(needed_sz); ImFormatStringV(&Buf[write_off - 1], (size_t)len + 1, fmt, args_copy); va_end(args_copy); } void ImGuiTextIndex::append(const char* base, int old_size, int new_size) { IM_ASSERT(old_size >= 0 && new_size >= old_size && new_size >= EndOffset); if (old_size == new_size) return; if (EndOffset == 0 || base[EndOffset - 1] == '\n') LineOffsets.push_back(EndOffset); const char* base_end = base + new_size; for (const char* p = base + old_size; (p = (const char*)memchr(p, '\n', base_end - p)) != 0; ) if (++p < base_end) // Don't push a trailing offset on last \n LineOffsets.push_back((int)(intptr_t)(p - base)); EndOffset = ImMax(EndOffset, new_size); } //----------------------------------------------------------------------------- // [SECTION] ImGuiListClipper //----------------------------------------------------------------------------- // FIXME-TABLE: This prevents us from using ImGuiListClipper _inside_ a table cell. // The problem we have is that without a Begin/End scheme for rows using the clipper is ambiguous. static bool GetSkipItemForListClipping() { ImGuiContext& g = *GImGui; return (g.CurrentTable ? g.CurrentTable->HostSkipItems : g.CurrentWindow->SkipItems); } static void ImGuiListClipper_SortAndFuseRanges(ImVector& ranges, int offset = 0) { if (ranges.Size - offset <= 1) return; // Helper to order ranges and fuse them together if possible (bubble sort is fine as we are only sorting 2-3 entries) for (int sort_end = ranges.Size - offset - 1; sort_end > 0; --sort_end) for (int i = offset; i < sort_end + offset; ++i) if (ranges[i].Min > ranges[i + 1].Min) ImSwap(ranges[i], ranges[i + 1]); // Now fuse ranges together as much as possible. for (int i = 1 + offset; i < ranges.Size; i++) { IM_ASSERT(!ranges[i].PosToIndexConvert && !ranges[i - 1].PosToIndexConvert); if (ranges[i - 1].Max < ranges[i].Min) continue; ranges[i - 1].Min = ImMin(ranges[i - 1].Min, ranges[i].Min); ranges[i - 1].Max = ImMax(ranges[i - 1].Max, ranges[i].Max); ranges.erase(ranges.Data + i); i--; } } static void ImGuiListClipper_SeekCursorAndSetupPrevLine(float pos_y, float line_height) { // Set cursor position and a few other things so that SetScrollHereY() and Columns() can work when seeking cursor. // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue. // The clipper should probably have a final step to display the last item in a regular manner, maybe with an opt-out flag for data sets which may have costly seek? ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; float off_y = pos_y - window->DC.CursorPos.y; window->DC.CursorPos.y = pos_y; window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, pos_y - g.Style.ItemSpacing.y); window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage. window->DC.PrevLineSize.y = (line_height - g.Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. if (ImGuiOldColumns* columns = window->DC.CurrentColumns) columns->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly if (ImGuiTable* table = g.CurrentTable) { if (table->IsInsideRow) ImGui::TableEndRow(table); table->RowPosY2 = window->DC.CursorPos.y; const int row_increase = (int)((off_y / line_height) + 0.5f); //table->CurrentRow += row_increase; // Can't do without fixing TableEndRow() table->RowBgColorCounter += row_increase; } } static void ImGuiListClipper_SeekCursorForItem(ImGuiListClipper* clipper, int item_n) { // StartPosY starts from ItemsFrozen hence the subtraction // Perform the add and multiply with double to allow seeking through larger ranges ImGuiListClipperData* data = (ImGuiListClipperData*)clipper->TempData; float pos_y = (float)((double)clipper->StartPosY + data->LossynessOffset + (double)(item_n - data->ItemsFrozen) * clipper->ItemsHeight); ImGuiListClipper_SeekCursorAndSetupPrevLine(pos_y, clipper->ItemsHeight); } ImGuiListClipper::ImGuiListClipper() { memset(this, 0, sizeof(*this)); } ImGuiListClipper::~ImGuiListClipper() { End(); } void ImGuiListClipper::Begin(int items_count, float items_height) { if (Ctx == NULL) Ctx = ImGui::GetCurrentContext(); ImGuiContext& g = *Ctx; ImGuiWindow* window = g.CurrentWindow; IMGUI_DEBUG_LOG_CLIPPER("Clipper: Begin(%d,%.2f) in '%s'\n", items_count, items_height, window->Name); if (ImGuiTable* table = g.CurrentTable) if (table->IsInsideRow) ImGui::TableEndRow(table); StartPosY = window->DC.CursorPos.y; ItemsHeight = items_height; ItemsCount = items_count; DisplayStart = -1; DisplayEnd = 0; // Acquire temporary buffer if (++g.ClipperTempDataStacked > g.ClipperTempData.Size) g.ClipperTempData.resize(g.ClipperTempDataStacked, ImGuiListClipperData()); ImGuiListClipperData* data = &g.ClipperTempData[g.ClipperTempDataStacked - 1]; data->Reset(this); data->LossynessOffset = window->DC.CursorStartPosLossyness.y; TempData = data; } void ImGuiListClipper::End() { if (ImGuiListClipperData* data = (ImGuiListClipperData*)TempData) { // In theory here we should assert that we are already at the right position, but it seems saner to just seek at the end and not assert/crash the user. ImGuiContext& g = *Ctx; IMGUI_DEBUG_LOG_CLIPPER("Clipper: End() in '%s'\n", g.CurrentWindow->Name); if (ItemsCount >= 0 && ItemsCount < INT_MAX && DisplayStart >= 0) ImGuiListClipper_SeekCursorForItem(this, ItemsCount); // Restore temporary buffer and fix back pointers which may be invalidated when nesting IM_ASSERT(data->ListClipper == this); data->StepNo = data->Ranges.Size; if (--g.ClipperTempDataStacked > 0) { data = &g.ClipperTempData[g.ClipperTempDataStacked - 1]; data->ListClipper->TempData = data; } TempData = NULL; } ItemsCount = -1; } void ImGuiListClipper::IncludeItemsByIndex(int item_begin, int item_end) { ImGuiListClipperData* data = (ImGuiListClipperData*)TempData; IM_ASSERT(DisplayStart < 0); // Only allowed after Begin() and if there has not been a specified range yet. IM_ASSERT(item_begin <= item_end); if (item_begin < item_end) data->Ranges.push_back(ImGuiListClipperRange::FromIndices(item_begin, item_end)); } static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper) { ImGuiContext& g = *clipper->Ctx; ImGuiWindow* window = g.CurrentWindow; ImGuiListClipperData* data = (ImGuiListClipperData*)clipper->TempData; IM_ASSERT(data != NULL && "Called ImGuiListClipper::Step() too many times, or before ImGuiListClipper::Begin() ?"); ImGuiTable* table = g.CurrentTable; if (table && table->IsInsideRow) ImGui::TableEndRow(table); // No items if (clipper->ItemsCount == 0 || GetSkipItemForListClipping()) return false; // While we are in frozen row state, keep displaying items one by one, unclipped // FIXME: Could be stored as a table-agnostic state. if (data->StepNo == 0 && table != NULL && !table->IsUnfrozenRows) { clipper->DisplayStart = data->ItemsFrozen; clipper->DisplayEnd = ImMin(data->ItemsFrozen + 1, clipper->ItemsCount); if (clipper->DisplayStart < clipper->DisplayEnd) data->ItemsFrozen++; return true; } // Step 0: Let you process the first element (regardless of it being visible or not, so we can measure the element height) bool calc_clipping = false; if (data->StepNo == 0) { clipper->StartPosY = window->DC.CursorPos.y; if (clipper->ItemsHeight <= 0.0f) { // Submit the first item (or range) so we can measure its height (generally the first range is 0..1) data->Ranges.push_front(ImGuiListClipperRange::FromIndices(data->ItemsFrozen, data->ItemsFrozen + 1)); clipper->DisplayStart = ImMax(data->Ranges[0].Min, data->ItemsFrozen); clipper->DisplayEnd = ImMin(data->Ranges[0].Max, clipper->ItemsCount); data->StepNo = 1; return true; } calc_clipping = true; // If on the first step with known item height, calculate clipping. } // Step 1: Let the clipper infer height from first range if (clipper->ItemsHeight <= 0.0f) { IM_ASSERT(data->StepNo == 1); if (table) IM_ASSERT(table->RowPosY1 == clipper->StartPosY && table->RowPosY2 == window->DC.CursorPos.y); clipper->ItemsHeight = (window->DC.CursorPos.y - clipper->StartPosY) / (float)(clipper->DisplayEnd - clipper->DisplayStart); bool affected_by_floating_point_precision = ImIsFloatAboveGuaranteedIntegerPrecision(clipper->StartPosY) || ImIsFloatAboveGuaranteedIntegerPrecision(window->DC.CursorPos.y); if (affected_by_floating_point_precision) clipper->ItemsHeight = window->DC.PrevLineSize.y + g.Style.ItemSpacing.y; // FIXME: Technically wouldn't allow multi-line entries. IM_ASSERT(clipper->ItemsHeight > 0.0f && "Unable to calculate item height! First item hasn't moved the cursor vertically!"); calc_clipping = true; // If item height had to be calculated, calculate clipping afterwards. } // Step 0 or 1: Calculate the actual ranges of visible elements. const int already_submitted = clipper->DisplayEnd; if (calc_clipping) { if (g.LogEnabled) { // If logging is active, do not perform any clipping data->Ranges.push_back(ImGuiListClipperRange::FromIndices(0, clipper->ItemsCount)); } else { // Add range selected to be included for navigation const bool is_nav_request = (g.NavMoveScoringItems && g.NavWindow && g.NavWindow->RootWindowForNav == window->RootWindowForNav); if (is_nav_request) data->Ranges.push_back(ImGuiListClipperRange::FromPositions(g.NavScoringNoClipRect.Min.y, g.NavScoringNoClipRect.Max.y, 0, 0)); if (is_nav_request && (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && g.NavTabbingDir == -1) data->Ranges.push_back(ImGuiListClipperRange::FromIndices(clipper->ItemsCount - 1, clipper->ItemsCount)); // Add focused/active item ImRect nav_rect_abs = ImGui::WindowRectRelToAbs(window, window->NavRectRel[0]); if (g.NavId != 0 && window->NavLastIds[0] == g.NavId) data->Ranges.push_back(ImGuiListClipperRange::FromPositions(nav_rect_abs.Min.y, nav_rect_abs.Max.y, 0, 0)); // Add visible range const int off_min = (is_nav_request && g.NavMoveClipDir == ImGuiDir_Up) ? -1 : 0; const int off_max = (is_nav_request && g.NavMoveClipDir == ImGuiDir_Down) ? 1 : 0; data->Ranges.push_back(ImGuiListClipperRange::FromPositions(window->ClipRect.Min.y, window->ClipRect.Max.y, off_min, off_max)); } // Convert position ranges to item index ranges // - Very important: when a starting position is after our maximum item, we set Min to (ItemsCount - 1). This allows us to handle most forms of wrapping. // - Due to how Selectable extra padding they tend to be "unaligned" with exact unit in the item list, // which with the flooring/ceiling tend to lead to 2 items instead of one being submitted. for (ImGuiListClipperRange& range : data->Ranges) if (range.PosToIndexConvert) { int m1 = (int)(((double)range.Min - window->DC.CursorPos.y - data->LossynessOffset) / clipper->ItemsHeight); int m2 = (int)((((double)range.Max - window->DC.CursorPos.y - data->LossynessOffset) / clipper->ItemsHeight) + 0.999999f); range.Min = ImClamp(already_submitted + m1 + range.PosToIndexOffsetMin, already_submitted, clipper->ItemsCount - 1); range.Max = ImClamp(already_submitted + m2 + range.PosToIndexOffsetMax, range.Min + 1, clipper->ItemsCount); range.PosToIndexConvert = false; } ImGuiListClipper_SortAndFuseRanges(data->Ranges, data->StepNo); } // Step 0+ (if item height is given in advance) or 1+: Display the next range in line. while (data->StepNo < data->Ranges.Size) { clipper->DisplayStart = ImMax(data->Ranges[data->StepNo].Min, already_submitted); clipper->DisplayEnd = ImMin(data->Ranges[data->StepNo].Max, clipper->ItemsCount); if (clipper->DisplayStart > already_submitted) //-V1051 ImGuiListClipper_SeekCursorForItem(clipper, clipper->DisplayStart); data->StepNo++; if (clipper->DisplayStart == clipper->DisplayEnd && data->StepNo < data->Ranges.Size) continue; return true; } // After the last step: Let the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), // Advance the cursor to the end of the list and then returns 'false' to end the loop. if (clipper->ItemsCount < INT_MAX) ImGuiListClipper_SeekCursorForItem(clipper, clipper->ItemsCount); return false; } bool ImGuiListClipper::Step() { ImGuiContext& g = *Ctx; bool need_items_height = (ItemsHeight <= 0.0f); bool ret = ImGuiListClipper_StepInternal(this); if (ret && (DisplayStart == DisplayEnd)) ret = false; if (g.CurrentTable && g.CurrentTable->IsUnfrozenRows == false) IMGUI_DEBUG_LOG_CLIPPER("Clipper: Step(): inside frozen table row.\n"); if (need_items_height && ItemsHeight > 0.0f) IMGUI_DEBUG_LOG_CLIPPER("Clipper: Step(): computed ItemsHeight: %.2f.\n", ItemsHeight); if (ret) { IMGUI_DEBUG_LOG_CLIPPER("Clipper: Step(): display %d to %d.\n", DisplayStart, DisplayEnd); } else { IMGUI_DEBUG_LOG_CLIPPER("Clipper: Step(): End.\n"); End(); } return ret; } //----------------------------------------------------------------------------- // [SECTION] STYLING //----------------------------------------------------------------------------- ImGuiStyle& ImGui::GetStyle() { IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?"); return GImGui->Style; } ImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul) { ImGuiStyle& style = GImGui->Style; ImVec4 c = style.Colors[idx]; c.w *= style.Alpha * alpha_mul; return ColorConvertFloat4ToU32(c); } ImU32 ImGui::GetColorU32(const ImVec4& col) { ImGuiStyle& style = GImGui->Style; ImVec4 c = col; c.w *= style.Alpha; return ColorConvertFloat4ToU32(c); } const ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx) { ImGuiStyle& style = GImGui->Style; return style.Colors[idx]; } ImU32 ImGui::GetColorU32(ImU32 col) { ImGuiStyle& style = GImGui->Style; if (style.Alpha >= 1.0f) return col; ImU32 a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT; a = (ImU32)(a * style.Alpha); // We don't need to clamp 0..255 because Style.Alpha is in 0..1 range. return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT); } // FIXME: This may incur a round-trip (if the end user got their data from a float4) but eventually we aim to store the in-flight colors as ImU32 void ImGui::PushStyleColor(ImGuiCol idx, ImU32 col) { ImGuiContext& g = *GImGui; ImGuiColorMod backup; backup.Col = idx; backup.BackupValue = g.Style.Colors[idx]; g.ColorStack.push_back(backup); if (g.DebugFlashStyleColorIdx != idx) g.Style.Colors[idx] = ColorConvertU32ToFloat4(col); } void ImGui::PushStyleColor(ImGuiCol idx, const ImVec4& col) { ImGuiContext& g = *GImGui; ImGuiColorMod backup; backup.Col = idx; backup.BackupValue = g.Style.Colors[idx]; g.ColorStack.push_back(backup); if (g.DebugFlashStyleColorIdx != idx) g.Style.Colors[idx] = col; } void ImGui::PopStyleColor(int count) { ImGuiContext& g = *GImGui; if (g.ColorStack.Size < count) { IM_ASSERT_USER_ERROR(g.ColorStack.Size > count, "Calling PopStyleColor() too many times!"); count = g.ColorStack.Size; } while (count > 0) { ImGuiColorMod& backup = g.ColorStack.back(); g.Style.Colors[backup.Col] = backup.BackupValue; g.ColorStack.pop_back(); count--; } } static const ImGuiDataVarInfo GStyleVarInfo[] = { { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, DisabledAlpha) }, // ImGuiStyleVar_DisabledAlpha { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, WindowPadding) }, // ImGuiStyleVar_WindowPadding { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, WindowRounding) }, // ImGuiStyleVar_WindowRounding { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, WindowBorderSize) }, // ImGuiStyleVar_WindowBorderSize { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, WindowMinSize) }, // ImGuiStyleVar_WindowMinSize { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, WindowTitleAlign) }, // ImGuiStyleVar_WindowTitleAlign { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ChildRounding) }, // ImGuiStyleVar_ChildRounding { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ChildBorderSize) }, // ImGuiStyleVar_ChildBorderSize { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, PopupRounding) }, // ImGuiStyleVar_PopupRounding { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, PopupBorderSize) }, // ImGuiStyleVar_PopupBorderSize { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, FramePadding) }, // ImGuiStyleVar_FramePadding { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, FrameRounding) }, // ImGuiStyleVar_FrameRounding { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, FrameBorderSize) }, // ImGuiStyleVar_FrameBorderSize { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ItemSpacing) }, // ImGuiStyleVar_ItemSpacing { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ItemInnerSpacing) }, // ImGuiStyleVar_ItemInnerSpacing { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, IndentSpacing) }, // ImGuiStyleVar_IndentSpacing { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, CellPadding) }, // ImGuiStyleVar_CellPadding { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ScrollbarSize) }, // ImGuiStyleVar_ScrollbarSize { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabRounding) }, // ImGuiStyleVar_TabRounding { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, TabBarBorderSize) }, // ImGuiStyleVar_TabBarBorderSize { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign { ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, SeparatorTextBorderSize)},// ImGuiStyleVar_SeparatorTextBorderSize { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SeparatorTextAlign) }, // ImGuiStyleVar_SeparatorTextAlign { ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SeparatorTextPadding) }, // ImGuiStyleVar_SeparatorTextPadding }; const ImGuiDataVarInfo* ImGui::GetStyleVarInfo(ImGuiStyleVar idx) { IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT); IM_STATIC_ASSERT(IM_ARRAYSIZE(GStyleVarInfo) == ImGuiStyleVar_COUNT); return &GStyleVarInfo[idx]; } void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) { ImGuiContext& g = *GImGui; const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx); if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1) { float* pvar = (float*)var_info->GetVarPtr(&g.Style); g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar)); *pvar = val; return; } IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); } void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) { ImGuiContext& g = *GImGui; const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx); if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2) { ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style); g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar)); *pvar = val; return; } IM_ASSERT_USER_ERROR(0, "Calling PushStyleVar() variant with wrong type!"); } void ImGui::PopStyleVar(int count) { ImGuiContext& g = *GImGui; if (g.StyleVarStack.Size < count) { IM_ASSERT_USER_ERROR(g.StyleVarStack.Size > count, "Calling PopStyleVar() too many times!"); count = g.StyleVarStack.Size; } while (count > 0) { // We avoid a generic memcpy(data, &backup.Backup.., GDataTypeSize[info->Type] * info->Count), the overhead in Debug is not worth it. ImGuiStyleMod& backup = g.StyleVarStack.back(); const ImGuiDataVarInfo* info = GetStyleVarInfo(backup.VarIdx); void* data = info->GetVarPtr(&g.Style); if (info->Type == ImGuiDataType_Float && info->Count == 1) { ((float*)data)[0] = backup.BackupFloat[0]; } else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; } g.StyleVarStack.pop_back(); count--; } } const char* ImGui::GetStyleColorName(ImGuiCol idx) { // Create switch-case from enum with regexp: ImGuiCol_{.*}, --> case ImGuiCol_\1: return "\1"; switch (idx) { case ImGuiCol_Text: return "Text"; case ImGuiCol_TextDisabled: return "TextDisabled"; case ImGuiCol_WindowBg: return "WindowBg"; case ImGuiCol_ChildBg: return "ChildBg"; case ImGuiCol_PopupBg: return "PopupBg"; case ImGuiCol_Border: return "Border"; case ImGuiCol_BorderShadow: return "BorderShadow"; case ImGuiCol_FrameBg: return "FrameBg"; case ImGuiCol_FrameBgHovered: return "FrameBgHovered"; case ImGuiCol_FrameBgActive: return "FrameBgActive"; case ImGuiCol_TitleBg: return "TitleBg"; case ImGuiCol_TitleBgActive: return "TitleBgActive"; case ImGuiCol_TitleBgCollapsed: return "TitleBgCollapsed"; case ImGuiCol_MenuBarBg: return "MenuBarBg"; case ImGuiCol_ScrollbarBg: return "ScrollbarBg"; case ImGuiCol_ScrollbarGrab: return "ScrollbarGrab"; case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered"; case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive"; case ImGuiCol_CheckMark: return "CheckMark"; case ImGuiCol_SliderGrab: return "SliderGrab"; case ImGuiCol_SliderGrabActive: return "SliderGrabActive"; case ImGuiCol_Button: return "Button"; case ImGuiCol_ButtonHovered: return "ButtonHovered"; case ImGuiCol_ButtonActive: return "ButtonActive"; case ImGuiCol_Header: return "Header"; case ImGuiCol_HeaderHovered: return "HeaderHovered"; case ImGuiCol_HeaderActive: return "HeaderActive"; case ImGuiCol_Separator: return "Separator"; case ImGuiCol_SeparatorHovered: return "SeparatorHovered"; case ImGuiCol_SeparatorActive: return "SeparatorActive"; case ImGuiCol_ResizeGrip: return "ResizeGrip"; case ImGuiCol_ResizeGripHovered: return "ResizeGripHovered"; case ImGuiCol_ResizeGripActive: return "ResizeGripActive"; case ImGuiCol_Tab: return "Tab"; case ImGuiCol_TabHovered: return "TabHovered"; case ImGuiCol_TabActive: return "TabActive"; case ImGuiCol_TabUnfocused: return "TabUnfocused"; case ImGuiCol_TabUnfocusedActive: return "TabUnfocusedActive"; case ImGuiCol_PlotLines: return "PlotLines"; case ImGuiCol_PlotLinesHovered: return "PlotLinesHovered"; case ImGuiCol_PlotHistogram: return "PlotHistogram"; case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered"; case ImGuiCol_TableHeaderBg: return "TableHeaderBg"; case ImGuiCol_TableBorderStrong: return "TableBorderStrong"; case ImGuiCol_TableBorderLight: return "TableBorderLight"; case ImGuiCol_TableRowBg: return "TableRowBg"; case ImGuiCol_TableRowBgAlt: return "TableRowBgAlt"; case ImGuiCol_TextSelectedBg: return "TextSelectedBg"; case ImGuiCol_DragDropTarget: return "DragDropTarget"; case ImGuiCol_NavHighlight: return "NavHighlight"; case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight"; case ImGuiCol_NavWindowingDimBg: return "NavWindowingDimBg"; case ImGuiCol_ModalWindowDimBg: return "ModalWindowDimBg"; } IM_ASSERT(0); return "Unknown"; } //----------------------------------------------------------------------------- // [SECTION] RENDER HELPERS // Some of those (internal) functions are currently quite a legacy mess - their signature and behavior will change, // we need a nicer separation between low-level functions and high-level functions relying on the ImGui context. // Also see imgui_draw.cpp for some more which have been reworked to not rely on ImGui:: context. //----------------------------------------------------------------------------- const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end) { const char* text_display_end = text; if (!text_end) text_end = (const char*)-1; while (text_display_end < text_end && *text_display_end != '\0' && (text_display_end[0] != '#' || text_display_end[1] != '#')) text_display_end++; return text_display_end; } // Internal ImGui functions to render text // RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText() void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; // Hide anything after a '##' string const char* text_display_end; if (hide_text_after_hash) { text_display_end = FindRenderedTextEnd(text, text_end); } else { if (!text_end) text_end = text + strlen(text); // FIXME-OPT text_display_end = text_end; } if (text != text_display_end) { window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end); if (g.LogEnabled) LogRenderedText(&pos, text, text_display_end); } } void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (!text_end) text_end = text + strlen(text); // FIXME-OPT if (text != text_end) { window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width); if (g.LogEnabled) LogRenderedText(&pos, text, text_end); } } // Default clip_rect uses (pos_min,pos_max) // Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges) // FIXME-OPT: Since we have or calculate text_size we could coarse clip whole block immediately, especally for text above draw_list->DrawList. // Effectively as this is called from widget doing their own coarse clipping it's not very valuable presently. Next time function will take // better advantage of the render function taking size into account for coarse clipping. void ImGui::RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_display_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect) { // Perform CPU side clipping for single clipped element to avoid using scissor state ImVec2 pos = pos_min; const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_display_end, false, 0.0f); const ImVec2* clip_min = clip_rect ? &clip_rect->Min : &pos_min; const ImVec2* clip_max = clip_rect ? &clip_rect->Max : &pos_max; bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y); if (clip_rect) // If we had no explicit clipping rectangle then pos==clip_min need_clipping |= (pos.x < clip_min->x) || (pos.y < clip_min->y); // Align whole block. We should defer that to the better rendering function when we'll have support for individual line alignment. if (align.x > 0.0f) pos.x = ImMax(pos.x, pos.x + (pos_max.x - pos.x - text_size.x) * align.x); if (align.y > 0.0f) pos.y = ImMax(pos.y, pos.y + (pos_max.y - pos.y - text_size.y) * align.y); // Render if (need_clipping) { ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y); draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect); } else { draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL); } } void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect) { // Hide anything after a '##' string const char* text_display_end = FindRenderedTextEnd(text, text_end); const int text_len = (int)(text_display_end - text); if (text_len == 0) return; ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_display_end, text_size_if_known, align, clip_rect); if (g.LogEnabled) LogRenderedText(&pos_min, text, text_display_end); } // Another overly complex function until we reorganize everything into a nice all-in-one helper. // This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) which define _where_ the ellipsis is, from actual clipping of text and limit of the ellipsis display. // This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move. void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known) { ImGuiContext& g = *GImGui; if (text_end_full == NULL) text_end_full = FindRenderedTextEnd(text); const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_end_full, false, 0.0f); //draw_list->AddLine(ImVec2(pos_max.x, pos_min.y - 4), ImVec2(pos_max.x, pos_max.y + 4), IM_COL32(0, 0, 255, 255)); //draw_list->AddLine(ImVec2(ellipsis_max_x, pos_min.y-2), ImVec2(ellipsis_max_x, pos_max.y+2), IM_COL32(0, 255, 0, 255)); //draw_list->AddLine(ImVec2(clip_max_x, pos_min.y), ImVec2(clip_max_x, pos_max.y), IM_COL32(255, 0, 0, 255)); // FIXME: We could technically remove (last_glyph->AdvanceX - last_glyph->X1) from text_size.x here and save a few pixels. if (text_size.x > pos_max.x - pos_min.x) { // Hello wo... // | | | // min max ellipsis_max // <-> this is generally some padding value const ImFont* font = draw_list->_Data->Font; const float font_size = draw_list->_Data->FontSize; const float font_scale = font_size / font->FontSize; const char* text_end_ellipsis = NULL; const float ellipsis_width = font->EllipsisWidth * font_scale; // We can now claim the space between pos_max.x and ellipsis_max.x const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_width) - pos_min.x, 1.0f); float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; if (text == text_end_ellipsis && text_end_ellipsis < text_end_full) { // Always display at least 1 character if there's no room for character + ellipsis text_end_ellipsis = text + ImTextCountUtf8BytesFromChar(text, text_end_full); text_size_clipped_x = font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text, text_end_ellipsis).x; } while (text_end_ellipsis > text && ImCharIsBlankA(text_end_ellipsis[-1])) { // Trim trailing space before ellipsis (FIXME: Supporting non-ascii blanks would be nice, for this we need a function to backtrack in UTF-8 text) text_end_ellipsis--; text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x; // Ascii blanks are always 1 byte } // Render text, render ellipsis RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f)); ImVec2 ellipsis_pos = ImTrunc(ImVec2(pos_min.x + text_size_clipped_x, pos_min.y)); if (ellipsis_pos.x + ellipsis_width <= ellipsis_max_x) for (int i = 0; i < font->EllipsisCharCount; i++, ellipsis_pos.x += font->EllipsisCharStep * font_scale) font->RenderChar(draw_list, font_size, ellipsis_pos, GetColorU32(ImGuiCol_Text), font->EllipsisChar); } else { RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_full, &text_size, ImVec2(0.0f, 0.0f)); } if (g.LogEnabled) LogRenderedText(&pos_min, text, text_end_full); } // Render a rectangle shaped with optional rounding and borders void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, float rounding) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding); const float border_size = g.Style.FrameBorderSize; if (border && border_size > 0.0f) { window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size); window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size); } } void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; const float border_size = g.Style.FrameBorderSize; if (border_size > 0.0f) { window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size); window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size); } } void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags) { ImGuiContext& g = *GImGui; if (id != g.NavId) return; if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw)) return; ImGuiWindow* window = g.CurrentWindow; if (window->DC.NavHideHighlightOneFrame) return; float rounding = (flags & ImGuiNavHighlightFlags_NoRounding) ? 0.0f : g.Style.FrameRounding; ImRect display_rect = bb; display_rect.ClipWith(window->ClipRect); const float thickness = 2.0f; if (flags & ImGuiNavHighlightFlags_Compact) { window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, 0, thickness); } else { const float distance = 3.0f + thickness * 0.5f; display_rect.Expand(ImVec2(distance, distance)); bool fully_visible = window->ClipRect.Contains(display_rect); if (!fully_visible) window->DrawList->PushClipRect(display_rect.Min, display_rect.Max); window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, 0, thickness); if (!fully_visible) window->DrawList->PopClipRect(); } } void ImGui::RenderMouseCursor(ImVec2 base_pos, float base_scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow) { ImGuiContext& g = *GImGui; IM_ASSERT(mouse_cursor > ImGuiMouseCursor_None && mouse_cursor < ImGuiMouseCursor_COUNT); ImFontAtlas* font_atlas = g.DrawListSharedData.Font->ContainerAtlas; for (ImGuiViewportP* viewport : g.Viewports) { // We scale cursor with current viewport/monitor, however Windows 10 for its own hardware cursor seems to be using a different scale factor. ImVec2 offset, size, uv[4]; if (!font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2])) continue; const ImVec2 pos = base_pos - offset; const float scale = base_scale; if (!viewport->GetMainRect().Overlaps(ImRect(pos, pos + ImVec2(size.x + 2, size.y + 2) * scale))) continue; ImDrawList* draw_list = GetForegroundDrawList(viewport); ImTextureID tex_id = font_atlas->TexID; draw_list->PushTextureID(tex_id); draw_list->AddImage(tex_id, pos + ImVec2(1, 0) * scale, pos + (ImVec2(1, 0) + size) * scale, uv[2], uv[3], col_shadow); draw_list->AddImage(tex_id, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow); draw_list->AddImage(tex_id, pos, pos + size * scale, uv[2], uv[3], col_border); draw_list->AddImage(tex_id, pos, pos + size * scale, uv[0], uv[1], col_fill); draw_list->PopTextureID(); } } //----------------------------------------------------------------------------- // [SECTION] INITIALIZATION, SHUTDOWN //----------------------------------------------------------------------------- // Internal state access - if you want to share Dear ImGui state between modules (e.g. DLL) or allocate it yourself // Note that we still point to some static data and members (such as GFontAtlas), so the state instance you end up using will point to the static data within its module ImGuiContext* ImGui::GetCurrentContext() { return GImGui; } void ImGui::SetCurrentContext(ImGuiContext* ctx) { #ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx); // For custom thread-based hackery you may want to have control over this. #else GImGui = ctx; #endif } void ImGui::SetAllocatorFunctions(ImGuiMemAllocFunc alloc_func, ImGuiMemFreeFunc free_func, void* user_data) { GImAllocatorAllocFunc = alloc_func; GImAllocatorFreeFunc = free_func; GImAllocatorUserData = user_data; } // This is provided to facilitate copying allocators from one static/DLL boundary to another (e.g. retrieve default allocator of your executable address space) void ImGui::GetAllocatorFunctions(ImGuiMemAllocFunc* p_alloc_func, ImGuiMemFreeFunc* p_free_func, void** p_user_data) { *p_alloc_func = GImAllocatorAllocFunc; *p_free_func = GImAllocatorFreeFunc; *p_user_data = GImAllocatorUserData; } ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas) { ImGuiContext* prev_ctx = GetCurrentContext(); ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas); SetCurrentContext(ctx); Initialize(); if (prev_ctx != NULL) SetCurrentContext(prev_ctx); // Restore previous context if any, else keep new one. return ctx; } void ImGui::DestroyContext(ImGuiContext* ctx) { ImGuiContext* prev_ctx = GetCurrentContext(); if (ctx == NULL) //-V1051 ctx = prev_ctx; SetCurrentContext(ctx); Shutdown(); SetCurrentContext((prev_ctx != ctx) ? prev_ctx : NULL); IM_DELETE(ctx); } // IMPORTANT: ###xxx suffixes must be same in ALL languages static const ImGuiLocEntry GLocalizationEntriesEnUS[] = { { ImGuiLocKey_VersionStr, "Dear ImGui " IMGUI_VERSION " (" IM_STRINGIFY(IMGUI_VERSION_NUM) ")" }, { ImGuiLocKey_TableSizeOne, "Size column to fit###SizeOne" }, { ImGuiLocKey_TableSizeAllFit, "Size all columns to fit###SizeAll" }, { ImGuiLocKey_TableSizeAllDefault, "Size all columns to default###SizeAll" }, { ImGuiLocKey_TableResetOrder, "Reset order###ResetOrder" }, { ImGuiLocKey_WindowingMainMenuBar, "(Main menu bar)" }, { ImGuiLocKey_WindowingPopup, "(Popup)" }, { ImGuiLocKey_WindowingUntitled, "(Untitled)" }, }; void ImGui::Initialize() { ImGuiContext& g = *GImGui; IM_ASSERT(!g.Initialized && !g.SettingsLoaded); // Add .ini handle for ImGuiWindow and ImGuiTable types { ImGuiSettingsHandler ini_handler; ini_handler.TypeName = "Window"; ini_handler.TypeHash = ImHashStr("Window"); ini_handler.ClearAllFn = WindowSettingsHandler_ClearAll; ini_handler.ReadOpenFn = WindowSettingsHandler_ReadOpen; ini_handler.ReadLineFn = WindowSettingsHandler_ReadLine; ini_handler.ApplyAllFn = WindowSettingsHandler_ApplyAll; ini_handler.WriteAllFn = WindowSettingsHandler_WriteAll; AddSettingsHandler(&ini_handler); } TableSettingsAddSettingsHandler(); // Setup default localization table LocalizeRegisterEntries(GLocalizationEntriesEnUS, IM_ARRAYSIZE(GLocalizationEntriesEnUS)); // Setup default platform clipboard/IME handlers. g.IO.GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations g.IO.SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; g.IO.ClipboardUserData = (void*)&g; // Default implementation use the ImGuiContext as user data (ideally those would be arguments to the function) g.IO.SetPlatformImeDataFn = SetPlatformImeDataFn_DefaultImpl; // Create default viewport ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)(); viewport->ID = IMGUI_VIEWPORT_DEFAULT_ID; g.Viewports.push_back(viewport); g.TempBuffer.resize(1024 * 3 + 1, 0); // Build KeysMayBeCharInput[] lookup table (1 bool per named key) for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) if ((key >= ImGuiKey_0 && key <= ImGuiKey_9) || (key >= ImGuiKey_A && key <= ImGuiKey_Z) || (key >= ImGuiKey_Keypad0 && key <= ImGuiKey_Keypad9) || key == ImGuiKey_Tab || key == ImGuiKey_Space || key == ImGuiKey_Apostrophe || key == ImGuiKey_Comma || key == ImGuiKey_Minus || key == ImGuiKey_Period || key == ImGuiKey_Slash || key == ImGuiKey_Semicolon || key == ImGuiKey_Equal || key == ImGuiKey_LeftBracket || key == ImGuiKey_RightBracket || key == ImGuiKey_GraveAccent || key == ImGuiKey_KeypadDecimal || key == ImGuiKey_KeypadDivide || key == ImGuiKey_KeypadMultiply || key == ImGuiKey_KeypadSubtract || key == ImGuiKey_KeypadAdd || key == ImGuiKey_KeypadEqual) g.KeysMayBeCharInput.SetBit(key); #ifdef IMGUI_HAS_DOCK #endif g.Initialized = true; } // This function is merely here to free heap allocations. void ImGui::Shutdown() { ImGuiContext& g = *GImGui; IM_ASSERT_USER_ERROR(g.IO.BackendPlatformUserData == NULL, "Forgot to shutdown Platform backend?"); IM_ASSERT_USER_ERROR(g.IO.BackendRendererUserData == NULL, "Forgot to shutdown Renderer backend?"); // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame) if (g.IO.Fonts && g.FontAtlasOwnedByContext) { g.IO.Fonts->Locked = false; IM_DELETE(g.IO.Fonts); } g.IO.Fonts = NULL; g.DrawListSharedData.TempBuffer.clear(); // Cleanup of other data are conditional on actually having initialized Dear ImGui. if (!g.Initialized) return; // Save settings (unless we haven't attempted to load them: CreateContext/DestroyContext without a call to NewFrame shouldn't save an empty file) if (g.SettingsLoaded && g.IO.IniFilename != NULL) SaveIniSettingsToDisk(g.IO.IniFilename); CallContextHooks(&g, ImGuiContextHookType_Shutdown); // Clear everything else g.Windows.clear_delete(); g.WindowsFocusOrder.clear(); g.WindowsTempSortBuffer.clear(); g.CurrentWindow = NULL; g.CurrentWindowStack.clear(); g.WindowsById.Clear(); g.NavWindow = NULL; g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL; g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL; g.MovingWindow = NULL; g.KeysRoutingTable.Clear(); g.ColorStack.clear(); g.StyleVarStack.clear(); g.FontStack.clear(); g.OpenPopupStack.clear(); g.BeginPopupStack.clear(); g.NavTreeNodeStack.clear(); g.Viewports.clear_delete(); g.TabBars.Clear(); g.CurrentTabBarStack.clear(); g.ShrinkWidthBuffer.clear(); g.ClipperTempData.clear_destruct(); g.Tables.Clear(); g.TablesTempData.clear_destruct(); g.DrawChannelsTempMergeBuffer.clear(); g.ClipboardHandlerData.clear(); g.MenusIdSubmittedThisFrame.clear(); g.InputTextState.ClearFreeMemory(); g.InputTextDeactivatedState.ClearFreeMemory(); g.SettingsWindows.clear(); g.SettingsHandlers.clear(); if (g.LogFile) { #ifndef IMGUI_DISABLE_TTY_FUNCTIONS if (g.LogFile != stdout) #endif ImFileClose(g.LogFile); g.LogFile = NULL; } g.LogBuffer.clear(); g.DebugLogBuf.clear(); g.DebugLogIndex.clear(); g.Initialized = false; } // No specific ordering/dependency support, will see as needed ImGuiID ImGui::AddContextHook(ImGuiContext* ctx, const ImGuiContextHook* hook) { ImGuiContext& g = *ctx; IM_ASSERT(hook->Callback != NULL && hook->HookId == 0 && hook->Type != ImGuiContextHookType_PendingRemoval_); g.Hooks.push_back(*hook); g.Hooks.back().HookId = ++g.HookIdNext; return g.HookIdNext; } // Deferred removal, avoiding issue with changing vector while iterating it void ImGui::RemoveContextHook(ImGuiContext* ctx, ImGuiID hook_id) { ImGuiContext& g = *ctx; IM_ASSERT(hook_id != 0); for (ImGuiContextHook& hook : g.Hooks) if (hook.HookId == hook_id) hook.Type = ImGuiContextHookType_PendingRemoval_; } // Call context hooks (used by e.g. test engine) // We assume a small number of hooks so all stored in same array void ImGui::CallContextHooks(ImGuiContext* ctx, ImGuiContextHookType hook_type) { ImGuiContext& g = *ctx; for (ImGuiContextHook& hook : g.Hooks) if (hook.Type == hook_type) hook.Callback(&g, &hook); } //----------------------------------------------------------------------------- // [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!) //----------------------------------------------------------------------------- // ImGuiWindow is mostly a dumb struct. It merely has a constructor and a few helper methods ImGuiWindow::ImGuiWindow(ImGuiContext* ctx, const char* name) : DrawListInst(NULL) { memset(this, 0, sizeof(*this)); Ctx = ctx; Name = ImStrdup(name); NameBufLen = (int)strlen(name) + 1; ID = ImHashStr(name); IDStack.push_back(ID); MoveId = GetID("#MOVE"); ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f); AutoFitFramesX = AutoFitFramesY = -1; AutoPosLastDirection = ImGuiDir_None; SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = 0; SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX); LastFrameActive = -1; LastTimeActive = -1.0f; FontWindowScale = 1.0f; SettingsOffset = -1; DrawList = &DrawListInst; DrawList->_Data = &Ctx->DrawListSharedData; DrawList->_OwnerName = Name; NavPreferredScoringPosRel[0] = NavPreferredScoringPosRel[1] = ImVec2(FLT_MAX, FLT_MAX); } ImGuiWindow::~ImGuiWindow() { IM_ASSERT(DrawList == &DrawListInst); IM_DELETE(Name); ColumnsStorage.clear_destruct(); } ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end) { ImGuiID seed = IDStack.back(); ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed); ImGuiContext& g = *Ctx; if (g.DebugHookIdInfo == id) ImGui::DebugHookIdInfo(id, ImGuiDataType_String, str, str_end); return id; } ImGuiID ImGuiWindow::GetID(const void* ptr) { ImGuiID seed = IDStack.back(); ImGuiID id = ImHashData(&ptr, sizeof(void*), seed); ImGuiContext& g = *Ctx; if (g.DebugHookIdInfo == id) ImGui::DebugHookIdInfo(id, ImGuiDataType_Pointer, ptr, NULL); return id; } ImGuiID ImGuiWindow::GetID(int n) { ImGuiID seed = IDStack.back(); ImGuiID id = ImHashData(&n, sizeof(n), seed); ImGuiContext& g = *Ctx; if (g.DebugHookIdInfo == id) ImGui::DebugHookIdInfo(id, ImGuiDataType_S32, (void*)(intptr_t)n, NULL); return id; } // This is only used in rare/specific situations to manufacture an ID out of nowhere. ImGuiID ImGuiWindow::GetIDFromRectangle(const ImRect& r_abs) { ImGuiID seed = IDStack.back(); ImRect r_rel = ImGui::WindowRectAbsToRel(this, r_abs); ImGuiID id = ImHashData(&r_rel, sizeof(r_rel), seed); return id; } static void SetCurrentWindow(ImGuiWindow* window) { ImGuiContext& g = *GImGui; g.CurrentWindow = window; g.CurrentTable = window && window->DC.CurrentTableIdx != -1 ? g.Tables.GetByIndex(window->DC.CurrentTableIdx) : NULL; if (window) { g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize(); ImGui::NavUpdateCurrentWindowIsScrollPushableX(); } } void ImGui::GcCompactTransientMiscBuffers() { ImGuiContext& g = *GImGui; g.ItemFlagsStack.clear(); g.GroupStack.clear(); TableGcCompactSettings(); } // Free up/compact internal window buffers, we can use this when a window becomes unused. // Not freed: // - ImGuiWindow, ImGuiWindowSettings, Name, StateStorage, ColumnsStorage (may hold useful data) // This should have no noticeable visual effect. When the window reappear however, expect new allocation/buffer growth/copy cost. void ImGui::GcCompactTransientWindowBuffers(ImGuiWindow* window) { window->MemoryCompacted = true; window->MemoryDrawListIdxCapacity = window->DrawList->IdxBuffer.Capacity; window->MemoryDrawListVtxCapacity = window->DrawList->VtxBuffer.Capacity; window->IDStack.clear(); window->DrawList->_ClearFreeMemory(); window->DC.ChildWindows.clear(); window->DC.ItemWidthStack.clear(); window->DC.TextWrapPosStack.clear(); } void ImGui::GcAwakeTransientWindowBuffers(ImGuiWindow* window) { // We stored capacity of the ImDrawList buffer to reduce growth-caused allocation/copy when awakening. // The other buffers tends to amortize much faster. window->MemoryCompacted = false; window->DrawList->IdxBuffer.reserve(window->MemoryDrawListIdxCapacity); window->DrawList->VtxBuffer.reserve(window->MemoryDrawListVtxCapacity); window->MemoryDrawListIdxCapacity = window->MemoryDrawListVtxCapacity = 0; } void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) { ImGuiContext& g = *GImGui; // Clear previous active id if (g.ActiveId != 0) { // While most behaved code would make an effort to not steal active id during window move/drag operations, // we at least need to be resilient to it. Canceling the move is rather aggressive and users of 'master' branch // may prefer the weird ill-defined half working situation ('docking' did assert), so may need to rework that. if (g.MovingWindow != NULL && g.ActiveId == g.MovingWindow->MoveId) { IMGUI_DEBUG_LOG_ACTIVEID("SetActiveID() cancel MovingWindow\n"); g.MovingWindow = NULL; } // This could be written in a more general way (e.g associate a hook to ActiveId), // but since this is currently quite an exception we'll leave it as is. // One common scenario leading to this is: pressing Key ->NavMoveRequestApplyResult() -> ClearActiveId() if (g.InputTextState.ID == g.ActiveId) InputTextDeactivateHook(g.ActiveId); } // Set active id g.ActiveIdIsJustActivated = (g.ActiveId != id); if (g.ActiveIdIsJustActivated) { IMGUI_DEBUG_LOG_ACTIVEID("SetActiveID() old:0x%08X (window \"%s\") -> new:0x%08X (window \"%s\")\n", g.ActiveId, g.ActiveIdWindow ? g.ActiveIdWindow->Name : "", id, window ? window->Name : ""); g.ActiveIdTimer = 0.0f; g.ActiveIdHasBeenPressedBefore = false; g.ActiveIdHasBeenEditedBefore = false; g.ActiveIdMouseButton = -1; if (id != 0) { g.LastActiveId = id; g.LastActiveIdTimer = 0.0f; } } g.ActiveId = id; g.ActiveIdAllowOverlap = false; g.ActiveIdNoClearOnFocusLoss = false; g.ActiveIdWindow = window; g.ActiveIdHasBeenEditedThisFrame = false; g.ActiveIdFromShortcut = false; if (id) { g.ActiveIdIsAlive = id; g.ActiveIdSource = (g.NavActivateId == id || g.NavJustMovedToId == id) ? g.NavInputSource : ImGuiInputSource_Mouse; IM_ASSERT(g.ActiveIdSource != ImGuiInputSource_None); } // Clear declaration of inputs claimed by the widget // (Please note that this is WIP and not all keys/inputs are thoroughly declared by all widgets yet) g.ActiveIdUsingNavDirMask = 0x00; g.ActiveIdUsingAllKeyboardKeys = false; #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO g.ActiveIdUsingNavInputMask = 0x00; #endif } void ImGui::ClearActiveID() { SetActiveID(0, NULL); // g.ActiveId = 0; } void ImGui::SetHoveredID(ImGuiID id) { ImGuiContext& g = *GImGui; g.HoveredId = id; g.HoveredIdAllowOverlap = false; if (id != 0 && g.HoveredIdPreviousFrame != id) g.HoveredIdTimer = g.HoveredIdNotActiveTimer = 0.0f; } ImGuiID ImGui::GetHoveredID() { ImGuiContext& g = *GImGui; return g.HoveredId ? g.HoveredId : g.HoveredIdPreviousFrame; } void ImGui::MarkItemEdited(ImGuiID id) { // This marking is solely to be able to provide info for IsItemDeactivatedAfterEdit(). // ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need to fill the data. ImGuiContext& g = *GImGui; if (g.LockMarkEdited > 0) return; if (g.ActiveId == id || g.ActiveId == 0) { g.ActiveIdHasBeenEditedThisFrame = true; g.ActiveIdHasBeenEditedBefore = true; } // We accept a MarkItemEdited() on drag and drop targets (see https://github.com/ocornut/imgui/issues/1875#issuecomment-978243343) // We accept 'ActiveIdPreviousFrame == id' for InputText() returning an edit after it has been taken ActiveId away (#4714) IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.ActiveIdPreviousFrame == id); //IM_ASSERT(g.CurrentWindow->DC.LastItemId == id); g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited; } bool ImGui::IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags) { // An active popup disable hovering on other windows (apart from its own children) // FIXME-OPT: This could be cached/stored within the window. ImGuiContext& g = *GImGui; if (g.NavWindow) if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow) if (focused_root_window->WasActive && focused_root_window != window->RootWindow) { // For the purpose of those flags we differentiate "standard popup" from "modal popup" // NB: The 'else' is important because Modal windows are also Popups. bool want_inhibit = false; if (focused_root_window->Flags & ImGuiWindowFlags_Modal) want_inhibit = true; else if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup)) want_inhibit = true; // Inhibit hover unless the window is within the stack of our modal/popup if (want_inhibit) if (!IsWindowWithinBeginStackOf(window->RootWindow, focused_root_window)) return false; } return true; } static inline float CalcDelayFromHoveredFlags(ImGuiHoveredFlags flags) { ImGuiContext& g = *GImGui; if (flags & ImGuiHoveredFlags_DelayNormal) return g.Style.HoverDelayNormal; if (flags & ImGuiHoveredFlags_DelayShort) return g.Style.HoverDelayShort; return 0.0f; } static ImGuiHoveredFlags ApplyHoverFlagsForTooltip(ImGuiHoveredFlags user_flags, ImGuiHoveredFlags shared_flags) { // Allow instance flags to override shared flags if (user_flags & (ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal)) shared_flags &= ~(ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal); return user_flags | shared_flags; } // This is roughly matching the behavior of internal-facing ItemHoverable() // - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered() // - this should work even for non-interactive items that have no ID, so we cannot use LastItemId bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; IM_ASSERT((flags & ~ImGuiHoveredFlags_AllowedMaskForIsItemHovered) == 0 && "Invalid flags for IsItemHovered()!"); if (g.NavDisableMouseHover && !g.NavDisableHighlight && !(flags & ImGuiHoveredFlags_NoNavOverride)) { if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled)) return false; if (!IsItemFocused()) return false; if (flags & ImGuiHoveredFlags_ForTooltip) flags = ApplyHoverFlagsForTooltip(flags, g.Style.HoverFlagsForTooltipNav); } else { // Test for bounding box overlap, as updated as ItemAdd() ImGuiItemStatusFlags status_flags = g.LastItemData.StatusFlags; if (!(status_flags & ImGuiItemStatusFlags_HoveredRect)) return false; if (flags & ImGuiHoveredFlags_ForTooltip) flags = ApplyHoverFlagsForTooltip(flags, g.Style.HoverFlagsForTooltipMouse); IM_ASSERT((flags & (ImGuiHoveredFlags_AnyWindow | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_NoPopupHierarchy)) == 0); // Flags not supported by this function // Done with rectangle culling so we can perform heavier checks now // Test if we are hovering the right window (our window could be behind another window) // [2021/03/02] Reworked / reverted the revert, finally. Note we want e.g. BeginGroup/ItemAdd/EndGroup to work as well. (#3851) // [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable // to use IsItemHovered() after EndChild() itself. Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was // the test that has been running for a long while. if (g.HoveredWindow != window && (status_flags & ImGuiItemStatusFlags_HoveredWindow) == 0) if ((flags & ImGuiHoveredFlags_AllowWhenOverlappedByWindow) == 0) return false; // Test if another item is active (e.g. being dragged) const ImGuiID id = g.LastItemData.ID; if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0) if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId) return false; // Test if interactions on this window are blocked by an active popup or modal. // The ImGuiHoveredFlags_AllowWhenBlockedByPopup flag will be tested here. if (!IsWindowContentHoverable(window, flags) && !(g.LastItemData.InFlags & ImGuiItemFlags_NoWindowHoverableCheck)) return false; // Test if the item is disabled if ((g.LastItemData.InFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled)) return false; // Special handling for calling after Begin() which represent the title bar or tab. // When the window is skipped/collapsed (SkipItems==true) that last item will never be overwritten so we need to detect the case. if (id == window->MoveId && window->WriteAccessed) return false; // Test if using AllowOverlap and overlapped if ((g.LastItemData.InFlags & ImGuiItemFlags_AllowOverlap) && id != 0) if ((flags & ImGuiHoveredFlags_AllowWhenOverlappedByItem) == 0) if (g.HoveredIdPreviousFrame != g.LastItemData.ID) return false; } // Handle hover delay // (some ideas: https://www.nngroup.com/articles/timing-exposing-content) const float delay = CalcDelayFromHoveredFlags(flags); if (delay > 0.0f || (flags & ImGuiHoveredFlags_Stationary)) { ImGuiID hover_delay_id = (g.LastItemData.ID != 0) ? g.LastItemData.ID : window->GetIDFromRectangle(g.LastItemData.Rect); if ((flags & ImGuiHoveredFlags_NoSharedDelay) && (g.HoverItemDelayIdPreviousFrame != hover_delay_id)) g.HoverItemDelayTimer = 0.0f; g.HoverItemDelayId = hover_delay_id; // When changing hovered item we requires a bit of stationary delay before activating hover timer, // but once unlocked on a given item we also moving. //if (g.HoverDelayTimer >= delay && (g.HoverDelayTimer - g.IO.DeltaTime < delay || g.MouseStationaryTimer - g.IO.DeltaTime < g.Style.HoverStationaryDelay)) { IMGUI_DEBUG_LOG("HoverDelayTimer = %f/%f, MouseStationaryTimer = %f\n", g.HoverDelayTimer, delay, g.MouseStationaryTimer); } if ((flags & ImGuiHoveredFlags_Stationary) != 0 && g.HoverItemUnlockedStationaryId != hover_delay_id) return false; if (g.HoverItemDelayTimer < delay) return false; } return true; } // Internal facing ItemHoverable() used when submitting widgets. Differs slightly from IsItemHovered(). // (this does not rely on LastItemData it can be called from a ButtonBehavior() call not following an ItemAdd() call) // FIXME-LEGACY: the 'ImGuiItemFlags item_flags' parameter was added on 2023-06-28. // If you used this in your legacy/custom widgets code: // - Commonly: if your ItemHoverable() call comes after an ItemAdd() call: pass 'item_flags = g.LastItemData.InFlags'. // - Rare: otherwise you may pass 'item_flags = 0' (ImGuiItemFlags_None) unless you want to benefit from special behavior handled by ItemHoverable. bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (g.HoveredWindow != window) return false; if (!IsMouseHoveringRect(bb.Min, bb.Max)) return false; if (g.HoveredId != 0 && g.HoveredId != id && !g.HoveredIdAllowOverlap) return false; if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap) if (!g.ActiveIdFromShortcut) return false; // Done with rectangle culling so we can perform heavier checks now. if (!(item_flags & ImGuiItemFlags_NoWindowHoverableCheck) && !IsWindowContentHoverable(window, ImGuiHoveredFlags_None)) { g.HoveredIdDisabled = true; return false; } // We exceptionally allow this function to be called with id==0 to allow using it for easy high-level // hover test in widgets code. We could also decide to split this function is two. if (id != 0) { // Drag source doesn't report as hovered if (g.DragDropActive && g.DragDropPayload.SourceId == id && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoDisableHover)) return false; SetHoveredID(id); // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. // This allows using patterns where a later submitted widget overlaps a previous one. Generally perceived as a front-to-back hit-test. if (item_flags & ImGuiItemFlags_AllowOverlap) { g.HoveredIdAllowOverlap = true; if (g.HoveredIdPreviousFrame != id) return false; } } // When disabled we'll return false but still set HoveredId if (item_flags & ImGuiItemFlags_Disabled) { // Release active id if turning disabled if (g.ActiveId == id && id != 0) ClearActiveID(); g.HoveredIdDisabled = true; return false; } #ifndef IMGUI_DISABLE_DEBUG_TOOLS if (id != 0) { // [DEBUG] Item Picker tool! // We perform the check here because reaching is path is rare (1~ time a frame), // making the cost of this tool near-zero! We could get better call-stack and support picking non-hovered // items if we performed the test in ItemAdd(), but that would incur a bigger runtime cost. if (g.DebugItemPickerActive && g.HoveredIdPreviousFrame == id) GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255)); if (g.DebugItemPickerBreakId == id) IM_DEBUG_BREAK(); } #endif if (g.NavDisableMouseHover) return false; return true; } // FIXME: This is inlined/duplicated in ItemAdd() // FIXME: The id != 0 path is not used by our codebase, may get rid of it? bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (!bb.Overlaps(window->ClipRect)) if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId && id != g.NavActivateId)) if (!g.LogEnabled) return true; return false; } // This is also inlined in ItemAdd() // Note: if ImGuiItemStatusFlags_HasDisplayRect is set, user needs to set g.LastItemData.DisplayRect. void ImGui::SetLastItemData(ImGuiID item_id, ImGuiItemFlags in_flags, ImGuiItemStatusFlags item_flags, const ImRect& item_rect) { ImGuiContext& g = *GImGui; g.LastItemData.ID = item_id; g.LastItemData.InFlags = in_flags; g.LastItemData.StatusFlags = item_flags; g.LastItemData.Rect = g.LastItemData.NavRect = item_rect; } float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x) { if (wrap_pos_x < 0.0f) return 0.0f; ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (wrap_pos_x == 0.0f) { // We could decide to setup a default wrapping max point for auto-resizing windows, // or have auto-wrap (with unspecified wrapping pos) behave as a ContentSize extending function? //if (window->Hidden && (window->Flags & ImGuiWindowFlags_AlwaysAutoResize)) // wrap_pos_x = ImMax(window->WorkRect.Min.x + g.FontSize * 10.0f, window->WorkRect.Max.x); //else wrap_pos_x = window->WorkRect.Max.x; } else if (wrap_pos_x > 0.0f) { wrap_pos_x += window->Pos.x - window->Scroll.x; // wrap_pos_x is provided is window local space } return ImMax(wrap_pos_x - pos.x, 1.0f); } // IM_ALLOC() == ImGui::MemAlloc() void* ImGui::MemAlloc(size_t size) { void* ptr = (*GImAllocatorAllocFunc)(size, GImAllocatorUserData); #ifndef IMGUI_DISABLE_DEBUG_TOOLS if (ImGuiContext* ctx = GImGui) DebugAllocHook(&ctx->DebugAllocInfo, ctx->FrameCount, ptr, size); #endif return ptr; } // IM_FREE() == ImGui::MemFree() void ImGui::MemFree(void* ptr) { #ifndef IMGUI_DISABLE_DEBUG_TOOLS if (ptr != NULL) if (ImGuiContext* ctx = GImGui) DebugAllocHook(&ctx->DebugAllocInfo, ctx->FrameCount, ptr, (size_t)-1); #endif return (*GImAllocatorFreeFunc)(ptr, GImAllocatorUserData); } // We record the number of allocation in recent frames, as a way to audit/sanitize our guiding principles of "no allocations on idle/repeating frames" void ImGui::DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size) { ImGuiDebugAllocEntry* entry = &info->LastEntriesBuf[info->LastEntriesIdx]; IM_UNUSED(ptr); if (entry->FrameCount != frame_count) { info->LastEntriesIdx = (info->LastEntriesIdx + 1) % IM_ARRAYSIZE(info->LastEntriesBuf); entry = &info->LastEntriesBuf[info->LastEntriesIdx]; entry->FrameCount = frame_count; entry->AllocCount = entry->FreeCount = 0; } if (size != (size_t)-1) { entry->AllocCount++; info->TotalAllocCount++; //printf("[%05d] MemAlloc(%d) -> 0x%p\n", frame_count, size, ptr); } else { entry->FreeCount++; info->TotalFreeCount++; //printf("[%05d] MemFree(0x%p)\n", frame_count, ptr); } } const char* ImGui::GetClipboardText() { ImGuiContext& g = *GImGui; return g.IO.GetClipboardTextFn ? g.IO.GetClipboardTextFn(g.IO.ClipboardUserData) : ""; } void ImGui::SetClipboardText(const char* text) { ImGuiContext& g = *GImGui; if (g.IO.SetClipboardTextFn) g.IO.SetClipboardTextFn(g.IO.ClipboardUserData, text); } const char* ImGui::GetVersion() { return IMGUI_VERSION; } ImGuiIO& ImGui::GetIO() { IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?"); return GImGui->IO; } // Pass this to your backend rendering function! Valid after Render() and until the next call to NewFrame() ImDrawData* ImGui::GetDrawData() { ImGuiContext& g = *GImGui; ImGuiViewportP* viewport = g.Viewports[0]; return viewport->DrawDataP.Valid ? &viewport->DrawDataP : NULL; } double ImGui::GetTime() { return GImGui->Time; } int ImGui::GetFrameCount() { return GImGui->FrameCount; } static ImDrawList* GetViewportBgFgDrawList(ImGuiViewportP* viewport, size_t drawlist_no, const char* drawlist_name) { // Create the draw list on demand, because they are not frequently used for all viewports ImGuiContext& g = *GImGui; IM_ASSERT(drawlist_no < IM_ARRAYSIZE(viewport->BgFgDrawLists)); ImDrawList* draw_list = viewport->BgFgDrawLists[drawlist_no]; if (draw_list == NULL) { draw_list = IM_NEW(ImDrawList)(&g.DrawListSharedData); draw_list->_OwnerName = drawlist_name; viewport->BgFgDrawLists[drawlist_no] = draw_list; } // Our ImDrawList system requires that there is always a command if (viewport->BgFgDrawListsLastFrame[drawlist_no] != g.FrameCount) { draw_list->_ResetForNewFrame(); draw_list->PushTextureID(g.IO.Fonts->TexID); draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size, false); viewport->BgFgDrawListsLastFrame[drawlist_no] = g.FrameCount; } return draw_list; } ImDrawList* ImGui::GetBackgroundDrawList(ImGuiViewport* viewport) { return GetViewportBgFgDrawList((ImGuiViewportP*)viewport, 0, "##Background"); } ImDrawList* ImGui::GetBackgroundDrawList() { ImGuiContext& g = *GImGui; return GetBackgroundDrawList(g.Viewports[0]); } ImDrawList* ImGui::GetForegroundDrawList(ImGuiViewport* viewport) { return GetViewportBgFgDrawList((ImGuiViewportP*)viewport, 1, "##Foreground"); } ImDrawList* ImGui::GetForegroundDrawList() { ImGuiContext& g = *GImGui; return GetForegroundDrawList(g.Viewports[0]); } ImDrawListSharedData* ImGui::GetDrawListSharedData() { return &GImGui->DrawListSharedData; } void ImGui::StartMouseMovingWindow(ImGuiWindow* window) { // Set ActiveId even if the _NoMove flag is set. Without it, dragging away from a window with _NoMove would activate hover on other windows. // We _also_ call this when clicking in a window empty space when io.ConfigWindowsMoveFromTitleBarOnly is set, but clear g.MovingWindow afterward. // This is because we want ActiveId to be set even when the window is not permitted to move. ImGuiContext& g = *GImGui; FocusWindow(window); SetActiveID(window->MoveId, window); g.NavDisableHighlight = true; g.ActiveIdClickOffset = g.IO.MouseClickedPos[0] - window->RootWindow->Pos; g.ActiveIdNoClearOnFocusLoss = true; SetActiveIdUsingAllKeyboardKeys(); bool can_move_window = true; if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindow->Flags & ImGuiWindowFlags_NoMove)) can_move_window = false; if (can_move_window) g.MovingWindow = window; } // Handle mouse moving window // Note: moving window with the navigation keys (Square + d-pad / CTRL+TAB + Arrows) are processed in NavUpdateWindowing() // FIXME: We don't have strong guarantee that g.MovingWindow stay synched with g.ActiveId == g.MovingWindow->MoveId. // This is currently enforced by the fact that BeginDragDropSource() is setting all g.ActiveIdUsingXXXX flags to inhibit navigation inputs, // but if we should more thoroughly test cases where g.ActiveId or g.MovingWindow gets changed and not the other. void ImGui::UpdateMouseMovingWindowNewFrame() { ImGuiContext& g = *GImGui; if (g.MovingWindow != NULL) { // We actually want to move the root window. g.MovingWindow == window we clicked on (could be a child window). // We track it to preserve Focus and so that generally ActiveIdWindow == MovingWindow and ActiveId == MovingWindow->MoveId for consistency. KeepAliveID(g.ActiveId); IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindow); ImGuiWindow* moving_window = g.MovingWindow->RootWindow; if (g.IO.MouseDown[0] && IsMousePosValid(&g.IO.MousePos)) { ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset; SetWindowPos(moving_window, pos, ImGuiCond_Always); FocusWindow(g.MovingWindow); } else { g.MovingWindow = NULL; ClearActiveID(); } } else { // When clicking/dragging from a window that has the _NoMove flag, we still set the ActiveId in order to prevent hovering others. if (g.ActiveIdWindow && g.ActiveIdWindow->MoveId == g.ActiveId) { KeepAliveID(g.ActiveId); if (!g.IO.MouseDown[0]) ClearActiveID(); } } } // Initiate moving window when clicking on empty space or title bar. // Handle left-click and right-click focus. void ImGui::UpdateMouseMovingWindowEndFrame() { ImGuiContext& g = *GImGui; if (g.ActiveId != 0 || g.HoveredId != 0) return; // Unless we just made a window/popup appear if (g.NavWindow && g.NavWindow->Appearing) return; // Click on empty space to focus window and start moving // (after we're done with all our widgets) if (g.IO.MouseClicked[0]) { // Handle the edge case of a popup being closed while clicking in its empty space. // If we try to focus it, FocusWindow() > ClosePopupsOverWindow() will accidentally close any parent popups because they are not linked together any more. ImGuiWindow* root_window = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL; const bool is_closed_popup = root_window && (root_window->Flags & ImGuiWindowFlags_Popup) && !IsPopupOpen(root_window->PopupId, ImGuiPopupFlags_AnyPopupLevel); if (root_window != NULL && !is_closed_popup) { StartMouseMovingWindow(g.HoveredWindow); //-V595 // Cancel moving if clicked outside of title bar if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(root_window->Flags & ImGuiWindowFlags_NoTitleBar)) if (!root_window->TitleBarRect().Contains(g.IO.MouseClickedPos[0])) g.MovingWindow = NULL; // Cancel moving if clicked over an item which was disabled or inhibited by popups (note that we know HoveredId == 0 already) if (g.HoveredIdDisabled) g.MovingWindow = NULL; } else if (root_window == NULL && g.NavWindow != NULL) { // Clicking on void disable focus FocusWindow(NULL, ImGuiFocusRequestFlags_UnlessBelowModal); } } // With right mouse button we close popups without changing focus based on where the mouse is aimed // Instead, focus will be restored to the window under the bottom-most closed popup. // (The left mouse button path calls FocusWindow on the hovered window, which will lead NewFrame->ClosePopupsOverWindow to trigger) if (g.IO.MouseClicked[1]) { // Find the top-most window between HoveredWindow and the top-most Modal Window. // This is where we can trim the popup stack. ImGuiWindow* modal = GetTopMostPopupModal(); bool hovered_window_above_modal = g.HoveredWindow && (modal == NULL || IsWindowAbove(g.HoveredWindow, modal)); ClosePopupsOverWindow(hovered_window_above_modal ? g.HoveredWindow : modal, true); } } static bool IsWindowActiveAndVisible(ImGuiWindow* window) { return (window->Active) && (!window->Hidden); } // The reason this is exposed in imgui_internal.h is: on touch-based system that don't have hovering, we want to dispatch inputs to the right target (imgui vs imgui+app) void ImGui::UpdateHoveredWindowAndCaptureFlags() { ImGuiContext& g = *GImGui; ImGuiIO& io = g.IO; g.WindowsHoverPadding = ImMax(g.Style.TouchExtraPadding, ImVec2(WINDOWS_HOVER_PADDING, WINDOWS_HOVER_PADDING)); // Find the window hovered by mouse: // - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow. // - When moving a window we can skip the search, which also conveniently bypasses the fact that window->WindowRectClipped is lagging as this point of the frame. // - We also support the moved window toggling the NoInputs flag after moving has started in order to be able to detect windows below it, which is useful for e.g. docking mechanisms. bool clear_hovered_windows = false; FindHoveredWindow(); // Modal windows prevents mouse from hovering behind them. ImGuiWindow* modal_window = GetTopMostPopupModal(); if (modal_window && g.HoveredWindow && !IsWindowWithinBeginStackOf(g.HoveredWindow->RootWindow, modal_window)) clear_hovered_windows = true; // Disabled mouse? if (io.ConfigFlags & ImGuiConfigFlags_NoMouse) clear_hovered_windows = true; // We track click ownership. When clicked outside of a window the click is owned by the application and // won't report hovering nor request capture even while dragging over our windows afterward. const bool has_open_popup = (g.OpenPopupStack.Size > 0); const bool has_open_modal = (modal_window != NULL); int mouse_earliest_down = -1; bool mouse_any_down = false; for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) { if (io.MouseClicked[i]) { io.MouseDownOwned[i] = (g.HoveredWindow != NULL) || has_open_popup; io.MouseDownOwnedUnlessPopupClose[i] = (g.HoveredWindow != NULL) || has_open_modal; } mouse_any_down |= io.MouseDown[i]; if (io.MouseDown[i]) if (mouse_earliest_down == -1 || io.MouseClickedTime[i] < io.MouseClickedTime[mouse_earliest_down]) mouse_earliest_down = i; } const bool mouse_avail = (mouse_earliest_down == -1) || io.MouseDownOwned[mouse_earliest_down]; const bool mouse_avail_unless_popup_close = (mouse_earliest_down == -1) || io.MouseDownOwnedUnlessPopupClose[mouse_earliest_down]; // If mouse was first clicked outside of ImGui bounds we also cancel out hovering. // FIXME: For patterns of drag and drop across OS windows, we may need to rework/remove this test (first committed 311c0ca9 on 2015/02) const bool mouse_dragging_extern_payload = g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0; if (!mouse_avail && !mouse_dragging_extern_payload) clear_hovered_windows = true; if (clear_hovered_windows) g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL; // Update io.WantCaptureMouse for the user application (true = dispatch mouse info to Dear ImGui only, false = dispatch mouse to Dear ImGui + underlying app) // Update io.WantCaptureMouseAllowPopupClose (experimental) to give a chance for app to react to popup closure with a drag if (g.WantCaptureMouseNextFrame != -1) { io.WantCaptureMouse = io.WantCaptureMouseUnlessPopupClose = (g.WantCaptureMouseNextFrame != 0); } else { io.WantCaptureMouse = (mouse_avail && (g.HoveredWindow != NULL || mouse_any_down)) || has_open_popup; io.WantCaptureMouseUnlessPopupClose = (mouse_avail_unless_popup_close && (g.HoveredWindow != NULL || mouse_any_down)) || has_open_modal; } // Update io.WantCaptureKeyboard for the user application (true = dispatch keyboard info to Dear ImGui only, false = dispatch keyboard info to Dear ImGui + underlying app) io.WantCaptureKeyboard = (g.ActiveId != 0) || (modal_window != NULL); if (io.NavActive && (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard)) io.WantCaptureKeyboard = true; if (g.WantCaptureKeyboardNextFrame != -1) // Manual override io.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != 0); // Update io.WantTextInput flag, this is to allow systems without a keyboard (e.g. mobile, hand-held) to show a software keyboard if possible io.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : false; } void ImGui::NewFrame() { IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() and ImGui::SetCurrentContext() ?"); ImGuiContext& g = *GImGui; // Remove pending delete hooks before frame start. // This deferred removal avoid issues of removal while iterating the hook vector for (int n = g.Hooks.Size - 1; n >= 0; n--) if (g.Hooks[n].Type == ImGuiContextHookType_PendingRemoval_) g.Hooks.erase(&g.Hooks[n]); CallContextHooks(&g, ImGuiContextHookType_NewFramePre); // Check and assert for various common IO and Configuration mistakes ErrorCheckNewFrameSanityChecks(); // Load settings on first frame, save settings when modified (after a delay) UpdateSettings(); g.Time += g.IO.DeltaTime; g.WithinFrameScope = true; g.FrameCount += 1; g.TooltipOverrideCount = 0; g.WindowsActiveCount = 0; g.MenusIdSubmittedThisFrame.resize(0); // Calculate frame-rate for the user, as a purely luxurious feature g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx]; g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime; g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame); g.FramerateSecPerFrameCount = ImMin(g.FramerateSecPerFrameCount + 1, IM_ARRAYSIZE(g.FramerateSecPerFrame)); g.IO.Framerate = (g.FramerateSecPerFrameAccum > 0.0f) ? (1.0f / (g.FramerateSecPerFrameAccum / (float)g.FramerateSecPerFrameCount)) : FLT_MAX; // Process input queue (trickle as many events as possible), turn events into writes to IO structure g.InputEventsTrail.resize(0); UpdateInputEvents(g.IO.ConfigInputTrickleEventQueue); // Update viewports (after processing input queue, so io.MouseHoveredViewport is set) UpdateViewportsNewFrame(); // Setup current font and draw list shared data g.IO.Fonts->Locked = true; SetCurrentFont(GetDefaultFont()); IM_ASSERT(g.Font->IsLoaded()); ImRect virtual_space(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); for (ImGuiViewportP* viewport : g.Viewports) virtual_space.Add(viewport->GetMainRect()); g.DrawListSharedData.ClipRectFullscreen = virtual_space.ToVec4(); g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol; g.DrawListSharedData.SetCircleTessellationMaxError(g.Style.CircleTessellationMaxError); g.DrawListSharedData.InitialFlags = ImDrawListFlags_None; if (g.Style.AntiAliasedLines) g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLines; if (g.Style.AntiAliasedLinesUseTex && !(g.Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedLines)) g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedLinesUseTex; if (g.Style.AntiAliasedFill) g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AntiAliasedFill; if (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset) g.DrawListSharedData.InitialFlags |= ImDrawListFlags_AllowVtxOffset; // Mark rendering data as invalid to prevent user who may have a handle on it to use it. for (ImGuiViewportP* viewport : g.Viewports) viewport->DrawDataP.Valid = false; // Drag and drop keep the source ID alive so even if the source disappear our state is consistent if (g.DragDropActive && g.DragDropPayload.SourceId == g.ActiveId) KeepAliveID(g.DragDropPayload.SourceId); // Update HoveredId data if (!g.HoveredIdPreviousFrame) g.HoveredIdTimer = 0.0f; if (!g.HoveredIdPreviousFrame || (g.HoveredId && g.ActiveId == g.HoveredId)) g.HoveredIdNotActiveTimer = 0.0f; if (g.HoveredId) g.HoveredIdTimer += g.IO.DeltaTime; if (g.HoveredId && g.ActiveId != g.HoveredId) g.HoveredIdNotActiveTimer += g.IO.DeltaTime; g.HoveredIdPreviousFrame = g.HoveredId; g.HoveredId = 0; g.HoveredIdAllowOverlap = false; g.HoveredIdDisabled = false; // Clear ActiveID if the item is not alive anymore. // In 1.87, the common most call to KeepAliveID() was moved from GetID() to ItemAdd(). // As a result, custom widget using ButtonBehavior() _without_ ItemAdd() need to call KeepAliveID() themselves. if (g.ActiveId != 0 && g.ActiveIdIsAlive != g.ActiveId && g.ActiveIdPreviousFrame == g.ActiveId) { IMGUI_DEBUG_LOG_ACTIVEID("NewFrame(): ClearActiveID() because it isn't marked alive anymore!\n"); ClearActiveID(); } // Update ActiveId data (clear reference to active widget if the widget isn't alive anymore) if (g.ActiveId) g.ActiveIdTimer += g.IO.DeltaTime; g.LastActiveIdTimer += g.IO.DeltaTime; g.ActiveIdPreviousFrame = g.ActiveId; g.ActiveIdPreviousFrameWindow = g.ActiveIdWindow; g.ActiveIdPreviousFrameHasBeenEditedBefore = g.ActiveIdHasBeenEditedBefore; g.ActiveIdIsAlive = 0; g.ActiveIdHasBeenEditedThisFrame = false; g.ActiveIdPreviousFrameIsAlive = false; g.ActiveIdIsJustActivated = false; if (g.TempInputId != 0 && g.ActiveId != g.TempInputId) g.TempInputId = 0; if (g.ActiveId == 0) { g.ActiveIdUsingNavDirMask = 0x00; g.ActiveIdUsingAllKeyboardKeys = false; #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO g.ActiveIdUsingNavInputMask = 0x00; #endif } #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO if (g.ActiveId == 0) g.ActiveIdUsingNavInputMask = 0; else if (g.ActiveIdUsingNavInputMask != 0) { // If your custom widget code used: { g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel); } // Since IMGUI_VERSION_NUM >= 18804 it should be: { SetKeyOwner(ImGuiKey_Escape, g.ActiveId); SetKeyOwner(ImGuiKey_NavGamepadCancel, g.ActiveId); } if (g.ActiveIdUsingNavInputMask & (1 << ImGuiNavInput_Cancel)) SetKeyOwner(ImGuiKey_Escape, g.ActiveId); if (g.ActiveIdUsingNavInputMask & ~(1 << ImGuiNavInput_Cancel)) IM_ASSERT(0); // Other values unsupported } #endif // Record when we have been stationary as this state is preserved while over same item. // FIXME: The way this is expressed means user cannot alter HoverStationaryDelay during the frame to use varying values. // To allow this we should store HoverItemMaxStationaryTime+ID and perform the >= check in IsItemHovered() function. if (g.HoverItemDelayId != 0 && g.MouseStationaryTimer >= g.Style.HoverStationaryDelay) g.HoverItemUnlockedStationaryId = g.HoverItemDelayId; else if (g.HoverItemDelayId == 0) g.HoverItemUnlockedStationaryId = 0; if (g.HoveredWindow != NULL && g.MouseStationaryTimer >= g.Style.HoverStationaryDelay) g.HoverWindowUnlockedStationaryId = g.HoveredWindow->ID; else if (g.HoveredWindow == NULL) g.HoverWindowUnlockedStationaryId = 0; // Update hover delay for IsItemHovered() with delays and tooltips g.HoverItemDelayIdPreviousFrame = g.HoverItemDelayId; if (g.HoverItemDelayId != 0) { g.HoverItemDelayTimer += g.IO.DeltaTime; g.HoverItemDelayClearTimer = 0.0f; g.HoverItemDelayId = 0; } else if (g.HoverItemDelayTimer > 0.0f) { // This gives a little bit of leeway before clearing the hover timer, allowing mouse to cross gaps // We could expose 0.25f as style.HoverClearDelay but I am not sure of the logic yet, this is particularly subtle. g.HoverItemDelayClearTimer += g.IO.DeltaTime; if (g.HoverItemDelayClearTimer >= ImMax(0.25f, g.IO.DeltaTime * 2.0f)) // ~7 frames at 30 Hz + allow for low framerate g.HoverItemDelayTimer = g.HoverItemDelayClearTimer = 0.0f; // May want a decaying timer, in which case need to clamp at max first, based on max of caller last requested timer. } // Drag and drop g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr; g.DragDropAcceptIdCurr = 0; g.DragDropAcceptIdCurrRectSurface = FLT_MAX; g.DragDropWithinSource = false; g.DragDropWithinTarget = false; g.DragDropHoldJustPressedId = 0; // Close popups on focus lost (currently wip/opt-in) //if (g.IO.AppFocusLost) // ClosePopupsExceptModals(); // Update keyboard input state UpdateKeyboardInputs(); //IM_ASSERT(g.IO.KeyCtrl == IsKeyDown(ImGuiKey_LeftCtrl) || IsKeyDown(ImGuiKey_RightCtrl)); //IM_ASSERT(g.IO.KeyShift == IsKeyDown(ImGuiKey_LeftShift) || IsKeyDown(ImGuiKey_RightShift)); //IM_ASSERT(g.IO.KeyAlt == IsKeyDown(ImGuiKey_LeftAlt) || IsKeyDown(ImGuiKey_RightAlt)); //IM_ASSERT(g.IO.KeySuper == IsKeyDown(ImGuiKey_LeftSuper) || IsKeyDown(ImGuiKey_RightSuper)); // Update gamepad/keyboard navigation NavUpdate(); // Update mouse input state UpdateMouseInputs(); // Find hovered window // (needs to be before UpdateMouseMovingWindowNewFrame so we fill g.HoveredWindowUnderMovingWindow on the mouse release frame) UpdateHoveredWindowAndCaptureFlags(); // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering) UpdateMouseMovingWindowNewFrame(); // Background darkening/whitening if (GetTopMostPopupModal() != NULL || (g.NavWindowingTarget != NULL && g.NavWindowingHighlightAlpha > 0.0f)) g.DimBgRatio = ImMin(g.DimBgRatio + g.IO.DeltaTime * 6.0f, 1.0f); else g.DimBgRatio = ImMax(g.DimBgRatio - g.IO.DeltaTime * 10.0f, 0.0f); g.MouseCursor = ImGuiMouseCursor_Arrow; g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1; // Platform IME data: reset for the frame g.PlatformImeDataPrev = g.PlatformImeData; g.PlatformImeData.WantVisible = false; // Mouse wheel scrolling, scale UpdateMouseWheel(); // Mark all windows as not visible and compact unused memory. IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size); const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer; for (ImGuiWindow* window : g.Windows) { window->WasActive = window->Active; window->Active = false; window->WriteAccessed = false; window->BeginCountPreviousFrame = window->BeginCount; window->BeginCount = 0; // Garbage collect transient buffers of recently unused windows if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time) GcCompactTransientWindowBuffers(window); } // Garbage collect transient buffers of recently unused tables for (int i = 0; i < g.TablesLastTimeActive.Size; i++) if (g.TablesLastTimeActive[i] >= 0.0f && g.TablesLastTimeActive[i] < memory_compact_start_time) TableGcCompactTransientBuffers(g.Tables.GetByIndex(i)); for (ImGuiTableTempData& table_temp_data : g.TablesTempData) if (table_temp_data.LastTimeActive >= 0.0f && table_temp_data.LastTimeActive < memory_compact_start_time) TableGcCompactTransientBuffers(&table_temp_data); if (g.GcCompactAll) GcCompactTransientMiscBuffers(); g.GcCompactAll = false; // Closing the focused window restore focus to the first active root window in descending z-order if (g.NavWindow && !g.NavWindow->WasActive) FocusTopMostWindowUnderOne(NULL, NULL, NULL, ImGuiFocusRequestFlags_RestoreFocusedChild); // No window should be open at the beginning of the frame. // But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear. g.CurrentWindowStack.resize(0); g.BeginPopupStack.resize(0); g.ItemFlagsStack.resize(0); g.ItemFlagsStack.push_back(ImGuiItemFlags_None); g.GroupStack.resize(0); // [DEBUG] Update debug features #ifndef IMGUI_DISABLE_DEBUG_TOOLS UpdateDebugToolItemPicker(); UpdateDebugToolStackQueries(); UpdateDebugToolFlashStyleColor(); if (g.DebugLocateFrames > 0 && --g.DebugLocateFrames == 0) { g.DebugLocateId = 0; g.DebugBreakInLocateId = false; } if (g.DebugLogAutoDisableFrames > 0 && --g.DebugLogAutoDisableFrames == 0) { DebugLog("(Debug Log: Auto-disabled some ImGuiDebugLogFlags after 2 frames)\n"); g.DebugLogFlags &= ~g.DebugLogAutoDisableFlags; g.DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None; } #endif // Create implicit/fallback window - which we will only render it if the user has added something to it. // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. // This fallback is particularly important as it prevents ImGui:: calls from crashing. g.WithinFrameScopeWithImplicitWindow = true; SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver); Begin("Debug##Default"); IM_ASSERT(g.CurrentWindow->IsFallbackWindow == true); // [DEBUG] When io.ConfigDebugBeginReturnValue is set, we make Begin()/BeginChild() return false at different level of the window-stack, // allowing to validate correct Begin/End behavior in user code. #ifndef IMGUI_DISABLE_DEBUG_TOOLS if (g.IO.ConfigDebugBeginReturnValueLoop) g.DebugBeginReturnValueCullDepth = (g.DebugBeginReturnValueCullDepth == -1) ? 0 : ((g.DebugBeginReturnValueCullDepth + ((g.FrameCount % 4) == 0 ? 1 : 0)) % 10); else g.DebugBeginReturnValueCullDepth = -1; #endif CallContextHooks(&g, ImGuiContextHookType_NewFramePost); } // FIXME: Add a more explicit sort order in the window structure. static int IMGUI_CDECL ChildWindowComparer(const void* lhs, const void* rhs) { const ImGuiWindow* const a = *(const ImGuiWindow* const *)lhs; const ImGuiWindow* const b = *(const ImGuiWindow* const *)rhs; if (int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup)) return d; if (int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip)) return d; return (a->BeginOrderWithinParent - b->BeginOrderWithinParent); } static void AddWindowToSortBuffer(ImVector* out_sorted_windows, ImGuiWindow* window) { out_sorted_windows->push_back(window); if (window->Active) { int count = window->DC.ChildWindows.Size; ImQsort(window->DC.ChildWindows.Data, (size_t)count, sizeof(ImGuiWindow*), ChildWindowComparer); for (int i = 0; i < count; i++) { ImGuiWindow* child = window->DC.ChildWindows[i]; if (child->Active) AddWindowToSortBuffer(out_sorted_windows, child); } } } static void AddWindowToDrawData(ImGuiWindow* window, int layer) { ImGuiContext& g = *GImGui; ImGuiViewportP* viewport = g.Viewports[0]; g.IO.MetricsRenderWindows++; if (window->DrawList->_Splitter._Count > 1) window->DrawList->ChannelsMerge(); // Merge if user forgot to merge back. Also required in Docking branch for ImGuiWindowFlags_DockNodeHost windows. ImGui::AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[layer], window->DrawList); for (ImGuiWindow* child : window->DC.ChildWindows) if (IsWindowActiveAndVisible(child)) // Clipped children may have been marked not active AddWindowToDrawData(child, layer); } static inline int GetWindowDisplayLayer(ImGuiWindow* window) { return (window->Flags & ImGuiWindowFlags_Tooltip) ? 1 : 0; } // Layer is locked for the root window, however child windows may use a different viewport (e.g. extruding menu) static inline void AddRootWindowToDrawData(ImGuiWindow* window) { AddWindowToDrawData(window, GetWindowDisplayLayer(window)); } static void FlattenDrawDataIntoSingleLayer(ImDrawDataBuilder* builder) { int n = builder->Layers[0]->Size; int full_size = n; for (int i = 1; i < IM_ARRAYSIZE(builder->Layers); i++) full_size += builder->Layers[i]->Size; builder->Layers[0]->resize(full_size); for (int layer_n = 1; layer_n < IM_ARRAYSIZE(builder->Layers); layer_n++) { ImVector* layer = builder->Layers[layer_n]; if (layer->empty()) continue; memcpy(builder->Layers[0]->Data + n, layer->Data, layer->Size * sizeof(ImDrawList*)); n += layer->Size; layer->resize(0); } } static void InitViewportDrawData(ImGuiViewportP* viewport) { ImGuiIO& io = ImGui::GetIO(); ImDrawData* draw_data = &viewport->DrawDataP; viewport->DrawDataBuilder.Layers[0] = &draw_data->CmdLists; viewport->DrawDataBuilder.Layers[1] = &viewport->DrawDataBuilder.LayerData1; viewport->DrawDataBuilder.Layers[0]->resize(0); viewport->DrawDataBuilder.Layers[1]->resize(0); draw_data->Valid = true; draw_data->CmdListsCount = 0; draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0; draw_data->DisplayPos = viewport->Pos; draw_data->DisplaySize = viewport->Size; draw_data->FramebufferScale = io.DisplayFramebufferScale; draw_data->OwnerViewport = viewport; } // Push a clipping rectangle for both ImGui logic (hit-testing etc.) and low-level ImDrawList rendering. // - When using this function it is sane to ensure that float are perfectly rounded to integer values, // so that e.g. (int)(max.x-min.x) in user's render produce correct result. // - If the code here changes, may need to update code of functions like NextColumn() and PushColumnClipRect(): // some frequently called functions which to modify both channels and clipping simultaneously tend to use the // more specialized SetWindowClipRectBeforeSetChannel() to avoid extraneous updates of underlying ImDrawCmds. void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect) { ImGuiWindow* window = GetCurrentWindow(); window->DrawList->PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect); window->ClipRect = window->DrawList->_ClipRectStack.back(); } void ImGui::PopClipRect() { ImGuiWindow* window = GetCurrentWindow(); window->DrawList->PopClipRect(); window->ClipRect = window->DrawList->_ClipRectStack.back(); } static void ImGui::RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col) { if ((col & IM_COL32_A_MASK) == 0) return; ImGuiViewportP* viewport = (ImGuiViewportP*)GetMainViewport(); ImRect viewport_rect = viewport->GetMainRect(); // Draw behind window by moving the draw command at the FRONT of the draw list { // We've already called AddWindowToDrawData() which called DrawList->ChannelsMerge() on DockNodeHost windows, // and draw list have been trimmed already, hence the explicit recreation of a draw command if missing. // FIXME: This is creating complication, might be simpler if we could inject a drawlist in drawdata at a given position and not attempt to manipulate ImDrawCmd order. ImDrawList* draw_list = window->RootWindow->DrawList; if (draw_list->CmdBuffer.Size == 0) draw_list->AddDrawCmd(); draw_list->PushClipRect(viewport_rect.Min - ImVec2(1, 1), viewport_rect.Max + ImVec2(1, 1), false); // FIXME: Need to stricty ensure ImDrawCmd are not merged (ElemCount==6 checks below will verify that) draw_list->AddRectFilled(viewport_rect.Min, viewport_rect.Max, col); ImDrawCmd cmd = draw_list->CmdBuffer.back(); IM_ASSERT(cmd.ElemCount == 6); draw_list->CmdBuffer.pop_back(); draw_list->CmdBuffer.push_front(cmd); draw_list->AddDrawCmd(); // We need to create a command as CmdBuffer.back().IdxOffset won't be correct if we append to same command. draw_list->PopClipRect(); } } ImGuiWindow* ImGui::FindBottomMostVisibleWindowWithinBeginStack(ImGuiWindow* parent_window) { ImGuiContext& g = *GImGui; ImGuiWindow* bottom_most_visible_window = parent_window; for (int i = FindWindowDisplayIndex(parent_window); i >= 0; i--) { ImGuiWindow* window = g.Windows[i]; if (window->Flags & ImGuiWindowFlags_ChildWindow) continue; if (!IsWindowWithinBeginStackOf(window, parent_window)) break; if (IsWindowActiveAndVisible(window) && GetWindowDisplayLayer(window) <= GetWindowDisplayLayer(parent_window)) bottom_most_visible_window = window; } return bottom_most_visible_window; } static void ImGui::RenderDimmedBackgrounds() { ImGuiContext& g = *GImGui; ImGuiWindow* modal_window = GetTopMostAndVisiblePopupModal(); if (g.DimBgRatio <= 0.0f && g.NavWindowingHighlightAlpha <= 0.0f) return; const bool dim_bg_for_modal = (modal_window != NULL); const bool dim_bg_for_window_list = (g.NavWindowingTargetAnim != NULL && g.NavWindowingTargetAnim->Active); if (!dim_bg_for_modal && !dim_bg_for_window_list) return; if (dim_bg_for_modal) { // Draw dimming behind modal or a begin stack child, whichever comes first in draw order. ImGuiWindow* dim_behind_window = FindBottomMostVisibleWindowWithinBeginStack(modal_window); RenderDimmedBackgroundBehindWindow(dim_behind_window, GetColorU32(ImGuiCol_ModalWindowDimBg, g.DimBgRatio)); } else if (dim_bg_for_window_list) { // Draw dimming behind CTRL+Tab target window RenderDimmedBackgroundBehindWindow(g.NavWindowingTargetAnim, GetColorU32(ImGuiCol_NavWindowingDimBg, g.DimBgRatio)); // Draw border around CTRL+Tab target window ImGuiWindow* window = g.NavWindowingTargetAnim; ImGuiViewport* viewport = GetMainViewport(); float distance = g.FontSize; ImRect bb = window->Rect(); bb.Expand(distance); if (bb.GetWidth() >= viewport->Size.x && bb.GetHeight() >= viewport->Size.y) bb.Expand(-distance - 1.0f); // If a window fits the entire viewport, adjust its highlight inward if (window->DrawList->CmdBuffer.Size == 0) window->DrawList->AddDrawCmd(); window->DrawList->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size); window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), window->WindowRounding, 0, 3.0f); window->DrawList->PopClipRect(); } } // This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal. void ImGui::EndFrame() { ImGuiContext& g = *GImGui; IM_ASSERT(g.Initialized); // Don't process EndFrame() multiple times. if (g.FrameCountEnded == g.FrameCount) return; IM_ASSERT(g.WithinFrameScope && "Forgot to call ImGui::NewFrame()?"); CallContextHooks(&g, ImGuiContextHookType_EndFramePre); ErrorCheckEndFrameSanityChecks(); // Notify Platform/OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME) ImGuiPlatformImeData* ime_data = &g.PlatformImeData; if (g.IO.SetPlatformImeDataFn && memcmp(ime_data, &g.PlatformImeDataPrev, sizeof(ImGuiPlatformImeData)) != 0) { IMGUI_DEBUG_LOG_IO("[io] Calling io.SetPlatformImeDataFn(): WantVisible: %d, InputPos (%.2f,%.2f)\n", ime_data->WantVisible, ime_data->InputPos.x, ime_data->InputPos.y); ImGuiViewport* viewport = GetMainViewport(); g.IO.SetPlatformImeDataFn(viewport, ime_data); } // Hide implicit/fallback "Debug" window if it hasn't been used g.WithinFrameScopeWithImplicitWindow = false; if (g.CurrentWindow && !g.CurrentWindow->WriteAccessed) g.CurrentWindow->Active = false; End(); // Update navigation: CTRL+Tab, wrap-around requests NavEndFrame(); // Drag and Drop: Elapse payload (if delivered, or if source stops being submitted) if (g.DragDropActive) { bool is_delivered = g.DragDropPayload.Delivery; bool is_elapsed = (g.DragDropPayload.DataFrameCount + 1 < g.FrameCount) && ((g.DragDropSourceFlags & ImGuiDragDropFlags_SourceAutoExpirePayload) || !IsMouseDown(g.DragDropMouseButton)); if (is_delivered || is_elapsed) ClearDragDrop(); } // Drag and Drop: Fallback for source tooltip. This is not ideal but better than nothing. if (g.DragDropActive && g.DragDropSourceFrameCount < g.FrameCount && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip)) { g.DragDropWithinSource = true; SetTooltip("..."); g.DragDropWithinSource = false; } // End frame g.WithinFrameScope = false; g.FrameCountEnded = g.FrameCount; // Initiate moving window + handle left-click and right-click focus UpdateMouseMovingWindowEndFrame(); // Sort the window list so that all child windows are after their parent // We cannot do that on FocusWindow() because children may not exist yet g.WindowsTempSortBuffer.resize(0); g.WindowsTempSortBuffer.reserve(g.Windows.Size); for (ImGuiWindow* window : g.Windows) { if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow)) // if a child is active its parent will add it continue; AddWindowToSortBuffer(&g.WindowsTempSortBuffer, window); } // This usually assert if there is a mismatch between the ImGuiWindowFlags_ChildWindow / ParentWindow values and DC.ChildWindows[] in parents, aka we've done something wrong. IM_ASSERT(g.Windows.Size == g.WindowsTempSortBuffer.Size); g.Windows.swap(g.WindowsTempSortBuffer); g.IO.MetricsActiveWindows = g.WindowsActiveCount; // Unlock font atlas g.IO.Fonts->Locked = false; // Clear Input data for next frame g.IO.MousePosPrev = g.IO.MousePos; g.IO.AppFocusLost = false; g.IO.MouseWheel = g.IO.MouseWheelH = 0.0f; g.IO.InputQueueCharacters.resize(0); CallContextHooks(&g, ImGuiContextHookType_EndFramePost); } // Prepare the data for rendering so you can call GetDrawData() // (As with anything within the ImGui:: namspace this doesn't touch your GPU or graphics API at all: // it is the role of the ImGui_ImplXXXX_RenderDrawData() function provided by the renderer backend) void ImGui::Render() { ImGuiContext& g = *GImGui; IM_ASSERT(g.Initialized); if (g.FrameCountEnded != g.FrameCount) EndFrame(); if (g.FrameCountRendered == g.FrameCount) return; g.FrameCountRendered = g.FrameCount; g.IO.MetricsRenderWindows = 0; CallContextHooks(&g, ImGuiContextHookType_RenderPre); // Draw modal/window whitening backgrounds RenderDimmedBackgrounds(); // Add background ImDrawList (for each active viewport) for (ImGuiViewportP* viewport : g.Viewports) { InitViewportDrawData(viewport); if (viewport->BgFgDrawLists[0] != NULL) AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetBackgroundDrawList(viewport)); } // Add ImDrawList to render ImGuiWindow* windows_to_render_top_most[2]; windows_to_render_top_most[0] = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget->RootWindow : NULL; windows_to_render_top_most[1] = (g.NavWindowingTarget ? g.NavWindowingListWindow : NULL); for (ImGuiWindow* window : g.Windows) { IM_MSVC_WARNING_SUPPRESS(6011); // Static Analysis false positive "warning C6011: Dereferencing NULL pointer 'window'" if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_top_most[0] && window != windows_to_render_top_most[1]) AddRootWindowToDrawData(window); } for (int n = 0; n < IM_ARRAYSIZE(windows_to_render_top_most); n++) if (windows_to_render_top_most[n] && IsWindowActiveAndVisible(windows_to_render_top_most[n])) // NavWindowingTarget is always temporarily displayed as the top-most window AddRootWindowToDrawData(windows_to_render_top_most[n]); // Draw software mouse cursor if requested by io.MouseDrawCursor flag if (g.IO.MouseDrawCursor && g.MouseCursor != ImGuiMouseCursor_None) RenderMouseCursor(g.IO.MousePos, g.Style.MouseCursorScale, g.MouseCursor, IM_COL32_WHITE, IM_COL32_BLACK, IM_COL32(0, 0, 0, 48)); // Setup ImDrawData structures for end-user g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = 0; for (ImGuiViewportP* viewport : g.Viewports) { FlattenDrawDataIntoSingleLayer(&viewport->DrawDataBuilder); // Add foreground ImDrawList (for each active viewport) if (viewport->BgFgDrawLists[1] != NULL) AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetForegroundDrawList(viewport)); // We call _PopUnusedDrawCmd() last thing, as RenderDimmedBackgrounds() rely on a valid command being there (especially in docking branch). ImDrawData* draw_data = &viewport->DrawDataP; IM_ASSERT(draw_data->CmdLists.Size == draw_data->CmdListsCount); for (ImDrawList* draw_list : draw_data->CmdLists) draw_list->_PopUnusedDrawCmd(); g.IO.MetricsRenderVertices += draw_data->TotalVtxCount; g.IO.MetricsRenderIndices += draw_data->TotalIdxCount; } CallContextHooks(&g, ImGuiContextHookType_RenderPost); } // Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker. // CalcTextSize("") should return ImVec2(0.0f, g.FontSize) ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width) { ImGuiContext& g = *GImGui; const char* text_display_end; if (hide_text_after_double_hash) text_display_end = FindRenderedTextEnd(text, text_end); // Hide anything after a '##' string else text_display_end = text_end; ImFont* font = g.Font; const float font_size = g.FontSize; if (text == text_display_end) return ImVec2(0.0f, font_size); ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL); // Round // FIXME: This has been here since Dec 2015 (7b0bf230) but down the line we want this out. // FIXME: Investigate using ceilf or e.g. // - https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c // - https://embarkstudios.github.io/rust-gpu/api/src/libm/math/ceilf.rs.html text_size.x = IM_TRUNC(text_size.x + 0.99999f); return text_size; } // Find window given position, search front-to-back // FIXME: Note that we have an inconsequential lag here: OuterRectClipped is updated in Begin(), so windows moved programmatically // with SetWindowPos() and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is // called, aka before the next Begin(). Moving window isn't affected. static void FindHoveredWindow() { ImGuiContext& g = *GImGui; ImGuiWindow* hovered_window = NULL; ImGuiWindow* hovered_window_ignoring_moving_window = NULL; if (g.MovingWindow && !(g.MovingWindow->Flags & ImGuiWindowFlags_NoMouseInputs)) hovered_window = g.MovingWindow; ImVec2 padding_regular = g.Style.TouchExtraPadding; ImVec2 padding_for_resize = g.IO.ConfigWindowsResizeFromEdges ? g.WindowsHoverPadding : padding_regular; for (int i = g.Windows.Size - 1; i >= 0; i--) { ImGuiWindow* window = g.Windows[i]; IM_MSVC_WARNING_SUPPRESS(28182); // [Static Analyzer] Dereferencing NULL pointer. if (!window->Active || window->Hidden) continue; if (window->Flags & ImGuiWindowFlags_NoMouseInputs) continue; // Using the clipped AABB, a child window will typically be clipped by its parent (not always) ImVec2 hit_padding = (window->Flags & (ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) ? padding_regular : padding_for_resize; if (!window->OuterRectClipped.ContainsWithPad(g.IO.MousePos, hit_padding)) continue; // Support for one rectangular hole in any given window // FIXME: Consider generalizing hit-testing override (with more generic data, callback, etc.) (#1512) if (window->HitTestHoleSize.x != 0) { ImVec2 hole_pos(window->Pos.x + (float)window->HitTestHoleOffset.x, window->Pos.y + (float)window->HitTestHoleOffset.y); ImVec2 hole_size((float)window->HitTestHoleSize.x, (float)window->HitTestHoleSize.y); if (ImRect(hole_pos, hole_pos + hole_size).Contains(g.IO.MousePos)) continue; } if (hovered_window == NULL) hovered_window = window; IM_MSVC_WARNING_SUPPRESS(28182); // [Static Analyzer] Dereferencing NULL pointer. if (hovered_window_ignoring_moving_window == NULL && (!g.MovingWindow || window->RootWindow != g.MovingWindow->RootWindow)) hovered_window_ignoring_moving_window = window; if (hovered_window && hovered_window_ignoring_moving_window) break; } g.HoveredWindow = hovered_window; g.HoveredWindowUnderMovingWindow = hovered_window_ignoring_moving_window; } bool ImGui::IsItemActive() { ImGuiContext& g = *GImGui; if (g.ActiveId) return g.ActiveId == g.LastItemData.ID; return false; } bool ImGui::IsItemActivated() { ImGuiContext& g = *GImGui; if (g.ActiveId) if (g.ActiveId == g.LastItemData.ID && g.ActiveIdPreviousFrame != g.LastItemData.ID) return true; return false; } bool ImGui::IsItemDeactivated() { ImGuiContext& g = *GImGui; if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDeactivated) return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Deactivated) != 0; return (g.ActiveIdPreviousFrame == g.LastItemData.ID && g.ActiveIdPreviousFrame != 0 && g.ActiveId != g.LastItemData.ID); } bool ImGui::IsItemDeactivatedAfterEdit() { ImGuiContext& g = *GImGui; return IsItemDeactivated() && (g.ActiveIdPreviousFrameHasBeenEditedBefore || (g.ActiveId == 0 && g.ActiveIdHasBeenEditedBefore)); } // == GetItemID() == GetFocusID() bool ImGui::IsItemFocused() { ImGuiContext& g = *GImGui; if (g.NavId != g.LastItemData.ID || g.NavId == 0) return false; return true; } // Important: this can be useful but it is NOT equivalent to the behavior of e.g.Button()! // Most widgets have specific reactions based on mouse-up/down state, mouse position etc. bool ImGui::IsItemClicked(ImGuiMouseButton mouse_button) { return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_None); } bool ImGui::IsItemToggledOpen() { ImGuiContext& g = *GImGui; return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledOpen) ? true : false; } bool ImGui::IsItemToggledSelection() { ImGuiContext& g = *GImGui; return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_ToggledSelection) ? true : false; } // IMPORTANT: If you are trying to check whether your mouse should be dispatched to Dear ImGui or to your underlying app, // you should not use this function! Use the 'io.WantCaptureMouse' boolean for that! // Refer to FAQ entry "How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application?" for details. bool ImGui::IsAnyItemHovered() { ImGuiContext& g = *GImGui; return g.HoveredId != 0 || g.HoveredIdPreviousFrame != 0; } bool ImGui::IsAnyItemActive() { ImGuiContext& g = *GImGui; return g.ActiveId != 0; } bool ImGui::IsAnyItemFocused() { ImGuiContext& g = *GImGui; return g.NavId != 0 && !g.NavDisableHighlight; } bool ImGui::IsItemVisible() { ImGuiContext& g = *GImGui; return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) != 0; } bool ImGui::IsItemEdited() { ImGuiContext& g = *GImGui; return (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Edited) != 0; } // Allow next item to be overlapped by subsequent items. // This works by requiring HoveredId to match for two subsequent frames, // so if a following items overwrite it our interactions will naturally be disabled. void ImGui::SetNextItemAllowOverlap() { ImGuiContext& g = *GImGui; g.NextItemData.ItemFlags |= ImGuiItemFlags_AllowOverlap; } #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority. // FIXME-LEGACY: Use SetNextItemAllowOverlap() *before* your item instead. void ImGui::SetItemAllowOverlap() { ImGuiContext& g = *GImGui; ImGuiID id = g.LastItemData.ID; if (g.HoveredId == id) g.HoveredIdAllowOverlap = true; if (g.ActiveId == id) // Before we made this obsolete, most calls to SetItemAllowOverlap() used to avoid this path by testing g.ActiveId != id. g.ActiveIdAllowOverlap = true; } #endif // FIXME: It might be undesirable that this will likely disable KeyOwner-aware shortcuts systems. Consider a more fine-tuned version for the two users of this function. void ImGui::SetActiveIdUsingAllKeyboardKeys() { ImGuiContext& g = *GImGui; IM_ASSERT(g.ActiveId != 0); g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_COUNT) - 1; g.ActiveIdUsingAllKeyboardKeys = true; NavMoveRequestCancel(); } ImGuiID ImGui::GetItemID() { ImGuiContext& g = *GImGui; return g.LastItemData.ID; } ImVec2 ImGui::GetItemRectMin() { ImGuiContext& g = *GImGui; return g.LastItemData.Rect.Min; } ImVec2 ImGui::GetItemRectMax() { ImGuiContext& g = *GImGui; return g.LastItemData.Rect.Max; } ImVec2 ImGui::GetItemRectSize() { ImGuiContext& g = *GImGui; return g.LastItemData.Rect.GetSize(); } // Prior to v1.90 2023/10/16, the BeginChild() function took a 'bool border = false' parameter instead of 'ImGuiChildFlags child_flags = 0'. // ImGuiChildFlags_Border is defined as always == 1 in order to allow old code passing 'true'. Read comments in imgui.h for details! bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags) { ImGuiID id = GetCurrentWindow()->GetID(str_id); return BeginChildEx(str_id, id, size_arg, child_flags, window_flags); } bool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags) { return BeginChildEx(NULL, id, size_arg, child_flags, window_flags); } bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags) { ImGuiContext& g = *GImGui; ImGuiWindow* parent_window = g.CurrentWindow; IM_ASSERT(id != 0); // Sanity check as it is likely that some user will accidentally pass ImGuiWindowFlags into the ImGuiChildFlags argument. const ImGuiChildFlags ImGuiChildFlags_SupportedMask_ = ImGuiChildFlags_Border | ImGuiChildFlags_AlwaysUseWindowPadding | ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_FrameStyle; IM_UNUSED(ImGuiChildFlags_SupportedMask_); IM_ASSERT((child_flags & ~ImGuiChildFlags_SupportedMask_) == 0 && "Illegal ImGuiChildFlags value. Did you pass ImGuiWindowFlags values instead of ImGuiChildFlags?"); IM_ASSERT((window_flags & ImGuiWindowFlags_AlwaysAutoResize) == 0 && "Cannot specify ImGuiWindowFlags_AlwaysAutoResize for BeginChild(). Use ImGuiChildFlags_AlwaysAutoResize!"); if (child_flags & ImGuiChildFlags_AlwaysAutoResize) { IM_ASSERT((child_flags & (ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY)) == 0 && "Cannot use ImGuiChildFlags_ResizeX or ImGuiChildFlags_ResizeY with ImGuiChildFlags_AlwaysAutoResize!"); IM_ASSERT((child_flags & (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY)) != 0 && "Must use ImGuiChildFlags_AutoResizeX or ImGuiChildFlags_AutoResizeY with ImGuiChildFlags_AlwaysAutoResize!"); } #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS if (window_flags & ImGuiWindowFlags_AlwaysUseWindowPadding) child_flags |= ImGuiChildFlags_AlwaysUseWindowPadding; #endif if (child_flags & ImGuiChildFlags_AutoResizeX) child_flags &= ~ImGuiChildFlags_ResizeX; if (child_flags & ImGuiChildFlags_AutoResizeY) child_flags &= ~ImGuiChildFlags_ResizeY; // Set window flags window_flags |= ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoTitleBar; window_flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag if (child_flags & (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize)) window_flags |= ImGuiWindowFlags_AlwaysAutoResize; if ((child_flags & (ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY)) == 0) window_flags |= ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings; // Special framed style if (child_flags & ImGuiChildFlags_FrameStyle) { PushStyleColor(ImGuiCol_ChildBg, g.Style.Colors[ImGuiCol_FrameBg]); PushStyleVar(ImGuiStyleVar_ChildRounding, g.Style.FrameRounding); PushStyleVar(ImGuiStyleVar_ChildBorderSize, g.Style.FrameBorderSize); PushStyleVar(ImGuiStyleVar_WindowPadding, g.Style.FramePadding); child_flags |= ImGuiChildFlags_Border | ImGuiChildFlags_AlwaysUseWindowPadding; window_flags |= ImGuiWindowFlags_NoMove; } // Forward child flags g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasChildFlags; g.NextWindowData.ChildFlags = child_flags; // Forward size // Important: Begin() has special processing to switch condition to ImGuiCond_FirstUseEver for a given axis when ImGuiChildFlags_ResizeXXX is set. // (the alternative would to store conditional flags per axis, which is possible but more code) const ImVec2 size_avail = GetContentRegionAvail(); const ImVec2 size_default((child_flags & ImGuiChildFlags_AutoResizeX) ? 0.0f : size_avail.x, (child_flags & ImGuiChildFlags_AutoResizeY) ? 0.0f : size_avail.y); const ImVec2 size = CalcItemSize(size_arg, size_default.x, size_default.y); SetNextWindowSize(size); // Build up name. If you need to append to a same child from multiple location in the ID stack, use BeginChild(ImGuiID id) with a stable value. // FIXME: 2023/11/14: commented out shorted version. We had an issue with multiple ### in child window path names, which the trailing hash helped workaround. // e.g. "ParentName###ParentIdentifier/ChildName###ChildIdentifier" would get hashed incorrectly by ImHashStr(), trailing _%08X somehow fixes it. const char* temp_window_name; /*if (name && parent_window->IDStack.back() == parent_window->ID) ImFormatStringToTempBuffer(&temp_window_name, NULL, "%s/%s", parent_window->Name, name); // May omit ID if in root of ID stack else*/ if (name) ImFormatStringToTempBuffer(&temp_window_name, NULL, "%s/%s_%08X", parent_window->Name, name, id); else ImFormatStringToTempBuffer(&temp_window_name, NULL, "%s/%08X", parent_window->Name, id); // Set style const float backup_border_size = g.Style.ChildBorderSize; if ((child_flags & ImGuiChildFlags_Border) == 0) g.Style.ChildBorderSize = 0.0f; // Begin into window const bool ret = Begin(temp_window_name, NULL, window_flags); // Restore style g.Style.ChildBorderSize = backup_border_size; if (child_flags & ImGuiChildFlags_FrameStyle) { PopStyleVar(3); PopStyleColor(); } ImGuiWindow* child_window = g.CurrentWindow; child_window->ChildId = id; // Set the cursor to handle case where the user called SetNextWindowPos()+BeginChild() manually. // While this is not really documented/defined, it seems that the expected thing to do. if (child_window->BeginCount == 1) parent_window->DC.CursorPos = child_window->Pos; // Process navigation-in immediately so NavInit can run on first frame // Can enter a child if (A) it has navigable items or (B) it can be scrolled. const ImGuiID temp_id_for_activation = ImHashStr("##Child", 0, id); if (g.ActiveId == temp_id_for_activation) ClearActiveID(); if (g.NavActivateId == id && !(window_flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY)) { FocusWindow(child_window); NavInitWindow(child_window, false); SetActiveID(temp_id_for_activation, child_window); // Steal ActiveId with another arbitrary id so that key-press won't activate child item g.ActiveIdSource = g.NavInputSource; } return ret; } void ImGui::EndChild() { ImGuiContext& g = *GImGui; ImGuiWindow* child_window = g.CurrentWindow; IM_ASSERT(g.WithinEndChild == false); IM_ASSERT(child_window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() calls g.WithinEndChild = true; ImVec2 child_size = child_window->Size; End(); if (child_window->BeginCount == 1) { ImGuiWindow* parent_window = g.CurrentWindow; ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + child_size); ItemSize(child_size); if ((child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY) && !(child_window->Flags & ImGuiWindowFlags_NavFlattened)) { ItemAdd(bb, child_window->ChildId); RenderNavHighlight(bb, child_window->ChildId); // When browsing a window that has no activable items (scroll only) we keep a highlight on the child (pass g.NavId to trick into always displaying) if (child_window->DC.NavLayersActiveMask == 0 && child_window == g.NavWindow) RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavHighlightFlags_Compact); } else { // Not navigable into ItemAdd(bb, 0); // But when flattened we directly reach items, adjust active layer mask accordingly if (child_window->Flags & ImGuiWindowFlags_NavFlattened) parent_window->DC.NavLayersActiveMaskNext |= child_window->DC.NavLayersActiveMaskNext; } if (g.HoveredWindow == child_window) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow; } g.WithinEndChild = false; g.LogLinePosY = -FLT_MAX; // To enforce a carriage return } static void SetWindowConditionAllowFlags(ImGuiWindow* window, ImGuiCond flags, bool enabled) { window->SetWindowPosAllowFlags = enabled ? (window->SetWindowPosAllowFlags | flags) : (window->SetWindowPosAllowFlags & ~flags); window->SetWindowSizeAllowFlags = enabled ? (window->SetWindowSizeAllowFlags | flags) : (window->SetWindowSizeAllowFlags & ~flags); window->SetWindowCollapsedAllowFlags = enabled ? (window->SetWindowCollapsedAllowFlags | flags) : (window->SetWindowCollapsedAllowFlags & ~flags); } ImGuiWindow* ImGui::FindWindowByID(ImGuiID id) { ImGuiContext& g = *GImGui; return (ImGuiWindow*)g.WindowsById.GetVoidPtr(id); } ImGuiWindow* ImGui::FindWindowByName(const char* name) { ImGuiID id = ImHashStr(name); return FindWindowByID(id); } static void ApplyWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings) { window->Pos = ImTrunc(ImVec2(settings->Pos.x, settings->Pos.y)); if (settings->Size.x > 0 && settings->Size.y > 0) window->Size = window->SizeFull = ImTrunc(ImVec2(settings->Size.x, settings->Size.y)); window->Collapsed = settings->Collapsed; } static void UpdateWindowInFocusOrderList(ImGuiWindow* window, bool just_created, ImGuiWindowFlags new_flags) { ImGuiContext& g = *GImGui; const bool new_is_explicit_child = (new_flags & ImGuiWindowFlags_ChildWindow) != 0 && ((new_flags & ImGuiWindowFlags_Popup) == 0 || (new_flags & ImGuiWindowFlags_ChildMenu) != 0); const bool child_flag_changed = new_is_explicit_child != window->IsExplicitChild; if ((just_created || child_flag_changed) && !new_is_explicit_child) { IM_ASSERT(!g.WindowsFocusOrder.contains(window)); g.WindowsFocusOrder.push_back(window); window->FocusOrder = (short)(g.WindowsFocusOrder.Size - 1); } else if (!just_created && child_flag_changed && new_is_explicit_child) { IM_ASSERT(g.WindowsFocusOrder[window->FocusOrder] == window); for (int n = window->FocusOrder + 1; n < g.WindowsFocusOrder.Size; n++) g.WindowsFocusOrder[n]->FocusOrder--; g.WindowsFocusOrder.erase(g.WindowsFocusOrder.Data + window->FocusOrder); window->FocusOrder = -1; } window->IsExplicitChild = new_is_explicit_child; } static void InitOrLoadWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings) { // Initial window state with e.g. default/arbitrary window position // Use SetNextWindowPos() with the appropriate condition flag to change the initial position of a window. const ImGuiViewport* main_viewport = ImGui::GetMainViewport(); window->Pos = main_viewport->Pos + ImVec2(60, 60); window->Size = window->SizeFull = ImVec2(0, 0); window->SetWindowPosAllowFlags = window->SetWindowSizeAllowFlags = window->SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing; if (settings != NULL) { SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false); ApplyWindowSettings(window, settings); } window->DC.CursorStartPos = window->DC.CursorMaxPos = window->DC.IdealMaxPos = window->Pos; // So first call to CalcWindowContentSizes() doesn't return crazy values if ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0) { window->AutoFitFramesX = window->AutoFitFramesY = 2; window->AutoFitOnlyGrows = false; } else { if (window->Size.x <= 0.0f) window->AutoFitFramesX = 2; if (window->Size.y <= 0.0f) window->AutoFitFramesY = 2; window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0); } } static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags) { // Create window the first time //IMGUI_DEBUG_LOG("CreateNewWindow '%s', flags = 0x%08X\n", name, flags); ImGuiContext& g = *GImGui; ImGuiWindow* window = IM_NEW(ImGuiWindow)(&g, name); window->Flags = flags; g.WindowsById.SetVoidPtr(window->ID, window); ImGuiWindowSettings* settings = NULL; if (!(flags & ImGuiWindowFlags_NoSavedSettings)) if ((settings = ImGui::FindWindowSettingsByWindow(window)) != 0) window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings); InitOrLoadWindowSettings(window, settings); if (flags & ImGuiWindowFlags_NoBringToFrontOnFocus) g.Windows.push_front(window); // Quite slow but rare and only once else g.Windows.push_back(window); return window; } static inline ImVec2 CalcWindowMinSize(ImGuiWindow* window) { // Popups, menus and childs bypass style.WindowMinSize by default, but we give then a non-zero minimum size to facilitate understanding problematic cases (e.g. empty popups) // FIXME: the if/else could probably be removed, "reduce artifacts" section for all windows. ImGuiContext& g = *GImGui; ImVec2 size_min; if (window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_ChildWindow)) { size_min.x = (window->ChildFlags & ImGuiChildFlags_ResizeX) ? g.Style.WindowMinSize.x : 4.0f; size_min.y = (window->ChildFlags & ImGuiChildFlags_ResizeY) ? g.Style.WindowMinSize.y : 4.0f; } else { ImGuiWindow* window_for_height = window; size_min.x = ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) == 0) ? g.Style.WindowMinSize.x : 4.0f; size_min.y = ((window->Flags & ImGuiWindowFlags_AlwaysAutoResize) == 0) ? g.Style.WindowMinSize.y : 4.0f; size_min.y = ImMax(size_min.y, window_for_height->TitleBarHeight() + window_for_height->MenuBarHeight() + ImMax(0.0f, g.Style.WindowRounding - 1.0f)); // Reduce artifacts with very small windows } return size_min; } static ImVec2 CalcWindowSizeAfterConstraint(ImGuiWindow* window, const ImVec2& size_desired) { ImGuiContext& g = *GImGui; ImVec2 new_size = size_desired; if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint) { // See comments in SetNextWindowSizeConstraints() for details about setting size_min an size_max. ImRect cr = g.NextWindowData.SizeConstraintRect; new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x; new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y; if (g.NextWindowData.SizeCallback) { ImGuiSizeCallbackData data; data.UserData = g.NextWindowData.SizeCallbackUserData; data.Pos = window->Pos; data.CurrentSize = window->SizeFull; data.DesiredSize = new_size; g.NextWindowData.SizeCallback(&data); new_size = data.DesiredSize; } new_size.x = IM_TRUNC(new_size.x); new_size.y = IM_TRUNC(new_size.y); } // Minimum size ImVec2 size_min = CalcWindowMinSize(window); return ImMax(new_size, size_min); } static void CalcWindowContentSizes(ImGuiWindow* window, ImVec2* content_size_current, ImVec2* content_size_ideal) { bool preserve_old_content_sizes = false; if (window->Collapsed && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) preserve_old_content_sizes = true; else if (window->Hidden && window->HiddenFramesCannotSkipItems == 0 && window->HiddenFramesCanSkipItems > 0) preserve_old_content_sizes = true; if (preserve_old_content_sizes) { *content_size_current = window->ContentSize; *content_size_ideal = window->ContentSizeIdeal; return; } content_size_current->x = (window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : IM_TRUNC(window->DC.CursorMaxPos.x - window->DC.CursorStartPos.x); content_size_current->y = (window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : IM_TRUNC(window->DC.CursorMaxPos.y - window->DC.CursorStartPos.y); content_size_ideal->x = (window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : IM_TRUNC(ImMax(window->DC.CursorMaxPos.x, window->DC.IdealMaxPos.x) - window->DC.CursorStartPos.x); content_size_ideal->y = (window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : IM_TRUNC(ImMax(window->DC.CursorMaxPos.y, window->DC.IdealMaxPos.y) - window->DC.CursorStartPos.y); } static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_contents) { ImGuiContext& g = *GImGui; ImGuiStyle& style = g.Style; const float decoration_w_without_scrollbars = window->DecoOuterSizeX1 + window->DecoOuterSizeX2 - window->ScrollbarSizes.x; const float decoration_h_without_scrollbars = window->DecoOuterSizeY1 + window->DecoOuterSizeY2 - window->ScrollbarSizes.y; ImVec2 size_pad = window->WindowPadding * 2.0f; ImVec2 size_desired = size_contents + size_pad + ImVec2(decoration_w_without_scrollbars, decoration_h_without_scrollbars); if (window->Flags & ImGuiWindowFlags_Tooltip) { // Tooltip always resize return size_desired; } else { // Maximum window size is determined by the viewport size or monitor size ImVec2 size_min = CalcWindowMinSize(window); ImVec2 size_max = ((window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_Popup)) ? ImVec2(FLT_MAX, FLT_MAX) : ImGui::GetMainViewport()->WorkSize - style.DisplaySafeAreaPadding * 2.0f; ImVec2 size_auto_fit = ImClamp(size_desired, size_min, size_max); // When the window cannot fit all contents (either because of constraints, either because screen is too small), // we are growing the size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than ViewportSize-WindowPadding. ImVec2 size_auto_fit_after_constraint = CalcWindowSizeAfterConstraint(window, size_auto_fit); bool will_have_scrollbar_x = (size_auto_fit_after_constraint.x - size_pad.x - decoration_w_without_scrollbars < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar); bool will_have_scrollbar_y = (size_auto_fit_after_constraint.y - size_pad.y - decoration_h_without_scrollbars < size_contents.y && !(window->Flags & ImGuiWindowFlags_NoScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysVerticalScrollbar); if (will_have_scrollbar_x) size_auto_fit.y += style.ScrollbarSize; if (will_have_scrollbar_y) size_auto_fit.x += style.ScrollbarSize; return size_auto_fit; } } ImVec2 ImGui::CalcWindowNextAutoFitSize(ImGuiWindow* window) { ImVec2 size_contents_current; ImVec2 size_contents_ideal; CalcWindowContentSizes(window, &size_contents_current, &size_contents_ideal); ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, size_contents_ideal); ImVec2 size_final = CalcWindowSizeAfterConstraint(window, size_auto_fit); return size_final; } static ImGuiCol GetWindowBgColorIdx(ImGuiWindow* window) { if (window->Flags & (ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) return ImGuiCol_PopupBg; if (window->Flags & ImGuiWindowFlags_ChildWindow) return ImGuiCol_ChildBg; return ImGuiCol_WindowBg; } static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, const ImVec2& corner_target, const ImVec2& corner_norm, ImVec2* out_pos, ImVec2* out_size) { ImVec2 pos_min = ImLerp(corner_target, window->Pos, corner_norm); // Expected window upper-left ImVec2 pos_max = ImLerp(window->Pos + window->Size, corner_target, corner_norm); // Expected window lower-right ImVec2 size_expected = pos_max - pos_min; ImVec2 size_constrained = CalcWindowSizeAfterConstraint(window, size_expected); *out_pos = pos_min; if (corner_norm.x == 0.0f) out_pos->x -= (size_constrained.x - size_expected.x); if (corner_norm.y == 0.0f) out_pos->y -= (size_constrained.y - size_expected.y); *out_size = size_constrained; } // Data for resizing from resize grip / corner struct ImGuiResizeGripDef { ImVec2 CornerPosN; ImVec2 InnerDir; int AngleMin12, AngleMax12; }; static const ImGuiResizeGripDef resize_grip_def[4] = { { ImVec2(1, 1), ImVec2(-1, -1), 0, 3 }, // Lower-right { ImVec2(0, 1), ImVec2(+1, -1), 3, 6 }, // Lower-left { ImVec2(0, 0), ImVec2(+1, +1), 6, 9 }, // Upper-left (Unused) { ImVec2(1, 0), ImVec2(-1, +1), 9, 12 } // Upper-right (Unused) }; // Data for resizing from borders struct ImGuiResizeBorderDef { ImVec2 InnerDir; // Normal toward inside ImVec2 SegmentN1, SegmentN2; // End positions, normalized (0,0: upper left) float OuterAngle; // Angle toward outside }; static const ImGuiResizeBorderDef resize_border_def[4] = { { ImVec2(+1, 0), ImVec2(0, 1), ImVec2(0, 0), IM_PI * 1.00f }, // Left { ImVec2(-1, 0), ImVec2(1, 0), ImVec2(1, 1), IM_PI * 0.00f }, // Right { ImVec2(0, +1), ImVec2(0, 0), ImVec2(1, 0), IM_PI * 1.50f }, // Up { ImVec2(0, -1), ImVec2(1, 1), ImVec2(0, 1), IM_PI * 0.50f } // Down }; static ImRect GetResizeBorderRect(ImGuiWindow* window, int border_n, float perp_padding, float thickness) { ImRect rect = window->Rect(); if (thickness == 0.0f) rect.Max -= ImVec2(1, 1); if (border_n == ImGuiDir_Left) { return ImRect(rect.Min.x - thickness, rect.Min.y + perp_padding, rect.Min.x + thickness, rect.Max.y - perp_padding); } if (border_n == ImGuiDir_Right) { return ImRect(rect.Max.x - thickness, rect.Min.y + perp_padding, rect.Max.x + thickness, rect.Max.y - perp_padding); } if (border_n == ImGuiDir_Up) { return ImRect(rect.Min.x + perp_padding, rect.Min.y - thickness, rect.Max.x - perp_padding, rect.Min.y + thickness); } if (border_n == ImGuiDir_Down) { return ImRect(rect.Min.x + perp_padding, rect.Max.y - thickness, rect.Max.x - perp_padding, rect.Max.y + thickness); } IM_ASSERT(0); return ImRect(); } // 0..3: corners (Lower-right, Lower-left, Unused, Unused) ImGuiID ImGui::GetWindowResizeCornerID(ImGuiWindow* window, int n) { IM_ASSERT(n >= 0 && n < 4); ImGuiID id = window->ID; id = ImHashStr("#RESIZE", 0, id); id = ImHashData(&n, sizeof(int), id); return id; } // Borders (Left, Right, Up, Down) ImGuiID ImGui::GetWindowResizeBorderID(ImGuiWindow* window, ImGuiDir dir) { IM_ASSERT(dir >= 0 && dir < 4); int n = (int)dir + 4; ImGuiID id = window->ID; id = ImHashStr("#RESIZE", 0, id); id = ImHashData(&n, sizeof(int), id); return id; } // Handle resize for: Resize Grips, Borders, Gamepad // Return true when using auto-fit (double-click on resize grip) static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_hovered, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4], const ImRect& visibility_rect) { ImGuiContext& g = *GImGui; ImGuiWindowFlags flags = window->Flags; if ((flags & ImGuiWindowFlags_NoResize) || (flags & ImGuiWindowFlags_AlwaysAutoResize) || window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) return false; if (window->WasActive == false) // Early out to avoid running this code for e.g. a hidden implicit/fallback Debug window. return false; int ret_auto_fit_mask = 0x00; const float grip_draw_size = IM_TRUNC(ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f)); const float grip_hover_inner_size = IM_TRUNC(grip_draw_size * 0.75f); const float grip_hover_outer_size = g.IO.ConfigWindowsResizeFromEdges ? WINDOWS_HOVER_PADDING : 0.0f; ImRect clamp_rect = visibility_rect; const bool window_move_from_title_bar = g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar); if (window_move_from_title_bar) clamp_rect.Min.y -= window->TitleBarHeight(); ImVec2 pos_target(FLT_MAX, FLT_MAX); ImVec2 size_target(FLT_MAX, FLT_MAX); // Resize grips and borders are on layer 1 window->DC.NavLayerCurrent = ImGuiNavLayer_Menu; // Manual resize grips PushID("#RESIZE"); for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++) { const ImGuiResizeGripDef& def = resize_grip_def[resize_grip_n]; const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, def.CornerPosN); // Using the FlattenChilds button flag we make the resize button accessible even if we are hovering over a child window bool hovered, held; ImRect resize_rect(corner - def.InnerDir * grip_hover_outer_size, corner + def.InnerDir * grip_hover_inner_size); if (resize_rect.Min.x > resize_rect.Max.x) ImSwap(resize_rect.Min.x, resize_rect.Max.x); if (resize_rect.Min.y > resize_rect.Max.y) ImSwap(resize_rect.Min.y, resize_rect.Max.y); ImGuiID resize_grip_id = window->GetID(resize_grip_n); // == GetWindowResizeCornerID() ItemAdd(resize_rect, resize_grip_id, NULL, ImGuiItemFlags_NoNav); ButtonBehavior(resize_rect, resize_grip_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus); //GetForegroundDrawList(window)->AddRect(resize_rect.Min, resize_rect.Max, IM_COL32(255, 255, 0, 255)); if (hovered || held) g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE; if (held && g.IO.MouseDoubleClicked[0]) { // Auto-fit when double-clicking size_target = CalcWindowSizeAfterConstraint(window, size_auto_fit); ret_auto_fit_mask = 0x03; // Both axises ClearActiveID(); } else if (held) { // Resize from any of the four corners // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position ImVec2 clamp_min = ImVec2(def.CornerPosN.x == 1.0f ? clamp_rect.Min.x : -FLT_MAX, (def.CornerPosN.y == 1.0f || (def.CornerPosN.y == 0.0f && window_move_from_title_bar)) ? clamp_rect.Min.y : -FLT_MAX); ImVec2 clamp_max = ImVec2(def.CornerPosN.x == 0.0f ? clamp_rect.Max.x : +FLT_MAX, def.CornerPosN.y == 0.0f ? clamp_rect.Max.y : +FLT_MAX); ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset + ImLerp(def.InnerDir * grip_hover_outer_size, def.InnerDir * -grip_hover_inner_size, def.CornerPosN); // Corner of the window corresponding to our corner grip corner_target = ImClamp(corner_target, clamp_min, clamp_max); CalcResizePosSizeFromAnyCorner(window, corner_target, def.CornerPosN, &pos_target, &size_target); } // Only lower-left grip is visible before hovering/activating if (resize_grip_n == 0 || held || hovered) resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); } int resize_border_mask = 0x00; if (window->Flags & ImGuiWindowFlags_ChildWindow) resize_border_mask |= ((window->ChildFlags & ImGuiChildFlags_ResizeX) ? 0x02 : 0) | ((window->ChildFlags & ImGuiChildFlags_ResizeY) ? 0x08 : 0); else resize_border_mask = g.IO.ConfigWindowsResizeFromEdges ? 0x0F : 0x00; for (int border_n = 0; border_n < 4; border_n++) { if ((resize_border_mask & (1 << border_n)) == 0) continue; const ImGuiResizeBorderDef& def = resize_border_def[border_n]; const ImGuiAxis axis = (border_n == ImGuiDir_Left || border_n == ImGuiDir_Right) ? ImGuiAxis_X : ImGuiAxis_Y; bool hovered, held; ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, WINDOWS_HOVER_PADDING); ImGuiID border_id = window->GetID(border_n + 4); // == GetWindowResizeBorderID() ItemAdd(border_rect, border_id, NULL, ImGuiItemFlags_NoNav); ButtonBehavior(border_rect, border_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus); //GetForegroundDrawList(window)->AddRect(border_rect.Min, border_rect.Max, IM_COL32(255, 255, 0, 255)); if (hovered && g.HoveredIdTimer <= WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER) hovered = false; if (hovered || held) g.MouseCursor = (axis == ImGuiAxis_X) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS; if (held && g.IO.MouseDoubleClicked[0]) { // Double-clicking bottom or right border auto-fit on this axis // FIXME: Support top and right borders: rework CalcResizePosSizeFromAnyCorner() to be reusable in both cases. if (border_n == 1 || border_n == 3) // Right and bottom border { size_target[axis] = CalcWindowSizeAfterConstraint(window, size_auto_fit)[axis]; ret_auto_fit_mask |= (1 << axis); hovered = held = false; // So border doesn't show highlighted at new position } ClearActiveID(); } else if (held) { // Switch to relative resizing mode when border geometry moved (e.g. resizing a child altering parent scroll), in order to avoid resizing feedback loop. // Currently only using relative mode on resizable child windows, as the problem to solve is more likely noticeable for them, but could apply for all windows eventually. // FIXME: May want to generalize this idiom at lower-level, so more widgets can use it! const bool just_scrolled_manually_while_resizing = (g.WheelingWindow != NULL && g.WheelingWindowScrolledFrame == g.FrameCount && IsWindowChildOf(window, g.WheelingWindow, false)); if (g.ActiveIdIsJustActivated || just_scrolled_manually_while_resizing) { g.WindowResizeBorderExpectedRect = border_rect; g.WindowResizeRelativeMode = false; } if ((window->Flags & ImGuiWindowFlags_ChildWindow) && memcmp(&g.WindowResizeBorderExpectedRect, &border_rect, sizeof(ImRect)) != 0) g.WindowResizeRelativeMode = true; const ImVec2 border_curr = (window->Pos + ImMin(def.SegmentN1, def.SegmentN2) * window->Size); const float border_target_rel_mode_for_axis = border_curr[axis] + g.IO.MouseDelta[axis]; const float border_target_abs_mode_for_axis = g.IO.MousePos[axis] - g.ActiveIdClickOffset[axis] + WINDOWS_HOVER_PADDING; // Match ButtonBehavior() padding above. // Use absolute mode position ImVec2 border_target = window->Pos; border_target[axis] = border_target_abs_mode_for_axis; // Use relative mode target for child window, ignore resize when moving back toward the ideal absolute position. bool ignore_resize = false; if (g.WindowResizeRelativeMode) { //GetForegroundDrawList()->AddText(GetMainViewport()->WorkPos, IM_COL32_WHITE, "Relative Mode"); border_target[axis] = border_target_rel_mode_for_axis; if (g.IO.MouseDelta[axis] == 0.0f || (g.IO.MouseDelta[axis] > 0.0f) == (border_target_rel_mode_for_axis > border_target_abs_mode_for_axis)) ignore_resize = true; } // Clamp, apply ImVec2 clamp_min(border_n == ImGuiDir_Right ? clamp_rect.Min.x : -FLT_MAX, border_n == ImGuiDir_Down || (border_n == ImGuiDir_Up && window_move_from_title_bar) ? clamp_rect.Min.y : -FLT_MAX); ImVec2 clamp_max(border_n == ImGuiDir_Left ? clamp_rect.Max.x : +FLT_MAX, border_n == ImGuiDir_Up ? clamp_rect.Max.y : +FLT_MAX); border_target = ImClamp(border_target, clamp_min, clamp_max); if (flags & ImGuiWindowFlags_ChildWindow) // Clamp resizing of childs within parent { if ((flags & (ImGuiWindowFlags_HorizontalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar)) == 0 || (flags & ImGuiWindowFlags_NoScrollbar)) border_target.x = ImClamp(border_target.x, window->ParentWindow->InnerClipRect.Min.x, window->ParentWindow->InnerClipRect.Max.x); if (flags & ImGuiWindowFlags_NoScrollbar) border_target.y = ImClamp(border_target.y, window->ParentWindow->InnerClipRect.Min.y, window->ParentWindow->InnerClipRect.Max.y); } if (!ignore_resize) CalcResizePosSizeFromAnyCorner(window, border_target, ImMin(def.SegmentN1, def.SegmentN2), &pos_target, &size_target); } if (hovered) *border_hovered = border_n; if (held) *border_held = border_n; } PopID(); // Restore nav layer window->DC.NavLayerCurrent = ImGuiNavLayer_Main; // Navigation resize (keyboard/gamepad) // FIXME: This cannot be moved to NavUpdateWindowing() because CalcWindowSizeAfterConstraint() need to callback into user. // Not even sure the callback works here. if (g.NavWindowingTarget && g.NavWindowingTarget->RootWindow == window) { ImVec2 nav_resize_dir; if (g.NavInputSource == ImGuiInputSource_Keyboard && g.IO.KeyShift) nav_resize_dir = GetKeyMagnitude2d(ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow); if (g.NavInputSource == ImGuiInputSource_Gamepad) nav_resize_dir = GetKeyMagnitude2d(ImGuiKey_GamepadDpadLeft, ImGuiKey_GamepadDpadRight, ImGuiKey_GamepadDpadUp, ImGuiKey_GamepadDpadDown); if (nav_resize_dir.x != 0.0f || nav_resize_dir.y != 0.0f) { const float NAV_RESIZE_SPEED = 600.0f; const float resize_step = NAV_RESIZE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y); g.NavWindowingAccumDeltaSize += nav_resize_dir * resize_step; g.NavWindowingAccumDeltaSize = ImMax(g.NavWindowingAccumDeltaSize, clamp_rect.Min - window->Pos - window->Size); // We need Pos+Size >= clmap_rect.Min, so Size >= clmap_rect.Min - Pos, so size_delta >= clmap_rect.Min - window->Pos - window->Size g.NavWindowingToggleLayer = false; g.NavDisableMouseHover = true; resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive); ImVec2 accum_floored = ImTrunc(g.NavWindowingAccumDeltaSize); if (accum_floored.x != 0.0f || accum_floored.y != 0.0f) { // FIXME-NAV: Should store and accumulate into a separate size buffer to handle sizing constraints properly, right now a constraint will make us stuck. size_target = CalcWindowSizeAfterConstraint(window, window->SizeFull + accum_floored); g.NavWindowingAccumDeltaSize -= accum_floored; } } } // Apply back modified position/size to window const ImVec2 curr_pos = window->Pos; const ImVec2 curr_size = window->SizeFull; if (size_target.x != FLT_MAX && (window->Size.x != size_target.x || window->SizeFull.x != size_target.x)) window->Size.x = window->SizeFull.x = size_target.x; if (size_target.y != FLT_MAX && (window->Size.y != size_target.y || window->SizeFull.y != size_target.y)) window->Size.y = window->SizeFull.y = size_target.y; if (pos_target.x != FLT_MAX && window->Pos.x != ImTrunc(pos_target.x)) window->Pos.x = ImTrunc(pos_target.x); if (pos_target.y != FLT_MAX && window->Pos.y != ImTrunc(pos_target.y)) window->Pos.y = ImTrunc(pos_target.y); if (curr_pos.x != window->Pos.x || curr_pos.y != window->Pos.y || curr_size.x != window->SizeFull.x || curr_size.y != window->SizeFull.y) MarkIniSettingsDirty(window); // Recalculate next expected border expected coordinates if (*border_held != -1) g.WindowResizeBorderExpectedRect = GetResizeBorderRect(window, *border_held, grip_hover_inner_size, WINDOWS_HOVER_PADDING); return ret_auto_fit_mask; } static inline void ClampWindowPos(ImGuiWindow* window, const ImRect& visibility_rect) { ImGuiContext& g = *GImGui; ImVec2 size_for_clamping = window->Size; if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(window->Flags & ImGuiWindowFlags_NoTitleBar)) size_for_clamping.y = window->TitleBarHeight(); window->Pos = ImClamp(window->Pos, visibility_rect.Min - size_for_clamping, visibility_rect.Max); } static void RenderWindowOuterSingleBorder(ImGuiWindow* window, int border_n, ImU32 border_col, float border_size) { const ImGuiResizeBorderDef& def = resize_border_def[border_n]; const float rounding = window->WindowRounding; const ImRect border_r = GetResizeBorderRect(window, border_n, rounding, 0.0f); window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.SegmentN1) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle - IM_PI * 0.25f, def.OuterAngle); window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.SegmentN2) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle, def.OuterAngle + IM_PI * 0.25f); window->DrawList->PathStroke(border_col, ImDrawFlags_None, border_size); } static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window) { ImGuiContext& g = *GImGui; const float border_size = window->WindowBorderSize; const ImU32 border_col = GetColorU32(ImGuiCol_Border); if (border_size > 0.0f && (window->Flags & ImGuiWindowFlags_NoBackground) == 0) window->DrawList->AddRect(window->Pos, window->Pos + window->Size, border_col, window->WindowRounding, 0, window->WindowBorderSize); else if (border_size > 0.0f) { if (window->ChildFlags & ImGuiChildFlags_ResizeX) // Similar code as 'resize_border_mask' computation in UpdateWindowManualResize() but we specifically only always draw explicit child resize border. RenderWindowOuterSingleBorder(window, 1, border_col, border_size); if (window->ChildFlags & ImGuiChildFlags_ResizeY) RenderWindowOuterSingleBorder(window, 3, border_col, border_size); } if (window->ResizeBorderHovered != -1 || window->ResizeBorderHeld != -1) { const int border_n = (window->ResizeBorderHeld != -1) ? window->ResizeBorderHeld : window->ResizeBorderHovered; const ImU32 border_col_resizing = GetColorU32((window->ResizeBorderHeld != -1) ? ImGuiCol_SeparatorActive : ImGuiCol_SeparatorHovered); RenderWindowOuterSingleBorder(window, border_n, border_col_resizing, ImMax(2.0f, window->WindowBorderSize)); // Thicker than usual } if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar)) { float y = window->Pos.y + window->TitleBarHeight() - 1; window->DrawList->AddLine(ImVec2(window->Pos.x + border_size, y), ImVec2(window->Pos.x + window->Size.x - border_size, y), border_col, g.Style.FrameBorderSize); } } // Draw background and borders // Draw and handle scrollbars void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, bool handle_borders_and_resize_grips, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size) { ImGuiContext& g = *GImGui; ImGuiStyle& style = g.Style; ImGuiWindowFlags flags = window->Flags; // Ensure that ScrollBar doesn't read last frame's SkipItems IM_ASSERT(window->BeginCount == 0); window->SkipItems = false; // Draw window + handle manual resize // As we highlight the title bar when want_focus is set, multiple reappearing windows will have their title bar highlighted on their reappearing frame. const float window_rounding = window->WindowRounding; const float window_border_size = window->WindowBorderSize; if (window->Collapsed) { // Title bar only const float backup_border_size = style.FrameBorderSize; g.Style.FrameBorderSize = window->WindowBorderSize; ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && !g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed); RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, true, window_rounding); g.Style.FrameBorderSize = backup_border_size; } else { // Window background if (!(flags & ImGuiWindowFlags_NoBackground)) { ImU32 bg_col = GetColorU32(GetWindowBgColorIdx(window)); bool override_alpha = false; float alpha = 1.0f; if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasBgAlpha) { alpha = g.NextWindowData.BgAlphaVal; override_alpha = true; } if (override_alpha) bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT); window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom); } // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) { ImU32 title_bar_col = GetColorU32(title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg); window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawFlags_RoundCornersTop); } // Menu bar if (flags & ImGuiWindowFlags_MenuBar) { ImRect menu_bar_rect = window->MenuBarRect(); menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them. window->DrawList->AddRectFilled(menu_bar_rect.Min + ImVec2(window_border_size, 0), menu_bar_rect.Max - ImVec2(window_border_size, 0), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawFlags_RoundCornersTop); if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y) window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize); } // Scrollbars if (window->ScrollbarX) Scrollbar(ImGuiAxis_X); if (window->ScrollbarY) Scrollbar(ImGuiAxis_Y); // Render resize grips (after their input handling so we don't have a frame of latency) if (handle_borders_and_resize_grips && !(flags & ImGuiWindowFlags_NoResize)) { for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++) { const ImU32 col = resize_grip_col[resize_grip_n]; if ((col & IM_COL32_A_MASK) == 0) continue; const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n]; const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPosN); window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, resize_grip_draw_size) : ImVec2(resize_grip_draw_size, window_border_size))); window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(resize_grip_draw_size, window_border_size) : ImVec2(window_border_size, resize_grip_draw_size))); window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + window_border_size), corner.y + grip.InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.AngleMin12, grip.AngleMax12); window->DrawList->PathFillConvex(col); } } // Borders if (handle_borders_and_resize_grips) RenderWindowOuterBorders(window); } } // Render title text, collapse button, close button void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open) { ImGuiContext& g = *GImGui; ImGuiStyle& style = g.Style; ImGuiWindowFlags flags = window->Flags; const bool has_close_button = (p_open != NULL); const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse) && (style.WindowMenuButtonPosition != ImGuiDir_None); // Close & Collapse button are on the Menu NavLayer and don't default focus (unless there's nothing else on that layer) // FIXME-NAV: Might want (or not?) to set the equivalent of ImGuiButtonFlags_NoNavFocus so that mouse clicks on standard title bar items don't necessarily set nav/keyboard ref? const ImGuiItemFlags item_flags_backup = g.CurrentItemFlags; g.CurrentItemFlags |= ImGuiItemFlags_NoNavDefaultFocus; window->DC.NavLayerCurrent = ImGuiNavLayer_Menu; // Layout buttons // FIXME: Would be nice to generalize the subtleties expressed here into reusable code. float pad_l = style.FramePadding.x; float pad_r = style.FramePadding.x; float button_sz = g.FontSize; ImVec2 close_button_pos; ImVec2 collapse_button_pos; if (has_close_button) { close_button_pos = ImVec2(title_bar_rect.Max.x - pad_r - button_sz, title_bar_rect.Min.y + style.FramePadding.y); pad_r += button_sz + style.ItemInnerSpacing.x; } if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Right) { collapse_button_pos = ImVec2(title_bar_rect.Max.x - pad_r - button_sz, title_bar_rect.Min.y + style.FramePadding.y); pad_r += button_sz + style.ItemInnerSpacing.x; } if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Left) { collapse_button_pos = ImVec2(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y + style.FramePadding.y); pad_l += button_sz + style.ItemInnerSpacing.x; } // Collapse button (submitting first so it gets priority when choosing a navigation init fallback) if (has_collapse_button) if (CollapseButton(window->GetID("#COLLAPSE"), collapse_button_pos)) window->WantCollapseToggle = true; // Defer actual collapsing to next frame as we are too far in the Begin() function // Close button if (has_close_button) if (CloseButton(window->GetID("#CLOSE"), close_button_pos)) *p_open = false; window->DC.NavLayerCurrent = ImGuiNavLayer_Main; g.CurrentItemFlags = item_flags_backup; // Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker) // FIXME: Refactor text alignment facilities along with RenderText helpers, this is WAY too much messy code.. const float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? button_sz * 0.80f : 0.0f; const ImVec2 text_size = CalcTextSize(name, NULL, true) + ImVec2(marker_size_x, 0.0f); // As a nice touch we try to ensure that centered title text doesn't get affected by visibility of Close/Collapse button, // while uncentered title text will still reach edges correctly. if (pad_l > style.FramePadding.x) pad_l += g.Style.ItemInnerSpacing.x; if (pad_r > style.FramePadding.x) pad_r += g.Style.ItemInnerSpacing.x; if (style.WindowTitleAlign.x > 0.0f && style.WindowTitleAlign.x < 1.0f) { float centerness = ImSaturate(1.0f - ImFabs(style.WindowTitleAlign.x - 0.5f) * 2.0f); // 0.0f on either edges, 1.0f on center float pad_extend = ImMin(ImMax(pad_l, pad_r), title_bar_rect.GetWidth() - pad_l - pad_r - text_size.x); pad_l = ImMax(pad_l, pad_extend * centerness); pad_r = ImMax(pad_r, pad_extend * centerness); } ImRect layout_r(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y, title_bar_rect.Max.x - pad_r, title_bar_rect.Max.y); ImRect clip_r(layout_r.Min.x, layout_r.Min.y, ImMin(layout_r.Max.x + g.Style.ItemInnerSpacing.x, title_bar_rect.Max.x), layout_r.Max.y); if (flags & ImGuiWindowFlags_UnsavedDocument) { ImVec2 marker_pos; marker_pos.x = ImClamp(layout_r.Min.x + (layout_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x + text_size.x, layout_r.Min.x, layout_r.Max.x); marker_pos.y = (layout_r.Min.y + layout_r.Max.y) * 0.5f; if (marker_pos.x > layout_r.Min.x) { RenderBullet(window->DrawList, marker_pos, GetColorU32(ImGuiCol_Text)); clip_r.Max.x = ImMin(clip_r.Max.x, marker_pos.x - (int)(marker_size_x * 0.5f)); } } //if (g.IO.KeyShift) window->DrawList->AddRect(layout_r.Min, layout_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG] //if (g.IO.KeyCtrl) window->DrawList->AddRect(clip_r.Min, clip_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG] RenderTextClipped(layout_r.Min, layout_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_r); } void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window) { window->ParentWindow = parent_window; window->RootWindow = window->RootWindowPopupTree = window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window; if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip)) window->RootWindow = parent_window->RootWindow; if (parent_window && (flags & ImGuiWindowFlags_Popup)) window->RootWindowPopupTree = parent_window->RootWindowPopupTree; if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight; while (window->RootWindowForNav->Flags & ImGuiWindowFlags_NavFlattened) { IM_ASSERT(window->RootWindowForNav->ParentWindow != NULL); window->RootWindowForNav = window->RootWindowForNav->ParentWindow; } } // When a modal popup is open, newly created windows that want focus (i.e. are not popups and do not specify ImGuiWindowFlags_NoFocusOnAppearing) // should be positioned behind that modal window, unless the window was created inside the modal begin-stack. // In case of multiple stacked modals newly created window honors begin stack order and does not go below its own modal parent. // - WindowA // FindBlockingModal() returns Modal1 // - WindowB // .. returns Modal1 // - Modal1 // .. returns Modal2 // - WindowC // .. returns Modal2 // - WindowD // .. returns Modal2 // - Modal2 // .. returns Modal2 // - WindowE // .. returns NULL // Notes: // - FindBlockingModal(NULL) == NULL is generally equivalent to GetTopMostPopupModal() == NULL. // Only difference is here we check for ->Active/WasActive but it may be unecessary. ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window) { ImGuiContext& g = *GImGui; if (g.OpenPopupStack.Size <= 0) return NULL; // Find a modal that has common parent with specified window. Specified window should be positioned behind that modal. for (ImGuiPopupData& popup_data : g.OpenPopupStack) { ImGuiWindow* popup_window = popup_data.Window; if (popup_window == NULL || !(popup_window->Flags & ImGuiWindowFlags_Modal)) continue; if (!popup_window->Active && !popup_window->WasActive) // Check WasActive, because this code may run before popup renders on current frame, also check Active to handle newly created windows. continue; if (window == NULL) // FindBlockingModal(NULL) test for if FocusWindow(NULL) is naturally possible via a mouse click. return popup_window; if (IsWindowWithinBeginStackOf(window, popup_window)) // Window may be over modal continue; return popup_window; // Place window right below first block modal } return NULL; } // Push a new Dear ImGui window to add widgets to. // - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair. // - Begin/End can be called multiple times during the frame with the same window name to append content. // - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file). // You can use the "##" or "###" markers to use the same label with different id, or same id with different label. See documentation at the top of this file. // - Return false when window is collapsed, so you can early out in your code. You always need to call ImGui::End() even if false is returned. // - Passing 'bool* p_open' displays a Close button on the upper-right corner of the window, the pointed value will be set to false when the button is pressed. bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; IM_ASSERT(name != NULL && name[0] != '\0'); // Window name required IM_ASSERT(g.WithinFrameScope); // Forgot to call ImGui::NewFrame() IM_ASSERT(g.FrameCountEnded != g.FrameCount); // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet // Find or create ImGuiWindow* window = FindWindowByName(name); const bool window_just_created = (window == NULL); if (window_just_created) window = CreateNewWindow(name, flags); // [DEBUG] Debug break requested by user if (g.DebugBreakInWindow == window->ID) IM_DEBUG_BREAK(); // Automatically disable manual moving/resizing when NoInputs is set if ((flags & ImGuiWindowFlags_NoInputs) == ImGuiWindowFlags_NoInputs) flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; if (flags & ImGuiWindowFlags_NavFlattened) IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow); const int current_frame = g.FrameCount; const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame); window->IsFallbackWindow = (g.CurrentWindowStack.Size == 0 && g.WithinFrameScopeWithImplicitWindow); // Update the Appearing flag bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on if (flags & ImGuiWindowFlags_Popup) { ImGuiPopupData& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size]; window_just_activated_by_user |= (window->PopupId != popup_ref.PopupId); // We recycle popups so treat window as activated if popup id changed window_just_activated_by_user |= (window != popup_ref.Window); } window->Appearing = window_just_activated_by_user; if (window->Appearing) SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, true); // Update Flags, LastFrameActive, BeginOrderXXX fields if (first_begin_of_the_frame) { UpdateWindowInFocusOrderList(window, window_just_created, flags); window->Flags = (ImGuiWindowFlags)flags; window->ChildFlags = (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasChildFlags) ? g.NextWindowData.ChildFlags : 0; window->LastFrameActive = current_frame; window->LastTimeActive = (float)g.Time; window->BeginOrderWithinParent = 0; window->BeginOrderWithinContext = (short)(g.WindowsActiveCount++); } else { flags = window->Flags; } // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack ImGuiWindow* parent_window_in_stack = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back().Window; ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow; IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); // We allow window memory to be compacted so recreate the base stack when needed. if (window->IDStack.Size == 0) window->IDStack.push_back(window->ID); // Add to stack g.CurrentWindow = window; ImGuiWindowStackData window_stack_data; window_stack_data.Window = window; window_stack_data.ParentLastItemDataBackup = g.LastItemData; window_stack_data.StackSizesOnBegin.SetToContextState(&g); g.CurrentWindowStack.push_back(window_stack_data); if (flags & ImGuiWindowFlags_ChildMenu) g.BeginMenuDepth++; // Update ->RootWindow and others pointers (before any possible call to FocusWindow) if (first_begin_of_the_frame) { UpdateWindowParentAndRootLinks(window, flags, parent_window); window->ParentWindowInBeginStack = parent_window_in_stack; // There's little point to expose a flag to set this: because the interesting cases won't be using parent_window_in_stack, // e.g. linking a tool window in a standalone viewport to a document window, regardless of their Begin() stack parenting. (#6798) window->ParentWindowForFocusRoute = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window_in_stack : NULL; } // Add to focus scope stack PushFocusScope((flags & ImGuiWindowFlags_NavFlattened) ? g.CurrentFocusScopeId : window->ID); window->NavRootFocusScopeId = g.CurrentFocusScopeId; // Add to popup stack if (flags & ImGuiWindowFlags_Popup) { ImGuiPopupData& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size]; popup_ref.Window = window; popup_ref.ParentNavLayer = parent_window_in_stack->DC.NavLayerCurrent; g.BeginPopupStack.push_back(popup_ref); window->PopupId = popup_ref.PopupId; } // Process SetNextWindow***() calls // (FIXME: Consider splitting the HasXXX flags into X/Y components bool window_pos_set_by_api = false; bool window_size_x_set_by_api = false, window_size_y_set_by_api = false; if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) { window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.NextWindowData.PosCond) != 0; if (window_pos_set_by_api && ImLengthSqr(g.NextWindowData.PosPivotVal) > 0.00001f) { // May be processed on the next frame if this is our first frame and we are measuring size // FIXME: Look into removing the branch so everything can go through this same code path for consistency. window->SetWindowPosVal = g.NextWindowData.PosVal; window->SetWindowPosPivot = g.NextWindowData.PosPivotVal; window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); } else { SetWindowPos(window, g.NextWindowData.PosVal, g.NextWindowData.PosCond); } } if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) { window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.x > 0.0f); window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.y > 0.0f); if ((window->ChildFlags & ImGuiChildFlags_ResizeX) && (window->SetWindowSizeAllowFlags & ImGuiCond_FirstUseEver) == 0) // Axis-specific conditions for BeginChild() g.NextWindowData.SizeVal.x = window->SizeFull.x; if ((window->ChildFlags & ImGuiChildFlags_ResizeY) && (window->SetWindowSizeAllowFlags & ImGuiCond_FirstUseEver) == 0) g.NextWindowData.SizeVal.y = window->SizeFull.y; SetWindowSize(window, g.NextWindowData.SizeVal, g.NextWindowData.SizeCond); } if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasScroll) { if (g.NextWindowData.ScrollVal.x >= 0.0f) { window->ScrollTarget.x = g.NextWindowData.ScrollVal.x; window->ScrollTargetCenterRatio.x = 0.0f; } if (g.NextWindowData.ScrollVal.y >= 0.0f) { window->ScrollTarget.y = g.NextWindowData.ScrollVal.y; window->ScrollTargetCenterRatio.y = 0.0f; } } if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasContentSize) window->ContentSizeExplicit = g.NextWindowData.ContentSizeVal; else if (first_begin_of_the_frame) window->ContentSizeExplicit = ImVec2(0.0f, 0.0f); if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasCollapsed) SetWindowCollapsed(window, g.NextWindowData.CollapsedVal, g.NextWindowData.CollapsedCond); if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasFocus) FocusWindow(window); if (window->Appearing) SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false); // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow() g.CurrentWindow = NULL; // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) { // Initialize const bool window_is_child_tooltip = (flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_Tooltip); // FIXME-WIP: Undocumented behavior of Child+Tooltip for pinned tooltip (#1345) const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesCannotSkipItems > 0); window->Active = true; window->HasCloseButton = (p_open != NULL); window->ClipRect = ImVec4(-FLT_MAX, -FLT_MAX, +FLT_MAX, +FLT_MAX); window->IDStack.resize(1); window->DrawList->_ResetForNewFrame(); window->DC.CurrentTableIdx = -1; // Restore buffer capacity when woken from a compacted state, to avoid if (window->MemoryCompacted) GcAwakeTransientWindowBuffers(window); // Update stored window name when it changes (which can _only_ happen with the "###" operator, so the ID would stay unchanged). // The title bar always display the 'name' parameter, so we only update the string storage if it needs to be visible to the end-user elsewhere. bool window_title_visible_elsewhere = false; if (g.NavWindowingListWindow != NULL && (window->Flags & ImGuiWindowFlags_NoNavFocus) == 0) // Window titles visible when using CTRL+TAB window_title_visible_elsewhere = true; if (window_title_visible_elsewhere && !window_just_created && strcmp(name, window->Name) != 0) { size_t buf_len = (size_t)window->NameBufLen; window->Name = ImStrdupcpy(window->Name, &buf_len, name); window->NameBufLen = (int)buf_len; } // UPDATE CONTENTS SIZE, UPDATE HIDDEN STATUS // Update contents size from last frame for auto-fitting (or use explicit size) CalcWindowContentSizes(window, &window->ContentSize, &window->ContentSizeIdeal); if (window->HiddenFramesCanSkipItems > 0) window->HiddenFramesCanSkipItems--; if (window->HiddenFramesCannotSkipItems > 0) window->HiddenFramesCannotSkipItems--; if (window->HiddenFramesForRenderOnly > 0) window->HiddenFramesForRenderOnly--; // Hide new windows for one frame until they calculate their size if (window_just_created && (!window_size_x_set_by_api || !window_size_y_set_by_api)) window->HiddenFramesCannotSkipItems = 1; // Hide popup/tooltip window when re-opening while we measure size (because we recycle the windows) // We reset Size/ContentSize for reappearing popups/tooltips early in this function, so further code won't be tempted to use the old size. if (window_just_activated_by_user && (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0) { window->HiddenFramesCannotSkipItems = 1; if (flags & ImGuiWindowFlags_AlwaysAutoResize) { if (!window_size_x_set_by_api) window->Size.x = window->SizeFull.x = 0.f; if (!window_size_y_set_by_api) window->Size.y = window->SizeFull.y = 0.f; window->ContentSize = window->ContentSizeIdeal = ImVec2(0.f, 0.f); } } // SELECT VIEWPORT // FIXME-VIEWPORT: In the docking/viewport branch, this is the point where we select the current viewport (which may affect the style) ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)GetMainViewport(); SetWindowViewport(window, viewport); SetCurrentWindow(window); // LOCK BORDER SIZE AND PADDING FOR THE FRAME (so that altering them doesn't cause inconsistencies) if (flags & ImGuiWindowFlags_ChildWindow) window->WindowBorderSize = style.ChildBorderSize; else window->WindowBorderSize = ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize; window->WindowPadding = style.WindowPadding; if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !(window->ChildFlags & ImGuiChildFlags_AlwaysUseWindowPadding) && window->WindowBorderSize == 0.0f) window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f); // Lock menu offset so size calculation can use it as menu-bar windows need a minimum size. window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x); window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y; bool use_current_size_for_scrollbar_x = window_just_created; bool use_current_size_for_scrollbar_y = window_just_created; // Collapse window by double-clicking on title bar // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse)) { // We don't use a regular button+id to test for double-click on title bar (mostly due to legacy reason, could be fixed), so verify that we don't have items over the title bar. ImRect title_bar_rect = window->TitleBarRect(); if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseClickedCount[0] == 2) window->WantCollapseToggle = true; if (window->WantCollapseToggle) { window->Collapsed = !window->Collapsed; if (!window->Collapsed) use_current_size_for_scrollbar_y = true; MarkIniSettingsDirty(window); } } else { window->Collapsed = false; } window->WantCollapseToggle = false; // SIZE // Outer Decoration Sizes // (we need to clear ScrollbarSize immediatly as CalcWindowAutoFitSize() needs it and can be called from other locations). const ImVec2 scrollbar_sizes_from_last_frame = window->ScrollbarSizes; window->DecoOuterSizeX1 = 0.0f; window->DecoOuterSizeX2 = 0.0f; window->DecoOuterSizeY1 = window->TitleBarHeight() + window->MenuBarHeight(); window->DecoOuterSizeY2 = 0.0f; window->ScrollbarSizes = ImVec2(0.0f, 0.0f); // Calculate auto-fit size, handle automatic resize const ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, window->ContentSizeIdeal); if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed) { // Using SetNextWindowSize() overrides ImGuiWindowFlags_AlwaysAutoResize, so it can be used on tooltips/popups, etc. if (!window_size_x_set_by_api) { window->SizeFull.x = size_auto_fit.x; use_current_size_for_scrollbar_x = true; } if (!window_size_y_set_by_api) { window->SizeFull.y = size_auto_fit.y; use_current_size_for_scrollbar_y = true; } } else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) { // Auto-fit may only grow window during the first few frames // We still process initial auto-fit on collapsed windows to get a window width, but otherwise don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed. if (!window_size_x_set_by_api && window->AutoFitFramesX > 0) { window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x; use_current_size_for_scrollbar_x = true; } if (!window_size_y_set_by_api && window->AutoFitFramesY > 0) { window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y; use_current_size_for_scrollbar_y = true; } if (!window->Collapsed) MarkIniSettingsDirty(window); } // Apply minimum/maximum window size constraints and final size window->SizeFull = CalcWindowSizeAfterConstraint(window, window->SizeFull); window->Size = window->Collapsed && !(flags & ImGuiWindowFlags_ChildWindow) ? window->TitleBarRect().GetSize() : window->SizeFull; // POSITION // Popup latch its initial position, will position itself when it appears next frame if (window_just_activated_by_user) { window->AutoPosLastDirection = ImGuiDir_None; if ((flags & ImGuiWindowFlags_Popup) != 0 && !(flags & ImGuiWindowFlags_Modal) && !window_pos_set_by_api) // FIXME: BeginPopup() could use SetNextWindowPos() window->Pos = g.BeginPopupStack.back().OpenPopupPos; } // Position child window if (flags & ImGuiWindowFlags_ChildWindow) { IM_ASSERT(parent_window && parent_window->Active); window->BeginOrderWithinParent = (short)parent_window->DC.ChildWindows.Size; parent_window->DC.ChildWindows.push_back(window); if (!(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api && !window_is_child_tooltip) window->Pos = parent_window->DC.CursorPos; } const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFramesCannotSkipItems == 0); if (window_pos_with_pivot) SetWindowPos(window, window->SetWindowPosVal - window->Size * window->SetWindowPosPivot, 0); // Position given a pivot (e.g. for centering) else if ((flags & ImGuiWindowFlags_ChildMenu) != 0) window->Pos = FindBestWindowPosForPopup(window); else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize) window->Pos = FindBestWindowPosForPopup(window); else if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !window_is_child_tooltip) window->Pos = FindBestWindowPosForPopup(window); // Calculate the range of allowed position for that window (to be movable and visible past safe area padding) // When clamping to stay visible, we will enforce that window->Pos stays inside of visibility_rect. ImRect viewport_rect(viewport->GetMainRect()); ImRect viewport_work_rect(viewport->GetWorkRect()); ImVec2 visibility_padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding); ImRect visibility_rect(viewport_work_rect.Min + visibility_padding, viewport_work_rect.Max - visibility_padding); // Clamp position/size so window stays visible within its viewport or monitor // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing. if (!window_pos_set_by_api && !(flags & ImGuiWindowFlags_ChildWindow)) if (viewport_rect.GetWidth() > 0.0f && viewport_rect.GetHeight() > 0.0f) ClampWindowPos(window, visibility_rect); window->Pos = ImTrunc(window->Pos); // Lock window rounding for the frame (so that altering them doesn't cause inconsistencies) // Large values tend to lead to variety of artifacts and are not recommended. window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding; // For windows with title bar or menu bar, we clamp to FrameHeight(FontSize + FramePadding.y * 2.0f) to completely hide artifacts. //if ((window->Flags & ImGuiWindowFlags_MenuBar) || !(window->Flags & ImGuiWindowFlags_NoTitleBar)) // window->WindowRounding = ImMin(window->WindowRounding, g.FontSize + style.FramePadding.y * 2.0f); // Apply window focus (new and reactivated windows are moved to front) bool want_focus = false; if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing)) { if (flags & ImGuiWindowFlags_Popup) want_focus = true; else if ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip)) == 0) want_focus = true; } // [Test Engine] Register whole window in the item system (before submitting further decorations) #ifdef IMGUI_ENABLE_TEST_ENGINE if (g.TestEngineHookItems) { IM_ASSERT(window->IDStack.Size == 1); window->IDStack.Size = 0; // As window->IDStack[0] == window->ID here, make sure TestEngine doesn't erroneously see window as parent of itself. IMGUI_TEST_ENGINE_ITEM_ADD(window->ID, window->Rect(), NULL); IMGUI_TEST_ENGINE_ITEM_INFO(window->ID, window->Name, (g.HoveredWindow == window) ? ImGuiItemStatusFlags_HoveredRect : 0); window->IDStack.Size = 1; } #endif // Handle manual resize: Resize Grips, Borders, Gamepad int border_hovered = -1, border_held = -1; ImU32 resize_grip_col[4] = {}; const int resize_grip_count = (window->Flags & ImGuiWindowFlags_ChildWindow) ? 0 : g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it. const float resize_grip_draw_size = IM_TRUNC(ImMax(g.FontSize * 1.10f, window->WindowRounding + 1.0f + g.FontSize * 0.2f)); if (!window->Collapsed) if (int auto_fit_mask = UpdateWindowManualResize(window, size_auto_fit, &border_hovered, &border_held, resize_grip_count, &resize_grip_col[0], visibility_rect)) { if (auto_fit_mask & (1 << ImGuiAxis_X)) use_current_size_for_scrollbar_x = true; if (auto_fit_mask & (1 << ImGuiAxis_Y)) use_current_size_for_scrollbar_y = true; } window->ResizeBorderHovered = (signed char)border_hovered; window->ResizeBorderHeld = (signed char)border_held; // SCROLLBAR VISIBILITY // Update scrollbar visibility (based on the Size that was effective during last frame or the auto-resized Size). if (!window->Collapsed) { // When reading the current size we need to read it after size constraints have been applied. // Intentionally use previous frame values for InnerRect and ScrollbarSizes. // And when we use window->DecorationUp here it doesn't have ScrollbarSizes.y applied yet. ImVec2 avail_size_from_current_frame = ImVec2(window->SizeFull.x, window->SizeFull.y - (window->DecoOuterSizeY1 + window->DecoOuterSizeY2)); ImVec2 avail_size_from_last_frame = window->InnerRect.GetSize() + scrollbar_sizes_from_last_frame; ImVec2 needed_size_from_last_frame = window_just_created ? ImVec2(0, 0) : window->ContentSize + window->WindowPadding * 2.0f; float size_x_for_scrollbars = use_current_size_for_scrollbar_x ? avail_size_from_current_frame.x : avail_size_from_last_frame.x; float size_y_for_scrollbars = use_current_size_for_scrollbar_y ? avail_size_from_current_frame.y : avail_size_from_last_frame.y; //bool scrollbar_y_from_last_frame = window->ScrollbarY; // FIXME: May want to use that in the ScrollbarX expression? How many pros vs cons? window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar)); window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((needed_size_from_last_frame.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); if (window->ScrollbarX && !window->ScrollbarY) window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar); window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); // Amend the partially filled window->DecorationXXX values. window->DecoOuterSizeX2 += window->ScrollbarSizes.x; window->DecoOuterSizeY2 += window->ScrollbarSizes.y; } // UPDATE RECTANGLES (1- THOSE NOT AFFECTED BY SCROLLING) // Update various regions. Variables they depend on should be set above in this function. // We set this up after processing the resize grip so that our rectangles doesn't lag by a frame. // Outer rectangle // Not affected by window border size. Used by: // - FindHoveredWindow() (w/ extra padding when border resize is enabled) // - Begin() initial clipping rect for drawing window background and borders. // - Begin() clipping whole child const ImRect host_rect = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip) ? parent_window->ClipRect : viewport_rect; const ImRect outer_rect = window->Rect(); const ImRect title_bar_rect = window->TitleBarRect(); window->OuterRectClipped = outer_rect; window->OuterRectClipped.ClipWith(host_rect); // Inner rectangle // Not affected by window border size. Used by: // - InnerClipRect // - ScrollToRectEx() // - NavUpdatePageUpPageDown() // - Scrollbar() window->InnerRect.Min.x = window->Pos.x + window->DecoOuterSizeX1; window->InnerRect.Min.y = window->Pos.y + window->DecoOuterSizeY1; window->InnerRect.Max.x = window->Pos.x + window->Size.x - window->DecoOuterSizeX2; window->InnerRect.Max.y = window->Pos.y + window->Size.y - window->DecoOuterSizeY2; // Inner clipping rectangle. // Will extend a little bit outside the normal work region. // This is to allow e.g. Selectable or CollapsingHeader or some separators to cover that space. // Force round operator last to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. // Note that if our window is collapsed we will end up with an inverted (~null) clipping rectangle which is the correct behavior. // Affected by window/frame border size. Used by: // - Begin() initial clip rect float top_border_size = (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize); window->InnerClipRect.Min.x = ImTrunc(0.5f + window->InnerRect.Min.x + ImMax(ImTrunc(window->WindowPadding.x * 0.5f), window->WindowBorderSize)); window->InnerClipRect.Min.y = ImTrunc(0.5f + window->InnerRect.Min.y + top_border_size); window->InnerClipRect.Max.x = ImTrunc(0.5f + window->InnerRect.Max.x - ImMax(ImTrunc(window->WindowPadding.x * 0.5f), window->WindowBorderSize)); window->InnerClipRect.Max.y = ImTrunc(0.5f + window->InnerRect.Max.y - window->WindowBorderSize); window->InnerClipRect.ClipWithFull(host_rect); // Default item width. Make it proportional to window size if window manually resizes if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize)) window->ItemWidthDefault = ImTrunc(window->Size.x * 0.65f); else window->ItemWidthDefault = ImTrunc(g.FontSize * 16.0f); // SCROLLING // Lock down maximum scrolling // The value of ScrollMax are ahead from ScrollbarX/ScrollbarY which is intentionally using InnerRect from previous rect in order to accommodate // for right/bottom aligned items without creating a scrollbar. window->ScrollMax.x = ImMax(0.0f, window->ContentSize.x + window->WindowPadding.x * 2.0f - window->InnerRect.GetWidth()); window->ScrollMax.y = ImMax(0.0f, window->ContentSize.y + window->WindowPadding.y * 2.0f - window->InnerRect.GetHeight()); // Apply scrolling window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window); window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); window->DecoInnerSizeX1 = window->DecoInnerSizeY1 = 0.0f; // DRAWING // Setup draw list and outer clipping rectangle IM_ASSERT(window->DrawList->CmdBuffer.Size == 1 && window->DrawList->CmdBuffer[0].ElemCount == 0); window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID); PushClipRect(host_rect.Min, host_rect.Max, false); // Child windows can render their decoration (bg color, border, scrollbars, etc.) within their parent to save a draw call (since 1.71) // When using overlapping child windows, this will break the assumption that child z-order is mapped to submission order. // FIXME: User code may rely on explicit sorting of overlapping child window and would need to disable this somehow. Please get in contact if you are affected (github #4493) { bool render_decorations_in_parent = false; if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip) { // - We test overlap with the previous child window only (testing all would end up being O(log N) not a good investment here) // - We disable this when the parent window has zero vertices, which is a common pattern leading to laying out multiple overlapping childs ImGuiWindow* previous_child = parent_window->DC.ChildWindows.Size >= 2 ? parent_window->DC.ChildWindows[parent_window->DC.ChildWindows.Size - 2] : NULL; bool previous_child_overlapping = previous_child ? previous_child->Rect().Overlaps(window->Rect()) : false; bool parent_is_empty = (parent_window->DrawList->VtxBuffer.Size == 0); if (window->DrawList->CmdBuffer.back().ElemCount == 0 && !parent_is_empty && !previous_child_overlapping) render_decorations_in_parent = true; } if (render_decorations_in_parent) window->DrawList = parent_window->DrawList; // Handle title bar, scrollbar, resize grips and resize borders const ImGuiWindow* window_to_highlight = g.NavWindowingTarget ? g.NavWindowingTarget : g.NavWindow; const bool title_bar_is_highlight = want_focus || (window_to_highlight && window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight); const bool handle_borders_and_resize_grips = true; // This exists to facilitate merge with 'docking' branch. RenderWindowDecorations(window, title_bar_rect, title_bar_is_highlight, handle_borders_and_resize_grips, resize_grip_count, resize_grip_col, resize_grip_draw_size); if (render_decorations_in_parent) window->DrawList = &window->DrawListInst; } // UPDATE RECTANGLES (2- THOSE AFFECTED BY SCROLLING) // Work rectangle. // Affected by window padding and border size. Used by: // - Columns() for right-most edge // - TreeNode(), CollapsingHeader() for right-most edge // - BeginTabBar() for right-most edge const bool allow_scrollbar_x = !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar); const bool allow_scrollbar_y = !(flags & ImGuiWindowFlags_NoScrollbar); const float work_rect_size_x = (window->ContentSizeExplicit.x != 0.0f ? window->ContentSizeExplicit.x : ImMax(allow_scrollbar_x ? window->ContentSize.x : 0.0f, window->Size.x - window->WindowPadding.x * 2.0f - (window->DecoOuterSizeX1 + window->DecoOuterSizeX2))); const float work_rect_size_y = (window->ContentSizeExplicit.y != 0.0f ? window->ContentSizeExplicit.y : ImMax(allow_scrollbar_y ? window->ContentSize.y : 0.0f, window->Size.y - window->WindowPadding.y * 2.0f - (window->DecoOuterSizeY1 + window->DecoOuterSizeY2))); window->WorkRect.Min.x = ImTrunc(window->InnerRect.Min.x - window->Scroll.x + ImMax(window->WindowPadding.x, window->WindowBorderSize)); window->WorkRect.Min.y = ImTrunc(window->InnerRect.Min.y - window->Scroll.y + ImMax(window->WindowPadding.y, window->WindowBorderSize)); window->WorkRect.Max.x = window->WorkRect.Min.x + work_rect_size_x; window->WorkRect.Max.y = window->WorkRect.Min.y + work_rect_size_y; window->ParentWorkRect = window->WorkRect; // [LEGACY] Content Region // FIXME-OBSOLETE: window->ContentRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it. // Unless explicit content size is specified by user, this currently represent the region leading to no scrolling. // Used by: // - Mouse wheel scrolling + many other things window->ContentRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x + window->DecoOuterSizeX1; window->ContentRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + window->DecoOuterSizeY1; window->ContentRegionRect.Max.x = window->ContentRegionRect.Min.x + (window->ContentSizeExplicit.x != 0.0f ? window->ContentSizeExplicit.x : (window->Size.x - window->WindowPadding.x * 2.0f - (window->DecoOuterSizeX1 + window->DecoOuterSizeX2))); window->ContentRegionRect.Max.y = window->ContentRegionRect.Min.y + (window->ContentSizeExplicit.y != 0.0f ? window->ContentSizeExplicit.y : (window->Size.y - window->WindowPadding.y * 2.0f - (window->DecoOuterSizeY1 + window->DecoOuterSizeY2))); // Setup drawing context // (NB: That term "drawing context / DC" lost its meaning a long time ago. Initially was meant to hold transient data only. Nowadays difference between window-> and window->DC-> is dubious.) window->DC.Indent.x = window->DecoOuterSizeX1 + window->WindowPadding.x - window->Scroll.x; window->DC.GroupOffset.x = 0.0f; window->DC.ColumnsOffset.x = 0.0f; // Record the loss of precision of CursorStartPos which can happen due to really large scrolling amount. // This is used by clipper to compensate and fix the most common use case of large scroll area. Easy and cheap, next best thing compared to switching everything to double or ImU64. double start_pos_highp_x = (double)window->Pos.x + window->WindowPadding.x - (double)window->Scroll.x + window->DecoOuterSizeX1 + window->DC.ColumnsOffset.x; double start_pos_highp_y = (double)window->Pos.y + window->WindowPadding.y - (double)window->Scroll.y + window->DecoOuterSizeY1; window->DC.CursorStartPos = ImVec2((float)start_pos_highp_x, (float)start_pos_highp_y); window->DC.CursorStartPosLossyness = ImVec2((float)(start_pos_highp_x - window->DC.CursorStartPos.x), (float)(start_pos_highp_y - window->DC.CursorStartPos.y)); window->DC.CursorPos = window->DC.CursorStartPos; window->DC.CursorPosPrevLine = window->DC.CursorPos; window->DC.CursorMaxPos = window->DC.CursorStartPos; window->DC.IdealMaxPos = window->DC.CursorStartPos; window->DC.CurrLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f); window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f; window->DC.IsSameLine = window->DC.IsSetPos = false; window->DC.NavLayerCurrent = ImGuiNavLayer_Main; window->DC.NavLayersActiveMask = window->DC.NavLayersActiveMaskNext; window->DC.NavLayersActiveMaskNext = 0x00; window->DC.NavIsScrollPushableX = true; window->DC.NavHideHighlightOneFrame = false; window->DC.NavWindowHasScrollY = (window->ScrollMax.y > 0.0f); window->DC.MenuBarAppending = false; window->DC.MenuColumns.Update(style.ItemSpacing.x, window_just_activated_by_user); window->DC.TreeDepth = 0; window->DC.TreeJumpToParentOnPopMask = 0x00; window->DC.ChildWindows.resize(0); window->DC.StateStorage = &window->StateStorage; window->DC.CurrentColumns = NULL; window->DC.LayoutType = ImGuiLayoutType_Vertical; window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical; window->DC.ItemWidth = window->ItemWidthDefault; window->DC.TextWrapPos = -1.0f; // disabled window->DC.ItemWidthStack.resize(0); window->DC.TextWrapPosStack.resize(0); if (window->AutoFitFramesX > 0) window->AutoFitFramesX--; if (window->AutoFitFramesY > 0) window->AutoFitFramesY--; // Apply focus (we need to call FocusWindow() AFTER setting DC.CursorStartPos so our initial navigation reference rectangle can start around there) // We ImGuiFocusRequestFlags_UnlessBelowModal to: // - Avoid focusing a window that is created outside of a modal. This will prevent active modal from being closed. // - Position window behind the modal that is not a begin-parent of this window. if (want_focus) FocusWindow(window, ImGuiFocusRequestFlags_UnlessBelowModal); if (want_focus && window == g.NavWindow) NavInitWindow(window, false); // <-- this is in the way for us to be able to defer and sort reappearing FocusWindow() calls // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) RenderWindowTitleBarContents(window, ImRect(title_bar_rect.Min.x + window->WindowBorderSize, title_bar_rect.Min.y, title_bar_rect.Max.x - window->WindowBorderSize, title_bar_rect.Max.y), name, p_open); // Clear hit test shape every frame window->HitTestHoleSize.x = window->HitTestHoleSize.y = 0; // Pressing CTRL+C while holding on a window copy its content to the clipboard // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope. // Maybe we can support CTRL+C on every element? /* //if (g.NavWindow == window && g.ActiveId == 0) if (g.ActiveId == window->MoveId) if (g.IO.KeyCtrl && IsKeyPressed(ImGuiKey_C)) LogToClipboard(); */ // We fill last item data based on Title Bar/Tab, in order for IsItemHovered() and IsItemActive() to be usable after Begin(). // This is useful to allow creating context menus on title bar only, etc. SetLastItemData(window->MoveId, g.CurrentItemFlags, IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0, title_bar_rect); // [DEBUG] #ifndef IMGUI_DISABLE_DEBUG_TOOLS if (g.DebugLocateId != 0 && (window->ID == g.DebugLocateId || window->MoveId == g.DebugLocateId)) DebugLocateItemResolveWithLastItem(); #endif // [Test Engine] Register title bar / tab with MoveId. #ifdef IMGUI_ENABLE_TEST_ENGINE if (!(window->Flags & ImGuiWindowFlags_NoTitleBar)) IMGUI_TEST_ENGINE_ITEM_ADD(g.LastItemData.ID, g.LastItemData.Rect, &g.LastItemData); #endif } else { // Append SetCurrentWindow(window); } PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true); // Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused) window->WriteAccessed = false; window->BeginCount++; g.NextWindowData.ClearFlags(); // Update visibility if (first_begin_of_the_frame) { if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_ChildMenu)) { // Child window can be out of sight and have "negative" clip windows. // Mark them as collapsed so commands are skipped earlier (we can't manually collapse them because they have no title bar). IM_ASSERT((flags & ImGuiWindowFlags_NoTitleBar) != 0); const bool nav_request = (flags & ImGuiWindowFlags_NavFlattened) && (g.NavAnyRequest && g.NavWindow && g.NavWindow->RootWindowForNav == window->RootWindowForNav); if (!g.LogEnabled && !nav_request) if (window->OuterRectClipped.Min.x >= window->OuterRectClipped.Max.x || window->OuterRectClipped.Min.y >= window->OuterRectClipped.Max.y) { if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) window->HiddenFramesCannotSkipItems = 1; else window->HiddenFramesCanSkipItems = 1; } // Hide along with parent or if parent is collapsed if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCanSkipItems > 0)) window->HiddenFramesCanSkipItems = 1; if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCannotSkipItems > 0)) window->HiddenFramesCannotSkipItems = 1; } // Don't render if style alpha is 0.0 at the time of Begin(). This is arbitrary and inconsistent but has been there for a long while (may remove at some point) if (style.Alpha <= 0.0f) window->HiddenFramesCanSkipItems = 1; // Update the Hidden flag bool hidden_regular = (window->HiddenFramesCanSkipItems > 0) || (window->HiddenFramesCannotSkipItems > 0); window->Hidden = hidden_regular || (window->HiddenFramesForRenderOnly > 0); // Disable inputs for requested number of frames if (window->DisableInputsFrames > 0) { window->DisableInputsFrames--; window->Flags |= ImGuiWindowFlags_NoInputs; } // Update the SkipItems flag, used to early out of all items functions (no layout required) bool skip_items = false; if (window->Collapsed || !window->Active || hidden_regular) if (window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && window->HiddenFramesCannotSkipItems <= 0) skip_items = true; window->SkipItems = skip_items; } // [DEBUG] io.ConfigDebugBeginReturnValue override return value to test Begin/End and BeginChild/EndChild behaviors. // (The implicit fallback window is NOT automatically ended allowing it to always be able to receive commands without crashing) #ifndef IMGUI_DISABLE_DEBUG_TOOLS if (!window->IsFallbackWindow) if ((g.IO.ConfigDebugBeginReturnValueOnce && window_just_created) || (g.IO.ConfigDebugBeginReturnValueLoop && g.DebugBeginReturnValueCullDepth == g.CurrentWindowStack.Size)) { if (window->AutoFitFramesX > 0) { window->AutoFitFramesX++; } if (window->AutoFitFramesY > 0) { window->AutoFitFramesY++; } return false; } #endif return !window->SkipItems; } void ImGui::End() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; // Error checking: verify that user hasn't called End() too many times! if (g.CurrentWindowStack.Size <= 1 && g.WithinFrameScopeWithImplicitWindow) { IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size > 1, "Calling End() too many times!"); return; } IM_ASSERT(g.CurrentWindowStack.Size > 0); // Error checking: verify that user doesn't directly call End() on a child window. if (window->Flags & ImGuiWindowFlags_ChildWindow) IM_ASSERT_USER_ERROR(g.WithinEndChild, "Must call EndChild() and not End()!"); // Close anything that is open if (window->DC.CurrentColumns) EndColumns(); PopClipRect(); // Inner window clip rectangle PopFocusScope(); // Stop logging if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging LogFinish(); if (window->DC.IsSetPos) ErrorCheckUsingSetCursorPosToExtendParentBoundaries(); // Pop from window stack g.LastItemData = g.CurrentWindowStack.back().ParentLastItemDataBackup; if (window->Flags & ImGuiWindowFlags_ChildMenu) g.BeginMenuDepth--; if (window->Flags & ImGuiWindowFlags_Popup) g.BeginPopupStack.pop_back(); g.CurrentWindowStack.back().StackSizesOnBegin.CompareWithContextState(&g); g.CurrentWindowStack.pop_back(); SetCurrentWindow(g.CurrentWindowStack.Size == 0 ? NULL : g.CurrentWindowStack.back().Window); } void ImGui::BringWindowToFocusFront(ImGuiWindow* window) { ImGuiContext& g = *GImGui; IM_ASSERT(window == window->RootWindow); const int cur_order = window->FocusOrder; IM_ASSERT(g.WindowsFocusOrder[cur_order] == window); if (g.WindowsFocusOrder.back() == window) return; const int new_order = g.WindowsFocusOrder.Size - 1; for (int n = cur_order; n < new_order; n++) { g.WindowsFocusOrder[n] = g.WindowsFocusOrder[n + 1]; g.WindowsFocusOrder[n]->FocusOrder--; IM_ASSERT(g.WindowsFocusOrder[n]->FocusOrder == n); } g.WindowsFocusOrder[new_order] = window; window->FocusOrder = (short)new_order; } void ImGui::BringWindowToDisplayFront(ImGuiWindow* window) { ImGuiContext& g = *GImGui; ImGuiWindow* current_front_window = g.Windows.back(); if (current_front_window == window || current_front_window->RootWindow == window) // Cheap early out (could be better) return; for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the top-most window if (g.Windows[i] == window) { memmove(&g.Windows[i], &g.Windows[i + 1], (size_t)(g.Windows.Size - i - 1) * sizeof(ImGuiWindow*)); g.Windows[g.Windows.Size - 1] = window; break; } } void ImGui::BringWindowToDisplayBack(ImGuiWindow* window) { ImGuiContext& g = *GImGui; if (g.Windows[0] == window) return; for (int i = 0; i < g.Windows.Size; i++) if (g.Windows[i] == window) { memmove(&g.Windows[1], &g.Windows[0], (size_t)i * sizeof(ImGuiWindow*)); g.Windows[0] = window; break; } } void ImGui::BringWindowToDisplayBehind(ImGuiWindow* window, ImGuiWindow* behind_window) { IM_ASSERT(window != NULL && behind_window != NULL); ImGuiContext& g = *GImGui; window = window->RootWindow; behind_window = behind_window->RootWindow; int pos_wnd = FindWindowDisplayIndex(window); int pos_beh = FindWindowDisplayIndex(behind_window); if (pos_wnd < pos_beh) { size_t copy_bytes = (pos_beh - pos_wnd - 1) * sizeof(ImGuiWindow*); memmove(&g.Windows.Data[pos_wnd], &g.Windows.Data[pos_wnd + 1], copy_bytes); g.Windows[pos_beh - 1] = window; } else { size_t copy_bytes = (pos_wnd - pos_beh) * sizeof(ImGuiWindow*); memmove(&g.Windows.Data[pos_beh + 1], &g.Windows.Data[pos_beh], copy_bytes); g.Windows[pos_beh] = window; } } int ImGui::FindWindowDisplayIndex(ImGuiWindow* window) { ImGuiContext& g = *GImGui; return g.Windows.index_from_ptr(g.Windows.find(window)); } // Moving window to front of display and set focus (which happens to be back of our sorted list) void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags) { ImGuiContext& g = *GImGui; // Modal check? if ((flags & ImGuiFocusRequestFlags_UnlessBelowModal) && (g.NavWindow != window)) // Early out in common case. if (ImGuiWindow* blocking_modal = FindBlockingModal(window)) { IMGUI_DEBUG_LOG_FOCUS("[focus] FocusWindow(\"%s\", UnlessBelowModal): prevented by \"%s\".\n", window ? window->Name : "", blocking_modal->Name); if (window && window == window->RootWindow && (window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0) BringWindowToDisplayBehind(window, blocking_modal); // Still bring to right below modal. return; } // Find last focused child (if any) and focus it instead. if ((flags & ImGuiFocusRequestFlags_RestoreFocusedChild) && window != NULL) window = NavRestoreLastChildNavWindow(window); // Apply focus if (g.NavWindow != window) { SetNavWindow(window); if (window && g.NavDisableMouseHover) g.NavMousePosDirty = true; g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId g.NavLayer = ImGuiNavLayer_Main; SetNavFocusScope(window ? window->NavRootFocusScopeId : 0); g.NavIdIsAlive = false; g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid; // Close popups if any ClosePopupsOverWindow(window, false); } // Move the root window to the top of the pile IM_ASSERT(window == NULL || window->RootWindow != NULL); ImGuiWindow* focus_front_window = window ? window->RootWindow : NULL; // NB: In docking branch this is window->RootWindowDockStop ImGuiWindow* display_front_window = window ? window->RootWindow : NULL; // Steal active widgets. Some of the cases it triggers includes: // - Focus a window while an InputText in another window is active, if focus happens before the old InputText can run. // - When using Nav to activate menu items (due to timing of activating on press->new window appears->losing ActiveId) if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != focus_front_window) if (!g.ActiveIdNoClearOnFocusLoss) ClearActiveID(); // Passing NULL allow to disable keyboard focus if (!window) return; // Bring to front BringWindowToFocusFront(focus_front_window); if (((window->Flags | display_front_window->Flags) & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0) BringWindowToDisplayFront(display_front_window); } void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window, ImGuiViewport* filter_viewport, ImGuiFocusRequestFlags flags) { ImGuiContext& g = *GImGui; IM_UNUSED(filter_viewport); // Unused in master branch. int start_idx = g.WindowsFocusOrder.Size - 1; if (under_this_window != NULL) { // Aim at root window behind us, if we are in a child window that's our own root (see #4640) int offset = -1; while (under_this_window->Flags & ImGuiWindowFlags_ChildWindow) { under_this_window = under_this_window->ParentWindow; offset = 0; } start_idx = FindWindowFocusIndex(under_this_window) + offset; } for (int i = start_idx; i >= 0; i--) { // We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user. ImGuiWindow* window = g.WindowsFocusOrder[i]; if (window == ignore_window || !window->WasActive) continue; if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) { FocusWindow(window, flags); return; } } FocusWindow(NULL, flags); } // Important: this alone doesn't alter current ImDrawList state. This is called by PushFont/PopFont only. void ImGui::SetCurrentFont(ImFont* font) { ImGuiContext& g = *GImGui; IM_ASSERT(font && font->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? IM_ASSERT(font->Scale > 0.0f); g.Font = font; g.FontBaseSize = ImMax(1.0f, g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale); g.FontSize = g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f; ImFontAtlas* atlas = g.Font->ContainerAtlas; g.DrawListSharedData.TexUvWhitePixel = atlas->TexUvWhitePixel; g.DrawListSharedData.TexUvLines = atlas->TexUvLines; g.DrawListSharedData.Font = g.Font; g.DrawListSharedData.FontSize = g.FontSize; } void ImGui::PushFont(ImFont* font) { ImGuiContext& g = *GImGui; if (!font) font = GetDefaultFont(); SetCurrentFont(font); g.FontStack.push_back(font); g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID); } void ImGui::PopFont() { ImGuiContext& g = *GImGui; g.CurrentWindow->DrawList->PopTextureID(); g.FontStack.pop_back(); SetCurrentFont(g.FontStack.empty() ? GetDefaultFont() : g.FontStack.back()); } void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled) { ImGuiContext& g = *GImGui; ImGuiItemFlags item_flags = g.CurrentItemFlags; IM_ASSERT(item_flags == g.ItemFlagsStack.back()); if (enabled) item_flags |= option; else item_flags &= ~option; g.CurrentItemFlags = item_flags; g.ItemFlagsStack.push_back(item_flags); } void ImGui::PopItemFlag() { ImGuiContext& g = *GImGui; IM_ASSERT(g.ItemFlagsStack.Size > 1); // Too many calls to PopItemFlag() - we always leave a 0 at the bottom of the stack. g.ItemFlagsStack.pop_back(); g.CurrentItemFlags = g.ItemFlagsStack.back(); } // BeginDisabled()/EndDisabled() // - Those can be nested but it cannot be used to enable an already disabled section (a single BeginDisabled(true) in the stack is enough to keep everything disabled) // - Visually this is currently altering alpha, but it is expected that in a future styling system this would work differently. // - Feedback welcome at https://github.com/ocornut/imgui/issues/211 // - BeginDisabled(false) essentially does nothing useful but is provided to facilitate use of boolean expressions. If you can avoid calling BeginDisabled(False)/EndDisabled() best to avoid it. // - Optimized shortcuts instead of PushStyleVar() + PushItemFlag() void ImGui::BeginDisabled(bool disabled) { ImGuiContext& g = *GImGui; bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0; if (!was_disabled && disabled) { g.DisabledAlphaBackup = g.Style.Alpha; g.Style.Alpha *= g.Style.DisabledAlpha; // PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * g.Style.DisabledAlpha); } if (was_disabled || disabled) g.CurrentItemFlags |= ImGuiItemFlags_Disabled; g.ItemFlagsStack.push_back(g.CurrentItemFlags); g.DisabledStackSize++; } void ImGui::EndDisabled() { ImGuiContext& g = *GImGui; IM_ASSERT(g.DisabledStackSize > 0); g.DisabledStackSize--; bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0; //PopItemFlag(); g.ItemFlagsStack.pop_back(); g.CurrentItemFlags = g.ItemFlagsStack.back(); if (was_disabled && (g.CurrentItemFlags & ImGuiItemFlags_Disabled) == 0) g.Style.Alpha = g.DisabledAlphaBackup; //PopStyleVar(); } void ImGui::PushTabStop(bool tab_stop) { PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop); } void ImGui::PopTabStop() { PopItemFlag(); } void ImGui::PushButtonRepeat(bool repeat) { PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat); } void ImGui::PopButtonRepeat() { PopItemFlag(); } void ImGui::PushTextWrapPos(float wrap_pos_x) { ImGuiWindow* window = GetCurrentWindow(); window->DC.TextWrapPosStack.push_back(window->DC.TextWrapPos); window->DC.TextWrapPos = wrap_pos_x; } void ImGui::PopTextWrapPos() { ImGuiWindow* window = GetCurrentWindow(); window->DC.TextWrapPos = window->DC.TextWrapPosStack.back(); window->DC.TextWrapPosStack.pop_back(); } static ImGuiWindow* GetCombinedRootWindow(ImGuiWindow* window, bool popup_hierarchy) { ImGuiWindow* last_window = NULL; while (last_window != window) { last_window = window; window = window->RootWindow; if (popup_hierarchy) window = window->RootWindowPopupTree; } return window; } bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent, bool popup_hierarchy) { ImGuiWindow* window_root = GetCombinedRootWindow(window, popup_hierarchy); if (window_root == potential_parent) return true; while (window != NULL) { if (window == potential_parent) return true; if (window == window_root) // end of chain return false; window = window->ParentWindow; } return false; } bool ImGui::IsWindowWithinBeginStackOf(ImGuiWindow* window, ImGuiWindow* potential_parent) { if (window->RootWindow == potential_parent) return true; while (window != NULL) { if (window == potential_parent) return true; window = window->ParentWindowInBeginStack; } return false; } bool ImGui::IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below) { ImGuiContext& g = *GImGui; // It would be saner to ensure that display layer is always reflected in the g.Windows[] order, which would likely requires altering all manipulations of that array const int display_layer_delta = GetWindowDisplayLayer(potential_above) - GetWindowDisplayLayer(potential_below); if (display_layer_delta != 0) return display_layer_delta > 0; for (int i = g.Windows.Size - 1; i >= 0; i--) { ImGuiWindow* candidate_window = g.Windows[i]; if (candidate_window == potential_above) return true; if (candidate_window == potential_below) return false; } return false; } // Is current window hovered and hoverable (e.g. not blocked by a popup/modal)? See ImGuiHoveredFlags_ for options. // IMPORTANT: If you are trying to check whether your mouse should be dispatched to Dear ImGui or to your underlying app, // you should not use this function! Use the 'io.WantCaptureMouse' boolean for that! // Refer to FAQ entry "How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application?" for details. bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) { IM_ASSERT((flags & ~ImGuiHoveredFlags_AllowedMaskForIsWindowHovered) == 0 && "Invalid flags for IsWindowHovered()!"); ImGuiContext& g = *GImGui; ImGuiWindow* ref_window = g.HoveredWindow; ImGuiWindow* cur_window = g.CurrentWindow; if (ref_window == NULL) return false; if ((flags & ImGuiHoveredFlags_AnyWindow) == 0) { IM_ASSERT(cur_window); // Not inside a Begin()/End() const bool popup_hierarchy = (flags & ImGuiHoveredFlags_NoPopupHierarchy) == 0; if (flags & ImGuiHoveredFlags_RootWindow) cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy); bool result; if (flags & ImGuiHoveredFlags_ChildWindows) result = IsWindowChildOf(ref_window, cur_window, popup_hierarchy); else result = (ref_window == cur_window); if (!result) return false; } if (!IsWindowContentHoverable(ref_window, flags)) return false; if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) if (g.ActiveId != 0 && !g.ActiveIdAllowOverlap && g.ActiveId != ref_window->MoveId) return false; // When changing hovered window we requires a bit of stationary delay before activating hover timer. // FIXME: We don't support delay other than stationary one for now, other delay would need a way // to fullfill the possibility that multiple IsWindowHovered() with varying flag could return true // for different windows of the hierarchy. Possibly need a Hash(Current+Flags) ==> (Timer) cache. // We can implement this for _Stationary because the data is linked to HoveredWindow rather than CurrentWindow. if (flags & ImGuiHoveredFlags_ForTooltip) flags = ApplyHoverFlagsForTooltip(flags, g.Style.HoverFlagsForTooltipMouse); if ((flags & ImGuiHoveredFlags_Stationary) != 0 && g.HoverWindowUnlockedStationaryId != ref_window->ID) return false; return true; } bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* ref_window = g.NavWindow; ImGuiWindow* cur_window = g.CurrentWindow; if (ref_window == NULL) return false; if (flags & ImGuiFocusedFlags_AnyWindow) return true; IM_ASSERT(cur_window); // Not inside a Begin()/End() const bool popup_hierarchy = (flags & ImGuiFocusedFlags_NoPopupHierarchy) == 0; if (flags & ImGuiHoveredFlags_RootWindow) cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy); if (flags & ImGuiHoveredFlags_ChildWindows) return IsWindowChildOf(ref_window, cur_window, popup_hierarchy); else return (ref_window == cur_window); } // Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext) // Note that NoNavFocus makes the window not reachable with CTRL+TAB but it can still be focused with mouse or programmatically. // If you want a window to never be focused, you may use the e.g. NoInputs flag. bool ImGui::IsWindowNavFocusable(ImGuiWindow* window) { return window->WasActive && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus); } float ImGui::GetWindowWidth() { ImGuiWindow* window = GImGui->CurrentWindow; return window->Size.x; } float ImGui::GetWindowHeight() { ImGuiWindow* window = GImGui->CurrentWindow; return window->Size.y; } ImVec2 ImGui::GetWindowPos() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; return window->Pos; } void ImGui::SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond) { // Test condition (NB: bit 0 is always true) and clear flags for next time if (cond && (window->SetWindowPosAllowFlags & cond) == 0) return; IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); window->SetWindowPosVal = ImVec2(FLT_MAX, FLT_MAX); // Set const ImVec2 old_pos = window->Pos; window->Pos = ImTrunc(pos); ImVec2 offset = window->Pos - old_pos; if (offset.x == 0.0f && offset.y == 0.0f) return; MarkIniSettingsDirty(window); window->DC.CursorPos += offset; // As we happen to move the window while it is being appended to (which is a bad idea - will smear) let's at least offset the cursor window->DC.CursorMaxPos += offset; // And more importantly we need to offset CursorMaxPos/CursorStartPos this so ContentSize calculation doesn't get affected. window->DC.IdealMaxPos += offset; window->DC.CursorStartPos += offset; } void ImGui::SetWindowPos(const ImVec2& pos, ImGuiCond cond) { ImGuiWindow* window = GetCurrentWindowRead(); SetWindowPos(window, pos, cond); } void ImGui::SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond) { if (ImGuiWindow* window = FindWindowByName(name)) SetWindowPos(window, pos, cond); } ImVec2 ImGui::GetWindowSize() { ImGuiWindow* window = GetCurrentWindowRead(); return window->Size; } void ImGui::SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond) { // Test condition (NB: bit 0 is always true) and clear flags for next time if (cond && (window->SetWindowSizeAllowFlags & cond) == 0) return; IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. window->SetWindowSizeAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); // Enable auto-fit (not done in BeginChild() path unless appearing or combined with ImGuiChildFlags_AlwaysAutoResize) if ((window->Flags & ImGuiWindowFlags_ChildWindow) == 0 || window->Appearing || (window->ChildFlags & ImGuiChildFlags_AlwaysAutoResize) != 0) window->AutoFitFramesX = (size.x <= 0.0f) ? 2 : 0; if ((window->Flags & ImGuiWindowFlags_ChildWindow) == 0 || window->Appearing || (window->ChildFlags & ImGuiChildFlags_AlwaysAutoResize) != 0) window->AutoFitFramesY = (size.y <= 0.0f) ? 2 : 0; // Set ImVec2 old_size = window->SizeFull; if (size.x <= 0.0f) window->AutoFitOnlyGrows = false; else window->SizeFull.x = IM_TRUNC(size.x); if (size.y <= 0.0f) window->AutoFitOnlyGrows = false; else window->SizeFull.y = IM_TRUNC(size.y); if (old_size.x != window->SizeFull.x || old_size.y != window->SizeFull.y) MarkIniSettingsDirty(window); } void ImGui::SetWindowSize(const ImVec2& size, ImGuiCond cond) { SetWindowSize(GImGui->CurrentWindow, size, cond); } void ImGui::SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond) { if (ImGuiWindow* window = FindWindowByName(name)) SetWindowSize(window, size, cond); } void ImGui::SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond) { // Test condition (NB: bit 0 is always true) and clear flags for next time if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0) return; window->SetWindowCollapsedAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); // Set window->Collapsed = collapsed; } void ImGui::SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size) { IM_ASSERT(window->HitTestHoleSize.x == 0); // We don't support multiple holes/hit test filters window->HitTestHoleSize = ImVec2ih(size); window->HitTestHoleOffset = ImVec2ih(pos - window->Pos); } void ImGui::SetWindowHiddenAndSkipItemsForCurrentFrame(ImGuiWindow* window) { window->Hidden = window->SkipItems = true; window->HiddenFramesCanSkipItems = 1; } void ImGui::SetWindowCollapsed(bool collapsed, ImGuiCond cond) { SetWindowCollapsed(GImGui->CurrentWindow, collapsed, cond); } bool ImGui::IsWindowCollapsed() { ImGuiWindow* window = GetCurrentWindowRead(); return window->Collapsed; } bool ImGui::IsWindowAppearing() { ImGuiWindow* window = GetCurrentWindowRead(); return window->Appearing; } void ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond) { if (ImGuiWindow* window = FindWindowByName(name)) SetWindowCollapsed(window, collapsed, cond); } void ImGui::SetWindowFocus() { FocusWindow(GImGui->CurrentWindow); } void ImGui::SetWindowFocus(const char* name) { if (name) { if (ImGuiWindow* window = FindWindowByName(name)) FocusWindow(window); } else { FocusWindow(NULL); } } void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pivot) { ImGuiContext& g = *GImGui; IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasPos; g.NextWindowData.PosVal = pos; g.NextWindowData.PosPivotVal = pivot; g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always; } void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond) { ImGuiContext& g = *GImGui; IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSize; g.NextWindowData.SizeVal = size; g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always; } // For each axis: // - Use 0.0f as min or FLT_MAX as max if you don't want limits, e.g. size_min = (500.0f, 0.0f), size_max = (FLT_MAX, FLT_MAX) sets a minimum width. // - Use -1 for both min and max of same axis to preserve current size which itself is a constraint. // - See "Demo->Examples->Constrained-resizing window" for examples. void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback, void* custom_callback_user_data) { ImGuiContext& g = *GImGui; g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint; g.NextWindowData.SizeConstraintRect = ImRect(size_min, size_max); g.NextWindowData.SizeCallback = custom_callback; g.NextWindowData.SizeCallbackUserData = custom_callback_user_data; } // Content size = inner scrollable rectangle, padded with WindowPadding. // SetNextWindowContentSize(ImVec2(100,100) + ImGuiWindowFlags_AlwaysAutoResize will always allow submitting a 100x100 item. void ImGui::SetNextWindowContentSize(const ImVec2& size) { ImGuiContext& g = *GImGui; g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasContentSize; g.NextWindowData.ContentSizeVal = ImTrunc(size); } void ImGui::SetNextWindowScroll(const ImVec2& scroll) { ImGuiContext& g = *GImGui; g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasScroll; g.NextWindowData.ScrollVal = scroll; } void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond) { ImGuiContext& g = *GImGui; IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasCollapsed; g.NextWindowData.CollapsedVal = collapsed; g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always; } void ImGui::SetNextWindowFocus() { ImGuiContext& g = *GImGui; g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasFocus; } void ImGui::SetNextWindowBgAlpha(float alpha) { ImGuiContext& g = *GImGui; g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasBgAlpha; g.NextWindowData.BgAlphaVal = alpha; } ImDrawList* ImGui::GetWindowDrawList() { ImGuiWindow* window = GetCurrentWindow(); return window->DrawList; } ImFont* ImGui::GetFont() { return GImGui->Font; } float ImGui::GetFontSize() { return GImGui->FontSize; } ImVec2 ImGui::GetFontTexUvWhitePixel() { return GImGui->DrawListSharedData.TexUvWhitePixel; } void ImGui::SetWindowFontScale(float scale) { IM_ASSERT(scale > 0.0f); ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); window->FontWindowScale = scale; g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize(); } void ImGui::PushFocusScope(ImGuiID id) { ImGuiContext& g = *GImGui; ImGuiFocusScopeData data; data.ID = id; data.WindowID = g.CurrentWindow->ID; g.FocusScopeStack.push_back(data); g.CurrentFocusScopeId = id; } void ImGui::PopFocusScope() { ImGuiContext& g = *GImGui; if (g.FocusScopeStack.Size == 0) { IM_ASSERT_USER_ERROR(g.FocusScopeStack.Size > 0, "Calling PopFocusScope() too many times!"); return; } g.FocusScopeStack.pop_back(); g.CurrentFocusScopeId = g.FocusScopeStack.Size ? g.FocusScopeStack.back().ID : 0; } void ImGui::SetNavFocusScope(ImGuiID focus_scope_id) { ImGuiContext& g = *GImGui; g.NavFocusScopeId = focus_scope_id; g.NavFocusRoute.resize(0); // Invalidate if (focus_scope_id == 0) return; IM_ASSERT(g.NavWindow != NULL); // Store current path (in reverse order) if (focus_scope_id == g.CurrentFocusScopeId) { // Top of focus stack contains local focus scopes inside current window for (int n = g.FocusScopeStack.Size - 1; n >= 0 && g.FocusScopeStack.Data[n].WindowID == g.CurrentWindow->ID; n--) g.NavFocusRoute.push_back(g.FocusScopeStack.Data[n]); } else if (focus_scope_id == g.NavWindow->NavRootFocusScopeId) g.NavFocusRoute.push_back({ focus_scope_id, g.NavWindow->ID }); else return; // Then follow on manually set ParentWindowForFocusRoute field (#6798) for (ImGuiWindow* window = g.NavWindow->ParentWindowForFocusRoute; window != NULL; window = window->ParentWindowForFocusRoute) g.NavFocusRoute.push_back({ window->NavRootFocusScopeId, window->ID }); IM_ASSERT(g.NavFocusRoute.Size < 100); // Maximum depth is technically 251 as per CalcRoutingScore(): 254 - 3 } // Focus = move navigation cursor, set scrolling, set focus window. void ImGui::FocusItem() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; IMGUI_DEBUG_LOG_FOCUS("FocusItem(0x%08x) in window \"%s\"\n", g.LastItemData.ID, window->Name); if (g.DragDropActive || g.MovingWindow != NULL) // FIXME: Opt-in flags for this? { IMGUI_DEBUG_LOG_FOCUS("FocusItem() ignored while DragDropActive!\n"); return; } ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_FocusApi | ImGuiNavMoveFlags_NoSetNavHighlight | ImGuiNavMoveFlags_NoSelect; ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY; SetNavWindow(window); NavMoveRequestSubmit(ImGuiDir_None, ImGuiDir_Up, move_flags, scroll_flags); NavMoveRequestResolveWithLastItem(&g.NavMoveResultLocal); } void ImGui::ActivateItemByID(ImGuiID id) { ImGuiContext& g = *GImGui; g.NavNextActivateId = id; g.NavNextActivateFlags = ImGuiActivateFlags_None; } // Note: this will likely be called ActivateItem() once we rework our Focus/Activation system! // But ActivateItem() should function without altering scroll/focus? void ImGui::SetKeyboardFocusHere(int offset) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(offset >= -1); // -1 is allowed but not below IMGUI_DEBUG_LOG_FOCUS("SetKeyboardFocusHere(%d) in window \"%s\"\n", offset, window->Name); // It makes sense in the vast majority of cases to never interrupt a drag and drop. // When we refactor this function into ActivateItem() we may want to make this an option. // MovingWindow is protected from most user inputs using SetActiveIdUsingNavAndKeys(), but // is also automatically dropped in the event g.ActiveId is stolen. if (g.DragDropActive || g.MovingWindow != NULL) { IMGUI_DEBUG_LOG_FOCUS("SetKeyboardFocusHere() ignored while DragDropActive!\n"); return; } SetNavWindow(window); ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_Activate | ImGuiNavMoveFlags_FocusApi | ImGuiNavMoveFlags_NoSetNavHighlight; ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY; NavMoveRequestSubmit(ImGuiDir_None, offset < 0 ? ImGuiDir_Up : ImGuiDir_Down, move_flags, scroll_flags); // FIXME-NAV: Once we refactor tabbing, add LegacyApi flag to not activate non-inputable. if (offset == -1) { NavMoveRequestResolveWithLastItem(&g.NavMoveResultLocal); } else { g.NavTabbingDir = 1; g.NavTabbingCounter = offset + 1; } } void ImGui::SetItemDefaultFocus() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (!window->Appearing) return; if (g.NavWindow != window->RootWindowForNav || (!g.NavInitRequest && g.NavInitResult.ID == 0) || g.NavLayer != window->DC.NavLayerCurrent) return; g.NavInitRequest = false; NavApplyItemToResult(&g.NavInitResult); NavUpdateAnyRequestFlag(); // Scroll could be done in NavInitRequestApplyResult() via an opt-in flag (we however don't want regular init requests to scroll) if (!window->ClipRect.Contains(g.LastItemData.Rect)) ScrollToRectEx(window, g.LastItemData.Rect, ImGuiScrollFlags_None); } void ImGui::SetStateStorage(ImGuiStorage* tree) { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.StateStorage = tree ? tree : &window->StateStorage; } ImGuiStorage* ImGui::GetStateStorage() { ImGuiWindow* window = GImGui->CurrentWindow; return window->DC.StateStorage; } void ImGui::PushID(const char* str_id) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiID id = window->GetID(str_id); window->IDStack.push_back(id); } void ImGui::PushID(const char* str_id_begin, const char* str_id_end) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiID id = window->GetID(str_id_begin, str_id_end); window->IDStack.push_back(id); } void ImGui::PushID(const void* ptr_id) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiID id = window->GetID(ptr_id); window->IDStack.push_back(id); } void ImGui::PushID(int int_id) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiID id = window->GetID(int_id); window->IDStack.push_back(id); } // Push a given id value ignoring the ID stack as a seed. void ImGui::PushOverrideID(ImGuiID id) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (g.DebugHookIdInfo == id) DebugHookIdInfo(id, ImGuiDataType_ID, NULL, NULL); window->IDStack.push_back(id); } // Helper to avoid a common series of PushOverrideID -> GetID() -> PopID() call // (note that when using this pattern, ID Stack Tool will tend to not display the intermediate stack level. // for that to work we would need to do PushOverrideID() -> ItemAdd() -> PopID() which would alter widget code a little more) ImGuiID ImGui::GetIDWithSeed(const char* str, const char* str_end, ImGuiID seed) { ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed); ImGuiContext& g = *GImGui; if (g.DebugHookIdInfo == id) DebugHookIdInfo(id, ImGuiDataType_String, str, str_end); return id; } ImGuiID ImGui::GetIDWithSeed(int n, ImGuiID seed) { ImGuiID id = ImHashData(&n, sizeof(n), seed); ImGuiContext& g = *GImGui; if (g.DebugHookIdInfo == id) DebugHookIdInfo(id, ImGuiDataType_S32, (void*)(intptr_t)n, NULL); return id; } void ImGui::PopID() { ImGuiWindow* window = GImGui->CurrentWindow; IM_ASSERT(window->IDStack.Size > 1); // Too many PopID(), or could be popping in a wrong/different window? window->IDStack.pop_back(); } ImGuiID ImGui::GetID(const char* str_id) { ImGuiWindow* window = GImGui->CurrentWindow; return window->GetID(str_id); } ImGuiID ImGui::GetID(const char* str_id_begin, const char* str_id_end) { ImGuiWindow* window = GImGui->CurrentWindow; return window->GetID(str_id_begin, str_id_end); } ImGuiID ImGui::GetID(const void* ptr_id) { ImGuiWindow* window = GImGui->CurrentWindow; return window->GetID(ptr_id); } bool ImGui::IsRectVisible(const ImVec2& size) { ImGuiWindow* window = GImGui->CurrentWindow; return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size)); } bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max) { ImGuiWindow* window = GImGui->CurrentWindow; return window->ClipRect.Overlaps(ImRect(rect_min, rect_max)); } //----------------------------------------------------------------------------- // [SECTION] INPUTS //----------------------------------------------------------------------------- // - GetKeyData() [Internal] // - GetKeyIndex() [Internal] // - GetKeyName() // - GetKeyChordName() [Internal] // - CalcTypematicRepeatAmount() [Internal] // - GetTypematicRepeatRate() [Internal] // - GetKeyPressedAmount() [Internal] // - GetKeyMagnitude2d() [Internal] //----------------------------------------------------------------------------- // - UpdateKeyRoutingTable() [Internal] // - GetRoutingIdFromOwnerId() [Internal] // - GetShortcutRoutingData() [Internal] // - CalcRoutingScore() [Internal] // - SetShortcutRouting() [Internal] // - TestShortcutRouting() [Internal] //----------------------------------------------------------------------------- // - IsKeyDown() // - IsKeyPressed() // - IsKeyReleased() //----------------------------------------------------------------------------- // - IsMouseDown() // - IsMouseClicked() // - IsMouseReleased() // - IsMouseDoubleClicked() // - GetMouseClickedCount() // - IsMouseHoveringRect() [Internal] // - IsMouseDragPastThreshold() [Internal] // - IsMouseDragging() // - GetMousePos() // - SetMousePos() [Internal] // - GetMousePosOnOpeningCurrentPopup() // - IsMousePosValid() // - IsAnyMouseDown() // - GetMouseDragDelta() // - ResetMouseDragDelta() // - GetMouseCursor() // - SetMouseCursor() //----------------------------------------------------------------------------- // - UpdateAliasKey() // - GetMergedModsFromKeys() // - UpdateKeyboardInputs() // - UpdateMouseInputs() //----------------------------------------------------------------------------- // - LockWheelingWindow [Internal] // - FindBestWheelingWindow [Internal] // - UpdateMouseWheel() [Internal] //----------------------------------------------------------------------------- // - SetNextFrameWantCaptureKeyboard() // - SetNextFrameWantCaptureMouse() //----------------------------------------------------------------------------- // - GetInputSourceName() [Internal] // - DebugPrintInputEvent() [Internal] // - UpdateInputEvents() [Internal] //----------------------------------------------------------------------------- // - GetKeyOwner() [Internal] // - TestKeyOwner() [Internal] // - SetKeyOwner() [Internal] // - SetItemKeyOwner() [Internal] // - Shortcut() [Internal] //----------------------------------------------------------------------------- ImGuiKeyChord ImGui::FixupKeyChord(ImGuiContext* ctx, ImGuiKeyChord key_chord) { // Convert ImGuiMod_Shortcut and add ImGuiMod_XXXX when a corresponding ImGuiKey_LeftXXX/ImGuiKey_RightXXX is specified. ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); if (IsModKey(key)) { if (key == ImGuiKey_LeftCtrl || key == ImGuiKey_RightCtrl) key_chord |= ImGuiMod_Ctrl; if (key == ImGuiKey_LeftShift || key == ImGuiKey_RightShift) key_chord |= ImGuiMod_Shift; if (key == ImGuiKey_LeftAlt || key == ImGuiKey_RightAlt) key_chord |= ImGuiMod_Alt; if (key == ImGuiKey_LeftSuper || key == ImGuiKey_RightSuper) key_chord |= ImGuiMod_Super; } if (key_chord & ImGuiMod_Shortcut) return (key_chord & ~ImGuiMod_Shortcut) | (ctx->IO.ConfigMacOSXBehaviors ? ImGuiMod_Super : ImGuiMod_Ctrl); return key_chord; } ImGuiKeyData* ImGui::GetKeyData(ImGuiContext* ctx, ImGuiKey key) { ImGuiContext& g = *ctx; // Special storage location for mods if (key & ImGuiMod_Mask_) key = ConvertSingleModFlagToKey(ctx, key); #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO IM_ASSERT(key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_NamedKey_END); if (IsLegacyKey(key) && g.IO.KeyMap[key] != -1) key = (ImGuiKey)g.IO.KeyMap[key]; // Remap native->imgui or imgui->native #else IM_ASSERT(IsNamedKey(key) && "Support for user key indices was dropped in favor of ImGuiKey. Please update backend & user code."); #endif return &g.IO.KeysData[key - ImGuiKey_KeysData_OFFSET]; } #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO ImGuiKey ImGui::GetKeyIndex(ImGuiKey key) { ImGuiContext& g = *GImGui; IM_ASSERT(IsNamedKey(key)); const ImGuiKeyData* key_data = GetKeyData(key); return (ImGuiKey)(key_data - g.IO.KeysData); } #endif // Those names a provided for debugging purpose and are not meant to be saved persistently not compared. static const char* const GKeyNames[] = { "Tab", "LeftArrow", "RightArrow", "UpArrow", "DownArrow", "PageUp", "PageDown", "Home", "End", "Insert", "Delete", "Backspace", "Space", "Enter", "Escape", "LeftCtrl", "LeftShift", "LeftAlt", "LeftSuper", "RightCtrl", "RightShift", "RightAlt", "RightSuper", "Menu", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24", "Apostrophe", "Comma", "Minus", "Period", "Slash", "Semicolon", "Equal", "LeftBracket", "Backslash", "RightBracket", "GraveAccent", "CapsLock", "ScrollLock", "NumLock", "PrintScreen", "Pause", "Keypad0", "Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", "Keypad6", "Keypad7", "Keypad8", "Keypad9", "KeypadDecimal", "KeypadDivide", "KeypadMultiply", "KeypadSubtract", "KeypadAdd", "KeypadEnter", "KeypadEqual", "AppBack", "AppForward", "GamepadStart", "GamepadBack", "GamepadFaceLeft", "GamepadFaceRight", "GamepadFaceUp", "GamepadFaceDown", "GamepadDpadLeft", "GamepadDpadRight", "GamepadDpadUp", "GamepadDpadDown", "GamepadL1", "GamepadR1", "GamepadL2", "GamepadR2", "GamepadL3", "GamepadR3", "GamepadLStickLeft", "GamepadLStickRight", "GamepadLStickUp", "GamepadLStickDown", "GamepadRStickLeft", "GamepadRStickRight", "GamepadRStickUp", "GamepadRStickDown", "MouseLeft", "MouseRight", "MouseMiddle", "MouseX1", "MouseX2", "MouseWheelX", "MouseWheelY", "ModCtrl", "ModShift", "ModAlt", "ModSuper", // ReservedForModXXX are showing the ModXXX names. }; IM_STATIC_ASSERT(ImGuiKey_NamedKey_COUNT == IM_ARRAYSIZE(GKeyNames)); const char* ImGui::GetKeyName(ImGuiKey key) { ImGuiContext& g = *GImGui; #ifdef IMGUI_DISABLE_OBSOLETE_KEYIO IM_ASSERT((IsNamedKeyOrModKey(key) || key == ImGuiKey_None) && "Support for user key indices was dropped in favor of ImGuiKey. Please update backend and user code."); #else if (IsLegacyKey(key)) { if (g.IO.KeyMap[key] == -1) return "N/A"; IM_ASSERT(IsNamedKey((ImGuiKey)g.IO.KeyMap[key])); key = (ImGuiKey)g.IO.KeyMap[key]; } #endif if (key == ImGuiKey_None) return "None"; if (key & ImGuiMod_Mask_) key = ConvertSingleModFlagToKey(&g, key); if (!IsNamedKey(key)) return "Unknown"; return GKeyNames[key - ImGuiKey_NamedKey_BEGIN]; } // ImGuiMod_Shortcut is translated to either Ctrl or Super. const char* ImGui::GetKeyChordName(ImGuiKeyChord key_chord) { ImGuiContext& g = *GImGui; key_chord = FixupKeyChord(&g, key_chord); ImFormatString(g.TempKeychordName, IM_ARRAYSIZE(g.TempKeychordName), "%s%s%s%s%s", (key_chord & ImGuiMod_Ctrl) ? "Ctrl+" : "", (key_chord & ImGuiMod_Shift) ? "Shift+" : "", (key_chord & ImGuiMod_Alt) ? "Alt+" : "", (key_chord & ImGuiMod_Super) ? (g.IO.ConfigMacOSXBehaviors ? "Cmd+" : "Super+") : "", GetKeyName((ImGuiKey)(key_chord & ~ImGuiMod_Mask_))); return g.TempKeychordName; } // t0 = previous time (e.g.: g.Time - g.IO.DeltaTime) // t1 = current time (e.g.: g.Time) // An event is triggered at: // t = 0.0f t = repeat_delay, t = repeat_delay + repeat_rate*N int ImGui::CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate) { if (t1 == 0.0f) return 1; if (t0 >= t1) return 0; if (repeat_rate <= 0.0f) return (t0 < repeat_delay) && (t1 >= repeat_delay); const int count_t0 = (t0 < repeat_delay) ? -1 : (int)((t0 - repeat_delay) / repeat_rate); const int count_t1 = (t1 < repeat_delay) ? -1 : (int)((t1 - repeat_delay) / repeat_rate); const int count = count_t1 - count_t0; return count; } void ImGui::GetTypematicRepeatRate(ImGuiInputFlags flags, float* repeat_delay, float* repeat_rate) { ImGuiContext& g = *GImGui; switch (flags & ImGuiInputFlags_RepeatRateMask_) { case ImGuiInputFlags_RepeatRateNavMove: *repeat_delay = g.IO.KeyRepeatDelay * 0.72f; *repeat_rate = g.IO.KeyRepeatRate * 0.80f; return; case ImGuiInputFlags_RepeatRateNavTweak: *repeat_delay = g.IO.KeyRepeatDelay * 0.72f; *repeat_rate = g.IO.KeyRepeatRate * 0.30f; return; case ImGuiInputFlags_RepeatRateDefault: default: *repeat_delay = g.IO.KeyRepeatDelay * 1.00f; *repeat_rate = g.IO.KeyRepeatRate * 1.00f; return; } } // Return value representing the number of presses in the last time period, for the given repeat rate // (most often returns 0 or 1. The result is generally only >1 when RepeatRate is smaller than DeltaTime, aka large DeltaTime or fast RepeatRate) int ImGui::GetKeyPressedAmount(ImGuiKey key, float repeat_delay, float repeat_rate) { ImGuiContext& g = *GImGui; const ImGuiKeyData* key_data = GetKeyData(key); if (!key_data->Down) // In theory this should already be encoded as (DownDuration < 0.0f), but testing this facilitates eating mechanism (until we finish work on key ownership) return 0; const float t = key_data->DownDuration; return CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, repeat_delay, repeat_rate); } // Return 2D vector representing the combination of four cardinal direction, with analog value support (for e.g. ImGuiKey_GamepadLStick* values). ImVec2 ImGui::GetKeyMagnitude2d(ImGuiKey key_left, ImGuiKey key_right, ImGuiKey key_up, ImGuiKey key_down) { return ImVec2( GetKeyData(key_right)->AnalogValue - GetKeyData(key_left)->AnalogValue, GetKeyData(key_down)->AnalogValue - GetKeyData(key_up)->AnalogValue); } // Rewrite routing data buffers to strip old entries + sort by key to make queries not touch scattered data. // Entries D,A,B,B,A,C,B --> A,A,B,B,B,C,D // Index A:1 B:2 C:5 D:0 --> A:0 B:2 C:5 D:6 // See 'Metrics->Key Owners & Shortcut Routing' to visualize the result of that operation. static void ImGui::UpdateKeyRoutingTable(ImGuiKeyRoutingTable* rt) { ImGuiContext& g = *GImGui; rt->EntriesNext.resize(0); for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { const int new_routing_start_idx = rt->EntriesNext.Size; ImGuiKeyRoutingData* routing_entry; for (int old_routing_idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; old_routing_idx != -1; old_routing_idx = routing_entry->NextEntryIndex) { routing_entry = &rt->Entries[old_routing_idx]; routing_entry->RoutingCurrScore = routing_entry->RoutingNextScore; routing_entry->RoutingCurr = routing_entry->RoutingNext; // Update entry routing_entry->RoutingNext = ImGuiKeyOwner_None; routing_entry->RoutingNextScore = 255; if (routing_entry->RoutingCurr == ImGuiKeyOwner_None) continue; rt->EntriesNext.push_back(*routing_entry); // Write alive ones into new buffer // Apply routing to owner if there's no owner already (RoutingCurr == None at this point) // This is the result of previous frame's SetShortcutRouting() call. if (routing_entry->Mods == g.IO.KeyMods) { ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key); if (owner_data->OwnerCurr == ImGuiKeyOwner_None) { owner_data->OwnerCurr = routing_entry->RoutingCurr; //IMGUI_DEBUG_LOG("SetKeyOwner(%s, owner_id=0x%08X) via Routing\n", GetKeyName(key), routing_entry->RoutingCurr); } } } // Rewrite linked-list rt->Index[key - ImGuiKey_NamedKey_BEGIN] = (ImGuiKeyRoutingIndex)(new_routing_start_idx < rt->EntriesNext.Size ? new_routing_start_idx : -1); for (int n = new_routing_start_idx; n < rt->EntriesNext.Size; n++) rt->EntriesNext[n].NextEntryIndex = (ImGuiKeyRoutingIndex)((n + 1 < rt->EntriesNext.Size) ? n + 1 : -1); } rt->Entries.swap(rt->EntriesNext); // Swap new and old indexes } // owner_id may be None/Any, but routing_id needs to be always be set, so we default to GetCurrentFocusScope(). static inline ImGuiID GetRoutingIdFromOwnerId(ImGuiID owner_id) { ImGuiContext& g = *GImGui; return (owner_id != ImGuiKeyOwner_None && owner_id != ImGuiKeyOwner_Any) ? owner_id : g.CurrentFocusScopeId; } ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord) { // Majority of shortcuts will be Key + any number of Mods // We accept _Single_ mod with ImGuiKey_None. // - Shortcut(ImGuiKey_S | ImGuiMod_Ctrl); // Legal // - Shortcut(ImGuiKey_S | ImGuiMod_Ctrl | ImGuiMod_Shift); // Legal // - Shortcut(ImGuiMod_Ctrl); // Legal // - Shortcut(ImGuiMod_Ctrl | ImGuiMod_Shift); // Not legal ImGuiContext& g = *GImGui; ImGuiKeyRoutingTable* rt = &g.KeysRoutingTable; ImGuiKeyRoutingData* routing_data; ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_); if (key == ImGuiKey_None) key = ConvertSingleModFlagToKey(&g, mods); IM_ASSERT(IsNamedKey(key) && (key_chord & ImGuiMod_Shortcut) == 0); // Please call ConvertShortcutMod() in calling function. // Get (in the majority of case, the linked list will have one element so this should be 2 reads. // Subsequent elements will be contiguous in memory as list is sorted/rebuilt in NewFrame). for (ImGuiKeyRoutingIndex idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; idx != -1; idx = routing_data->NextEntryIndex) { routing_data = &rt->Entries[idx]; if (routing_data->Mods == mods) return routing_data; } // Add to linked-list ImGuiKeyRoutingIndex routing_data_idx = (ImGuiKeyRoutingIndex)rt->Entries.Size; rt->Entries.push_back(ImGuiKeyRoutingData()); routing_data = &rt->Entries[routing_data_idx]; routing_data->Mods = (ImU16)mods; routing_data->NextEntryIndex = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; // Setup linked list rt->Index[key - ImGuiKey_NamedKey_BEGIN] = routing_data_idx; return routing_data; } // Current score encoding (lower is highest priority): // - 0: ImGuiInputFlags_RouteGlobalHigh // - 1: ImGuiInputFlags_RouteFocused (if item active) // - 2: ImGuiInputFlags_RouteGlobal // - 3+: ImGuiInputFlags_RouteFocused (if window in focus-stack) // - 254: ImGuiInputFlags_RouteGlobalLow // - 255: never route // 'flags' should include an explicit routing policy static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInputFlags flags) { if (flags & ImGuiInputFlags_RouteFocused) { ImGuiContext& g = *GImGui; // ActiveID gets top priority // (we don't check g.ActiveIdUsingAllKeys here. Routing is applied but if input ownership is tested later it may discard it) if (owner_id != 0 && g.ActiveId == owner_id) return 1; // Score based on distance to focused window (lower is better) // Assuming both windows are submitting a routing request, // - When Window....... is focused -> Window scores 3 (best), Window/ChildB scores 255 (no match) // - When Window/ChildB is focused -> Window scores 4, Window/ChildB scores 3 (best) // Assuming only WindowA is submitting a routing request, // - When Window/ChildB is focused -> Window scores 4 (best), Window/ChildB doesn't have a score. // This essentially follow the window->ParentWindowForFocusRoute chain. if (focus_scope_id == 0) return 255; for (int index_in_focus_path = 0; index_in_focus_path < g.NavFocusRoute.Size; index_in_focus_path++) if (g.NavFocusRoute.Data[index_in_focus_path].ID == focus_scope_id) return 3 + index_in_focus_path; return 255; } // ImGuiInputFlags_RouteGlobalHigh is default, so calls without flags are not conditional if (flags & ImGuiInputFlags_RouteGlobal) return 2; if (flags & ImGuiInputFlags_RouteGlobalLow) return 254; return 0; } // We need this to filter some Shortcut() routes when an item e.g. an InputText() is active // e.g. ImGuiKey_G won't be considered a shortcut when item is active, but ImGuiMod|ImGuiKey_G can be. static bool IsKeyChordPotentiallyCharInput(ImGuiKeyChord key_chord) { // Mimic 'ignore_char_inputs' logic in InputText() ImGuiContext& g = *GImGui; // When the right mods are pressed it cannot be a char input so we won't filter the shortcut out. ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_); const bool ignore_char_inputs = ((mods & ImGuiMod_Ctrl) && !(mods & ImGuiMod_Alt)) || (g.IO.ConfigMacOSXBehaviors && (mods & ImGuiMod_Super)); if (ignore_char_inputs) return false; // Return true for A-Z, 0-9 and other keys associated to char inputs. Other keys such as F1-F12 won't be filtered. ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); return g.KeysMayBeCharInput.TestBit(key); } // Request a desired route for an input chord (key + mods). // Return true if the route is available this frame. // - Routes and key ownership are attributed at the beginning of next frame based on best score and mod state. // (Conceptually this does a "Submit for next frame" + "Test for current frame". // As such, it could be called TrySetXXX or SubmitXXX, or the Submit and Test operations should be separate.) bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags) { ImGuiContext& g = *GImGui; if ((flags & ImGuiInputFlags_RouteMask_) == 0) flags |= ImGuiInputFlags_RouteGlobalHigh; // IMPORTANT: This is the default for SetShortcutRouting() but NOT Shortcut() else IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteMask_)); // Check that only 1 routing flag is used IM_ASSERT(owner_id != ImGuiKeyOwner_Any && owner_id != ImGuiKeyOwner_None); // Convert ImGuiMod_Shortcut and add ImGuiMod_XXXX when a corresponding ImGuiKey_LeftXXX/ImGuiKey_RightXXX is specified. key_chord = FixupKeyChord(&g, key_chord); // [DEBUG] Debug break requested by user if (g.DebugBreakInShortcutRouting == key_chord) IM_DEBUG_BREAK(); if (flags & ImGuiInputFlags_RouteUnlessBgFocused) if (g.NavWindow == NULL) return false; // Note how ImGuiInputFlags_RouteAlways won't set routing and thus won't set owner. May want to rework this? if (flags & ImGuiInputFlags_RouteAlways) { IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> always\n", GetKeyChordName(key_chord), owner_id, flags); return true; } // Specific culling when there's an active. if (g.ActiveId != 0 && g.ActiveId != owner_id) { // Cull shortcuts with no modifiers when it could generate a character. // e.g. Shortcut(ImGuiKey_G) also generates 'g' character, should not trigger when InputText() is active. // but Shortcut(Ctrl+G) should generally trigger when InputText() is active. // TL;DR: lettered shortcut with no mods or with only Alt mod will not trigger while an item reading text input is active. // (We cannot filter based on io.InputQueueCharacters[] contents because of trickling and key<>chars submission order are undefined) if ((flags & ImGuiInputFlags_RouteFocused) && g.IO.WantTextInput && IsKeyChordPotentiallyCharInput(key_chord)) { IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> filtered as potential char input\n", GetKeyChordName(key_chord), owner_id, flags); return false; } // ActiveIdUsingAllKeyboardKeys trumps all for ActiveId if ((flags & ImGuiInputFlags_RouteGlobalHigh) == 0 && g.ActiveIdUsingAllKeyboardKeys) { ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); if (key == ImGuiKey_None) key = ConvertSingleModFlagToKey(&g, (ImGuiKey)(key_chord & ImGuiMod_Mask_)); if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END) return false; } } // FIXME-SHORTCUT: A way to configure the location/focus-scope to test would render this more flexible. const int score = CalcRoutingScore(g.CurrentFocusScopeId, owner_id, flags); IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> score %d\n", GetKeyChordName(key_chord), owner_id, flags, score); if (score == 255) return false; // Submit routing for NEXT frame (assuming score is sufficient) // FIXME: Could expose a way to use a "serve last" policy for same score resolution (using <= instead of <). ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord); //const bool set_route = (flags & ImGuiInputFlags_ServeLast) ? (score <= routing_data->RoutingNextScore) : (score < routing_data->RoutingNextScore); if (score < routing_data->RoutingNextScore) { routing_data->RoutingNext = owner_id; routing_data->RoutingNextScore = (ImU8)score; } // Return routing state for CURRENT frame if (routing_data->RoutingCurr == owner_id) IMGUI_DEBUG_LOG_INPUTROUTING("--> granting current route\n"); return routing_data->RoutingCurr == owner_id; } // Currently unused by core (but used by tests) // Note: this cannot be turned into GetShortcutRouting() because we do the owner_id->routing_id translation, name would be more misleading. bool ImGui::TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id) { ImGuiContext& g = *GImGui; const ImGuiID routing_id = GetRoutingIdFromOwnerId(owner_id); key_chord = FixupKeyChord(&g, key_chord); ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord); // FIXME: Could avoid creating entry. return routing_data->RoutingCurr == routing_id; } // Note that Dear ImGui doesn't know the meaning/semantic of ImGuiKey from 0..511: they are legacy native keycodes. // Consider transitioning from 'IsKeyDown(MY_ENGINE_KEY_A)' (<1.87) to IsKeyDown(ImGuiKey_A) (>= 1.87) bool ImGui::IsKeyDown(ImGuiKey key) { return IsKeyDown(key, ImGuiKeyOwner_Any); } bool ImGui::IsKeyDown(ImGuiKey key, ImGuiID owner_id) { const ImGuiKeyData* key_data = GetKeyData(key); if (!key_data->Down) return false; if (!TestKeyOwner(key, owner_id)) return false; return true; } bool ImGui::IsKeyPressed(ImGuiKey key, bool repeat) { return IsKeyPressed(key, ImGuiKeyOwner_Any, repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None); } // Important: unless legacy IsKeyPressed(ImGuiKey, bool repeat=true) which DEFAULT to repeat, this requires EXPLICIT repeat. bool ImGui::IsKeyPressed(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags) { const ImGuiKeyData* key_data = GetKeyData(key); if (!key_data->Down) // In theory this should already be encoded as (DownDuration < 0.0f), but testing this facilitates eating mechanism (until we finish work on key ownership) return false; const float t = key_data->DownDuration; if (t < 0.0f) return false; IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsKeyPressed) == 0); // Passing flags not supported by this function! if (flags & (ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_)) // Setting any _RepeatXXX option enables _Repeat flags |= ImGuiInputFlags_Repeat; bool pressed = (t == 0.0f); if (!pressed && (flags & ImGuiInputFlags_Repeat) != 0) { float repeat_delay, repeat_rate; GetTypematicRepeatRate(flags, &repeat_delay, &repeat_rate); pressed = (t > repeat_delay) && GetKeyPressedAmount(key, repeat_delay, repeat_rate) > 0; if (pressed && (flags & ImGuiInputFlags_RepeatUntilMask_)) { // Slightly bias 'key_pressed_time' as DownDuration is an accumulation of DeltaTime which we compare to an absolute time value. // Ideally we'd replace DownDuration with KeyPressedTime but it would break user's code. ImGuiContext& g = *GImGui; double key_pressed_time = g.Time - t + 0.00001f; if ((flags & ImGuiInputFlags_RepeatUntilKeyModsChange) && (g.LastKeyModsChangeTime > key_pressed_time)) pressed = false; if ((flags & ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone) && (g.LastKeyModsChangeFromNoneTime > key_pressed_time)) pressed = false; if ((flags & ImGuiInputFlags_RepeatUntilOtherKeyPress) && (g.LastKeyboardKeyPressTime > key_pressed_time)) pressed = false; } } if (!pressed) return false; if (!TestKeyOwner(key, owner_id)) return false; return true; } bool ImGui::IsKeyReleased(ImGuiKey key) { return IsKeyReleased(key, ImGuiKeyOwner_Any); } bool ImGui::IsKeyReleased(ImGuiKey key, ImGuiID owner_id) { const ImGuiKeyData* key_data = GetKeyData(key); if (key_data->DownDurationPrev < 0.0f || key_data->Down) return false; if (!TestKeyOwner(key, owner_id)) return false; return true; } bool ImGui::IsMouseDown(ImGuiMouseButton button) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); return g.IO.MouseDown[button] && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any); // should be same as IsKeyDown(MouseButtonToKey(button), ImGuiKeyOwner_Any), but this allows legacy code hijacking the io.Mousedown[] array. } bool ImGui::IsMouseDown(ImGuiMouseButton button, ImGuiID owner_id) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); return g.IO.MouseDown[button] && TestKeyOwner(MouseButtonToKey(button), owner_id); // Should be same as IsKeyDown(MouseButtonToKey(button), owner_id), but this allows legacy code hijacking the io.Mousedown[] array. } bool ImGui::IsMouseClicked(ImGuiMouseButton button, bool repeat) { return IsMouseClicked(button, ImGuiKeyOwner_Any, repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None); } bool ImGui::IsMouseClicked(ImGuiMouseButton button, ImGuiID owner_id, ImGuiInputFlags flags) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); if (!g.IO.MouseDown[button]) // In theory this should already be encoded as (DownDuration < 0.0f), but testing this facilitates eating mechanism (until we finish work on key ownership) return false; const float t = g.IO.MouseDownDuration[button]; if (t < 0.0f) return false; IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsMouseClicked) == 0); // Passing flags not supported by this function! // FIXME: Could support RepeatRate and RepeatUntil flags here. const bool repeat = (flags & ImGuiInputFlags_Repeat) != 0; const bool pressed = (t == 0.0f) || (repeat && t > g.IO.KeyRepeatDelay && CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0); if (!pressed) return false; if (!TestKeyOwner(MouseButtonToKey(button), owner_id)) return false; return true; } bool ImGui::IsMouseReleased(ImGuiMouseButton button) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); return g.IO.MouseReleased[button] && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any); // Should be same as IsKeyReleased(MouseButtonToKey(button), ImGuiKeyOwner_Any) } bool ImGui::IsMouseReleased(ImGuiMouseButton button, ImGuiID owner_id) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); return g.IO.MouseReleased[button] && TestKeyOwner(MouseButtonToKey(button), owner_id); // Should be same as IsKeyReleased(MouseButtonToKey(button), owner_id) } bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); return g.IO.MouseClickedCount[button] == 2 && TestKeyOwner(MouseButtonToKey(button), ImGuiKeyOwner_Any); } bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button, ImGuiID owner_id) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); return g.IO.MouseClickedCount[button] == 2 && TestKeyOwner(MouseButtonToKey(button), owner_id); } int ImGui::GetMouseClickedCount(ImGuiMouseButton button) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); return g.IO.MouseClickedCount[button]; } // Test if mouse cursor is hovering given rectangle // NB- Rectangle is clipped by our current clip setting // NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style.TouchExtraPadding) bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip) { ImGuiContext& g = *GImGui; // Clip ImRect rect_clipped(r_min, r_max); if (clip) rect_clipped.ClipWith(g.CurrentWindow->ClipRect); // Hit testing, expanded for touch input if (!rect_clipped.ContainsWithPad(g.IO.MousePos, g.Style.TouchExtraPadding)) return false; return true; } // Return if a mouse click/drag went past the given threshold. Valid to call during the MouseReleased frame. // [Internal] This doesn't test if the button is pressed bool ImGui::IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); if (lock_threshold < 0.0f) lock_threshold = g.IO.MouseDragThreshold; return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold; } bool ImGui::IsMouseDragging(ImGuiMouseButton button, float lock_threshold) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); if (!g.IO.MouseDown[button]) return false; return IsMouseDragPastThreshold(button, lock_threshold); } ImVec2 ImGui::GetMousePos() { ImGuiContext& g = *GImGui; return g.IO.MousePos; } // This is called TeleportMousePos() and not SetMousePos() to emphasis that setting MousePosPrev will effectively clear mouse delta as well. // It is expected you only call this if (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos) is set and supported by backend. void ImGui::TeleportMousePos(const ImVec2& pos) { ImGuiContext& g = *GImGui; g.IO.MousePos = g.IO.MousePosPrev = pos; g.IO.MouseDelta = ImVec2(0.0f, 0.0f); g.IO.WantSetMousePos = true; //IMGUI_DEBUG_LOG_IO("TeleportMousePos: (%.1f,%.1f)\n", io.MousePos.x, io.MousePos.y); } // NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed! ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup() { ImGuiContext& g = *GImGui; if (g.BeginPopupStack.Size > 0) return g.OpenPopupStack[g.BeginPopupStack.Size - 1].OpenMousePos; return g.IO.MousePos; } // We typically use ImVec2(-FLT_MAX,-FLT_MAX) to denote an invalid mouse position. bool ImGui::IsMousePosValid(const ImVec2* mouse_pos) { // The assert is only to silence a false-positive in XCode Static Analysis. // Because GImGui is not dereferenced in every code path, the static analyzer assume that it may be NULL (which it doesn't for other functions). IM_ASSERT(GImGui != NULL); const float MOUSE_INVALID = -256000.0f; ImVec2 p = mouse_pos ? *mouse_pos : GImGui->IO.MousePos; return p.x >= MOUSE_INVALID && p.y >= MOUSE_INVALID; } // [WILL OBSOLETE] This was designed for backends, but prefer having backend maintain a mask of held mouse buttons, because upcoming input queue system will make this invalid. bool ImGui::IsAnyMouseDown() { ImGuiContext& g = *GImGui; for (int n = 0; n < IM_ARRAYSIZE(g.IO.MouseDown); n++) if (g.IO.MouseDown[n]) return true; return false; } // Return the delta from the initial clicking position while the mouse button is clicked or was just released. // This is locked and return 0.0f until the mouse moves past a distance threshold at least once. // NB: This is only valid if IsMousePosValid(). backends in theory should always keep mouse position valid when dragging even outside the client window. ImVec2 ImGui::GetMouseDragDelta(ImGuiMouseButton button, float lock_threshold) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); if (lock_threshold < 0.0f) lock_threshold = g.IO.MouseDragThreshold; if (g.IO.MouseDown[button] || g.IO.MouseReleased[button]) if (g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold) if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MouseClickedPos[button])) return g.IO.MousePos - g.IO.MouseClickedPos[button]; return ImVec2(0.0f, 0.0f); } void ImGui::ResetMouseDragDelta(ImGuiMouseButton button) { ImGuiContext& g = *GImGui; IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); // NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr g.IO.MouseClickedPos[button] = g.IO.MousePos; } // Get desired mouse cursor shape. // Important: this is meant to be used by a platform backend, it is reset in ImGui::NewFrame(), // updated during the frame, and locked in EndFrame()/Render(). // If you use software rendering by setting io.MouseDrawCursor then Dear ImGui will render those for you ImGuiMouseCursor ImGui::GetMouseCursor() { ImGuiContext& g = *GImGui; return g.MouseCursor; } void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type) { ImGuiContext& g = *GImGui; g.MouseCursor = cursor_type; } static void UpdateAliasKey(ImGuiKey key, bool v, float analog_value) { IM_ASSERT(ImGui::IsAliasKey(key)); ImGuiKeyData* key_data = ImGui::GetKeyData(key); key_data->Down = v; key_data->AnalogValue = analog_value; } // [Internal] Do not use directly static ImGuiKeyChord GetMergedModsFromKeys() { ImGuiKeyChord mods = 0; if (ImGui::IsKeyDown(ImGuiMod_Ctrl)) { mods |= ImGuiMod_Ctrl; } if (ImGui::IsKeyDown(ImGuiMod_Shift)) { mods |= ImGuiMod_Shift; } if (ImGui::IsKeyDown(ImGuiMod_Alt)) { mods |= ImGuiMod_Alt; } if (ImGui::IsKeyDown(ImGuiMod_Super)) { mods |= ImGuiMod_Super; } return mods; } static void ImGui::UpdateKeyboardInputs() { ImGuiContext& g = *GImGui; ImGuiIO& io = g.IO; // Import legacy keys or verify they are not used #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO if (io.BackendUsingLegacyKeyArrays == 0) { // Backend used new io.AddKeyEvent() API: Good! Verify that old arrays are never written to externally. for (int n = 0; n < ImGuiKey_LegacyNativeKey_END; n++) IM_ASSERT((io.KeysDown[n] == false || IsKeyDown((ImGuiKey)n)) && "Backend needs to either only use io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!"); } else { if (g.FrameCount == 0) for (int n = ImGuiKey_LegacyNativeKey_BEGIN; n < ImGuiKey_LegacyNativeKey_END; n++) IM_ASSERT(g.IO.KeyMap[n] == -1 && "Backend is not allowed to write to io.KeyMap[0..511]!"); // Build reverse KeyMap (Named -> Legacy) for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++) if (io.KeyMap[n] != -1) { IM_ASSERT(IsLegacyKey((ImGuiKey)io.KeyMap[n])); io.KeyMap[io.KeyMap[n]] = n; } // Import legacy keys into new ones for (int n = ImGuiKey_LegacyNativeKey_BEGIN; n < ImGuiKey_LegacyNativeKey_END; n++) if (io.KeysDown[n] || io.BackendUsingLegacyKeyArrays == 1) { const ImGuiKey key = (ImGuiKey)(io.KeyMap[n] != -1 ? io.KeyMap[n] : n); IM_ASSERT(io.KeyMap[n] == -1 || IsNamedKey(key)); io.KeysData[key].Down = io.KeysDown[n]; if (key != n) io.KeysDown[key] = io.KeysDown[n]; // Allow legacy code using io.KeysDown[GetKeyIndex()] with old backends io.BackendUsingLegacyKeyArrays = 1; } if (io.BackendUsingLegacyKeyArrays == 1) { GetKeyData(ImGuiMod_Ctrl)->Down = io.KeyCtrl; GetKeyData(ImGuiMod_Shift)->Down = io.KeyShift; GetKeyData(ImGuiMod_Alt)->Down = io.KeyAlt; GetKeyData(ImGuiMod_Super)->Down = io.KeySuper; } } #endif // Import legacy ImGuiNavInput_ io inputs and convert to gamepad keys #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; if (io.BackendUsingLegacyNavInputArray && nav_gamepad_active) { #define MAP_LEGACY_NAV_INPUT_TO_KEY1(_KEY, _NAV1) do { io.KeysData[_KEY].Down = (io.NavInputs[_NAV1] > 0.0f); io.KeysData[_KEY].AnalogValue = io.NavInputs[_NAV1]; } while (0) #define MAP_LEGACY_NAV_INPUT_TO_KEY2(_KEY, _NAV1, _NAV2) do { io.KeysData[_KEY].Down = (io.NavInputs[_NAV1] > 0.0f) || (io.NavInputs[_NAV2] > 0.0f); io.KeysData[_KEY].AnalogValue = ImMax(io.NavInputs[_NAV1], io.NavInputs[_NAV2]); } while (0) MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceDown, ImGuiNavInput_Activate); MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceRight, ImGuiNavInput_Cancel); MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceLeft, ImGuiNavInput_Menu); MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadFaceUp, ImGuiNavInput_Input); MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadLeft, ImGuiNavInput_DpadLeft); MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadRight, ImGuiNavInput_DpadRight); MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadUp, ImGuiNavInput_DpadUp); MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadDpadDown, ImGuiNavInput_DpadDown); MAP_LEGACY_NAV_INPUT_TO_KEY2(ImGuiKey_GamepadL1, ImGuiNavInput_FocusPrev, ImGuiNavInput_TweakSlow); MAP_LEGACY_NAV_INPUT_TO_KEY2(ImGuiKey_GamepadR1, ImGuiNavInput_FocusNext, ImGuiNavInput_TweakFast); MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickLeft, ImGuiNavInput_LStickLeft); MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickRight, ImGuiNavInput_LStickRight); MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickUp, ImGuiNavInput_LStickUp); MAP_LEGACY_NAV_INPUT_TO_KEY1(ImGuiKey_GamepadLStickDown, ImGuiNavInput_LStickDown); #undef NAV_MAP_KEY } #endif // Update aliases for (int n = 0; n < ImGuiMouseButton_COUNT; n++) UpdateAliasKey(MouseButtonToKey(n), io.MouseDown[n], io.MouseDown[n] ? 1.0f : 0.0f); UpdateAliasKey(ImGuiKey_MouseWheelX, io.MouseWheelH != 0.0f, io.MouseWheelH); UpdateAliasKey(ImGuiKey_MouseWheelY, io.MouseWheel != 0.0f, io.MouseWheel); // Synchronize io.KeyMods and io.KeyCtrl/io.KeyShift/etc. values. // - New backends (1.87+): send io.AddKeyEvent(ImGuiMod_XXX) -> -> (here) deriving io.KeyMods + io.KeyXXX from key array. // - Legacy backends: set io.KeyXXX bools -> (above) set key array from io.KeyXXX -> (here) deriving io.KeyMods + io.KeyXXX from key array. // So with legacy backends the 4 values will do a unnecessary back-and-forth but it makes the code simpler and future facing. const ImGuiKeyChord prev_key_mods = io.KeyMods; io.KeyMods = GetMergedModsFromKeys(); io.KeyCtrl = (io.KeyMods & ImGuiMod_Ctrl) != 0; io.KeyShift = (io.KeyMods & ImGuiMod_Shift) != 0; io.KeyAlt = (io.KeyMods & ImGuiMod_Alt) != 0; io.KeySuper = (io.KeyMods & ImGuiMod_Super) != 0; if (prev_key_mods != io.KeyMods) g.LastKeyModsChangeTime = g.Time; if (prev_key_mods != io.KeyMods && prev_key_mods == 0) g.LastKeyModsChangeFromNoneTime = g.Time; // Clear gamepad data if disabled if ((io.BackendFlags & ImGuiBackendFlags_HasGamepad) == 0) for (int i = ImGuiKey_Gamepad_BEGIN; i < ImGuiKey_Gamepad_END; i++) { io.KeysData[i - ImGuiKey_KeysData_OFFSET].Down = false; io.KeysData[i - ImGuiKey_KeysData_OFFSET].AnalogValue = 0.0f; } // Update keys for (int i = 0; i < ImGuiKey_KeysData_SIZE; i++) { ImGuiKeyData* key_data = &io.KeysData[i]; key_data->DownDurationPrev = key_data->DownDuration; key_data->DownDuration = key_data->Down ? (key_data->DownDuration < 0.0f ? 0.0f : key_data->DownDuration + io.DeltaTime) : -1.0f; if (key_data->DownDuration == 0.0f) { ImGuiKey key = (ImGuiKey)(ImGuiKey_KeysData_OFFSET + i); if (IsKeyboardKey(key)) g.LastKeyboardKeyPressTime = g.Time; else if (key == ImGuiKey_ReservedForModCtrl || key == ImGuiKey_ReservedForModShift || key == ImGuiKey_ReservedForModAlt || key == ImGuiKey_ReservedForModSuper) g.LastKeyboardKeyPressTime = g.Time; } } // Update keys/input owner (named keys only): one entry per key for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { ImGuiKeyData* key_data = &io.KeysData[key - ImGuiKey_KeysData_OFFSET]; ImGuiKeyOwnerData* owner_data = &g.KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN]; owner_data->OwnerCurr = owner_data->OwnerNext; if (!key_data->Down) // Important: ownership is released on the frame after a release. Ensure a 'MouseDown -> CloseWindow -> MouseUp' chain doesn't lead to someone else seeing the MouseUp. owner_data->OwnerNext = ImGuiKeyOwner_None; owner_data->LockThisFrame = owner_data->LockUntilRelease = owner_data->LockUntilRelease && key_data->Down; // Clear LockUntilRelease when key is not Down anymore } // Update key routing (for e.g. shortcuts) UpdateKeyRoutingTable(&g.KeysRoutingTable); } static void ImGui::UpdateMouseInputs() { ImGuiContext& g = *GImGui; ImGuiIO& io = g.IO; // Mouse Wheel swapping flag // As a standard behavior holding SHIFT while using Vertical Mouse Wheel triggers Horizontal scroll instead // - We avoid doing it on OSX as it the OS input layer handles this already. // - FIXME: However this means when running on OSX over Emscripten, Shift+WheelY will incur two swapping (1 in OS, 1 here), canceling the feature. // - FIXME: When we can distinguish e.g. touchpad scroll events from mouse ones, we'll set this accordingly based on input source. io.MouseWheelRequestAxisSwap = io.KeyShift && !io.ConfigMacOSXBehaviors; // Round mouse position to avoid spreading non-rounded position (e.g. UpdateManualResize doesn't support them well) if (IsMousePosValid(&io.MousePos)) io.MousePos = g.MouseLastValidPos = ImFloor(io.MousePos); // If mouse just appeared or disappeared (usually denoted by -FLT_MAX components) we cancel out movement in MouseDelta if (IsMousePosValid(&io.MousePos) && IsMousePosValid(&io.MousePosPrev)) io.MouseDelta = io.MousePos - io.MousePosPrev; else io.MouseDelta = ImVec2(0.0f, 0.0f); // Update stationary timer. // FIXME: May need to rework again to have some tolerance for occasional small movement, while being functional on high-framerates. const float mouse_stationary_threshold = (io.MouseSource == ImGuiMouseSource_Mouse) ? 2.0f : 3.0f; // Slightly higher threshold for ImGuiMouseSource_TouchScreen/ImGuiMouseSource_Pen, may need rework. const bool mouse_stationary = (ImLengthSqr(io.MouseDelta) <= mouse_stationary_threshold * mouse_stationary_threshold); g.MouseStationaryTimer = mouse_stationary ? (g.MouseStationaryTimer + io.DeltaTime) : 0.0f; //IMGUI_DEBUG_LOG("%.4f\n", g.MouseStationaryTimer); // If mouse moved we re-enable mouse hovering in case it was disabled by gamepad/keyboard. In theory should use a >0.0f threshold but would need to reset in everywhere we set this to true. if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f) g.NavDisableMouseHover = false; for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) { io.MouseClicked[i] = io.MouseDown[i] && io.MouseDownDuration[i] < 0.0f; io.MouseClickedCount[i] = 0; // Will be filled below io.MouseReleased[i] = !io.MouseDown[i] && io.MouseDownDuration[i] >= 0.0f; io.MouseDownDurationPrev[i] = io.MouseDownDuration[i]; io.MouseDownDuration[i] = io.MouseDown[i] ? (io.MouseDownDuration[i] < 0.0f ? 0.0f : io.MouseDownDuration[i] + io.DeltaTime) : -1.0f; if (io.MouseClicked[i]) { bool is_repeated_click = false; if ((float)(g.Time - io.MouseClickedTime[i]) < io.MouseDoubleClickTime) { ImVec2 delta_from_click_pos = IsMousePosValid(&io.MousePos) ? (io.MousePos - io.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f); if (ImLengthSqr(delta_from_click_pos) < io.MouseDoubleClickMaxDist * io.MouseDoubleClickMaxDist) is_repeated_click = true; } if (is_repeated_click) io.MouseClickedLastCount[i]++; else io.MouseClickedLastCount[i] = 1; io.MouseClickedTime[i] = g.Time; io.MouseClickedPos[i] = io.MousePos; io.MouseClickedCount[i] = io.MouseClickedLastCount[i]; io.MouseDragMaxDistanceSqr[i] = 0.0f; } else if (io.MouseDown[i]) { // Maintain the maximum distance we reaching from the initial click position, which is used with dragging threshold float delta_sqr_click_pos = IsMousePosValid(&io.MousePos) ? ImLengthSqr(io.MousePos - io.MouseClickedPos[i]) : 0.0f; io.MouseDragMaxDistanceSqr[i] = ImMax(io.MouseDragMaxDistanceSqr[i], delta_sqr_click_pos); } // We provide io.MouseDoubleClicked[] as a legacy service io.MouseDoubleClicked[i] = (io.MouseClickedCount[i] == 2); // Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation if (io.MouseClicked[i]) g.NavDisableMouseHover = false; } } static void LockWheelingWindow(ImGuiWindow* window, float wheel_amount) { ImGuiContext& g = *GImGui; if (window) g.WheelingWindowReleaseTimer = ImMin(g.WheelingWindowReleaseTimer + ImAbs(wheel_amount) * WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER, WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER); else g.WheelingWindowReleaseTimer = 0.0f; if (g.WheelingWindow == window) return; IMGUI_DEBUG_LOG_IO("[io] LockWheelingWindow() \"%s\"\n", window ? window->Name : "NULL"); g.WheelingWindow = window; g.WheelingWindowRefMousePos = g.IO.MousePos; if (window == NULL) { g.WheelingWindowStartFrame = -1; g.WheelingAxisAvg = ImVec2(0.0f, 0.0f); } } static ImGuiWindow* FindBestWheelingWindow(const ImVec2& wheel) { // For each axis, find window in the hierarchy that may want to use scrolling ImGuiContext& g = *GImGui; ImGuiWindow* windows[2] = { NULL, NULL }; for (int axis = 0; axis < 2; axis++) if (wheel[axis] != 0.0f) for (ImGuiWindow* window = windows[axis] = g.HoveredWindow; window->Flags & ImGuiWindowFlags_ChildWindow; window = windows[axis] = window->ParentWindow) { // Bubble up into parent window if: // - a child window doesn't allow any scrolling. // - a child window has the ImGuiWindowFlags_NoScrollWithMouse flag. //// - a child window doesn't need scrolling because it is already at the edge for the direction we are going in (FIXME-WIP) const bool has_scrolling = (window->ScrollMax[axis] != 0.0f); const bool inputs_disabled = (window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs); //const bool scrolling_past_limits = (wheel_v < 0.0f) ? (window->Scroll[axis] <= 0.0f) : (window->Scroll[axis] >= window->ScrollMax[axis]); if (has_scrolling && !inputs_disabled) // && !scrolling_past_limits) break; // select this window } if (windows[0] == NULL && windows[1] == NULL) return NULL; // If there's only one window or only one axis then there's no ambiguity if (windows[0] == windows[1] || windows[0] == NULL || windows[1] == NULL) return windows[1] ? windows[1] : windows[0]; // If candidate are different windows we need to decide which one to prioritize // - First frame: only find a winner if one axis is zero. // - Subsequent frames: only find a winner when one is more than the other. if (g.WheelingWindowStartFrame == -1) g.WheelingWindowStartFrame = g.FrameCount; if ((g.WheelingWindowStartFrame == g.FrameCount && wheel.x != 0.0f && wheel.y != 0.0f) || (g.WheelingAxisAvg.x == g.WheelingAxisAvg.y)) { g.WheelingWindowWheelRemainder = wheel; return NULL; } return (g.WheelingAxisAvg.x > g.WheelingAxisAvg.y) ? windows[0] : windows[1]; } // Called by NewFrame() void ImGui::UpdateMouseWheel() { // Reset the locked window if we move the mouse or after the timer elapses. // FIXME: Ideally we could refactor to have one timer for "changing window w/ same axis" and a shorter timer for "changing window or axis w/ other axis" (#3795) ImGuiContext& g = *GImGui; if (g.WheelingWindow != NULL) { g.WheelingWindowReleaseTimer -= g.IO.DeltaTime; if (IsMousePosValid() && ImLengthSqr(g.IO.MousePos - g.WheelingWindowRefMousePos) > g.IO.MouseDragThreshold * g.IO.MouseDragThreshold) g.WheelingWindowReleaseTimer = 0.0f; if (g.WheelingWindowReleaseTimer <= 0.0f) LockWheelingWindow(NULL, 0.0f); } ImVec2 wheel; wheel.x = TestKeyOwner(ImGuiKey_MouseWheelX, ImGuiKeyOwner_None) ? g.IO.MouseWheelH : 0.0f; wheel.y = TestKeyOwner(ImGuiKey_MouseWheelY, ImGuiKeyOwner_None) ? g.IO.MouseWheel : 0.0f; //IMGUI_DEBUG_LOG("MouseWheel X:%.3f Y:%.3f\n", wheel_x, wheel_y); ImGuiWindow* mouse_window = g.WheelingWindow ? g.WheelingWindow : g.HoveredWindow; if (!mouse_window || mouse_window->Collapsed) return; // Zoom / Scale window // FIXME-OBSOLETE: This is an old feature, it still works but pretty much nobody is using it and may be best redesigned. if (wheel.y != 0.0f && g.IO.KeyCtrl && g.IO.FontAllowUserScaling) { LockWheelingWindow(mouse_window, wheel.y); ImGuiWindow* window = mouse_window; const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); const float scale = new_font_scale / window->FontWindowScale; window->FontWindowScale = new_font_scale; if (window == window->RootWindow) { const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size; SetWindowPos(window, window->Pos + offset, 0); window->Size = ImTrunc(window->Size * scale); window->SizeFull = ImTrunc(window->SizeFull * scale); } return; } if (g.IO.KeyCtrl) return; // Mouse wheel scrolling // Read about io.MouseWheelRequestAxisSwap and its issue on Mac+Emscripten in UpdateMouseInputs() if (g.IO.MouseWheelRequestAxisSwap) wheel = ImVec2(wheel.y, 0.0f); // Maintain a rough average of moving magnitude on both axises // FIXME: should by based on wall clock time rather than frame-counter g.WheelingAxisAvg.x = ImExponentialMovingAverage(g.WheelingAxisAvg.x, ImAbs(wheel.x), 30); g.WheelingAxisAvg.y = ImExponentialMovingAverage(g.WheelingAxisAvg.y, ImAbs(wheel.y), 30); // In the rare situation where FindBestWheelingWindow() had to defer first frame of wheeling due to ambiguous main axis, reinject it now. wheel += g.WheelingWindowWheelRemainder; g.WheelingWindowWheelRemainder = ImVec2(0.0f, 0.0f); if (wheel.x == 0.0f && wheel.y == 0.0f) return; // Mouse wheel scrolling: find target and apply // - don't renew lock if axis doesn't apply on the window. // - select a main axis when both axises are being moved. if (ImGuiWindow* window = (g.WheelingWindow ? g.WheelingWindow : FindBestWheelingWindow(wheel))) if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)) { bool do_scroll[2] = { wheel.x != 0.0f && window->ScrollMax.x != 0.0f, wheel.y != 0.0f && window->ScrollMax.y != 0.0f }; if (do_scroll[ImGuiAxis_X] && do_scroll[ImGuiAxis_Y]) do_scroll[(g.WheelingAxisAvg.x > g.WheelingAxisAvg.y) ? ImGuiAxis_Y : ImGuiAxis_X] = false; if (do_scroll[ImGuiAxis_X]) { LockWheelingWindow(window, wheel.x); float max_step = window->InnerRect.GetWidth() * 0.67f; float scroll_step = ImTrunc(ImMin(2 * window->CalcFontSize(), max_step)); SetScrollX(window, window->Scroll.x - wheel.x * scroll_step); g.WheelingWindowScrolledFrame = g.FrameCount; } if (do_scroll[ImGuiAxis_Y]) { LockWheelingWindow(window, wheel.y); float max_step = window->InnerRect.GetHeight() * 0.67f; float scroll_step = ImTrunc(ImMin(5 * window->CalcFontSize(), max_step)); SetScrollY(window, window->Scroll.y - wheel.y * scroll_step); g.WheelingWindowScrolledFrame = g.FrameCount; } } } void ImGui::SetNextFrameWantCaptureKeyboard(bool want_capture_keyboard) { ImGuiContext& g = *GImGui; g.WantCaptureKeyboardNextFrame = want_capture_keyboard ? 1 : 0; } void ImGui::SetNextFrameWantCaptureMouse(bool want_capture_mouse) { ImGuiContext& g = *GImGui; g.WantCaptureMouseNextFrame = want_capture_mouse ? 1 : 0; } #ifndef IMGUI_DISABLE_DEBUG_TOOLS static const char* GetInputSourceName(ImGuiInputSource source) { const char* input_source_names[] = { "None", "Mouse", "Keyboard", "Gamepad", "Clipboard" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT && source >= 0 && source < ImGuiInputSource_COUNT); return input_source_names[source]; } static const char* GetMouseSourceName(ImGuiMouseSource source) { const char* mouse_source_names[] = { "Mouse", "TouchScreen", "Pen" }; IM_ASSERT(IM_ARRAYSIZE(mouse_source_names) == ImGuiMouseSource_COUNT && source >= 0 && source < ImGuiMouseSource_COUNT); return mouse_source_names[source]; } static void DebugPrintInputEvent(const char* prefix, const ImGuiInputEvent* e) { ImGuiContext& g = *GImGui; if (e->Type == ImGuiInputEventType_MousePos) { if (e->MousePos.PosX == -FLT_MAX && e->MousePos.PosY == -FLT_MAX) IMGUI_DEBUG_LOG_IO("[io] %s: MousePos (-FLT_MAX, -FLT_MAX)\n", prefix); else IMGUI_DEBUG_LOG_IO("[io] %s: MousePos (%.1f, %.1f) (%s)\n", prefix, e->MousePos.PosX, e->MousePos.PosY, GetMouseSourceName(e->MousePos.MouseSource)); return; } if (e->Type == ImGuiInputEventType_MouseButton) { IMGUI_DEBUG_LOG_IO("[io] %s: MouseButton %d %s (%s)\n", prefix, e->MouseButton.Button, e->MouseButton.Down ? "Down" : "Up", GetMouseSourceName(e->MouseButton.MouseSource)); return; } if (e->Type == ImGuiInputEventType_MouseWheel) { IMGUI_DEBUG_LOG_IO("[io] %s: MouseWheel (%.3f, %.3f) (%s)\n", prefix, e->MouseWheel.WheelX, e->MouseWheel.WheelY, GetMouseSourceName(e->MouseWheel.MouseSource)); return; } if (e->Type == ImGuiInputEventType_Key) { IMGUI_DEBUG_LOG_IO("[io] %s: Key \"%s\" %s\n", prefix, ImGui::GetKeyName(e->Key.Key), e->Key.Down ? "Down" : "Up"); return; } if (e->Type == ImGuiInputEventType_Text) { IMGUI_DEBUG_LOG_IO("[io] %s: Text: %c (U+%08X)\n", prefix, e->Text.Char, e->Text.Char); return; } if (e->Type == ImGuiInputEventType_Focus) { IMGUI_DEBUG_LOG_IO("[io] %s: AppFocused %d\n", prefix, e->AppFocused.Focused); return; } } #endif // Process input queue // We always call this with the value of 'bool g.IO.ConfigInputTrickleEventQueue'. // - trickle_fast_inputs = false : process all events, turn into flattened input state (e.g. successive down/up/down/up will be lost) // - trickle_fast_inputs = true : process as many events as possible (successive down/up/down/up will be trickled over several frames so nothing is lost) (new feature in 1.87) void ImGui::UpdateInputEvents(bool trickle_fast_inputs) { ImGuiContext& g = *GImGui; ImGuiIO& io = g.IO; // Only trickle chars<>key when working with InputText() // FIXME: InputText() could parse event trail? // FIXME: Could specialize chars<>keys trickling rules for control keys (those not typically associated to characters) const bool trickle_interleaved_keys_and_text = (trickle_fast_inputs && g.WantTextInputNextFrame == 1); bool mouse_moved = false, mouse_wheeled = false, key_changed = false, text_inputted = false; int mouse_button_changed = 0x00; ImBitArray key_changed_mask; int event_n = 0; for (; event_n < g.InputEventsQueue.Size; event_n++) { ImGuiInputEvent* e = &g.InputEventsQueue[event_n]; if (e->Type == ImGuiInputEventType_MousePos) { if (g.IO.WantSetMousePos) continue; // Trickling Rule: Stop processing queued events if we already handled a mouse button change ImVec2 event_pos(e->MousePos.PosX, e->MousePos.PosY); if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_wheeled || key_changed || text_inputted)) break; io.MousePos = event_pos; io.MouseSource = e->MousePos.MouseSource; mouse_moved = true; } else if (e->Type == ImGuiInputEventType_MouseButton) { // Trickling Rule: Stop processing queued events if we got multiple action on the same button const ImGuiMouseButton button = e->MouseButton.Button; IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT); if (trickle_fast_inputs && ((mouse_button_changed & (1 << button)) || mouse_wheeled)) break; if (trickle_fast_inputs && e->MouseButton.MouseSource == ImGuiMouseSource_TouchScreen && mouse_moved) // #2702: TouchScreen have no initial hover. break; io.MouseDown[button] = e->MouseButton.Down; io.MouseSource = e->MouseButton.MouseSource; mouse_button_changed |= (1 << button); } else if (e->Type == ImGuiInputEventType_MouseWheel) { // Trickling Rule: Stop processing queued events if we got multiple action on the event if (trickle_fast_inputs && (mouse_moved || mouse_button_changed != 0)) break; io.MouseWheelH += e->MouseWheel.WheelX; io.MouseWheel += e->MouseWheel.WheelY; io.MouseSource = e->MouseWheel.MouseSource; mouse_wheeled = true; } else if (e->Type == ImGuiInputEventType_Key) { // Trickling Rule: Stop processing queued events if we got multiple action on the same button ImGuiKey key = e->Key.Key; IM_ASSERT(key != ImGuiKey_None); ImGuiKeyData* key_data = GetKeyData(key); const int key_data_index = (int)(key_data - g.IO.KeysData); if (trickle_fast_inputs && key_data->Down != e->Key.Down && (key_changed_mask.TestBit(key_data_index) || text_inputted || mouse_button_changed != 0)) break; key_data->Down = e->Key.Down; key_data->AnalogValue = e->Key.AnalogValue; key_changed = true; key_changed_mask.SetBit(key_data_index); // Allow legacy code using io.KeysDown[GetKeyIndex()] with new backends #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO io.KeysDown[key_data_index] = key_data->Down; if (io.KeyMap[key_data_index] != -1) io.KeysDown[io.KeyMap[key_data_index]] = key_data->Down; #endif } else if (e->Type == ImGuiInputEventType_Text) { // Trickling Rule: Stop processing queued events if keys/mouse have been interacted with if (trickle_fast_inputs && ((key_changed && trickle_interleaved_keys_and_text) || mouse_button_changed != 0 || mouse_moved || mouse_wheeled)) break; unsigned int c = e->Text.Char; io.InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar)c : IM_UNICODE_CODEPOINT_INVALID); if (trickle_interleaved_keys_and_text) text_inputted = true; } else if (e->Type == ImGuiInputEventType_Focus) { // We intentionally overwrite this and process in NewFrame(), in order to give a chance // to multi-viewports backends to queue AddFocusEvent(false) + AddFocusEvent(true) in same frame. const bool focus_lost = !e->AppFocused.Focused; io.AppFocusLost = focus_lost; } else { IM_ASSERT(0 && "Unknown event!"); } } // Record trail (for domain-specific applications wanting to access a precise trail) //if (event_n != 0) IMGUI_DEBUG_LOG_IO("Processed: %d / Remaining: %d\n", event_n, g.InputEventsQueue.Size - event_n); for (int n = 0; n < event_n; n++) g.InputEventsTrail.push_back(g.InputEventsQueue[n]); // [DEBUG] #ifndef IMGUI_DISABLE_DEBUG_TOOLS if (event_n != 0 && (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO)) for (int n = 0; n < g.InputEventsQueue.Size; n++) DebugPrintInputEvent(n < event_n ? "Processed" : "Remaining", &g.InputEventsQueue[n]); #endif // Remaining events will be processed on the next frame if (event_n == g.InputEventsQueue.Size) g.InputEventsQueue.resize(0); else g.InputEventsQueue.erase(g.InputEventsQueue.Data, g.InputEventsQueue.Data + event_n); // Clear buttons state when focus is lost // - this is useful so e.g. releasing Alt after focus loss on Alt-Tab doesn't trigger the Alt menu toggle. // - we clear in EndFrame() and not now in order allow application/user code polling this flag // (e.g. custom backend may want to clear additional data, custom widgets may want to react with a "canceling" event). if (g.IO.AppFocusLost) g.IO.ClearInputKeys(); } ImGuiID ImGui::GetKeyOwner(ImGuiKey key) { if (!IsNamedKeyOrModKey(key)) return ImGuiKeyOwner_None; ImGuiContext& g = *GImGui; ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key); ImGuiID owner_id = owner_data->OwnerCurr; if (g.ActiveIdUsingAllKeyboardKeys && owner_id != g.ActiveId && owner_id != ImGuiKeyOwner_Any) if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END) return ImGuiKeyOwner_None; return owner_id; } // TestKeyOwner(..., ID) : (owner == None || owner == ID) // TestKeyOwner(..., None) : (owner == None) // TestKeyOwner(..., Any) : no owner test // All paths are also testing for key not being locked, for the rare cases that key have been locked with using ImGuiInputFlags_LockXXX flags. bool ImGui::TestKeyOwner(ImGuiKey key, ImGuiID owner_id) { if (!IsNamedKeyOrModKey(key)) return true; ImGuiContext& g = *GImGui; if (g.ActiveIdUsingAllKeyboardKeys && owner_id != g.ActiveId && owner_id != ImGuiKeyOwner_Any) if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END) return false; ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key); if (owner_id == ImGuiKeyOwner_Any) return (owner_data->LockThisFrame == false); // Note: SetKeyOwner() sets OwnerCurr. It is not strictly required for most mouse routing overlap (because of ActiveId/HoveredId // are acting as filter before this has a chance to filter), but sane as soon as user tries to look into things. // Setting OwnerCurr in SetKeyOwner() is more consistent than testing OwnerNext here: would be inconsistent with getter and other functions. if (owner_data->OwnerCurr != owner_id) { if (owner_data->LockThisFrame) return false; if (owner_data->OwnerCurr != ImGuiKeyOwner_None) return false; } return true; } // _LockXXX flags are useful to lock keys away from code which is not input-owner aware. // When using _LockXXX flags, you can use ImGuiKeyOwner_Any to lock keys from everyone. // - SetKeyOwner(..., None) : clears owner // - SetKeyOwner(..., Any, !Lock) : illegal (assert) // - SetKeyOwner(..., Any or None, Lock) : set lock void ImGui::SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags) { ImGuiContext& g = *GImGui; IM_ASSERT(IsNamedKeyOrModKey(key) && (owner_id != ImGuiKeyOwner_Any || (flags & (ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease)))); // Can only use _Any with _LockXXX flags (to eat a key away without an ID to retrieve it) IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetKeyOwner) == 0); // Passing flags not supported by this function! //IMGUI_DEBUG_LOG("SetKeyOwner(%s, owner_id=0x%08X, flags=%08X)\n", GetKeyName(key), owner_id, flags); ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key); owner_data->OwnerCurr = owner_data->OwnerNext = owner_id; // We cannot lock by default as it would likely break lots of legacy code. // In the case of using LockUntilRelease while key is not down we still lock during the frame (no key_data->Down test) owner_data->LockUntilRelease = (flags & ImGuiInputFlags_LockUntilRelease) != 0; owner_data->LockThisFrame = (flags & ImGuiInputFlags_LockThisFrame) != 0 || (owner_data->LockUntilRelease); } // Rarely used helper void ImGui::SetKeyOwnersForKeyChord(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags) { if (key_chord & ImGuiMod_Ctrl) { SetKeyOwner(ImGuiMod_Ctrl, owner_id, flags); } if (key_chord & ImGuiMod_Shift) { SetKeyOwner(ImGuiMod_Shift, owner_id, flags); } if (key_chord & ImGuiMod_Alt) { SetKeyOwner(ImGuiMod_Alt, owner_id, flags); } if (key_chord & ImGuiMod_Super) { SetKeyOwner(ImGuiMod_Super, owner_id, flags); } if (key_chord & ImGuiMod_Shortcut) { SetKeyOwner(ImGuiMod_Shortcut, owner_id, flags); } if (key_chord & ~ImGuiMod_Mask_) { SetKeyOwner((ImGuiKey)(key_chord & ~ImGuiMod_Mask_), owner_id, flags); } } // This is more or less equivalent to: // if (IsItemHovered() || IsItemActive()) // SetKeyOwner(key, GetItemID()); // Extensive uses of that (e.g. many calls for a single item) may want to manually perform the tests once and then call SetKeyOwner() multiple times. // More advanced usage scenarios may want to call SetKeyOwner() manually based on different condition. // Worth noting is that only one item can be hovered and only one item can be active, therefore this usage pattern doesn't need to bother with routing and priority. void ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags) { ImGuiContext& g = *GImGui; ImGuiID id = g.LastItemData.ID; if (id == 0 || (g.HoveredId != id && g.ActiveId != id)) return; if ((flags & ImGuiInputFlags_CondMask_) == 0) flags |= ImGuiInputFlags_CondDefault_; if ((g.HoveredId == id && (flags & ImGuiInputFlags_CondHovered)) || (g.ActiveId == id && (flags & ImGuiInputFlags_CondActive))) { IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetItemKeyOwner) == 0); // Passing flags not supported by this function! SetKeyOwner(key, id, flags & ~ImGuiInputFlags_CondMask_); } } // This is the only public API until we expose owner_id versions of the API as replacements. bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord) { return IsKeyChordPressed(key_chord, 0, ImGuiInputFlags_None); } // This is equivalent to comparing KeyMods + doing a IsKeyPressed() bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags) { ImGuiContext& g = *GImGui; key_chord = FixupKeyChord(&g, key_chord); ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_); if (g.IO.KeyMods != mods) return false; // Special storage location for mods ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); if (key == ImGuiKey_None) key = ConvertSingleModFlagToKey(&g, mods); if (!IsKeyPressed(key, owner_id, (flags & ImGuiInputFlags_RepeatMask_))) return false; return true; } void ImGui::SetNextItemShortcut(ImGuiKeyChord key_chord) { ImGuiContext& g = *GImGui; g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasShortcut; g.NextItemData.Shortcut = key_chord; } bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags) { //ImGuiContext& g = *GImGui; //IMGUI_DEBUG_LOG("Shortcut(%s, owner_id=0x%08X, flags=%X)\n", GetKeyChordName(key_chord, g.TempBuffer.Data, g.TempBuffer.Size), owner_id, flags); // When using (owner_id == 0/Any): SetShortcutRouting() will use CurrentFocusScopeId and filter with this, so IsKeyPressed() is fine with he 0/Any. if ((flags & ImGuiInputFlags_RouteMask_) == 0) flags |= ImGuiInputFlags_RouteFocused; // Using 'owner_id == ImGuiKeyOwner_Any/0': auto-assign an owner based on current focus scope (each window has its focus scope by default) // Effectively makes Shortcut() always input-owner aware. if (owner_id == ImGuiKeyOwner_Any || owner_id == ImGuiKeyOwner_None) owner_id = GetRoutingIdFromOwnerId(owner_id); // Submit route if (!SetShortcutRouting(key_chord, owner_id, flags)) return false; // Default repeat behavior for Shortcut() // So e.g. pressing Ctrl+W and releasing Ctrl while holding W will not trigger the W shortcut. if ((flags & ImGuiInputFlags_Repeat) != 0 && (flags & ImGuiInputFlags_RepeatUntilMask_) == 0) flags |= ImGuiInputFlags_RepeatUntilKeyModsChange; if (!IsKeyChordPressed(key_chord, owner_id, flags)) return false; IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByShortcut) == 0); // Passing flags not supported by this function! return true; } //----------------------------------------------------------------------------- // [SECTION] ERROR CHECKING //----------------------------------------------------------------------------- // Helper function to verify ABI compatibility between caller code and compiled version of Dear ImGui. // Verify that the type sizes are matching between the calling file's compilation unit and imgui.cpp's compilation unit // If this triggers you have an issue: // - Most commonly: mismatched headers and compiled code version. // - Or: mismatched configuration #define, compilation settings, packing pragma etc. // The configuration settings mentioned in imconfig.h must be set for all compilation units involved with Dear ImGui, // which is way it is required you put them in your imconfig file (and not just before including imgui.h). // Otherwise it is possible that different compilation units would see different structure layout bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_vert, size_t sz_idx) { bool error = false; if (strcmp(version, IMGUI_VERSION) != 0) { error = true; IM_ASSERT(strcmp(version, IMGUI_VERSION) == 0 && "Mismatched version string!"); } if (sz_io != sizeof(ImGuiIO)) { error = true; IM_ASSERT(sz_io == sizeof(ImGuiIO) && "Mismatched struct layout!"); } if (sz_style != sizeof(ImGuiStyle)) { error = true; IM_ASSERT(sz_style == sizeof(ImGuiStyle) && "Mismatched struct layout!"); } if (sz_vec2 != sizeof(ImVec2)) { error = true; IM_ASSERT(sz_vec2 == sizeof(ImVec2) && "Mismatched struct layout!"); } if (sz_vec4 != sizeof(ImVec4)) { error = true; IM_ASSERT(sz_vec4 == sizeof(ImVec4) && "Mismatched struct layout!"); } if (sz_vert != sizeof(ImDrawVert)) { error = true; IM_ASSERT(sz_vert == sizeof(ImDrawVert) && "Mismatched struct layout!"); } if (sz_idx != sizeof(ImDrawIdx)) { error = true; IM_ASSERT(sz_idx == sizeof(ImDrawIdx) && "Mismatched struct layout!"); } return !error; } // Until 1.89 (IMGUI_VERSION_NUM < 18814) it was legal to use SetCursorPos() to extend the boundary of a parent (e.g. window or table cell) // This is causing issues and ambiguity and we need to retire that. // See https://github.com/ocornut/imgui/issues/5548 for more details. // [Scenario 1] // Previously this would make the window content size ~200x200: // Begin(...) + SetCursorScreenPos(GetCursorScreenPos() + ImVec2(200,200)) + End(); // NOT OK // Instead, please submit an item: // Begin(...) + SetCursorScreenPos(GetCursorScreenPos() + ImVec2(200,200)) + Dummy(ImVec2(0,0)) + End(); // OK // Alternative: // Begin(...) + Dummy(ImVec2(200,200)) + End(); // OK // [Scenario 2] // For reference this is one of the issue what we aim to fix with this change: // BeginGroup() + SomeItem("foobar") + SetCursorScreenPos(GetCursorScreenPos()) + EndGroup() // The previous logic made SetCursorScreenPos(GetCursorScreenPos()) have a side-effect! It would erroneously incorporate ItemSpacing.y after the item into content size, making the group taller! // While this code is a little twisted, no-one would expect SetXXX(GetXXX()) to have a side-effect. Using vertical alignment patterns could trigger this issue. void ImGui::ErrorCheckUsingSetCursorPosToExtendParentBoundaries() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(window->DC.IsSetPos); window->DC.IsSetPos = false; #ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS if (window->DC.CursorPos.x <= window->DC.CursorMaxPos.x && window->DC.CursorPos.y <= window->DC.CursorMaxPos.y) return; if (window->SkipItems) return; IM_ASSERT(0 && "Code uses SetCursorPos()/SetCursorScreenPos() to extend window/parent boundaries. Please submit an item e.g. Dummy() to validate extent."); #else window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos); #endif } static void ImGui::ErrorCheckNewFrameSanityChecks() { ImGuiContext& g = *GImGui; // Check user IM_ASSERT macro // (IF YOU GET A WARNING OR COMPILE ERROR HERE: it means your assert macro is incorrectly defined! // If your macro uses multiple statements, it NEEDS to be surrounded by a 'do { ... } while (0)' block. // This is a common C/C++ idiom to allow multiple statements macros to be used in control flow blocks.) // #define IM_ASSERT(EXPR) if (SomeCode(EXPR)) SomeMoreCode(); // Wrong! // #define IM_ASSERT(EXPR) do { if (SomeCode(EXPR)) SomeMoreCode(); } while (0) // Correct! if (true) IM_ASSERT(1); else IM_ASSERT(0); // Emscripten backends are often imprecise in their submission of DeltaTime. (#6114, #3644) // Ideally the Emscripten app/backend should aim to fix or smooth this value and avoid feeding zero, but we tolerate it. #ifdef __EMSCRIPTEN__ if (g.IO.DeltaTime <= 0.0f && g.FrameCount > 0) g.IO.DeltaTime = 0.00001f; #endif // Check user data // (We pass an error message in the assert expression to make it visible to programmers who are not using a debugger, as most assert handlers display their argument) IM_ASSERT(g.Initialized); IM_ASSERT((g.IO.DeltaTime > 0.0f || g.FrameCount == 0) && "Need a positive DeltaTime!"); IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forgot to call Render() or EndFrame() at the end of the previous frame?"); IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f && "Invalid DisplaySize value!"); IM_ASSERT(g.IO.Fonts->IsBuilt() && "Font Atlas not built! Make sure you called ImGui_ImplXXXX_NewFrame() function for renderer backend, which should call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8()"); IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting!"); IM_ASSERT(g.Style.CircleTessellationMaxError > 0.0f && "Invalid style setting!"); IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting!"); // Allows us to avoid a few clamps in color computations IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting."); IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right); IM_ASSERT(g.Style.ColorButtonPosition == ImGuiDir_Left || g.Style.ColorButtonPosition == ImGuiDir_Right); #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_COUNT; n++) IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < ImGuiKey_LegacyNativeKey_END && "io.KeyMap[] contains an out of bound value (need to be 0..511, or -1 for unmapped key)"); // Check: required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was only added in 1.60 WIP) if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && g.IO.BackendUsingLegacyKeyArrays == 1) IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation."); #endif // Check: the io.ConfigWindowsResizeFromEdges option requires backend to honor mouse cursor changes and set the ImGuiBackendFlags_HasMouseCursors flag accordingly. if (g.IO.ConfigWindowsResizeFromEdges && !(g.IO.BackendFlags & ImGuiBackendFlags_HasMouseCursors)) g.IO.ConfigWindowsResizeFromEdges = false; } static void ImGui::ErrorCheckEndFrameSanityChecks() { ImGuiContext& g = *GImGui; // Verify that io.KeyXXX fields haven't been tampered with. Key mods should not be modified between NewFrame() and EndFrame() // One possible reason leading to this assert is that your backends update inputs _AFTER_ NewFrame(). // It is known that when some modal native windows called mid-frame takes focus away, some backends such as GLFW will // send key release events mid-frame. This would normally trigger this assertion and lead to sheared inputs. // We silently accommodate for this case by ignoring the case where all io.KeyXXX modifiers were released (aka key_mod_flags == 0), // while still correctly asserting on mid-frame key press events. const ImGuiKeyChord key_mods = GetMergedModsFromKeys(); IM_ASSERT((key_mods == 0 || g.IO.KeyMods == key_mods) && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods"); IM_UNUSED(key_mods); // [EXPERIMENTAL] Recover from errors: You may call this yourself before EndFrame(). //ErrorCheckEndFrameRecover(); // Report when there is a mismatch of Begin/BeginChild vs End/EndChild calls. Important: Remember that the Begin/BeginChild API requires you // to always call End/EndChild even if Begin/BeginChild returns false! (this is unfortunately inconsistent with most other Begin* API). if (g.CurrentWindowStack.Size != 1) { if (g.CurrentWindowStack.Size > 1) { ImGuiWindow* window = g.CurrentWindowStack.back().Window; // <-- This window was not Ended! IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you forget to call End/EndChild?"); IM_UNUSED(window); while (g.CurrentWindowStack.Size > 1) End(); } else { IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size == 1, "Mismatched Begin/BeginChild vs End/EndChild calls: did you call End/EndChild too much?"); } } IM_ASSERT_USER_ERROR(g.GroupStack.Size == 0, "Missing EndGroup call!"); } // Experimental recovery from incorrect usage of BeginXXX/EndXXX/PushXXX/PopXXX calls. // Must be called during or before EndFrame(). // This is generally flawed as we are not necessarily End/Popping things in the right order. // FIXME: Can't recover from inside BeginTabItem/EndTabItem yet. // FIXME: Can't recover from interleaved BeginTabBar/Begin void ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data) { // PVS-Studio V1044 is "Loop break conditions do not depend on the number of iterations" ImGuiContext& g = *GImGui; while (g.CurrentWindowStack.Size > 0) //-V1044 { ErrorCheckEndWindowRecover(log_callback, user_data); ImGuiWindow* window = g.CurrentWindow; if (g.CurrentWindowStack.Size == 1) { IM_ASSERT(window->IsFallbackWindow); break; } if (window->Flags & ImGuiWindowFlags_ChildWindow) { if (log_callback) log_callback(user_data, "Recovered from missing EndChild() for '%s'", window->Name); EndChild(); } else { if (log_callback) log_callback(user_data, "Recovered from missing End() for '%s'", window->Name); End(); } } } // Must be called before End()/EndChild() void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data) { ImGuiContext& g = *GImGui; while (g.CurrentTable && (g.CurrentTable->OuterWindow == g.CurrentWindow || g.CurrentTable->InnerWindow == g.CurrentWindow)) { if (log_callback) log_callback(user_data, "Recovered from missing EndTable() in '%s'", g.CurrentTable->OuterWindow->Name); EndTable(); } ImGuiWindow* window = g.CurrentWindow; ImGuiStackSizes* stack_sizes = &g.CurrentWindowStack.back().StackSizesOnBegin; IM_ASSERT(window != NULL); while (g.CurrentTabBar != NULL) //-V1044 { if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'", window->Name); EndTabBar(); } while (window->DC.TreeDepth > 0) { if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'", window->Name); TreePop(); } while (g.GroupStack.Size > stack_sizes->SizeOfGroupStack) //-V1044 { if (log_callback) log_callback(user_data, "Recovered from missing EndGroup() in '%s'", window->Name); EndGroup(); } while (window->IDStack.Size > 1) { if (log_callback) log_callback(user_data, "Recovered from missing PopID() in '%s'", window->Name); PopID(); } while (g.DisabledStackSize > stack_sizes->SizeOfDisabledStack) //-V1044 { if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'", window->Name); EndDisabled(); } while (g.ColorStack.Size > stack_sizes->SizeOfColorStack) { if (log_callback) log_callback(user_data, "Recovered from missing PopStyleColor() in '%s' for ImGuiCol_%s", window->Name, GetStyleColorName(g.ColorStack.back().Col)); PopStyleColor(); } while (g.ItemFlagsStack.Size > stack_sizes->SizeOfItemFlagsStack) //-V1044 { if (log_callback) log_callback(user_data, "Recovered from missing PopItemFlag() in '%s'", window->Name); PopItemFlag(); } while (g.StyleVarStack.Size > stack_sizes->SizeOfStyleVarStack) //-V1044 { if (log_callback) log_callback(user_data, "Recovered from missing PopStyleVar() in '%s'", window->Name); PopStyleVar(); } while (g.FontStack.Size > stack_sizes->SizeOfFontStack) //-V1044 { if (log_callback) log_callback(user_data, "Recovered from missing PopFont() in '%s'", window->Name); PopFont(); } while (g.FocusScopeStack.Size > stack_sizes->SizeOfFocusScopeStack + 1) //-V1044 { if (log_callback) log_callback(user_data, "Recovered from missing PopFocusScope() in '%s'", window->Name); PopFocusScope(); } } // Save current stack sizes for later compare void ImGuiStackSizes::SetToContextState(ImGuiContext* ctx) { ImGuiContext& g = *ctx; ImGuiWindow* window = g.CurrentWindow; SizeOfIDStack = (short)window->IDStack.Size; SizeOfColorStack = (short)g.ColorStack.Size; SizeOfStyleVarStack = (short)g.StyleVarStack.Size; SizeOfFontStack = (short)g.FontStack.Size; SizeOfFocusScopeStack = (short)g.FocusScopeStack.Size; SizeOfGroupStack = (short)g.GroupStack.Size; SizeOfItemFlagsStack = (short)g.ItemFlagsStack.Size; SizeOfBeginPopupStack = (short)g.BeginPopupStack.Size; SizeOfDisabledStack = (short)g.DisabledStackSize; } // Compare to detect usage errors void ImGuiStackSizes::CompareWithContextState(ImGuiContext* ctx) { ImGuiContext& g = *ctx; ImGuiWindow* window = g.CurrentWindow; IM_UNUSED(window); // Window stacks // NOT checking: DC.ItemWidth, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin) IM_ASSERT(SizeOfIDStack == window->IDStack.Size && "PushID/PopID or TreeNode/TreePop Mismatch!"); // Global stacks // For color, style and font stacks there is an incentive to use Push/Begin/Pop/.../End patterns, so we relax our checks a little to allow them. IM_ASSERT(SizeOfGroupStack == g.GroupStack.Size && "BeginGroup/EndGroup Mismatch!"); IM_ASSERT(SizeOfBeginPopupStack == g.BeginPopupStack.Size && "BeginPopup/EndPopup or BeginMenu/EndMenu Mismatch!"); IM_ASSERT(SizeOfDisabledStack == g.DisabledStackSize && "BeginDisabled/EndDisabled Mismatch!"); IM_ASSERT(SizeOfItemFlagsStack >= g.ItemFlagsStack.Size && "PushItemFlag/PopItemFlag Mismatch!"); IM_ASSERT(SizeOfColorStack >= g.ColorStack.Size && "PushStyleColor/PopStyleColor Mismatch!"); IM_ASSERT(SizeOfStyleVarStack >= g.StyleVarStack.Size && "PushStyleVar/PopStyleVar Mismatch!"); IM_ASSERT(SizeOfFontStack >= g.FontStack.Size && "PushFont/PopFont Mismatch!"); IM_ASSERT(SizeOfFocusScopeStack == g.FocusScopeStack.Size && "PushFocusScope/PopFocusScope Mismatch!"); } //----------------------------------------------------------------------------- // [SECTION] ITEM SUBMISSION //----------------------------------------------------------------------------- // - KeepAliveID() // - ItemHandleShortcut() [Internal] // - ItemAdd() //----------------------------------------------------------------------------- // Code not using ItemAdd() may need to call this manually otherwise ActiveId will be cleared. In IMGUI_VERSION_NUM < 18717 this was called by GetID(). void ImGui::KeepAliveID(ImGuiID id) { ImGuiContext& g = *GImGui; if (g.ActiveId == id) g.ActiveIdIsAlive = id; if (g.ActiveIdPreviousFrame == id) g.ActiveIdPreviousFrameIsAlive = true; } static void ItemHandleShortcut(ImGuiID id) { // FIXME: Generalize Activation queue? ImGuiContext& g = *GImGui; if (ImGui::Shortcut(g.NextItemData.Shortcut, id, ImGuiInputFlags_None) && g.NavActivateId == 0) { g.NavActivateId = id; // Will effectively disable clipping. g.NavActivateFlags = ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_FromShortcut; if (g.ActiveId == 0 || g.ActiveId == id) g.NavActivateDownId = g.NavActivatePressedId = id; ImGui::NavHighlightActivated(id); } } // Declare item bounding box for clipping and interaction. // Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface // declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction. // THIS IS IN THE PERFORMANCE CRITICAL PATH (UNTIL THE CLIPPING TEST AND EARLY-RETURN) bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGuiItemFlags extra_flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; // Set item data // (DisplayRect is left untouched, made valid when ImGuiItemStatusFlags_HasDisplayRect is set) g.LastItemData.ID = id; g.LastItemData.Rect = bb; g.LastItemData.NavRect = nav_bb_arg ? *nav_bb_arg : bb; g.LastItemData.InFlags = g.CurrentItemFlags | g.NextItemData.ItemFlags | extra_flags; g.LastItemData.StatusFlags = ImGuiItemStatusFlags_None; // Note: we don't copy 'g.NextItemData.SelectionUserData' to an hypothetical g.LastItemData.SelectionUserData: since the former is not cleared. if (id != 0) { KeepAliveID(id); // Directional navigation processing // Runs prior to clipping early-out // (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests // unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of // thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame. // We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able // to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick). // We intentionally don't check if g.NavWindow != NULL because g.NavAnyRequest should only be set when it is non null. // If we crash on a NULL g.NavWindow we need to fix the bug elsewhere. if (!(g.LastItemData.InFlags & ImGuiItemFlags_NoNav)) { // FIMXE-NAV: investigate changing the window tests into a simple 'if (g.NavFocusScopeId == g.CurrentFocusScopeId)' test. window->DC.NavLayersActiveMaskNext |= (1 << window->DC.NavLayerCurrent); if (g.NavId == id || g.NavAnyRequest) if (g.NavWindow->RootWindowForNav == window->RootWindowForNav) if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened)) NavProcessItem(); } if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasShortcut) ItemHandleShortcut(id); } // Lightweight clear of SetNextItemXXX data. g.NextItemData.Flags = ImGuiNextItemDataFlags_None; g.NextItemData.ItemFlags = ImGuiItemFlags_None; #ifdef IMGUI_ENABLE_TEST_ENGINE if (id != 0) IMGUI_TEST_ENGINE_ITEM_ADD(id, g.LastItemData.NavRect, &g.LastItemData); #endif // Clipping test // (this is a modified copy of IsClippedEx() so we can reuse the is_rect_visible value) //const bool is_clipped = IsClippedEx(bb, id); //if (is_clipped) // return false; // g.NavActivateId is not necessarily == g.NavId, in the case of remote activation (e.g. shortcuts) const bool is_rect_visible = bb.Overlaps(window->ClipRect); if (!is_rect_visible) if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId && id != g.NavActivateId)) if (!g.LogEnabled) return false; // [DEBUG] #ifndef IMGUI_DISABLE_DEBUG_TOOLS if (id != 0) { if (id == g.DebugLocateId) DebugLocateItemResolveWithLastItem(); // [DEBUG] People keep stumbling on this problem and using "" as identifier in the root of a window instead of "##something". // Empty identifier are valid and useful in a small amount of cases, but 99.9% of the time you want to use "##something". // READ THE FAQ: https://dearimgui.com/faq IM_ASSERT(id != window->ID && "Cannot have an empty ID at the root of a window. If you need an empty label, use ## and read the FAQ about how the ID Stack works!"); } //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] //if ((g.LastItemData.InFlags & ImGuiItemFlags_NoNav) == 0) // window->DrawList->AddRect(g.LastItemData.NavRect.Min, g.LastItemData.NavRect.Max, IM_COL32(255,255,0,255)); // [DEBUG] #endif // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them) if (is_rect_visible) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Visible; if (IsMouseHoveringRect(bb.Min, bb.Max)) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect; return true; } //----------------------------------------------------------------------------- // [SECTION] LAYOUT //----------------------------------------------------------------------------- // - ItemSize() // - SameLine() // - GetCursorScreenPos() // - SetCursorScreenPos() // - GetCursorPos(), GetCursorPosX(), GetCursorPosY() // - SetCursorPos(), SetCursorPosX(), SetCursorPosY() // - GetCursorStartPos() // - Indent() // - Unindent() // - SetNextItemWidth() // - PushItemWidth() // - PushMultiItemsWidths() // - PopItemWidth() // - CalcItemWidth() // - CalcItemSize() // - GetTextLineHeight() // - GetTextLineHeightWithSpacing() // - GetFrameHeight() // - GetFrameHeightWithSpacing() // - GetContentRegionMax() // - GetContentRegionMaxAbs() [Internal] // - GetContentRegionAvail(), // - GetWindowContentRegionMin(), GetWindowContentRegionMax() // - BeginGroup() // - EndGroup() // Also see in imgui_widgets: tab bars, and in imgui_tables: tables, columns. //----------------------------------------------------------------------------- // Advance cursor given item size for layout. // Register minimum needed size so it can extend the bounding box used for auto-fit calculation. // See comments in ItemAdd() about how/why the size provided to ItemSize() vs ItemAdd() may often different. // THIS IS IN THE PERFORMANCE CRITICAL PATH. void ImGui::ItemSize(const ImVec2& size, float text_baseline_y) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (window->SkipItems) return; // We increase the height in this function to accommodate for baseline offset. // In theory we should be offsetting the starting position (window->DC.CursorPos), that will be the topic of a larger refactor, // but since ItemSize() is not yet an API that moves the cursor (to handle e.g. wrapping) enlarging the height has the same effect. const float offset_to_match_baseline_y = (text_baseline_y >= 0) ? ImMax(0.0f, window->DC.CurrLineTextBaseOffset - text_baseline_y) : 0.0f; const float line_y1 = window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y; const float line_height = ImMax(window->DC.CurrLineSize.y, /*ImMax(*/window->DC.CursorPos.y - line_y1/*, 0.0f)*/ + size.y + offset_to_match_baseline_y); // Always align ourselves on pixel boundaries //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG] window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x; window->DC.CursorPosPrevLine.y = line_y1; window->DC.CursorPos.x = IM_TRUNC(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); // Next line window->DC.CursorPos.y = IM_TRUNC(line_y1 + line_height + g.Style.ItemSpacing.y); // Next line window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x); window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y); //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG] window->DC.PrevLineSize.y = line_height; window->DC.CurrLineSize.y = 0.0f; window->DC.PrevLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, text_baseline_y); window->DC.CurrLineTextBaseOffset = 0.0f; window->DC.IsSameLine = window->DC.IsSetPos = false; // Horizontal layout mode if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) SameLine(); } // Gets back to previous line and continue with horizontal layout // offset_from_start_x == 0 : follow right after previous item // offset_from_start_x != 0 : align to specified x position (relative to window/group left) // spacing_w < 0 : use default spacing if offset_from_start_x == 0, no spacing if offset_from_start_x != 0 // spacing_w >= 0 : enforce spacing amount void ImGui::SameLine(float offset_from_start_x, float spacing_w) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (window->SkipItems) return; if (offset_from_start_x != 0.0f) { if (spacing_w < 0.0f) spacing_w = 0.0f; window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + offset_from_start_x + spacing_w + window->DC.GroupOffset.x + window->DC.ColumnsOffset.x; window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y; } else { if (spacing_w < 0.0f) spacing_w = g.Style.ItemSpacing.x; window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w; window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y; } window->DC.CurrLineSize = window->DC.PrevLineSize; window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset; window->DC.IsSameLine = true; } ImVec2 ImGui::GetCursorScreenPos() { ImGuiWindow* window = GetCurrentWindowRead(); return window->DC.CursorPos; } void ImGui::SetCursorScreenPos(const ImVec2& pos) { ImGuiWindow* window = GetCurrentWindow(); window->DC.CursorPos = pos; //window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos); window->DC.IsSetPos = true; } // User generally sees positions in window coordinates. Internally we store CursorPos in absolute screen coordinates because it is more convenient. // Conversion happens as we pass the value to user, but it makes our naming convention confusing because GetCursorPos() == (DC.CursorPos - window.Pos). May want to rename 'DC.CursorPos'. ImVec2 ImGui::GetCursorPos() { ImGuiWindow* window = GetCurrentWindowRead(); return window->DC.CursorPos - window->Pos + window->Scroll; } float ImGui::GetCursorPosX() { ImGuiWindow* window = GetCurrentWindowRead(); return window->DC.CursorPos.x - window->Pos.x + window->Scroll.x; } float ImGui::GetCursorPosY() { ImGuiWindow* window = GetCurrentWindowRead(); return window->DC.CursorPos.y - window->Pos.y + window->Scroll.y; } void ImGui::SetCursorPos(const ImVec2& local_pos) { ImGuiWindow* window = GetCurrentWindow(); window->DC.CursorPos = window->Pos - window->Scroll + local_pos; //window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos); window->DC.IsSetPos = true; } void ImGui::SetCursorPosX(float x) { ImGuiWindow* window = GetCurrentWindow(); window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x; //window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPos.x); window->DC.IsSetPos = true; } void ImGui::SetCursorPosY(float y) { ImGuiWindow* window = GetCurrentWindow(); window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y; //window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y); window->DC.IsSetPos = true; } ImVec2 ImGui::GetCursorStartPos() { ImGuiWindow* window = GetCurrentWindowRead(); return window->DC.CursorStartPos - window->Pos; } void ImGui::Indent(float indent_w) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); window->DC.Indent.x += (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing; window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x; } void ImGui::Unindent(float indent_w) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); window->DC.Indent.x -= (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing; window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x; } // Affect large frame+labels widgets only. void ImGui::SetNextItemWidth(float item_width) { ImGuiContext& g = *GImGui; g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasWidth; g.NextItemData.Width = item_width; } // FIXME: Remove the == 0.0f behavior? void ImGui::PushItemWidth(float item_width) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; window->DC.ItemWidthStack.push_back(window->DC.ItemWidth); // Backup current width window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width); g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth; } void ImGui::PushMultiItemsWidths(int components, float w_full) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(components > 0); const ImGuiStyle& style = g.Style; window->DC.ItemWidthStack.push_back(window->DC.ItemWidth); // Backup current width float w_items = w_full - style.ItemInnerSpacing.x * (components - 1); float prev_split = w_items; for (int i = components - 1; i > 0; i--) { float next_split = IM_TRUNC(w_items * i / components); window->DC.ItemWidthStack.push_back(ImMax(prev_split - next_split, 1.0f)); prev_split = next_split; } window->DC.ItemWidth = ImMax(prev_split, 1.0f); g.NextItemData.Flags &= ~ImGuiNextItemDataFlags_HasWidth; } void ImGui::PopItemWidth() { ImGuiWindow* window = GetCurrentWindow(); window->DC.ItemWidth = window->DC.ItemWidthStack.back(); window->DC.ItemWidthStack.pop_back(); } // Calculate default item width given value passed to PushItemWidth() or SetNextItemWidth(). // The SetNextItemWidth() data is generally cleared/consumed by ItemAdd() or NextItemData.ClearFlags() float ImGui::CalcItemWidth() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; float w; if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasWidth) w = g.NextItemData.Width; else w = window->DC.ItemWidth; if (w < 0.0f) { float region_max_x = GetContentRegionMaxAbs().x; w = ImMax(1.0f, region_max_x - window->DC.CursorPos.x + w); } w = IM_TRUNC(w); return w; } // [Internal] Calculate full item size given user provided 'size' parameter and default width/height. Default width is often == CalcItemWidth(). // Those two functions CalcItemWidth vs CalcItemSize are awkwardly named because they are not fully symmetrical. // Note that only CalcItemWidth() is publicly exposed. // The 4.0f here may be changed to match CalcItemWidth() and/or BeginChild() (right now we have a mismatch which is harmless but undesirable) ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_w, float default_h) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImVec2 region_max; if (size.x < 0.0f || size.y < 0.0f) region_max = GetContentRegionMaxAbs(); if (size.x == 0.0f) size.x = default_w; else if (size.x < 0.0f) size.x = ImMax(4.0f, region_max.x - window->DC.CursorPos.x + size.x); if (size.y == 0.0f) size.y = default_h; else if (size.y < 0.0f) size.y = ImMax(4.0f, region_max.y - window->DC.CursorPos.y + size.y); return size; } float ImGui::GetTextLineHeight() { ImGuiContext& g = *GImGui; return g.FontSize; } float ImGui::GetTextLineHeightWithSpacing() { ImGuiContext& g = *GImGui; return g.FontSize + g.Style.ItemSpacing.y; } float ImGui::GetFrameHeight() { ImGuiContext& g = *GImGui; return g.FontSize + g.Style.FramePadding.y * 2.0f; } float ImGui::GetFrameHeightWithSpacing() { ImGuiContext& g = *GImGui; return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y; } // FIXME: All the Contents Region function are messy or misleading. WE WILL AIM TO OBSOLETE ALL OF THEM WITH A NEW "WORK RECT" API. Thanks for your patience! // FIXME: This is in window space (not screen space!). ImVec2 ImGui::GetContentRegionMax() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImVec2 mx = (window->DC.CurrentColumns || g.CurrentTable) ? window->WorkRect.Max : window->ContentRegionRect.Max; return mx - window->Pos; } // [Internal] Absolute coordinate. Saner. This is not exposed until we finishing refactoring work rect features. ImVec2 ImGui::GetContentRegionMaxAbs() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImVec2 mx = (window->DC.CurrentColumns || g.CurrentTable) ? window->WorkRect.Max : window->ContentRegionRect.Max; return mx; } ImVec2 ImGui::GetContentRegionAvail() { ImGuiWindow* window = GImGui->CurrentWindow; return GetContentRegionMaxAbs() - window->DC.CursorPos; } // In window space (not screen space!) ImVec2 ImGui::GetWindowContentRegionMin() { ImGuiWindow* window = GImGui->CurrentWindow; return window->ContentRegionRect.Min - window->Pos; } ImVec2 ImGui::GetWindowContentRegionMax() { ImGuiWindow* window = GImGui->CurrentWindow; return window->ContentRegionRect.Max - window->Pos; } // Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) // Groups are currently a mishmash of functionalities which should perhaps be clarified and separated. // FIXME-OPT: Could we safely early out on ->SkipItems? void ImGui::BeginGroup() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; g.GroupStack.resize(g.GroupStack.Size + 1); ImGuiGroupData& group_data = g.GroupStack.back(); group_data.WindowID = window->ID; group_data.BackupCursorPos = window->DC.CursorPos; group_data.BackupCursorPosPrevLine = window->DC.CursorPosPrevLine; group_data.BackupCursorMaxPos = window->DC.CursorMaxPos; group_data.BackupIndent = window->DC.Indent; group_data.BackupGroupOffset = window->DC.GroupOffset; group_data.BackupCurrLineSize = window->DC.CurrLineSize; group_data.BackupCurrLineTextBaseOffset = window->DC.CurrLineTextBaseOffset; group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive; group_data.BackupHoveredIdIsAlive = g.HoveredId != 0; group_data.BackupIsSameLine = window->DC.IsSameLine; group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive; group_data.EmitItem = true; window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x; window->DC.Indent = window->DC.GroupOffset; window->DC.CursorMaxPos = window->DC.CursorPos; window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); if (g.LogEnabled) g.LogLinePosY = -FLT_MAX; // To enforce a carriage return } void ImGui::EndGroup() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(g.GroupStack.Size > 0); // Mismatched BeginGroup()/EndGroup() calls ImGuiGroupData& group_data = g.GroupStack.back(); IM_ASSERT(group_data.WindowID == window->ID); // EndGroup() in wrong window? if (window->DC.IsSetPos) ErrorCheckUsingSetCursorPosToExtendParentBoundaries(); ImRect group_bb(group_data.BackupCursorPos, ImMax(window->DC.CursorMaxPos, group_data.BackupCursorPos)); window->DC.CursorPos = group_data.BackupCursorPos; window->DC.CursorPosPrevLine = group_data.BackupCursorPosPrevLine; window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos); window->DC.Indent = group_data.BackupIndent; window->DC.GroupOffset = group_data.BackupGroupOffset; window->DC.CurrLineSize = group_data.BackupCurrLineSize; window->DC.CurrLineTextBaseOffset = group_data.BackupCurrLineTextBaseOffset; window->DC.IsSameLine = group_data.BackupIsSameLine; if (g.LogEnabled) g.LogLinePosY = -FLT_MAX; // To enforce a carriage return if (!group_data.EmitItem) { g.GroupStack.pop_back(); return; } window->DC.CurrLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now. ItemSize(group_bb.GetSize()); ItemAdd(group_bb, 0, NULL, ImGuiItemFlags_NoTabStop); // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive(), IsItemDeactivated() etc. will be functional on the entire group. // It would be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but would put a little more burden on individual widgets. // Also if you grep for LastItemId you'll notice it is only used in that context. // (The two tests not the same because ActiveIdIsAlive is an ID itself, in order to be able to handle ActiveId being overwritten during the frame.) const bool group_contains_curr_active_id = (group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId; const bool group_contains_prev_active_id = (group_data.BackupActiveIdPreviousFrameIsAlive == false) && (g.ActiveIdPreviousFrameIsAlive == true); if (group_contains_curr_active_id) g.LastItemData.ID = g.ActiveId; else if (group_contains_prev_active_id) g.LastItemData.ID = g.ActiveIdPreviousFrame; g.LastItemData.Rect = group_bb; // Forward Hovered flag const bool group_contains_curr_hovered_id = (group_data.BackupHoveredIdIsAlive == false) && g.HoveredId != 0; if (group_contains_curr_hovered_id) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow; // Forward Edited flag if (group_contains_curr_active_id && g.ActiveIdHasBeenEditedThisFrame) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited; // Forward Deactivated flag g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDeactivated; if (group_contains_prev_active_id && g.ActiveId != g.ActiveIdPreviousFrame) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Deactivated; g.GroupStack.pop_back(); if (g.DebugShowGroupRects) window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // [Debug] } //----------------------------------------------------------------------------- // [SECTION] SCROLLING //----------------------------------------------------------------------------- // Helper to snap on edges when aiming at an item very close to the edge, // So the difference between WindowPadding and ItemSpacing will be in the visible area after scrolling. // When we refactor the scrolling API this may be configurable with a flag? // Note that the effect for this won't be visible on X axis with default Style settings as WindowPadding.x == ItemSpacing.x by default. static float CalcScrollEdgeSnap(float target, float snap_min, float snap_max, float snap_threshold, float center_ratio) { if (target <= snap_min + snap_threshold) return ImLerp(snap_min, target, center_ratio); if (target >= snap_max - snap_threshold) return ImLerp(target, snap_max, center_ratio); return target; } static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window) { ImVec2 scroll = window->Scroll; ImVec2 decoration_size(window->DecoOuterSizeX1 + window->DecoInnerSizeX1 + window->DecoOuterSizeX2, window->DecoOuterSizeY1 + window->DecoInnerSizeY1 + window->DecoOuterSizeY2); for (int axis = 0; axis < 2; axis++) { if (window->ScrollTarget[axis] < FLT_MAX) { float center_ratio = window->ScrollTargetCenterRatio[axis]; float scroll_target = window->ScrollTarget[axis]; if (window->ScrollTargetEdgeSnapDist[axis] > 0.0f) { float snap_min = 0.0f; float snap_max = window->ScrollMax[axis] + window->SizeFull[axis] - decoration_size[axis]; scroll_target = CalcScrollEdgeSnap(scroll_target, snap_min, snap_max, window->ScrollTargetEdgeSnapDist[axis], center_ratio); } scroll[axis] = scroll_target - center_ratio * (window->SizeFull[axis] - decoration_size[axis]); } scroll[axis] = IM_ROUND(ImMax(scroll[axis], 0.0f)); if (!window->Collapsed && !window->SkipItems) scroll[axis] = ImMin(scroll[axis], window->ScrollMax[axis]); } return scroll; } void ImGui::ScrollToItem(ImGuiScrollFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ScrollToRectEx(window, g.LastItemData.NavRect, flags); } void ImGui::ScrollToRect(ImGuiWindow* window, const ImRect& item_rect, ImGuiScrollFlags flags) { ScrollToRectEx(window, item_rect, flags); } // Scroll to keep newly navigated item fully into view ImVec2 ImGui::ScrollToRectEx(ImGuiWindow* window, const ImRect& item_rect, ImGuiScrollFlags flags) { ImGuiContext& g = *GImGui; ImRect scroll_rect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1)); scroll_rect.Min.x = ImMin(scroll_rect.Min.x + window->DecoInnerSizeX1, scroll_rect.Max.x); scroll_rect.Min.y = ImMin(scroll_rect.Min.y + window->DecoInnerSizeY1, scroll_rect.Max.y); //GetForegroundDrawList(window)->AddRect(item_rect.Min, item_rect.Max, IM_COL32(255,0,0,255), 0.0f, 0, 5.0f); // [DEBUG] //GetForegroundDrawList(window)->AddRect(scroll_rect.Min, scroll_rect.Max, IM_COL32_WHITE); // [DEBUG] // Check that only one behavior is selected per axis IM_ASSERT((flags & ImGuiScrollFlags_MaskX_) == 0 || ImIsPowerOfTwo(flags & ImGuiScrollFlags_MaskX_)); IM_ASSERT((flags & ImGuiScrollFlags_MaskY_) == 0 || ImIsPowerOfTwo(flags & ImGuiScrollFlags_MaskY_)); // Defaults ImGuiScrollFlags in_flags = flags; if ((flags & ImGuiScrollFlags_MaskX_) == 0 && window->ScrollbarX) flags |= ImGuiScrollFlags_KeepVisibleEdgeX; if ((flags & ImGuiScrollFlags_MaskY_) == 0) flags |= window->Appearing ? ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeY; const bool fully_visible_x = item_rect.Min.x >= scroll_rect.Min.x && item_rect.Max.x <= scroll_rect.Max.x; const bool fully_visible_y = item_rect.Min.y >= scroll_rect.Min.y && item_rect.Max.y <= scroll_rect.Max.y; const bool can_be_fully_visible_x = (item_rect.GetWidth() + g.Style.ItemSpacing.x * 2.0f) <= scroll_rect.GetWidth() || (window->AutoFitFramesX > 0) || (window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0; const bool can_be_fully_visible_y = (item_rect.GetHeight() + g.Style.ItemSpacing.y * 2.0f) <= scroll_rect.GetHeight() || (window->AutoFitFramesY > 0) || (window->Flags & ImGuiWindowFlags_AlwaysAutoResize) != 0; if ((flags & ImGuiScrollFlags_KeepVisibleEdgeX) && !fully_visible_x) { if (item_rect.Min.x < scroll_rect.Min.x || !can_be_fully_visible_x) SetScrollFromPosX(window, item_rect.Min.x - g.Style.ItemSpacing.x - window->Pos.x, 0.0f); else if (item_rect.Max.x >= scroll_rect.Max.x) SetScrollFromPosX(window, item_rect.Max.x + g.Style.ItemSpacing.x - window->Pos.x, 1.0f); } else if (((flags & ImGuiScrollFlags_KeepVisibleCenterX) && !fully_visible_x) || (flags & ImGuiScrollFlags_AlwaysCenterX)) { if (can_be_fully_visible_x) SetScrollFromPosX(window, ImTrunc((item_rect.Min.x + item_rect.Max.x) * 0.5f) - window->Pos.x, 0.5f); else SetScrollFromPosX(window, item_rect.Min.x - window->Pos.x, 0.0f); } if ((flags & ImGuiScrollFlags_KeepVisibleEdgeY) && !fully_visible_y) { if (item_rect.Min.y < scroll_rect.Min.y || !can_be_fully_visible_y) SetScrollFromPosY(window, item_rect.Min.y - g.Style.ItemSpacing.y - window->Pos.y, 0.0f); else if (item_rect.Max.y >= scroll_rect.Max.y) SetScrollFromPosY(window, item_rect.Max.y + g.Style.ItemSpacing.y - window->Pos.y, 1.0f); } else if (((flags & ImGuiScrollFlags_KeepVisibleCenterY) && !fully_visible_y) || (flags & ImGuiScrollFlags_AlwaysCenterY)) { if (can_be_fully_visible_y) SetScrollFromPosY(window, ImTrunc((item_rect.Min.y + item_rect.Max.y) * 0.5f) - window->Pos.y, 0.5f); else SetScrollFromPosY(window, item_rect.Min.y - window->Pos.y, 0.0f); } ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window); ImVec2 delta_scroll = next_scroll - window->Scroll; // Also scroll parent window to keep us into view if necessary if (!(flags & ImGuiScrollFlags_NoScrollParent) && (window->Flags & ImGuiWindowFlags_ChildWindow)) { // FIXME-SCROLL: May be an option? if ((in_flags & (ImGuiScrollFlags_AlwaysCenterX | ImGuiScrollFlags_KeepVisibleCenterX)) != 0) in_flags = (in_flags & ~ImGuiScrollFlags_MaskX_) | ImGuiScrollFlags_KeepVisibleEdgeX; if ((in_flags & (ImGuiScrollFlags_AlwaysCenterY | ImGuiScrollFlags_KeepVisibleCenterY)) != 0) in_flags = (in_flags & ~ImGuiScrollFlags_MaskY_) | ImGuiScrollFlags_KeepVisibleEdgeY; delta_scroll += ScrollToRectEx(window->ParentWindow, ImRect(item_rect.Min - delta_scroll, item_rect.Max - delta_scroll), in_flags); } return delta_scroll; } float ImGui::GetScrollX() { ImGuiWindow* window = GImGui->CurrentWindow; return window->Scroll.x; } float ImGui::GetScrollY() { ImGuiWindow* window = GImGui->CurrentWindow; return window->Scroll.y; } float ImGui::GetScrollMaxX() { ImGuiWindow* window = GImGui->CurrentWindow; return window->ScrollMax.x; } float ImGui::GetScrollMaxY() { ImGuiWindow* window = GImGui->CurrentWindow; return window->ScrollMax.y; } void ImGui::SetScrollX(ImGuiWindow* window, float scroll_x) { window->ScrollTarget.x = scroll_x; window->ScrollTargetCenterRatio.x = 0.0f; window->ScrollTargetEdgeSnapDist.x = 0.0f; } void ImGui::SetScrollY(ImGuiWindow* window, float scroll_y) { window->ScrollTarget.y = scroll_y; window->ScrollTargetCenterRatio.y = 0.0f; window->ScrollTargetEdgeSnapDist.y = 0.0f; } void ImGui::SetScrollX(float scroll_x) { ImGuiContext& g = *GImGui; SetScrollX(g.CurrentWindow, scroll_x); } void ImGui::SetScrollY(float scroll_y) { ImGuiContext& g = *GImGui; SetScrollY(g.CurrentWindow, scroll_y); } // Note that a local position will vary depending on initial scroll value, // This is a little bit confusing so bear with us: // - local_pos = (absolution_pos - window->Pos) // - So local_x/local_y are 0.0f for a position at the upper-left corner of a window, // and generally local_x/local_y are >(padding+decoration) && <(size-padding-decoration) when in the visible area. // - They mostly exist because of legacy API. // Following the rules above, when trying to work with scrolling code, consider that: // - SetScrollFromPosY(0.0f) == SetScrollY(0.0f + scroll.y) == has no effect! // - SetScrollFromPosY(-scroll.y) == SetScrollY(-scroll.y + scroll.y) == SetScrollY(0.0f) == reset scroll. Of course writing SetScrollY(0.0f) directly then makes more sense // We store a target position so centering and clamping can occur on the next frame when we are guaranteed to have a known window size void ImGui::SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio) { IM_ASSERT(center_x_ratio >= 0.0f && center_x_ratio <= 1.0f); window->ScrollTarget.x = IM_TRUNC(local_x - window->DecoOuterSizeX1 - window->DecoInnerSizeX1 + window->Scroll.x); // Convert local position to scroll offset window->ScrollTargetCenterRatio.x = center_x_ratio; window->ScrollTargetEdgeSnapDist.x = 0.0f; } void ImGui::SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio) { IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); window->ScrollTarget.y = IM_TRUNC(local_y - window->DecoOuterSizeY1 - window->DecoInnerSizeY1 + window->Scroll.y); // Convert local position to scroll offset window->ScrollTargetCenterRatio.y = center_y_ratio; window->ScrollTargetEdgeSnapDist.y = 0.0f; } void ImGui::SetScrollFromPosX(float local_x, float center_x_ratio) { ImGuiContext& g = *GImGui; SetScrollFromPosX(g.CurrentWindow, local_x, center_x_ratio); } void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio) { ImGuiContext& g = *GImGui; SetScrollFromPosY(g.CurrentWindow, local_y, center_y_ratio); } // center_x_ratio: 0.0f left of last item, 0.5f horizontal center of last item, 1.0f right of last item. void ImGui::SetScrollHereX(float center_x_ratio) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; float spacing_x = ImMax(window->WindowPadding.x, g.Style.ItemSpacing.x); float target_pos_x = ImLerp(g.LastItemData.Rect.Min.x - spacing_x, g.LastItemData.Rect.Max.x + spacing_x, center_x_ratio); SetScrollFromPosX(window, target_pos_x - window->Pos.x, center_x_ratio); // Convert from absolute to local pos // Tweak: snap on edges when aiming at an item very close to the edge window->ScrollTargetEdgeSnapDist.x = ImMax(0.0f, window->WindowPadding.x - spacing_x); } // center_y_ratio: 0.0f top of last item, 0.5f vertical center of last item, 1.0f bottom of last item. void ImGui::SetScrollHereY(float center_y_ratio) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; float spacing_y = ImMax(window->WindowPadding.y, g.Style.ItemSpacing.y); float target_pos_y = ImLerp(window->DC.CursorPosPrevLine.y - spacing_y, window->DC.CursorPosPrevLine.y + window->DC.PrevLineSize.y + spacing_y, center_y_ratio); SetScrollFromPosY(window, target_pos_y - window->Pos.y, center_y_ratio); // Convert from absolute to local pos // Tweak: snap on edges when aiming at an item very close to the edge window->ScrollTargetEdgeSnapDist.y = ImMax(0.0f, window->WindowPadding.y - spacing_y); } //----------------------------------------------------------------------------- // [SECTION] TOOLTIPS //----------------------------------------------------------------------------- bool ImGui::BeginTooltip() { return BeginTooltipEx(ImGuiTooltipFlags_None, ImGuiWindowFlags_None); } bool ImGui::BeginItemTooltip() { if (!IsItemHovered(ImGuiHoveredFlags_ForTooltip)) return false; return BeginTooltipEx(ImGuiTooltipFlags_None, ImGuiWindowFlags_None); } bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags) { ImGuiContext& g = *GImGui; if (g.DragDropWithinSource || g.DragDropWithinTarget) { // Drag and Drop tooltips are positioning differently than other tooltips: // - offset visibility to increase visibility around mouse. // - never clamp within outer viewport boundary. // We call SetNextWindowPos() to enforce position and disable clamping. // See FindBestWindowPosForPopup() for positionning logic of other tooltips (not drag and drop ones). //ImVec2 tooltip_pos = g.IO.MousePos - g.ActiveIdClickOffset - g.Style.WindowPadding; ImVec2 tooltip_pos = g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET * g.Style.MouseCursorScale; SetNextWindowPos(tooltip_pos); SetNextWindowBgAlpha(g.Style.Colors[ImGuiCol_PopupBg].w * 0.60f); //PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * 0.60f); // This would be nice but e.g ColorButton with checkboard has issue with transparent colors :( tooltip_flags |= ImGuiTooltipFlags_OverridePrevious; } char window_name[16]; ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", g.TooltipOverrideCount); if (tooltip_flags & ImGuiTooltipFlags_OverridePrevious) if (ImGuiWindow* window = FindWindowByName(window_name)) if (window->Active) { // Hide previous tooltip from being displayed. We can't easily "reset" the content of a window so we create a new one. SetWindowHiddenAndSkipItemsForCurrentFrame(window); ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount); } ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize; Begin(window_name, NULL, flags | extra_window_flags); // 2023-03-09: Added bool return value to the API, but currently always returning true. // If this ever returns false we need to update BeginDragDropSource() accordingly. //if (!ret) // End(); //return ret; return true; } void ImGui::EndTooltip() { IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip); // Mismatched BeginTooltip()/EndTooltip() calls End(); } void ImGui::SetTooltip(const char* fmt, ...) { va_list args; va_start(args, fmt); SetTooltipV(fmt, args); va_end(args); } void ImGui::SetTooltipV(const char* fmt, va_list args) { if (!BeginTooltipEx(ImGuiTooltipFlags_OverridePrevious, ImGuiWindowFlags_None)) return; TextV(fmt, args); EndTooltip(); } // Shortcut to use 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav'. // Defaults to == ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort when using the mouse. void ImGui::SetItemTooltip(const char* fmt, ...) { va_list args; va_start(args, fmt); if (IsItemHovered(ImGuiHoveredFlags_ForTooltip)) SetTooltipV(fmt, args); va_end(args); } void ImGui::SetItemTooltipV(const char* fmt, va_list args) { if (IsItemHovered(ImGuiHoveredFlags_ForTooltip)) SetTooltipV(fmt, args); } //----------------------------------------------------------------------------- // [SECTION] POPUPS //----------------------------------------------------------------------------- // Supported flags: ImGuiPopupFlags_AnyPopupId, ImGuiPopupFlags_AnyPopupLevel bool ImGui::IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; if (popup_flags & ImGuiPopupFlags_AnyPopupId) { // Return true if any popup is open at the current BeginPopup() level of the popup stack // This may be used to e.g. test for another popups already opened to handle popups priorities at the same level. IM_ASSERT(id == 0); if (popup_flags & ImGuiPopupFlags_AnyPopupLevel) return g.OpenPopupStack.Size > 0; else return g.OpenPopupStack.Size > g.BeginPopupStack.Size; } else { if (popup_flags & ImGuiPopupFlags_AnyPopupLevel) { // Return true if the popup is open anywhere in the popup stack for (int n = 0; n < g.OpenPopupStack.Size; n++) if (g.OpenPopupStack[n].PopupId == id) return true; return false; } else { // Return true if the popup is open at the current BeginPopup() level of the popup stack (this is the most-common query) return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == id; } } } bool ImGui::IsPopupOpen(const char* str_id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; ImGuiID id = (popup_flags & ImGuiPopupFlags_AnyPopupId) ? 0 : g.CurrentWindow->GetID(str_id); if ((popup_flags & ImGuiPopupFlags_AnyPopupLevel) && id != 0) IM_ASSERT(0 && "Cannot use IsPopupOpen() with a string id and ImGuiPopupFlags_AnyPopupLevel."); // But non-string version is legal and used internally return IsPopupOpen(id, popup_flags); } // Also see FindBlockingModal(NULL) ImGuiWindow* ImGui::GetTopMostPopupModal() { ImGuiContext& g = *GImGui; for (int n = g.OpenPopupStack.Size - 1; n >= 0; n--) if (ImGuiWindow* popup = g.OpenPopupStack.Data[n].Window) if (popup->Flags & ImGuiWindowFlags_Modal) return popup; return NULL; } // See Demo->Stacked Modal to confirm what this is for. ImGuiWindow* ImGui::GetTopMostAndVisiblePopupModal() { ImGuiContext& g = *GImGui; for (int n = g.OpenPopupStack.Size - 1; n >= 0; n--) if (ImGuiWindow* popup = g.OpenPopupStack.Data[n].Window) if ((popup->Flags & ImGuiWindowFlags_Modal) && IsWindowActiveAndVisible(popup)) return popup; return NULL; } void ImGui::OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; ImGuiID id = g.CurrentWindow->GetID(str_id); IMGUI_DEBUG_LOG_POPUP("[popup] OpenPopup(\"%s\" -> 0x%08X)\n", str_id, id); OpenPopupEx(id, popup_flags); } void ImGui::OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags) { OpenPopupEx(id, popup_flags); } // Mark popup as open (toggle toward open state). // Popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. // Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). // One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL) void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; ImGuiWindow* parent_window = g.CurrentWindow; const int current_stack_size = g.BeginPopupStack.Size; if (popup_flags & ImGuiPopupFlags_NoOpenOverExistingPopup) if (IsPopupOpen((ImGuiID)0, ImGuiPopupFlags_AnyPopupId)) return; ImGuiPopupData popup_ref; // Tagged as new ref as Window will be set back to NULL if we write this into OpenPopupStack. popup_ref.PopupId = id; popup_ref.Window = NULL; popup_ref.BackupNavWindow = g.NavWindow; // When popup closes focus may be restored to NavWindow (depend on window type). popup_ref.OpenFrameCount = g.FrameCount; popup_ref.OpenParentId = parent_window->IDStack.back(); popup_ref.OpenPopupPos = NavCalcPreferredRefPos(); popup_ref.OpenMousePos = IsMousePosValid(&g.IO.MousePos) ? g.IO.MousePos : popup_ref.OpenPopupPos; IMGUI_DEBUG_LOG_POPUP("[popup] OpenPopupEx(0x%08X)\n", id); if (g.OpenPopupStack.Size < current_stack_size + 1) { g.OpenPopupStack.push_back(popup_ref); } else { // Gently handle the user mistakenly calling OpenPopup() every frames: it is likely a programming mistake! // However, if we were to run the regular code path, the ui would become completely unusable because the popup will always be // in hidden-while-calculating-size state _while_ claiming focus. Which is extremely confusing situation for the programmer. // Instead, for successive frames calls to OpenPopup(), we silently avoid reopening even if ImGuiPopupFlags_NoReopen is not specified. bool keep_existing = false; if (g.OpenPopupStack[current_stack_size].PopupId == id) if ((g.OpenPopupStack[current_stack_size].OpenFrameCount == g.FrameCount - 1) || (popup_flags & ImGuiPopupFlags_NoReopen)) keep_existing = true; if (keep_existing) { // No reopen g.OpenPopupStack[current_stack_size].OpenFrameCount = popup_ref.OpenFrameCount; } else { // Reopen: close child popups if any, then flag popup for open/reopen (set position, focus, init navigation) ClosePopupToLevel(current_stack_size, false); g.OpenPopupStack.push_back(popup_ref); } // When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by ClosePopupsOverWindow(). // This is equivalent to what ClosePopupToLevel() does. //if (g.OpenPopupStack[current_stack_size].PopupId == id) // FocusWindow(parent_window); } } // When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it. // This function closes any popups that are over 'ref_window'. void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup) { ImGuiContext& g = *GImGui; if (g.OpenPopupStack.Size == 0) return; // Don't close our own child popup windows. int popup_count_to_keep = 0; if (ref_window) { // Find the highest popup which is a descendant of the reference window (generally reference window = NavWindow) for (; popup_count_to_keep < g.OpenPopupStack.Size; popup_count_to_keep++) { ImGuiPopupData& popup = g.OpenPopupStack[popup_count_to_keep]; if (!popup.Window) continue; IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0); // Trim the stack unless the popup is a direct parent of the reference window (the reference window is often the NavWindow) // - Clicking/Focusing Window2 won't close Popup1: // Window -> Popup1 -> Window2(Ref) // - Clicking/focusing Popup1 will close Popup2 and Popup3: // Window -> Popup1(Ref) -> Popup2 -> Popup3 // - Each popups may contain child windows, which is why we compare ->RootWindow! // Window -> Popup1 -> Popup1_Child -> Popup2 -> Popup2_Child // We step through every popup from bottom to top to validate their position relative to reference window. bool ref_window_is_descendent_of_popup = false; for (int n = popup_count_to_keep; n < g.OpenPopupStack.Size; n++) if (ImGuiWindow* popup_window = g.OpenPopupStack[n].Window) if (IsWindowWithinBeginStackOf(ref_window, popup_window)) { ref_window_is_descendent_of_popup = true; break; } if (!ref_window_is_descendent_of_popup) break; } } if (popup_count_to_keep < g.OpenPopupStack.Size) // This test is not required but it allows to set a convenient breakpoint on the statement below { IMGUI_DEBUG_LOG_POPUP("[popup] ClosePopupsOverWindow(\"%s\")\n", ref_window ? ref_window->Name : ""); ClosePopupToLevel(popup_count_to_keep, restore_focus_to_window_under_popup); } } void ImGui::ClosePopupsExceptModals() { ImGuiContext& g = *GImGui; int popup_count_to_keep; for (popup_count_to_keep = g.OpenPopupStack.Size; popup_count_to_keep > 0; popup_count_to_keep--) { ImGuiWindow* window = g.OpenPopupStack[popup_count_to_keep - 1].Window; if (!window || (window->Flags & ImGuiWindowFlags_Modal)) break; } if (popup_count_to_keep < g.OpenPopupStack.Size) // This test is not required but it allows to set a convenient breakpoint on the statement below ClosePopupToLevel(popup_count_to_keep, true); } void ImGui::ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup) { ImGuiContext& g = *GImGui; IMGUI_DEBUG_LOG_POPUP("[popup] ClosePopupToLevel(%d), restore_focus_to_window_under_popup=%d\n", remaining, restore_focus_to_window_under_popup); IM_ASSERT(remaining >= 0 && remaining < g.OpenPopupStack.Size); // Trim open popup stack ImGuiWindow* popup_window = g.OpenPopupStack[remaining].Window; ImGuiWindow* popup_backup_nav_window = g.OpenPopupStack[remaining].BackupNavWindow; g.OpenPopupStack.resize(remaining); if (restore_focus_to_window_under_popup) { ImGuiWindow* focus_window = (popup_window && popup_window->Flags & ImGuiWindowFlags_ChildMenu) ? popup_window->ParentWindow : popup_backup_nav_window; if (focus_window && !focus_window->WasActive && popup_window) FocusTopMostWindowUnderOne(popup_window, NULL, NULL, ImGuiFocusRequestFlags_RestoreFocusedChild); // Fallback else FocusWindow(focus_window, (g.NavLayer == ImGuiNavLayer_Main) ? ImGuiFocusRequestFlags_RestoreFocusedChild : ImGuiFocusRequestFlags_None); } } // Close the popup we have begin-ed into. void ImGui::CloseCurrentPopup() { ImGuiContext& g = *GImGui; int popup_idx = g.BeginPopupStack.Size - 1; if (popup_idx < 0 || popup_idx >= g.OpenPopupStack.Size || g.BeginPopupStack[popup_idx].PopupId != g.OpenPopupStack[popup_idx].PopupId) return; // Closing a menu closes its top-most parent popup (unless a modal) while (popup_idx > 0) { ImGuiWindow* popup_window = g.OpenPopupStack[popup_idx].Window; ImGuiWindow* parent_popup_window = g.OpenPopupStack[popup_idx - 1].Window; bool close_parent = false; if (popup_window && (popup_window->Flags & ImGuiWindowFlags_ChildMenu)) if (parent_popup_window && !(parent_popup_window->Flags & ImGuiWindowFlags_MenuBar)) close_parent = true; if (!close_parent) break; popup_idx--; } IMGUI_DEBUG_LOG_POPUP("[popup] CloseCurrentPopup %d -> %d\n", g.BeginPopupStack.Size - 1, popup_idx); ClosePopupToLevel(popup_idx, true); // A common pattern is to close a popup when selecting a menu item/selectable that will open another window. // To improve this usage pattern, we avoid nav highlight for a single frame in the parent window. // Similarly, we could avoid mouse hover highlight in this window but it is less visually problematic. if (ImGuiWindow* window = g.NavWindow) window->DC.NavHideHighlightOneFrame = true; } // Attention! BeginPopup() adds default flags which BeginPopupEx()! bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags flags) { ImGuiContext& g = *GImGui; if (!IsPopupOpen(id, ImGuiPopupFlags_None)) { g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values return false; } char name[20]; if (flags & ImGuiWindowFlags_ChildMenu) ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.BeginMenuDepth); // Recycle windows based on depth else ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame flags |= ImGuiWindowFlags_Popup; bool is_open = Begin(name, NULL, flags); if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display) EndPopup(); //g.CurrentWindow->FocusRouteParentWindow = g.CurrentWindow->ParentWindowInBeginStack; return is_open; } bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags) { ImGuiContext& g = *GImGui; if (g.OpenPopupStack.Size <= g.BeginPopupStack.Size) // Early out for performance { g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values return false; } flags |= ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings; ImGuiID id = g.CurrentWindow->GetID(str_id); return BeginPopupEx(id, flags); } // If 'p_open' is specified for a modal popup window, the popup will have a regular close button which will close the popup. // Note that popup visibility status is owned by Dear ImGui (and manipulated with e.g. OpenPopup). // - *p_open set back to false in BeginPopupModal() when popup is not open. // - if you set *p_open to false before calling BeginPopupModal(), it will close the popup. bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; const ImGuiID id = window->GetID(name); if (!IsPopupOpen(id, ImGuiPopupFlags_None)) { g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values if (p_open && *p_open) *p_open = false; return false; } // Center modal windows by default for increased visibility // (this won't really last as settings will kick in, and is mostly for backward compatibility. user may do the same themselves) // FIXME: Should test for (PosCond & window->SetWindowPosAllowFlags) with the upcoming window. if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0) { const ImGuiViewport* viewport = GetMainViewport(); SetNextWindowPos(viewport->GetCenter(), ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f)); } flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse; const bool is_open = Begin(name, p_open, flags); if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display) { EndPopup(); if (is_open) ClosePopupToLevel(g.BeginPopupStack.Size, true); return false; } return is_open; } void ImGui::EndPopup() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginPopup()/EndPopup() calls IM_ASSERT(g.BeginPopupStack.Size > 0); // Make all menus and popups wrap around for now, may need to expose that policy (e.g. focus scope could include wrap/loop policy flags used by new move requests) if (g.NavWindow == window) NavMoveRequestTryWrapping(window, ImGuiNavMoveFlags_LoopY); // Child-popups don't need to be laid out IM_ASSERT(g.WithinEndChild == false); if (window->Flags & ImGuiWindowFlags_ChildWindow) g.WithinEndChild = true; End(); g.WithinEndChild = false; } // Helper to open a popup if mouse button is released over the item // - This is essentially the same as BeginPopupContextItem() but without the trailing BeginPopup() void ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_); if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) { ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) OpenPopupEx(id, popup_flags); } } // This is a helper to handle the simplest case of associating one named popup to one given widget. // - To create a popup associated to the last item, you generally want to pass a NULL value to str_id. // - To create a popup with a specific identifier, pass it in str_id. // - This is useful when using using BeginPopupContextItem() on an item which doesn't have an identifier, e.g. a Text() call. // - This is useful when multiple code locations may want to manipulate/open the same popup, given an explicit id. // - You may want to handle the whole on user side if you have specific needs (e.g. tweaking IsItemHovered() parameters). // This is essentially the same as: // id = str_id ? GetID(str_id) : GetItemID(); // OpenPopupOnItemClick(str_id, ImGuiPopupFlags_MouseButtonRight); // return BeginPopup(id); // Which is essentially the same as: // id = str_id ? GetID(str_id) : GetItemID(); // if (IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right)) // OpenPopup(id); // return BeginPopup(id); // The main difference being that this is tweaked to avoid computing the ID twice. bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (window->SkipItems) return false; ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_); if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) OpenPopupEx(id, popup_flags); return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings); } bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (!str_id) str_id = "window_context"; ImGuiID id = window->GetID(str_id); int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_); if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered()) OpenPopupEx(id, popup_flags); return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings); } bool ImGui::BeginPopupContextVoid(const char* str_id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (!str_id) str_id = "void_context"; ImGuiID id = window->GetID(str_id); int mouse_button = (popup_flags & ImGuiPopupFlags_MouseButtonMask_); if (IsMouseReleased(mouse_button) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow)) if (GetTopMostPopupModal() == NULL) OpenPopupEx(id, popup_flags); return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings); } // r_avoid = the rectangle to avoid (e.g. for tooltip it is a rectangle around the mouse cursor which we want to avoid. for popups it's a small point around the cursor.) // r_outer = the visible area rectangle, minus safe area padding. If our popup size won't fit because of safe area padding we ignore it. // (r_outer is usually equivalent to the viewport rectangle minus padding, but when multi-viewports are enabled and monitor // information are available, it may represent the entire platform monitor from the frame of reference of the current viewport. // this allows us to have tooltips/popups displayed out of the parent viewport.) ImVec2 ImGui::FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy) { ImVec2 base_pos_clamped = ImClamp(ref_pos, r_outer.Min, r_outer.Max - size); //GetForegroundDrawList()->AddRect(r_avoid.Min, r_avoid.Max, IM_COL32(255,0,0,255)); //GetForegroundDrawList()->AddRect(r_outer.Min, r_outer.Max, IM_COL32(0,255,0,255)); // Combo Box policy (we want a connecting edge) if (policy == ImGuiPopupPositionPolicy_ComboBox) { const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Down, ImGuiDir_Right, ImGuiDir_Left, ImGuiDir_Up }; for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++) { const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n]; if (n != -1 && dir == *last_dir) // Already tried this direction? continue; ImVec2 pos; if (dir == ImGuiDir_Down) pos = ImVec2(r_avoid.Min.x, r_avoid.Max.y); // Below, Toward Right (default) if (dir == ImGuiDir_Right) pos = ImVec2(r_avoid.Min.x, r_avoid.Min.y - size.y); // Above, Toward Right if (dir == ImGuiDir_Left) pos = ImVec2(r_avoid.Max.x - size.x, r_avoid.Max.y); // Below, Toward Left if (dir == ImGuiDir_Up) pos = ImVec2(r_avoid.Max.x - size.x, r_avoid.Min.y - size.y); // Above, Toward Left if (!r_outer.Contains(ImRect(pos, pos + size))) continue; *last_dir = dir; return pos; } } // Tooltip and Default popup policy // (Always first try the direction we used on the last frame, if any) if (policy == ImGuiPopupPositionPolicy_Tooltip || policy == ImGuiPopupPositionPolicy_Default) { const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Right, ImGuiDir_Down, ImGuiDir_Up, ImGuiDir_Left }; for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++) { const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n]; if (n != -1 && dir == *last_dir) // Already tried this direction? continue; const float avail_w = (dir == ImGuiDir_Left ? r_avoid.Min.x : r_outer.Max.x) - (dir == ImGuiDir_Right ? r_avoid.Max.x : r_outer.Min.x); const float avail_h = (dir == ImGuiDir_Up ? r_avoid.Min.y : r_outer.Max.y) - (dir == ImGuiDir_Down ? r_avoid.Max.y : r_outer.Min.y); // If there's not enough room on one axis, there's no point in positioning on a side on this axis (e.g. when not enough width, use a top/bottom position to maximize available width) if (avail_w < size.x && (dir == ImGuiDir_Left || dir == ImGuiDir_Right)) continue; if (avail_h < size.y && (dir == ImGuiDir_Up || dir == ImGuiDir_Down)) continue; ImVec2 pos; pos.x = (dir == ImGuiDir_Left) ? r_avoid.Min.x - size.x : (dir == ImGuiDir_Right) ? r_avoid.Max.x : base_pos_clamped.x; pos.y = (dir == ImGuiDir_Up) ? r_avoid.Min.y - size.y : (dir == ImGuiDir_Down) ? r_avoid.Max.y : base_pos_clamped.y; // Clamp top-left corner of popup pos.x = ImMax(pos.x, r_outer.Min.x); pos.y = ImMax(pos.y, r_outer.Min.y); *last_dir = dir; return pos; } } // Fallback when not enough room: *last_dir = ImGuiDir_None; // For tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible. if (policy == ImGuiPopupPositionPolicy_Tooltip) return ref_pos + ImVec2(2, 2); // Otherwise try to keep within display ImVec2 pos = ref_pos; pos.x = ImMax(ImMin(pos.x + size.x, r_outer.Max.x) - size.x, r_outer.Min.x); pos.y = ImMax(ImMin(pos.y + size.y, r_outer.Max.y) - size.y, r_outer.Min.y); return pos; } // Note that this is used for popups, which can overlap the non work-area of individual viewports. ImRect ImGui::GetPopupAllowedExtentRect(ImGuiWindow* window) { ImGuiContext& g = *GImGui; IM_UNUSED(window); ImRect r_screen = ((ImGuiViewportP*)(void*)GetMainViewport())->GetMainRect(); ImVec2 padding = g.Style.DisplaySafeAreaPadding; r_screen.Expand(ImVec2((r_screen.GetWidth() > padding.x * 2) ? -padding.x : 0.0f, (r_screen.GetHeight() > padding.y * 2) ? -padding.y : 0.0f)); return r_screen; } ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window) { ImGuiContext& g = *GImGui; ImRect r_outer = GetPopupAllowedExtentRect(window); if (window->Flags & ImGuiWindowFlags_ChildMenu) { // Child menus typically request _any_ position within the parent menu item, and then we move the new menu outside the parent bounds. // This is how we end up with child menus appearing (most-commonly) on the right of the parent menu. IM_ASSERT(g.CurrentWindow == window); ImGuiWindow* parent_window = g.CurrentWindowStack[g.CurrentWindowStack.Size - 2].Window; float horizontal_overlap = g.Style.ItemInnerSpacing.x; // We want some overlap to convey the relative depth of each menu (currently the amount of overlap is hard-coded to style.ItemSpacing.x). ImRect r_avoid; if (parent_window->DC.MenuBarAppending) r_avoid = ImRect(-FLT_MAX, parent_window->ClipRect.Min.y, FLT_MAX, parent_window->ClipRect.Max.y); // Avoid parent menu-bar. If we wanted multi-line menu-bar, we may instead want to have the calling window setup e.g. a NextWindowData.PosConstraintAvoidRect field else r_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX); return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Default); } if (window->Flags & ImGuiWindowFlags_Popup) { return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, ImRect(window->Pos, window->Pos), ImGuiPopupPositionPolicy_Default); // Ideally we'd disable r_avoid here } if (window->Flags & ImGuiWindowFlags_Tooltip) { // Position tooltip (always follows mouse + clamp within outer boundaries) // Note that drag and drop tooltips are NOT using this path: BeginTooltipEx() manually sets their position. // In theory we could handle both cases in same location, but requires a bit of shuffling as drag and drop tooltips are calling SetWindowPos() leading to 'window_pos_set_by_api' being set in Begin() IM_ASSERT(g.CurrentWindow == window); const float scale = g.Style.MouseCursorScale; const ImVec2 ref_pos = NavCalcPreferredRefPos(); const ImVec2 tooltip_pos = ref_pos + TOOLTIP_DEFAULT_OFFSET * scale; ImRect r_avoid; if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos)) r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8); else r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * scale, ref_pos.y + 24 * scale); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important. //GetForegroundDrawList()->AddRect(r_avoid.Min, r_avoid.Max, IM_COL32(255, 0, 255, 255)); return FindBestWindowPosForPopupEx(tooltip_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Tooltip); } IM_ASSERT(0); return window->Pos; } //----------------------------------------------------------------------------- // [SECTION] KEYBOARD/GAMEPAD NAVIGATION //----------------------------------------------------------------------------- // FIXME-NAV: The existence of SetNavID vs SetFocusID vs FocusWindow() needs to be clarified/reworked. // In our terminology those should be interchangeable, yet right now this is super confusing. // Those two functions are merely a legacy artifact, so at minimum naming should be clarified. void ImGui::SetNavWindow(ImGuiWindow* window) { ImGuiContext& g = *GImGui; if (g.NavWindow != window) { IMGUI_DEBUG_LOG_FOCUS("[focus] SetNavWindow(\"%s\")\n", window ? window->Name : ""); g.NavWindow = window; g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid; } g.NavInitRequest = g.NavMoveSubmitted = g.NavMoveScoringItems = false; NavUpdateAnyRequestFlag(); } void ImGui::NavHighlightActivated(ImGuiID id) { ImGuiContext& g = *GImGui; g.NavHighlightActivatedId = id; g.NavHighlightActivatedTimer = NAV_ACTIVATE_HIGHLIGHT_TIMER; } void ImGui::NavClearPreferredPosForAxis(ImGuiAxis axis) { ImGuiContext& g = *GImGui; g.NavWindow->RootWindowForNav->NavPreferredScoringPosRel[g.NavLayer][axis] = FLT_MAX; } void ImGui::SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel) { ImGuiContext& g = *GImGui; IM_ASSERT(g.NavWindow != NULL); IM_ASSERT(nav_layer == ImGuiNavLayer_Main || nav_layer == ImGuiNavLayer_Menu); g.NavId = id; g.NavLayer = nav_layer; SetNavFocusScope(focus_scope_id); g.NavWindow->NavLastIds[nav_layer] = id; g.NavWindow->NavRectRel[nav_layer] = rect_rel; // Clear preferred scoring position (NavMoveRequestApplyResult() will tend to restore it) NavClearPreferredPosForAxis(ImGuiAxis_X); NavClearPreferredPosForAxis(ImGuiAxis_Y); } void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) { ImGuiContext& g = *GImGui; IM_ASSERT(id != 0); if (g.NavWindow != window) SetNavWindow(window); // Assume that SetFocusID() is called in the context where its window->DC.NavLayerCurrent and g.CurrentFocusScopeId are valid. // Note that window may be != g.CurrentWindow (e.g. SetFocusID call in InputTextEx for multi-line text) const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent; g.NavId = id; g.NavLayer = nav_layer; SetNavFocusScope(g.CurrentFocusScopeId); window->NavLastIds[nav_layer] = id; if (g.LastItemData.ID == id) window->NavRectRel[nav_layer] = WindowRectAbsToRel(window, g.LastItemData.NavRect); if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad) g.NavDisableMouseHover = true; else g.NavDisableHighlight = true; // Clear preferred scoring position (NavMoveRequestApplyResult() will tend to restore it) NavClearPreferredPosForAxis(ImGuiAxis_X); NavClearPreferredPosForAxis(ImGuiAxis_Y); } static ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy) { if (ImFabs(dx) > ImFabs(dy)) return (dx > 0.0f) ? ImGuiDir_Right : ImGuiDir_Left; return (dy > 0.0f) ? ImGuiDir_Down : ImGuiDir_Up; } static float inline NavScoreItemDistInterval(float cand_min, float cand_max, float curr_min, float curr_max) { if (cand_max < curr_min) return cand_max - curr_min; if (curr_max < cand_min) return cand_min - curr_max; return 0.0f; } // Scoring function for gamepad/keyboard directional navigation. Based on https://gist.github.com/rygorous/6981057 static bool ImGui::NavScoreItem(ImGuiNavItemData* result) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (g.NavLayer != window->DC.NavLayerCurrent) return false; // FIXME: Those are not good variables names ImRect cand = g.LastItemData.NavRect; // Current item nav rectangle const ImRect curr = g.NavScoringRect; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having varied item width) g.NavScoringDebugCount++; // When entering through a NavFlattened border, we consider child window items as fully clipped for scoring if (window->ParentWindow == g.NavWindow) { IM_ASSERT((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened); if (!window->ClipRect.Overlaps(cand)) return false; cand.ClipWithFull(window->ClipRect); // This allows the scored item to not overlap other candidates in the parent window } // Compute distance between boxes // FIXME-NAV: Introducing biases for vertical navigation, needs to be removed. float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x); float dby = NavScoreItemDistInterval(ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f), ImLerp(curr.Min.y, curr.Max.y, 0.2f), ImLerp(curr.Min.y, curr.Max.y, 0.8f)); // Scale down on Y to keep using box-distance for vertically touching items if (dby != 0.0f && dbx != 0.0f) dbx = (dbx / 1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f); float dist_box = ImFabs(dbx) + ImFabs(dby); // Compute distance between centers (this is off by a factor of 2, but we only compare center distances with each other so it doesn't matter) float dcx = (cand.Min.x + cand.Max.x) - (curr.Min.x + curr.Max.x); float dcy = (cand.Min.y + cand.Max.y) - (curr.Min.y + curr.Max.y); float dist_center = ImFabs(dcx) + ImFabs(dcy); // L1 metric (need this for our connectedness guarantee) // Determine which quadrant of 'curr' our candidate item 'cand' lies in based on distance ImGuiDir quadrant; float dax = 0.0f, day = 0.0f, dist_axial = 0.0f; if (dbx != 0.0f || dby != 0.0f) { // For non-overlapping boxes, use distance between boxes dax = dbx; day = dby; dist_axial = dist_box; quadrant = ImGetDirQuadrantFromDelta(dbx, dby); } else if (dcx != 0.0f || dcy != 0.0f) { // For overlapping boxes with different centers, use distance between centers dax = dcx; day = dcy; dist_axial = dist_center; quadrant = ImGetDirQuadrantFromDelta(dcx, dcy); } else { // Degenerate case: two overlapping buttons with same center, break ties arbitrarily (note that LastItemId here is really the _previous_ item order, but it doesn't matter) quadrant = (g.LastItemData.ID < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right; } const ImGuiDir move_dir = g.NavMoveDir; #if IMGUI_DEBUG_NAV_SCORING char buf[200]; if (g.IO.KeyCtrl) // Hold CTRL to preview score in matching quadrant. CTRL+Arrow to rotate. { if (quadrant == move_dir) { ImFormatString(buf, IM_ARRAYSIZE(buf), "%.0f/%.0f", dist_box, dist_center); ImDrawList* draw_list = GetForegroundDrawList(window); draw_list->AddRectFilled(cand.Min, cand.Max, IM_COL32(255, 0, 0, 80)); draw_list->AddRectFilled(cand.Min, cand.Min + CalcTextSize(buf), IM_COL32(255, 0, 0, 200)); draw_list->AddText(cand.Min, IM_COL32(255, 255, 255, 255), buf); } } const bool debug_hovering = IsMouseHoveringRect(cand.Min, cand.Max); const bool debug_tty = (g.IO.KeyCtrl && IsKeyPressed(ImGuiKey_Space)); if (debug_hovering || debug_tty) { ImFormatString(buf, IM_ARRAYSIZE(buf), "d-box (%7.3f,%7.3f) -> %7.3f\nd-center (%7.3f,%7.3f) -> %7.3f\nd-axial (%7.3f,%7.3f) -> %7.3f\nnav %c, quadrant %c", dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial, "-WENS"[move_dir+1], "-WENS"[quadrant+1]); if (debug_hovering) { ImDrawList* draw_list = GetForegroundDrawList(window); draw_list->AddRect(curr.Min, curr.Max, IM_COL32(255, 200, 0, 100)); draw_list->AddRect(cand.Min, cand.Max, IM_COL32(255, 255, 0, 200)); draw_list->AddRectFilled(cand.Max - ImVec2(4, 4), cand.Max + CalcTextSize(buf) + ImVec2(4, 4), IM_COL32(40, 0, 0, 200)); draw_list->AddText(cand.Max, ~0U, buf); } if (debug_tty) { IMGUI_DEBUG_LOG_NAV("id 0x%08X\n%s\n", g.LastItemData.ID, buf); } } #endif // Is it in the quadrant we're interested in moving to? bool new_best = false; if (quadrant == move_dir) { // Does it beat the current best candidate? if (dist_box < result->DistBox) { result->DistBox = dist_box; result->DistCenter = dist_center; return true; } if (dist_box == result->DistBox) { // Try using distance between center points to break ties if (dist_center < result->DistCenter) { result->DistCenter = dist_center; new_best = true; } else if (dist_center == result->DistCenter) { // Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" items // (with higher index) to the right/downwards by an infinitesimal amount since we the current "best" button already (so it must have a lower index), // this is fairly easy. This rule ensures that all buttons with dx==dy==0 will end up being linked in order of appearance along the x axis. if (((move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down) ? dby : dbx) < 0.0f) // moving bj to the right/down decreases distance new_best = true; } } } // Axial check: if 'curr' has no link at all in some direction and 'cand' lies roughly in that direction, add a tentative link. This will only be kept if no "real" matches // are found, so it only augments the graph produced by the above method using extra links. (important, since it doesn't guarantee strong connectedness) // This is just to avoid buttons having no links in a particular direction when there's a suitable neighbor. you get good graphs without this too. // 2017/09/29: FIXME: This now currently only enabled inside menu bars, ideally we'd disable it everywhere. Menus in particular need to catch failure. For general navigation it feels awkward. // Disabling it may lead to disconnected graphs when nodes are very spaced out on different axis. Perhaps consider offering this as an option? if (result->DistBox == FLT_MAX && dist_axial < result->DistAxial) // Check axial match if (g.NavLayer == ImGuiNavLayer_Menu && !(g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) if ((move_dir == ImGuiDir_Left && dax < 0.0f) || (move_dir == ImGuiDir_Right && dax > 0.0f) || (move_dir == ImGuiDir_Up && day < 0.0f) || (move_dir == ImGuiDir_Down && day > 0.0f)) { result->DistAxial = dist_axial; new_best = true; } return new_best; } static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; result->Window = window; result->ID = g.LastItemData.ID; result->FocusScopeId = g.CurrentFocusScopeId; result->InFlags = g.LastItemData.InFlags; result->RectRel = WindowRectAbsToRel(window, g.LastItemData.NavRect); if (result->InFlags & ImGuiItemFlags_HasSelectionUserData) { IM_ASSERT(g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid); result->SelectionUserData = g.NextItemData.SelectionUserData; // INTENTIONAL: At this point this field is not cleared in NextItemData. Avoid unnecessary copy to LastItemData. } } // True when current work location may be scrolled horizontally when moving left / right. // This is generally always true UNLESS within a column. We don't have a vertical equivalent. void ImGui::NavUpdateCurrentWindowIsScrollPushableX() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; window->DC.NavIsScrollPushableX = (g.CurrentTable == NULL && window->DC.CurrentColumns == NULL); } // We get there when either NavId == id, or when g.NavAnyRequest is set (which is updated by NavUpdateAnyRequestFlag above) // This is called after LastItemData is set, but NextItemData is also still valid. static void ImGui::NavProcessItem() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; const ImGuiID id = g.LastItemData.ID; const ImGuiItemFlags item_flags = g.LastItemData.InFlags; // When inside a container that isn't scrollable with Left<>Right, clip NavRect accordingly (#2221) if (window->DC.NavIsScrollPushableX == false) { g.LastItemData.NavRect.Min.x = ImClamp(g.LastItemData.NavRect.Min.x, window->ClipRect.Min.x, window->ClipRect.Max.x); g.LastItemData.NavRect.Max.x = ImClamp(g.LastItemData.NavRect.Max.x, window->ClipRect.Min.x, window->ClipRect.Max.x); } const ImRect nav_bb = g.LastItemData.NavRect; // Process Init Request if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent && (item_flags & ImGuiItemFlags_Disabled) == 0) { // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback const bool candidate_for_nav_default_focus = (item_flags & ImGuiItemFlags_NoNavDefaultFocus) == 0; if (candidate_for_nav_default_focus || g.NavInitResult.ID == 0) { NavApplyItemToResult(&g.NavInitResult); } if (candidate_for_nav_default_focus) { g.NavInitRequest = false; // Found a match, clear request NavUpdateAnyRequestFlag(); } } // Process Move Request (scoring for navigation) // FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRect + scoring from a rect wrapped according to current wrapping policy) if (g.NavMoveScoringItems && (item_flags & ImGuiItemFlags_Disabled) == 0 && (window->Flags & ImGuiWindowFlags_NoNavInputs) == 0) { const bool is_tabbing = (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) != 0; if (is_tabbing) { NavProcessItemForTabbingRequest(id, item_flags, g.NavMoveFlags); } else if (g.NavId != id || (g.NavMoveFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) { ImGuiNavItemData* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther; if (NavScoreItem(result)) NavApplyItemToResult(result); // Features like PageUp/PageDown need to maintain a separate score for the visible set of items. const float VISIBLE_RATIO = 0.70f; if ((g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb)) if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) - ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >= (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO) if (NavScoreItem(&g.NavMoveResultLocalVisible)) NavApplyItemToResult(&g.NavMoveResultLocalVisible); } } // Update information for currently focused/navigated item if (g.NavId == id) { if (g.NavWindow != window) SetNavWindow(window); // Always refresh g.NavWindow, because some operations such as FocusItem() may not have a window. g.NavLayer = window->DC.NavLayerCurrent; SetNavFocusScope(g.CurrentFocusScopeId); // Will set g.NavFocusScopeId AND store g.NavFocusScopePath g.NavFocusScopeId = g.CurrentFocusScopeId; g.NavIdIsAlive = true; if (g.LastItemData.InFlags & ImGuiItemFlags_HasSelectionUserData) { IM_ASSERT(g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid); g.NavLastValidSelectionUserData = g.NextItemData.SelectionUserData; // INTENTIONAL: At this point this field is not cleared in NextItemData. Avoid unnecessary copy to LastItemData. } window->NavRectRel[window->DC.NavLayerCurrent] = WindowRectAbsToRel(window, nav_bb); // Store item bounding box (relative to window position) } } // Handle "scoring" of an item for a tabbing/focusing request initiated by NavUpdateCreateTabbingRequest(). // Note that SetKeyboardFocusHere() API calls are considered tabbing requests! // - Case 1: no nav/active id: set result to first eligible item, stop storing. // - Case 2: tab forward: on ref id set counter, on counter elapse store result // - Case 3: tab forward wrap: set result to first eligible item (preemptively), on ref id set counter, on next frame if counter hasn't elapsed store result. // FIXME-TABBING: Could be done as a next-frame forwarded request // - Case 4: tab backward: store all results, on ref id pick prev, stop storing // - Case 5: tab backward wrap: store all results, on ref id if no result keep storing until last // FIXME-TABBING: Could be done as next-frame forwarded requested void ImGui::NavProcessItemForTabbingRequest(ImGuiID id, ImGuiItemFlags item_flags, ImGuiNavMoveFlags move_flags) { ImGuiContext& g = *GImGui; if ((move_flags & ImGuiNavMoveFlags_FocusApi) == 0) { if (g.NavLayer != g.CurrentWindow->DC.NavLayerCurrent) return; if (g.NavFocusScopeId != g.CurrentFocusScopeId) return; } // - Can always land on an item when using API call. // - Tabbing with _NavEnableKeyboard (space/enter/arrows): goes through every item. // - Tabbing without _NavEnableKeyboard: goes through inputable items only. bool can_stop; if (move_flags & ImGuiNavMoveFlags_FocusApi) can_stop = true; else can_stop = (item_flags & ImGuiItemFlags_NoTabStop) == 0 && ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) || (item_flags & ImGuiItemFlags_Inputable)); // Always store in NavMoveResultLocal (unlike directional request which uses NavMoveResultOther on sibling/flattened windows) ImGuiNavItemData* result = &g.NavMoveResultLocal; if (g.NavTabbingDir == +1) { // Tab Forward or SetKeyboardFocusHere() with >= 0 if (can_stop && g.NavTabbingResultFirst.ID == 0) NavApplyItemToResult(&g.NavTabbingResultFirst); if (can_stop && g.NavTabbingCounter > 0 && --g.NavTabbingCounter == 0) NavMoveRequestResolveWithLastItem(result); else if (g.NavId == id) g.NavTabbingCounter = 1; } else if (g.NavTabbingDir == -1) { // Tab Backward if (g.NavId == id) { if (result->ID) { g.NavMoveScoringItems = false; NavUpdateAnyRequestFlag(); } } else if (can_stop) { // Keep applying until reaching NavId NavApplyItemToResult(result); } } else if (g.NavTabbingDir == 0) { if (can_stop && g.NavId == id) NavMoveRequestResolveWithLastItem(result); if (can_stop && g.NavTabbingResultFirst.ID == 0) // Tab init NavApplyItemToResult(&g.NavTabbingResultFirst); } } bool ImGui::NavMoveRequestButNoResultYet() { ImGuiContext& g = *GImGui; return g.NavMoveScoringItems && g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0; } // FIXME: ScoringRect is not set void ImGui::NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags) { ImGuiContext& g = *GImGui; IM_ASSERT(g.NavWindow != NULL); if (move_flags & ImGuiNavMoveFlags_IsTabbing) move_flags |= ImGuiNavMoveFlags_AllowCurrentNavId; g.NavMoveSubmitted = g.NavMoveScoringItems = true; g.NavMoveDir = move_dir; g.NavMoveDirForDebug = move_dir; g.NavMoveClipDir = clip_dir; g.NavMoveFlags = move_flags; g.NavMoveScrollFlags = scroll_flags; g.NavMoveForwardToNextFrame = false; g.NavMoveKeyMods = (move_flags & ImGuiNavMoveFlags_FocusApi) ? 0 : g.IO.KeyMods; g.NavMoveResultLocal.Clear(); g.NavMoveResultLocalVisible.Clear(); g.NavMoveResultOther.Clear(); g.NavTabbingCounter = 0; g.NavTabbingResultFirst.Clear(); NavUpdateAnyRequestFlag(); } void ImGui::NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result) { ImGuiContext& g = *GImGui; g.NavMoveScoringItems = false; // Ensure request doesn't need more processing NavApplyItemToResult(result); NavUpdateAnyRequestFlag(); } // Called by TreePop() to implement ImGuiTreeNodeFlags_NavLeftJumpsBackHere void ImGui::NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiNavTreeNodeData* tree_node_data) { ImGuiContext& g = *GImGui; g.NavMoveScoringItems = false; g.LastItemData.ID = tree_node_data->ID; g.LastItemData.InFlags = tree_node_data->InFlags & ~ImGuiItemFlags_HasSelectionUserData; // Losing SelectionUserData, recovered next-frame (cheaper). g.LastItemData.NavRect = tree_node_data->NavRect; NavApplyItemToResult(result); // Result this instead of implementing a NavApplyPastTreeNodeToResult() NavClearPreferredPosForAxis(ImGuiAxis_Y); NavUpdateAnyRequestFlag(); } void ImGui::NavMoveRequestCancel() { ImGuiContext& g = *GImGui; g.NavMoveSubmitted = g.NavMoveScoringItems = false; NavUpdateAnyRequestFlag(); } // Forward will reuse the move request again on the next frame (generally with modifications done to it) void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags) { ImGuiContext& g = *GImGui; IM_ASSERT(g.NavMoveForwardToNextFrame == false); NavMoveRequestCancel(); g.NavMoveForwardToNextFrame = true; g.NavMoveDir = move_dir; g.NavMoveClipDir = clip_dir; g.NavMoveFlags = move_flags | ImGuiNavMoveFlags_Forwarded; g.NavMoveScrollFlags = scroll_flags; } // Navigation wrap-around logic is delayed to the end of the frame because this operation is only valid after entire // popup is assembled and in case of appended popups it is not clear which EndPopup() call is final. void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags wrap_flags) { ImGuiContext& g = *GImGui; IM_ASSERT((wrap_flags & ImGuiNavMoveFlags_WrapMask_ ) != 0 && (wrap_flags & ~ImGuiNavMoveFlags_WrapMask_) == 0); // Call with _WrapX, _WrapY, _LoopX, _LoopY // In theory we should test for NavMoveRequestButNoResultYet() but there's no point doing it: // as NavEndFrame() will do the same test. It will end up calling NavUpdateCreateWrappingRequest(). if (g.NavWindow == window && g.NavMoveScoringItems && g.NavLayer == ImGuiNavLayer_Main) g.NavMoveFlags = (g.NavMoveFlags & ~ImGuiNavMoveFlags_WrapMask_) | wrap_flags; } // FIXME: This could be replaced by updating a frame number in each window when (window == NavWindow) and (NavLayer == 0). // This way we could find the last focused window among our children. It would be much less confusing this way? static void ImGui::NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window) { ImGuiWindow* parent = nav_window; while (parent && parent->RootWindow != parent && (parent->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0) parent = parent->ParentWindow; if (parent && parent != nav_window) parent->NavLastChildNavWindow = nav_window; } // Restore the last focused child. // Call when we are expected to land on the Main Layer (0) after FocusWindow() static ImGuiWindow* ImGui::NavRestoreLastChildNavWindow(ImGuiWindow* window) { if (window->NavLastChildNavWindow && window->NavLastChildNavWindow->WasActive) return window->NavLastChildNavWindow; return window; } void ImGui::NavRestoreLayer(ImGuiNavLayer layer) { ImGuiContext& g = *GImGui; if (layer == ImGuiNavLayer_Main) { ImGuiWindow* prev_nav_window = g.NavWindow; g.NavWindow = NavRestoreLastChildNavWindow(g.NavWindow); // FIXME-NAV: Should clear ongoing nav requests? g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid; if (prev_nav_window) IMGUI_DEBUG_LOG_FOCUS("[focus] NavRestoreLayer: from \"%s\" to SetNavWindow(\"%s\")\n", prev_nav_window->Name, g.NavWindow->Name); } ImGuiWindow* window = g.NavWindow; if (window->NavLastIds[layer] != 0) { SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]); } else { g.NavLayer = layer; NavInitWindow(window, true); } } void ImGui::NavRestoreHighlightAfterMove() { ImGuiContext& g = *GImGui; g.NavDisableHighlight = false; g.NavDisableMouseHover = g.NavMousePosDirty = true; } static inline void ImGui::NavUpdateAnyRequestFlag() { ImGuiContext& g = *GImGui; g.NavAnyRequest = g.NavMoveScoringItems || g.NavInitRequest || (IMGUI_DEBUG_NAV_SCORING && g.NavWindow != NULL); if (g.NavAnyRequest) IM_ASSERT(g.NavWindow != NULL); } // This needs to be called before we submit any widget (aka in or before Begin) void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit) { ImGuiContext& g = *GImGui; IM_ASSERT(window == g.NavWindow); if (window->Flags & ImGuiWindowFlags_NoNavInputs) { g.NavId = 0; SetNavFocusScope(window->NavRootFocusScopeId); return; } bool init_for_nav = false; if (window == window->RootWindow || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit) init_for_nav = true; IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from NavInitWindow(), init_for_nav=%d, window=\"%s\", layer=%d\n", init_for_nav, window->Name, g.NavLayer); if (init_for_nav) { SetNavID(0, g.NavLayer, window->NavRootFocusScopeId, ImRect()); g.NavInitRequest = true; g.NavInitRequestFromMove = false; g.NavInitResult.ID = 0; NavUpdateAnyRequestFlag(); } else { g.NavId = window->NavLastIds[0]; SetNavFocusScope(window->NavRootFocusScopeId); } } static ImVec2 ImGui::NavCalcPreferredRefPos() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.NavWindow; if (g.NavDisableHighlight || !g.NavDisableMouseHover || !window) { // Mouse (we need a fallback in case the mouse becomes invalid after being used) // The +1.0f offset when stored by OpenPopupEx() allows reopening this or another popup (same or another mouse button) while not moving the mouse, it is pretty standard. // In theory we could move that +1.0f offset in OpenPopupEx() ImVec2 p = IsMousePosValid(&g.IO.MousePos) ? g.IO.MousePos : g.MouseLastValidPos; return ImVec2(p.x + 1.0f, p.y); } else { // When navigation is active and mouse is disabled, pick a position around the bottom left of the currently navigated item // Take account of upcoming scrolling (maybe set mouse pos should be done in EndFrame?) ImRect rect_rel = WindowRectRelToAbs(window, window->NavRectRel[g.NavLayer]); if (window->LastFrameActive != g.FrameCount && (window->ScrollTarget.x != FLT_MAX || window->ScrollTarget.y != FLT_MAX)) { ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window); rect_rel.Translate(window->Scroll - next_scroll); } ImVec2 pos = ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x * 4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight())); ImGuiViewport* viewport = GetMainViewport(); return ImTrunc(ImClamp(pos, viewport->Pos, viewport->Pos + viewport->Size)); // ImTrunc() is important because non-integer mouse position application in backend might be lossy and result in undesirable non-zero delta. } } float ImGui::GetNavTweakPressedAmount(ImGuiAxis axis) { ImGuiContext& g = *GImGui; float repeat_delay, repeat_rate; GetTypematicRepeatRate(ImGuiInputFlags_RepeatRateNavTweak, &repeat_delay, &repeat_rate); ImGuiKey key_less, key_more; if (g.NavInputSource == ImGuiInputSource_Gamepad) { key_less = (axis == ImGuiAxis_X) ? ImGuiKey_GamepadDpadLeft : ImGuiKey_GamepadDpadUp; key_more = (axis == ImGuiAxis_X) ? ImGuiKey_GamepadDpadRight : ImGuiKey_GamepadDpadDown; } else { key_less = (axis == ImGuiAxis_X) ? ImGuiKey_LeftArrow : ImGuiKey_UpArrow; key_more = (axis == ImGuiAxis_X) ? ImGuiKey_RightArrow : ImGuiKey_DownArrow; } float amount = (float)GetKeyPressedAmount(key_more, repeat_delay, repeat_rate) - (float)GetKeyPressedAmount(key_less, repeat_delay, repeat_rate); if (amount != 0.0f && IsKeyDown(key_less) && IsKeyDown(key_more)) // Cancel when opposite directions are held, regardless of repeat phase amount = 0.0f; return amount; } static void ImGui::NavUpdate() { ImGuiContext& g = *GImGui; ImGuiIO& io = g.IO; io.WantSetMousePos = false; //if (g.NavScoringDebugCount > 0) IMGUI_DEBUG_LOG_NAV("[nav] NavScoringDebugCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.NavScoringDebugCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest); // Set input source based on which keys are last pressed (as some features differs when used with Gamepad vs Keyboard) // FIXME-NAV: Now that keys are separated maybe we can get rid of NavInputSource? const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; const ImGuiKey nav_gamepad_keys_to_change_source[] = { ImGuiKey_GamepadFaceRight, ImGuiKey_GamepadFaceLeft, ImGuiKey_GamepadFaceUp, ImGuiKey_GamepadFaceDown, ImGuiKey_GamepadDpadRight, ImGuiKey_GamepadDpadLeft, ImGuiKey_GamepadDpadUp, ImGuiKey_GamepadDpadDown }; if (nav_gamepad_active) for (ImGuiKey key : nav_gamepad_keys_to_change_source) if (IsKeyDown(key)) g.NavInputSource = ImGuiInputSource_Gamepad; const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0; const ImGuiKey nav_keyboard_keys_to_change_source[] = { ImGuiKey_Space, ImGuiKey_Enter, ImGuiKey_Escape, ImGuiKey_RightArrow, ImGuiKey_LeftArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow }; if (nav_keyboard_active) for (ImGuiKey key : nav_keyboard_keys_to_change_source) if (IsKeyDown(key)) g.NavInputSource = ImGuiInputSource_Keyboard; // Process navigation init request (select first/default focus) g.NavJustMovedToId = 0; if (g.NavInitResult.ID != 0) NavInitRequestApplyResult(); g.NavInitRequest = false; g.NavInitRequestFromMove = false; g.NavInitResult.ID = 0; // Process navigation move request if (g.NavMoveSubmitted) NavMoveRequestApplyResult(); g.NavTabbingCounter = 0; g.NavMoveSubmitted = g.NavMoveScoringItems = false; // Schedule mouse position update (will be done at the bottom of this function, after 1) processing all move requests and 2) updating scrolling) bool set_mouse_pos = false; if (g.NavMousePosDirty && g.NavIdIsAlive) if (!g.NavDisableHighlight && g.NavDisableMouseHover && g.NavWindow) set_mouse_pos = true; g.NavMousePosDirty = false; IM_ASSERT(g.NavLayer == ImGuiNavLayer_Main || g.NavLayer == ImGuiNavLayer_Menu); // Store our return window (for returning from Menu Layer to Main Layer) and clear it as soon as we step back in our own Layer 0 if (g.NavWindow) NavSaveLastChildNavWindowIntoParent(g.NavWindow); if (g.NavWindow && g.NavWindow->NavLastChildNavWindow != NULL && g.NavLayer == ImGuiNavLayer_Main) g.NavWindow->NavLastChildNavWindow = NULL; // Update CTRL+TAB and Windowing features (hold Square to move/resize/etc.) NavUpdateWindowing(); // Set output flags for user application io.NavActive = (nav_keyboard_active || nav_gamepad_active) && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs); io.NavVisible = (io.NavActive && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL); // Process NavCancel input (to close a popup, get back to parent, clear focus) NavUpdateCancelRequest(); // Process manual activation request g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = 0; g.NavActivateFlags = ImGuiActivateFlags_None; if (g.NavId != 0 && !g.NavDisableHighlight && !g.NavWindowingTarget && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { const bool activate_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Space, ImGuiKeyOwner_None)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate, ImGuiKeyOwner_None)); const bool activate_pressed = activate_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Space, ImGuiKeyOwner_None)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, ImGuiKeyOwner_None))); const bool input_down = (nav_keyboard_active && (IsKeyDown(ImGuiKey_Enter, ImGuiKeyOwner_None) || IsKeyDown(ImGuiKey_KeypadEnter, ImGuiKeyOwner_None))) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadInput, ImGuiKeyOwner_None)); const bool input_pressed = input_down && ((nav_keyboard_active && (IsKeyPressed(ImGuiKey_Enter, ImGuiKeyOwner_None) || IsKeyPressed(ImGuiKey_KeypadEnter, ImGuiKeyOwner_None))) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadInput, ImGuiKeyOwner_None))); if (g.ActiveId == 0 && activate_pressed) { g.NavActivateId = g.NavId; g.NavActivateFlags = ImGuiActivateFlags_PreferTweak; } if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && input_pressed) { g.NavActivateId = g.NavId; g.NavActivateFlags = ImGuiActivateFlags_PreferInput; } if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (activate_down || input_down)) g.NavActivateDownId = g.NavId; if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (activate_pressed || input_pressed)) { g.NavActivatePressedId = g.NavId; NavHighlightActivated(g.NavId); } } if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) g.NavDisableHighlight = true; if (g.NavActivateId != 0) IM_ASSERT(g.NavActivateDownId == g.NavActivateId); // Highlight if (g.NavHighlightActivatedTimer > 0.0f) g.NavHighlightActivatedTimer = ImMax(0.0f, g.NavHighlightActivatedTimer - io.DeltaTime); if (g.NavHighlightActivatedTimer == 0.0f) g.NavHighlightActivatedId = 0; // Process programmatic activation request // FIXME-NAV: Those should eventually be queued (unlike focus they don't cancel each others) if (g.NavNextActivateId != 0) { g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavNextActivateId; g.NavActivateFlags = g.NavNextActivateFlags; } g.NavNextActivateId = 0; // Process move requests NavUpdateCreateMoveRequest(); if (g.NavMoveDir == ImGuiDir_None) NavUpdateCreateTabbingRequest(); NavUpdateAnyRequestFlag(); g.NavIdIsAlive = false; // Scrolling if (g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget) { // *Fallback* manual-scroll with Nav directional keys when window has no navigable item ImGuiWindow* window = g.NavWindow; const float scroll_speed = IM_ROUND(window->CalcFontSize() * 100 * io.DeltaTime); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. const ImGuiDir move_dir = g.NavMoveDir; if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavWindowHasScrollY && move_dir != ImGuiDir_None) { if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right) SetScrollX(window, ImTrunc(window->Scroll.x + ((move_dir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed)); if (move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down) SetScrollY(window, ImTrunc(window->Scroll.y + ((move_dir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed)); } // *Normal* Manual scroll with LStick // Next movement request will clamp the NavId reference rectangle to the visible area, so navigation will resume within those bounds. if (nav_gamepad_active) { const ImVec2 scroll_dir = GetKeyMagnitude2d(ImGuiKey_GamepadLStickLeft, ImGuiKey_GamepadLStickRight, ImGuiKey_GamepadLStickUp, ImGuiKey_GamepadLStickDown); const float tweak_factor = IsKeyDown(ImGuiKey_NavGamepadTweakSlow) ? 1.0f / 10.0f : IsKeyDown(ImGuiKey_NavGamepadTweakFast) ? 10.0f : 1.0f; if (scroll_dir.x != 0.0f && window->ScrollbarX) SetScrollX(window, ImTrunc(window->Scroll.x + scroll_dir.x * scroll_speed * tweak_factor)); if (scroll_dir.y != 0.0f) SetScrollY(window, ImTrunc(window->Scroll.y + scroll_dir.y * scroll_speed * tweak_factor)); } } // Always prioritize mouse highlight if navigation is disabled if (!nav_keyboard_active && !nav_gamepad_active) { g.NavDisableHighlight = true; g.NavDisableMouseHover = set_mouse_pos = false; } // Update mouse position if requested // (This will take into account the possibility that a Scroll was queued in the window to offset our absolute mouse position before scroll has been applied) if (set_mouse_pos && (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos)) TeleportMousePos(NavCalcPreferredRefPos()); // [DEBUG] g.NavScoringDebugCount = 0; #if IMGUI_DEBUG_NAV_RECTS if (ImGuiWindow* debug_window = g.NavWindow) { ImDrawList* draw_list = GetForegroundDrawList(debug_window); int layer = g.NavLayer; /* for (int layer = 0; layer < 2; layer++)*/ { ImRect r = WindowRectRelToAbs(debug_window, debug_window->NavRectRel[layer]); draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 200, 0, 255)); } //if (1) { ImU32 col = (!debug_window->Hidden) ? IM_COL32(255,0,255,255) : IM_COL32(255,0,0,255); ImVec2 p = NavCalcPreferredRefPos(); char buf[32]; ImFormatString(buf, 32, "%d", g.NavLayer); draw_list->AddCircleFilled(p, 3.0f, col); draw_list->AddText(NULL, 13.0f, p + ImVec2(8,-4), col, buf); } } #endif } void ImGui::NavInitRequestApplyResult() { // In very rare cases g.NavWindow may be null (e.g. clearing focus after requesting an init request, which does happen when releasing Alt while clicking on void) ImGuiContext& g = *GImGui; if (!g.NavWindow) return; ImGuiNavItemData* result = &g.NavInitResult; if (g.NavId != result->ID) { g.NavJustMovedToId = result->ID; g.NavJustMovedToFocusScopeId = result->FocusScopeId; g.NavJustMovedToKeyMods = 0; } // Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called) // FIXME-NAV: On _NavFlattened windows, g.NavWindow will only be updated during subsequent frame. Not a problem currently. IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: ApplyResult: NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID, g.NavLayer, g.NavWindow->Name); SetNavID(result->ID, g.NavLayer, result->FocusScopeId, result->RectRel); g.NavIdIsAlive = true; // Mark as alive from previous frame as we got a result if (result->SelectionUserData != ImGuiSelectionUserData_Invalid) g.NavLastValidSelectionUserData = result->SelectionUserData; if (g.NavInitRequestFromMove) NavRestoreHighlightAfterMove(); } // Bias scoring rect ahead of scoring + update preferred pos (if missing) using source position static void NavBiasScoringRect(ImRect& r, ImVec2& preferred_pos_rel, ImGuiDir move_dir, ImGuiNavMoveFlags move_flags) { // Bias initial rect ImGuiContext& g = *GImGui; const ImVec2 rel_to_abs_offset = g.NavWindow->DC.CursorStartPos; // Initialize bias on departure if we don't have any. So mouse-click + arrow will record bias. // - We default to L/U bias, so moving down from a large source item into several columns will land on left-most column. // - But each successful move sets new bias on one axis, only cleared when using mouse. if ((move_flags & ImGuiNavMoveFlags_Forwarded) == 0) { if (preferred_pos_rel.x == FLT_MAX) preferred_pos_rel.x = ImMin(r.Min.x + 1.0f, r.Max.x) - rel_to_abs_offset.x; if (preferred_pos_rel.y == FLT_MAX) preferred_pos_rel.y = r.GetCenter().y - rel_to_abs_offset.y; } // Apply general bias on the other axis if ((move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down) && preferred_pos_rel.x != FLT_MAX) r.Min.x = r.Max.x = preferred_pos_rel.x + rel_to_abs_offset.x; else if ((move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right) && preferred_pos_rel.y != FLT_MAX) r.Min.y = r.Max.y = preferred_pos_rel.y + rel_to_abs_offset.y; } void ImGui::NavUpdateCreateMoveRequest() { ImGuiContext& g = *GImGui; ImGuiIO& io = g.IO; ImGuiWindow* window = g.NavWindow; const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0; if (g.NavMoveForwardToNextFrame && window != NULL) { // Forwarding previous request (which has been modified, e.g. wrap around menus rewrite the requests with a starting rectangle at the other side of the window) // (preserve most state, which were already set by the NavMoveRequestForward() function) IM_ASSERT(g.NavMoveDir != ImGuiDir_None && g.NavMoveClipDir != ImGuiDir_None); IM_ASSERT(g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded); IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequestForward %d\n", g.NavMoveDir); } else { // Initiate directional inputs request g.NavMoveDir = ImGuiDir_None; g.NavMoveFlags = ImGuiNavMoveFlags_None; g.NavMoveScrollFlags = ImGuiScrollFlags_None; if (window && !g.NavWindowingTarget && !(window->Flags & ImGuiWindowFlags_NoNavInputs)) { const ImGuiInputFlags repeat_mode = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateNavMove; if (!IsActiveIdUsingNavDir(ImGuiDir_Left) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadLeft, ImGuiKeyOwner_None, repeat_mode)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_LeftArrow, ImGuiKeyOwner_None, repeat_mode)))) { g.NavMoveDir = ImGuiDir_Left; } if (!IsActiveIdUsingNavDir(ImGuiDir_Right) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadRight, ImGuiKeyOwner_None, repeat_mode)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_RightArrow, ImGuiKeyOwner_None, repeat_mode)))) { g.NavMoveDir = ImGuiDir_Right; } if (!IsActiveIdUsingNavDir(ImGuiDir_Up) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadUp, ImGuiKeyOwner_None, repeat_mode)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_UpArrow, ImGuiKeyOwner_None, repeat_mode)))) { g.NavMoveDir = ImGuiDir_Up; } if (!IsActiveIdUsingNavDir(ImGuiDir_Down) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadDown, ImGuiKeyOwner_None, repeat_mode)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_DownArrow, ImGuiKeyOwner_None, repeat_mode)))) { g.NavMoveDir = ImGuiDir_Down; } } g.NavMoveClipDir = g.NavMoveDir; g.NavScoringNoClipRect = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX); } // Update PageUp/PageDown/Home/End scroll // FIXME-NAV: Consider enabling those keys even without the master ImGuiConfigFlags_NavEnableKeyboard flag? float scoring_rect_offset_y = 0.0f; if (window && g.NavMoveDir == ImGuiDir_None && nav_keyboard_active) scoring_rect_offset_y = NavUpdatePageUpPageDown(); if (scoring_rect_offset_y != 0.0f) { g.NavScoringNoClipRect = window->InnerRect; g.NavScoringNoClipRect.TranslateY(scoring_rect_offset_y); } // [DEBUG] Always send a request when holding CTRL. Hold CTRL + Arrow change the direction. #if IMGUI_DEBUG_NAV_SCORING //if (io.KeyCtrl && IsKeyPressed(ImGuiKey_C)) // g.NavMoveDirForDebug = (ImGuiDir)((g.NavMoveDirForDebug + 1) & 3); if (io.KeyCtrl) { if (g.NavMoveDir == ImGuiDir_None) g.NavMoveDir = g.NavMoveDirForDebug; g.NavMoveClipDir = g.NavMoveDir; g.NavMoveFlags |= ImGuiNavMoveFlags_DebugNoResult; } #endif // Submit g.NavMoveForwardToNextFrame = false; if (g.NavMoveDir != ImGuiDir_None) NavMoveRequestSubmit(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags, g.NavMoveScrollFlags); // Moving with no reference triggers an init request (will be used as a fallback if the direction fails to find a match) if (g.NavMoveSubmitted && g.NavId == 0) { IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from move, window \"%s\", layer=%d\n", window ? window->Name : "", g.NavLayer); g.NavInitRequest = g.NavInitRequestFromMove = true; g.NavInitResult.ID = 0; g.NavDisableHighlight = false; } // When using gamepad, we project the reference nav bounding box into window visible area. // This is to allow resuming navigation inside the visible area after doing a large amount of scrolling, // since with gamepad all movements are relative (can't focus a visible object like we can with the mouse). if (g.NavMoveSubmitted && g.NavInputSource == ImGuiInputSource_Gamepad && g.NavLayer == ImGuiNavLayer_Main && window != NULL)// && (g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded)) { bool clamp_x = (g.NavMoveFlags & (ImGuiNavMoveFlags_LoopX | ImGuiNavMoveFlags_WrapX)) == 0; bool clamp_y = (g.NavMoveFlags & (ImGuiNavMoveFlags_LoopY | ImGuiNavMoveFlags_WrapY)) == 0; ImRect inner_rect_rel = WindowRectAbsToRel(window, ImRect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1))); // Take account of changing scroll to handle triggering a new move request on a scrolling frame. (#6171) // Otherwise 'inner_rect_rel' would be off on the move result frame. inner_rect_rel.Translate(CalcNextScrollFromScrollTargetAndClamp(window) - window->Scroll); if ((clamp_x || clamp_y) && !inner_rect_rel.Contains(window->NavRectRel[g.NavLayer])) { IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: clamp NavRectRel for gamepad move\n"); float pad_x = ImMin(inner_rect_rel.GetWidth(), window->CalcFontSize() * 0.5f); float pad_y = ImMin(inner_rect_rel.GetHeight(), window->CalcFontSize() * 0.5f); // Terrible approximation for the intent of starting navigation from first fully visible item inner_rect_rel.Min.x = clamp_x ? (inner_rect_rel.Min.x + pad_x) : -FLT_MAX; inner_rect_rel.Max.x = clamp_x ? (inner_rect_rel.Max.x - pad_x) : +FLT_MAX; inner_rect_rel.Min.y = clamp_y ? (inner_rect_rel.Min.y + pad_y) : -FLT_MAX; inner_rect_rel.Max.y = clamp_y ? (inner_rect_rel.Max.y - pad_y) : +FLT_MAX; window->NavRectRel[g.NavLayer].ClipWithFull(inner_rect_rel); g.NavId = 0; } } // For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items) ImRect scoring_rect; if (window != NULL) { ImRect nav_rect_rel = !window->NavRectRel[g.NavLayer].IsInverted() ? window->NavRectRel[g.NavLayer] : ImRect(0, 0, 0, 0); scoring_rect = WindowRectRelToAbs(window, nav_rect_rel); scoring_rect.TranslateY(scoring_rect_offset_y); if (g.NavMoveSubmitted) NavBiasScoringRect(scoring_rect, window->RootWindowForNav->NavPreferredScoringPosRel[g.NavLayer], g.NavMoveDir, g.NavMoveFlags); IM_ASSERT(!scoring_rect.IsInverted()); // Ensure we have a non-inverted bounding box here will allow us to remove extraneous ImFabs() calls in NavScoreItem(). //GetForegroundDrawList()->AddRect(scoring_rect.Min, scoring_rect.Max, IM_COL32(255,200,0,255)); // [DEBUG] //if (!g.NavScoringNoClipRect.IsInverted()) { GetForegroundDrawList()->AddRect(g.NavScoringNoClipRect.Min, g.NavScoringNoClipRect.Max, IM_COL32(255, 200, 0, 255)); } // [DEBUG] } g.NavScoringRect = scoring_rect; g.NavScoringNoClipRect.Add(scoring_rect); } void ImGui::NavUpdateCreateTabbingRequest() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.NavWindow; IM_ASSERT(g.NavMoveDir == ImGuiDir_None); if (window == NULL || g.NavWindowingTarget != NULL || (window->Flags & ImGuiWindowFlags_NoNavInputs)) return; const bool tab_pressed = IsKeyPressed(ImGuiKey_Tab, ImGuiKeyOwner_None, ImGuiInputFlags_Repeat) && !g.IO.KeyCtrl && !g.IO.KeyAlt; if (!tab_pressed) return; // Initiate tabbing request // (this is ALWAYS ENABLED, regardless of ImGuiConfigFlags_NavEnableKeyboard flag!) // See NavProcessItemForTabbingRequest() for a description of the various forward/backward tabbing cases with and without wrapping. const bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0; if (nav_keyboard_active) g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.NavDisableHighlight == true && g.ActiveId == 0) ? 0 : +1; else g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.ActiveId == 0) ? 0 : +1; ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_IsTabbing | ImGuiNavMoveFlags_Activate; ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY; ImGuiDir clip_dir = (g.NavTabbingDir < 0) ? ImGuiDir_Up : ImGuiDir_Down; NavMoveRequestSubmit(ImGuiDir_None, clip_dir, move_flags, scroll_flags); // FIXME-NAV: Once we refactor tabbing, add LegacyApi flag to not activate non-inputable. g.NavTabbingCounter = -1; } // Apply result from previous frame navigation directional move request. Always called from NavUpdate() void ImGui::NavMoveRequestApplyResult() { ImGuiContext& g = *GImGui; #if IMGUI_DEBUG_NAV_SCORING if (g.NavMoveFlags & ImGuiNavMoveFlags_DebugNoResult) // [DEBUG] Scoring all items in NavWindow at all times return; #endif // Select which result to use ImGuiNavItemData* result = (g.NavMoveResultLocal.ID != 0) ? &g.NavMoveResultLocal : (g.NavMoveResultOther.ID != 0) ? &g.NavMoveResultOther : NULL; // Tabbing forward wrap if ((g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && result == NULL) if ((g.NavTabbingCounter == 1 || g.NavTabbingDir == 0) && g.NavTabbingResultFirst.ID) result = &g.NavTabbingResultFirst; // In a situation when there are no results but NavId != 0, re-enable the Navigation highlight (because g.NavId is not considered as a possible result) const ImGuiAxis axis = (g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) ? ImGuiAxis_Y : ImGuiAxis_X; if (result == NULL) { if (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) g.NavMoveFlags |= ImGuiNavMoveFlags_NoSetNavHighlight; if (g.NavId != 0 && (g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavHighlight) == 0) NavRestoreHighlightAfterMove(); NavClearPreferredPosForAxis(axis); // On a failed move, clear preferred pos for this axis. IMGUI_DEBUG_LOG_NAV("[nav] NavMoveSubmitted but not led to a result!\n"); return; } // PageUp/PageDown behavior first jumps to the bottom/top mostly visible item, _otherwise_ use the result from the previous/next page. if (g.NavMoveFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) if (g.NavMoveResultLocalVisible.ID != 0 && g.NavMoveResultLocalVisible.ID != g.NavId) result = &g.NavMoveResultLocalVisible; // Maybe entering a flattened child from the outside? In this case solve the tie using the regular scoring rules. if (result != &g.NavMoveResultOther && g.NavMoveResultOther.ID != 0 && g.NavMoveResultOther.Window->ParentWindow == g.NavWindow) if ((g.NavMoveResultOther.DistBox < result->DistBox) || (g.NavMoveResultOther.DistBox == result->DistBox && g.NavMoveResultOther.DistCenter < result->DistCenter)) result = &g.NavMoveResultOther; IM_ASSERT(g.NavWindow && result->Window); // Scroll to keep newly navigated item fully into view. if (g.NavLayer == ImGuiNavLayer_Main) { ImRect rect_abs = WindowRectRelToAbs(result->Window, result->RectRel); ScrollToRectEx(result->Window, rect_abs, g.NavMoveScrollFlags); if (g.NavMoveFlags & ImGuiNavMoveFlags_ScrollToEdgeY) { // FIXME: Should remove this? Or make more precise: use ScrollToRectEx() with edge? float scroll_target = (g.NavMoveDir == ImGuiDir_Up) ? result->Window->ScrollMax.y : 0.0f; SetScrollY(result->Window, scroll_target); } } if (g.NavWindow != result->Window) { IMGUI_DEBUG_LOG_FOCUS("[focus] NavMoveRequest: SetNavWindow(\"%s\")\n", result->Window->Name); g.NavWindow = result->Window; g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid; } // FIXME: Could become optional e.g. ImGuiNavMoveFlags_NoClearActiveId if we later want to apply navigation requests without altering active input. if (g.ActiveId != result->ID) ClearActiveID(); // Don't set NavJustMovedToId if just landed on the same spot (which may happen with ImGuiNavMoveFlags_AllowCurrentNavId) // PageUp/PageDown however sets always set NavJustMovedTo (vs Home/End which doesn't) mimicking Windows behavior. if ((g.NavId != result->ID || (g.NavMoveFlags & ImGuiNavMoveFlags_IsPageMove)) && (g.NavMoveFlags & ImGuiNavMoveFlags_NoSelect) == 0) { g.NavJustMovedToId = result->ID; g.NavJustMovedToFocusScopeId = result->FocusScopeId; g.NavJustMovedToKeyMods = g.NavMoveKeyMods; } // Apply new NavID/Focus IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", result->ID, g.NavLayer, g.NavWindow->Name); ImVec2 preferred_scoring_pos_rel = g.NavWindow->RootWindowForNav->NavPreferredScoringPosRel[g.NavLayer]; SetNavID(result->ID, g.NavLayer, result->FocusScopeId, result->RectRel); if (result->SelectionUserData != ImGuiSelectionUserData_Invalid) g.NavLastValidSelectionUserData = result->SelectionUserData; // Restore last preferred position for current axis // (storing in RootWindowForNav-> as the info is desirable at the beginning of a Move Request. In theory all storage should use RootWindowForNav..) if ((g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) == 0) { preferred_scoring_pos_rel[axis] = result->RectRel.GetCenter()[axis]; g.NavWindow->RootWindowForNav->NavPreferredScoringPosRel[g.NavLayer] = preferred_scoring_pos_rel; } // Tabbing: Activates Inputable, otherwise only Focus if ((g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && (result->InFlags & ImGuiItemFlags_Inputable) == 0) g.NavMoveFlags &= ~ImGuiNavMoveFlags_Activate; // Activate if (g.NavMoveFlags & ImGuiNavMoveFlags_Activate) { g.NavNextActivateId = result->ID; g.NavNextActivateFlags = ImGuiActivateFlags_None; if (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) g.NavNextActivateFlags |= ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState | ImGuiActivateFlags_FromTabbing; } // Enable nav highlight if ((g.NavMoveFlags & ImGuiNavMoveFlags_NoSetNavHighlight) == 0) NavRestoreHighlightAfterMove(); } // Process NavCancel input (to close a popup, get back to parent, clear focus) // FIXME: In order to support e.g. Escape to clear a selection we'll need: // - either to store the equivalent of ActiveIdUsingKeyInputMask for a FocusScope and test for it. // - either to move most/all of those tests to the epilogue/end functions of the scope they are dealing with (e.g. exit child window in EndChild()) or in EndFrame(), to allow an earlier intercept static void ImGui::NavUpdateCancelRequest() { ImGuiContext& g = *GImGui; const bool nav_gamepad_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; const bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0; if (!(nav_keyboard_active && IsKeyPressed(ImGuiKey_Escape, ImGuiKeyOwner_None)) && !(nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadCancel, ImGuiKeyOwner_None))) return; IMGUI_DEBUG_LOG_NAV("[nav] NavUpdateCancelRequest()\n"); if (g.ActiveId != 0) { ClearActiveID(); } else if (g.NavLayer != ImGuiNavLayer_Main) { // Leave the "menu" layer NavRestoreLayer(ImGuiNavLayer_Main); NavRestoreHighlightAfterMove(); } else if (g.NavWindow && g.NavWindow != g.NavWindow->RootWindow && !(g.NavWindow->RootWindowForNav->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->RootWindowForNav->ParentWindow) { // Exit child window ImGuiWindow* child_window = g.NavWindow->RootWindowForNav; ImGuiWindow* parent_window = child_window->ParentWindow; IM_ASSERT(child_window->ChildId != 0); FocusWindow(parent_window); SetNavID(child_window->ChildId, ImGuiNavLayer_Main, 0, WindowRectAbsToRel(parent_window, child_window->Rect())); NavRestoreHighlightAfterMove(); } else if (g.OpenPopupStack.Size > 0 && g.OpenPopupStack.back().Window != NULL && !(g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal)) { // Close open popup/menu ClosePopupToLevel(g.OpenPopupStack.Size - 1, true); } else { // Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup) || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow))) g.NavWindow->NavLastIds[0] = 0; g.NavId = 0; } } // Handle PageUp/PageDown/Home/End keys // Called from NavUpdateCreateMoveRequest() which will use our output to create a move request // FIXME-NAV: This doesn't work properly with NavFlattened siblings as we use NavWindow rectangle for reference // FIXME-NAV: how to get Home/End to aim at the beginning/end of a 2D grid? static float ImGui::NavUpdatePageUpPageDown() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.NavWindow; if ((window->Flags & ImGuiWindowFlags_NoNavInputs) || g.NavWindowingTarget != NULL) return 0.0f; const bool page_up_held = IsKeyDown(ImGuiKey_PageUp, ImGuiKeyOwner_None); const bool page_down_held = IsKeyDown(ImGuiKey_PageDown, ImGuiKeyOwner_None); const bool home_pressed = IsKeyPressed(ImGuiKey_Home, ImGuiKeyOwner_None, ImGuiInputFlags_Repeat); const bool end_pressed = IsKeyPressed(ImGuiKey_End, ImGuiKeyOwner_None, ImGuiInputFlags_Repeat); if (page_up_held == page_down_held && home_pressed == end_pressed) // Proceed if either (not both) are pressed, otherwise early out return 0.0f; if (g.NavLayer != ImGuiNavLayer_Main) NavRestoreLayer(ImGuiNavLayer_Main); if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavWindowHasScrollY) { // Fallback manual-scroll when window has no navigable item if (IsKeyPressed(ImGuiKey_PageUp, ImGuiKeyOwner_None, ImGuiInputFlags_Repeat)) SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight()); else if (IsKeyPressed(ImGuiKey_PageDown, ImGuiKeyOwner_None, ImGuiInputFlags_Repeat)) SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight()); else if (home_pressed) SetScrollY(window, 0.0f); else if (end_pressed) SetScrollY(window, window->ScrollMax.y); } else { ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer]; const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight()); float nav_scoring_rect_offset_y = 0.0f; if (IsKeyPressed(ImGuiKey_PageUp, true)) { nav_scoring_rect_offset_y = -page_offset_y; g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset up, we request the down direction (so we can always land on the last item) g.NavMoveClipDir = ImGuiDir_Up; g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet | ImGuiNavMoveFlags_IsPageMove; } else if (IsKeyPressed(ImGuiKey_PageDown, true)) { nav_scoring_rect_offset_y = +page_offset_y; g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset down, we request the up direction (so we can always land on the last item) g.NavMoveClipDir = ImGuiDir_Down; g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet | ImGuiNavMoveFlags_IsPageMove; } else if (home_pressed) { // FIXME-NAV: handling of Home/End is assuming that the top/bottom most item will be visible with Scroll.y == 0/ScrollMax.y // Scrolling will be handled via the ImGuiNavMoveFlags_ScrollToEdgeY flag, we don't scroll immediately to avoid scrolling happening before nav result. // Preserve current horizontal position if we have any. nav_rect_rel.Min.y = nav_rect_rel.Max.y = 0.0f; if (nav_rect_rel.IsInverted()) nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f; g.NavMoveDir = ImGuiDir_Down; g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdgeY; // FIXME-NAV: MoveClipDir left to _None, intentional? } else if (end_pressed) { nav_rect_rel.Min.y = nav_rect_rel.Max.y = window->ContentSize.y; if (nav_rect_rel.IsInverted()) nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f; g.NavMoveDir = ImGuiDir_Up; g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdgeY; // FIXME-NAV: MoveClipDir left to _None, intentional? } return nav_scoring_rect_offset_y; } return 0.0f; } static void ImGui::NavEndFrame() { ImGuiContext& g = *GImGui; // Show CTRL+TAB list window if (g.NavWindowingTarget != NULL) NavUpdateWindowingOverlay(); // Perform wrap-around in menus // FIXME-NAV: Wrap may need to apply a weight bias on the other axis. e.g. 4x4 grid with 2 last items missing on last item won't handle LoopY/WrapY correctly. // FIXME-NAV: Wrap (not Loop) support could be handled by the scoring function and then WrapX would function without an extra frame. if (g.NavWindow && NavMoveRequestButNoResultYet() && (g.NavMoveFlags & ImGuiNavMoveFlags_WrapMask_) && (g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded) == 0) NavUpdateCreateWrappingRequest(); } static void ImGui::NavUpdateCreateWrappingRequest() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.NavWindow; bool do_forward = false; ImRect bb_rel = window->NavRectRel[g.NavLayer]; ImGuiDir clip_dir = g.NavMoveDir; const ImGuiNavMoveFlags move_flags = g.NavMoveFlags; //const ImGuiAxis move_axis = (g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) ? ImGuiAxis_Y : ImGuiAxis_X; if (g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX))) { bb_rel.Min.x = bb_rel.Max.x = window->ContentSize.x + window->WindowPadding.x; if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(-bb_rel.GetHeight()); // Previous row clip_dir = ImGuiDir_Up; } do_forward = true; } if (g.NavMoveDir == ImGuiDir_Right && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX))) { bb_rel.Min.x = bb_rel.Max.x = -window->WindowPadding.x; if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(+bb_rel.GetHeight()); // Next row clip_dir = ImGuiDir_Down; } do_forward = true; } if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY))) { bb_rel.Min.y = bb_rel.Max.y = window->ContentSize.y + window->WindowPadding.y; if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(-bb_rel.GetWidth()); // Previous column clip_dir = ImGuiDir_Left; } do_forward = true; } if (g.NavMoveDir == ImGuiDir_Down && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY))) { bb_rel.Min.y = bb_rel.Max.y = -window->WindowPadding.y; if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(+bb_rel.GetWidth()); // Next column clip_dir = ImGuiDir_Right; } do_forward = true; } if (!do_forward) return; window->NavRectRel[g.NavLayer] = bb_rel; NavClearPreferredPosForAxis(ImGuiAxis_X); NavClearPreferredPosForAxis(ImGuiAxis_Y); NavMoveRequestForward(g.NavMoveDir, clip_dir, move_flags, g.NavMoveScrollFlags); } static int ImGui::FindWindowFocusIndex(ImGuiWindow* window) { ImGuiContext& g = *GImGui; IM_UNUSED(g); int order = window->FocusOrder; IM_ASSERT(window->RootWindow == window); // No child window (not testing _ChildWindow because of docking) IM_ASSERT(g.WindowsFocusOrder[order] == window); return order; } static ImGuiWindow* FindWindowNavFocusable(int i_start, int i_stop, int dir) // FIXME-OPT O(N) { ImGuiContext& g = *GImGui; for (int i = i_start; i >= 0 && i < g.WindowsFocusOrder.Size && i != i_stop; i += dir) if (ImGui::IsWindowNavFocusable(g.WindowsFocusOrder[i])) return g.WindowsFocusOrder[i]; return NULL; } static void NavUpdateWindowingHighlightWindow(int focus_change_dir) { ImGuiContext& g = *GImGui; IM_ASSERT(g.NavWindowingTarget); if (g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal) return; const int i_current = ImGui::FindWindowFocusIndex(g.NavWindowingTarget); ImGuiWindow* window_target = FindWindowNavFocusable(i_current + focus_change_dir, -INT_MAX, focus_change_dir); if (!window_target) window_target = FindWindowNavFocusable((focus_change_dir < 0) ? (g.WindowsFocusOrder.Size - 1) : 0, i_current, focus_change_dir); if (window_target) // Don't reset windowing target if there's a single window in the list { g.NavWindowingTarget = g.NavWindowingTargetAnim = window_target; g.NavWindowingAccumDeltaPos = g.NavWindowingAccumDeltaSize = ImVec2(0.0f, 0.0f); } g.NavWindowingToggleLayer = false; } // Windowing management mode // Keyboard: CTRL+Tab (change focus/move/resize), Alt (toggle menu layer) // Gamepad: Hold Menu/Square (change focus/move/resize), Tap Menu/Square (toggle menu layer) static void ImGui::NavUpdateWindowing() { ImGuiContext& g = *GImGui; ImGuiIO& io = g.IO; ImGuiWindow* apply_focus_window = NULL; bool apply_toggle_layer = false; ImGuiWindow* modal_window = GetTopMostPopupModal(); bool allow_windowing = (modal_window == NULL); // FIXME: This prevent CTRL+TAB from being usable with windows that are inside the Begin-stack of that modal. if (!allow_windowing) g.NavWindowingTarget = NULL; // Fade out if (g.NavWindowingTargetAnim && g.NavWindowingTarget == NULL) { g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha - io.DeltaTime * 10.0f, 0.0f); if (g.DimBgRatio <= 0.0f && g.NavWindowingHighlightAlpha <= 0.0f) g.NavWindowingTargetAnim = NULL; } // Start CTRL+Tab or Square+L/R window selection // (g.ConfigNavWindowingKeyNext/g.ConfigNavWindowingKeyPrev defaults are ImGuiMod_Ctrl|ImGuiKey_Tab and ImGuiMod_Ctrl|ImGuiMod_Shift|ImGuiKey_Tab) const ImGuiID owner_id = ImHashStr("###NavUpdateWindowing"); const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0; const bool keyboard_next_window = allow_windowing && g.ConfigNavWindowingKeyNext && Shortcut(g.ConfigNavWindowingKeyNext, owner_id, ImGuiInputFlags_Repeat | ImGuiInputFlags_RouteAlways); const bool keyboard_prev_window = allow_windowing && g.ConfigNavWindowingKeyPrev && Shortcut(g.ConfigNavWindowingKeyPrev, owner_id, ImGuiInputFlags_Repeat | ImGuiInputFlags_RouteAlways); const bool start_windowing_with_gamepad = allow_windowing && nav_gamepad_active && !g.NavWindowingTarget && IsKeyPressed(ImGuiKey_NavGamepadMenu, 0, ImGuiInputFlags_None); const bool start_windowing_with_keyboard = allow_windowing && !g.NavWindowingTarget && (keyboard_next_window || keyboard_prev_window); // Note: enabled even without NavEnableKeyboard! if (start_windowing_with_gamepad || start_windowing_with_keyboard) if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1)) { g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow; g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f; g.NavWindowingAccumDeltaPos = g.NavWindowingAccumDeltaSize = ImVec2(0.0f, 0.0f); g.NavWindowingToggleLayer = start_windowing_with_gamepad ? true : false; // Gamepad starts toggling layer g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad; // Register ownership of our mods. Using ImGuiInputFlags_RouteGlobalHigh in the Shortcut() calls instead would probably be correct but may have more side-effects. if (keyboard_next_window || keyboard_prev_window) SetKeyOwnersForKeyChord((g.ConfigNavWindowingKeyNext | g.ConfigNavWindowingKeyPrev) & ImGuiMod_Mask_, owner_id); } // Gamepad update g.NavWindowingTimer += io.DeltaTime; if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_Gamepad) { // Highlight only appears after a brief time holding the button, so that a fast tap on PadMenu (to toggle NavLayer) doesn't add visual noise g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // Select window to focus const int focus_change_dir = (int)IsKeyPressed(ImGuiKey_GamepadL1) - (int)IsKeyPressed(ImGuiKey_GamepadR1); if (focus_change_dir != 0) { NavUpdateWindowingHighlightWindow(focus_change_dir); g.NavWindowingHighlightAlpha = 1.0f; } // Single press toggles NavLayer, long press with L/R apply actual focus on release (until then the window was merely rendered top-most) if (!IsKeyDown(ImGuiKey_NavGamepadMenu)) { g.NavWindowingToggleLayer &= (g.NavWindowingHighlightAlpha < 1.0f); // Once button was held long enough we don't consider it a tap-to-toggle-layer press anymore. if (g.NavWindowingToggleLayer && g.NavWindow) apply_toggle_layer = true; else if (!g.NavWindowingToggleLayer) apply_focus_window = g.NavWindowingTarget; g.NavWindowingTarget = NULL; } } // Keyboard: Focus if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_Keyboard) { // Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise ImGuiKeyChord shared_mods = ((g.ConfigNavWindowingKeyNext ? g.ConfigNavWindowingKeyNext : ImGuiMod_Mask_) & (g.ConfigNavWindowingKeyPrev ? g.ConfigNavWindowingKeyPrev : ImGuiMod_Mask_)) & ImGuiMod_Mask_; IM_ASSERT(shared_mods != 0); // Next/Prev shortcut currently needs a shared modifier to "hold", otherwise Prev actions would keep cycling between two windows. g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // 1.0f if (keyboard_next_window || keyboard_prev_window) NavUpdateWindowingHighlightWindow(keyboard_next_window ? -1 : +1); else if ((io.KeyMods & shared_mods) != shared_mods) apply_focus_window = g.NavWindowingTarget; } // Keyboard: Press and Release ALT to toggle menu layer const ImGuiKey windowing_toggle_keys[] = { ImGuiKey_LeftAlt, ImGuiKey_RightAlt }; for (ImGuiKey windowing_toggle_key : windowing_toggle_keys) if (nav_keyboard_active && IsKeyPressed(windowing_toggle_key, ImGuiKeyOwner_None)) { g.NavWindowingToggleLayer = true; g.NavWindowingToggleKey = windowing_toggle_key; g.NavInputSource = ImGuiInputSource_Keyboard; break; } if (g.NavWindowingToggleLayer && g.NavInputSource == ImGuiInputSource_Keyboard) { // We cancel toggling nav layer when any text has been typed (generally while holding Alt). (See #370) // We cancel toggling nav layer when other modifiers are pressed. (See #4439) // - AltGR is Alt+Ctrl on some layout but we can't reliably detect it (not all backends/systems/layout emit it as Alt+Ctrl). // We cancel toggling nav layer if an owner has claimed the key. if (io.InputQueueCharacters.Size > 0 || io.KeyCtrl || io.KeyShift || io.KeySuper) g.NavWindowingToggleLayer = false; if (TestKeyOwner(g.NavWindowingToggleKey, ImGuiKeyOwner_None) == false || TestKeyOwner(ImGuiMod_Alt, ImGuiKeyOwner_None) == false) g.NavWindowingToggleLayer = false; // Apply layer toggle on Alt release // Important: as before version <18314 we lacked an explicit IO event for focus gain/loss, we also compare mouse validity to detect old backends clearing mouse pos on focus loss. if (IsKeyReleased(g.NavWindowingToggleKey) && g.NavWindowingToggleLayer) if (g.ActiveId == 0 || g.ActiveIdAllowOverlap) if (IsMousePosValid(&io.MousePos) == IsMousePosValid(&io.MousePosPrev)) apply_toggle_layer = true; if (!IsKeyDown(g.NavWindowingToggleKey)) g.NavWindowingToggleLayer = false; } // Move window if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) { ImVec2 nav_move_dir; if (g.NavInputSource == ImGuiInputSource_Keyboard && !io.KeyShift) nav_move_dir = GetKeyMagnitude2d(ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow); if (g.NavInputSource == ImGuiInputSource_Gamepad) nav_move_dir = GetKeyMagnitude2d(ImGuiKey_GamepadLStickLeft, ImGuiKey_GamepadLStickRight, ImGuiKey_GamepadLStickUp, ImGuiKey_GamepadLStickDown); if (nav_move_dir.x != 0.0f || nav_move_dir.y != 0.0f) { const float NAV_MOVE_SPEED = 800.0f; const float move_step = NAV_MOVE_SPEED * io.DeltaTime * ImMin(io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y); g.NavWindowingAccumDeltaPos += nav_move_dir * move_step; g.NavDisableMouseHover = true; ImVec2 accum_floored = ImTrunc(g.NavWindowingAccumDeltaPos); if (accum_floored.x != 0.0f || accum_floored.y != 0.0f) { ImGuiWindow* moving_window = g.NavWindowingTarget->RootWindow; SetWindowPos(moving_window, moving_window->Pos + accum_floored, ImGuiCond_Always); g.NavWindowingAccumDeltaPos -= accum_floored; } } } // Apply final focus if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindow)) { ClearActiveID(); NavRestoreHighlightAfterMove(); ClosePopupsOverWindow(apply_focus_window, false); FocusWindow(apply_focus_window, ImGuiFocusRequestFlags_RestoreFocusedChild); apply_focus_window = g.NavWindow; if (apply_focus_window->NavLastIds[0] == 0) NavInitWindow(apply_focus_window, false); // If the window has ONLY a menu layer (no main layer), select it directly // Use NavLayersActiveMaskNext since windows didn't have a chance to be Begin()-ed on this frame, // so CTRL+Tab where the keys are only held for 1 frame will be able to use correct layers mask since // the target window as already been previewed once. // FIXME-NAV: This should be done in NavInit.. or in FocusWindow... However in both of those cases, // we won't have a guarantee that windows has been visible before and therefore NavLayersActiveMask* // won't be valid. if (apply_focus_window->DC.NavLayersActiveMaskNext == (1 << ImGuiNavLayer_Menu)) g.NavLayer = ImGuiNavLayer_Menu; } if (apply_focus_window) g.NavWindowingTarget = NULL; // Apply menu/layer toggle if (apply_toggle_layer && g.NavWindow) { ClearActiveID(); // Move to parent menu if necessary ImGuiWindow* new_nav_window = g.NavWindow; while (new_nav_window->ParentWindow && (new_nav_window->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) == 0 && (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0) new_nav_window = new_nav_window->ParentWindow; if (new_nav_window != g.NavWindow) { ImGuiWindow* old_nav_window = g.NavWindow; FocusWindow(new_nav_window); new_nav_window->NavLastChildNavWindow = old_nav_window; } // Toggle layer const ImGuiNavLayer new_nav_layer = (g.NavWindow->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) ? (ImGuiNavLayer)((int)g.NavLayer ^ 1) : ImGuiNavLayer_Main; if (new_nav_layer != g.NavLayer) { // Reinitialize navigation when entering menu bar with the Alt key (FIXME: could be a properly of the layer?) if (new_nav_layer == ImGuiNavLayer_Menu) g.NavWindow->NavLastIds[new_nav_layer] = 0; NavRestoreLayer(new_nav_layer); NavRestoreHighlightAfterMove(); } } } // Window has already passed the IsWindowNavFocusable() static const char* GetFallbackWindowNameForWindowingList(ImGuiWindow* window) { if (window->Flags & ImGuiWindowFlags_Popup) return ImGui::LocalizeGetMsg(ImGuiLocKey_WindowingPopup); if ((window->Flags & ImGuiWindowFlags_MenuBar) && strcmp(window->Name, "##MainMenuBar") == 0) return ImGui::LocalizeGetMsg(ImGuiLocKey_WindowingMainMenuBar); return ImGui::LocalizeGetMsg(ImGuiLocKey_WindowingUntitled); } // Overlay displayed when using CTRL+TAB. Called by EndFrame(). void ImGui::NavUpdateWindowingOverlay() { ImGuiContext& g = *GImGui; IM_ASSERT(g.NavWindowingTarget != NULL); if (g.NavWindowingTimer < NAV_WINDOWING_LIST_APPEAR_DELAY) return; if (g.NavWindowingListWindow == NULL) g.NavWindowingListWindow = FindWindowByName("###NavWindowingList"); const ImGuiViewport* viewport = GetMainViewport(); SetNextWindowSizeConstraints(ImVec2(viewport->Size.x * 0.20f, viewport->Size.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX)); SetNextWindowPos(viewport->GetCenter(), ImGuiCond_Always, ImVec2(0.5f, 0.5f)); PushStyleVar(ImGuiStyleVar_WindowPadding, g.Style.WindowPadding * 2.0f); Begin("###NavWindowingList", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings); for (int n = g.WindowsFocusOrder.Size - 1; n >= 0; n--) { ImGuiWindow* window = g.WindowsFocusOrder[n]; IM_ASSERT(window != NULL); // Fix static analyzers if (!IsWindowNavFocusable(window)) continue; const char* label = window->Name; if (label == FindRenderedTextEnd(label)) label = GetFallbackWindowNameForWindowingList(window); Selectable(label, g.NavWindowingTarget == window); } End(); PopStyleVar(); } //----------------------------------------------------------------------------- // [SECTION] DRAG AND DROP //----------------------------------------------------------------------------- bool ImGui::IsDragDropActive() { ImGuiContext& g = *GImGui; return g.DragDropActive; } void ImGui::ClearDragDrop() { ImGuiContext& g = *GImGui; g.DragDropActive = false; g.DragDropPayload.Clear(); g.DragDropAcceptFlags = ImGuiDragDropFlags_None; g.DragDropAcceptIdCurr = g.DragDropAcceptIdPrev = 0; g.DragDropAcceptIdCurrRectSurface = FLT_MAX; g.DragDropAcceptFrameCount = -1; g.DragDropPayloadBufHeap.clear(); memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal)); } bool ImGui::BeginTooltipHidden() { ImGuiContext& g = *GImGui; bool ret = Begin("##Tooltip_Hidden", NULL, ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize); SetWindowHiddenAndSkipItemsForCurrentFrame(g.CurrentWindow); return ret; } // When this returns true you need to: a) call SetDragDropPayload() exactly once, b) you may render the payload visual/description, c) call EndDragDropSource() // If the item has an identifier: // - This assume/require the item to be activated (typically via ButtonBehavior). // - Therefore if you want to use this with a mouse button other than left mouse button, it is up to the item itself to activate with another button. // - We then pull and use the mouse button that was used to activate the item and use it to carry on the drag. // If the item has no identifier: // - Currently always assume left mouse button. bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; // FIXME-DRAGDROP: While in the common-most "drag from non-zero active id" case we can tell the mouse button, // in both SourceExtern and id==0 cases we may requires something else (explicit flags or some heuristic). ImGuiMouseButton mouse_button = ImGuiMouseButton_Left; bool source_drag_active = false; ImGuiID source_id = 0; ImGuiID source_parent_id = 0; if (!(flags & ImGuiDragDropFlags_SourceExtern)) { source_id = g.LastItemData.ID; if (source_id != 0) { // Common path: items with ID if (g.ActiveId != source_id) return false; if (g.ActiveIdMouseButton != -1) mouse_button = g.ActiveIdMouseButton; if (g.IO.MouseDown[mouse_button] == false || window->SkipItems) return false; g.ActiveIdAllowOverlap = false; } else { // Uncommon path: items without ID if (g.IO.MouseDown[mouse_button] == false || window->SkipItems) return false; if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) == 0 && (g.ActiveId == 0 || g.ActiveIdWindow != window)) return false; // If you want to use BeginDragDropSource() on an item with no unique identifier for interaction, such as Text() or Image(), you need to: // A) Read the explanation below, B) Use the ImGuiDragDropFlags_SourceAllowNullID flag. if (!(flags & ImGuiDragDropFlags_SourceAllowNullID)) { IM_ASSERT(0); return false; } // Magic fallback to handle items with no assigned ID, e.g. Text(), Image() // We build a throwaway ID based on current ID stack + relative AABB of items in window. // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING/RESIZINGG OF THE WIDGET, so if your widget moves your dragging operation will be canceled. // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive. // Rely on keeping other window->LastItemXXX fields intact. source_id = g.LastItemData.ID = window->GetIDFromRectangle(g.LastItemData.Rect); KeepAliveID(source_id); bool is_hovered = ItemHoverable(g.LastItemData.Rect, source_id, g.LastItemData.InFlags); if (is_hovered && g.IO.MouseClicked[mouse_button]) { SetActiveID(source_id, window); FocusWindow(window); } if (g.ActiveId == source_id) // Allow the underlying widget to display/return hovered during the mouse release frame, else we would get a flicker. g.ActiveIdAllowOverlap = is_hovered; } if (g.ActiveId != source_id) return false; source_parent_id = window->IDStack.back(); source_drag_active = IsMouseDragging(mouse_button); // Disable navigation and key inputs while dragging + cancel existing request if any SetActiveIdUsingAllKeyboardKeys(); } else { window = NULL; source_id = ImHashStr("#SourceExtern"); source_drag_active = true; } if (source_drag_active) { if (!g.DragDropActive) { IM_ASSERT(source_id != 0); ClearDragDrop(); ImGuiPayload& payload = g.DragDropPayload; payload.SourceId = source_id; payload.SourceParentId = source_parent_id; g.DragDropActive = true; g.DragDropSourceFlags = flags; g.DragDropMouseButton = mouse_button; if (payload.SourceId == g.ActiveId) g.ActiveIdNoClearOnFocusLoss = true; } g.DragDropSourceFrameCount = g.FrameCount; g.DragDropWithinSource = true; if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip)) { // Target can request the Source to not display its tooltip (we use a dedicated flag to make this request explicit) // We unfortunately can't just modify the source flags and skip the call to BeginTooltip, as caller may be emitting contents. bool ret; if (g.DragDropAcceptIdPrev && (g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip)) ret = BeginTooltipHidden(); else ret = BeginTooltip(); IM_ASSERT(ret); // FIXME-NEWBEGIN: If this ever becomes false, we need to Begin("##Hidden", NULL, ImGuiWindowFlags_NoSavedSettings) + SetWindowHiddendAndSkipItemsForCurrentFrame(). IM_UNUSED(ret); } if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern)) g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_HoveredRect; return true; } return false; } void ImGui::EndDragDropSource() { ImGuiContext& g = *GImGui; IM_ASSERT(g.DragDropActive); IM_ASSERT(g.DragDropWithinSource && "Not after a BeginDragDropSource()?"); if (!(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip)) EndTooltip(); // Discard the drag if have not called SetDragDropPayload() if (g.DragDropPayload.DataFrameCount == -1) ClearDragDrop(); g.DragDropWithinSource = false; } // Use 'cond' to choose to submit payload on drag start or every frame bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond) { ImGuiContext& g = *GImGui; ImGuiPayload& payload = g.DragDropPayload; if (cond == 0) cond = ImGuiCond_Always; IM_ASSERT(type != NULL); IM_ASSERT(strlen(type) < IM_ARRAYSIZE(payload.DataType) && "Payload type can be at most 32 characters long"); IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0)); IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once); IM_ASSERT(payload.SourceId != 0); // Not called between BeginDragDropSource() and EndDragDropSource() if (cond == ImGuiCond_Always || payload.DataFrameCount == -1) { // Copy payload ImStrncpy(payload.DataType, type, IM_ARRAYSIZE(payload.DataType)); g.DragDropPayloadBufHeap.resize(0); if (data_size > sizeof(g.DragDropPayloadBufLocal)) { // Store in heap g.DragDropPayloadBufHeap.resize((int)data_size); payload.Data = g.DragDropPayloadBufHeap.Data; memcpy(payload.Data, data, data_size); } else if (data_size > 0) { // Store locally memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal)); payload.Data = g.DragDropPayloadBufLocal; memcpy(payload.Data, data, data_size); } else { payload.Data = NULL; } payload.DataSize = (int)data_size; } payload.DataFrameCount = g.FrameCount; // Return whether the payload has been accepted return (g.DragDropAcceptFrameCount == g.FrameCount) || (g.DragDropAcceptFrameCount == g.FrameCount - 1); } bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id) { ImGuiContext& g = *GImGui; if (!g.DragDropActive) return false; ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* hovered_window = g.HoveredWindowUnderMovingWindow; if (hovered_window == NULL || window->RootWindow != hovered_window->RootWindow) return false; IM_ASSERT(id != 0); if (!IsMouseHoveringRect(bb.Min, bb.Max) || (id == g.DragDropPayload.SourceId)) return false; if (window->SkipItems) return false; IM_ASSERT(g.DragDropWithinTarget == false); g.DragDropTargetRect = bb; g.DragDropTargetClipRect = window->ClipRect; // May want to be overriden by user depending on use case? g.DragDropTargetId = id; g.DragDropWithinTarget = true; return true; } // We don't use BeginDragDropTargetCustom() and duplicate its code because: // 1) we use LastItemData's ImGuiItemStatusFlags_HoveredRect which handles items that push a temporarily clip rectangle in their code. Calling BeginDragDropTargetCustom(LastItemRect) would not handle them. // 2) and it's faster. as this code may be very frequently called, we want to early out as fast as we can. // Also note how the HoveredWindow test is positioned differently in both functions (in both functions we optimize for the cheapest early out case) bool ImGui::BeginDragDropTarget() { ImGuiContext& g = *GImGui; if (!g.DragDropActive) return false; ImGuiWindow* window = g.CurrentWindow; if (!(g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect)) return false; ImGuiWindow* hovered_window = g.HoveredWindowUnderMovingWindow; if (hovered_window == NULL || window->RootWindow != hovered_window->RootWindow || window->SkipItems) return false; const ImRect& display_rect = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? g.LastItemData.DisplayRect : g.LastItemData.Rect; ImGuiID id = g.LastItemData.ID; if (id == 0) { id = window->GetIDFromRectangle(display_rect); KeepAliveID(id); } if (g.DragDropPayload.SourceId == id) return false; IM_ASSERT(g.DragDropWithinTarget == false); g.DragDropTargetRect = display_rect; g.DragDropTargetClipRect = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HasClipRect) ? g.LastItemData.ClipRect : window->ClipRect; g.DragDropTargetId = id; g.DragDropWithinTarget = true; return true; } bool ImGui::IsDragDropPayloadBeingAccepted() { ImGuiContext& g = *GImGui; return g.DragDropActive && g.DragDropAcceptIdPrev != 0; } const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags) { ImGuiContext& g = *GImGui; ImGuiPayload& payload = g.DragDropPayload; IM_ASSERT(g.DragDropActive); // Not called between BeginDragDropTarget() and EndDragDropTarget() ? IM_ASSERT(payload.DataFrameCount != -1); // Forgot to call EndDragDropTarget() ? if (type != NULL && !payload.IsDataType(type)) return NULL; // Accept smallest drag target bounding box, this allows us to nest drag targets conveniently without ordering constraints. // NB: We currently accept NULL id as target. However, overlapping targets requires a unique ID to function! const bool was_accepted_previously = (g.DragDropAcceptIdPrev == g.DragDropTargetId); ImRect r = g.DragDropTargetRect; float r_surface = r.GetWidth() * r.GetHeight(); if (r_surface > g.DragDropAcceptIdCurrRectSurface) return NULL; g.DragDropAcceptFlags = flags; g.DragDropAcceptIdCurr = g.DragDropTargetId; g.DragDropAcceptIdCurrRectSurface = r_surface; //IMGUI_DEBUG_LOG("AcceptDragDropPayload(): %08X: accept\n", g.DragDropTargetId); // Render default drop visuals payload.Preview = was_accepted_previously; flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that live for 1 frame) if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview) RenderDragDropTargetRect(r, g.DragDropTargetClipRect); g.DragDropAcceptFrameCount = g.FrameCount; payload.Delivery = was_accepted_previously && !IsMouseDown(g.DragDropMouseButton); // For extern drag sources affecting OS window focus, it's easier to just test !IsMouseDown() instead of IsMouseReleased() if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery)) return NULL; //IMGUI_DEBUG_LOG("AcceptDragDropPayload(): %08X: return payload\n", g.DragDropTargetId); return &payload; } // FIXME-STYLE FIXME-DRAGDROP: Settle on a proper default visuals for drop target. void ImGui::RenderDragDropTargetRect(const ImRect& bb, const ImRect& item_clip_rect) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImRect bb_display = bb; bb_display.ClipWith(item_clip_rect); // Clip THEN expand so we have a way to visualize that target is not entirely visible. bb_display.Expand(3.5f); bool push_clip_rect = !window->ClipRect.Contains(bb_display); if (push_clip_rect) window->DrawList->PushClipRectFullScreen(); window->DrawList->AddRect(bb_display.Min, bb_display.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, 0, 2.0f); if (push_clip_rect) window->DrawList->PopClipRect(); } const ImGuiPayload* ImGui::GetDragDropPayload() { ImGuiContext& g = *GImGui; return (g.DragDropActive && g.DragDropPayload.DataFrameCount != -1) ? &g.DragDropPayload : NULL; } void ImGui::EndDragDropTarget() { ImGuiContext& g = *GImGui; IM_ASSERT(g.DragDropActive); IM_ASSERT(g.DragDropWithinTarget); g.DragDropWithinTarget = false; // Clear drag and drop state payload right after delivery if (g.DragDropPayload.Delivery) ClearDragDrop(); } //----------------------------------------------------------------------------- // [SECTION] LOGGING/CAPTURING //----------------------------------------------------------------------------- // All text output from the interface can be captured into tty/file/clipboard. // By default, tree nodes are automatically opened during logging. //----------------------------------------------------------------------------- // Pass text data straight to log (without being displayed) static inline void LogTextV(ImGuiContext& g, const char* fmt, va_list args) { if (g.LogFile) { g.LogBuffer.Buf.resize(0); g.LogBuffer.appendfv(fmt, args); ImFileWrite(g.LogBuffer.c_str(), sizeof(char), (ImU64)g.LogBuffer.size(), g.LogFile); } else { g.LogBuffer.appendfv(fmt, args); } } void ImGui::LogText(const char* fmt, ...) { ImGuiContext& g = *GImGui; if (!g.LogEnabled) return; va_list args; va_start(args, fmt); LogTextV(g, fmt, args); va_end(args); } void ImGui::LogTextV(const char* fmt, va_list args) { ImGuiContext& g = *GImGui; if (!g.LogEnabled) return; LogTextV(g, fmt, args); } // Internal version that takes a position to decide on newline placement and pad items according to their depth. // We split text into individual lines to add current tree level padding // FIXME: This code is a little complicated perhaps, considering simplifying the whole system. void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; const char* prefix = g.LogNextPrefix; const char* suffix = g.LogNextSuffix; g.LogNextPrefix = g.LogNextSuffix = NULL; if (!text_end) text_end = FindRenderedTextEnd(text, text_end); const bool log_new_line = ref_pos && (ref_pos->y > g.LogLinePosY + g.Style.FramePadding.y + 1); if (ref_pos) g.LogLinePosY = ref_pos->y; if (log_new_line) { LogText(IM_NEWLINE); g.LogLineFirstItem = true; } if (prefix) LogRenderedText(ref_pos, prefix, prefix + strlen(prefix)); // Calculate end ourself to ensure "##" are included here. // Re-adjust padding if we have popped out of our starting depth if (g.LogDepthRef > window->DC.TreeDepth) g.LogDepthRef = window->DC.TreeDepth; const int tree_depth = (window->DC.TreeDepth - g.LogDepthRef); const char* text_remaining = text; for (;;) { // Split the string. Each new line (after a '\n') is followed by indentation corresponding to the current depth of our log entry. // We don't add a trailing \n yet to allow a subsequent item on the same line to be captured. const char* line_start = text_remaining; const char* line_end = ImStreolRange(line_start, text_end); const bool is_last_line = (line_end == text_end); if (line_start != line_end || !is_last_line) { const int line_length = (int)(line_end - line_start); const int indentation = g.LogLineFirstItem ? tree_depth * 4 : 1; LogText("%*s%.*s", indentation, "", line_length, line_start); g.LogLineFirstItem = false; if (*line_end == '\n') { LogText(IM_NEWLINE); g.LogLineFirstItem = true; } } if (is_last_line) break; text_remaining = line_end + 1; } if (suffix) LogRenderedText(ref_pos, suffix, suffix + strlen(suffix)); } // Start logging/capturing text output void ImGui::LogBegin(ImGuiLogType type, int auto_open_depth) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(g.LogEnabled == false); IM_ASSERT(g.LogFile == NULL); IM_ASSERT(g.LogBuffer.empty()); g.LogEnabled = true; g.LogType = type; g.LogNextPrefix = g.LogNextSuffix = NULL; g.LogDepthRef = window->DC.TreeDepth; g.LogDepthToExpand = ((auto_open_depth >= 0) ? auto_open_depth : g.LogDepthToExpandDefault); g.LogLinePosY = FLT_MAX; g.LogLineFirstItem = true; } // Important: doesn't copy underlying data, use carefully (prefix/suffix must be in scope at the time of the next LogRenderedText) void ImGui::LogSetNextTextDecoration(const char* prefix, const char* suffix) { ImGuiContext& g = *GImGui; g.LogNextPrefix = prefix; g.LogNextSuffix = suffix; } void ImGui::LogToTTY(int auto_open_depth) { ImGuiContext& g = *GImGui; if (g.LogEnabled) return; IM_UNUSED(auto_open_depth); #ifndef IMGUI_DISABLE_TTY_FUNCTIONS LogBegin(ImGuiLogType_TTY, auto_open_depth); g.LogFile = stdout; #endif } // Start logging/capturing text output to given file void ImGui::LogToFile(int auto_open_depth, const char* filename) { ImGuiContext& g = *GImGui; if (g.LogEnabled) return; // FIXME: We could probably open the file in text mode "at", however note that clipboard/buffer logging will still // be subject to outputting OS-incompatible carriage return if within strings the user doesn't use IM_NEWLINE. // By opening the file in binary mode "ab" we have consistent output everywhere. if (!filename) filename = g.IO.LogFilename; if (!filename || !filename[0]) return; ImFileHandle f = ImFileOpen(filename, "ab"); if (!f) { IM_ASSERT(0); return; } LogBegin(ImGuiLogType_File, auto_open_depth); g.LogFile = f; } // Start logging/capturing text output to clipboard void ImGui::LogToClipboard(int auto_open_depth) { ImGuiContext& g = *GImGui; if (g.LogEnabled) return; LogBegin(ImGuiLogType_Clipboard, auto_open_depth); } void ImGui::LogToBuffer(int auto_open_depth) { ImGuiContext& g = *GImGui; if (g.LogEnabled) return; LogBegin(ImGuiLogType_Buffer, auto_open_depth); } void ImGui::LogFinish() { ImGuiContext& g = *GImGui; if (!g.LogEnabled) return; LogText(IM_NEWLINE); switch (g.LogType) { case ImGuiLogType_TTY: #ifndef IMGUI_DISABLE_TTY_FUNCTIONS fflush(g.LogFile); #endif break; case ImGuiLogType_File: ImFileClose(g.LogFile); break; case ImGuiLogType_Buffer: break; case ImGuiLogType_Clipboard: if (!g.LogBuffer.empty()) SetClipboardText(g.LogBuffer.begin()); break; case ImGuiLogType_None: IM_ASSERT(0); break; } g.LogEnabled = false; g.LogType = ImGuiLogType_None; g.LogFile = NULL; g.LogBuffer.clear(); } // Helper to display logging buttons // FIXME-OBSOLETE: We should probably obsolete this and let the user have their own helper (this is one of the oldest function alive!) void ImGui::LogButtons() { ImGuiContext& g = *GImGui; PushID("LogButtons"); #ifndef IMGUI_DISABLE_TTY_FUNCTIONS const bool log_to_tty = Button("Log To TTY"); SameLine(); #else const bool log_to_tty = false; #endif const bool log_to_file = Button("Log To File"); SameLine(); const bool log_to_clipboard = Button("Log To Clipboard"); SameLine(); PushTabStop(false); SetNextItemWidth(80.0f); SliderInt("Default Depth", &g.LogDepthToExpandDefault, 0, 9, NULL); PopTabStop(); PopID(); // Start logging at the end of the function so that the buttons don't appear in the log if (log_to_tty) LogToTTY(); if (log_to_file) LogToFile(); if (log_to_clipboard) LogToClipboard(); } //----------------------------------------------------------------------------- // [SECTION] SETTINGS //----------------------------------------------------------------------------- // - UpdateSettings() [Internal] // - MarkIniSettingsDirty() [Internal] // - FindSettingsHandler() [Internal] // - ClearIniSettings() [Internal] // - LoadIniSettingsFromDisk() // - LoadIniSettingsFromMemory() // - SaveIniSettingsToDisk() // - SaveIniSettingsToMemory() //----------------------------------------------------------------------------- // - CreateNewWindowSettings() [Internal] // - FindWindowSettingsByID() [Internal] // - FindWindowSettingsByWindow() [Internal] // - ClearWindowSettings() [Internal] // - WindowSettingsHandler_***() [Internal] //----------------------------------------------------------------------------- // Called by NewFrame() void ImGui::UpdateSettings() { // Load settings on first frame (if not explicitly loaded manually before) ImGuiContext& g = *GImGui; if (!g.SettingsLoaded) { IM_ASSERT(g.SettingsWindows.empty()); if (g.IO.IniFilename) LoadIniSettingsFromDisk(g.IO.IniFilename); g.SettingsLoaded = true; } // Save settings (with a delay after the last modification, so we don't spam disk too much) if (g.SettingsDirtyTimer > 0.0f) { g.SettingsDirtyTimer -= g.IO.DeltaTime; if (g.SettingsDirtyTimer <= 0.0f) { if (g.IO.IniFilename != NULL) SaveIniSettingsToDisk(g.IO.IniFilename); else g.IO.WantSaveIniSettings = true; // Let user know they can call SaveIniSettingsToMemory(). user will need to clear io.WantSaveIniSettings themselves. g.SettingsDirtyTimer = 0.0f; } } } void ImGui::MarkIniSettingsDirty() { ImGuiContext& g = *GImGui; if (g.SettingsDirtyTimer <= 0.0f) g.SettingsDirtyTimer = g.IO.IniSavingRate; } void ImGui::MarkIniSettingsDirty(ImGuiWindow* window) { ImGuiContext& g = *GImGui; if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings)) if (g.SettingsDirtyTimer <= 0.0f) g.SettingsDirtyTimer = g.IO.IniSavingRate; } void ImGui::AddSettingsHandler(const ImGuiSettingsHandler* handler) { ImGuiContext& g = *GImGui; IM_ASSERT(FindSettingsHandler(handler->TypeName) == NULL); g.SettingsHandlers.push_back(*handler); } void ImGui::RemoveSettingsHandler(const char* type_name) { ImGuiContext& g = *GImGui; if (ImGuiSettingsHandler* handler = FindSettingsHandler(type_name)) g.SettingsHandlers.erase(handler); } ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name) { ImGuiContext& g = *GImGui; const ImGuiID type_hash = ImHashStr(type_name); for (ImGuiSettingsHandler& handler : g.SettingsHandlers) if (handler.TypeHash == type_hash) return &handler; return NULL; } // Clear all settings (windows, tables, docking etc.) void ImGui::ClearIniSettings() { ImGuiContext& g = *GImGui; g.SettingsIniData.clear(); for (ImGuiSettingsHandler& handler : g.SettingsHandlers) if (handler.ClearAllFn != NULL) handler.ClearAllFn(&g, &handler); } void ImGui::LoadIniSettingsFromDisk(const char* ini_filename) { size_t file_data_size = 0; char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", &file_data_size); if (!file_data) return; if (file_data_size > 0) LoadIniSettingsFromMemory(file_data, (size_t)file_data_size); IM_FREE(file_data); } // Zero-tolerance, no error reporting, cheap .ini parsing // Set ini_size==0 to let us use strlen(ini_data). Do not call this function with a 0 if your buffer is actually empty! void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size) { ImGuiContext& g = *GImGui; IM_ASSERT(g.Initialized); //IM_ASSERT(!g.WithinFrameScope && "Cannot be called between NewFrame() and EndFrame()"); //IM_ASSERT(g.SettingsLoaded == false && g.FrameCount == 0); // For user convenience, we allow passing a non zero-terminated string (hence the ini_size parameter). // For our convenience and to make the code simpler, we'll also write zero-terminators within the buffer. So let's create a writable copy.. if (ini_size == 0) ini_size = strlen(ini_data); g.SettingsIniData.Buf.resize((int)ini_size + 1); char* const buf = g.SettingsIniData.Buf.Data; char* const buf_end = buf + ini_size; memcpy(buf, ini_data, ini_size); buf_end[0] = 0; // Call pre-read handlers // Some types will clear their data (e.g. dock information) some types will allow merge/override (window) for (ImGuiSettingsHandler& handler : g.SettingsHandlers) if (handler.ReadInitFn != NULL) handler.ReadInitFn(&g, &handler); void* entry_data = NULL; ImGuiSettingsHandler* entry_handler = NULL; char* line_end = NULL; for (char* line = buf; line < buf_end; line = line_end + 1) { // Skip new lines markers, then find end of the line while (*line == '\n' || *line == '\r') line++; line_end = line; while (line_end < buf_end && *line_end != '\n' && *line_end != '\r') line_end++; line_end[0] = 0; if (line[0] == ';') continue; if (line[0] == '[' && line_end > line && line_end[-1] == ']') { // Parse "[Type][Name]". Note that 'Name' can itself contains [] characters, which is acceptable with the current format and parsing code. line_end[-1] = 0; const char* name_end = line_end - 1; const char* type_start = line + 1; char* type_end = (char*)(void*)ImStrchrRange(type_start, name_end, ']'); const char* name_start = type_end ? ImStrchrRange(type_end + 1, name_end, '[') : NULL; if (!type_end || !name_start) continue; *type_end = 0; // Overwrite first ']' name_start++; // Skip second '[' entry_handler = FindSettingsHandler(type_start); entry_data = entry_handler ? entry_handler->ReadOpenFn(&g, entry_handler, name_start) : NULL; } else if (entry_handler != NULL && entry_data != NULL) { // Let type handler parse the line entry_handler->ReadLineFn(&g, entry_handler, entry_data, line); } } g.SettingsLoaded = true; // [DEBUG] Restore untouched copy so it can be browsed in Metrics (not strictly necessary) memcpy(buf, ini_data, ini_size); // Call post-read handlers for (ImGuiSettingsHandler& handler : g.SettingsHandlers) if (handler.ApplyAllFn != NULL) handler.ApplyAllFn(&g, &handler); } void ImGui::SaveIniSettingsToDisk(const char* ini_filename) { ImGuiContext& g = *GImGui; g.SettingsDirtyTimer = 0.0f; if (!ini_filename) return; size_t ini_data_size = 0; const char* ini_data = SaveIniSettingsToMemory(&ini_data_size); ImFileHandle f = ImFileOpen(ini_filename, "wt"); if (!f) return; ImFileWrite(ini_data, sizeof(char), ini_data_size, f); ImFileClose(f); } // Call registered handlers (e.g. SettingsHandlerWindow_WriteAll() + custom handlers) to write their stuff into a text buffer const char* ImGui::SaveIniSettingsToMemory(size_t* out_size) { ImGuiContext& g = *GImGui; g.SettingsDirtyTimer = 0.0f; g.SettingsIniData.Buf.resize(0); g.SettingsIniData.Buf.push_back(0); for (ImGuiSettingsHandler& handler : g.SettingsHandlers) handler.WriteAllFn(&g, &handler, &g.SettingsIniData); if (out_size) *out_size = (size_t)g.SettingsIniData.size(); return g.SettingsIniData.c_str(); } ImGuiWindowSettings* ImGui::CreateNewWindowSettings(const char* name) { ImGuiContext& g = *GImGui; if (g.IO.ConfigDebugIniSettings == false) { // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID() // Preserve the full string when ConfigDebugVerboseIniSettings is set to make .ini inspection easier. if (const char* p = strstr(name, "###")) name = p; } const size_t name_len = strlen(name); // Allocate chunk const size_t chunk_size = sizeof(ImGuiWindowSettings) + name_len + 1; ImGuiWindowSettings* settings = g.SettingsWindows.alloc_chunk(chunk_size); IM_PLACEMENT_NEW(settings) ImGuiWindowSettings(); settings->ID = ImHashStr(name, name_len); memcpy(settings->GetName(), name, name_len + 1); // Store with zero terminator return settings; } // We don't provide a FindWindowSettingsByName() because Docking system doesn't always hold on names. // This is called once per window .ini entry + once per newly instantiated window. ImGuiWindowSettings* ImGui::FindWindowSettingsByID(ImGuiID id) { ImGuiContext& g = *GImGui; for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings)) if (settings->ID == id && !settings->WantDelete) return settings; return NULL; } // This is faster if you are holding on a Window already as we don't need to perform a search. ImGuiWindowSettings* ImGui::FindWindowSettingsByWindow(ImGuiWindow* window) { ImGuiContext& g = *GImGui; if (window->SettingsOffset != -1) return g.SettingsWindows.ptr_from_offset(window->SettingsOffset); return FindWindowSettingsByID(window->ID); } // This will revert window to its initial state, including enabling the ImGuiCond_FirstUseEver/ImGuiCond_Once conditions once more. void ImGui::ClearWindowSettings(const char* name) { //IMGUI_DEBUG_LOG("ClearWindowSettings('%s')\n", name); ImGuiWindow* window = FindWindowByName(name); if (window != NULL) { window->Flags |= ImGuiWindowFlags_NoSavedSettings; InitOrLoadWindowSettings(window, NULL); } if (ImGuiWindowSettings* settings = window ? FindWindowSettingsByWindow(window) : FindWindowSettingsByID(ImHashStr(name))) settings->WantDelete = true; } static void WindowSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*) { ImGuiContext& g = *ctx; for (ImGuiWindow* window : g.Windows) window->SettingsOffset = -1; g.SettingsWindows.clear(); } static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name) { ImGuiID id = ImHashStr(name); ImGuiWindowSettings* settings = ImGui::FindWindowSettingsByID(id); if (settings) *settings = ImGuiWindowSettings(); // Clear existing if recycling previous entry else settings = ImGui::CreateNewWindowSettings(name); settings->ID = id; settings->WantApply = true; return (void*)settings; } static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line) { ImGuiWindowSettings* settings = (ImGuiWindowSettings*)entry; int x, y; int i; if (sscanf(line, "Pos=%i,%i", &x, &y) == 2) { settings->Pos = ImVec2ih((short)x, (short)y); } else if (sscanf(line, "Size=%i,%i", &x, &y) == 2) { settings->Size = ImVec2ih((short)x, (short)y); } else if (sscanf(line, "Collapsed=%d", &i) == 1) { settings->Collapsed = (i != 0); } else if (sscanf(line, "IsChild=%d", &i) == 1) { settings->IsChild = (i != 0); } } // Apply to existing windows (if any) static void WindowSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*) { ImGuiContext& g = *ctx; for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings)) if (settings->WantApply) { if (ImGuiWindow* window = ImGui::FindWindowByID(settings->ID)) ApplyWindowSettings(window, settings); settings->WantApply = false; } } static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) { // Gather data from windows that were active during this session // (if a window wasn't opened in this session we preserve its settings) ImGuiContext& g = *ctx; for (ImGuiWindow* window : g.Windows) { if (window->Flags & ImGuiWindowFlags_NoSavedSettings) continue; ImGuiWindowSettings* settings = ImGui::FindWindowSettingsByWindow(window); if (!settings) { settings = ImGui::CreateNewWindowSettings(window->Name); window->SettingsOffset = g.SettingsWindows.offset_from_ptr(settings); } IM_ASSERT(settings->ID == window->ID); settings->Pos = ImVec2ih(window->Pos); settings->Size = ImVec2ih(window->SizeFull); settings->IsChild = (window->Flags & ImGuiWindowFlags_ChildWindow) != 0; settings->Collapsed = window->Collapsed; settings->WantDelete = false; } // Write to text buffer buf->reserve(buf->size() + g.SettingsWindows.size() * 6); // ballpark reserve for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings)) { if (settings->WantDelete) continue; const char* settings_name = settings->GetName(); buf->appendf("[%s][%s]\n", handler->TypeName, settings_name); if (settings->IsChild) { buf->appendf("IsChild=1\n"); buf->appendf("Size=%d,%d\n", settings->Size.x, settings->Size.y); } else { buf->appendf("Pos=%d,%d\n", settings->Pos.x, settings->Pos.y); buf->appendf("Size=%d,%d\n", settings->Size.x, settings->Size.y); if (settings->Collapsed) buf->appendf("Collapsed=1\n"); } buf->append("\n"); } } //----------------------------------------------------------------------------- // [SECTION] LOCALIZATION //----------------------------------------------------------------------------- void ImGui::LocalizeRegisterEntries(const ImGuiLocEntry* entries, int count) { ImGuiContext& g = *GImGui; for (int n = 0; n < count; n++) g.LocalizationTable[entries[n].Key] = entries[n].Text; } //----------------------------------------------------------------------------- // [SECTION] VIEWPORTS, PLATFORM WINDOWS //----------------------------------------------------------------------------- // - GetMainViewport() // - SetWindowViewport() [Internal] // - UpdateViewportsNewFrame() [Internal] // (this section is more complete in the 'docking' branch) //----------------------------------------------------------------------------- ImGuiViewport* ImGui::GetMainViewport() { ImGuiContext& g = *GImGui; return g.Viewports[0]; } void ImGui::SetWindowViewport(ImGuiWindow* window, ImGuiViewportP* viewport) { window->Viewport = viewport; } // Update viewports and monitor infos static void ImGui::UpdateViewportsNewFrame() { ImGuiContext& g = *GImGui; IM_ASSERT(g.Viewports.Size == 1); // Update main viewport with current platform position. // FIXME-VIEWPORT: Size is driven by backend/user code for backward-compatibility but we should aim to make this more consistent. ImGuiViewportP* main_viewport = g.Viewports[0]; main_viewport->Flags = ImGuiViewportFlags_IsPlatformWindow | ImGuiViewportFlags_OwnedByApp; main_viewport->Pos = ImVec2(0.0f, 0.0f); main_viewport->Size = g.IO.DisplaySize; for (ImGuiViewportP* viewport : g.Viewports) { // Lock down space taken by menu bars and status bars, reset the offset for fucntions like BeginMainMenuBar() to alter them again. viewport->WorkOffsetMin = viewport->BuildWorkOffsetMin; viewport->WorkOffsetMax = viewport->BuildWorkOffsetMax; viewport->BuildWorkOffsetMin = viewport->BuildWorkOffsetMax = ImVec2(0.0f, 0.0f); viewport->UpdateWorkRect(); } } //----------------------------------------------------------------------------- // [SECTION] DOCKING //----------------------------------------------------------------------------- // (this section is filled in the 'docking' branch) //----------------------------------------------------------------------------- // [SECTION] PLATFORM DEPENDENT HELPERS //----------------------------------------------------------------------------- #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) #ifdef _MSC_VER #pragma comment(lib, "user32") #pragma comment(lib, "kernel32") #endif // Win32 clipboard implementation // We use g.ClipboardHandlerData for temporary storage to ensure it is freed on Shutdown() static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx) { ImGuiContext& g = *(ImGuiContext*)user_data_ctx; g.ClipboardHandlerData.clear(); if (!::OpenClipboard(NULL)) return NULL; HANDLE wbuf_handle = ::GetClipboardData(CF_UNICODETEXT); if (wbuf_handle == NULL) { ::CloseClipboard(); return NULL; } if (const WCHAR* wbuf_global = (const WCHAR*)::GlobalLock(wbuf_handle)) { int buf_len = ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1, NULL, 0, NULL, NULL); g.ClipboardHandlerData.resize(buf_len); ::WideCharToMultiByte(CP_UTF8, 0, wbuf_global, -1, g.ClipboardHandlerData.Data, buf_len, NULL, NULL); } ::GlobalUnlock(wbuf_handle); ::CloseClipboard(); return g.ClipboardHandlerData.Data; } static void SetClipboardTextFn_DefaultImpl(void*, const char* text) { if (!::OpenClipboard(NULL)) return; const int wbuf_length = ::MultiByteToWideChar(CP_UTF8, 0, text, -1, NULL, 0); HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(WCHAR)); if (wbuf_handle == NULL) { ::CloseClipboard(); return; } WCHAR* wbuf_global = (WCHAR*)::GlobalLock(wbuf_handle); ::MultiByteToWideChar(CP_UTF8, 0, text, -1, wbuf_global, wbuf_length); ::GlobalUnlock(wbuf_handle); ::EmptyClipboard(); if (::SetClipboardData(CF_UNICODETEXT, wbuf_handle) == NULL) ::GlobalFree(wbuf_handle); ::CloseClipboard(); } #elif defined(__APPLE__) && TARGET_OS_OSX && defined(IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS) #include // Use old API to avoid need for separate .mm file static PasteboardRef main_clipboard = 0; // OSX clipboard implementation // If you enable this you will need to add '-framework ApplicationServices' to your linker command-line! static void SetClipboardTextFn_DefaultImpl(void*, const char* text) { if (!main_clipboard) PasteboardCreate(kPasteboardClipboard, &main_clipboard); PasteboardClear(main_clipboard); CFDataRef cf_data = CFDataCreate(kCFAllocatorDefault, (const UInt8*)text, strlen(text)); if (cf_data) { PasteboardPutItemFlavor(main_clipboard, (PasteboardItemID)1, CFSTR("public.utf8-plain-text"), cf_data, 0); CFRelease(cf_data); } } static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx) { ImGuiContext& g = *(ImGuiContext*)user_data_ctx; if (!main_clipboard) PasteboardCreate(kPasteboardClipboard, &main_clipboard); PasteboardSynchronize(main_clipboard); ItemCount item_count = 0; PasteboardGetItemCount(main_clipboard, &item_count); for (ItemCount i = 0; i < item_count; i++) { PasteboardItemID item_id = 0; PasteboardGetItemIdentifier(main_clipboard, i + 1, &item_id); CFArrayRef flavor_type_array = 0; PasteboardCopyItemFlavors(main_clipboard, item_id, &flavor_type_array); for (CFIndex j = 0, nj = CFArrayGetCount(flavor_type_array); j < nj; j++) { CFDataRef cf_data; if (PasteboardCopyItemFlavorData(main_clipboard, item_id, CFSTR("public.utf8-plain-text"), &cf_data) == noErr) { g.ClipboardHandlerData.clear(); int length = (int)CFDataGetLength(cf_data); g.ClipboardHandlerData.resize(length + 1); CFDataGetBytes(cf_data, CFRangeMake(0, length), (UInt8*)g.ClipboardHandlerData.Data); g.ClipboardHandlerData[length] = 0; CFRelease(cf_data); return g.ClipboardHandlerData.Data; } } } return NULL; } #else // Local Dear ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers. static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx) { ImGuiContext& g = *(ImGuiContext*)user_data_ctx; return g.ClipboardHandlerData.empty() ? NULL : g.ClipboardHandlerData.begin(); } static void SetClipboardTextFn_DefaultImpl(void* user_data_ctx, const char* text) { ImGuiContext& g = *(ImGuiContext*)user_data_ctx; g.ClipboardHandlerData.clear(); const char* text_end = text + strlen(text); g.ClipboardHandlerData.resize((int)(text_end - text) + 1); memcpy(&g.ClipboardHandlerData[0], text, (size_t)(text_end - text)); g.ClipboardHandlerData[(int)(text_end - text)] = 0; } #endif // Win32 API IME support (for Asian languages, etc.) #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) #include #ifdef _MSC_VER #pragma comment(lib, "imm32") #endif static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatformImeData* data) { // Notify OS Input Method Editor of text input position HWND hwnd = (HWND)viewport->PlatformHandleRaw; if (hwnd == 0) return; //::ImmAssociateContextEx(hwnd, NULL, data->WantVisible ? IACE_DEFAULT : 0); if (HIMC himc = ::ImmGetContext(hwnd)) { COMPOSITIONFORM composition_form = {}; composition_form.ptCurrentPos.x = (LONG)data->InputPos.x; composition_form.ptCurrentPos.y = (LONG)data->InputPos.y; composition_form.dwStyle = CFS_FORCE_POSITION; ::ImmSetCompositionWindow(himc, &composition_form); CANDIDATEFORM candidate_form = {}; candidate_form.dwStyle = CFS_CANDIDATEPOS; candidate_form.ptCurrentPos.x = (LONG)data->InputPos.x; candidate_form.ptCurrentPos.y = (LONG)data->InputPos.y; ::ImmSetCandidateWindow(himc, &candidate_form); ::ImmReleaseContext(hwnd, himc); } } #else static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport*, ImGuiPlatformImeData*) {} #endif //----------------------------------------------------------------------------- // [SECTION] METRICS/DEBUGGER WINDOW //----------------------------------------------------------------------------- // - DebugRenderViewportThumbnail() [Internal] // - RenderViewportsThumbnails() [Internal] // - DebugTextEncoding() // - MetricsHelpMarker() [Internal] // - ShowFontAtlas() [Internal] // - ShowMetricsWindow() // - DebugNodeColumns() [Internal] // - DebugNodeDrawList() [Internal] // - DebugNodeDrawCmdShowMeshAndBoundingBox() [Internal] // - DebugNodeFont() [Internal] // - DebugNodeFontGlyph() [Internal] // - DebugNodeStorage() [Internal] // - DebugNodeTabBar() [Internal] // - DebugNodeViewport() [Internal] // - DebugNodeWindow() [Internal] // - DebugNodeWindowSettings() [Internal] // - DebugNodeWindowsList() [Internal] // - DebugNodeWindowsListByBeginStackParent() [Internal] //----------------------------------------------------------------------------- #ifndef IMGUI_DISABLE_DEBUG_TOOLS void ImGui::DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport, const ImRect& bb) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImVec2 scale = bb.GetSize() / viewport->Size; ImVec2 off = bb.Min - viewport->Pos * scale; float alpha_mul = 1.0f; window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul * 0.40f)); for (ImGuiWindow* thumb_window : g.Windows) { if (!thumb_window->WasActive || (thumb_window->Flags & ImGuiWindowFlags_ChildWindow)) continue; ImRect thumb_r = thumb_window->Rect(); ImRect title_r = thumb_window->TitleBarRect(); thumb_r = ImRect(ImTrunc(off + thumb_r.Min * scale), ImTrunc(off + thumb_r.Max * scale)); title_r = ImRect(ImTrunc(off + title_r.Min * scale), ImTrunc(off + ImVec2(title_r.Max.x, title_r.Min.y + title_r.GetHeight() * 3.0f) * scale)); // Exaggerate title bar height thumb_r.ClipWithFull(bb); title_r.ClipWithFull(bb); const bool window_is_focused = (g.NavWindow && thumb_window->RootWindowForTitleBarHighlight == g.NavWindow->RootWindowForTitleBarHighlight); window->DrawList->AddRectFilled(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_WindowBg, alpha_mul)); window->DrawList->AddRectFilled(title_r.Min, title_r.Max, GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg, alpha_mul)); window->DrawList->AddRect(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_Border, alpha_mul)); window->DrawList->AddText(g.Font, g.FontSize * 1.0f, title_r.Min, GetColorU32(ImGuiCol_Text, alpha_mul), thumb_window->Name, FindRenderedTextEnd(thumb_window->Name)); } draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul)); if (viewport->ID == g.DebugMetricsConfig.HighlightViewportID) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255)); } static void RenderViewportsThumbnails() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; float SCALE = 1.0f / 8.0f; ImRect bb_full(g.Viewports[0]->Pos, g.Viewports[0]->Pos + g.Viewports[0]->Size); ImVec2 p = window->DC.CursorPos; ImVec2 off = p - bb_full.Min * SCALE; // Draw viewports for (ImGuiViewportP* viewport : g.Viewports) { ImRect viewport_draw_bb(off + (viewport->Pos) * SCALE, off + (viewport->Pos + viewport->Size) * SCALE); ImGui::DebugRenderViewportThumbnail(window->DrawList, viewport, viewport_draw_bb); } ImGui::Dummy(bb_full.GetSize() * SCALE); } // Draw an arbitrary US keyboard layout to visualize translated keys void ImGui::DebugRenderKeyboardPreview(ImDrawList* draw_list) { const float scale = ImGui::GetFontSize() / 13.0f; const ImVec2 key_size = ImVec2(35.0f, 35.0f) * scale; const float key_rounding = 3.0f * scale; const ImVec2 key_face_size = ImVec2(25.0f, 25.0f) * scale; const ImVec2 key_face_pos = ImVec2(5.0f, 3.0f) * scale; const float key_face_rounding = 2.0f * scale; const ImVec2 key_label_pos = ImVec2(7.0f, 4.0f) * scale; const ImVec2 key_step = ImVec2(key_size.x - 1.0f, key_size.y - 1.0f); const float key_row_offset = 9.0f * scale; ImVec2 board_min = GetCursorScreenPos(); ImVec2 board_max = ImVec2(board_min.x + 3 * key_step.x + 2 * key_row_offset + 10.0f, board_min.y + 3 * key_step.y + 10.0f); ImVec2 start_pos = ImVec2(board_min.x + 5.0f - key_step.x, board_min.y); struct KeyLayoutData { int Row, Col; const char* Label; ImGuiKey Key; }; const KeyLayoutData keys_to_display[] = { { 0, 0, "", ImGuiKey_Tab }, { 0, 1, "Q", ImGuiKey_Q }, { 0, 2, "W", ImGuiKey_W }, { 0, 3, "E", ImGuiKey_E }, { 0, 4, "R", ImGuiKey_R }, { 1, 0, "", ImGuiKey_CapsLock }, { 1, 1, "A", ImGuiKey_A }, { 1, 2, "S", ImGuiKey_S }, { 1, 3, "D", ImGuiKey_D }, { 1, 4, "F", ImGuiKey_F }, { 2, 0, "", ImGuiKey_LeftShift },{ 2, 1, "Z", ImGuiKey_Z }, { 2, 2, "X", ImGuiKey_X }, { 2, 3, "C", ImGuiKey_C }, { 2, 4, "V", ImGuiKey_V } }; // Elements rendered manually via ImDrawList API are not clipped automatically. // While not strictly necessary, here IsItemVisible() is used to avoid rendering these shapes when they are out of view. Dummy(board_max - board_min); if (!IsItemVisible()) return; draw_list->PushClipRect(board_min, board_max, true); for (int n = 0; n < IM_ARRAYSIZE(keys_to_display); n++) { const KeyLayoutData* key_data = &keys_to_display[n]; ImVec2 key_min = ImVec2(start_pos.x + key_data->Col * key_step.x + key_data->Row * key_row_offset, start_pos.y + key_data->Row * key_step.y); ImVec2 key_max = key_min + key_size; draw_list->AddRectFilled(key_min, key_max, IM_COL32(204, 204, 204, 255), key_rounding); draw_list->AddRect(key_min, key_max, IM_COL32(24, 24, 24, 255), key_rounding); ImVec2 face_min = ImVec2(key_min.x + key_face_pos.x, key_min.y + key_face_pos.y); ImVec2 face_max = ImVec2(face_min.x + key_face_size.x, face_min.y + key_face_size.y); draw_list->AddRect(face_min, face_max, IM_COL32(193, 193, 193, 255), key_face_rounding, ImDrawFlags_None, 2.0f); draw_list->AddRectFilled(face_min, face_max, IM_COL32(252, 252, 252, 255), key_face_rounding); ImVec2 label_min = ImVec2(key_min.x + key_label_pos.x, key_min.y + key_label_pos.y); draw_list->AddText(label_min, IM_COL32(64, 64, 64, 255), key_data->Label); if (IsKeyDown(key_data->Key)) draw_list->AddRectFilled(key_min, key_max, IM_COL32(255, 0, 0, 128), key_rounding); } draw_list->PopClipRect(); } // Helper tool to diagnose between text encoding issues and font loading issues. Pass your UTF-8 string and verify that there are correct. void ImGui::DebugTextEncoding(const char* str) { Text("Text: \"%s\"", str); if (!BeginTable("##DebugTextEncoding", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable)) return; TableSetupColumn("Offset"); TableSetupColumn("UTF-8"); TableSetupColumn("Glyph"); TableSetupColumn("Codepoint"); TableHeadersRow(); for (const char* p = str; *p != 0; ) { unsigned int c; const int c_utf8_len = ImTextCharFromUtf8(&c, p, NULL); TableNextColumn(); Text("%d", (int)(p - str)); TableNextColumn(); for (int byte_index = 0; byte_index < c_utf8_len; byte_index++) { if (byte_index > 0) SameLine(); Text("0x%02X", (int)(unsigned char)p[byte_index]); } TableNextColumn(); if (GetFont()->FindGlyphNoFallback((ImWchar)c)) TextUnformatted(p, p + c_utf8_len); else TextUnformatted((c == IM_UNICODE_CODEPOINT_INVALID) ? "[invalid]" : "[missing]"); TableNextColumn(); Text("U+%04X", (int)c); p += c_utf8_len; } EndTable(); } static void DebugFlashStyleColorStop() { ImGuiContext& g = *GImGui; if (g.DebugFlashStyleColorIdx != ImGuiCol_COUNT) g.Style.Colors[g.DebugFlashStyleColorIdx] = g.DebugFlashStyleColorBackup; g.DebugFlashStyleColorIdx = ImGuiCol_COUNT; } // Flash a given style color for some + inhibit modifications of this color via PushStyleColor() calls. void ImGui::DebugFlashStyleColor(ImGuiCol idx) { ImGuiContext& g = *GImGui; DebugFlashStyleColorStop(); g.DebugFlashStyleColorTime = 0.5f; g.DebugFlashStyleColorIdx = idx; g.DebugFlashStyleColorBackup = g.Style.Colors[idx]; } void ImGui::UpdateDebugToolFlashStyleColor() { ImGuiContext& g = *GImGui; if (g.DebugFlashStyleColorTime <= 0.0f) return; ColorConvertHSVtoRGB(cosf(g.DebugFlashStyleColorTime * 6.0f) * 0.5f + 0.5f, 0.5f, 0.5f, g.Style.Colors[g.DebugFlashStyleColorIdx].x, g.Style.Colors[g.DebugFlashStyleColorIdx].y, g.Style.Colors[g.DebugFlashStyleColorIdx].z); g.Style.Colors[g.DebugFlashStyleColorIdx].w = 1.0f; if ((g.DebugFlashStyleColorTime -= g.IO.DeltaTime) <= 0.0f) DebugFlashStyleColorStop(); } // Avoid naming collision with imgui_demo.cpp's HelpMarker() for unity builds. static void MetricsHelpMarker(const char* desc) { ImGui::TextDisabled("(?)"); if (ImGui::BeginItemTooltip()) { ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); ImGui::TextUnformatted(desc); ImGui::PopTextWrapPos(); ImGui::EndTooltip(); } } // [DEBUG] List fonts in a font atlas and display its texture void ImGui::ShowFontAtlas(ImFontAtlas* atlas) { for (ImFont* font : atlas->Fonts) { PushID(font); DebugNodeFont(font); PopID(); } if (TreeNode("Font Atlas", "Font Atlas (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight)) { ImGuiContext& g = *GImGui; ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig; Checkbox("Tint with Text Color", &cfg->ShowAtlasTintedWithTextColor); // Using text color ensure visibility of core atlas data, but will alter custom colored icons ImVec4 tint_col = cfg->ShowAtlasTintedWithTextColor ? GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f); ImVec4 border_col = GetStyleColorVec4(ImGuiCol_Border); Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), tint_col, border_col); TreePop(); } } void ImGui::ShowMetricsWindow(bool* p_open) { ImGuiContext& g = *GImGui; ImGuiIO& io = g.IO; ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig; if (cfg->ShowDebugLog) ShowDebugLogWindow(&cfg->ShowDebugLog); if (cfg->ShowIDStackTool) ShowIDStackToolWindow(&cfg->ShowIDStackTool); if (!Begin("Dear ImGui Metrics/Debugger", p_open) || GetCurrentWindow()->BeginCount > 1) { End(); return; } // [DEBUG] Clear debug breaks hooks after exactly one cycle. DebugBreakClearData(); // Basic info Text("Dear ImGui %s", GetVersion()); Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); Text("%d vertices, %d indices (%d triangles)", io.MetricsRenderVertices, io.MetricsRenderIndices, io.MetricsRenderIndices / 3); Text("%d visible windows, %d current allocations", io.MetricsRenderWindows, g.DebugAllocInfo.TotalAllocCount - g.DebugAllocInfo.TotalFreeCount); //SameLine(); if (SmallButton("GC")) { g.GcCompactAll = true; } Separator(); // Debugging enums enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Content, WRT_ContentIdeal, WRT_ContentRegionRect, WRT_Count }; // Windows Rect Type const char* wrt_rects_names[WRT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Content", "ContentIdeal", "ContentRegionRect" }; enum { TRT_OuterRect, TRT_InnerRect, TRT_WorkRect, TRT_HostClipRect, TRT_InnerClipRect, TRT_BackgroundClipRect, TRT_ColumnsRect, TRT_ColumnsWorkRect, TRT_ColumnsClipRect, TRT_ColumnsContentHeadersUsed, TRT_ColumnsContentHeadersIdeal, TRT_ColumnsContentFrozen, TRT_ColumnsContentUnfrozen, TRT_Count }; // Tables Rect Type const char* trt_rects_names[TRT_Count] = { "OuterRect", "InnerRect", "WorkRect", "HostClipRect", "InnerClipRect", "BackgroundClipRect", "ColumnsRect", "ColumnsWorkRect", "ColumnsClipRect", "ColumnsContentHeadersUsed", "ColumnsContentHeadersIdeal", "ColumnsContentFrozen", "ColumnsContentUnfrozen" }; if (cfg->ShowWindowsRectsType < 0) cfg->ShowWindowsRectsType = WRT_WorkRect; if (cfg->ShowTablesRectsType < 0) cfg->ShowTablesRectsType = TRT_WorkRect; struct Funcs { static ImRect GetTableRect(ImGuiTable* table, int rect_type, int n) { ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); // Always using last submitted instance if (rect_type == TRT_OuterRect) { return table->OuterRect; } else if (rect_type == TRT_InnerRect) { return table->InnerRect; } else if (rect_type == TRT_WorkRect) { return table->WorkRect; } else if (rect_type == TRT_HostClipRect) { return table->HostClipRect; } else if (rect_type == TRT_InnerClipRect) { return table->InnerClipRect; } else if (rect_type == TRT_BackgroundClipRect) { return table->BgClipRect; } else if (rect_type == TRT_ColumnsRect) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MaxX, table->InnerClipRect.Min.y + table_instance->LastOuterHeight); } else if (rect_type == TRT_ColumnsWorkRect) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->WorkRect.Min.y, c->WorkMaxX, table->WorkRect.Max.y); } else if (rect_type == TRT_ColumnsClipRect) { ImGuiTableColumn* c = &table->Columns[n]; return c->ClipRect; } else if (rect_type == TRT_ColumnsContentHeadersUsed){ ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersUsed, table->InnerClipRect.Min.y + table_instance->LastTopHeadersRowHeight); } // Note: y1/y2 not always accurate else if (rect_type == TRT_ColumnsContentHeadersIdeal){ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersIdeal, table->InnerClipRect.Min.y + table_instance->LastTopHeadersRowHeight); } else if (rect_type == TRT_ColumnsContentFrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXFrozen, table->InnerClipRect.Min.y + table_instance->LastFrozenHeight); } else if (rect_type == TRT_ColumnsContentUnfrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y + table_instance->LastFrozenHeight, c->ContentMaxXUnfrozen, table->InnerClipRect.Max.y); } IM_ASSERT(0); return ImRect(); } static ImRect GetWindowRect(ImGuiWindow* window, int rect_type) { if (rect_type == WRT_OuterRect) { return window->Rect(); } else if (rect_type == WRT_OuterRectClipped) { return window->OuterRectClipped; } else if (rect_type == WRT_InnerRect) { return window->InnerRect; } else if (rect_type == WRT_InnerClipRect) { return window->InnerClipRect; } else if (rect_type == WRT_WorkRect) { return window->WorkRect; } else if (rect_type == WRT_Content) { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSize); } else if (rect_type == WRT_ContentIdeal) { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSizeIdeal); } else if (rect_type == WRT_ContentRegionRect) { return window->ContentRegionRect; } IM_ASSERT(0); return ImRect(); } }; // Tools if (TreeNode("Tools")) { // Debug Break features // The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted. SeparatorTextEx(0, "Debug breaks", NULL, CalcTextSize("(?)").x + g.Style.SeparatorTextPadding.x); SameLine(); MetricsHelpMarker("Will call the IM_DEBUG_BREAK() macro to break in debugger.\nWarning: If you don't have a debugger attached, this will probably crash."); if (Checkbox("Show Item Picker", &g.DebugItemPickerActive) && g.DebugItemPickerActive) DebugStartItemPicker(); Checkbox("Show \"Debug Break\" buttons in other sections (io.ConfigDebugIsDebuggerPresent)", &g.IO.ConfigDebugIsDebuggerPresent); SeparatorText("Visualize"); Checkbox("Show Debug Log", &cfg->ShowDebugLog); SameLine(); MetricsHelpMarker("You can also call ImGui::ShowDebugLogWindow() from your code."); Checkbox("Show ID Stack Tool", &cfg->ShowIDStackTool); SameLine(); MetricsHelpMarker("You can also call ImGui::ShowIDStackToolWindow() from your code."); Checkbox("Show windows begin order", &cfg->ShowWindowsBeginOrder); Checkbox("Show windows rectangles", &cfg->ShowWindowsRects); SameLine(); SetNextItemWidth(GetFontSize() * 12); cfg->ShowWindowsRects |= Combo("##show_windows_rect_type", &cfg->ShowWindowsRectsType, wrt_rects_names, WRT_Count, WRT_Count); if (cfg->ShowWindowsRects && g.NavWindow != NULL) { BulletText("'%s':", g.NavWindow->Name); Indent(); for (int rect_n = 0; rect_n < WRT_Count; rect_n++) { ImRect r = Funcs::GetWindowRect(g.NavWindow, rect_n); Text("(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), wrt_rects_names[rect_n]); } Unindent(); } Checkbox("Show tables rectangles", &cfg->ShowTablesRects); SameLine(); SetNextItemWidth(GetFontSize() * 12); cfg->ShowTablesRects |= Combo("##show_table_rects_type", &cfg->ShowTablesRectsType, trt_rects_names, TRT_Count, TRT_Count); if (cfg->ShowTablesRects && g.NavWindow != NULL) { for (int table_n = 0; table_n < g.Tables.GetMapSize(); table_n++) { ImGuiTable* table = g.Tables.TryGetMapData(table_n); if (table == NULL || table->LastFrameActive < g.FrameCount - 1 || (table->OuterWindow != g.NavWindow && table->InnerWindow != g.NavWindow)) continue; BulletText("Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name); if (IsItemHovered()) GetForegroundDrawList()->AddRect(table->OuterRect.Min - ImVec2(1, 1), table->OuterRect.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f); Indent(); char buf[128]; for (int rect_n = 0; rect_n < TRT_Count; rect_n++) { if (rect_n >= TRT_ColumnsRect) { if (rect_n != TRT_ColumnsRect && rect_n != TRT_ColumnsClipRect) continue; for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { ImRect r = Funcs::GetTableRect(table, rect_n, column_n); ImFormatString(buf, IM_ARRAYSIZE(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) Col %d %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), column_n, trt_rects_names[rect_n]); Selectable(buf); if (IsItemHovered()) GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f); } } else { ImRect r = Funcs::GetTableRect(table, rect_n, -1); ImFormatString(buf, IM_ARRAYSIZE(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), trt_rects_names[rect_n]); Selectable(buf); if (IsItemHovered()) GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f); } } Unindent(); } } Checkbox("Show groups rectangles", &g.DebugShowGroupRects); // Storing in context as this is used by group code and prefers to be in hot-data SeparatorText("Validate"); Checkbox("Debug Begin/BeginChild return value", &io.ConfigDebugBeginReturnValueLoop); SameLine(); MetricsHelpMarker("Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths then repeat. Windows should be flickering while running."); Checkbox("UTF-8 Encoding viewer", &cfg->ShowTextEncodingViewer); SameLine(); MetricsHelpMarker("You can also call ImGui::DebugTextEncoding() from your code with a given string to test that your UTF-8 encoding settings are correct."); if (cfg->ShowTextEncodingViewer) { static char buf[64] = ""; SetNextItemWidth(-FLT_MIN); InputText("##DebugTextEncodingBuf", buf, IM_ARRAYSIZE(buf)); if (buf[0] != 0) DebugTextEncoding(buf); } TreePop(); } // Windows if (TreeNode("Windows", "Windows (%d)", g.Windows.Size)) { //SetNextItemOpen(true, ImGuiCond_Once); DebugNodeWindowsList(&g.Windows, "By display order"); DebugNodeWindowsList(&g.WindowsFocusOrder, "By focus order (root windows)"); if (TreeNode("By submission order (begin stack)")) { // Here we display windows in their submitted order/hierarchy, however note that the Begin stack doesn't constitute a Parent<>Child relationship! ImVector& temp_buffer = g.WindowsTempSortBuffer; temp_buffer.resize(0); for (ImGuiWindow* window : g.Windows) if (window->LastFrameActive + 1 >= g.FrameCount) temp_buffer.push_back(window); struct Func { static int IMGUI_CDECL WindowComparerByBeginOrder(const void* lhs, const void* rhs) { return ((int)(*(const ImGuiWindow* const *)lhs)->BeginOrderWithinContext - (*(const ImGuiWindow* const*)rhs)->BeginOrderWithinContext); } }; ImQsort(temp_buffer.Data, (size_t)temp_buffer.Size, sizeof(ImGuiWindow*), Func::WindowComparerByBeginOrder); DebugNodeWindowsListByBeginStackParent(temp_buffer.Data, temp_buffer.Size, NULL); TreePop(); } TreePop(); } // DrawLists int drawlist_count = 0; for (ImGuiViewportP* viewport : g.Viewports) drawlist_count += viewport->DrawDataP.CmdLists.Size; if (TreeNode("DrawLists", "DrawLists (%d)", drawlist_count)) { Checkbox("Show ImDrawCmd mesh when hovering", &cfg->ShowDrawCmdMesh); Checkbox("Show ImDrawCmd bounding boxes when hovering", &cfg->ShowDrawCmdBoundingBoxes); for (ImGuiViewportP* viewport : g.Viewports) for (ImDrawList* draw_list : viewport->DrawDataP.CmdLists) DebugNodeDrawList(NULL, viewport, draw_list, "DrawList"); TreePop(); } // Viewports if (TreeNode("Viewports", "Viewports (%d)", g.Viewports.Size)) { SetNextItemOpen(true, ImGuiCond_Once); if (TreeNode("Windows Minimap")) { RenderViewportsThumbnails(); TreePop(); } cfg->HighlightViewportID = 0; for (ImGuiViewportP* viewport : g.Viewports) DebugNodeViewport(viewport); TreePop(); } // Details for Popups if (TreeNode("Popups", "Popups (%d)", g.OpenPopupStack.Size)) { for (const ImGuiPopupData& popup_data : g.OpenPopupStack) { // As it's difficult to interact with tree nodes while popups are open, we display everything inline. ImGuiWindow* window = popup_data.Window; BulletText("PopupID: %08x, Window: '%s' (%s%s), BackupNavWindow '%s', ParentWindow '%s'", popup_data.PopupId, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? "Child;" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? "Menu;" : "", popup_data.BackupNavWindow ? popup_data.BackupNavWindow->Name : "NULL", window && window->ParentWindow ? window->ParentWindow->Name : "NULL"); } TreePop(); } // Details for TabBars if (TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.GetAliveCount())) { for (int n = 0; n < g.TabBars.GetMapSize(); n++) if (ImGuiTabBar* tab_bar = g.TabBars.TryGetMapData(n)) { PushID(tab_bar); DebugNodeTabBar(tab_bar, "TabBar"); PopID(); } TreePop(); } // Details for Tables if (TreeNode("Tables", "Tables (%d)", g.Tables.GetAliveCount())) { for (int n = 0; n < g.Tables.GetMapSize(); n++) if (ImGuiTable* table = g.Tables.TryGetMapData(n)) DebugNodeTable(table); TreePop(); } // Details for Fonts ImFontAtlas* atlas = g.IO.Fonts; if (TreeNode("Fonts", "Fonts (%d)", atlas->Fonts.Size)) { ShowFontAtlas(atlas); TreePop(); } // Details for InputText if (TreeNode("InputText")) { DebugNodeInputTextState(&g.InputTextState); TreePop(); } // Details for TypingSelect if (TreeNode("TypingSelect", "TypingSelect (%d)", g.TypingSelectState.SearchBuffer[0] != 0 ? 1 : 0)) { DebugNodeTypingSelectState(&g.TypingSelectState); TreePop(); } // Details for Docking #ifdef IMGUI_HAS_DOCK if (TreeNode("Docking")) { TreePop(); } #endif // #ifdef IMGUI_HAS_DOCK // Settings if (TreeNode("Settings")) { if (SmallButton("Clear")) ClearIniSettings(); SameLine(); if (SmallButton("Save to memory")) SaveIniSettingsToMemory(); SameLine(); if (SmallButton("Save to disk")) SaveIniSettingsToDisk(g.IO.IniFilename); SameLine(); if (g.IO.IniFilename) Text("\"%s\"", g.IO.IniFilename); else TextUnformatted(""); Checkbox("io.ConfigDebugIniSettings", &io.ConfigDebugIniSettings); Text("SettingsDirtyTimer %.2f", g.SettingsDirtyTimer); if (TreeNode("SettingsHandlers", "Settings handlers: (%d)", g.SettingsHandlers.Size)) { for (ImGuiSettingsHandler& handler : g.SettingsHandlers) BulletText("\"%s\"", handler.TypeName); TreePop(); } if (TreeNode("SettingsWindows", "Settings packed data: Windows: %d bytes", g.SettingsWindows.size())) { for (ImGuiWindowSettings* settings = g.SettingsWindows.begin(); settings != NULL; settings = g.SettingsWindows.next_chunk(settings)) DebugNodeWindowSettings(settings); TreePop(); } if (TreeNode("SettingsTables", "Settings packed data: Tables: %d bytes", g.SettingsTables.size())) { for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings)) DebugNodeTableSettings(settings); TreePop(); } #ifdef IMGUI_HAS_DOCK #endif // #ifdef IMGUI_HAS_DOCK if (TreeNode("SettingsIniData", "Settings unpacked data (.ini): %d bytes", g.SettingsIniData.size())) { InputTextMultiline("##Ini", (char*)(void*)g.SettingsIniData.c_str(), g.SettingsIniData.Buf.Size, ImVec2(-FLT_MIN, GetTextLineHeight() * 20), ImGuiInputTextFlags_ReadOnly); TreePop(); } TreePop(); } // Settings if (TreeNode("Memory allocations")) { ImGuiDebugAllocInfo* info = &g.DebugAllocInfo; Text("%d current allocations", info->TotalAllocCount - info->TotalFreeCount); if (SmallButton("GC now")) { g.GcCompactAll = true; } Text("Recent frames with allocations:"); int buf_size = IM_ARRAYSIZE(info->LastEntriesBuf); for (int n = buf_size - 1; n >= 0; n--) { ImGuiDebugAllocEntry* entry = &info->LastEntriesBuf[(info->LastEntriesIdx - n + buf_size) % buf_size]; BulletText("Frame %06d: %+3d ( %2d malloc, %2d free )%s", entry->FrameCount, entry->AllocCount - entry->FreeCount, entry->AllocCount, entry->FreeCount, (n == 0) ? " (most recent)" : ""); } TreePop(); } if (TreeNode("Inputs")) { Text("KEYBOARD/GAMEPAD/MOUSE KEYS"); { // We iterate both legacy native range and named ImGuiKey ranges, which is a little odd but this allows displaying the data for old/new backends. // User code should never have to go through such hoops! You can generally iterate between ImGuiKey_NamedKey_BEGIN and ImGuiKey_NamedKey_END. Indent(); #ifdef IMGUI_DISABLE_OBSOLETE_KEYIO struct funcs { static bool IsLegacyNativeDupe(ImGuiKey) { return false; } }; #else struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key >= 0 && key < 512 && GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array //Text("Legacy raw:"); for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key++) { if (io.KeysDown[key]) { SameLine(); Text("\"%s\" %d", GetKeyName(key), key); } } #endif Text("Keys down:"); for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !IsKeyDown(key)) continue; SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); SameLine(); Text("(%.02f)", GetKeyData(key)->DownDuration); } Text("Keys pressed:"); for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !IsKeyPressed(key)) continue; SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); } Text("Keys released:"); for (ImGuiKey key = ImGuiKey_KeysData_OFFSET; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !IsKeyReleased(key)) continue; SameLine(); Text(IsNamedKey(key) ? "\"%s\"" : "\"%s\" %d", GetKeyName(key), key); } Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); Text("Chars queue:"); for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; SameLine(); Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public. DebugRenderKeyboardPreview(GetWindowDrawList()); Unindent(); } Text("MOUSE STATE"); { Indent(); if (IsMousePosValid()) Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y); else Text("Mouse pos: "); Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y); int count = IM_ARRAYSIZE(io.MouseDown); Text("Mouse down:"); for (int i = 0; i < count; i++) if (IsMouseDown(i)) { SameLine(); Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); } Text("Mouse clicked:"); for (int i = 0; i < count; i++) if (IsMouseClicked(i)) { SameLine(); Text("b%d (%d)", i, io.MouseClickedCount[i]); } Text("Mouse released:"); for (int i = 0; i < count; i++) if (IsMouseReleased(i)) { SameLine(); Text("b%d", i); } Text("Mouse wheel: %.1f", io.MouseWheel); Text("MouseStationaryTimer: %.2f", g.MouseStationaryTimer); Text("Mouse source: %s", GetMouseSourceName(io.MouseSource)); Text("Pen Pressure: %.1f", io.PenPressure); // Note: currently unused Unindent(); } Text("MOUSE WHEELING"); { Indent(); Text("WheelingWindow: '%s'", g.WheelingWindow ? g.WheelingWindow->Name : "NULL"); Text("WheelingWindowReleaseTimer: %.2f", g.WheelingWindowReleaseTimer); Text("WheelingAxisAvg[] = { %.3f, %.3f }, Main Axis: %s", g.WheelingAxisAvg.x, g.WheelingAxisAvg.y, (g.WheelingAxisAvg.x > g.WheelingAxisAvg.y) ? "X" : (g.WheelingAxisAvg.x < g.WheelingAxisAvg.y) ? "Y" : ""); Unindent(); } Text("KEY OWNERS"); { Indent(); if (BeginChild("##owners", ImVec2(-FLT_MIN, GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY, ImGuiWindowFlags_NoSavedSettings)) for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key); if (owner_data->OwnerCurr == ImGuiKeyOwner_None) continue; Text("%s: 0x%08X%s", GetKeyName(key), owner_data->OwnerCurr, owner_data->LockUntilRelease ? " LockUntilRelease" : owner_data->LockThisFrame ? " LockThisFrame" : ""); DebugLocateItemOnHover(owner_data->OwnerCurr); } EndChild(); Unindent(); } Text("SHORTCUT ROUTING"); SameLine(); MetricsHelpMarker("Declared shortcut routes automatically set key owner when mods matches."); { Indent(); if (BeginChild("##routes", ImVec2(-FLT_MIN, GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY, ImGuiWindowFlags_NoSavedSettings)) for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { ImGuiKeyRoutingTable* rt = &g.KeysRoutingTable; for (ImGuiKeyRoutingIndex idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; idx != -1; ) { ImGuiKeyRoutingData* routing_data = &rt->Entries[idx]; ImGuiKeyChord key_chord = key | routing_data->Mods; Text("%s: 0x%08X (scored %d)", GetKeyChordName(key_chord), routing_data->RoutingCurr, routing_data->RoutingCurrScore); DebugLocateItemOnHover(routing_data->RoutingCurr); if (g.IO.ConfigDebugIsDebuggerPresent) { SameLine(); if (DebugBreakButton("**DebugBreak**", "in SetShortcutRouting() for this KeyChord")) g.DebugBreakInShortcutRouting = key_chord; } idx = routing_data->NextEntryIndex; } } EndChild(); Text("(ActiveIdUsing: AllKeyboardKeys: %d, NavDirMask: 0x%X)", g.ActiveIdUsingAllKeyboardKeys, g.ActiveIdUsingNavDirMask); Unindent(); } TreePop(); } if (TreeNode("Internal state")) { Text("WINDOWING"); Indent(); Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); Text("HoveredWindow->Root: '%s'", g.HoveredWindow ? g.HoveredWindow->RootWindow->Name : "NULL"); Text("HoveredWindowUnderMovingWindow: '%s'", g.HoveredWindowUnderMovingWindow ? g.HoveredWindowUnderMovingWindow->Name : "NULL"); Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL"); Unindent(); Text("ITEMS"); Indent(); Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, GetInputSourceName(g.ActiveIdSource)); DebugLocateItemOnHover(g.ActiveId); Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); Text("ActiveIdUsing: AllKeyboardKeys: %d, NavDirMask: %X", g.ActiveIdUsingAllKeyboardKeys, g.ActiveIdUsingNavDirMask); Text("HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Not displaying g.HoveredId as it is update mid-frame Text("HoverItemDelayId: 0x%08X, Timer: %.2f, ClearTimer: %.2f", g.HoverItemDelayId, g.HoverItemDelayTimer, g.HoverItemDelayClearTimer); Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize); DebugLocateItemOnHover(g.DragDropPayload.SourceId); Unindent(); Text("NAV,FOCUS"); Indent(); Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL"); Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer); DebugLocateItemOnHover(g.NavId); Text("NavInputSource: %s", GetInputSourceName(g.NavInputSource)); Text("NavLastValidSelectionUserData = %" IM_PRId64 " (0x%" IM_PRIX64 ")", g.NavLastValidSelectionUserData, g.NavLastValidSelectionUserData); Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible); Text("NavActivateId/DownId/PressedId: %08X/%08X/%08X", g.NavActivateId, g.NavActivateDownId, g.NavActivatePressedId); Text("NavActivateFlags: %04X", g.NavActivateFlags); Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover); Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId); Text("NavFocusRoute[] = "); for (int path_n = g.NavFocusRoute.Size - 1; path_n >= 0; path_n--) { const ImGuiFocusScopeData& focus_scope = g.NavFocusRoute[path_n]; SameLine(0.0f, 0.0f); Text("0x%08X/", focus_scope.ID); SetItemTooltip("In window \"%s\"", FindWindowByID(focus_scope.WindowID)->Name); } Text("NavWindowingTarget: '%s'", g.NavWindowingTarget ? g.NavWindowingTarget->Name : "NULL"); Unindent(); TreePop(); } // Overlay: Display windows Rectangles and Begin Order if (cfg->ShowWindowsRects || cfg->ShowWindowsBeginOrder) { for (ImGuiWindow* window : g.Windows) { if (!window->WasActive) continue; ImDrawList* draw_list = GetForegroundDrawList(window); if (cfg->ShowWindowsRects) { ImRect r = Funcs::GetWindowRect(window, cfg->ShowWindowsRectsType); draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255)); } if (cfg->ShowWindowsBeginOrder && !(window->Flags & ImGuiWindowFlags_ChildWindow)) { char buf[32]; ImFormatString(buf, IM_ARRAYSIZE(buf), "%d", window->BeginOrderWithinContext); float font_size = GetFontSize(); draw_list->AddRectFilled(window->Pos, window->Pos + ImVec2(font_size, font_size), IM_COL32(200, 100, 100, 255)); draw_list->AddText(window->Pos, IM_COL32(255, 255, 255, 255), buf); } } } // Overlay: Display Tables Rectangles if (cfg->ShowTablesRects) { for (int table_n = 0; table_n < g.Tables.GetMapSize(); table_n++) { ImGuiTable* table = g.Tables.TryGetMapData(table_n); if (table == NULL || table->LastFrameActive < g.FrameCount - 1) continue; ImDrawList* draw_list = GetForegroundDrawList(table->OuterWindow); if (cfg->ShowTablesRectsType >= TRT_ColumnsRect) { for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, column_n); ImU32 col = (table->HoveredColumnBody == column_n) ? IM_COL32(255, 255, 128, 255) : IM_COL32(255, 0, 128, 255); float thickness = (table->HoveredColumnBody == column_n) ? 3.0f : 1.0f; draw_list->AddRect(r.Min, r.Max, col, 0.0f, 0, thickness); } } else { ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, -1); draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255)); } } } #ifdef IMGUI_HAS_DOCK // Overlay: Display Docking info if (show_docking_nodes && g.IO.KeyCtrl) { } #endif // #ifdef IMGUI_HAS_DOCK End(); } void ImGui::DebugBreakClearData() { // Those fields are scattered in their respective subsystem to stay in hot-data locations ImGuiContext& g = *GImGui; g.DebugBreakInWindow = 0; g.DebugBreakInTable = 0; g.DebugBreakInShortcutRouting = ImGuiKey_None; } void ImGui::DebugBreakButtonTooltip(bool keyboard_only, const char* description_of_location) { if (!BeginItemTooltip()) return; Text("To call IM_DEBUG_BREAK() %s:", description_of_location); Separator(); TextUnformatted(keyboard_only ? "- Press 'Pause/Break' on keyboard." : "- Press 'Pause/Break' on keyboard.\n- or Click (may alter focus/active id).\n- or navigate using keyboard and press space."); Separator(); TextUnformatted("Choose one way that doesn't interfere with what you are trying to debug!\nYou need a debugger attached or this will crash!"); EndTooltip(); } // Special button that doesn't take focus, doesn't take input owner, and can be activated without a click etc. // In order to reduce interferences with the contents we are trying to debug into. bool ImGui::DebugBreakButton(const char* label, const char* description_of_location) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; const ImGuiID id = window->GetID(label); const ImVec2 label_size = CalcTextSize(label, NULL, true); ImVec2 pos = window->DC.CursorPos + ImVec2(0.0f, window->DC.CurrLineTextBaseOffset); ImVec2 size = ImVec2(label_size.x + g.Style.FramePadding.x * 2.0f, label_size.y); const ImRect bb(pos, pos + size); ItemSize(size, 0.0f); if (!ItemAdd(bb, id)) return false; // WE DO NOT USE ButtonEx() or ButtonBehavior() in order to reduce our side-effects. bool hovered = ItemHoverable(bb, id, g.CurrentItemFlags); bool pressed = hovered && (IsKeyChordPressed(g.DebugBreakKeyChord) || IsMouseClicked(0) || g.NavActivateId == id); DebugBreakButtonTooltip(false, description_of_location); ImVec4 col4f = GetStyleColorVec4(hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); ImVec4 hsv; ColorConvertRGBtoHSV(col4f.x, col4f.y, col4f.z, hsv.x, hsv.y, hsv.z); ColorConvertHSVtoRGB(hsv.x + 0.20f, hsv.y, hsv.z, col4f.x, col4f.y, col4f.z); RenderNavHighlight(bb, id); RenderFrame(bb.Min, bb.Max, GetColorU32(col4f), true, g.Style.FrameRounding); RenderTextClipped(bb.Min, bb.Max, label, NULL, &label_size, g.Style.ButtonTextAlign, &bb); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); return pressed; } // [DEBUG] Display contents of Columns void ImGui::DebugNodeColumns(ImGuiOldColumns* columns) { if (!TreeNode((void*)(uintptr_t)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags)) return; BulletText("Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->OffMaxX - columns->OffMinX, columns->OffMinX, columns->OffMaxX); for (ImGuiOldColumnData& column : columns->Columns) BulletText("Column %02d: OffsetNorm %.3f (= %.1f px)", (int)columns->Columns.index_from_ptr(&column), column.OffsetNorm, GetColumnOffsetFromNorm(columns, column.OffsetNorm)); TreePop(); } static void FormatTextureIDForDebugDisplay(char* buf, int buf_size, ImTextureID tex_id) { union { void* ptr; int integer; } tex_id_opaque; memcpy(&tex_id_opaque, &tex_id, ImMin(sizeof(void*), sizeof(tex_id))); if (sizeof(tex_id) >= sizeof(void*)) ImFormatString(buf, buf_size, "0x%p", tex_id_opaque.ptr); else ImFormatString(buf, buf_size, "0x%04X", tex_id_opaque.integer); } // [DEBUG] Display contents of ImDrawList void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, const ImDrawList* draw_list, const char* label) { ImGuiContext& g = *GImGui; IM_UNUSED(viewport); // Used in docking branch ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig; int cmd_count = draw_list->CmdBuffer.Size; if (cmd_count > 0 && draw_list->CmdBuffer.back().ElemCount == 0 && draw_list->CmdBuffer.back().UserCallback == NULL) cmd_count--; bool node_open = TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, cmd_count); if (draw_list == GetWindowDrawList()) { SameLine(); TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f), "CURRENTLY APPENDING"); // Can't display stats for active draw list! (we don't have the data double-buffered) if (node_open) TreePop(); return; } ImDrawList* fg_draw_list = GetForegroundDrawList(window); // Render additional visuals into the top-most draw list if (window && IsItemHovered() && fg_draw_list) fg_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255)); if (!node_open) return; if (window && !window->WasActive) TextDisabled("Warning: owning Window is inactive. This DrawList is not being rendered!"); for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.Data; pcmd < draw_list->CmdBuffer.Data + cmd_count; pcmd++) { if (pcmd->UserCallback) { BulletText("Callback %p, user_data %p", pcmd->UserCallback, pcmd->UserCallbackData); continue; } char texid_desc[20]; FormatTextureIDForDebugDisplay(texid_desc, IM_ARRAYSIZE(texid_desc), pcmd->TextureId); char buf[300]; ImFormatString(buf, IM_ARRAYSIZE(buf), "DrawCmd:%5d tris, Tex %s, ClipRect (%4.0f,%4.0f)-(%4.0f,%4.0f)", pcmd->ElemCount / 3, texid_desc, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); bool pcmd_node_open = TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "%s", buf); if (IsItemHovered() && (cfg->ShowDrawCmdMesh || cfg->ShowDrawCmdBoundingBoxes) && fg_draw_list) DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, cfg->ShowDrawCmdMesh, cfg->ShowDrawCmdBoundingBoxes); if (!pcmd_node_open) continue; // Calculate approximate coverage area (touched pixel count) // This will be in pixels squared as long there's no post-scaling happening to the renderer output. const ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; const ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + pcmd->VtxOffset; float total_area = 0.0f; for (unsigned int idx_n = pcmd->IdxOffset; idx_n < pcmd->IdxOffset + pcmd->ElemCount; ) { ImVec2 triangle[3]; for (int n = 0; n < 3; n++, idx_n++) triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos; total_area += ImTriangleArea(triangle[0], triangle[1], triangle[2]); } // Display vertex information summary. Hover to get all triangles drawn in wire-frame ImFormatString(buf, IM_ARRAYSIZE(buf), "Mesh: ElemCount: %d, VtxOffset: +%d, IdxOffset: +%d, Area: ~%0.f px", pcmd->ElemCount, pcmd->VtxOffset, pcmd->IdxOffset, total_area); Selectable(buf); if (IsItemHovered() && fg_draw_list) DebugNodeDrawCmdShowMeshAndBoundingBox(fg_draw_list, draw_list, pcmd, true, false); // Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted. ImGuiListClipper clipper; clipper.Begin(pcmd->ElemCount / 3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible. while (clipper.Step()) for (int prim = clipper.DisplayStart, idx_i = pcmd->IdxOffset + clipper.DisplayStart * 3; prim < clipper.DisplayEnd; prim++) { char* buf_p = buf, * buf_end = buf + IM_ARRAYSIZE(buf); ImVec2 triangle[3]; for (int n = 0; n < 3; n++, idx_i++) { const ImDrawVert& v = vtx_buffer[idx_buffer ? idx_buffer[idx_i] : idx_i]; triangle[n] = v.pos; buf_p += ImFormatString(buf_p, buf_end - buf_p, "%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n", (n == 0) ? "Vert:" : " ", idx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); } Selectable(buf, false); if (fg_draw_list && IsItemHovered()) { ImDrawListFlags backup_flags = fg_draw_list->Flags; fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles. fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f); fg_draw_list->Flags = backup_flags; } } TreePop(); } TreePop(); } // [DEBUG] Display mesh/aabb of a ImDrawCmd void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb) { IM_ASSERT(show_mesh || show_aabb); // Draw wire-frame version of all triangles ImRect clip_rect = draw_cmd->ClipRect; ImRect vtxs_rect(FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX); ImDrawListFlags backup_flags = out_draw_list->Flags; out_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles. for (unsigned int idx_n = draw_cmd->IdxOffset, idx_end = draw_cmd->IdxOffset + draw_cmd->ElemCount; idx_n < idx_end; ) { ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; // We don't hold on those pointers past iterations as ->AddPolyline() may invalidate them if out_draw_list==draw_list ImDrawVert* vtx_buffer = draw_list->VtxBuffer.Data + draw_cmd->VtxOffset; ImVec2 triangle[3]; for (int n = 0; n < 3; n++, idx_n++) vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos)); if (show_mesh) out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f); // In yellow: mesh triangles } // Draw bounding boxes if (show_aabb) { out_draw_list->AddRect(ImTrunc(clip_rect.Min), ImTrunc(clip_rect.Max), IM_COL32(255, 0, 255, 255)); // In pink: clipping rectangle submitted to GPU out_draw_list->AddRect(ImTrunc(vtxs_rect.Min), ImTrunc(vtxs_rect.Max), IM_COL32(0, 255, 255, 255)); // In cyan: bounding box of triangles } out_draw_list->Flags = backup_flags; } // [DEBUG] Display details for a single font, called by ShowStyleEditor(). void ImGui::DebugNodeFont(ImFont* font) { bool opened = TreeNode(font, "Font: \"%s\"\n%.2f px, %d glyphs, %d file(s)", font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size, font->ConfigDataCount); SameLine(); if (SmallButton("Set as default")) GetIO().FontDefault = font; if (!opened) return; // Display preview text PushFont(font); Text("The quick brown fox jumps over the lazy dog"); PopFont(); // Display details SetNextItemWidth(GetFontSize() * 8); DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); SameLine(); MetricsHelpMarker( "Note than the default embedded font is NOT meant to be scaled.\n\n" "Font are currently rendered into bitmaps at a given size at the time of building the atlas. " "You may oversample them to get some flexibility with scaling. " "You can also render at multiple sizes and select which one to use at runtime.\n\n" "(Glimmer of hope: the atlas system will be rewritten in the future to make scaling more flexible.)"); Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent); char c_str[5]; Text("Fallback character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->FallbackChar), font->FallbackChar); Text("Ellipsis character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->EllipsisChar), font->EllipsisChar); const int surface_sqrt = (int)ImSqrt((float)font->MetricsTotalSurface); Text("Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, surface_sqrt, surface_sqrt); for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) if (font->ConfigData) if (const ImFontConfig* cfg = &font->ConfigData[config_i]) BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d, Offset: (%.1f,%.1f)", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH, cfg->GlyphOffset.x, cfg->GlyphOffset.y); // Display all glyphs of the fonts in separate pages of 256 characters if (TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size)) { ImDrawList* draw_list = GetWindowDrawList(); const ImU32 glyph_col = GetColorU32(ImGuiCol_Text); const float cell_size = font->FontSize * 1; const float cell_spacing = GetStyle().ItemSpacing.y; for (unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256) { // Skip ahead if a large bunch of glyphs are not present in the font (test in chunks of 4k) // This is only a small optimization to reduce the number of iterations when IM_UNICODE_MAX_CODEPOINT // is large // (if ImWchar==ImWchar32 we will do at least about 272 queries here) if (!(base & 4095) && font->IsGlyphRangeUnused(base, base + 4095)) { base += 4096 - 256; continue; } int count = 0; for (unsigned int n = 0; n < 256; n++) if (font->FindGlyphNoFallback((ImWchar)(base + n))) count++; if (count <= 0) continue; if (!TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ? "glyphs" : "glyph")) continue; // Draw a 16x16 grid of glyphs ImVec2 base_pos = GetCursorScreenPos(); for (unsigned int n = 0; n < 256; n++) { // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions // available here and thus cannot easily generate a zero-terminated UTF-8 encoded string. ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing)); ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size); const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n)); draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50)); if (!glyph) continue; font->RenderChar(draw_list, cell_size, cell_p1, glyph_col, (ImWchar)(base + n)); if (IsMouseHoveringRect(cell_p1, cell_p2) && BeginTooltip()) { DebugNodeFontGlyph(font, glyph); EndTooltip(); } } Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16)); TreePop(); } TreePop(); } TreePop(); } void ImGui::DebugNodeFontGlyph(ImFont*, const ImFontGlyph* glyph) { Text("Codepoint: U+%04X", glyph->Codepoint); Separator(); Text("Visible: %d", glyph->Visible); Text("AdvanceX: %.1f", glyph->AdvanceX); Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1); Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1); } // [DEBUG] Display contents of ImGuiStorage void ImGui::DebugNodeStorage(ImGuiStorage* storage, const char* label) { if (!TreeNode(label, "%s: %d entries, %d bytes", label, storage->Data.Size, storage->Data.size_in_bytes())) return; for (const ImGuiStorage::ImGuiStoragePair& p : storage->Data) BulletText("Key 0x%08X Value { i: %d }", p.key, p.val_i); // Important: we currently don't store a type, real value may not be integer. TreePop(); } // [DEBUG] Display contents of ImGuiTabBar void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label) { // Standalone tab bars (not associated to docking/windows functionality) currently hold no discernible strings. char buf[256]; char* p = buf; const char* buf_end = buf + IM_ARRAYSIZE(buf); const bool is_active = (tab_bar->PrevFrameVisible >= GetFrameCount() - 2); p += ImFormatString(p, buf_end - p, "%s 0x%08X (%d tabs)%s {", label, tab_bar->ID, tab_bar->Tabs.Size, is_active ? "" : " *Inactive*"); for (int tab_n = 0; tab_n < ImMin(tab_bar->Tabs.Size, 3); tab_n++) { ImGuiTabItem* tab = &tab_bar->Tabs[tab_n]; p += ImFormatString(p, buf_end - p, "%s'%s'", tab_n > 0 ? ", " : "", TabBarGetTabName(tab_bar, tab)); } p += ImFormatString(p, buf_end - p, (tab_bar->Tabs.Size > 3) ? " ... }" : " } "); if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } bool open = TreeNode(label, "%s", buf); if (!is_active) { PopStyleColor(); } if (is_active && IsItemHovered()) { ImDrawList* draw_list = GetForegroundDrawList(); draw_list->AddRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max, IM_COL32(255, 255, 0, 255)); draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255)); draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255)); } if (open) { for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++) { ImGuiTabItem* tab = &tab_bar->Tabs[tab_n]; PushID(tab); if (SmallButton("<")) { TabBarQueueReorder(tab_bar, tab, -1); } SameLine(0, 2); if (SmallButton(">")) { TabBarQueueReorder(tab_bar, tab, +1); } SameLine(); Text("%02d%c Tab 0x%08X '%s' Offset: %.2f, Width: %.2f/%.2f", tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID, TabBarGetTabName(tab_bar, tab), tab->Offset, tab->Width, tab->ContentWidth); PopID(); } TreePop(); } } void ImGui::DebugNodeViewport(ImGuiViewportP* viewport) { ImGuiContext& g = *GImGui; SetNextItemOpen(true, ImGuiCond_Once); bool open = TreeNode("viewport0", "Viewport #%d", 0); if (IsItemHovered()) g.DebugMetricsConfig.HighlightViewportID = viewport->ID; if (open) { ImGuiWindowFlags flags = viewport->Flags; BulletText("Main Pos: (%.0f,%.0f), Size: (%.0f,%.0f)\nWorkArea Offset Left: %.0f Top: %.0f, Right: %.0f, Bottom: %.0f", viewport->Pos.x, viewport->Pos.y, viewport->Size.x, viewport->Size.y, viewport->WorkOffsetMin.x, viewport->WorkOffsetMin.y, viewport->WorkOffsetMax.x, viewport->WorkOffsetMax.y); BulletText("Flags: 0x%04X =%s%s%s", viewport->Flags, (flags & ImGuiViewportFlags_IsPlatformWindow) ? " IsPlatformWindow" : "", (flags & ImGuiViewportFlags_IsPlatformMonitor) ? " IsPlatformMonitor" : "", (flags & ImGuiViewportFlags_OwnedByApp) ? " OwnedByApp" : ""); for (ImDrawList* draw_list : viewport->DrawDataP.CmdLists) DebugNodeDrawList(NULL, viewport, draw_list, "DrawList"); TreePop(); } } void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label) { if (window == NULL) { BulletText("%s: NULL", label); return; } ImGuiContext& g = *GImGui; const bool is_active = window->WasActive; ImGuiTreeNodeFlags tree_node_flags = (window == g.NavWindow) ? ImGuiTreeNodeFlags_Selected : ImGuiTreeNodeFlags_None; if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } const bool open = TreeNodeEx(label, tree_node_flags, "%s '%s'%s", label, window->Name, is_active ? "" : " *Inactive*"); if (!is_active) { PopStyleColor(); } if (IsItemHovered() && is_active) GetForegroundDrawList(window)->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255)); if (!open) return; if (window->MemoryCompacted) TextDisabled("Note: some memory buffers have been compacted/freed."); if (g.IO.ConfigDebugIsDebuggerPresent && DebugBreakButton("**DebugBreak**", "in Begin()")) g.DebugBreakInWindow = window->ID; ImGuiWindowFlags flags = window->Flags; DebugNodeDrawList(window, window->Viewport, window->DrawList, "DrawList"); BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), ContentSize (%.1f,%.1f) Ideal (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->ContentSize.x, window->ContentSize.y, window->ContentSizeIdeal.x, window->ContentSizeIdeal.y); BulletText("Flags: 0x%08X (%s%s%s%s%s%s%s%s%s..)", flags, (flags & ImGuiWindowFlags_ChildWindow) ? "Child " : "", (flags & ImGuiWindowFlags_Tooltip) ? "Tooltip " : "", (flags & ImGuiWindowFlags_Popup) ? "Popup " : "", (flags & ImGuiWindowFlags_Modal) ? "Modal " : "", (flags & ImGuiWindowFlags_ChildMenu) ? "ChildMenu " : "", (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : "", (flags & ImGuiWindowFlags_NoMouseInputs)? "NoMouseInputs":"", (flags & ImGuiWindowFlags_NoNavInputs) ? "NoNavInputs" : "", (flags & ImGuiWindowFlags_AlwaysAutoResize) ? "AlwaysAutoResize" : ""); BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f) Scrollbar:%s%s", window->Scroll.x, window->ScrollMax.x, window->Scroll.y, window->ScrollMax.y, window->ScrollbarX ? "X" : "", window->ScrollbarY ? "Y" : ""); BulletText("Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1); BulletText("Appearing: %d, Hidden: %d (CanSkip %d Cannot %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesCanSkipItems, window->HiddenFramesCannotSkipItems, window->SkipItems); for (int layer = 0; layer < ImGuiNavLayer_COUNT; layer++) { ImRect r = window->NavRectRel[layer]; if (r.Min.x >= r.Max.y && r.Min.y >= r.Max.y) BulletText("NavLastIds[%d]: 0x%08X", layer, window->NavLastIds[layer]); else BulletText("NavLastIds[%d]: 0x%08X at +(%.1f,%.1f)(%.1f,%.1f)", layer, window->NavLastIds[layer], r.Min.x, r.Min.y, r.Max.x, r.Max.y); DebugLocateItemOnHover(window->NavLastIds[layer]); } const ImVec2* pr = window->NavPreferredScoringPosRel; for (int layer = 0; layer < ImGuiNavLayer_COUNT; layer++) BulletText("NavPreferredScoringPosRel[%d] = {%.1f,%.1f)", layer, (pr[layer].x == FLT_MAX ? -99999.0f : pr[layer].x), (pr[layer].y == FLT_MAX ? -99999.0f : pr[layer].y)); // Display as 99999.0f so it looks neater. BulletText("NavLayersActiveMask: %X, NavLastChildNavWindow: %s", window->DC.NavLayersActiveMask, window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL"); if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow, "RootWindow"); } if (window->ParentWindow != NULL) { DebugNodeWindow(window->ParentWindow, "ParentWindow"); } if (window->ParentWindowForFocusRoute != NULL) { DebugNodeWindow(window->ParentWindowForFocusRoute, "ParentWindowForFocusRoute"); } if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows, "ChildWindows"); } if (window->ColumnsStorage.Size > 0 && TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size)) { for (ImGuiOldColumns& columns : window->ColumnsStorage) DebugNodeColumns(&columns); TreePop(); } DebugNodeStorage(&window->StateStorage, "Storage"); TreePop(); } void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings* settings) { if (settings->WantDelete) BeginDisabled(); Text("0x%08X \"%s\" Pos (%d,%d) Size (%d,%d) Collapsed=%d", settings->ID, settings->GetName(), settings->Pos.x, settings->Pos.y, settings->Size.x, settings->Size.y, settings->Collapsed); if (settings->WantDelete) EndDisabled(); } void ImGui::DebugNodeWindowsList(ImVector* windows, const char* label) { if (!TreeNode(label, "%s (%d)", label, windows->Size)) return; for (int i = windows->Size - 1; i >= 0; i--) // Iterate front to back { PushID((*windows)[i]); DebugNodeWindow((*windows)[i], "Window"); PopID(); } TreePop(); } // FIXME-OPT: This is technically suboptimal, but it is simpler this way. void ImGui::DebugNodeWindowsListByBeginStackParent(ImGuiWindow** windows, int windows_size, ImGuiWindow* parent_in_begin_stack) { for (int i = 0; i < windows_size; i++) { ImGuiWindow* window = windows[i]; if (window->ParentWindowInBeginStack != parent_in_begin_stack) continue; char buf[20]; ImFormatString(buf, IM_ARRAYSIZE(buf), "[%04d] Window", window->BeginOrderWithinContext); //BulletText("[%04d] Window '%s'", window->BeginOrderWithinContext, window->Name); DebugNodeWindow(window, buf); Indent(); DebugNodeWindowsListByBeginStackParent(windows + i + 1, windows_size - i - 1, window); Unindent(); } } //----------------------------------------------------------------------------- // [SECTION] DEBUG LOG WINDOW //----------------------------------------------------------------------------- void ImGui::DebugLog(const char* fmt, ...) { va_list args; va_start(args, fmt); DebugLogV(fmt, args); va_end(args); } void ImGui::DebugLogV(const char* fmt, va_list args) { ImGuiContext& g = *GImGui; const int old_size = g.DebugLogBuf.size(); g.DebugLogBuf.appendf("[%05d] ", g.FrameCount); g.DebugLogBuf.appendfv(fmt, args); g.DebugLogIndex.append(g.DebugLogBuf.c_str(), old_size, g.DebugLogBuf.size()); if (g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTTY) IMGUI_DEBUG_PRINTF("%s", g.DebugLogBuf.begin() + old_size); #ifdef IMGUI_ENABLE_TEST_ENGINE if (g.DebugLogFlags & ImGuiDebugLogFlags_OutputToTestEngine) IMGUI_TEST_ENGINE_LOG("%s", g.DebugLogBuf.begin() + old_size); #endif } // FIXME-LAYOUT: To be done automatically via layout mode once we rework ItemSize/ItemAdd into ItemLayout. static void SameLineOrWrap(const ImVec2& size) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImVec2 pos(window->DC.CursorPosPrevLine.x + g.Style.ItemSpacing.x, window->DC.CursorPosPrevLine.y); if (window->ClipRect.Contains(ImRect(pos, pos + size))) ImGui::SameLine(); } static void ShowDebugLogFlag(const char* name, ImGuiDebugLogFlags flags) { ImGuiContext& g = *GImGui; ImVec2 size(ImGui::GetFrameHeight() + g.Style.ItemInnerSpacing.x + ImGui::CalcTextSize(name).x, ImGui::GetFrameHeight()); SameLineOrWrap(size); // FIXME-LAYOUT: To be done automatically once we rework ItemSize/ItemAdd into ItemLayout. if (ImGui::CheckboxFlags(name, &g.DebugLogFlags, flags) && g.IO.KeyShift && (g.DebugLogFlags & flags) != 0) { g.DebugLogAutoDisableFrames = 2; g.DebugLogAutoDisableFlags |= flags; } ImGui::SetItemTooltip("Hold SHIFT when clicking to enable for 2 frames only (useful for spammy log entries)"); } void ImGui::ShowDebugLogWindow(bool* p_open) { ImGuiContext& g = *GImGui; if (!(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize)) SetNextWindowSize(ImVec2(0.0f, GetFontSize() * 12.0f), ImGuiCond_FirstUseEver); if (!Begin("Dear ImGui Debug Log", p_open) || GetCurrentWindow()->BeginCount > 1) { End(); return; } ImGuiDebugLogFlags all_enable_flags = ImGuiDebugLogFlags_EventMask_ & ~ImGuiDebugLogFlags_EventInputRouting; CheckboxFlags("All", &g.DebugLogFlags, all_enable_flags); SetItemTooltip("(except InputRouting which is spammy)"); ShowDebugLogFlag("ActiveId", ImGuiDebugLogFlags_EventActiveId); ShowDebugLogFlag("Clipper", ImGuiDebugLogFlags_EventClipper); ShowDebugLogFlag("Focus", ImGuiDebugLogFlags_EventFocus); ShowDebugLogFlag("IO", ImGuiDebugLogFlags_EventIO); ShowDebugLogFlag("Nav", ImGuiDebugLogFlags_EventNav); ShowDebugLogFlag("Popup", ImGuiDebugLogFlags_EventPopup); //ShowDebugLogFlag("Selection", ImGuiDebugLogFlags_EventSelection); ShowDebugLogFlag("InputRouting", ImGuiDebugLogFlags_EventInputRouting); if (SmallButton("Clear")) { g.DebugLogBuf.clear(); g.DebugLogIndex.clear(); } SameLine(); if (SmallButton("Copy")) SetClipboardText(g.DebugLogBuf.c_str()); BeginChild("##log", ImVec2(0.0f, 0.0f), ImGuiChildFlags_Border, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar); const ImGuiDebugLogFlags backup_log_flags = g.DebugLogFlags; g.DebugLogFlags &= ~ImGuiDebugLogFlags_EventClipper; ImGuiListClipper clipper; clipper.Begin(g.DebugLogIndex.size()); while (clipper.Step()) for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++) { const char* line_begin = g.DebugLogIndex.get_line_begin(g.DebugLogBuf.c_str(), line_no); const char* line_end = g.DebugLogIndex.get_line_end(g.DebugLogBuf.c_str(), line_no); TextUnformatted(line_begin, line_end); // Display line ImRect text_rect = g.LastItemData.Rect; if (IsItemHovered()) for (const char* p = line_begin; p <= line_end - 10; p++) // Search for 0x???????? identifiers { ImGuiID id = 0; if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1) continue; ImVec2 p0 = CalcTextSize(line_begin, p); ImVec2 p1 = CalcTextSize(p, p + 10); g.LastItemData.Rect = ImRect(text_rect.Min + ImVec2(p0.x, 0.0f), text_rect.Min + ImVec2(p0.x + p1.x, p1.y)); if (IsMouseHoveringRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, true)) DebugLocateItemOnHover(id); p += 10; } } g.DebugLogFlags = backup_log_flags; if (GetScrollY() >= GetScrollMaxY()) SetScrollHereY(1.0f); EndChild(); End(); } //----------------------------------------------------------------------------- // [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, ID STACK TOOL) //----------------------------------------------------------------------------- // Draw a small cross at current CursorPos in current window's DrawList void ImGui::DebugDrawCursorPos(ImU32 col) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImVec2 pos = window->DC.CursorPos; window->DrawList->AddLine(ImVec2(pos.x, pos.y - 3.0f), ImVec2(pos.x, pos.y + 4.0f), col, 1.0f); window->DrawList->AddLine(ImVec2(pos.x - 3.0f, pos.y), ImVec2(pos.x + 4.0f, pos.y), col, 1.0f); } // Draw a 10px wide rectangle around CurposPos.x using Line Y1/Y2 in current window's DrawList void ImGui::DebugDrawLineExtents(ImU32 col) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; float curr_x = window->DC.CursorPos.x; float line_y1 = (window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y); float line_y2 = line_y1 + (window->DC.IsSameLine ? window->DC.PrevLineSize.y : window->DC.CurrLineSize.y); window->DrawList->AddLine(ImVec2(curr_x - 5.0f, line_y1), ImVec2(curr_x + 5.0f, line_y1), col, 1.0f); window->DrawList->AddLine(ImVec2(curr_x - 0.5f, line_y1), ImVec2(curr_x - 0.5f, line_y2), col, 1.0f); window->DrawList->AddLine(ImVec2(curr_x - 5.0f, line_y2), ImVec2(curr_x + 5.0f, line_y2), col, 1.0f); } // Draw last item rect in ForegroundDrawList (so it is always visible) void ImGui::DebugDrawItemRect(ImU32 col) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; GetForegroundDrawList(window)->AddRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, col); } // [DEBUG] Locate item position/rectangle given an ID. static const ImU32 DEBUG_LOCATE_ITEM_COLOR = IM_COL32(0, 255, 0, 255); // Green void ImGui::DebugLocateItem(ImGuiID target_id) { ImGuiContext& g = *GImGui; g.DebugLocateId = target_id; g.DebugLocateFrames = 2; g.DebugBreakInLocateId = false; } // FIXME: Doesn't work over through a modal window, because they clear HoveredWindow. void ImGui::DebugLocateItemOnHover(ImGuiID target_id) { if (target_id == 0 || !IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenBlockedByPopup)) return; ImGuiContext& g = *GImGui; DebugLocateItem(target_id); GetForegroundDrawList(g.CurrentWindow)->AddRect(g.LastItemData.Rect.Min - ImVec2(3.0f, 3.0f), g.LastItemData.Rect.Max + ImVec2(3.0f, 3.0f), DEBUG_LOCATE_ITEM_COLOR); // Can't easily use a context menu here because it will mess with focus, active id etc. if (g.IO.ConfigDebugIsDebuggerPresent && g.MouseStationaryTimer > 1.0f) { DebugBreakButtonTooltip(false, "in ItemAdd()"); if (IsKeyChordPressed(g.DebugBreakKeyChord)) g.DebugBreakInLocateId = true; } } void ImGui::DebugLocateItemResolveWithLastItem() { ImGuiContext& g = *GImGui; // [DEBUG] Debug break requested by user if (g.DebugBreakInLocateId) IM_DEBUG_BREAK(); ImGuiLastItemData item_data = g.LastItemData; g.DebugLocateId = 0; ImDrawList* draw_list = GetForegroundDrawList(g.CurrentWindow); ImRect r = item_data.Rect; r.Expand(3.0f); ImVec2 p1 = g.IO.MousePos; ImVec2 p2 = ImVec2((p1.x < r.Min.x) ? r.Min.x : (p1.x > r.Max.x) ? r.Max.x : p1.x, (p1.y < r.Min.y) ? r.Min.y : (p1.y > r.Max.y) ? r.Max.y : p1.y); draw_list->AddRect(r.Min, r.Max, DEBUG_LOCATE_ITEM_COLOR); draw_list->AddLine(p1, p2, DEBUG_LOCATE_ITEM_COLOR); } // [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack. void ImGui::UpdateDebugToolItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerBreakId = 0; if (!g.DebugItemPickerActive) return; const ImGuiID hovered_id = g.HoveredIdPreviousFrame; SetMouseCursor(ImGuiMouseCursor_Hand); if (IsKeyPressed(ImGuiKey_Escape)) g.DebugItemPickerActive = false; const bool change_mapping = g.IO.KeyMods == (ImGuiMod_Ctrl | ImGuiMod_Shift); if (!change_mapping && IsMouseClicked(g.DebugItemPickerMouseButton) && hovered_id) { g.DebugItemPickerBreakId = hovered_id; g.DebugItemPickerActive = false; } for (int mouse_button = 0; mouse_button < 3; mouse_button++) if (change_mapping && IsMouseClicked(mouse_button)) g.DebugItemPickerMouseButton = (ImU8)mouse_button; SetNextWindowBgAlpha(0.70f); if (!BeginTooltip()) return; Text("HoveredId: 0x%08X", hovered_id); Text("Press ESC to abort picking."); const char* mouse_button_names[] = { "Left", "Right", "Middle" }; if (change_mapping) Text("Remap w/ Ctrl+Shift: click anywhere to select new mouse button."); else TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled), "Click %s Button to break in debugger! (remap w/ Ctrl+Shift)", mouse_button_names[g.DebugItemPickerMouseButton]); EndTooltip(); } // [DEBUG] ID Stack Tool: update queries. Called by NewFrame() void ImGui::UpdateDebugToolStackQueries() { ImGuiContext& g = *GImGui; ImGuiIDStackTool* tool = &g.DebugIDStackTool; // Clear hook when id stack tool is not visible g.DebugHookIdInfo = 0; if (g.FrameCount != tool->LastActiveFrame + 1) return; // Update queries. The steps are: -1: query Stack, >= 0: query each stack item // We can only perform 1 ID Info query every frame. This is designed so the GetID() tests are cheap and constant-time const ImGuiID query_id = g.HoveredIdPreviousFrame ? g.HoveredIdPreviousFrame : g.ActiveId; if (tool->QueryId != query_id) { tool->QueryId = query_id; tool->StackLevel = -1; tool->Results.resize(0); } if (query_id == 0) return; // Advance to next stack level when we got our result, or after 2 frames (in case we never get a result) int stack_level = tool->StackLevel; if (stack_level >= 0 && stack_level < tool->Results.Size) if (tool->Results[stack_level].QuerySuccess || tool->Results[stack_level].QueryFrameCount > 2) tool->StackLevel++; // Update hook stack_level = tool->StackLevel; if (stack_level == -1) g.DebugHookIdInfo = query_id; if (stack_level >= 0 && stack_level < tool->Results.Size) { g.DebugHookIdInfo = tool->Results[stack_level].ID; tool->Results[stack_level].QueryFrameCount++; } } // [DEBUG] ID Stack tool: hooks called by GetID() family functions void ImGui::DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* data_id, const void* data_id_end) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiIDStackTool* tool = &g.DebugIDStackTool; // Step 0: stack query // This assumes that the ID was computed with the current ID stack, which tends to be the case for our widget. if (tool->StackLevel == -1) { tool->StackLevel++; tool->Results.resize(window->IDStack.Size + 1, ImGuiStackLevelInfo()); for (int n = 0; n < window->IDStack.Size + 1; n++) tool->Results[n].ID = (n < window->IDStack.Size) ? window->IDStack[n] : id; return; } // Step 1+: query for individual level IM_ASSERT(tool->StackLevel >= 0); if (tool->StackLevel != window->IDStack.Size) return; ImGuiStackLevelInfo* info = &tool->Results[tool->StackLevel]; IM_ASSERT(info->ID == id && info->QueryFrameCount > 0); switch (data_type) { case ImGuiDataType_S32: ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "%d", (int)(intptr_t)data_id); break; case ImGuiDataType_String: ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "%.*s", data_id_end ? (int)((const char*)data_id_end - (const char*)data_id) : (int)strlen((const char*)data_id), (const char*)data_id); break; case ImGuiDataType_Pointer: ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "(void*)0x%p", data_id); break; case ImGuiDataType_ID: if (info->Desc[0] != 0) // PushOverrideID() is often used to avoid hashing twice, which would lead to 2 calls to DebugHookIdInfo(). We prioritize the first one. return; ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "0x%08X [override]", id); break; default: IM_ASSERT(0); } info->QuerySuccess = true; info->DataType = data_type; } static int StackToolFormatLevelInfo(ImGuiIDStackTool* tool, int n, bool format_for_ui, char* buf, size_t buf_size) { ImGuiStackLevelInfo* info = &tool->Results[n]; ImGuiWindow* window = (info->Desc[0] == 0 && n == 0) ? ImGui::FindWindowByID(info->ID) : NULL; if (window) // Source: window name (because the root ID don't call GetID() and so doesn't get hooked) return ImFormatString(buf, buf_size, format_for_ui ? "\"%s\" [window]" : "%s", window->Name); if (info->QuerySuccess) // Source: GetID() hooks (prioritize over ItemInfo() because we frequently use patterns like: PushID(str), Button("") where they both have same id) return ImFormatString(buf, buf_size, (format_for_ui && info->DataType == ImGuiDataType_String) ? "\"%s\"" : "%s", info->Desc); if (tool->StackLevel < tool->Results.Size) // Only start using fallback below when all queries are done, so during queries we don't flickering ??? markers. return (*buf = 0); #ifdef IMGUI_ENABLE_TEST_ENGINE if (const char* label = ImGuiTestEngine_FindItemDebugLabel(GImGui, info->ID)) // Source: ImGuiTestEngine's ItemInfo() return ImFormatString(buf, buf_size, format_for_ui ? "??? \"%s\"" : "%s", label); #endif return ImFormatString(buf, buf_size, "???"); } // ID Stack Tool: Display UI void ImGui::ShowIDStackToolWindow(bool* p_open) { ImGuiContext& g = *GImGui; if (!(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize)) SetNextWindowSize(ImVec2(0.0f, GetFontSize() * 8.0f), ImGuiCond_FirstUseEver); if (!Begin("Dear ImGui ID Stack Tool", p_open) || GetCurrentWindow()->BeginCount > 1) { End(); return; } // Display hovered/active status ImGuiIDStackTool* tool = &g.DebugIDStackTool; const ImGuiID hovered_id = g.HoveredIdPreviousFrame; const ImGuiID active_id = g.ActiveId; #ifdef IMGUI_ENABLE_TEST_ENGINE Text("HoveredId: 0x%08X (\"%s\"), ActiveId: 0x%08X (\"%s\")", hovered_id, hovered_id ? ImGuiTestEngine_FindItemDebugLabel(&g, hovered_id) : "", active_id, active_id ? ImGuiTestEngine_FindItemDebugLabel(&g, active_id) : ""); #else Text("HoveredId: 0x%08X, ActiveId: 0x%08X", hovered_id, active_id); #endif SameLine(); MetricsHelpMarker("Hover an item with the mouse to display elements of the ID Stack leading to the item's final ID.\nEach level of the stack correspond to a PushID() call.\nAll levels of the stack are hashed together to make the final ID of a widget (ID displayed at the bottom level of the stack).\nRead FAQ entry about the ID stack for details."); // CTRL+C to copy path const float time_since_copy = (float)g.Time - tool->CopyToClipboardLastTime; Checkbox("Ctrl+C: copy path to clipboard", &tool->CopyToClipboardOnCtrlC); SameLine(); TextColored((time_since_copy >= 0.0f && time_since_copy < 0.75f && ImFmod(time_since_copy, 0.25f) < 0.25f * 0.5f) ? ImVec4(1.f, 1.f, 0.3f, 1.f) : ImVec4(), "*COPIED*"); if (tool->CopyToClipboardOnCtrlC && IsKeyDown(ImGuiMod_Ctrl) && IsKeyPressed(ImGuiKey_C)) { tool->CopyToClipboardLastTime = (float)g.Time; char* p = g.TempBuffer.Data; char* p_end = p + g.TempBuffer.Size; for (int stack_n = 0; stack_n < tool->Results.Size && p + 3 < p_end; stack_n++) { *p++ = '/'; char level_desc[256]; StackToolFormatLevelInfo(tool, stack_n, false, level_desc, IM_ARRAYSIZE(level_desc)); for (int n = 0; level_desc[n] && p + 2 < p_end; n++) { if (level_desc[n] == '/') *p++ = '\\'; *p++ = level_desc[n]; } } *p = '\0'; SetClipboardText(g.TempBuffer.Data); } // Display decorated stack tool->LastActiveFrame = g.FrameCount; if (tool->Results.Size > 0 && BeginTable("##table", 3, ImGuiTableFlags_Borders)) { const float id_width = CalcTextSize("0xDDDDDDDD").x; TableSetupColumn("Seed", ImGuiTableColumnFlags_WidthFixed, id_width); TableSetupColumn("PushID", ImGuiTableColumnFlags_WidthStretch); TableSetupColumn("Result", ImGuiTableColumnFlags_WidthFixed, id_width); TableHeadersRow(); for (int n = 0; n < tool->Results.Size; n++) { ImGuiStackLevelInfo* info = &tool->Results[n]; TableNextColumn(); Text("0x%08X", (n > 0) ? tool->Results[n - 1].ID : 0); TableNextColumn(); StackToolFormatLevelInfo(tool, n, true, g.TempBuffer.Data, g.TempBuffer.Size); TextUnformatted(g.TempBuffer.Data); TableNextColumn(); Text("0x%08X", info->ID); if (n == tool->Results.Size - 1) TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_Header)); } EndTable(); } End(); } #else void ImGui::ShowMetricsWindow(bool*) {} void ImGui::ShowFontAtlas(ImFontAtlas*) {} void ImGui::DebugNodeColumns(ImGuiOldColumns*) {} void ImGui::DebugNodeDrawList(ImGuiWindow*, ImGuiViewportP*, const ImDrawList*, const char*) {} void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList*, const ImDrawList*, const ImDrawCmd*, bool, bool) {} void ImGui::DebugNodeFont(ImFont*) {} void ImGui::DebugNodeStorage(ImGuiStorage*, const char*) {} void ImGui::DebugNodeTabBar(ImGuiTabBar*, const char*) {} void ImGui::DebugNodeWindow(ImGuiWindow*, const char*) {} void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings*) {} void ImGui::DebugNodeWindowsList(ImVector*, const char*) {} void ImGui::DebugNodeViewport(ImGuiViewportP*) {} void ImGui::DebugLog(const char*, ...) {} void ImGui::DebugLogV(const char*, va_list) {} void ImGui::ShowDebugLogWindow(bool*) {} void ImGui::ShowIDStackToolWindow(bool*) {} void ImGui::DebugHookIdInfo(ImGuiID, ImGuiDataType, const void*, const void*) {} #endif // #ifndef IMGUI_DISABLE_DEBUG_TOOLS //----------------------------------------------------------------------------- // Include imgui_user.inl at the end of imgui.cpp to access private data/functions that aren't exposed. // Prefer just including imgui_internal.h from your code rather than using this define. If a declaration is missing from imgui_internal.h add it or request it on the github. #ifdef IMGUI_INCLUDE_IMGUI_USER_INL #include "imgui_user.inl" #endif //----------------------------------------------------------------------------- #endif // #ifndef IMGUI_DISABLE RenderKit-ospray-f2a61c2/apps/common/external/imgui/imgui.h000066400000000000000000012015561456566705700240330ustar00rootroot00000000000000// dear imgui, v1.90.3 // (headers) // Help: // - See links below. // - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that. // - Read top of imgui.cpp for more details, links and comments. // Resources: // - FAQ https://dearimgui.com/faq // - Getting Started https://dearimgui.com/getting-started // - Homepage https://github.com/ocornut/imgui // - Releases & changelog https://github.com/ocornut/imgui/releases // - Gallery https://github.com/ocornut/imgui/issues/6897 (please post your screenshots/video there!) // - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there) // - Glossary https://github.com/ocornut/imgui/wiki/Glossary // - Issues & support https://github.com/ocornut/imgui/issues // - Tests & Automation https://github.com/ocornut/imgui_test_engine // For first-time users having issues compiling/linking/running/loading fonts: // please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above. // Everything else should be asked in 'Issues'! We are building a database of cross-linked knowledge there. // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.90.3" #define IMGUI_VERSION_NUM 19030 #define IMGUI_HAS_TABLE /* Index of this file: // [SECTION] Header mess // [SECTION] Forward declarations and basic types // [SECTION] Dear ImGui end-user API functions // [SECTION] Flags & Enumerations // [SECTION] Tables API flags and structures (ImGuiTableFlags, ImGuiTableColumnFlags, ImGuiTableRowFlags, ImGuiTableBgTarget, ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs) // [SECTION] Helpers: Memory allocations macros, ImVector<> // [SECTION] ImGuiStyle // [SECTION] ImGuiIO // [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiPayload) // [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, Math Operators, ImColor) // [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawListFlags, ImDrawList, ImDrawData) // [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont) // [SECTION] Viewports (ImGuiViewportFlags, ImGuiViewport) // [SECTION] Platform Dependent Interfaces (ImGuiPlatformImeData) // [SECTION] Obsolete functions and types */ #pragma once // Configuration file with compile-time options // (edit imconfig.h or '#define IMGUI_USER_CONFIG "myfilename.h" from your build system) #ifdef IMGUI_USER_CONFIG #include IMGUI_USER_CONFIG #endif #include "imconfig.h" #ifndef IMGUI_DISABLE //----------------------------------------------------------------------------- // [SECTION] Header mess //----------------------------------------------------------------------------- // Includes #include // FLT_MIN, FLT_MAX #include // va_list, va_start, va_end #include // ptrdiff_t, NULL #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp // Define attributes of all API symbols declarations (e.g. for DLL under Windows) // IMGUI_API is used for core imgui functions, IMGUI_IMPL_API is used for the default backends files (imgui_impl_xxx.h) // Using dear imgui via a shared library is not recommended: we don't guarantee backward nor forward ABI compatibility + this is a call-heavy library and function call overhead adds up. #ifndef IMGUI_API #define IMGUI_API #endif #ifndef IMGUI_IMPL_API #define IMGUI_IMPL_API IMGUI_API #endif // Helper Macros #ifndef IM_ASSERT #include #define IM_ASSERT(_EXPR) assert(_EXPR) // You can override the default assert handler by editing imconfig.h #endif #define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR)))) // Size of a static C-style array. Don't use on pointers! #define IM_UNUSED(_VAR) ((void)(_VAR)) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds. #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) // Helper Macros - IM_FMTARGS, IM_FMTLIST: Apply printf-style warnings to our formatting functions. // (MSVC provides an equivalent mechanism via SAL Annotations but it would require the macros in a different // location. e.g. #include + void myprintf(_Printf_format_string_ const char* format, ...)) #if !defined(IMGUI_USE_STB_SPRINTF) && defined(__MINGW32__) && !defined(__clang__) #define IM_FMTARGS(FMT) __attribute__((format(gnu_printf, FMT, FMT+1))) #define IM_FMTLIST(FMT) __attribute__((format(gnu_printf, FMT, 0))) #elif !defined(IMGUI_USE_STB_SPRINTF) && (defined(__clang__) || defined(__GNUC__)) #define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) #define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0))) #else #define IM_FMTARGS(FMT) #define IM_FMTLIST(FMT) #endif // Disable some of MSVC most aggressive Debug runtime checks in function header/footer (used in some simple/low-level functions) #if defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(IMGUI_DEBUG_PARANOID) #define IM_MSVC_RUNTIME_CHECKS_OFF __pragma(runtime_checks("",off)) __pragma(check_stack(off)) __pragma(strict_gs_check(push,off)) #define IM_MSVC_RUNTIME_CHECKS_RESTORE __pragma(runtime_checks("",restore)) __pragma(check_stack()) __pragma(strict_gs_check(pop)) #else #define IM_MSVC_RUNTIME_CHECKS_OFF #define IM_MSVC_RUNTIME_CHECKS_RESTORE #endif // Warnings #ifdef _MSC_VER #pragma warning (push) #pragma warning (disable: 26495) // [Static Analyzer] Variable 'XXX' is uninitialized. Always initialize a member variable (type.6). #endif #if defined(__clang__) #pragma clang diagnostic push #if __has_warning("-Wunknown-warning-option") #pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' #endif #pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' #pragma clang diagnostic ignored "-Wold-style-cast" #pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" #pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter #elif defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #endif //----------------------------------------------------------------------------- // [SECTION] Forward declarations and basic types //----------------------------------------------------------------------------- // Forward declarations struct ImDrawChannel; // Temporary storage to output draw commands out of order, used by ImDrawListSplitter and ImDrawList::ChannelsSplit() struct ImDrawCmd; // A single draw command within a parent ImDrawList (generally maps to 1 GPU draw call, unless it is a callback) struct ImDrawData; // All draw command lists required to render the frame + pos/size coordinates to use for the projection matrix. struct ImDrawList; // A single draw command list (generally one per window, conceptually you may see this as a dynamic "mesh" builder) struct ImDrawListSharedData; // Data shared among multiple draw lists (typically owned by parent ImGui context, but you may create one yourself) struct ImDrawListSplitter; // Helper to split a draw list into different layers which can be drawn into out of order, then flattened back. struct ImDrawVert; // A single vertex (pos + uv + col = 20 bytes by default. Override layout with IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT) struct ImFont; // Runtime data for a single font within a parent ImFontAtlas struct ImFontAtlas; // Runtime data for multiple fonts, bake multiple fonts into a single texture, TTF/OTF font loader struct ImFontBuilderIO; // Opaque interface to a font builder (stb_truetype or FreeType). struct ImFontConfig; // Configuration data when adding a font or merging fonts struct ImFontGlyph; // A single font glyph (code point + coordinates within in ImFontAtlas + offset) struct ImFontGlyphRangesBuilder; // Helper to build glyph ranges from text/string data struct ImColor; // Helper functions to create a color that can be converted to either u32 or float4 (*OBSOLETE* please avoid using) struct ImGuiContext; // Dear ImGui context (opaque structure, unless including imgui_internal.h) struct ImGuiIO; // Main configuration and I/O between your application and ImGui struct ImGuiInputTextCallbackData; // Shared state of InputText() when using custom ImGuiInputTextCallback (rare/advanced use) struct ImGuiKeyData; // Storage for ImGuiIO and IsKeyDown(), IsKeyPressed() etc functions. struct ImGuiListClipper; // Helper to manually clip large list of items struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame struct ImGuiPayload; // User data payload for drag and drop operations struct ImGuiPlatformImeData; // Platform IME data for io.SetPlatformImeDataFn() function. struct ImGuiSizeCallbackData; // Callback data when using SetNextWindowSizeConstraints() (rare/advanced use) struct ImGuiStorage; // Helper for key->value storage struct ImGuiStyle; // Runtime data for styling/colors struct ImGuiTableSortSpecs; // Sorting specifications for a table (often handling sort specs for a single column, occasionally more) struct ImGuiTableColumnSortSpecs; // Sorting specification for one column of a table struct ImGuiTextBuffer; // Helper to hold and append into a text buffer (~string builder) struct ImGuiTextFilter; // Helper to parse and apply text filters (e.g. "aaaaa[,bbbbb][,ccccc]") struct ImGuiViewport; // A Platform Window (always only one in 'master' branch), in the future may represent Platform Monitor // Enumerations // - We don't use strongly typed enums much because they add constraints (can't extend in private code, can't store typed in bit fields, extra casting on iteration) // - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists! // In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. enum ImGuiKey : int; // -> enum ImGuiKey // Enum: A key identifier (ImGuiKey_XXX or ImGuiMod_XXX value) enum ImGuiMouseSource : int; // -> enum ImGuiMouseSource // Enum; A mouse input source identifier (Mouse, TouchScreen, Pen) typedef int ImGuiCol; // -> enum ImGuiCol_ // Enum: A color identifier for styling typedef int ImGuiCond; // -> enum ImGuiCond_ // Enum: A condition for many Set*() functions typedef int ImGuiDataType; // -> enum ImGuiDataType_ // Enum: A primary data type typedef int ImGuiDir; // -> enum ImGuiDir_ // Enum: A cardinal direction typedef int ImGuiMouseButton; // -> enum ImGuiMouseButton_ // Enum: A mouse button identifier (0=left, 1=right, 2=middle) typedef int ImGuiMouseCursor; // -> enum ImGuiMouseCursor_ // Enum: A mouse cursor shape typedef int ImGuiSortDirection; // -> enum ImGuiSortDirection_ // Enum: A sorting direction (ascending or descending) typedef int ImGuiStyleVar; // -> enum ImGuiStyleVar_ // Enum: A variable identifier for styling typedef int ImGuiTableBgTarget; // -> enum ImGuiTableBgTarget_ // Enum: A color target for TableSetBgColor() // Flags (declared as int to allow using as flags without overhead, and to not pollute the top of this file) // - Tip: Use your programming IDE navigation facilities on the names in the _central column_ below to find the actual flags/enum lists! // In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. typedef int ImDrawFlags; // -> enum ImDrawFlags_ // Flags: for ImDrawList functions typedef int ImDrawListFlags; // -> enum ImDrawListFlags_ // Flags: for ImDrawList instance typedef int ImFontAtlasFlags; // -> enum ImFontAtlasFlags_ // Flags: for ImFontAtlas build typedef int ImGuiBackendFlags; // -> enum ImGuiBackendFlags_ // Flags: for io.BackendFlags typedef int ImGuiButtonFlags; // -> enum ImGuiButtonFlags_ // Flags: for InvisibleButton() typedef int ImGuiChildFlags; // -> enum ImGuiChildFlags_ // Flags: for BeginChild() typedef int ImGuiColorEditFlags; // -> enum ImGuiColorEditFlags_ // Flags: for ColorEdit4(), ColorPicker4() etc. typedef int ImGuiConfigFlags; // -> enum ImGuiConfigFlags_ // Flags: for io.ConfigFlags typedef int ImGuiComboFlags; // -> enum ImGuiComboFlags_ // Flags: for BeginCombo() typedef int ImGuiDragDropFlags; // -> enum ImGuiDragDropFlags_ // Flags: for BeginDragDropSource(), AcceptDragDropPayload() typedef int ImGuiFocusedFlags; // -> enum ImGuiFocusedFlags_ // Flags: for IsWindowFocused() typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: for IsItemHovered(), IsWindowHovered() etc. typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText(), InputTextMultiline() typedef int ImGuiKeyChord; // -> ImGuiKey | ImGuiMod_XXX // Flags: for IsKeyChordPressed(), Shortcut() etc. an ImGuiKey optionally OR-ed with one or more ImGuiMod_XXX values. typedef int ImGuiPopupFlags; // -> enum ImGuiPopupFlags_ // Flags: for OpenPopup*(), BeginPopupContext*(), IsPopupOpen() typedef int ImGuiSelectableFlags; // -> enum ImGuiSelectableFlags_ // Flags: for Selectable() typedef int ImGuiSliderFlags; // -> enum ImGuiSliderFlags_ // Flags: for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc. typedef int ImGuiTabBarFlags; // -> enum ImGuiTabBarFlags_ // Flags: for BeginTabBar() typedef int ImGuiTabItemFlags; // -> enum ImGuiTabItemFlags_ // Flags: for BeginTabItem() typedef int ImGuiTableFlags; // -> enum ImGuiTableFlags_ // Flags: For BeginTable() typedef int ImGuiTableColumnFlags; // -> enum ImGuiTableColumnFlags_// Flags: For TableSetupColumn() typedef int ImGuiTableRowFlags; // -> enum ImGuiTableRowFlags_ // Flags: For TableNextRow() typedef int ImGuiTreeNodeFlags; // -> enum ImGuiTreeNodeFlags_ // Flags: for TreeNode(), TreeNodeEx(), CollapsingHeader() typedef int ImGuiViewportFlags; // -> enum ImGuiViewportFlags_ // Flags: for ImGuiViewport typedef int ImGuiWindowFlags; // -> enum ImGuiWindowFlags_ // Flags: for Begin(), BeginChild() // ImTexture: user data for renderer backend to identify a texture [Compile-time configurable type] // - To use something else than an opaque void* pointer: override with e.g. '#define ImTextureID MyTextureType*' in your imconfig.h file. // - This can be whatever to you want it to be! read the FAQ about ImTextureID for details. #ifndef ImTextureID typedef void* ImTextureID; // Default: store a pointer or an integer fitting in a pointer (most renderer backends are ok with that) #endif // ImDrawIdx: vertex index. [Compile-time configurable type] // - To use 16-bit indices + allow large meshes: backend need to set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset' and handle ImDrawCmd::VtxOffset (recommended). // - To use 32-bit indices: override with '#define ImDrawIdx unsigned int' in your imconfig.h file. #ifndef ImDrawIdx typedef unsigned short ImDrawIdx; // Default: 16-bit (for maximum compatibility with renderer backends) #endif // Scalar data types typedef unsigned int ImGuiID;// A unique ID used by widgets (typically the result of hashing a stack of string) typedef signed char ImS8; // 8-bit signed integer typedef unsigned char ImU8; // 8-bit unsigned integer typedef signed short ImS16; // 16-bit signed integer typedef unsigned short ImU16; // 16-bit unsigned integer typedef signed int ImS32; // 32-bit signed integer == int typedef unsigned int ImU32; // 32-bit unsigned integer (often used to store packed colors) typedef signed long long ImS64; // 64-bit signed integer typedef unsigned long long ImU64; // 64-bit unsigned integer // Character types // (we generally use UTF-8 encoded string in the API. This is storage specifically for a decoded character used for keyboard input and display) typedef unsigned int ImWchar32; // A single decoded U32 character/code point. We encode them as multi bytes UTF-8 when used in strings. typedef unsigned short ImWchar16; // A single decoded U16 character/code point. We encode them as multi bytes UTF-8 when used in strings. #ifdef IMGUI_USE_WCHAR32 // ImWchar [configurable type: override in imconfig.h with '#define IMGUI_USE_WCHAR32' to support Unicode planes 1-16] typedef ImWchar32 ImWchar; #else typedef ImWchar16 ImWchar; #endif // Callback and functions types typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data); // Callback function for ImGui::InputText() typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); // Callback function for ImGui::SetNextWindowSizeConstraints() typedef void* (*ImGuiMemAllocFunc)(size_t sz, void* user_data); // Function signature for ImGui::SetAllocatorFunctions() typedef void (*ImGuiMemFreeFunc)(void* ptr, void* user_data); // Function signature for ImGui::SetAllocatorFunctions() // ImVec2: 2D vector used to store positions, sizes etc. [Compile-time configurable type] // This is a frequently used type in the API. Consider using IM_VEC2_CLASS_EXTRA to create implicit cast from/to our preferred type. // Add '#define IMGUI_DEFINE_MATH_OPERATORS' in your imconfig.h file to benefit from courtesy maths operators for those types. IM_MSVC_RUNTIME_CHECKS_OFF struct ImVec2 { float x, y; constexpr ImVec2() : x(0.0f), y(0.0f) { } constexpr ImVec2(float _x, float _y) : x(_x), y(_y) { } float& operator[] (size_t idx) { IM_ASSERT(idx == 0 || idx == 1); return ((float*)(void*)(char*)this)[idx]; } // We very rarely use this [] operator, so the assert overhead is fine. float operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return ((const float*)(const void*)(const char*)this)[idx]; } #ifdef IM_VEC2_CLASS_EXTRA IM_VEC2_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec2. #endif }; // ImVec4: 4D vector used to store clipping rectangles, colors etc. [Compile-time configurable type] struct ImVec4 { float x, y, z, w; constexpr ImVec4() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) { } constexpr ImVec4(float _x, float _y, float _z, float _w) : x(_x), y(_y), z(_z), w(_w) { } #ifdef IM_VEC4_CLASS_EXTRA IM_VEC4_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec4. #endif }; IM_MSVC_RUNTIME_CHECKS_RESTORE //----------------------------------------------------------------------------- // [SECTION] Dear ImGui end-user API functions // (Note that ImGui:: being a namespace, you can add extra ImGui:: functions in your own separate file. Please don't modify imgui source files!) //----------------------------------------------------------------------------- namespace ImGui { // Context creation and access // - Each context create its own ImFontAtlas by default. You may instance one yourself and pass it to CreateContext() to share a font atlas between contexts. // - DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for details. IMGUI_API ImGuiContext* CreateContext(ImFontAtlas* shared_font_atlas = NULL); IMGUI_API void DestroyContext(ImGuiContext* ctx = NULL); // NULL = destroy current context IMGUI_API ImGuiContext* GetCurrentContext(); IMGUI_API void SetCurrentContext(ImGuiContext* ctx); // Main IMGUI_API ImGuiIO& GetIO(); // access the IO structure (mouse/keyboard/gamepad inputs, time, various configuration options/flags) IMGUI_API ImGuiStyle& GetStyle(); // access the Style structure (colors, sizes). Always use PushStyleColor(), PushStyleVar() to modify style mid-frame! IMGUI_API void NewFrame(); // start a new Dear ImGui frame, you can submit any command from this point until Render()/EndFrame(). IMGUI_API void EndFrame(); // ends the Dear ImGui frame. automatically called by Render(). If you don't need to render data (skipping rendering) you may call EndFrame() without Render()... but you'll have wasted CPU already! If you don't need to render, better to not create any windows and not call NewFrame() at all! IMGUI_API void Render(); // ends the Dear ImGui frame, finalize the draw data. You can then get call GetDrawData(). IMGUI_API ImDrawData* GetDrawData(); // valid after Render() and until the next call to NewFrame(). this is what you have to render. // Demo, Debug, Information IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create Demo window. demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application! IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create Metrics/Debugger window. display Dear ImGui internals: windows, draw commands, various internal state, etc. IMGUI_API void ShowDebugLogWindow(bool* p_open = NULL); // create Debug Log window. display a simplified log of important dear imgui events. IMGUI_API void ShowIDStackToolWindow(bool* p_open = NULL); // create Stack Tool window. hover items with mouse to query information about the source of their unique ID. IMGUI_API void ShowAboutWindow(bool* p_open = NULL); // create About window. display Dear ImGui version, credits and build/system information. IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // add style editor block (not a window). you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style) IMGUI_API bool ShowStyleSelector(const char* label); // add style selector block (not a window), essentially a combo listing the default styles. IMGUI_API void ShowFontSelector(const char* label); // add font selector block (not a window), essentially a combo listing the loaded fonts. IMGUI_API void ShowUserGuide(); // add basic help/info block (not a window): how to manipulate ImGui as an end-user (mouse/keyboard controls). IMGUI_API const char* GetVersion(); // get the compiled version string e.g. "1.80 WIP" (essentially the value for IMGUI_VERSION from the compiled version of imgui.cpp) // Styles IMGUI_API void StyleColorsDark(ImGuiStyle* dst = NULL); // new, recommended style (default) IMGUI_API void StyleColorsLight(ImGuiStyle* dst = NULL); // best used with borders and a custom, thicker font IMGUI_API void StyleColorsClassic(ImGuiStyle* dst = NULL); // classic imgui style // Windows // - Begin() = push window to the stack and start appending to it. End() = pop window from the stack. // - Passing 'bool* p_open != NULL' shows a window-closing widget in the upper-right corner of the window, // which clicking will set the boolean to false when clicked. // - You may append multiple times to the same window during the same frame by calling Begin()/End() pairs multiple times. // Some information such as 'flags' or 'p_open' will only be considered by the first call to Begin(). // - Begin() return false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting // anything to the window. Always call a matching End() for each Begin() call, regardless of its return value! // [Important: due to legacy reason, Begin/End and BeginChild/EndChild are inconsistent with all other functions // such as BeginMenu/EndMenu, BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding // BeginXXX function returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.] // - Note that the bottom of window stack always contains a window called "Debug". IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); IMGUI_API void End(); // Child Windows // - Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window. Child windows can embed their own child. // - Before 1.90 (November 2023), the "ImGuiChildFlags child_flags = 0" parameter was "bool border = false". // This API is backward compatible with old code, as we guarantee that ImGuiChildFlags_Border == true. // Consider updating your old code: // BeginChild("Name", size, false) -> Begin("Name", size, 0); or Begin("Name", size, ImGuiChildFlags_None); // BeginChild("Name", size, true) -> Begin("Name", size, ImGuiChildFlags_Border); // - Manual sizing (each axis can use a different setting e.g. ImVec2(0.0f, 400.0f)): // == 0.0f: use remaining parent window size for this axis. // > 0.0f: use specified size for this axis. // < 0.0f: right/bottom-align to specified distance from available content boundaries. // - Specifying ImGuiChildFlags_AutoResizeX or ImGuiChildFlags_AutoResizeY makes the sizing automatic based on child contents. // Combining both ImGuiChildFlags_AutoResizeX _and_ ImGuiChildFlags_AutoResizeY defeats purpose of a scrolling region and is NOT recommended. // - BeginChild() returns false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting // anything to the window. Always call a matching EndChild() for each BeginChild() call, regardless of its return value. // [Important: due to legacy reason, Begin/End and BeginChild/EndChild are inconsistent with all other functions // such as BeginMenu/EndMenu, BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding // BeginXXX function returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.] IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0, 0), ImGuiChildFlags child_flags = 0, ImGuiWindowFlags window_flags = 0); IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0, 0), ImGuiChildFlags child_flags = 0, ImGuiWindowFlags window_flags = 0); IMGUI_API void EndChild(); // Windows Utilities // - 'current window' = the window we are appending into while inside a Begin()/End() block. 'next window' = next window we will Begin() into. IMGUI_API bool IsWindowAppearing(); IMGUI_API bool IsWindowCollapsed(); IMGUI_API bool IsWindowFocused(ImGuiFocusedFlags flags=0); // is current window focused? or its root/child, depending on flags. see flags for options. IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags=0); // is current window hovered and hoverable (e.g. not blocked by a popup/modal)? See ImGuiHoveredFlags_ for options. IMPORTANT: If you are trying to check whether your mouse should be dispatched to Dear ImGui or to your underlying app, you should not use this function! Use the 'io.WantCaptureMouse' boolean for that! Refer to FAQ entry "How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application?" for details. IMGUI_API ImDrawList* GetWindowDrawList(); // get draw list associated to the current window, to append your own drawing primitives IMGUI_API ImVec2 GetWindowPos(); // get current window position in screen space (note: it is unlikely you need to use this. Consider using current layout pos instead, GetCursorScreenPos()) IMGUI_API ImVec2 GetWindowSize(); // get current window size (note: it is unlikely you need to use this. Consider using GetCursorScreenPos() and e.g. GetContentRegionAvail() instead) IMGUI_API float GetWindowWidth(); // get current window width (shortcut for GetWindowSize().x) IMGUI_API float GetWindowHeight(); // get current window height (shortcut for GetWindowSize().y) // Window manipulation // - Prefer using SetNextXXX functions (before Begin) rather that SetXXX functions (after Begin). IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0, const ImVec2& pivot = ImVec2(0, 0)); // set next window position. call before Begin(). use pivot=(0.5f,0.5f) to center on given point, etc. IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin() IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use 0.0f or FLT_MAX if you don't want limits. Use -1 for both min and max of same axis to preserve current size (which itself is a constraint). Use callback to apply non-trivial programmatic constraints. IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (~ scrollable client area, which enforce the range of scrollbars). Not including window decorations (title bar, menu bar, etc.) nor WindowPadding. set an axis to 0.0f to leave it automatic. call before Begin() IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // set next window collapsed state. call before Begin() IMGUI_API void SetNextWindowFocus(); // set next window to be focused / top-most. call before Begin() IMGUI_API void SetNextWindowScroll(const ImVec2& scroll); // set next window scrolling value (use < 0.0f to not affect a given axis). IMGUI_API void SetNextWindowBgAlpha(float alpha); // set next window background color alpha. helper to easily override the Alpha component of ImGuiCol_WindowBg/ChildBg/PopupBg. you may also use ImGuiWindowFlags_NoBackground. IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects. IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0, 0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / top-most. prefer using SetNextWindowFocus(). IMGUI_API void SetWindowFontScale(float scale); // [OBSOLETE] set font scale. Adjust IO.FontGlobalScale if you want to scale all windows. This is an old API! For correct scaling, prefer to reload font + rebuild ImFontAtlas + call style.ScaleAllSizes(). IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond = 0); // set named window position. IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis. IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0); // set named window collapsed state IMGUI_API void SetWindowFocus(const char* name); // set named window to be focused / top-most. use NULL to remove focus. // Content region // - Retrieve available space from a given point. GetContentRegionAvail() is frequently useful. // - Those functions are bound to be redesigned (they are confusing, incomplete and the Min/Max return values are in local window coordinates which increases confusion) IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos() IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates IMGUI_API ImVec2 GetWindowContentRegionMin(); // content boundaries min for the full window (roughly (0,0)-Scroll), in window coordinates IMGUI_API ImVec2 GetWindowContentRegionMax(); // content boundaries max for the full window (roughly (0,0)+Size-Scroll) where Size can be overridden with SetNextWindowContentSize(), in window coordinates // Windows Scrolling // - Any change of Scroll will be applied at the beginning of next frame in the first call to Begin(). // - You may instead use SetNextWindowScroll() prior to calling Begin() to avoid this delay, as an alternative to using SetScrollX()/SetScrollY(). IMGUI_API float GetScrollX(); // get scrolling amount [0 .. GetScrollMaxX()] IMGUI_API float GetScrollY(); // get scrolling amount [0 .. GetScrollMaxY()] IMGUI_API void SetScrollX(float scroll_x); // set scrolling amount [0 .. GetScrollMaxX()] IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0 .. GetScrollMaxY()] IMGUI_API float GetScrollMaxX(); // get maximum scrolling amount ~~ ContentSize.x - WindowSize.x - DecorationsSize.x IMGUI_API float GetScrollMaxY(); // get maximum scrolling amount ~~ ContentSize.y - WindowSize.y - DecorationsSize.y IMGUI_API void SetScrollHereX(float center_x_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_x_ratio=0.0: left, 0.5: center, 1.0: right. When using to make a "default/current item" visible, consider using SetItemDefaultFocus() instead. IMGUI_API void SetScrollHereY(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. When using to make a "default/current item" visible, consider using SetItemDefaultFocus() instead. IMGUI_API void SetScrollFromPosX(float local_x, float center_x_ratio = 0.5f); // adjust scrolling amount to make given position visible. Generally GetCursorStartPos() + offset to compute a valid position. IMGUI_API void SetScrollFromPosY(float local_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position visible. Generally GetCursorStartPos() + offset to compute a valid position. // Parameters stacks (shared) IMGUI_API void PushFont(ImFont* font); // use NULL as a shortcut to push default font IMGUI_API void PopFont(); IMGUI_API void PushStyleColor(ImGuiCol idx, ImU32 col); // modify a style color. always use this if you modify the style after NewFrame(). IMGUI_API void PushStyleColor(ImGuiCol idx, const ImVec4& col); IMGUI_API void PopStyleColor(int count = 1); IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); // modify a style float variable. always use this if you modify the style after NewFrame(). IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val); // modify a style ImVec2 variable. always use this if you modify the style after NewFrame(). IMGUI_API void PopStyleVar(int count = 1); IMGUI_API void PushTabStop(bool tab_stop); // == tab stop enable. Allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets IMGUI_API void PopTabStop(); IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame. IMGUI_API void PopButtonRepeat(); // Parameters stacks (current window) IMGUI_API void PushItemWidth(float item_width); // push width of items for common large "item+label" widgets. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -FLT_MIN always align width to the right side). IMGUI_API void PopItemWidth(); IMGUI_API void SetNextItemWidth(float item_width); // set width of the _next_ common large "item+label" widget. >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -FLT_MIN always align width to the right side) IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position. NOT necessarily the width of last item unlike most 'Item' functions. IMGUI_API void PushTextWrapPos(float wrap_local_pos_x = 0.0f); // push word-wrapping position for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space IMGUI_API void PopTextWrapPos(); // Style read access // - Use the ShowStyleEditor() function to interactively see/edit the colors. IMGUI_API ImFont* GetFont(); // get current font IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul = 1.0f); // retrieve given style color with style alpha applied and optional extra alpha multiplier, packed as a 32-bit value suitable for ImDrawList IMGUI_API ImU32 GetColorU32(const ImVec4& col); // retrieve given color with style alpha applied, packed as a 32-bit value suitable for ImDrawList IMGUI_API ImU32 GetColorU32(ImU32 col); // retrieve given color with style alpha applied, packed as a 32-bit value suitable for ImDrawList IMGUI_API const ImVec4& GetStyleColorVec4(ImGuiCol idx); // retrieve style color as stored in ImGuiStyle structure. use to feed back into PushStyleColor(), otherwise use GetColorU32() to get style color with style alpha baked in. // Layout cursor positioning // - By "cursor" we mean the current output position. // - The typical widget behavior is to output themselves at the current cursor position, then move the cursor one line down. // - You can call SameLine() between widgets to undo the last carriage return and output at the right of the preceding widget. // - Attention! We currently have inconsistencies between window-local and absolute positions we will aim to fix with future API: // - Absolute coordinate: GetCursorScreenPos(), SetCursorScreenPos(), all ImDrawList:: functions. -> this is the preferred way forward. // - Window-local coordinates: SameLine(), GetCursorPos(), SetCursorPos(), GetCursorStartPos(), GetContentRegionMax(), GetWindowContentRegion*(), PushTextWrapPos() // - GetCursorScreenPos() = GetCursorPos() + GetWindowPos(). GetWindowPos() is almost only ever useful to convert from window-local to absolute coordinates. IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute coordinates (prefer using this, also more useful to work with ImDrawList API). IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute coordinates IMGUI_API ImVec2 GetCursorPos(); // [window-local] cursor position in window coordinates (relative to window position) IMGUI_API float GetCursorPosX(); // [window-local] " IMGUI_API float GetCursorPosY(); // [window-local] " IMGUI_API void SetCursorPos(const ImVec2& local_pos); // [window-local] " IMGUI_API void SetCursorPosX(float local_x); // [window-local] " IMGUI_API void SetCursorPosY(float local_y); // [window-local] " IMGUI_API ImVec2 GetCursorStartPos(); // [window-local] initial cursor position, in window coordinates // Other layout functions IMGUI_API void Separator(); // separator, generally horizontal. inside a menu bar or in horizontal layout mode, this becomes a vertical separator. IMGUI_API void SameLine(float offset_from_start_x=0.0f, float spacing=-1.0f); // call between widgets or groups to layout them horizontally. X position given in window coordinates. IMGUI_API void NewLine(); // undo a SameLine() or force a new line when in a horizontal-layout context. IMGUI_API void Spacing(); // add vertical spacing. IMGUI_API void Dummy(const ImVec2& size); // add a dummy item of given size. unlike InvisibleButton(), Dummy() won't take the mouse click or be navigable into. IMGUI_API void Indent(float indent_w = 0.0f); // move content position toward the right, by indent_w, or style.IndentSpacing if indent_w <= 0 IMGUI_API void Unindent(float indent_w = 0.0f); // move content position back to the left, by indent_w, or style.IndentSpacing if indent_w <= 0 IMGUI_API void BeginGroup(); // lock horizontal starting position IMGUI_API void EndGroup(); // unlock horizontal starting position + capture the whole group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) IMGUI_API void AlignTextToFramePadding(); // vertically align upcoming text baseline to FramePadding.y so that it will align properly to regularly framed items (call if you have text on a line before a framed item) IMGUI_API float GetTextLineHeight(); // ~ FontSize IMGUI_API float GetTextLineHeightWithSpacing(); // ~ FontSize + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of text) IMGUI_API float GetFrameHeight(); // ~ FontSize + style.FramePadding.y * 2 IMGUI_API float GetFrameHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets) // ID stack/scopes // Read the FAQ (docs/FAQ.md or http://dearimgui.com/faq) for more details about how ID are handled in dear imgui. // - Those questions are answered and impacted by understanding of the ID stack system: // - "Q: Why is my widget not reacting when I click on it?" // - "Q: How can I have widgets with an empty label?" // - "Q: How can I have multiple widgets with the same label?" // - Short version: ID are hashes of the entire ID stack. If you are creating widgets in a loop you most likely // want to push a unique identifier (e.g. object pointer, loop index) to uniquely differentiate them. // - You can also use the "Label##foobar" syntax within widget label to distinguish them from each others. // - In this header file we use the "label"/"name" terminology to denote a string that will be displayed + used as an ID, // whereas "str_id" denote a string that is only used as an ID and not normally displayed. IMGUI_API void PushID(const char* str_id); // push string into the ID stack (will hash string). IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end); // push string into the ID stack (will hash string). IMGUI_API void PushID(const void* ptr_id); // push pointer into the ID stack (will hash pointer). IMGUI_API void PushID(int int_id); // push integer into the ID stack (will hash integer). IMGUI_API void PopID(); // pop from the ID stack. IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage yourself IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end); IMGUI_API ImGuiID GetID(const void* ptr_id); // Widgets: Text IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Roughly equivalent to Text("%s", text) but: A) doesn't require null terminated string if 'text_end' is specified, B) it's faster, no memory copy is done, no buffer size limits, recommended for long chunks of text. IMGUI_API void Text(const char* fmt, ...) IM_FMTARGS(1); // formatted text IMGUI_API void TextV(const char* fmt, va_list args) IM_FMTLIST(1); IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_FMTARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor(); IMGUI_API void TextColoredV(const ImVec4& col, const char* fmt, va_list args) IM_FMTLIST(2); IMGUI_API void TextDisabled(const char* fmt, ...) IM_FMTARGS(1); // shortcut for PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); Text(fmt, ...); PopStyleColor(); IMGUI_API void TextDisabledV(const char* fmt, va_list args) IM_FMTLIST(1); IMGUI_API void TextWrapped(const char* fmt, ...) IM_FMTARGS(1); // shortcut for PushTextWrapPos(0.0f); Text(fmt, ...); PopTextWrapPos();. Note that this won't work on an auto-resizing window if there's no other widgets to extend the window width, yoy may need to set a size using SetNextWindowSize(). IMGUI_API void TextWrappedV(const char* fmt, va_list args) IM_FMTLIST(1); IMGUI_API void LabelText(const char* label, const char* fmt, ...) IM_FMTARGS(2); // display text+label aligned the same way as value+label widgets IMGUI_API void LabelTextV(const char* label, const char* fmt, va_list args) IM_FMTLIST(2); IMGUI_API void BulletText(const char* fmt, ...) IM_FMTARGS(1); // shortcut for Bullet()+Text() IMGUI_API void BulletTextV(const char* fmt, va_list args) IM_FMTLIST(1); IMGUI_API void SeparatorText(const char* label); // currently: formatted text with an horizontal line // Widgets: Main // - Most widgets return true when the value has been changed or when pressed/selected // - You may also use one of the many IsItemXXX functions (e.g. IsItemActive, IsItemHovered, etc.) to query widget state. IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0, 0)); // button IMGUI_API bool SmallButton(const char* label); // button with (FramePadding.y == 0) to easily embed within text IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size, ImGuiButtonFlags flags = 0); // flexible button behavior without the visuals, frequently useful to build custom behaviors using the public api (along with IsItemActive, IsItemHovered, etc.) IMGUI_API bool ArrowButton(const char* str_id, ImGuiDir dir); // square button with an arrow shape IMGUI_API bool Checkbox(const char* label, bool* v); IMGUI_API bool CheckboxFlags(const char* label, int* flags, int flags_value); IMGUI_API bool CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value); IMGUI_API bool RadioButton(const char* label, bool active); // use with e.g. if (RadioButton("one", my_value==1)) { my_value = 1; } IMGUI_API bool RadioButton(const char* label, int* v, int v_button); // shortcut to handle the above pattern when value is an integer IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-FLT_MIN, 0), const char* overlay = NULL); IMGUI_API void Bullet(); // draw a small circle + keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses // Widgets: Images // - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples // - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above. // - Note that Image() may add +2.0f to provided size if a border is visible, ImageButton() adds style.FramePadding*2.0f to provided size. IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& tint_col = ImVec4(1, 1, 1, 1), const ImVec4& border_col = ImVec4(0, 0, 0, 0)); IMGUI_API bool ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); // Widgets: Combo Box (Dropdown) // - The BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it, by creating e.g. Selectable() items. // - The old Combo() api are helpers over BeginCombo()/EndCombo() which are kept available for convenience purpose. This is analogous to how ListBox are created. IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0); IMGUI_API void EndCombo(); // only call EndCombo() if BeginCombo() returns true! IMGUI_API bool Combo(const char* label, int* current_item, const char* const items[], int items_count, int popup_max_height_in_items = -1); IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int popup_max_height_in_items = -1); // Separate items with \0 within a string, end item-list with \0\0. e.g. "One\0Two\0Three\0" IMGUI_API bool Combo(const char* label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int popup_max_height_in_items = -1); // Widgets: Drag Sliders // - CTRL+Click on any drag box to turn them into an input box. Manually input values aren't clamped by default and can go off-bounds. Use ImGuiSliderFlags_AlwaysClamp to always clamp. // - For all the Float2/Float3/Float4/Int2/Int3/Int4 versions of every function, note that a 'float v[X]' function argument is the same as 'float* v', // the array syntax is just a way to document the number of elements that are expected to be accessible. You can pass address of your first element out of a contiguous set, e.g. &myvector.x // - Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc. // - Format string may also be set to NULL or use the default format ("%f" or "%d"). // - Speed are per-pixel of mouse movement (v_speed=0.2f: mouse needs to move by 5 pixels to increase value by 1). For gamepad/keyboard navigation, minimum speed is Max(v_speed, minimum_step_at_given_precision). // - Use v_min < v_max to clamp edits to given limits. Note that CTRL+Click manual input can override those limits if ImGuiSliderFlags_AlwaysClamp is not used. // - Use v_max = FLT_MAX / INT_MAX etc to avoid clamping to a maximum, same with v_min = -FLT_MAX / INT_MIN to avoid clamping to a minimum. // - We use the same sets of flags for DragXXX() and SliderXXX() functions as the features are the same and it makes it easier to swap them. // - Legacy: Pre-1.78 there are DragXXX() function signatures that take a final `float power=1.0f' argument instead of the `ImGuiSliderFlags flags=0' argument. // If you get a warning converting a float to ImGuiSliderFlags, read https://github.com/ocornut/imgui/issues/3361 IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0); // If v_min >= v_max we have no bound IMGUI_API bool DragFloat2(const char* label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0); IMGUI_API bool DragFloat3(const char* label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0); IMGUI_API bool DragFloat4(const char* label, float v[4], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", ImGuiSliderFlags flags = 0); IMGUI_API bool DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* format = "%.3f", const char* format_max = NULL, ImGuiSliderFlags flags = 0); IMGUI_API bool DragInt(const char* label, int* v, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0); // If v_min >= v_max we have no bound IMGUI_API bool DragInt2(const char* label, int v[2], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0); IMGUI_API bool DragInt3(const char* label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0); IMGUI_API bool DragInt4(const char* label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0); IMGUI_API bool DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", const char* format_max = NULL, ImGuiSliderFlags flags = 0); IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, ImGuiSliderFlags flags = 0); IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, ImGuiSliderFlags flags = 0); // Widgets: Regular Sliders // - CTRL+Click on any slider to turn them into an input box. Manually input values aren't clamped by default and can go off-bounds. Use ImGuiSliderFlags_AlwaysClamp to always clamp. // - Adjust format string to decorate the value with a prefix, a suffix, or adapt the editing and display precision e.g. "%.3f" -> 1.234; "%5.2f secs" -> 01.23 secs; "Biscuit: %.0f" -> Biscuit: 1; etc. // - Format string may also be set to NULL or use the default format ("%f" or "%d"). // - Legacy: Pre-1.78 there are SliderXXX() function signatures that take a final `float power=1.0f' argument instead of the `ImGuiSliderFlags flags=0' argument. // If you get a warning converting a float to ImGuiSliderFlags, read https://github.com/ocornut/imgui/issues/3361 IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); // adjust format to decorate the value with a prefix or a suffix for in-slider labels or unit display. IMGUI_API bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); IMGUI_API bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); IMGUI_API bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); IMGUI_API bool SliderAngle(const char* label, float* v_rad, float v_degrees_min = -360.0f, float v_degrees_max = +360.0f, const char* format = "%.0f deg", ImGuiSliderFlags flags = 0); IMGUI_API bool SliderInt(const char* label, int* v, int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); IMGUI_API bool SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); IMGUI_API bool SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); IMGUI_API bool SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); IMGUI_API bool SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0); IMGUI_API bool SliderScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0); IMGUI_API bool VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format = "%.3f", ImGuiSliderFlags flags = 0); IMGUI_API bool VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format = "%d", ImGuiSliderFlags flags = 0); IMGUI_API bool VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format = NULL, ImGuiSliderFlags flags = 0); // Widgets: Input with Keyboard // - If you want to use InputText() with std::string or any custom dynamic string type, see misc/cpp/imgui_stdlib.h and comments in imgui_demo.cpp. // - Most of the ImGuiInputTextFlags flags are only useful for InputText() and not for InputFloatX, InputIntX, InputDouble etc. IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputTextWithHint(const char* label, const char* hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, const char* format = "%.3f", ImGuiInputTextFlags flags = 0); IMGUI_API bool InputFloat2(const char* label, float v[2], const char* format = "%.3f", ImGuiInputTextFlags flags = 0); IMGUI_API bool InputFloat3(const char* label, float v[3], const char* format = "%.3f", ImGuiInputTextFlags flags = 0); IMGUI_API bool InputFloat4(const char* label, float v[4], const char* format = "%.3f", ImGuiInputTextFlags flags = 0); IMGUI_API bool InputInt(const char* label, int* v, int step = 1, int step_fast = 100, ImGuiInputTextFlags flags = 0); IMGUI_API bool InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags = 0); IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags = 0); IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags = 0); IMGUI_API bool InputDouble(const char* label, double* v, double step = 0.0, double step_fast = 0.0, const char* format = "%.6f", ImGuiInputTextFlags flags = 0); IMGUI_API bool InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); IMGUI_API bool InputScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); // Widgets: Color Editor/Picker (tip: the ColorEdit* functions have a little color square that can be left-clicked to open a picker, and right-clicked to open an option menu.) // - Note that in C++ a 'float v[X]' function argument is the _same_ as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. // - You can pass the address of a first float element out of a contiguous structure, e.g. &myvector.x IMGUI_API bool ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags = 0); IMGUI_API bool ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0); IMGUI_API bool ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags = 0); IMGUI_API bool ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = NULL); IMGUI_API bool ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // display a color square/button, hover for details, return true when pressed. IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // initialize current options (generally on application startup) if you want to select a default format, picker type, etc. User will be able to change many settings, unless you pass the _NoOptions flag to your calls. // Widgets: Trees // - TreeNode functions return true when the node is open, in which case you need to also call TreePop() when you are finished displaying the tree node contents. IMGUI_API bool TreeNode(const char* label); IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_FMTARGS(2); // helper variation to easily decorelate the id from the displayed string. Read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet(). IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_FMTARGS(2); // " IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args) IM_FMTLIST(2); IMGUI_API bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args) IM_FMTLIST(2); IMGUI_API bool TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags = 0); IMGUI_API bool TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3); IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3); IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); IMGUI_API void TreePush(const char* str_id); // ~ Indent()+PushID(). Already called by TreeNode() when returning true, but you can call TreePush/TreePop yourself if desired. IMGUI_API void TreePush(const void* ptr_id); // " IMGUI_API void TreePop(); // ~ Unindent()+PopID() IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop(). IMGUI_API bool CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags = 0); // when 'p_visible != NULL': if '*p_visible==true' display an additional small close button on upper right of the header which will set the bool to false when clicked, if '*p_visible==false' don't display the header. IMGUI_API void SetNextItemOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state. // Widgets: Selectables // - A selectable highlights when hovered, and can display another color when selected. // - Neighbors selectable extend their highlight bounds in order to leave no gap between them. This is so a series of selected Selectable appear contiguous. IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper. // Widgets: List Boxes // - This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label. // - You can submit contents and manage your selection state however you want it, by creating e.g. Selectable() or any other items. // - The simplified/old ListBox() api are helpers over BeginListBox()/EndListBox() which are kept available for convenience purpose. This is analoguous to how Combos are created. // - Choose frame width: size.x > 0.0f: custom / size.x < 0.0f or -FLT_MIN: right-align / size.x = 0.0f (default): use current ItemWidth // - Choose frame height: size.y > 0.0f: custom / size.y < 0.0f or -FLT_MIN: bottom-align / size.y = 0.0f (default): arbitrary default height which can fit ~7 items IMGUI_API bool BeginListBox(const char* label, const ImVec2& size = ImVec2(0, 0)); // open a framed scrolling region IMGUI_API void EndListBox(); // only call EndListBox() if BeginListBox() returned true! IMGUI_API bool ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items = -1); IMGUI_API bool ListBox(const char* label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int height_in_items = -1); // Widgets: Data Plotting // - Consider using ImPlot (https://github.com/epezent/implot) which is much better! IMGUI_API void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float)); IMGUI_API void PlotLines(const char* label, float(*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0)); IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float)); IMGUI_API void PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0)); // Widgets: Value() Helpers. // - Those are merely shortcut to calling Text() with a format string. Output single value in "name: value" format (tip: freely declare more in your code to handle your types. you can add functions to the ImGui namespace) IMGUI_API void Value(const char* prefix, bool b); IMGUI_API void Value(const char* prefix, int v); IMGUI_API void Value(const char* prefix, unsigned int v); IMGUI_API void Value(const char* prefix, float v, const char* float_format = NULL); // Widgets: Menus // - Use BeginMenuBar() on a window ImGuiWindowFlags_MenuBar to append to its menu bar. // - Use BeginMainMenuBar() to create a menu bar at the top of the screen and append to it. // - Use BeginMenu() to create a menu. You can call BeginMenu() multiple time with the same identifier to append more items to it. // - Not that MenuItem() keyboardshortcuts are displayed as a convenience but _not processed_ by Dear ImGui at the moment. IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set on parent window). IMGUI_API void EndMenuBar(); // only call EndMenuBar() if BeginMenuBar() returns true! IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar. IMGUI_API void EndMainMenuBar(); // only call EndMainMenuBar() if BeginMainMenuBar() returns true! IMGUI_API bool BeginMenu(const char* label, bool enabled = true); // create a sub-menu entry. only call EndMenu() if this returns true! IMGUI_API void EndMenu(); // only call EndMenu() if BeginMenu() returns true! IMGUI_API bool MenuItem(const char* label, const char* shortcut = NULL, bool selected = false, bool enabled = true); // return true when activated. IMGUI_API bool MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL // Tooltips // - Tooltips are windows following the mouse. They do not take focus away. // - A tooltip window can contain items of any types. SetTooltip() is a shortcut for the 'if (BeginTooltip()) { Text(...); EndTooltip(); }' idiom. IMGUI_API bool BeginTooltip(); // begin/append a tooltip window. IMGUI_API void EndTooltip(); // only call EndTooltip() if BeginTooltip()/BeginItemTooltip() returns true! IMGUI_API void SetTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip. Often used after a ImGui::IsItemHovered() check. Override any previous call to SetTooltip(). IMGUI_API void SetTooltipV(const char* fmt, va_list args) IM_FMTLIST(1); // Tooltips: helpers for showing a tooltip when hovering an item // - BeginItemTooltip() is a shortcut for the 'if (IsItemHovered(ImGuiHoveredFlags_ForTooltip) && BeginTooltip())' idiom. // - SetItemTooltip() is a shortcut for the 'if (IsItemHovered(ImGuiHoveredFlags_ForTooltip)) { SetTooltip(...); }' idiom. // - Where 'ImGuiHoveredFlags_ForTooltip' itself is a shortcut to use 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' depending on active input type. For mouse it defaults to 'ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort'. IMGUI_API bool BeginItemTooltip(); // begin/append a tooltip window if preceding item was hovered. IMGUI_API void SetItemTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip if preceeding item was hovered. override any previous call to SetTooltip(). IMGUI_API void SetItemTooltipV(const char* fmt, va_list args) IM_FMTLIST(1); // Popups, Modals // - They block normal mouse hovering detection (and therefore most mouse interactions) behind them. // - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE. // - Their visibility state (~bool) is held internally instead of being held by the programmer as we are used to with regular Begin*() calls. // - The 3 properties above are related: we need to retain popup visibility state in the library because popups may be closed as any time. // - You can bypass the hovering restriction by using ImGuiHoveredFlags_AllowWhenBlockedByPopup when calling IsItemHovered() or IsWindowHovered(). // - IMPORTANT: Popup identifiers are relative to the current ID stack, so OpenPopup and BeginPopup generally needs to be at the same level of the stack. // This is sometimes leading to confusing mistakes. May rework this in the future. // - BeginPopup(): query popup state, if open start appending into the window. Call EndPopup() afterwards if returned true. ImGuiWindowFlags are forwarded to the window. // - BeginPopupModal(): block every interaction behind the window, cannot be closed by user, add a dimming background, has a title bar. IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // return true if the modal is open, and you can start outputting to it. IMGUI_API void EndPopup(); // only call EndPopup() if BeginPopupXXX() returns true! // Popups: open/close functions // - OpenPopup(): set popup state to open. ImGuiPopupFlags are available for opening options. // - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE. // - CloseCurrentPopup(): use inside the BeginPopup()/EndPopup() scope to close manually. // - CloseCurrentPopup() is called by default by Selectable()/MenuItem() when activated (FIXME: need some options). // - Use ImGuiPopupFlags_NoOpenOverExistingPopup to avoid opening a popup if there's already one at the same level. This is equivalent to e.g. testing for !IsAnyPopupOpen() prior to OpenPopup(). // - Use IsWindowAppearing() after BeginPopup() to tell if a window just opened. // - IMPORTANT: Notice that for OpenPopupOnItemClick() we exceptionally default flags to 1 (== ImGuiPopupFlags_MouseButtonRight) for backward compatibility with older API taking 'int mouse_button = 1' parameter IMGUI_API void OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags = 0); // call to mark popup as open (don't call every frame!). IMGUI_API void OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags = 0); // id overload to facilitate calling from nested stacks IMGUI_API void OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors) IMGUI_API void CloseCurrentPopup(); // manually close the popup we have begin-ed into. // Popups: open+begin combined functions helpers // - Helpers to do OpenPopup+BeginPopup where the Open action is triggered by e.g. hovering an item and right-clicking. // - They are convenient to easily create context menus, hence the name. // - IMPORTANT: Notice that BeginPopupContextXXX takes ImGuiPopupFlags just like OpenPopup() and unlike BeginPopup(). For full consistency, we may add ImGuiWindowFlags to the BeginPopupContextXXX functions in the future. // - IMPORTANT: Notice that we exceptionally default their flags to 1 (== ImGuiPopupFlags_MouseButtonRight) for backward compatibility with older API taking 'int mouse_button = 1' parameter, so if you add other flags remember to re-add the ImGuiPopupFlags_MouseButtonRight. IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked on last item. Use str_id==NULL to associate the popup to previous item. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1);// open+begin popup when clicked on current window. IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked in void (where there are no windows). // Popups: query functions // - IsPopupOpen(): return true if the popup is open at the current BeginPopup() level of the popup stack. // - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId: return true if any popup is open at the current BeginPopup() level of the popup stack. // - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId + ImGuiPopupFlags_AnyPopupLevel: return true if any popup is open. IMGUI_API bool IsPopupOpen(const char* str_id, ImGuiPopupFlags flags = 0); // return true if the popup is open. // Tables // - Full-featured replacement for old Columns API. // - See Demo->Tables for demo code. See top of imgui_tables.cpp for general commentary. // - See ImGuiTableFlags_ and ImGuiTableColumnFlags_ enums for a description of available flags. // The typical call flow is: // - 1. Call BeginTable(), early out if returning false. // - 2. Optionally call TableSetupColumn() to submit column name/flags/defaults. // - 3. Optionally call TableSetupScrollFreeze() to request scroll freezing of columns/rows. // - 4. Optionally call TableHeadersRow() to submit a header row. Names are pulled from TableSetupColumn() data. // - 5. Populate contents: // - In most situations you can use TableNextRow() + TableSetColumnIndex(N) to start appending into a column. // - If you are using tables as a sort of grid, where every column is holding the same type of contents, // you may prefer using TableNextColumn() instead of TableNextRow() + TableSetColumnIndex(). // TableNextColumn() will automatically wrap-around into the next row if needed. // - IMPORTANT: Comparatively to the old Columns() API, we need to call TableNextColumn() for the first column! // - Summary of possible call flow: // - TableNextRow() -> TableSetColumnIndex(0) -> Text("Hello 0") -> TableSetColumnIndex(1) -> Text("Hello 1") // OK // - TableNextRow() -> TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK // - TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK: TableNextColumn() automatically gets to next row! // - TableNextRow() -> Text("Hello 0") // Not OK! Missing TableSetColumnIndex() or TableNextColumn()! Text will not appear! // - 5. Call EndTable() IMGUI_API bool BeginTable(const char* str_id, int column, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0.0f, 0.0f), float inner_width = 0.0f); IMGUI_API void EndTable(); // only call EndTable() if BeginTable() returns true! IMGUI_API void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = 0.0f); // append into the first cell of a new row. IMGUI_API bool TableNextColumn(); // append into the next column (or first column of next row if currently in last column). Return true when column is visible. IMGUI_API bool TableSetColumnIndex(int column_n); // append into the specified column. Return true when column is visible. // Tables: Headers & Columns declaration // - Use TableSetupColumn() to specify label, resizing policy, default width/weight, id, various other flags etc. // - Use TableHeadersRow() to create a header row and automatically submit a TableHeader() for each column. // Headers are required to perform: reordering, sorting, and opening the context menu. // The context menu can also be made available in columns body using ImGuiTableFlags_ContextMenuInBody. // - You may manually submit headers using TableNextRow() + TableHeader() calls, but this is only useful in // some advanced use cases (e.g. adding custom widgets in header row). // - Use TableSetupScrollFreeze() to lock columns/rows so they stay visible when scrolled. IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = 0.0f, ImGuiID user_id = 0); IMGUI_API void TableSetupScrollFreeze(int cols, int rows); // lock columns/rows so they stay visible when scrolled. IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used) IMGUI_API void TableHeadersRow(); // submit a row with headers cells based on data provided to TableSetupColumn() + submit context menu IMGUI_API void TableAngledHeadersRow(); // submit a row with angled headers for every column with the ImGuiTableColumnFlags_AngledHeader flag. MUST BE FIRST ROW. // Tables: Sorting & Miscellaneous functions // - Sorting: call TableGetSortSpecs() to retrieve latest sort specs for the table. NULL when not sorting. // When 'sort_specs->SpecsDirty == true' you should sort your data. It will be true when sorting specs have // changed since last call, or the first time. Make sure to set 'SpecsDirty = false' after sorting, // else you may wastefully sort your data every frame! // - Functions args 'int column_n' treat the default value of -1 as the same as passing the current column index. IMGUI_API ImGuiTableSortSpecs* TableGetSortSpecs(); // get latest sort specs for the table (NULL if not sorting). Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable(). IMGUI_API int TableGetColumnCount(); // return number of columns (value passed to BeginTable) IMGUI_API int TableGetColumnIndex(); // return current column index. IMGUI_API int TableGetRowIndex(); // return current row index. IMGUI_API const char* TableGetColumnName(int column_n = -1); // return "" if column didn't have a name declared by TableSetupColumn(). Pass -1 to use current column. IMGUI_API ImGuiTableColumnFlags TableGetColumnFlags(int column_n = -1); // return column flags so you can query their Enabled/Visible/Sorted/Hovered status flags. Pass -1 to use current column. IMGUI_API void TableSetColumnEnabled(int column_n, bool v);// change user accessible enabled/disabled state of a column. Set to false to hide the column. User can use the context menu to change this themselves (right-click in headers, or right-click in columns body with ImGuiTableFlags_ContextMenuInBody) IMGUI_API void TableSetBgColor(ImGuiTableBgTarget target, ImU32 color, int column_n = -1); // change the color of a cell, row, or column. See ImGuiTableBgTarget_ flags for details. // Legacy Columns API (prefer using Tables!) // - You can also use SameLine(pos_x) to mimic simplified columns. IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished IMGUI_API int GetColumnIndex(); // get current column index IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column IMGUI_API void SetColumnWidth(int column_index, float width); // set column width (in pixels). pass -1 to use current column IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is typically 0.0f IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column IMGUI_API int GetColumnsCount(); // Tab Bars, Tabs // - Note: Tabs are automatically created by the docking system (when in 'docking' branch). Use this to create tab bars/tabs yourself. IMGUI_API bool BeginTabBar(const char* str_id, ImGuiTabBarFlags flags = 0); // create and append into a TabBar IMGUI_API void EndTabBar(); // only call EndTabBar() if BeginTabBar() returns true! IMGUI_API bool BeginTabItem(const char* label, bool* p_open = NULL, ImGuiTabItemFlags flags = 0); // create a Tab. Returns true if the Tab is selected. IMGUI_API void EndTabItem(); // only call EndTabItem() if BeginTabItem() returns true! IMGUI_API bool TabItemButton(const char* label, ImGuiTabItemFlags flags = 0); // create a Tab behaving like a button. return true when clicked. cannot be selected in the tab bar. IMGUI_API void SetTabItemClosed(const char* tab_or_docked_window_label); // notify TabBar or Docking system of a closed tab/window ahead (useful to reduce visual flicker on reorderable tab bars). For tab-bar: call after BeginTabBar() and before Tab submissions. Otherwise call with a window name. // Logging/Capture // - All text output from the interface can be captured into tty/file/clipboard. By default, tree nodes are automatically opened during logging. IMGUI_API void LogToTTY(int auto_open_depth = -1); // start logging to tty (stdout) IMGUI_API void LogToFile(int auto_open_depth = -1, const char* filename = NULL); // start logging to file IMGUI_API void LogToClipboard(int auto_open_depth = -1); // start logging to OS clipboard IMGUI_API void LogFinish(); // stop logging (close file, etc.) IMGUI_API void LogButtons(); // helper to display buttons for logging to tty/file/clipboard IMGUI_API void LogText(const char* fmt, ...) IM_FMTARGS(1); // pass text data straight to log (without being displayed) IMGUI_API void LogTextV(const char* fmt, va_list args) IM_FMTLIST(1); // Drag and Drop // - On source items, call BeginDragDropSource(), if it returns true also call SetDragDropPayload() + EndDragDropSource(). // - On target candidates, call BeginDragDropTarget(), if it returns true also call AcceptDragDropPayload() + EndDragDropTarget(). // - If you stop calling BeginDragDropSource() the payload is preserved however it won't have a preview tooltip (we currently display a fallback "..." tooltip, see #1725) // - An item can be both drag source and drop target. IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0); // call after submitting an item which may be dragged. when this return true, you can call SetDragDropPayload() + EndDragDropSource() IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t sz, ImGuiCond cond = 0); // type is a user defined string of maximum 32 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. Return true when payload has been accepted. IMGUI_API void EndDragDropSource(); // only call EndDragDropSource() if BeginDragDropSource() returns true! IMGUI_API bool BeginDragDropTarget(); // call after submitting an item that may receive a payload. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget() IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released. IMGUI_API void EndDragDropTarget(); // only call EndDragDropTarget() if BeginDragDropTarget() returns true! IMGUI_API const ImGuiPayload* GetDragDropPayload(); // peek directly into the current payload from anywhere. returns NULL when drag and drop is finished or inactive. use ImGuiPayload::IsDataType() to test for the payload type. // Disabling [BETA API] // - Disable all user interactions and dim items visuals (applying style.DisabledAlpha over current colors) // - Those can be nested but it cannot be used to enable an already disabled section (a single BeginDisabled(true) in the stack is enough to keep everything disabled) // - BeginDisabled(false) essentially does nothing useful but is provided to facilitate use of boolean expressions. If you can avoid calling BeginDisabled(False)/EndDisabled() best to avoid it. IMGUI_API void BeginDisabled(bool disabled = true); IMGUI_API void EndDisabled(); // Clipping // - Mouse hovering is affected by ImGui::PushClipRect() calls, unlike direct calls to ImDrawList::PushClipRect() which are render only. IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect); IMGUI_API void PopClipRect(); // Focus, Activation // - Prefer using "SetItemDefaultFocus()" over "if (IsWindowAppearing()) SetScrollHereY()" when applicable to signify "this is the default item" IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a window. IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget. // Overlapping mode IMGUI_API void SetNextItemAllowOverlap(); // allow next item to be overlapped by a subsequent item. Useful with invisible buttons, selectable, treenode covering an area where subsequent items may need to be added. Note that both Selectable() and TreeNode() have dedicated flags doing this. // Item/Widgets Utilities and Query Functions // - Most of the functions are referring to the previous Item that has been submitted. // - See Demo Window under "Widgets->Querying Status" for an interactive visualization of most of those functions. IMGUI_API bool IsItemHovered(ImGuiHoveredFlags flags = 0); // is the last item hovered? (and usable, aka not blocked by a popup, etc.). See ImGuiHoveredFlags for more options. IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited. This will continuously return true while holding mouse button on an item. Items that don't interact will always return false) IMGUI_API bool IsItemFocused(); // is the last item focused for keyboard/gamepad navigation? IMGUI_API bool IsItemClicked(ImGuiMouseButton mouse_button = 0); // is the last item hovered and mouse clicked on? (**) == IsMouseClicked(mouse_button) && IsItemHovered()Important. (**) this is NOT equivalent to the behavior of e.g. Button(). Read comments in function definition. IMGUI_API bool IsItemVisible(); // is the last item visible? (items may be out of sight because of clipping/scrolling) IMGUI_API bool IsItemEdited(); // did the last item modify its underlying value this frame? or was pressed? This is generally the same as the "bool" return value of many widgets. IMGUI_API bool IsItemActivated(); // was the last item just made active (item was previously inactive). IMGUI_API bool IsItemDeactivated(); // was the last item just made inactive (item was previously active). Useful for Undo/Redo patterns with widgets that require continuous editing. IMGUI_API bool IsItemDeactivatedAfterEdit(); // was the last item just made inactive and made a value change when it was active? (e.g. Slider/Drag moved). Useful for Undo/Redo patterns with widgets that require continuous editing. Note that you may get false positives (some widgets such as Combo()/ListBox()/Selectable() will return true even when clicking an already selected item). IMGUI_API bool IsItemToggledOpen(); // was the last item open state toggled? set by TreeNode(). IMGUI_API bool IsAnyItemHovered(); // is any item hovered? IMGUI_API bool IsAnyItemActive(); // is any item active? IMGUI_API bool IsAnyItemFocused(); // is any item focused? IMGUI_API ImGuiID GetItemID(); // get ID of last item (~~ often same ImGui::GetID(label) beforehand) IMGUI_API ImVec2 GetItemRectMin(); // get upper-left bounding rectangle of the last item (screen space) IMGUI_API ImVec2 GetItemRectMax(); // get lower-right bounding rectangle of the last item (screen space) IMGUI_API ImVec2 GetItemRectSize(); // get size of last item // Viewports // - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows. // - In 'docking' branch with multi-viewport enabled, we extend this concept to have multiple active viewports. // - In the future we will extend this concept further to also represent Platform Monitor and support a "no main platform window" operation mode. IMGUI_API ImGuiViewport* GetMainViewport(); // return primary/default viewport. This can never be NULL. // Background/Foreground Draw Lists IMGUI_API ImDrawList* GetBackgroundDrawList(); // this draw list will be the first rendered one. Useful to quickly draw shapes/text behind dear imgui contents. IMGUI_API ImDrawList* GetForegroundDrawList(); // this draw list will be the last rendered one. Useful to quickly draw shapes/text over dear imgui contents. // Miscellaneous Utilities IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped. IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side. IMGUI_API double GetTime(); // get global imgui time. incremented by io.DeltaTime every frame. IMGUI_API int GetFrameCount(); // get global imgui frame count. incremented by 1 every frame. IMGUI_API ImDrawListSharedData* GetDrawListSharedData(); // you may use this when creating your own ImDrawList instances. IMGUI_API const char* GetStyleColorName(ImGuiCol idx); // get a string corresponding to the enum value (for display, saving, etc.). IMGUI_API void SetStateStorage(ImGuiStorage* storage); // replace current window storage with our own (if you want to manipulate it yourself, typically clear subsection of it) IMGUI_API ImGuiStorage* GetStateStorage(); // Text Utilities IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); // Color Utilities IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in); IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4& in); IMGUI_API void ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v); IMGUI_API void ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b); // Inputs Utilities: Keyboard/Mouse/Gamepad // - the ImGuiKey enum contains all possible keyboard, mouse and gamepad inputs (e.g. ImGuiKey_A, ImGuiKey_MouseLeft, ImGuiKey_GamepadDpadUp...). // - before v1.87, we used ImGuiKey to carry native/user indices as defined by each backends. About use of those legacy ImGuiKey values: // - without IMGUI_DISABLE_OBSOLETE_KEYIO (legacy support): you can still use your legacy native/user indices (< 512) according to how your backend/engine stored them in io.KeysDown[], but need to cast them to ImGuiKey. // - with IMGUI_DISABLE_OBSOLETE_KEYIO (this is the way forward): any use of ImGuiKey will assert with key < 512. GetKeyIndex() is pass-through and therefore deprecated (gone if IMGUI_DISABLE_OBSOLETE_KEYIO is defined). IMGUI_API bool IsKeyDown(ImGuiKey key); // is key being held. IMGUI_API bool IsKeyPressed(ImGuiKey key, bool repeat = true); // was key pressed (went from !Down to Down)? if repeat=true, uses io.KeyRepeatDelay / KeyRepeatRate IMGUI_API bool IsKeyReleased(ImGuiKey key); // was key released (went from Down to !Down)? IMGUI_API bool IsKeyChordPressed(ImGuiKeyChord key_chord); // was key chord (mods + key) pressed, e.g. you can pass 'ImGuiMod_Ctrl | ImGuiKey_S' as a key-chord. This doesn't do any routing or focus check, please consider using Shortcut() function instead. IMGUI_API int GetKeyPressedAmount(ImGuiKey key, float repeat_delay, float rate); // uses provided repeat rate/delay. return a count, most often 0 or 1 but might be >1 if RepeatRate is small enough that DeltaTime > RepeatRate IMGUI_API const char* GetKeyName(ImGuiKey key); // [DEBUG] returns English name of the key. Those names a provided for debugging purpose and are not meant to be saved persistently not compared. IMGUI_API void SetNextFrameWantCaptureKeyboard(bool want_capture_keyboard); // Override io.WantCaptureKeyboard flag next frame (said flag is left for your application to handle, typically when true it instructs your app to ignore inputs). e.g. force capture keyboard when your widget is being hovered. This is equivalent to setting "io.WantCaptureKeyboard = want_capture_keyboard"; after the next NewFrame() call. // Inputs Utilities: Mouse specific // - To refer to a mouse button, you may use named enums in your code e.g. ImGuiMouseButton_Left, ImGuiMouseButton_Right. // - You can also use regular integer: it is forever guaranteed that 0=Left, 1=Right, 2=Middle. // - Dragging operations are only reported after mouse has moved a certain distance away from the initial clicking position (see 'lock_threshold' and 'io.MouseDraggingThreshold') IMGUI_API bool IsMouseDown(ImGuiMouseButton button); // is mouse button held? IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, bool repeat = false); // did mouse button clicked? (went from !Down to Down). Same as GetMouseClickedCount() == 1. IMGUI_API bool IsMouseReleased(ImGuiMouseButton button); // did mouse button released? (went from Down to !Down) IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button); // did mouse button double-clicked? Same as GetMouseClickedCount() == 2. (note that a double-click will also report IsMouseClicked() == true) IMGUI_API int GetMouseClickedCount(ImGuiMouseButton button); // return the number of successive mouse-clicks at the time where a click happen (otherwise 0). IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true);// is mouse hovering given bounding rect (in screen space). clipped by current clipping settings, but disregarding of other consideration of focus/window ordering/popup-block. IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); // by convention we use (-FLT_MAX,-FLT_MAX) to denote that there is no mouse available IMGUI_API bool IsAnyMouseDown(); // [WILL OBSOLETE] is any mouse button held? This was designed for backends, but prefer having backend maintain a mask of held mouse buttons, because upcoming input queue system will make this invalid. IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve mouse position at the time of opening popup we have BeginPopup() into (helper to avoid user backing that value themselves) IMGUI_API bool IsMouseDragging(ImGuiMouseButton button, float lock_threshold = -1.0f); // is mouse dragging? (if lock_threshold < -1.0f, uses io.MouseDraggingThreshold) IMGUI_API ImVec2 GetMouseDragDelta(ImGuiMouseButton button = 0, float lock_threshold = -1.0f); // return the delta from the initial clicking position while the mouse button is pressed or was just released. This is locked and return 0.0f until the mouse moves past a distance threshold at least once (if lock_threshold < -1.0f, uses io.MouseDraggingThreshold) IMGUI_API void ResetMouseDragDelta(ImGuiMouseButton button = 0); // IMGUI_API ImGuiMouseCursor GetMouseCursor(); // get desired mouse cursor shape. Important: reset in ImGui::NewFrame(), this is updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you IMGUI_API void SetMouseCursor(ImGuiMouseCursor cursor_type); // set desired mouse cursor shape IMGUI_API void SetNextFrameWantCaptureMouse(bool want_capture_mouse); // Override io.WantCaptureMouse flag next frame (said flag is left for your application to handle, typical when true it instucts your app to ignore inputs). This is equivalent to setting "io.WantCaptureMouse = want_capture_mouse;" after the next NewFrame() call. // Clipboard Utilities // - Also see the LogToClipboard() function to capture GUI into clipboard, or easily output text data to the clipboard. IMGUI_API const char* GetClipboardText(); IMGUI_API void SetClipboardText(const char* text); // Settings/.Ini Utilities // - The disk functions are automatically called if io.IniFilename != NULL (default is "imgui.ini"). // - Set io.IniFilename to NULL to load/save manually. Read io.WantSaveIniSettings description about handling .ini saving manually. // - Important: default value "imgui.ini" is relative to current working dir! Most apps will want to lock this to an absolute path (e.g. same path as executables). IMGUI_API void LoadIniSettingsFromDisk(const char* ini_filename); // call after CreateContext() and before the first call to NewFrame(). NewFrame() automatically calls LoadIniSettingsFromDisk(io.IniFilename). IMGUI_API void LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size=0); // call after CreateContext() and before the first call to NewFrame() to provide .ini data from your own data source. IMGUI_API void SaveIniSettingsToDisk(const char* ini_filename); // this is automatically called (if io.IniFilename is not empty) a few seconds after any modification that should be reflected in the .ini file (and also by DestroyContext). IMGUI_API const char* SaveIniSettingsToMemory(size_t* out_ini_size = NULL); // return a zero-terminated string with the .ini data which you can save by your own mean. call when io.WantSaveIniSettings is set, then save data by your own mean and clear io.WantSaveIniSettings. // Debug Utilities // - Your main debugging friend is the ShowMetricsWindow() function, which is also accessible from Demo->Tools->Metrics Debugger IMGUI_API void DebugTextEncoding(const char* text); IMGUI_API void DebugFlashStyleColor(ImGuiCol idx); IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // This is called by IMGUI_CHECKVERSION() macro. // Memory Allocators // - Those functions are not reliant on the current context. // - DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. IMGUI_API void SetAllocatorFunctions(ImGuiMemAllocFunc alloc_func, ImGuiMemFreeFunc free_func, void* user_data = NULL); IMGUI_API void GetAllocatorFunctions(ImGuiMemAllocFunc* p_alloc_func, ImGuiMemFreeFunc* p_free_func, void** p_user_data); IMGUI_API void* MemAlloc(size_t size); IMGUI_API void MemFree(void* ptr); } // namespace ImGui //----------------------------------------------------------------------------- // [SECTION] Flags & Enumerations //----------------------------------------------------------------------------- // Flags for ImGui::Begin() // (Those are per-window flags. There are shared flags in ImGuiIO: io.ConfigWindowsResizeFromEdges and io.ConfigWindowsMoveFromTitleBarOnly) enum ImGuiWindowFlags_ { ImGuiWindowFlags_None = 0, ImGuiWindowFlags_NoTitleBar = 1 << 0, // Disable title-bar ImGuiWindowFlags_NoResize = 1 << 1, // Disable user resizing with the lower-right grip ImGuiWindowFlags_NoMove = 1 << 2, // Disable user moving the window ImGuiWindowFlags_NoScrollbar = 1 << 3, // Disable scrollbars (window can still scroll with mouse or programmatically) ImGuiWindowFlags_NoScrollWithMouse = 1 << 4, // Disable user vertically scrolling with mouse wheel. On child window, mouse wheel will be forwarded to the parent unless NoScrollbar is also set. ImGuiWindowFlags_NoCollapse = 1 << 5, // Disable user collapsing window by double-clicking on it. Also referred to as Window Menu Button (e.g. within a docking node). ImGuiWindowFlags_AlwaysAutoResize = 1 << 6, // Resize every window to its content every frame ImGuiWindowFlags_NoBackground = 1 << 7, // Disable drawing background color (WindowBg, etc.) and outside border. Similar as using SetNextWindowBgAlpha(0.0f). ImGuiWindowFlags_NoSavedSettings = 1 << 8, // Never load/save settings in .ini file ImGuiWindowFlags_NoMouseInputs = 1 << 9, // Disable catching mouse, hovering test with pass through. ImGuiWindowFlags_MenuBar = 1 << 10, // Has a menu-bar ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You may use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section. ImGuiWindowFlags_NoFocusOnAppearing = 1 << 12, // Disable taking focus when transitioning from hidden to visible state ImGuiWindowFlags_NoBringToFrontOnFocus = 1 << 13, // Disable bringing window to front when taking focus (e.g. clicking on it or programmatically giving it focus) ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) ImGuiWindowFlags_NoNavInputs = 1 << 16, // No gamepad/keyboard navigation within the window ImGuiWindowFlags_NoNavFocus = 1 << 17, // No focusing toward this window with gamepad/keyboard navigation (e.g. skipped by CTRL+TAB) ImGuiWindowFlags_UnsavedDocument = 1 << 18, // Display a dot next to the title. When used in a tab/docking context, tab is selected when clicking the X + closure is not assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar. ImGuiWindowFlags_NoNav = ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, ImGuiWindowFlags_NoDecoration = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse, ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, // [Internal] ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] On child window: share focus scope, allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows. ImGuiWindowFlags_ChildWindow = 1 << 24, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_Tooltip = 1 << 25, // Don't use! For internal use by BeginTooltip() ImGuiWindowFlags_Popup = 1 << 26, // Don't use! For internal use by BeginPopup() ImGuiWindowFlags_Modal = 1 << 27, // Don't use! For internal use by BeginPopupModal() ImGuiWindowFlags_ChildMenu = 1 << 28, // Don't use! For internal use by BeginMenu() // Obsolete names #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 30, // Obsoleted in 1.90: Use ImGuiChildFlags_AlwaysUseWindowPadding in BeginChild() call. #endif }; // Flags for ImGui::BeginChild() // (Legacy: bit 0 must always correspond to ImGuiChildFlags_Border to be backward compatible with old API using 'bool border = false'. // About using AutoResizeX/AutoResizeY flags: // - May be combined with SetNextWindowSizeConstraints() to set a min/max size for each axis (see "Demo->Child->Auto-resize with Constraints"). // - Size measurement for a given axis is only performed when the child window is within visible boundaries, or is just appearing. // - This allows BeginChild() to return false when not within boundaries (e.g. when scrolling), which is more optimal. BUT it won't update its auto-size while clipped. // While not perfect, it is a better default behavior as the always-on performance gain is more valuable than the occasional "resizing after becoming visible again" glitch. // - You may also use ImGuiChildFlags_AlwaysAutoResize to force an update even when child window is not in view. // HOWEVER PLEASE UNDERSTAND THAT DOING SO WILL PREVENT BeginChild() FROM EVER RETURNING FALSE, disabling benefits of coarse clipping. enum ImGuiChildFlags_ { ImGuiChildFlags_None = 0, ImGuiChildFlags_Border = 1 << 0, // Show an outer border and enable WindowPadding. (IMPORTANT: this is always == 1 == true for legacy reason) ImGuiChildFlags_AlwaysUseWindowPadding = 1 << 1, // Pad with style.WindowPadding even if no border are drawn (no padding by default for non-bordered child windows because it makes more sense) ImGuiChildFlags_ResizeX = 1 << 2, // Allow resize from right border (layout direction). Enable .ini saving (unless ImGuiWindowFlags_NoSavedSettings passed to window flags) ImGuiChildFlags_ResizeY = 1 << 3, // Allow resize from bottom border (layout direction). " ImGuiChildFlags_AutoResizeX = 1 << 4, // Enable auto-resizing width. Read "IMPORTANT: Size measurement" details above. ImGuiChildFlags_AutoResizeY = 1 << 5, // Enable auto-resizing height. Read "IMPORTANT: Size measurement" details above. ImGuiChildFlags_AlwaysAutoResize = 1 << 6, // Combined with AutoResizeX/AutoResizeY. Always measure size even when child is hidden, always return true, always disable clipping optimization! NOT RECOMMENDED. ImGuiChildFlags_FrameStyle = 1 << 7, // Style the child window like a framed item: use FrameBg, FrameRounding, FrameBorderSize, FramePadding instead of ChildBg, ChildRounding, ChildBorderSize, WindowPadding. }; // Flags for ImGui::InputText() // (Those are per-item flags. There are shared flags in ImGuiIO: io.ConfigInputTextCursorBlink and io.ConfigInputTextEnterKeepActive) enum ImGuiInputTextFlags_ { ImGuiInputTextFlags_None = 0, ImGuiInputTextFlags_CharsDecimal = 1 << 0, // Allow 0123456789.+-*/ ImGuiInputTextFlags_CharsHexadecimal = 1 << 1, // Allow 0123456789ABCDEFabcdef ImGuiInputTextFlags_CharsUppercase = 1 << 2, // Turn a..z into A..Z ImGuiInputTextFlags_CharsNoBlank = 1 << 3, // Filter out spaces, tabs ImGuiInputTextFlags_AutoSelectAll = 1 << 4, // Select entire text when first taking mouse focus ImGuiInputTextFlags_EnterReturnsTrue = 1 << 5, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider looking at the IsItemDeactivatedAfterEdit() function. ImGuiInputTextFlags_CallbackCompletion = 1 << 6, // Callback on pressing TAB (for completion handling) ImGuiInputTextFlags_CallbackHistory = 1 << 7, // Callback on pressing Up/Down arrows (for history handling) ImGuiInputTextFlags_CallbackAlways = 1 << 8, // Callback on each iteration. User code may query cursor position, modify text buffer. ImGuiInputTextFlags_CallbackCharFilter = 1 << 9, // Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard. ImGuiInputTextFlags_AllowTabInput = 1 << 10, // Pressing TAB input a '\t' character into the text field ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 11, // In multi-line mode, unfocus with Enter, add new line with Ctrl+Enter (default is opposite: unfocus with Ctrl+Enter, add line with Enter). ImGuiInputTextFlags_NoHorizontalScroll = 1 << 12, // Disable following the cursor horizontally ImGuiInputTextFlags_AlwaysOverwrite = 1 << 13, // Overwrite mode ImGuiInputTextFlags_ReadOnly = 1 << 14, // Read-only mode ImGuiInputTextFlags_Password = 1 << 15, // Password mode, display all characters as '*' ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID(). ImGuiInputTextFlags_CharsScientific = 1 << 17, // Allow 0123456789.+-*/eE (Scientific notation input) ImGuiInputTextFlags_CallbackResize = 1 << 18, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this) ImGuiInputTextFlags_CallbackEdit = 1 << 19, // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active) ImGuiInputTextFlags_EscapeClearsAll = 1 << 20, // Escape key clears content if not empty, and deactivate otherwise (contrast to default behavior of Escape to revert) // Obsolete names //ImGuiInputTextFlags_AlwaysInsertMode = ImGuiInputTextFlags_AlwaysOverwrite // [renamed in 1.82] name was not matching behavior }; // Flags for ImGui::TreeNodeEx(), ImGui::CollapsingHeader*() enum ImGuiTreeNodeFlags_ { ImGuiTreeNodeFlags_None = 0, ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected ImGuiTreeNodeFlags_Framed = 1 << 1, // Draw frame with background (e.g. for CollapsingHeader) ImGuiTreeNodeFlags_AllowOverlap = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes) ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Need double-click to open node ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Only open when clicking on the arrow part. If ImGuiTreeNodeFlags_OpenOnDoubleClick is also set, single-click arrow or double-click all box to open. ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow. IMPORTANT: node can still be marked open/close if you don't set the _Leaf flag! ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding(). ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line. In the future we may refactor the hit system to be front-to-back, allowing natural overlaps and then this can become the default. ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (bypass the indented area). ImGuiTreeNodeFlags_SpanAllColumns = 1 << 13, // Frame will span all columns of its container table (text will still fit in current column) ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 14, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop) //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 15, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog, #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS ImGuiTreeNodeFlags_AllowItemOverlap = ImGuiTreeNodeFlags_AllowOverlap, // Renamed in 1.89.7 #endif }; // Flags for OpenPopup*(), BeginPopupContext*(), IsPopupOpen() functions. // - To be backward compatible with older API which took an 'int mouse_button = 1' argument instead of 'ImGuiPopupFlags flags', // we need to treat small flags values as a mouse button index, so we encode the mouse button in the first few bits of the flags. // It is therefore guaranteed to be legal to pass a mouse button index in ImGuiPopupFlags. // - For the same reason, we exceptionally default the ImGuiPopupFlags argument of BeginPopupContextXXX functions to 1 instead of 0. // IMPORTANT: because the default parameter is 1 (==ImGuiPopupFlags_MouseButtonRight), if you rely on the default parameter // and want to use another flag, you need to pass in the ImGuiPopupFlags_MouseButtonRight flag explicitly. // - Multiple buttons currently cannot be combined/or-ed in those functions (we could allow it later). enum ImGuiPopupFlags_ { ImGuiPopupFlags_None = 0, ImGuiPopupFlags_MouseButtonLeft = 0, // For BeginPopupContext*(): open on Left Mouse release. Guaranteed to always be == 0 (same as ImGuiMouseButton_Left) ImGuiPopupFlags_MouseButtonRight = 1, // For BeginPopupContext*(): open on Right Mouse release. Guaranteed to always be == 1 (same as ImGuiMouseButton_Right) ImGuiPopupFlags_MouseButtonMiddle = 2, // For BeginPopupContext*(): open on Middle Mouse release. Guaranteed to always be == 2 (same as ImGuiMouseButton_Middle) ImGuiPopupFlags_MouseButtonMask_ = 0x1F, ImGuiPopupFlags_MouseButtonDefault_ = 1, ImGuiPopupFlags_NoReopen = 1 << 5, // For OpenPopup*(), BeginPopupContext*(): don't reopen same popup if already open (won't reposition, won't reinitialize navigation) //ImGuiPopupFlags_NoReopenAlwaysNavInit = 1 << 6, // For OpenPopup*(), BeginPopupContext*(): focus and initialize navigation even when not reopening. ImGuiPopupFlags_NoOpenOverExistingPopup = 1 << 7, // For OpenPopup*(), BeginPopupContext*(): don't open if there's already a popup at the same level of the popup stack ImGuiPopupFlags_NoOpenOverItems = 1 << 8, // For BeginPopupContextWindow(): don't return true when hovering items, only when hovering empty space ImGuiPopupFlags_AnyPopupId = 1 << 10, // For IsPopupOpen(): ignore the ImGuiID parameter and test for any popup. ImGuiPopupFlags_AnyPopupLevel = 1 << 11, // For IsPopupOpen(): search/test at any level of the popup stack (default test in the current level) ImGuiPopupFlags_AnyPopup = ImGuiPopupFlags_AnyPopupId | ImGuiPopupFlags_AnyPopupLevel, }; // Flags for ImGui::Selectable() enum ImGuiSelectableFlags_ { ImGuiSelectableFlags_None = 0, ImGuiSelectableFlags_DontClosePopups = 1 << 0, // Clicking this doesn't close parent popup window ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Frame will span all columns of its container table (text will still fit in current column) ImGuiSelectableFlags_AllowDoubleClick = 1 << 2, // Generate press events on double clicks too ImGuiSelectableFlags_Disabled = 1 << 3, // Cannot be selected, display grayed out text ImGuiSelectableFlags_AllowOverlap = 1 << 4, // (WIP) Hit testing to allow subsequent widgets to overlap this one #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS ImGuiSelectableFlags_AllowItemOverlap = ImGuiSelectableFlags_AllowOverlap, // Renamed in 1.89.7 #endif }; // Flags for ImGui::BeginCombo() enum ImGuiComboFlags_ { ImGuiComboFlags_None = 0, ImGuiComboFlags_PopupAlignLeft = 1 << 0, // Align the popup toward the left by default ImGuiComboFlags_HeightSmall = 1 << 1, // Max ~4 items visible. Tip: If you want your combo popup to be a specific size you can use SetNextWindowSizeConstraints() prior to calling BeginCombo() ImGuiComboFlags_HeightRegular = 1 << 2, // Max ~8 items visible (default) ImGuiComboFlags_HeightLarge = 1 << 3, // Max ~20 items visible ImGuiComboFlags_HeightLargest = 1 << 4, // As many fitting items as possible ImGuiComboFlags_NoArrowButton = 1 << 5, // Display on the preview box without the square arrow button ImGuiComboFlags_NoPreview = 1 << 6, // Display only a square arrow button ImGuiComboFlags_WidthFitPreview = 1 << 7, // Width dynamically calculated from preview contents ImGuiComboFlags_HeightMask_ = ImGuiComboFlags_HeightSmall | ImGuiComboFlags_HeightRegular | ImGuiComboFlags_HeightLarge | ImGuiComboFlags_HeightLargest, }; // Flags for ImGui::BeginTabBar() enum ImGuiTabBarFlags_ { ImGuiTabBarFlags_None = 0, ImGuiTabBarFlags_Reorderable = 1 << 0, // Allow manually dragging tabs to re-order them + New tabs are appended at the end of list ImGuiTabBarFlags_AutoSelectNewTabs = 1 << 1, // Automatically select new tabs when they appear ImGuiTabBarFlags_TabListPopupButton = 1 << 2, // Disable buttons to open the tab list popup ImGuiTabBarFlags_NoCloseWithMiddleMouseButton = 1 << 3, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You may handle this behavior manually on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false. ImGuiTabBarFlags_NoTabListScrollingButtons = 1 << 4, // Disable scrolling buttons (apply when fitting policy is ImGuiTabBarFlags_FittingPolicyScroll) ImGuiTabBarFlags_NoTooltip = 1 << 5, // Disable tooltips when hovering a tab ImGuiTabBarFlags_FittingPolicyResizeDown = 1 << 6, // Resize tabs when they don't fit ImGuiTabBarFlags_FittingPolicyScroll = 1 << 7, // Add scroll buttons when tabs don't fit ImGuiTabBarFlags_FittingPolicyMask_ = ImGuiTabBarFlags_FittingPolicyResizeDown | ImGuiTabBarFlags_FittingPolicyScroll, ImGuiTabBarFlags_FittingPolicyDefault_ = ImGuiTabBarFlags_FittingPolicyResizeDown, }; // Flags for ImGui::BeginTabItem() enum ImGuiTabItemFlags_ { ImGuiTabItemFlags_None = 0, ImGuiTabItemFlags_UnsavedDocument = 1 << 0, // Display a dot next to the title + set ImGuiTabItemFlags_NoAssumedClosure. ImGuiTabItemFlags_SetSelected = 1 << 1, // Trigger flag to programmatically make the tab selected when calling BeginTabItem() ImGuiTabItemFlags_NoCloseWithMiddleMouseButton = 1 << 2, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You may handle this behavior manually on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false. ImGuiTabItemFlags_NoPushId = 1 << 3, // Don't call PushID()/PopID() on BeginTabItem()/EndTabItem() ImGuiTabItemFlags_NoTooltip = 1 << 4, // Disable tooltip for the given tab ImGuiTabItemFlags_NoReorder = 1 << 5, // Disable reordering this tab or having another tab cross over this tab ImGuiTabItemFlags_Leading = 1 << 6, // Enforce the tab position to the left of the tab bar (after the tab list popup button) ImGuiTabItemFlags_Trailing = 1 << 7, // Enforce the tab position to the right of the tab bar (before the scrolling buttons) ImGuiTabItemFlags_NoAssumedClosure = 1 << 8, // Tab is selected when trying to close + closure is not immediately assumed (will wait for user to stop submitting the tab). Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar. }; // Flags for ImGui::IsWindowFocused() enum ImGuiFocusedFlags_ { ImGuiFocusedFlags_None = 0, ImGuiFocusedFlags_ChildWindows = 1 << 0, // Return true if any children of the window is focused ImGuiFocusedFlags_RootWindow = 1 << 1, // Test from root window (top most parent of the current hierarchy) ImGuiFocusedFlags_AnyWindow = 1 << 2, // Return true if any window is focused. Important: If you are trying to tell how to dispatch your low-level inputs, do NOT use this. Use 'io.WantCaptureMouse' instead! Please read the FAQ! ImGuiFocusedFlags_NoPopupHierarchy = 1 << 3, // Do not consider popup hierarchy (do not treat popup emitter as parent of popup) (when used with _ChildWindows or _RootWindow) //ImGuiFocusedFlags_DockHierarchy = 1 << 4, // Consider docking hierarchy (treat dockspace host as parent of docked window) (when used with _ChildWindows or _RootWindow) ImGuiFocusedFlags_RootAndChildWindows = ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows, }; // Flags for ImGui::IsItemHovered(), ImGui::IsWindowHovered() // Note: if you are trying to check whether your mouse should be dispatched to Dear ImGui or to your app, you should use 'io.WantCaptureMouse' instead! Please read the FAQ! // Note: windows with the ImGuiWindowFlags_NoInputs flag are ignored by IsWindowHovered() calls. enum ImGuiHoveredFlags_ { ImGuiHoveredFlags_None = 0, // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them. ImGuiHoveredFlags_ChildWindows = 1 << 0, // IsWindowHovered() only: Return true if any children of the window is hovered ImGuiHoveredFlags_RootWindow = 1 << 1, // IsWindowHovered() only: Test from root window (top most parent of the current hierarchy) ImGuiHoveredFlags_AnyWindow = 1 << 2, // IsWindowHovered() only: Return true if any window is hovered ImGuiHoveredFlags_NoPopupHierarchy = 1 << 3, // IsWindowHovered() only: Do not consider popup hierarchy (do not treat popup emitter as parent of popup) (when used with _ChildWindows or _RootWindow) //ImGuiHoveredFlags_DockHierarchy = 1 << 4, // IsWindowHovered() only: Consider docking hierarchy (treat dockspace host as parent of docked window) (when used with _ChildWindows or _RootWindow) ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 5, // Return true even if a popup window is normally blocking access to this item/window //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 6, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 7, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns. ImGuiHoveredFlags_AllowWhenOverlappedByItem = 1 << 8, // IsItemHovered() only: Return true even if the item uses AllowOverlap mode and is overlapped by another hoverable item. ImGuiHoveredFlags_AllowWhenOverlappedByWindow = 1 << 9, // IsItemHovered() only: Return true even if the position is obstructed or overlapped by another window. ImGuiHoveredFlags_AllowWhenDisabled = 1 << 10, // IsItemHovered() only: Return true even if the item is disabled ImGuiHoveredFlags_NoNavOverride = 1 << 11, // IsItemHovered() only: Disable using gamepad/keyboard navigation state when active, always query mouse ImGuiHoveredFlags_AllowWhenOverlapped = ImGuiHoveredFlags_AllowWhenOverlappedByItem | ImGuiHoveredFlags_AllowWhenOverlappedByWindow, ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped, ImGuiHoveredFlags_RootAndChildWindows = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows, // Tooltips mode // - typically used in IsItemHovered() + SetTooltip() sequence. // - this is a shortcut to pull flags from 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' where you can reconfigure desired behavior. // e.g. 'TooltipHoveredFlagsForMouse' defaults to 'ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort'. // - for frequently actioned or hovered items providing a tooltip, you want may to use ImGuiHoveredFlags_ForTooltip (stationary + delay) so the tooltip doesn't show too often. // - for items which main purpose is to be hovered, or items with low affordance, or in less consistent apps, prefer no delay or shorter delay. ImGuiHoveredFlags_ForTooltip = 1 << 12, // Shortcut for standard flags when using IsItemHovered() + SetTooltip() sequence. // (Advanced) Mouse Hovering delays. // - generally you can use ImGuiHoveredFlags_ForTooltip to use application-standardized flags. // - use those if you need specific overrides. ImGuiHoveredFlags_Stationary = 1 << 13, // Require mouse to be stationary for style.HoverStationaryDelay (~0.15 sec) _at least one time_. After this, can move on same item/window. Using the stationary test tends to reduces the need for a long delay. ImGuiHoveredFlags_DelayNone = 1 << 14, // IsItemHovered() only: Return true immediately (default). As this is the default you generally ignore this. ImGuiHoveredFlags_DelayShort = 1 << 15, // IsItemHovered() only: Return true after style.HoverDelayShort elapsed (~0.15 sec) (shared between items) + requires mouse to be stationary for style.HoverStationaryDelay (once per item). ImGuiHoveredFlags_DelayNormal = 1 << 16, // IsItemHovered() only: Return true after style.HoverDelayNormal elapsed (~0.40 sec) (shared between items) + requires mouse to be stationary for style.HoverStationaryDelay (once per item). ImGuiHoveredFlags_NoSharedDelay = 1 << 17, // IsItemHovered() only: Disable shared delay system where moving from one item to the next keeps the previous timer for a short time (standard for tooltips with long delays) }; // Flags for ImGui::BeginDragDropSource(), ImGui::AcceptDragDropPayload() enum ImGuiDragDropFlags_ { ImGuiDragDropFlags_None = 0, // BeginDragDropSource() flags ImGuiDragDropFlags_SourceNoPreviewTooltip = 1 << 0, // Disable preview tooltip. By default, a successful call to BeginDragDropSource opens a tooltip so you can display a preview or description of the source contents. This flag disables this behavior. ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return false, to avoid subsequent user code submitting tooltips. This flag disables this behavior so you can still call IsItemHovered() on the source item. ImGuiDragDropFlags_SourceNoHoldToOpenOthers = 1 << 2, // Disable the behavior that allows to open tree nodes and collapsing header by holding over them while dragging a source item. ImGuiDragDropFlags_SourceAllowNullID = 1 << 3, // Allow items such as Text(), Image() that have no unique identifier to be used as drag source, by manufacturing a temporary identifier based on their window-relative position. This is extremely unusual within the dear imgui ecosystem and so we made it explicit. ImGuiDragDropFlags_SourceExtern = 1 << 4, // External source (from outside of dear imgui), won't attempt to read current item/window info. Will always return true. Only one Extern source can be active simultaneously. ImGuiDragDropFlags_SourceAutoExpirePayload = 1 << 5, // Automatically expire the payload if the source cease to be submitted (otherwise payloads are persisting while being dragged) // AcceptDragDropPayload() flags ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, // AcceptDragDropPayload() will returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered. ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, // Do not draw the default highlight rectangle when hovering over target. ImGuiDragDropFlags_AcceptNoPreviewTooltip = 1 << 12, // Request hiding the BeginDragDropSource tooltip from the BeginDragDropTarget site. ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect, // For peeking ahead and inspecting the payload before delivery. }; // Standard Drag and Drop payload types. You can define you own payload types using short strings. Types starting with '_' are defined by Dear ImGui. #define IMGUI_PAYLOAD_TYPE_COLOR_3F "_COL3F" // float[3]: Standard type for colors, without alpha. User code may use this type. #define IMGUI_PAYLOAD_TYPE_COLOR_4F "_COL4F" // float[4]: Standard type for colors. User code may use this type. // A primary data type enum ImGuiDataType_ { ImGuiDataType_S8, // signed char / char (with sensible compilers) ImGuiDataType_U8, // unsigned char ImGuiDataType_S16, // short ImGuiDataType_U16, // unsigned short ImGuiDataType_S32, // int ImGuiDataType_U32, // unsigned int ImGuiDataType_S64, // long long / __int64 ImGuiDataType_U64, // unsigned long long / unsigned __int64 ImGuiDataType_Float, // float ImGuiDataType_Double, // double ImGuiDataType_COUNT }; // A cardinal direction enum ImGuiDir_ { ImGuiDir_None = -1, ImGuiDir_Left = 0, ImGuiDir_Right = 1, ImGuiDir_Up = 2, ImGuiDir_Down = 3, ImGuiDir_COUNT }; // A sorting direction enum ImGuiSortDirection_ { ImGuiSortDirection_None = 0, ImGuiSortDirection_Ascending = 1, // Ascending = 0->9, A->Z etc. ImGuiSortDirection_Descending = 2 // Descending = 9->0, Z->A etc. }; // Since 1.90, defining IMGUI_DISABLE_OBSOLETE_FUNCTIONS automatically defines IMGUI_DISABLE_OBSOLETE_KEYIO as well. #if defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS) && !defined(IMGUI_DISABLE_OBSOLETE_KEYIO) #define IMGUI_DISABLE_OBSOLETE_KEYIO #endif // A key identifier (ImGuiKey_XXX or ImGuiMod_XXX value): can represent Keyboard, Mouse and Gamepad values. // All our named keys are >= 512. Keys value 0 to 511 are left unused as legacy native/opaque key values (< 1.87). // Since >= 1.89 we increased typing (went from int to enum), some legacy code may need a cast to ImGuiKey. // Read details about the 1.87 and 1.89 transition : https://github.com/ocornut/imgui/issues/4921 // Note that "Keys" related to physical keys and are not the same concept as input "Characters", the later are submitted via io.AddInputCharacter(). // The keyboard key enum values are named after the keys on a standard US keyboard, and on other keyboard types the keys reported may not match the keycaps. enum ImGuiKey : int { // Keyboard ImGuiKey_None = 0, ImGuiKey_Tab = 512, // == ImGuiKey_NamedKey_BEGIN ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow, ImGuiKey_PageUp, ImGuiKey_PageDown, ImGuiKey_Home, ImGuiKey_End, ImGuiKey_Insert, ImGuiKey_Delete, ImGuiKey_Backspace, ImGuiKey_Space, ImGuiKey_Enter, ImGuiKey_Escape, ImGuiKey_LeftCtrl, ImGuiKey_LeftShift, ImGuiKey_LeftAlt, ImGuiKey_LeftSuper, ImGuiKey_RightCtrl, ImGuiKey_RightShift, ImGuiKey_RightAlt, ImGuiKey_RightSuper, ImGuiKey_Menu, ImGuiKey_0, ImGuiKey_1, ImGuiKey_2, ImGuiKey_3, ImGuiKey_4, ImGuiKey_5, ImGuiKey_6, ImGuiKey_7, ImGuiKey_8, ImGuiKey_9, ImGuiKey_A, ImGuiKey_B, ImGuiKey_C, ImGuiKey_D, ImGuiKey_E, ImGuiKey_F, ImGuiKey_G, ImGuiKey_H, ImGuiKey_I, ImGuiKey_J, ImGuiKey_K, ImGuiKey_L, ImGuiKey_M, ImGuiKey_N, ImGuiKey_O, ImGuiKey_P, ImGuiKey_Q, ImGuiKey_R, ImGuiKey_S, ImGuiKey_T, ImGuiKey_U, ImGuiKey_V, ImGuiKey_W, ImGuiKey_X, ImGuiKey_Y, ImGuiKey_Z, ImGuiKey_F1, ImGuiKey_F2, ImGuiKey_F3, ImGuiKey_F4, ImGuiKey_F5, ImGuiKey_F6, ImGuiKey_F7, ImGuiKey_F8, ImGuiKey_F9, ImGuiKey_F10, ImGuiKey_F11, ImGuiKey_F12, ImGuiKey_F13, ImGuiKey_F14, ImGuiKey_F15, ImGuiKey_F16, ImGuiKey_F17, ImGuiKey_F18, ImGuiKey_F19, ImGuiKey_F20, ImGuiKey_F21, ImGuiKey_F22, ImGuiKey_F23, ImGuiKey_F24, ImGuiKey_Apostrophe, // ' ImGuiKey_Comma, // , ImGuiKey_Minus, // - ImGuiKey_Period, // . ImGuiKey_Slash, // / ImGuiKey_Semicolon, // ; ImGuiKey_Equal, // = ImGuiKey_LeftBracket, // [ ImGuiKey_Backslash, // \ (this text inhibit multiline comment caused by backslash) ImGuiKey_RightBracket, // ] ImGuiKey_GraveAccent, // ` ImGuiKey_CapsLock, ImGuiKey_ScrollLock, ImGuiKey_NumLock, ImGuiKey_PrintScreen, ImGuiKey_Pause, ImGuiKey_Keypad0, ImGuiKey_Keypad1, ImGuiKey_Keypad2, ImGuiKey_Keypad3, ImGuiKey_Keypad4, ImGuiKey_Keypad5, ImGuiKey_Keypad6, ImGuiKey_Keypad7, ImGuiKey_Keypad8, ImGuiKey_Keypad9, ImGuiKey_KeypadDecimal, ImGuiKey_KeypadDivide, ImGuiKey_KeypadMultiply, ImGuiKey_KeypadSubtract, ImGuiKey_KeypadAdd, ImGuiKey_KeypadEnter, ImGuiKey_KeypadEqual, ImGuiKey_AppBack, // Available on some keyboard/mouses. Often referred as "Browser Back" ImGuiKey_AppForward, // Gamepad (some of those are analog values, 0.0f to 1.0f) // NAVIGATION ACTION // (download controller mapping PNG/PSD at http://dearimgui.com/controls_sheets) ImGuiKey_GamepadStart, // Menu (Xbox) + (Switch) Start/Options (PS) ImGuiKey_GamepadBack, // View (Xbox) - (Switch) Share (PS) ImGuiKey_GamepadFaceLeft, // X (Xbox) Y (Switch) Square (PS) // Tap: Toggle Menu. Hold: Windowing mode (Focus/Move/Resize windows) ImGuiKey_GamepadFaceRight, // B (Xbox) A (Switch) Circle (PS) // Cancel / Close / Exit ImGuiKey_GamepadFaceUp, // Y (Xbox) X (Switch) Triangle (PS) // Text Input / On-screen Keyboard ImGuiKey_GamepadFaceDown, // A (Xbox) B (Switch) Cross (PS) // Activate / Open / Toggle / Tweak ImGuiKey_GamepadDpadLeft, // D-pad Left // Move / Tweak / Resize Window (in Windowing mode) ImGuiKey_GamepadDpadRight, // D-pad Right // Move / Tweak / Resize Window (in Windowing mode) ImGuiKey_GamepadDpadUp, // D-pad Up // Move / Tweak / Resize Window (in Windowing mode) ImGuiKey_GamepadDpadDown, // D-pad Down // Move / Tweak / Resize Window (in Windowing mode) ImGuiKey_GamepadL1, // L Bumper (Xbox) L (Switch) L1 (PS) // Tweak Slower / Focus Previous (in Windowing mode) ImGuiKey_GamepadR1, // R Bumper (Xbox) R (Switch) R1 (PS) // Tweak Faster / Focus Next (in Windowing mode) ImGuiKey_GamepadL2, // L Trig. (Xbox) ZL (Switch) L2 (PS) [Analog] ImGuiKey_GamepadR2, // R Trig. (Xbox) ZR (Switch) R2 (PS) [Analog] ImGuiKey_GamepadL3, // L Stick (Xbox) L3 (Switch) L3 (PS) ImGuiKey_GamepadR3, // R Stick (Xbox) R3 (Switch) R3 (PS) ImGuiKey_GamepadLStickLeft, // [Analog] // Move Window (in Windowing mode) ImGuiKey_GamepadLStickRight, // [Analog] // Move Window (in Windowing mode) ImGuiKey_GamepadLStickUp, // [Analog] // Move Window (in Windowing mode) ImGuiKey_GamepadLStickDown, // [Analog] // Move Window (in Windowing mode) ImGuiKey_GamepadRStickLeft, // [Analog] ImGuiKey_GamepadRStickRight, // [Analog] ImGuiKey_GamepadRStickUp, // [Analog] ImGuiKey_GamepadRStickDown, // [Analog] // Aliases: Mouse Buttons (auto-submitted from AddMouseButtonEvent() calls) // - This is mirroring the data also written to io.MouseDown[], io.MouseWheel, in a format allowing them to be accessed via standard key API. ImGuiKey_MouseLeft, ImGuiKey_MouseRight, ImGuiKey_MouseMiddle, ImGuiKey_MouseX1, ImGuiKey_MouseX2, ImGuiKey_MouseWheelX, ImGuiKey_MouseWheelY, // [Internal] Reserved for mod storage ImGuiKey_ReservedForModCtrl, ImGuiKey_ReservedForModShift, ImGuiKey_ReservedForModAlt, ImGuiKey_ReservedForModSuper, ImGuiKey_COUNT, // Keyboard Modifiers (explicitly submitted by backend via AddKeyEvent() calls) // - This is mirroring the data also written to io.KeyCtrl, io.KeyShift, io.KeyAlt, io.KeySuper, in a format allowing // them to be accessed via standard key API, allowing calls such as IsKeyPressed(), IsKeyReleased(), querying duration etc. // - Code polling every key (e.g. an interface to detect a key press for input mapping) might want to ignore those // and prefer using the real keys (e.g. ImGuiKey_LeftCtrl, ImGuiKey_RightCtrl instead of ImGuiMod_Ctrl). // - In theory the value of keyboard modifiers should be roughly equivalent to a logical or of the equivalent left/right keys. // In practice: it's complicated; mods are often provided from different sources. Keyboard layout, IME, sticky keys and // backends tend to interfere and break that equivalence. The safer decision is to relay that ambiguity down to the end-user... ImGuiMod_None = 0, ImGuiMod_Ctrl = 1 << 12, // Ctrl ImGuiMod_Shift = 1 << 13, // Shift ImGuiMod_Alt = 1 << 14, // Option/Menu ImGuiMod_Super = 1 << 15, // Cmd/Super/Windows ImGuiMod_Shortcut = 1 << 11, // Alias for Ctrl (non-macOS) _or_ Super (macOS). ImGuiMod_Mask_ = 0xF800, // 5-bits // [Internal] Prior to 1.87 we required user to fill io.KeysDown[512] using their own native index + the io.KeyMap[] array. // We are ditching this method but keeping a legacy path for user code doing e.g. IsKeyPressed(MY_NATIVE_KEY_CODE) // If you need to iterate all keys (for e.g. an input mapper) you may use ImGuiKey_NamedKey_BEGIN..ImGuiKey_NamedKey_END. ImGuiKey_NamedKey_BEGIN = 512, ImGuiKey_NamedKey_END = ImGuiKey_COUNT, ImGuiKey_NamedKey_COUNT = ImGuiKey_NamedKey_END - ImGuiKey_NamedKey_BEGIN, #ifdef IMGUI_DISABLE_OBSOLETE_KEYIO ImGuiKey_KeysData_SIZE = ImGuiKey_NamedKey_COUNT, // Size of KeysData[]: only hold named keys ImGuiKey_KeysData_OFFSET = ImGuiKey_NamedKey_BEGIN, // Accesses to io.KeysData[] must use (key - ImGuiKey_KeysData_OFFSET) index. #else ImGuiKey_KeysData_SIZE = ImGuiKey_COUNT, // Size of KeysData[]: hold legacy 0..512 keycodes + named keys ImGuiKey_KeysData_OFFSET = 0, // Accesses to io.KeysData[] must use (key - ImGuiKey_KeysData_OFFSET) index. #endif #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS ImGuiKey_ModCtrl = ImGuiMod_Ctrl, ImGuiKey_ModShift = ImGuiMod_Shift, ImGuiKey_ModAlt = ImGuiMod_Alt, ImGuiKey_ModSuper = ImGuiMod_Super, // Renamed in 1.89 //ImGuiKey_KeyPadEnter = ImGuiKey_KeypadEnter, // Renamed in 1.87 #endif }; #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO // OBSOLETED in 1.88 (from July 2022): ImGuiNavInput and io.NavInputs[]. // Official backends between 1.60 and 1.86: will keep working and feed gamepad inputs as long as IMGUI_DISABLE_OBSOLETE_KEYIO is not set. // Custom backends: feed gamepad inputs via io.AddKeyEvent() and ImGuiKey_GamepadXXX enums. enum ImGuiNavInput { ImGuiNavInput_Activate, ImGuiNavInput_Cancel, ImGuiNavInput_Input, ImGuiNavInput_Menu, ImGuiNavInput_DpadLeft, ImGuiNavInput_DpadRight, ImGuiNavInput_DpadUp, ImGuiNavInput_DpadDown, ImGuiNavInput_LStickLeft, ImGuiNavInput_LStickRight, ImGuiNavInput_LStickUp, ImGuiNavInput_LStickDown, ImGuiNavInput_FocusPrev, ImGuiNavInput_FocusNext, ImGuiNavInput_TweakSlow, ImGuiNavInput_TweakFast, ImGuiNavInput_COUNT, }; #endif // Configuration flags stored in io.ConfigFlags. Set by user/application. enum ImGuiConfigFlags_ { ImGuiConfigFlags_None = 0, ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. Enable full Tabbing + directional arrows + space/enter to activate. ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. Backend also needs to set ImGuiBackendFlags_HasGamepad. ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Instruct navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your backend, otherwise ImGui will react as if the mouse is jumping around back and forth. ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Instruct navigation to not set the io.WantCaptureKeyboard flag when io.NavActive is set. ImGuiConfigFlags_NoMouse = 1 << 4, // Instruct imgui to clear mouse position/buttons in NewFrame(). This allows ignoring the mouse information set by the backend. ImGuiConfigFlags_NoMouseCursorChange = 1 << 5, // Instruct backend to not alter mouse cursor shape and visibility. Use if the backend cursor changes are interfering with yours and you don't want to use SetMouseCursor() to change mouse cursor. You may want to honor requests from imgui by reading GetMouseCursor() yourself instead. // User storage (to allow your backend/engine to communicate to code that may be shared between multiple projects. Those flags are NOT used by core Dear ImGui) ImGuiConfigFlags_IsSRGB = 1 << 20, // Application is SRGB-aware. ImGuiConfigFlags_IsTouchScreen = 1 << 21, // Application is using a touch screen instead of a mouse. }; // Backend capabilities flags stored in io.BackendFlags. Set by imgui_impl_xxx or custom backend. enum ImGuiBackendFlags_ { ImGuiBackendFlags_None = 0, ImGuiBackendFlags_HasGamepad = 1 << 0, // Backend Platform supports gamepad and currently has one connected. ImGuiBackendFlags_HasMouseCursors = 1 << 1, // Backend Platform supports honoring GetMouseCursor() value to change the OS cursor shape. ImGuiBackendFlags_HasSetMousePos = 1 << 2, // Backend Platform supports io.WantSetMousePos requests to reposition the OS mouse position (only used if ImGuiConfigFlags_NavEnableSetMousePos is set). ImGuiBackendFlags_RendererHasVtxOffset = 1 << 3, // Backend Renderer supports ImDrawCmd::VtxOffset. This enables output of large meshes (64K+ vertices) while still using 16-bit indices. }; // Enumeration for PushStyleColor() / PopStyleColor() enum ImGuiCol_ { ImGuiCol_Text, ImGuiCol_TextDisabled, ImGuiCol_WindowBg, // Background of normal windows ImGuiCol_ChildBg, // Background of child windows ImGuiCol_PopupBg, // Background of popups, menus, tooltips windows ImGuiCol_Border, ImGuiCol_BorderShadow, ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive, ImGuiCol_TitleBg, // Title bar ImGuiCol_TitleBgActive, // Title bar when focused ImGuiCol_TitleBgCollapsed, // Title bar when collapsed ImGuiCol_MenuBarBg, ImGuiCol_ScrollbarBg, ImGuiCol_ScrollbarGrab, ImGuiCol_ScrollbarGrabHovered, ImGuiCol_ScrollbarGrabActive, ImGuiCol_CheckMark, // Checkbox tick and RadioButton circle ImGuiCol_SliderGrab, ImGuiCol_SliderGrabActive, ImGuiCol_Button, ImGuiCol_ButtonHovered, ImGuiCol_ButtonActive, ImGuiCol_Header, // Header* colors are used for CollapsingHeader, TreeNode, Selectable, MenuItem ImGuiCol_HeaderHovered, ImGuiCol_HeaderActive, ImGuiCol_Separator, ImGuiCol_SeparatorHovered, ImGuiCol_SeparatorActive, ImGuiCol_ResizeGrip, // Resize grip in lower-right and lower-left corners of windows. ImGuiCol_ResizeGripHovered, ImGuiCol_ResizeGripActive, ImGuiCol_Tab, // TabItem in a TabBar ImGuiCol_TabHovered, ImGuiCol_TabActive, ImGuiCol_TabUnfocused, ImGuiCol_TabUnfocusedActive, ImGuiCol_PlotLines, ImGuiCol_PlotLinesHovered, ImGuiCol_PlotHistogram, ImGuiCol_PlotHistogramHovered, ImGuiCol_TableHeaderBg, // Table header background ImGuiCol_TableBorderStrong, // Table outer and header borders (prefer using Alpha=1.0 here) ImGuiCol_TableBorderLight, // Table inner borders (prefer using Alpha=1.0 here) ImGuiCol_TableRowBg, // Table row background (even rows) ImGuiCol_TableRowBgAlt, // Table row background (odd rows) ImGuiCol_TextSelectedBg, ImGuiCol_DragDropTarget, // Rectangle highlighting a drop target ImGuiCol_NavHighlight, // Gamepad/keyboard: current highlighted item ImGuiCol_NavWindowingHighlight, // Highlight window when using CTRL+TAB ImGuiCol_NavWindowingDimBg, // Darken/colorize entire screen behind the CTRL+TAB window list, when active ImGuiCol_ModalWindowDimBg, // Darken/colorize entire screen behind a modal window, when one is active ImGuiCol_COUNT }; // Enumeration for PushStyleVar() / PopStyleVar() to temporarily modify the ImGuiStyle structure. // - The enum only refers to fields of ImGuiStyle which makes sense to be pushed/popped inside UI code. // During initialization or between frames, feel free to just poke into ImGuiStyle directly. // - Tip: Use your programming IDE navigation facilities on the names in the _second column_ below to find the actual members and their description. // In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. // - When changing this enum, you need to update the associated internal table GStyleVarInfo[] accordingly. This is where we link enum values to members offset/type. enum ImGuiStyleVar_ { // Enum name --------------------- // Member in ImGuiStyle structure (see ImGuiStyle for descriptions) ImGuiStyleVar_Alpha, // float Alpha ImGuiStyleVar_DisabledAlpha, // float DisabledAlpha ImGuiStyleVar_WindowPadding, // ImVec2 WindowPadding ImGuiStyleVar_WindowRounding, // float WindowRounding ImGuiStyleVar_WindowBorderSize, // float WindowBorderSize ImGuiStyleVar_WindowMinSize, // ImVec2 WindowMinSize ImGuiStyleVar_WindowTitleAlign, // ImVec2 WindowTitleAlign ImGuiStyleVar_ChildRounding, // float ChildRounding ImGuiStyleVar_ChildBorderSize, // float ChildBorderSize ImGuiStyleVar_PopupRounding, // float PopupRounding ImGuiStyleVar_PopupBorderSize, // float PopupBorderSize ImGuiStyleVar_FramePadding, // ImVec2 FramePadding ImGuiStyleVar_FrameRounding, // float FrameRounding ImGuiStyleVar_FrameBorderSize, // float FrameBorderSize ImGuiStyleVar_ItemSpacing, // ImVec2 ItemSpacing ImGuiStyleVar_ItemInnerSpacing, // ImVec2 ItemInnerSpacing ImGuiStyleVar_IndentSpacing, // float IndentSpacing ImGuiStyleVar_CellPadding, // ImVec2 CellPadding ImGuiStyleVar_ScrollbarSize, // float ScrollbarSize ImGuiStyleVar_ScrollbarRounding, // float ScrollbarRounding ImGuiStyleVar_GrabMinSize, // float GrabMinSize ImGuiStyleVar_GrabRounding, // float GrabRounding ImGuiStyleVar_TabRounding, // float TabRounding ImGuiStyleVar_TabBarBorderSize, // float TabBarBorderSize ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign ImGuiStyleVar_SeparatorTextBorderSize,// float SeparatorTextBorderSize ImGuiStyleVar_SeparatorTextAlign, // ImVec2 SeparatorTextAlign ImGuiStyleVar_SeparatorTextPadding,// ImVec2 SeparatorTextPadding ImGuiStyleVar_COUNT }; // Flags for InvisibleButton() [extended in imgui_internal.h] enum ImGuiButtonFlags_ { ImGuiButtonFlags_None = 0, ImGuiButtonFlags_MouseButtonLeft = 1 << 0, // React on left mouse button (default) ImGuiButtonFlags_MouseButtonRight = 1 << 1, // React on right mouse button ImGuiButtonFlags_MouseButtonMiddle = 1 << 2, // React on center mouse button // [Internal] ImGuiButtonFlags_MouseButtonMask_ = ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle, ImGuiButtonFlags_MouseButtonDefault_ = ImGuiButtonFlags_MouseButtonLeft, }; // Flags for ColorEdit3() / ColorEdit4() / ColorPicker3() / ColorPicker4() / ColorButton() enum ImGuiColorEditFlags_ { ImGuiColorEditFlags_None = 0, ImGuiColorEditFlags_NoAlpha = 1 << 1, // // ColorEdit, ColorPicker, ColorButton: ignore Alpha component (will only read 3 components from the input pointer). ImGuiColorEditFlags_NoPicker = 1 << 2, // // ColorEdit: disable picker when clicking on color square. ImGuiColorEditFlags_NoOptions = 1 << 3, // // ColorEdit: disable toggling options menu when right-clicking on inputs/small preview. ImGuiColorEditFlags_NoSmallPreview = 1 << 4, // // ColorEdit, ColorPicker: disable color square preview next to the inputs. (e.g. to show only the inputs) ImGuiColorEditFlags_NoInputs = 1 << 5, // // ColorEdit, ColorPicker: disable inputs sliders/text widgets (e.g. to show only the small preview color square). ImGuiColorEditFlags_NoTooltip = 1 << 6, // // ColorEdit, ColorPicker, ColorButton: disable tooltip when hovering the preview. ImGuiColorEditFlags_NoLabel = 1 << 7, // // ColorEdit, ColorPicker: disable display of inline text label (the label is still forwarded to the tooltip and picker). ImGuiColorEditFlags_NoSidePreview = 1 << 8, // // ColorPicker: disable bigger color preview on right side of the picker, use small color square preview instead. ImGuiColorEditFlags_NoDragDrop = 1 << 9, // // ColorEdit: disable drag and drop target. ColorButton: disable drag and drop source. ImGuiColorEditFlags_NoBorder = 1 << 10, // // ColorButton: disable border (which is enforced by default) // User Options (right-click on widget to change some of them). ImGuiColorEditFlags_AlphaBar = 1 << 16, // // ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker. ImGuiColorEditFlags_AlphaPreview = 1 << 17, // // ColorEdit, ColorPicker, ColorButton: display preview as a transparent color over a checkerboard, instead of opaque. ImGuiColorEditFlags_AlphaPreviewHalf= 1 << 18, // // ColorEdit, ColorPicker, ColorButton: display half opaque / half checkerboard, instead of opaque. ImGuiColorEditFlags_HDR = 1 << 19, // // (WIP) ColorEdit: Currently only disable 0.0f..1.0f limits in RGBA edition (note: you probably want to use ImGuiColorEditFlags_Float flag as well). ImGuiColorEditFlags_DisplayRGB = 1 << 20, // [Display] // ColorEdit: override _display_ type among RGB/HSV/Hex. ColorPicker: select any combination using one or more of RGB/HSV/Hex. ImGuiColorEditFlags_DisplayHSV = 1 << 21, // [Display] // " ImGuiColorEditFlags_DisplayHex = 1 << 22, // [Display] // " ImGuiColorEditFlags_Uint8 = 1 << 23, // [DataType] // ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0..255. ImGuiColorEditFlags_Float = 1 << 24, // [DataType] // ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0.0f..1.0f floats instead of 0..255 integers. No round-trip of value via integers. ImGuiColorEditFlags_PickerHueBar = 1 << 25, // [Picker] // ColorPicker: bar for Hue, rectangle for Sat/Value. ImGuiColorEditFlags_PickerHueWheel = 1 << 26, // [Picker] // ColorPicker: wheel for Hue, triangle for Sat/Value. ImGuiColorEditFlags_InputRGB = 1 << 27, // [Input] // ColorEdit, ColorPicker: input and output data in RGB format. ImGuiColorEditFlags_InputHSV = 1 << 28, // [Input] // ColorEdit, ColorPicker: input and output data in HSV format. // Defaults Options. You can set application defaults using SetColorEditOptions(). The intent is that you probably don't want to // override them in most of your calls. Let the user choose via the option menu and/or call SetColorEditOptions() once during startup. ImGuiColorEditFlags_DefaultOptions_ = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueBar, // [Internal] Masks ImGuiColorEditFlags_DisplayMask_ = ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_DisplayHex, ImGuiColorEditFlags_DataTypeMask_ = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_Float, ImGuiColorEditFlags_PickerMask_ = ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_PickerHueBar, ImGuiColorEditFlags_InputMask_ = ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_InputHSV, // Obsolete names //ImGuiColorEditFlags_RGB = ImGuiColorEditFlags_DisplayRGB, ImGuiColorEditFlags_HSV = ImGuiColorEditFlags_DisplayHSV, ImGuiColorEditFlags_HEX = ImGuiColorEditFlags_DisplayHex // [renamed in 1.69] }; // Flags for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc. // We use the same sets of flags for DragXXX() and SliderXXX() functions as the features are the same and it makes it easier to swap them. // (Those are per-item flags. There are shared flags in ImGuiIO: io.ConfigDragClickToInputText) enum ImGuiSliderFlags_ { ImGuiSliderFlags_None = 0, ImGuiSliderFlags_AlwaysClamp = 1 << 4, // Clamp value to min/max bounds when input manually with CTRL+Click. By default CTRL+Click allows going out of bounds. ImGuiSliderFlags_Logarithmic = 1 << 5, // Make the widget logarithmic (linear otherwise). Consider using ImGuiSliderFlags_NoRoundToFormat with this if using a format-string with small amount of digits. ImGuiSliderFlags_NoRoundToFormat = 1 << 6, // Disable rounding underlying value to match precision of the display format string (e.g. %.3f values are rounded to those 3 digits) ImGuiSliderFlags_NoInput = 1 << 7, // Disable CTRL+Click or Enter key allowing to input text directly into the widget ImGuiSliderFlags_InvalidMask_ = 0x7000000F, // [Internal] We treat using those bits as being potentially a 'float power' argument from the previous API that has got miscast to this enum, and will trigger an assert if needed. // Obsolete names //ImGuiSliderFlags_ClampOnInput = ImGuiSliderFlags_AlwaysClamp, // [renamed in 1.79] }; // Identify a mouse button. // Those values are guaranteed to be stable and we frequently use 0/1 directly. Named enums provided for convenience. enum ImGuiMouseButton_ { ImGuiMouseButton_Left = 0, ImGuiMouseButton_Right = 1, ImGuiMouseButton_Middle = 2, ImGuiMouseButton_COUNT = 5 }; // Enumeration for GetMouseCursor() // User code may request backend to display given cursor by calling SetMouseCursor(), which is why we have some cursors that are marked unused here enum ImGuiMouseCursor_ { ImGuiMouseCursor_None = -1, ImGuiMouseCursor_Arrow = 0, ImGuiMouseCursor_TextInput, // When hovering over InputText, etc. ImGuiMouseCursor_ResizeAll, // (Unused by Dear ImGui functions) ImGuiMouseCursor_ResizeNS, // When hovering over a horizontal border ImGuiMouseCursor_ResizeEW, // When hovering over a vertical border or a column ImGuiMouseCursor_ResizeNESW, // When hovering over the bottom-left corner of a window ImGuiMouseCursor_ResizeNWSE, // When hovering over the bottom-right corner of a window ImGuiMouseCursor_Hand, // (Unused by Dear ImGui functions. Use for e.g. hyperlinks) ImGuiMouseCursor_NotAllowed, // When hovering something with disallowed interaction. Usually a crossed circle. ImGuiMouseCursor_COUNT }; // Enumeration for AddMouseSourceEvent() actual source of Mouse Input data. // Historically we use "Mouse" terminology everywhere to indicate pointer data, e.g. MousePos, IsMousePressed(), io.AddMousePosEvent() // But that "Mouse" data can come from different source which occasionally may be useful for application to know about. // You can submit a change of pointer type using io.AddMouseSourceEvent(). enum ImGuiMouseSource : int { ImGuiMouseSource_Mouse = 0, // Input is coming from an actual mouse. ImGuiMouseSource_TouchScreen, // Input is coming from a touch screen (no hovering prior to initial press, less precise initial press aiming, dual-axis wheeling possible). ImGuiMouseSource_Pen, // Input is coming from a pressure/magnetic pen (often used in conjunction with high-sampling rates). ImGuiMouseSource_COUNT }; // Enumeration for ImGui::SetNextWindow***(), SetWindow***(), SetNextItem***() functions // Represent a condition. // Important: Treat as a regular enum! Do NOT combine multiple values using binary operators! All the functions above treat 0 as a shortcut to ImGuiCond_Always. enum ImGuiCond_ { ImGuiCond_None = 0, // No condition (always set the variable), same as _Always ImGuiCond_Always = 1 << 0, // No condition (always set the variable), same as _None ImGuiCond_Once = 1 << 1, // Set the variable once per runtime session (only the first call will succeed) ImGuiCond_FirstUseEver = 1 << 2, // Set the variable if the object/window has no persistently saved data (no entry in .ini file) ImGuiCond_Appearing = 1 << 3, // Set the variable if the object/window is appearing after being hidden/inactive (or the first time) }; //----------------------------------------------------------------------------- // [SECTION] Tables API flags and structures (ImGuiTableFlags, ImGuiTableColumnFlags, ImGuiTableRowFlags, ImGuiTableBgTarget, ImGuiTableSortSpecs, ImGuiTableColumnSortSpecs) //----------------------------------------------------------------------------- // Flags for ImGui::BeginTable() // - Important! Sizing policies have complex and subtle side effects, much more so than you would expect. // Read comments/demos carefully + experiment with live demos to get acquainted with them. // - The DEFAULT sizing policies are: // - Default to ImGuiTableFlags_SizingFixedFit if ScrollX is on, or if host window has ImGuiWindowFlags_AlwaysAutoResize. // - Default to ImGuiTableFlags_SizingStretchSame if ScrollX is off. // - When ScrollX is off: // - Table defaults to ImGuiTableFlags_SizingStretchSame -> all Columns defaults to ImGuiTableColumnFlags_WidthStretch with same weight. // - Columns sizing policy allowed: Stretch (default), Fixed/Auto. // - Fixed Columns (if any) will generally obtain their requested width (unless the table cannot fit them all). // - Stretch Columns will share the remaining width according to their respective weight. // - Mixed Fixed/Stretch columns is possible but has various side-effects on resizing behaviors. // The typical use of mixing sizing policies is: any number of LEADING Fixed columns, followed by one or two TRAILING Stretch columns. // (this is because the visible order of columns have subtle but necessary effects on how they react to manual resizing). // - When ScrollX is on: // - Table defaults to ImGuiTableFlags_SizingFixedFit -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed // - Columns sizing policy allowed: Fixed/Auto mostly. // - Fixed Columns can be enlarged as needed. Table will show a horizontal scrollbar if needed. // - When using auto-resizing (non-resizable) fixed columns, querying the content width to use item right-alignment e.g. SetNextItemWidth(-FLT_MIN) doesn't make sense, would create a feedback loop. // - Using Stretch columns OFTEN DOES NOT MAKE SENSE if ScrollX is on, UNLESS you have specified a value for 'inner_width' in BeginTable(). // If you specify a value for 'inner_width' then effectively the scrolling space is known and Stretch or mixed Fixed/Stretch columns become meaningful again. // - Read on documentation at the top of imgui_tables.cpp for details. enum ImGuiTableFlags_ { // Features ImGuiTableFlags_None = 0, ImGuiTableFlags_Resizable = 1 << 0, // Enable resizing columns. ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers) ImGuiTableFlags_Hideable = 1 << 2, // Enable hiding/disabling columns in context menu. ImGuiTableFlags_Sortable = 1 << 3, // Enable sorting. Call TableGetSortSpecs() to obtain sort specs. Also see ImGuiTableFlags_SortMulti and ImGuiTableFlags_SortTristate. ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width and sort settings in the .ini file. ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will display table context menu. By default it is available in TableHeadersRow(). // Decorations ImGuiTableFlags_RowBg = 1 << 6, // Set each RowBg color with ImGuiCol_TableRowBg or ImGuiCol_TableRowBgAlt (equivalent of calling TableSetBgColor with ImGuiTableBgFlags_RowBg0 on each row manually) ImGuiTableFlags_BordersInnerH = 1 << 7, // Draw horizontal borders between rows. ImGuiTableFlags_BordersOuterH = 1 << 8, // Draw horizontal borders at the top and bottom. ImGuiTableFlags_BordersInnerV = 1 << 9, // Draw vertical borders between columns. ImGuiTableFlags_BordersOuterV = 1 << 10, // Draw vertical borders on the left and right sides. ImGuiTableFlags_BordersH = ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_BordersOuterH, // Draw horizontal borders. ImGuiTableFlags_BordersV = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersOuterV, // Draw vertical borders. ImGuiTableFlags_BordersInner = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersInnerH, // Draw inner borders. ImGuiTableFlags_BordersOuter = ImGuiTableFlags_BordersOuterV | ImGuiTableFlags_BordersOuterH, // Draw outer borders. ImGuiTableFlags_Borders = ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter, // Draw all borders. ImGuiTableFlags_NoBordersInBody = 1 << 11, // [ALPHA] Disable vertical borders in columns Body (borders will always appear in Headers). -> May move to style ImGuiTableFlags_NoBordersInBodyUntilResize = 1 << 12, // [ALPHA] Disable vertical borders in columns Body until hovered for resize (borders will always appear in Headers). -> May move to style // Sizing Policy (read above for defaults) ImGuiTableFlags_SizingFixedFit = 1 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching contents width. ImGuiTableFlags_SizingFixedSame = 2 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching the maximum contents width of all columns. Implicitly enable ImGuiTableFlags_NoKeepColumnsVisible. ImGuiTableFlags_SizingStretchProp = 3 << 13, // Columns default to _WidthStretch with default weights proportional to each columns contents widths. ImGuiTableFlags_SizingStretchSame = 4 << 13, // Columns default to _WidthStretch with default weights all equal, unless overridden by TableSetupColumn(). // Sizing Extra Options ImGuiTableFlags_NoHostExtendX = 1 << 16, // Make outer width auto-fit to columns, overriding outer_size.x value. Only available when ScrollX/ScrollY are disabled and Stretch columns are not used. ImGuiTableFlags_NoHostExtendY = 1 << 17, // Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit). Only available when ScrollX/ScrollY are disabled. Data below the limit will be clipped and not visible. ImGuiTableFlags_NoKeepColumnsVisible = 1 << 18, // Disable keeping column always minimally visible when ScrollX is off and table gets too small. Not recommended if columns are resizable. ImGuiTableFlags_PreciseWidths = 1 << 19, // Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth. // Clipping ImGuiTableFlags_NoClip = 1 << 20, // Disable clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow into other columns). Generally incompatible with TableSetupScrollFreeze(). // Padding ImGuiTableFlags_PadOuterX = 1 << 21, // Default if BordersOuterV is on. Enable outermost padding. Generally desirable if you have headers. ImGuiTableFlags_NoPadOuterX = 1 << 22, // Default if BordersOuterV is off. Disable outermost padding. ImGuiTableFlags_NoPadInnerX = 1 << 23, // Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off). // Scrolling ImGuiTableFlags_ScrollX = 1 << 24, // Enable horizontal scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. Changes default sizing policy. Because this creates a child window, ScrollY is currently generally recommended when using ScrollX. ImGuiTableFlags_ScrollY = 1 << 25, // Enable vertical scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. // Sorting ImGuiTableFlags_SortMulti = 1 << 26, // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1). ImGuiTableFlags_SortTristate = 1 << 27, // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0). // Miscellaneous ImGuiTableFlags_HighlightHoveredColumn = 1 << 28, // Highlight column headers when hovered (may evolve into a fuller highlight) // [Internal] Combinations and masks ImGuiTableFlags_SizingMask_ = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_SizingFixedSame | ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_SizingStretchSame, }; // Flags for ImGui::TableSetupColumn() enum ImGuiTableColumnFlags_ { // Input configuration flags ImGuiTableColumnFlags_None = 0, ImGuiTableColumnFlags_Disabled = 1 << 0, // Overriding/master disable flag: hide column, won't show in context menu (unlike calling TableSetColumnEnabled() which manipulates the user accessible state) ImGuiTableColumnFlags_DefaultHide = 1 << 1, // Default as a hidden/disabled column. ImGuiTableColumnFlags_DefaultSort = 1 << 2, // Default as a sorting column. ImGuiTableColumnFlags_WidthStretch = 1 << 3, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _SizingStretchSame or _SizingStretchProp). ImGuiTableColumnFlags_WidthFixed = 1 << 4, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _SizingFixedFit and table is resizable). ImGuiTableColumnFlags_NoResize = 1 << 5, // Disable manual resizing. ImGuiTableColumnFlags_NoReorder = 1 << 6, // Disable manual reordering this column, this will also prevent other columns from crossing over this column. ImGuiTableColumnFlags_NoHide = 1 << 7, // Disable ability to hide/disable this column. ImGuiTableColumnFlags_NoClip = 1 << 8, // Disable clipping for this column (all NoClip columns will render in a same draw command). ImGuiTableColumnFlags_NoSort = 1 << 9, // Disable ability to sort on this field (even if ImGuiTableFlags_Sortable is set on the table). ImGuiTableColumnFlags_NoSortAscending = 1 << 10, // Disable ability to sort in the ascending direction. ImGuiTableColumnFlags_NoSortDescending = 1 << 11, // Disable ability to sort in the descending direction. ImGuiTableColumnFlags_NoHeaderLabel = 1 << 12, // TableHeadersRow() will not submit horizontal label for this column. Convenient for some small columns. Name will still appear in context menu or in angled headers. ImGuiTableColumnFlags_NoHeaderWidth = 1 << 13, // Disable header text width contribution to automatic column width. ImGuiTableColumnFlags_PreferSortAscending = 1 << 14, // Make the initial sort direction Ascending when first sorting on this column (default). ImGuiTableColumnFlags_PreferSortDescending = 1 << 15, // Make the initial sort direction Descending when first sorting on this column. ImGuiTableColumnFlags_IndentEnable = 1 << 16, // Use current Indent value when entering cell (default for column 0). ImGuiTableColumnFlags_IndentDisable = 1 << 17, // Ignore current Indent value when entering cell (default for columns > 0). Indentation changes _within_ the cell will still be honored. ImGuiTableColumnFlags_AngledHeader = 1 << 18, // TableHeadersRow() will submit an angled header row for this column. Note this will add an extra row. // Output status flags, read-only via TableGetColumnFlags() ImGuiTableColumnFlags_IsEnabled = 1 << 24, // Status: is enabled == not hidden by user/api (referred to as "Hide" in _DefaultHide and _NoHide) flags. ImGuiTableColumnFlags_IsVisible = 1 << 25, // Status: is visible == is enabled AND not clipped by scrolling. ImGuiTableColumnFlags_IsSorted = 1 << 26, // Status: is currently part of the sort specs ImGuiTableColumnFlags_IsHovered = 1 << 27, // Status: is hovered by mouse // [Internal] Combinations and masks ImGuiTableColumnFlags_WidthMask_ = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_WidthFixed, ImGuiTableColumnFlags_IndentMask_ = ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_IndentDisable, ImGuiTableColumnFlags_StatusMask_ = ImGuiTableColumnFlags_IsEnabled | ImGuiTableColumnFlags_IsVisible | ImGuiTableColumnFlags_IsSorted | ImGuiTableColumnFlags_IsHovered, ImGuiTableColumnFlags_NoDirectResize_ = 1 << 30, // [Internal] Disable user resizing this column directly (it may however we resized indirectly from its left edge) }; // Flags for ImGui::TableNextRow() enum ImGuiTableRowFlags_ { ImGuiTableRowFlags_None = 0, ImGuiTableRowFlags_Headers = 1 << 0, // Identify header row (set default background color + width of its contents accounted differently for auto column width) }; // Enum for ImGui::TableSetBgColor() // Background colors are rendering in 3 layers: // - Layer 0: draw with RowBg0 color if set, otherwise draw with ColumnBg0 if set. // - Layer 1: draw with RowBg1 color if set, otherwise draw with ColumnBg1 if set. // - Layer 2: draw with CellBg color if set. // The purpose of the two row/columns layers is to let you decide if a background color change should override or blend with the existing color. // When using ImGuiTableFlags_RowBg on the table, each row has the RowBg0 color automatically set for odd/even rows. // If you set the color of RowBg0 target, your color will override the existing RowBg0 color. // If you set the color of RowBg1 or ColumnBg1 target, your color will blend over the RowBg0 color. enum ImGuiTableBgTarget_ { ImGuiTableBgTarget_None = 0, ImGuiTableBgTarget_RowBg0 = 1, // Set row background color 0 (generally used for background, automatically set when ImGuiTableFlags_RowBg is used) ImGuiTableBgTarget_RowBg1 = 2, // Set row background color 1 (generally used for selection marking) ImGuiTableBgTarget_CellBg = 3, // Set cell background color (top-most color) }; // Sorting specifications for a table (often handling sort specs for a single column, occasionally more) // Obtained by calling TableGetSortSpecs(). // When 'SpecsDirty == true' you can sort your data. It will be true with sorting specs have changed since last call, or the first time. // Make sure to set 'SpecsDirty = false' after sorting, else you may wastefully sort your data every frame! struct ImGuiTableSortSpecs { const ImGuiTableColumnSortSpecs* Specs; // Pointer to sort spec array. int SpecsCount; // Sort spec count. Most often 1. May be > 1 when ImGuiTableFlags_SortMulti is enabled. May be == 0 when ImGuiTableFlags_SortTristate is enabled. bool SpecsDirty; // Set to true when specs have changed since last time! Use this to sort again, then clear the flag. ImGuiTableSortSpecs() { memset(this, 0, sizeof(*this)); } }; // Sorting specification for one column of a table (sizeof == 12 bytes) struct ImGuiTableColumnSortSpecs { ImGuiID ColumnUserID; // User id of the column (if specified by a TableSetupColumn() call) ImS16 ColumnIndex; // Index of the column ImS16 SortOrder; // Index within parent ImGuiTableSortSpecs (always stored in order starting from 0, tables sorted on a single criteria will always have a 0 here) ImGuiSortDirection SortDirection : 8; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending ImGuiTableColumnSortSpecs() { memset(this, 0, sizeof(*this)); } }; //----------------------------------------------------------------------------- // [SECTION] Helpers: Memory allocations macros, ImVector<> //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // IM_MALLOC(), IM_FREE(), IM_NEW(), IM_PLACEMENT_NEW(), IM_DELETE() // We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax. // Defining a custom placement new() with a custom parameter allows us to bypass including which on some platforms complains when user has disabled exceptions. //----------------------------------------------------------------------------- struct ImNewWrapper {}; inline void* operator new(size_t, ImNewWrapper, void* ptr) { return ptr; } inline void operator delete(void*, ImNewWrapper, void*) {} // This is only required so we can use the symmetrical new() #define IM_ALLOC(_SIZE) ImGui::MemAlloc(_SIZE) #define IM_FREE(_PTR) ImGui::MemFree(_PTR) #define IM_PLACEMENT_NEW(_PTR) new(ImNewWrapper(), _PTR) #define IM_NEW(_TYPE) new(ImNewWrapper(), ImGui::MemAlloc(sizeof(_TYPE))) _TYPE template void IM_DELETE(T* p) { if (p) { p->~T(); ImGui::MemFree(p); } } //----------------------------------------------------------------------------- // ImVector<> // Lightweight std::vector<>-like class to avoid dragging dependencies (also, some implementations of STL with debug enabled are absurdly slow, we bypass it so our code runs fast in debug). //----------------------------------------------------------------------------- // - You generally do NOT need to care or use this ever. But we need to make it available in imgui.h because some of our public structures are relying on it. // - We use std-like naming convention here, which is a little unusual for this codebase. // - Important: clear() frees memory, resize(0) keep the allocated buffer. We use resize(0) a lot to intentionally recycle allocated buffers across frames and amortize our costs. // - Important: our implementation does NOT call C++ constructors/destructors, we treat everything as raw data! This is intentional but be extra mindful of that, // Do NOT use this class as a std::vector replacement in your own code! Many of the structures used by dear imgui can be safely initialized by a zero-memset. //----------------------------------------------------------------------------- IM_MSVC_RUNTIME_CHECKS_OFF template struct ImVector { int Size; int Capacity; T* Data; // Provide standard typedefs but we don't use them ourselves. typedef T value_type; typedef value_type* iterator; typedef const value_type* const_iterator; // Constructors, destructor inline ImVector() { Size = Capacity = 0; Data = NULL; } inline ImVector(const ImVector& src) { Size = Capacity = 0; Data = NULL; operator=(src); } inline ImVector& operator=(const ImVector& src) { clear(); resize(src.Size); if (src.Data) memcpy(Data, src.Data, (size_t)Size * sizeof(T)); return *this; } inline ~ImVector() { if (Data) IM_FREE(Data); } // Important: does not destruct anything inline void clear() { if (Data) { Size = Capacity = 0; IM_FREE(Data); Data = NULL; } } // Important: does not destruct anything inline void clear_delete() { for (int n = 0; n < Size; n++) IM_DELETE(Data[n]); clear(); } // Important: never called automatically! always explicit. inline void clear_destruct() { for (int n = 0; n < Size; n++) Data[n].~T(); clear(); } // Important: never called automatically! always explicit. inline bool empty() const { return Size == 0; } inline int size() const { return Size; } inline int size_in_bytes() const { return Size * (int)sizeof(T); } inline int max_size() const { return 0x7FFFFFFF / (int)sizeof(T); } inline int capacity() const { return Capacity; } inline T& operator[](int i) { IM_ASSERT(i >= 0 && i < Size); return Data[i]; } inline const T& operator[](int i) const { IM_ASSERT(i >= 0 && i < Size); return Data[i]; } inline T* begin() { return Data; } inline const T* begin() const { return Data; } inline T* end() { return Data + Size; } inline const T* end() const { return Data + Size; } inline T& front() { IM_ASSERT(Size > 0); return Data[0]; } inline const T& front() const { IM_ASSERT(Size > 0); return Data[0]; } inline T& back() { IM_ASSERT(Size > 0); return Data[Size - 1]; } inline const T& back() const { IM_ASSERT(Size > 0); return Data[Size - 1]; } inline void swap(ImVector& rhs) { int rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; int rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; T* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; } inline int _grow_capacity(int sz) const { int new_capacity = Capacity ? (Capacity + Capacity / 2) : 8; return new_capacity > sz ? new_capacity : sz; } inline void resize(int new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; } inline void resize(int new_size, const T& v) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) memcpy(&Data[n], &v, sizeof(v)); Size = new_size; } inline void shrink(int new_size) { IM_ASSERT(new_size <= Size); Size = new_size; } // Resize a vector to a smaller size, guaranteed not to cause a reallocation inline void reserve(int new_capacity) { if (new_capacity <= Capacity) return; T* new_data = (T*)IM_ALLOC((size_t)new_capacity * sizeof(T)); if (Data) { memcpy(new_data, Data, (size_t)Size * sizeof(T)); IM_FREE(Data); } Data = new_data; Capacity = new_capacity; } inline void reserve_discard(int new_capacity) { if (new_capacity <= Capacity) return; if (Data) IM_FREE(Data); Data = (T*)IM_ALLOC((size_t)new_capacity * sizeof(T)); Capacity = new_capacity; } // NB: It is illegal to call push_back/push_front/insert with a reference pointing inside the ImVector data itself! e.g. v.push_back(v[10]) is forbidden. inline void push_back(const T& v) { if (Size == Capacity) reserve(_grow_capacity(Size + 1)); memcpy(&Data[Size], &v, sizeof(v)); Size++; } inline void pop_back() { IM_ASSERT(Size > 0); Size--; } inline void push_front(const T& v) { if (Size == 0) push_back(v); else insert(Data, v); } inline T* erase(const T* it) { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(T)); Size--; return Data + off; } inline T* erase(const T* it, const T* it_last){ IM_ASSERT(it >= Data && it < Data + Size && it_last >= it && it_last <= Data + Size); const ptrdiff_t count = it_last - it; const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + count, ((size_t)Size - (size_t)off - (size_t)count) * sizeof(T)); Size -= (int)count; return Data + off; } inline T* erase_unsorted(const T* it) { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; if (it < Data + Size - 1) memcpy(Data + off, Data + Size - 1, sizeof(T)); Size--; return Data + off; } inline T* insert(const T* it, const T& v) { IM_ASSERT(it >= Data && it <= Data + Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(T)); memcpy(&Data[off], &v, sizeof(v)); Size++; return Data + off; } inline bool contains(const T& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; } inline T* find(const T& v) { T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data == v) break; else ++data; return data; } inline const T* find(const T& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data == v) break; else ++data; return data; } inline int find_index(const T& v) const { const T* data_end = Data + Size; const T* it = find(v); if (it == data_end) return -1; const ptrdiff_t off = it - Data; return (int)off; } inline bool find_erase(const T& v) { const T* it = find(v); if (it < Data + Size) { erase(it); return true; } return false; } inline bool find_erase_unsorted(const T& v) { const T* it = find(v); if (it < Data + Size) { erase_unsorted(it); return true; } return false; } inline int index_from_ptr(const T* it) const { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; return (int)off; } }; IM_MSVC_RUNTIME_CHECKS_RESTORE //----------------------------------------------------------------------------- // [SECTION] ImGuiStyle //----------------------------------------------------------------------------- // You may modify the ImGui::GetStyle() main instance during initialization and before NewFrame(). // During the frame, use ImGui::PushStyleVar(ImGuiStyleVar_XXXX)/PopStyleVar() to alter the main style values, // and ImGui::PushStyleColor(ImGuiCol_XXX)/PopStyleColor() for colors. //----------------------------------------------------------------------------- struct ImGuiStyle { float Alpha; // Global alpha applies to everything in Dear ImGui. float DisabledAlpha; // Additional alpha multiplier applied by BeginDisabled(). Multiply over current value of Alpha. ImVec2 WindowPadding; // Padding within a window. float WindowRounding; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended. float WindowBorderSize; // Thickness of border around windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). ImVec2 WindowMinSize; // Minimum window size. This is a global setting. If you want to constrain individual windows, use SetNextWindowSizeConstraints(). ImVec2 WindowTitleAlign; // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered. ImGuiDir WindowMenuButtonPosition; // Side of the collapsing/docking button in the title bar (None/Left/Right). Defaults to ImGuiDir_Left. float ChildRounding; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows. float ChildBorderSize; // Thickness of border around child windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). float PopupRounding; // Radius of popup window corners rounding. (Note that tooltip windows use WindowRounding) float PopupBorderSize; // Thickness of border around popup/tooltip windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). ImVec2 FramePadding; // Padding within a framed rectangle (used by most widgets). float FrameRounding; // Radius of frame corners rounding. Set to 0.0f to have rectangular frame (used by most widgets). float FrameBorderSize; // Thickness of border around frames. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines. ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label). ImVec2 CellPadding; // Padding within a table cell. CellPadding.y may be altered between different rows. ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). float ColumnsMinSpacing; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1). float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar. float ScrollbarRounding; // Radius of grab corners for scrollbar. float GrabMinSize; // Minimum width/height of a grab box for slider/scrollbar. float GrabRounding; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. float LogSliderDeadzone; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero. float TabRounding; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs. float TabBorderSize; // Thickness of border around tabs. float TabMinWidthForCloseButton; // Minimum width for close button to appear on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected. float TabBarBorderSize; // Thickness of tab-bar separator, which takes on the tab active color to denote focus. float TableAngledHeadersAngle; // Angle of angled headers (supported values range from -50.0f degrees to +50.0f degrees). ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right. ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered). ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line. float SeparatorTextBorderSize; // Thickkness of border in SeparatorText() ImVec2 SeparatorTextAlign; // Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center). ImVec2 SeparatorTextPadding; // Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y. ImVec2 DisplayWindowPadding; // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows. ImVec2 DisplaySafeAreaPadding; // If you cannot see the edges of your screen (e.g. on a TV) increase the safe area padding. Apply to popups/tooltips as well regular windows. NB: Prefer configuring your TV sets correctly! float MouseCursorScale; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later. bool AntiAliasedLines; // Enable anti-aliased lines/borders. Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList). bool AntiAliasedLinesUseTex; // Enable anti-aliased lines/borders using textures where possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). Latched at the beginning of the frame (copied to ImDrawList). bool AntiAliasedFill; // Enable anti-aliased edges around filled shapes (rounded rectangles, circles, etc.). Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame (copied to ImDrawList). float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. float CircleTessellationMaxError; // Maximum error (in pixels) allowed when using AddCircle()/AddCircleFilled() or drawing rounded corner rectangles with no explicit segment count specified. Decrease for higher quality but more geometry. ImVec4 Colors[ImGuiCol_COUNT]; // Behaviors // (It is possible to modify those fields mid-frame if specific behavior need it, unlike e.g. configuration fields in ImGuiIO) float HoverStationaryDelay; // Delay for IsItemHovered(ImGuiHoveredFlags_Stationary). Time required to consider mouse stationary. float HoverDelayShort; // Delay for IsItemHovered(ImGuiHoveredFlags_DelayShort). Usually used along with HoverStationaryDelay. float HoverDelayNormal; // Delay for IsItemHovered(ImGuiHoveredFlags_DelayNormal). " ImGuiHoveredFlags HoverFlagsForTooltipMouse;// Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using mouse. ImGuiHoveredFlags HoverFlagsForTooltipNav; // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using keyboard/gamepad. IMGUI_API ImGuiStyle(); IMGUI_API void ScaleAllSizes(float scale_factor); }; //----------------------------------------------------------------------------- // [SECTION] ImGuiIO //----------------------------------------------------------------------------- // Communicate most settings and inputs/outputs to Dear ImGui using this structure. // Access via ImGui::GetIO(). Read 'Programmer guide' section in .cpp file for general usage. //----------------------------------------------------------------------------- // [Internal] Storage used by IsKeyDown(), IsKeyPressed() etc functions. // If prior to 1.87 you used io.KeysDownDuration[] (which was marked as internal), you should use GetKeyData(key)->DownDuration and *NOT* io.KeysData[key]->DownDuration. struct ImGuiKeyData { bool Down; // True for if key is down float DownDuration; // Duration the key has been down (<0.0f: not pressed, 0.0f: just pressed, >0.0f: time held) float DownDurationPrev; // Last frame duration the key has been down float AnalogValue; // 0.0f..1.0f for gamepad values }; struct ImGuiIO { //------------------------------------------------------------------ // Configuration // Default value //------------------------------------------------------------------ ImGuiConfigFlags ConfigFlags; // = 0 // See ImGuiConfigFlags_ enum. Set by user/application. Gamepad/keyboard navigation options, etc. ImGuiBackendFlags BackendFlags; // = 0 // See ImGuiBackendFlags_ enum. Set by backend (imgui_impl_xxx files or custom backend) to communicate features supported by the backend. ImVec2 DisplaySize; // // Main display size, in pixels (generally == GetMainViewport()->Size). May change every frame. float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. May change every frame. float IniSavingRate; // = 5.0f // Minimum time between saving positions/sizes to .ini file, in seconds. const char* IniFilename; // = "imgui.ini" // Path to .ini file (important: default "imgui.ini" is relative to current working dir!). Set NULL to disable automatic .ini loading/saving or if you want to manually call LoadIniSettingsXXX() / SaveIniSettingsXXX() functions. const char* LogFilename; // = "imgui_log.txt"// Path to .log file (default parameter to ImGui::LogToFile when no file is specified). void* UserData; // = NULL // Store your own data. ImFontAtlas*Fonts; // // Font atlas: load, rasterize and pack one or more fonts into a single texture. float FontGlobalScale; // = 1.0f // Global scale all fonts bool FontAllowUserScaling; // = false // Allow user scaling text of individual window with CTRL+Wheel. ImFont* FontDefault; // = NULL // Font to use on NewFrame(). Use NULL to uses Fonts->Fonts[0]. ImVec2 DisplayFramebufferScale; // = (1, 1) // For retina display or other situations where window coordinates are different from framebuffer coordinates. This generally ends up in ImDrawData::FramebufferScale. // Miscellaneous options bool MouseDrawCursor; // = false // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations. bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl. bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates. bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting). bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will keep item active and select contents (single-line only). bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard. bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag) bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar. float ConfigMemoryCompactTimer; // = 60.0f // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable. // Inputs Behaviors // (other variables, ones which are expected to be tweaked within UI code, are exposed in ImGuiStyle) float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds. float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels. float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging. float KeyRepeatDelay; // = 0.275f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.). float KeyRepeatRate; // = 0.050f // When holding a key/button, rate at which it repeats, in seconds. //------------------------------------------------------------------ // Debug options //------------------------------------------------------------------ // Option to enable various debug tools showing buttons that will call the IM_DEBUG_BREAK() macro. // - The Item Picker tool will be available regardless of this being enabled, in order to maximize its discoverability. // - Requires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application. // e.g. io.ConfigDebugIsDebuggerPresent = ::IsDebuggerPresent() on Win32, or refer to ImOsIsDebuggerPresent() imgui_test_engine/imgui_te_utils.cpp for a Unix compatible version). bool ConfigDebugIsDebuggerPresent; // = false // Enable various tools calling IM_DEBUG_BREAK(). // Tools to test correct Begin/End and BeginChild/EndChild behaviors. // - Presently Begin()/End() and BeginChild()/EndChild() needs to ALWAYS be called in tandem, regardless of return value of BeginXXX() // - This is inconsistent with other BeginXXX functions and create confusion for many users. // - We expect to update the API eventually. In the meanwhile we provide tools to facilitate checking user-code behavior. bool ConfigDebugBeginReturnValueOnce;// = false // First-time calls to Begin()/BeginChild() will return false. NEEDS TO BE SET AT APPLICATION BOOT TIME if you don't want to miss windows. bool ConfigDebugBeginReturnValueLoop;// = false // Some calls to Begin()/BeginChild() will return false. Will cycle through window depths then repeat. Suggested use: add "io.ConfigDebugBeginReturnValue = io.KeyShift" in your main loop then occasionally press SHIFT. Windows should be flickering while running. // Option to deactivate io.AddFocusEvent(false) handling. // - May facilitate interactions with a debugger when focus loss leads to clearing inputs data. // - Backends may have other side-effects on focus loss, so this will reduce side-effects but not necessary remove all of them. bool ConfigDebugIgnoreFocusLoss; // = false // Ignore io.AddFocusEvent(false), consequently not calling io.ClearInputKeys() in input processing. // Options to audit .ini data bool ConfigDebugIniSettings; // = false // Save .ini data with extra comments (particularly helpful for Docking, but makes saving slower) //------------------------------------------------------------------ // Platform Functions // (the imgui_impl_xxxx backend files are setting those up for you) //------------------------------------------------------------------ // Optional: Platform/Renderer backend name (informational only! will be displayed in About Window) + User data for backend/wrappers to store their own stuff. const char* BackendPlatformName; // = NULL const char* BackendRendererName; // = NULL void* BackendPlatformUserData; // = NULL // User data for platform backend void* BackendRendererUserData; // = NULL // User data for renderer backend void* BackendLanguageUserData; // = NULL // User data for non C++ programming language backend // Optional: Access OS clipboard // (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures) const char* (*GetClipboardTextFn)(void* user_data); void (*SetClipboardTextFn)(void* user_data, const char* text); void* ClipboardUserData; // Optional: Notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME on Windows) // (default to use native imm32 api on Windows) void (*SetPlatformImeDataFn)(ImGuiViewport* viewport, ImGuiPlatformImeData* data); // Optional: Platform locale ImWchar PlatformLocaleDecimalPoint; // '.' // [Experimental] Configure decimal point e.g. '.' or ',' useful for some languages (e.g. German), generally pulled from *localeconv()->decimal_point //------------------------------------------------------------------ // Input - Call before calling NewFrame() //------------------------------------------------------------------ // Input Functions IMGUI_API void AddKeyEvent(ImGuiKey key, bool down); // Queue a new key down/up event. Key should be "translated" (as in, generally ImGuiKey_A matches the key end-user would use to emit an 'A' character) IMGUI_API void AddKeyAnalogEvent(ImGuiKey key, bool down, float v); // Queue a new key down/up event for analog values (e.g. ImGuiKey_Gamepad_ values). Dead-zones should be handled by the backend. IMGUI_API void AddMousePosEvent(float x, float y); // Queue a mouse position update. Use -FLT_MAX,-FLT_MAX to signify no mouse (e.g. app not focused and not hovered) IMGUI_API void AddMouseButtonEvent(int button, bool down); // Queue a mouse button change IMGUI_API void AddMouseWheelEvent(float wheel_x, float wheel_y); // Queue a mouse wheel update. wheel_y<0: scroll down, wheel_y>0: scroll up, wheel_x<0: scroll right, wheel_x>0: scroll left. IMGUI_API void AddMouseSourceEvent(ImGuiMouseSource source); // Queue a mouse source change (Mouse/TouchScreen/Pen) IMGUI_API void AddFocusEvent(bool focused); // Queue a gain/loss of focus for the application (generally based on OS/platform focus of your window) IMGUI_API void AddInputCharacter(unsigned int c); // Queue a new character input IMGUI_API void AddInputCharacterUTF16(ImWchar16 c); // Queue a new character input from a UTF-16 character, it can be a surrogate IMGUI_API void AddInputCharactersUTF8(const char* str); // Queue a new characters input from a UTF-8 string IMGUI_API void SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native_scancode, int native_legacy_index = -1); // [Optional] Specify index for legacy <1.87 IsKeyXXX() functions with native indices + specify native keycode, scancode. IMGUI_API void SetAppAcceptingEvents(bool accepting_events); // Set master flag for accepting key/mouse/text events (default to true). Useful if you have native dialog boxes that are interrupting your application loop/refresh, and you want to disable events being queued while your app is frozen. IMGUI_API void ClearEventsQueue(); // Clear all incoming events. IMGUI_API void ClearInputKeys(); // Clear current keyboard/mouse/gamepad state + current frame text input buffer. Equivalent to releasing all keys/buttons. #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS IMGUI_API void ClearInputCharacters(); // [Obsoleted in 1.89.8] Clear the current frame text input buffer. Now included within ClearInputKeys(). #endif //------------------------------------------------------------------ // Output - Updated by NewFrame() or EndFrame()/Render() // (when reading from the io.WantCaptureMouse, io.WantCaptureKeyboard flags to dispatch your inputs, it is // generally easier and more correct to use their state BEFORE calling NewFrame(). See FAQ for details!) //------------------------------------------------------------------ bool WantCaptureMouse; // Set when Dear ImGui will use mouse inputs, in this case do not dispatch them to your main game/application (either way, always pass on mouse inputs to imgui). (e.g. unclicked mouse is hovering over an imgui window, widget is active, mouse was clicked over an imgui window, etc.). bool WantCaptureKeyboard; // Set when Dear ImGui will use keyboard inputs, in this case do not dispatch them to your main game/application (either way, always pass keyboard inputs to imgui). (e.g. InputText active, or an imgui window is focused and navigation is enabled, etc.). bool WantTextInput; // Mobile/console: when set, you may display an on-screen keyboard. This is set by Dear ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active). bool WantSetMousePos; // MousePos has been altered, backend should reposition mouse on next frame. Rarely used! Set only when ImGuiConfigFlags_NavEnableSetMousePos flag is enabled. bool WantSaveIniSettings; // When manual .ini load/save is active (io.IniFilename == NULL), this will be set to notify your application that you can call SaveIniSettingsToMemory() and save yourself. Important: clear io.WantSaveIniSettings yourself after saving! bool NavActive; // Keyboard/Gamepad navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag. bool NavVisible; // Keyboard/Gamepad navigation is visible and allowed (will handle ImGuiKey_NavXXX events). float Framerate; // Estimate of application framerate (rolling average over 60 frames, based on io.DeltaTime), in frame per second. Solely for convenience. Slow applications may not want to use a moving average or may want to reset underlying buffers occasionally. int MetricsRenderVertices; // Vertices output during last call to Render() int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3 int MetricsRenderWindows; // Number of visible windows int MetricsActiveWindows; // Number of active windows ImVec2 MouseDelta; // Mouse delta. Note that this is zero if either current or previous position are invalid (-FLT_MAX,-FLT_MAX), so a disappearing/reappearing mouse won't have a huge delta. // Legacy: before 1.87, we required backend to fill io.KeyMap[] (imgui->native map) during initialization and io.KeysDown[] (native indices) every frame. // This is still temporarily supported as a legacy feature. However the new preferred scheme is for backend to call io.AddKeyEvent(). // Old (<1.87): ImGui::IsKeyPressed(ImGui::GetIO().KeyMap[ImGuiKey_Space]) --> New (1.87+) ImGui::IsKeyPressed(ImGuiKey_Space) #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO int KeyMap[ImGuiKey_COUNT]; // [LEGACY] Input: map of indices into the KeysDown[512] entries array which represent your "native" keyboard state. The first 512 are now unused and should be kept zero. Legacy backend will write into KeyMap[] using ImGuiKey_ indices which are always >512. bool KeysDown[ImGuiKey_COUNT]; // [LEGACY] Input: Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). This used to be [512] sized. It is now ImGuiKey_COUNT to allow legacy io.KeysDown[GetKeyIndex(...)] to work without an overflow. float NavInputs[ImGuiNavInput_COUNT]; // [LEGACY] Since 1.88, NavInputs[] was removed. Backends from 1.60 to 1.86 won't build. Feed gamepad inputs via io.AddKeyEvent() and ImGuiKey_GamepadXXX enums. //void* ImeWindowHandle; // [Obsoleted in 1.87] Set ImGuiViewport::PlatformHandleRaw instead. Set this to your HWND to get automatic IME cursor positioning. #endif //------------------------------------------------------------------ // [Internal] Dear ImGui will maintain those fields. Forward compatibility not guaranteed! //------------------------------------------------------------------ ImGuiContext* Ctx; // Parent UI context (needs to be set explicitly by parent). // Main Input State // (this block used to be written by backend, since 1.87 it is best to NOT write to those directly, call the AddXXX functions above instead) // (reading from those variables is fair game, as they are extremely unlikely to be moving anywhere) ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX, -FLT_MAX) if mouse is unavailable (on another screen, etc.) bool MouseDown[5]; // Mouse buttons: 0=left, 1=right, 2=middle + extras (ImGuiMouseButton_COUNT == 5). Dear ImGui mostly uses left and right buttons. Other buttons allow us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text. >0 scrolls Up, <0 scrolls Down. Hold SHIFT to turn vertical scroll into horizontal scroll. float MouseWheelH; // Mouse wheel Horizontal. >0 scrolls Left, <0 scrolls Right. Most users don't have a mouse with a horizontal wheel, may not be filled by all backends. ImGuiMouseSource MouseSource; // Mouse actual input peripheral (Mouse/TouchScreen/Pen). bool KeyCtrl; // Keyboard modifier down: Control bool KeyShift; // Keyboard modifier down: Shift bool KeyAlt; // Keyboard modifier down: Alt bool KeySuper; // Keyboard modifier down: Cmd/Super/Windows // Other state maintained from data above + IO function calls ImGuiKeyChord KeyMods; // Key mods flags (any of ImGuiMod_Ctrl/ImGuiMod_Shift/ImGuiMod_Alt/ImGuiMod_Super flags, same as io.KeyCtrl/KeyShift/KeyAlt/KeySuper but merged into flags. DOES NOT CONTAINS ImGuiMod_Shortcut which is pretranslated). Read-only, updated by NewFrame() ImGuiKeyData KeysData[ImGuiKey_KeysData_SIZE]; // Key state for all known keys. Use IsKeyXXX() functions to access this. bool WantCaptureMouseUnlessPopupClose; // Alternative to WantCaptureMouse: (WantCaptureMouse == true && WantCaptureMouseUnlessPopupClose == false) when a click over void is expected to close a popup. ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid) ImVec2 MouseClickedPos[5]; // Position at time of clicking double MouseClickedTime[5]; // Time of last click (used to figure out double-click) bool MouseClicked[5]; // Mouse button went from !Down to Down (same as MouseClickedCount[x] != 0) bool MouseDoubleClicked[5]; // Has mouse button been double-clicked? (same as MouseClickedCount[x] == 2) ImU16 MouseClickedCount[5]; // == 0 (not clicked), == 1 (same as MouseClicked[]), == 2 (double-clicked), == 3 (triple-clicked) etc. when going from !Down to Down ImU16 MouseClickedLastCount[5]; // Count successive number of clicks. Stays valid after mouse release. Reset after another click is done. bool MouseReleased[5]; // Mouse button went from Down to !Down bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds. bool MouseDownOwnedUnlessPopupClose[5]; // Track if button was clicked inside a dear imgui window. bool MouseWheelRequestAxisSwap; // On a non-Mac system, holding SHIFT requests WheelY to perform the equivalent of a WheelX event. On a Mac system this is already enforced by the system. float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked) float MouseDownDurationPrev[5]; // Previous time the mouse button has been down float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the clicking point (used for moving thresholds) float PenPressure; // Touch/Pen pressure (0.0f to 1.0f, should be >0.0f only when MouseDown[0] == true). Helper storage currently unused by Dear ImGui. bool AppFocusLost; // Only modify via AddFocusEvent() bool AppAcceptingEvents; // Only modify via SetAppAcceptingEvents() ImS8 BackendUsingLegacyKeyArrays; // -1: unknown, 0: using AddKeyEvent(), 1: using legacy io.KeysDown[] bool BackendUsingLegacyNavInputArray; // 0: using AddKeyAnalogEvent(), 1: writing to legacy io.NavInputs[] directly ImWchar16 InputQueueSurrogate; // For AddInputCharacterUTF16() ImVector InputQueueCharacters; // Queue of _characters_ input (obtained by platform backend). Fill using AddInputCharacter() helper. IMGUI_API ImGuiIO(); }; //----------------------------------------------------------------------------- // [SECTION] Misc data structures (ImGuiInputTextCallbackData, ImGuiSizeCallbackData, ImGuiPayload) //----------------------------------------------------------------------------- // Shared state of InputText(), passed as an argument to your callback when a ImGuiInputTextFlags_Callback* flag is used. // The callback function should return 0 by default. // Callbacks (follow a flag name and see comments in ImGuiInputTextFlags_ declarations for more details) // - ImGuiInputTextFlags_CallbackEdit: Callback on buffer edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active) // - ImGuiInputTextFlags_CallbackAlways: Callback on each iteration // - ImGuiInputTextFlags_CallbackCompletion: Callback on pressing TAB // - ImGuiInputTextFlags_CallbackHistory: Callback on pressing Up/Down arrows // - ImGuiInputTextFlags_CallbackCharFilter: Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard. // - ImGuiInputTextFlags_CallbackResize: Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. struct ImGuiInputTextCallbackData { ImGuiContext* Ctx; // Parent UI context ImGuiInputTextFlags EventFlag; // One ImGuiInputTextFlags_Callback* // Read-only ImGuiInputTextFlags Flags; // What user passed to InputText() // Read-only void* UserData; // What user passed to InputText() // Read-only // Arguments for the different callback events // - To modify the text buffer in a callback, prefer using the InsertChars() / DeleteChars() function. InsertChars() will take care of calling the resize callback if necessary. // - If you know your edits are not going to resize the underlying buffer allocation, you may modify the contents of 'Buf[]' directly. You need to update 'BufTextLen' accordingly (0 <= BufTextLen < BufSize) and set 'BufDirty'' to true so InputText can update its internal state. ImWchar EventChar; // Character input // Read-write // [CharFilter] Replace character with another one, or set to zero to drop. return 1 is equivalent to setting EventChar=0; ImGuiKey EventKey; // Key pressed (Up/Down/TAB) // Read-only // [Completion,History] char* Buf; // Text buffer // Read-write // [Resize] Can replace pointer / [Completion,History,Always] Only write to pointed data, don't replace the actual pointer! int BufTextLen; // Text length (in bytes) // Read-write // [Resize,Completion,History,Always] Exclude zero-terminator storage. In C land: == strlen(some_text), in C++ land: string.length() int BufSize; // Buffer size (in bytes) = capacity+1 // Read-only // [Resize,Completion,History,Always] Include zero-terminator storage. In C land == ARRAYSIZE(my_char_array), in C++ land: string.capacity()+1 bool BufDirty; // Set if you modify Buf/BufTextLen! // Write // [Completion,History,Always] int CursorPos; // // Read-write // [Completion,History,Always] int SelectionStart; // // Read-write // [Completion,History,Always] == to SelectionEnd when no selection) int SelectionEnd; // // Read-write // [Completion,History,Always] // Helper functions for text manipulation. // Use those function to benefit from the CallbackResize behaviors. Calling those function reset the selection. IMGUI_API ImGuiInputTextCallbackData(); IMGUI_API void DeleteChars(int pos, int bytes_count); IMGUI_API void InsertChars(int pos, const char* text, const char* text_end = NULL); void SelectAll() { SelectionStart = 0; SelectionEnd = BufTextLen; } void ClearSelection() { SelectionStart = SelectionEnd = BufTextLen; } bool HasSelection() const { return SelectionStart != SelectionEnd; } }; // Resizing callback data to apply custom constraint. As enabled by SetNextWindowSizeConstraints(). Callback is called during the next Begin(). // NB: For basic min/max size constraint on each axis you don't need to use the callback! The SetNextWindowSizeConstraints() parameters are enough. struct ImGuiSizeCallbackData { void* UserData; // Read-only. What user passed to SetNextWindowSizeConstraints(). Generally store an integer or float in here (need reinterpret_cast<>). ImVec2 Pos; // Read-only. Window position, for reference. ImVec2 CurrentSize; // Read-only. Current window size. ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing. }; // Data payload for Drag and Drop operations: AcceptDragDropPayload(), GetDragDropPayload() struct ImGuiPayload { // Members void* Data; // Data (copied and owned by dear imgui) int DataSize; // Data size // [Internal] ImGuiID SourceId; // Source item id ImGuiID SourceParentId; // Source parent id (if available) int DataFrameCount; // Data timestamp char DataType[32 + 1]; // Data type tag (short user-supplied string, 32 characters max) bool Preview; // Set when AcceptDragDropPayload() was called and mouse has been hovering the target item (nb: handle overlapping drag targets) bool Delivery; // Set when AcceptDragDropPayload() was called and mouse button is released over the target item. ImGuiPayload() { Clear(); } void Clear() { SourceId = SourceParentId = 0; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Preview = Delivery = false; } bool IsDataType(const char* type) const { return DataFrameCount != -1 && strcmp(type, DataType) == 0; } bool IsPreview() const { return Preview; } bool IsDelivery() const { return Delivery; } }; //----------------------------------------------------------------------------- // [SECTION] Helpers (ImGuiOnceUponAFrame, ImGuiTextFilter, ImGuiTextBuffer, ImGuiStorage, ImGuiListClipper, Math Operators, ImColor) //----------------------------------------------------------------------------- // Helper: Unicode defines #define IM_UNICODE_CODEPOINT_INVALID 0xFFFD // Invalid Unicode code point (standard value). #ifdef IMGUI_USE_WCHAR32 #define IM_UNICODE_CODEPOINT_MAX 0x10FFFF // Maximum Unicode code point supported by this build. #else #define IM_UNICODE_CODEPOINT_MAX 0xFFFF // Maximum Unicode code point supported by this build. #endif // Helper: Execute a block of code at maximum once a frame. Convenient if you want to quickly create a UI within deep-nested code that runs multiple times every frame. // Usage: static ImGuiOnceUponAFrame oaf; if (oaf) ImGui::Text("This will be called only once per frame"); struct ImGuiOnceUponAFrame { ImGuiOnceUponAFrame() { RefFrame = -1; } mutable int RefFrame; operator bool() const { int current_frame = ImGui::GetFrameCount(); if (RefFrame == current_frame) return false; RefFrame = current_frame; return true; } }; // Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" struct ImGuiTextFilter { IMGUI_API ImGuiTextFilter(const char* default_filter = ""); IMGUI_API bool Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build IMGUI_API bool PassFilter(const char* text, const char* text_end = NULL) const; IMGUI_API void Build(); void Clear() { InputBuf[0] = 0; Build(); } bool IsActive() const { return !Filters.empty(); } // [Internal] struct ImGuiTextRange { const char* b; const char* e; ImGuiTextRange() { b = e = NULL; } ImGuiTextRange(const char* _b, const char* _e) { b = _b; e = _e; } bool empty() const { return b == e; } IMGUI_API void split(char separator, ImVector* out) const; }; char InputBuf[256]; ImVectorFilters; int CountGrep; }; // Helper: Growable text buffer for logging/accumulating text // (this could be called 'ImGuiTextBuilder' / 'ImGuiStringBuilder') struct ImGuiTextBuffer { ImVector Buf; IMGUI_API static char EmptyString[1]; ImGuiTextBuffer() { } inline char operator[](int i) const { IM_ASSERT(Buf.Data != NULL); return Buf.Data[i]; } const char* begin() const { return Buf.Data ? &Buf.front() : EmptyString; } const char* end() const { return Buf.Data ? &Buf.back() : EmptyString; } // Buf is zero-terminated, so end() will point on the zero-terminator int size() const { return Buf.Size ? Buf.Size - 1 : 0; } bool empty() const { return Buf.Size <= 1; } void clear() { Buf.clear(); } void reserve(int capacity) { Buf.reserve(capacity); } const char* c_str() const { return Buf.Data ? Buf.Data : EmptyString; } IMGUI_API void append(const char* str, const char* str_end = NULL); IMGUI_API void appendf(const char* fmt, ...) IM_FMTARGS(2); IMGUI_API void appendfv(const char* fmt, va_list args) IM_FMTLIST(2); }; // Helper: Key->Value storage // Typically you don't have to worry about this since a storage is held within each Window. // We use it to e.g. store collapse state for a tree (Int 0/1) // This is optimized for efficient lookup (dichotomy into a contiguous buffer) and rare insertion (typically tied to user interactions aka max once a frame) // You can use it as custom user storage for temporary values. Declare your own storage if, for example: // - You want to manipulate the open/close state of a particular sub-tree in your interface (tree node uses Int 0/1 to store their state). // - You want to store custom debug data easily without adding or editing structures in your code (probably not efficient, but convenient) // Types are NOT stored, so it is up to you to make sure your Key don't collide with different types. struct ImGuiStorage { // [Internal] struct ImGuiStoragePair { ImGuiID key; union { int val_i; float val_f; void* val_p; }; ImGuiStoragePair(ImGuiID _key, int _val) { key = _key; val_i = _val; } ImGuiStoragePair(ImGuiID _key, float _val) { key = _key; val_f = _val; } ImGuiStoragePair(ImGuiID _key, void* _val) { key = _key; val_p = _val; } }; ImVector Data; // - Get***() functions find pair, never add/allocate. Pairs are sorted so a query is O(log N) // - Set***() functions find pair, insertion on demand if missing. // - Sorted insertion is costly, paid once. A typical frame shouldn't need to insert any new pair. void Clear() { Data.clear(); } IMGUI_API int GetInt(ImGuiID key, int default_val = 0) const; IMGUI_API void SetInt(ImGuiID key, int val); IMGUI_API bool GetBool(ImGuiID key, bool default_val = false) const; IMGUI_API void SetBool(ImGuiID key, bool val); IMGUI_API float GetFloat(ImGuiID key, float default_val = 0.0f) const; IMGUI_API void SetFloat(ImGuiID key, float val); IMGUI_API void* GetVoidPtr(ImGuiID key) const; // default_val is NULL IMGUI_API void SetVoidPtr(ImGuiID key, void* val); // - Get***Ref() functions finds pair, insert on demand if missing, return pointer. Useful if you intend to do Get+Set. // - References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer. // - A typical use case where this is convenient for quick hacking (e.g. add storage during a live Edit&Continue session if you can't modify existing struct) // float* pvar = ImGui::GetFloatRef(key); ImGui::SliderFloat("var", pvar, 0, 100.0f); some_var += *pvar; IMGUI_API int* GetIntRef(ImGuiID key, int default_val = 0); IMGUI_API bool* GetBoolRef(ImGuiID key, bool default_val = false); IMGUI_API float* GetFloatRef(ImGuiID key, float default_val = 0.0f); IMGUI_API void** GetVoidPtrRef(ImGuiID key, void* default_val = NULL); // Advanced: for quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once. IMGUI_API void BuildSortByKey(); // Obsolete: use on your own storage if you know only integer are being stored (open/close all tree nodes) IMGUI_API void SetAllInt(int val); }; // Helper: Manually clip large list of items. // If you have lots evenly spaced items and you have random access to the list, you can perform coarse // clipping based on visibility to only submit items that are in view. // The clipper calculates the range of visible items and advance the cursor to compensate for the non-visible items we have skipped. // (Dear ImGui already clip items based on their bounds but: it needs to first layout the item to do so, and generally // fetching/submitting your own data incurs additional cost. Coarse clipping using ImGuiListClipper allows you to easily // scale using lists with tens of thousands of items without a problem) // Usage: // ImGuiListClipper clipper; // clipper.Begin(1000); // We have 1000 elements, evenly spaced. // while (clipper.Step()) // for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) // ImGui::Text("line number %d", i); // Generally what happens is: // - Clipper lets you process the first element (DisplayStart = 0, DisplayEnd = 1) regardless of it being visible or not. // - User code submit that one element. // - Clipper can measure the height of the first element // - Clipper calculate the actual range of elements to display based on the current clipping rectangle, position the cursor before the first visible element. // - User code submit visible elements. // - The clipper also handles various subtleties related to keyboard/gamepad navigation, wrapping etc. struct ImGuiListClipper { ImGuiContext* Ctx; // Parent UI context int DisplayStart; // First item to display, updated by each call to Step() int DisplayEnd; // End of items to display (exclusive) int ItemsCount; // [Internal] Number of items float ItemsHeight; // [Internal] Height of item after a first step and item submission can calculate it float StartPosY; // [Internal] Cursor position at the time of Begin() or after table frozen rows are all processed void* TempData; // [Internal] Internal data // items_count: Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step) // items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing(). IMGUI_API ImGuiListClipper(); IMGUI_API ~ImGuiListClipper(); IMGUI_API void Begin(int items_count, float items_height = -1.0f); IMGUI_API void End(); // Automatically called on the last call of Step() that returns false. IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items. // Call IncludeItemByIndex() or IncludeItemsByIndex() *BEFORE* first call to Step() if you need a range of items to not be clipped, regardless of their visibility. // (Due to alignment / padding of certain items it is possible that an extra item may be included on either end of the display range). inline void IncludeItemByIndex(int item_index) { IncludeItemsByIndex(item_index, item_index + 1); } IMGUI_API void IncludeItemsByIndex(int item_begin, int item_end); // item_end is exclusive e.g. use (42, 42+1) to make item 42 never clipped. #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS inline void IncludeRangeByIndices(int item_begin, int item_end) { IncludeItemsByIndex(item_begin, item_end); } // [renamed in 1.89.9] inline void ForceDisplayRangeByIndices(int item_begin, int item_end) { IncludeItemsByIndex(item_begin, item_end); } // [renamed in 1.89.6] //inline ImGuiListClipper(int items_count, float items_height = -1.0f) { memset(this, 0, sizeof(*this)); ItemsCount = -1; Begin(items_count, items_height); } // [removed in 1.79] #endif }; // Helpers: ImVec2/ImVec4 operators // - It is important that we are keeping those disabled by default so they don't leak in user space. // - This is in order to allow user enabling implicit cast operators between ImVec2/ImVec4 and their own types (using IM_VEC2_CLASS_EXTRA in imconfig.h) // - You can use '#define IMGUI_DEFINE_MATH_OPERATORS' to import our operators, provided as a courtesy. #ifdef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED IM_MSVC_RUNTIME_CHECKS_OFF static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); } static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); } static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); } static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); } static inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); } static inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); } static inline ImVec2 operator-(const ImVec2& lhs) { return ImVec2(-lhs.x, -lhs.y); } static inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; } static inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; } static inline ImVec2& operator+=(ImVec2& lhs, const ImVec2& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; return lhs; } static inline ImVec2& operator-=(ImVec2& lhs, const ImVec2& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; return lhs; } static inline ImVec2& operator*=(ImVec2& lhs, const ImVec2& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; return lhs; } static inline ImVec2& operator/=(ImVec2& lhs, const ImVec2& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; return lhs; } static inline bool operator==(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; } static inline bool operator!=(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y; } static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); } static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); } static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); } static inline bool operator==(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w; } static inline bool operator!=(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z || lhs.w != rhs.w; } IM_MSVC_RUNTIME_CHECKS_RESTORE #endif // Helpers macros to generate 32-bit encoded colors // User can declare their own format by #defining the 5 _SHIFT/_MASK macros in their imconfig file. #ifndef IM_COL32_R_SHIFT #ifdef IMGUI_USE_BGRA_PACKED_COLOR #define IM_COL32_R_SHIFT 16 #define IM_COL32_G_SHIFT 8 #define IM_COL32_B_SHIFT 0 #define IM_COL32_A_SHIFT 24 #define IM_COL32_A_MASK 0xFF000000 #else #define IM_COL32_R_SHIFT 0 #define IM_COL32_G_SHIFT 8 #define IM_COL32_B_SHIFT 16 #define IM_COL32_A_SHIFT 24 #define IM_COL32_A_MASK 0xFF000000 #endif #endif #define IM_COL32(R,G,B,A) (((ImU32)(A)<> IM_COL32_R_SHIFT) & 0xFF) * (1.0f / 255.0f), (float)((rgba >> IM_COL32_G_SHIFT) & 0xFF) * (1.0f / 255.0f), (float)((rgba >> IM_COL32_B_SHIFT) & 0xFF) * (1.0f / 255.0f), (float)((rgba >> IM_COL32_A_SHIFT) & 0xFF) * (1.0f / 255.0f)) {} inline operator ImU32() const { return ImGui::ColorConvertFloat4ToU32(Value); } inline operator ImVec4() const { return Value; } // FIXME-OBSOLETE: May need to obsolete/cleanup those helpers. inline void SetHSV(float h, float s, float v, float a = 1.0f){ ImGui::ColorConvertHSVtoRGB(h, s, v, Value.x, Value.y, Value.z); Value.w = a; } static ImColor HSV(float h, float s, float v, float a = 1.0f) { float r, g, b; ImGui::ColorConvertHSVtoRGB(h, s, v, r, g, b); return ImColor(r, g, b, a); } }; //----------------------------------------------------------------------------- // [SECTION] Drawing API (ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawListFlags, ImDrawList, ImDrawData) // Hold a series of drawing commands. The user provides a renderer for ImDrawData which essentially contains an array of ImDrawList. //----------------------------------------------------------------------------- // The maximum line width to bake anti-aliased textures for. Build atlas with ImFontAtlasFlags_NoBakedLines to disable baking. #ifndef IM_DRAWLIST_TEX_LINES_WIDTH_MAX #define IM_DRAWLIST_TEX_LINES_WIDTH_MAX (63) #endif // ImDrawCallback: Draw callbacks for advanced uses [configurable type: override in imconfig.h] // NB: You most likely do NOT need to use draw callbacks just to create your own widget or customized UI rendering, // you can poke into the draw list for that! Draw callback may be useful for example to: // A) Change your GPU render state, // B) render a complex 3D scene inside a UI element without an intermediate texture/render target, etc. // The expected behavior from your rendering function is 'if (cmd.UserCallback != NULL) { cmd.UserCallback(parent_list, cmd); } else { RenderTriangles() }' // If you want to override the signature of ImDrawCallback, you can simply use e.g. '#define ImDrawCallback MyDrawCallback' (in imconfig.h) + update rendering backend accordingly. #ifndef ImDrawCallback typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd); #endif // Special Draw callback value to request renderer backend to reset the graphics/render state. // The renderer backend needs to handle this special value, otherwise it will crash trying to call a function at this address. // This is useful, for example, if you submitted callbacks which you know have altered the render state and you want it to be restored. // Render state is not reset by default because they are many perfectly useful way of altering render state (e.g. changing shader/blending settings before an Image call). #define ImDrawCallback_ResetRenderState (ImDrawCallback)(-8) // Typically, 1 command = 1 GPU draw call (unless command is a callback) // - VtxOffset: When 'io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset' is enabled, // this fields allow us to render meshes larger than 64K vertices while keeping 16-bit indices. // Backends made for <1.71. will typically ignore the VtxOffset fields. // - The ClipRect/TextureId/VtxOffset fields must be contiguous as we memcmp() them together (this is asserted for). struct ImDrawCmd { ImVec4 ClipRect; // 4*4 // Clipping rectangle (x1, y1, x2, y2). Subtract ImDrawData->DisplayPos to get clipping rectangle in "viewport" coordinates ImTextureID TextureId; // 4-8 // User-provided texture ID. Set by user in ImfontAtlas::SetTexID() for fonts or passed to Image*() functions. Ignore if never using images or multiple fonts atlas. unsigned int VtxOffset; // 4 // Start offset in vertex buffer. ImGuiBackendFlags_RendererHasVtxOffset: always 0, otherwise may be >0 to support meshes larger than 64K vertices with 16-bit indices. unsigned int IdxOffset; // 4 // Start offset in index buffer. unsigned int ElemCount; // 4 // Number of indices (multiple of 3) to be rendered as triangles. Vertices are stored in the callee ImDrawList's vtx_buffer[] array, indices in idx_buffer[]. ImDrawCallback UserCallback; // 4-8 // If != NULL, call the function instead of rendering the vertices. clip_rect and texture_id will be set normally. void* UserCallbackData; // 4-8 // The draw callback code can access this. ImDrawCmd() { memset(this, 0, sizeof(*this)); } // Also ensure our padding fields are zeroed // Since 1.83: returns ImTextureID associated with this draw call. Warning: DO NOT assume this is always same as 'TextureId' (we will change this function for an upcoming feature) inline ImTextureID GetTexID() const { return TextureId; } }; // Vertex layout #ifndef IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; ImVec2 uv; ImU32 col; }; #else // You can override the vertex format layout by defining IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT in imconfig.h // The code expect ImVec2 pos (8 bytes), ImVec2 uv (8 bytes), ImU32 col (4 bytes), but you can re-order them or add other fields as needed to simplify integration in your engine. // The type has to be described within the macro (you can either declare the struct or use a typedef). This is because ImVec2/ImU32 are likely not declared at the time you'd want to set your type up. // NOTE: IMGUI DOESN'T CLEAR THE STRUCTURE AND DOESN'T CALL A CONSTRUCTOR SO ANY CUSTOM FIELD WILL BE UNINITIALIZED. IF YOU ADD EXTRA FIELDS (SUCH AS A 'Z' COORDINATES) YOU WILL NEED TO CLEAR THEM DURING RENDER OR TO IGNORE THEM. IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT; #endif // [Internal] For use by ImDrawList struct ImDrawCmdHeader { ImVec4 ClipRect; ImTextureID TextureId; unsigned int VtxOffset; }; // [Internal] For use by ImDrawListSplitter struct ImDrawChannel { ImVector _CmdBuffer; ImVector _IdxBuffer; }; // Split/Merge functions are used to split the draw list into different layers which can be drawn into out of order. // This is used by the Columns/Tables API, so items of each column can be batched together in a same draw call. struct ImDrawListSplitter { int _Current; // Current channel number (0) int _Count; // Number of active channels (1+) ImVector _Channels; // Draw channels (not resized down so _Count might be < Channels.Size) inline ImDrawListSplitter() { memset(this, 0, sizeof(*this)); } inline ~ImDrawListSplitter() { ClearFreeMemory(); } inline void Clear() { _Current = 0; _Count = 1; } // Do not clear Channels[] so our allocations are reused next frame IMGUI_API void ClearFreeMemory(); IMGUI_API void Split(ImDrawList* draw_list, int count); IMGUI_API void Merge(ImDrawList* draw_list); IMGUI_API void SetCurrentChannel(ImDrawList* draw_list, int channel_idx); }; // Flags for ImDrawList functions // (Legacy: bit 0 must always correspond to ImDrawFlags_Closed to be backward compatible with old API using a bool. Bits 1..3 must be unused) enum ImDrawFlags_ { ImDrawFlags_None = 0, ImDrawFlags_Closed = 1 << 0, // PathStroke(), AddPolyline(): specify that shape should be closed (Important: this is always == 1 for legacy reason) ImDrawFlags_RoundCornersTopLeft = 1 << 4, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-left corner only (when rounding > 0.0f, we default to all corners). Was 0x01. ImDrawFlags_RoundCornersTopRight = 1 << 5, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-right corner only (when rounding > 0.0f, we default to all corners). Was 0x02. ImDrawFlags_RoundCornersBottomLeft = 1 << 6, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-left corner only (when rounding > 0.0f, we default to all corners). Was 0x04. ImDrawFlags_RoundCornersBottomRight = 1 << 7, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-right corner only (when rounding > 0.0f, we default to all corners). Wax 0x08. ImDrawFlags_RoundCornersNone = 1 << 8, // AddRect(), AddRectFilled(), PathRect(): disable rounding on all corners (when rounding > 0.0f). This is NOT zero, NOT an implicit flag! ImDrawFlags_RoundCornersTop = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight, ImDrawFlags_RoundCornersBottom = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight, ImDrawFlags_RoundCornersLeft = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersTopLeft, ImDrawFlags_RoundCornersRight = ImDrawFlags_RoundCornersBottomRight | ImDrawFlags_RoundCornersTopRight, ImDrawFlags_RoundCornersAll = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight, ImDrawFlags_RoundCornersDefault_ = ImDrawFlags_RoundCornersAll, // Default to ALL corners if none of the _RoundCornersXX flags are specified. ImDrawFlags_RoundCornersMask_ = ImDrawFlags_RoundCornersAll | ImDrawFlags_RoundCornersNone, }; // Flags for ImDrawList instance. Those are set automatically by ImGui:: functions from ImGuiIO settings, and generally not manipulated directly. // It is however possible to temporarily alter flags between calls to ImDrawList:: functions. enum ImDrawListFlags_ { ImDrawListFlags_None = 0, ImDrawListFlags_AntiAliasedLines = 1 << 0, // Enable anti-aliased lines/borders (*2 the number of triangles for 1.0f wide line or lines thin enough to be drawn using textures, otherwise *3 the number of triangles) ImDrawListFlags_AntiAliasedLinesUseTex = 1 << 1, // Enable anti-aliased lines/borders using textures when possible. Require backend to render with bilinear filtering (NOT point/nearest filtering). ImDrawListFlags_AntiAliasedFill = 1 << 2, // Enable anti-aliased edge around filled shapes (rounded rectangles, circles). ImDrawListFlags_AllowVtxOffset = 1 << 3, // Can emit 'VtxOffset > 0' to allow large meshes. Set when 'ImGuiBackendFlags_RendererHasVtxOffset' is enabled. }; // Draw command list // This is the low-level list of polygons that ImGui:: functions are filling. At the end of the frame, // all command lists are passed to your ImGuiIO::RenderDrawListFn function for rendering. // Each dear imgui window contains its own ImDrawList. You can use ImGui::GetWindowDrawList() to // access the current window draw list and draw custom primitives. // You can interleave normal ImGui:: calls and adding primitives to the current draw list. // In single viewport mode, top-left is == GetMainViewport()->Pos (generally 0,0), bottom-right is == GetMainViewport()->Pos+Size (generally io.DisplaySize). // You are totally free to apply whatever transformation matrix to want to the data (depending on the use of the transformation you may want to apply it to ClipRect as well!) // Important: Primitives are always added to the list and not culled (culling is done at higher-level by ImGui:: functions), if you use this API a lot consider coarse culling your drawn objects. struct ImDrawList { // This is what you have to render ImVector CmdBuffer; // Draw commands. Typically 1 command = 1 GPU draw call, unless the command is a callback. ImVector IdxBuffer; // Index buffer. Each command consume ImDrawCmd::ElemCount of those ImVector VtxBuffer; // Vertex buffer. ImDrawListFlags Flags; // Flags, you may poke into these to adjust anti-aliasing settings per-primitive. // [Internal, used while building lists] unsigned int _VtxCurrentIdx; // [Internal] generally == VtxBuffer.Size unless we are past 64K vertices, in which case this gets reset to 0. ImDrawListSharedData* _Data; // Pointer to shared draw data (you can use ImGui::GetDrawListSharedData() to get the one from current ImGui context) const char* _OwnerName; // Pointer to owner window's name for debugging ImDrawVert* _VtxWritePtr; // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> operators too much) ImDrawIdx* _IdxWritePtr; // [Internal] point within IdxBuffer.Data after each add command (to avoid using the ImVector<> operators too much) ImVector _ClipRectStack; // [Internal] ImVector _TextureIdStack; // [Internal] ImVector _Path; // [Internal] current path building ImDrawCmdHeader _CmdHeader; // [Internal] template of active commands. Fields should match those of CmdBuffer.back(). ImDrawListSplitter _Splitter; // [Internal] for channels api (note: prefer using your own persistent instance of ImDrawListSplitter!) float _FringeScale; // [Internal] anti-alias fringe is scaled by this value, this helps to keep things sharp while zooming at vertex buffer content // If you want to create ImDrawList instances, pass them ImGui::GetDrawListSharedData() or create and use your own ImDrawListSharedData (so you can use ImDrawList without ImGui) ImDrawList(ImDrawListSharedData* shared_data) { memset(this, 0, sizeof(*this)); _Data = shared_data; } ~ImDrawList() { _ClearFreeMemory(); } IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect = false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) IMGUI_API void PushClipRectFullScreen(); IMGUI_API void PopClipRect(); IMGUI_API void PushTextureID(ImTextureID texture_id); IMGUI_API void PopTextureID(); inline ImVec2 GetClipRectMin() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.x, cr.y); } inline ImVec2 GetClipRectMax() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.z, cr.w); } // Primitives // - Filled shapes must always use clockwise winding order. The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing. // - For rectangular primitives, "p_min" and "p_max" represent the upper-left and lower-right corners. // - For circle primitives, use "num_segments == 0" to automatically calculate tessellation (preferred). // In older versions (until Dear ImGui 1.77) the AddCircle functions defaulted to num_segments == 12. // In future versions we will use textures to provide cheaper and higher-quality circles. // Use AddNgon() and AddNgonFilled() functions if you need to guarantee a specific number of sides. IMGUI_API void AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness = 1.0f); IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size) IMGUI_API void AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0); // a: upper-left, b: lower-right (== upper-left + size) IMGUI_API void AddRectFilledMultiColor(const ImVec2& p_min, const ImVec2& p_max, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left); IMGUI_API void AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness = 1.0f); IMGUI_API void AddQuadFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col); IMGUI_API void AddTriangle(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness = 1.0f); IMGUI_API void AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col); IMGUI_API void AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments = 0, float thickness = 1.0f); IMGUI_API void AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments = 0); IMGUI_API void AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness = 1.0f); IMGUI_API void AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments); IMGUI_API void AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f); IMGUI_API void AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0); IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL); IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness); IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col); IMGUI_API void AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0); // Cubic Bezier (4 control points) IMGUI_API void AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness, int num_segments = 0); // Quadratic Bezier (3 control points) // Image primitives // - Read FAQ to understand what ImTextureID is. // - "p_min" and "p_max" represent the upper-left and lower-right corners of the rectangle. // - "uv_min" and "uv_max" represent the normalized texture coordinates to use for those corners. Using (0,0)->(1,1) texture coordinates will generally display the entire texture. IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min = ImVec2(0, 0), const ImVec2& uv_max = ImVec2(1, 1), ImU32 col = IM_COL32_WHITE); IMGUI_API void AddImageQuad(ImTextureID user_texture_id, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& uv1 = ImVec2(0, 0), const ImVec2& uv2 = ImVec2(1, 0), const ImVec2& uv3 = ImVec2(1, 1), const ImVec2& uv4 = ImVec2(0, 1), ImU32 col = IM_COL32_WHITE); IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags = 0); // Stateful path API, add points then finish with PathFillConvex() or PathStroke() // - Filled shapes must always use clockwise winding order. The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing. inline void PathClear() { _Path.Size = 0; } inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size - 1], &pos, 8) != 0) _Path.push_back(pos); } inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; } inline void PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, flags, thickness); _Path.Size = 0; } IMGUI_API void PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments = 0); IMGUI_API void PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle IMGUI_API void PathEllipticalArcTo(const ImVec2& center, float radius_x, float radius_y, float rot, float a_min, float a_max, int num_segments = 0); // Ellipse IMGUI_API void PathBezierCubicCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0); // Cubic Bezier (4 control points) IMGUI_API void PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3, int num_segments = 0); // Quadratic Bezier (3 control points) IMGUI_API void PathRect(const ImVec2& rect_min, const ImVec2& rect_max, float rounding = 0.0f, ImDrawFlags flags = 0); // Advanced IMGUI_API void AddCallback(ImDrawCallback callback, void* callback_data); // Your rendering function must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles. IMGUI_API void AddDrawCmd(); // This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending). Otherwise primitives are merged into the same draw-call as much as possible IMGUI_API ImDrawList* CloneOutput() const; // Create a clone of the CmdBuffer/IdxBuffer/VtxBuffer. // Advanced: Channels // - Use to split render into layers. By switching channels to can render out-of-order (e.g. submit FG primitives before BG primitives) // - Use to minimize draw calls (e.g. if going back-and-forth between multiple clipping rectangles, prefer to append into separate channels then merge at the end) // - This API shouldn't have been in ImDrawList in the first place! // Prefer using your own persistent instance of ImDrawListSplitter as you can stack them. // Using the ImDrawList::ChannelsXXXX you cannot stack a split over another. inline void ChannelsSplit(int count) { _Splitter.Split(this, count); } inline void ChannelsMerge() { _Splitter.Merge(this); } inline void ChannelsSetCurrent(int n) { _Splitter.SetCurrentChannel(this, n); } // Advanced: Primitives allocations // - We render triangles (three vertices) // - All primitives needs to be reserved via PrimReserve() beforehand. IMGUI_API void PrimReserve(int idx_count, int vtx_count); IMGUI_API void PrimUnreserve(int idx_count, int vtx_count); IMGUI_API void PrimRect(const ImVec2& a, const ImVec2& b, ImU32 col); // Axis aligned rectangle (composed of two triangles) IMGUI_API void PrimRectUV(const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col); IMGUI_API void PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col); inline void PrimWriteVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { _VtxWritePtr->pos = pos; _VtxWritePtr->uv = uv; _VtxWritePtr->col = col; _VtxWritePtr++; _VtxCurrentIdx++; } inline void PrimWriteIdx(ImDrawIdx idx) { *_IdxWritePtr = idx; _IdxWritePtr++; } inline void PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) { PrimWriteIdx((ImDrawIdx)_VtxCurrentIdx); PrimWriteVtx(pos, uv, col); } // Write vertex with unique index // Obsolete names //inline void AddBezierCurve(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0) { AddBezierCubic(p1, p2, p3, p4, col, thickness, num_segments); } // OBSOLETED in 1.80 (Jan 2021) //inline void PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments = 0) { PathBezierCubicCurveTo(p2, p3, p4, num_segments); } // OBSOLETED in 1.80 (Jan 2021) // [Internal helpers] IMGUI_API void _ResetForNewFrame(); IMGUI_API void _ClearFreeMemory(); IMGUI_API void _PopUnusedDrawCmd(); IMGUI_API void _TryMergeDrawCmds(); IMGUI_API void _OnChangedClipRect(); IMGUI_API void _OnChangedTextureID(); IMGUI_API void _OnChangedVtxOffset(); IMGUI_API int _CalcCircleAutoSegmentCount(float radius) const; IMGUI_API void _PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step); IMGUI_API void _PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments); }; // All draw data to render a Dear ImGui frame // (NB: the style and the naming convention here is a little inconsistent, we currently preserve them for backward compatibility purpose, // as this is one of the oldest structure exposed by the library! Basically, ImDrawList == CmdList) struct ImDrawData { bool Valid; // Only valid after Render() is called and before the next NewFrame() is called. int CmdListsCount; // Number of ImDrawList* to render (should always be == CmdLists.size) int TotalIdxCount; // For convenience, sum of all ImDrawList's IdxBuffer.Size int TotalVtxCount; // For convenience, sum of all ImDrawList's VtxBuffer.Size ImVector CmdLists; // Array of ImDrawList* to render. The ImDrawLists are owned by ImGuiContext and only pointed to from here. ImVec2 DisplayPos; // Top-left position of the viewport to render (== top-left of the orthogonal projection matrix to use) (== GetMainViewport()->Pos for the main viewport, == (0.0) in most single-viewport applications) ImVec2 DisplaySize; // Size of the viewport to render (== GetMainViewport()->Size for the main viewport, == io.DisplaySize in most single-viewport applications) ImVec2 FramebufferScale; // Amount of pixels for each unit of DisplaySize. Based on io.DisplayFramebufferScale. Generally (1,1) on normal display, (2,2) on OSX with Retina display. ImGuiViewport* OwnerViewport; // Viewport carrying the ImDrawData instance, might be of use to the renderer (generally not). // Functions ImDrawData() { Clear(); } IMGUI_API void Clear(); IMGUI_API void AddDrawList(ImDrawList* draw_list); // Helper to add an external draw list into an existing ImDrawData. IMGUI_API void DeIndexAllBuffers(); // Helper to convert all buffers from indexed to non-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering! IMGUI_API void ScaleClipRects(const ImVec2& fb_scale); // Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than Dear ImGui expects, or if there is a difference between your window resolution and framebuffer resolution. }; //----------------------------------------------------------------------------- // [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontAtlasFlags, ImFontAtlas, ImFontGlyphRangesBuilder, ImFont) //----------------------------------------------------------------------------- struct ImFontConfig { void* FontData; // // TTF/OTF data int FontDataSize; // // TTF/OTF data size bool FontDataOwnedByAtlas; // true // TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself). int FontNo; // 0 // Index of font within TTF/OTF file float SizePixels; // // Size in pixels for rasterizer (more or less maps to the resulting font height). int OversampleH; // 2 // Rasterize at higher quality for sub-pixel positioning. Note the difference between 2 and 3 is minimal. You can reduce this to 1 for large glyphs save memory. Read https://github.com/nothings/stb/blob/master/tests/oversample/README.md for details. int OversampleV; // 1 // Rasterize at higher quality for sub-pixel positioning. This is not really useful as we don't use sub-pixel positions on the Y axis. bool PixelSnapH; // false // Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1. ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs. Only X axis is supported for now. ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input. const ImWchar* GlyphRanges; // NULL // THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). float GlyphMinAdvanceX; // 0 // Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font float GlyphMaxAdvanceX; // FLT_MAX // Maximum AdvanceX for glyphs bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights. unsigned int FontBuilderFlags; // 0 // Settings for custom font builder. THIS IS BUILDER IMPLEMENTATION DEPENDENT. Leave as zero if unsure. float RasterizerMultiply; // 1.0f // Linearly brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. This is a silly thing we may remove in the future. float RasterizerDensity; // 1.0f // DPI scale for rasterization, not altering other font metrics: make it easy to swap between e.g. a 100% and a 400% fonts for a zooming display. IMPORTANT: If you increase this it is expected that you increase font scale accordingly, otherwise quality may look lowered. ImWchar EllipsisChar; // -1 // Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used. // [Internal] char Name[40]; // Name (strictly to ease debugging) ImFont* DstFont; IMGUI_API ImFontConfig(); }; // Hold rendering data for one glyph. // (Note: some language parsers may fail to convert the 31+1 bitfield members, in this case maybe drop store a single u32 or we can rework this) struct ImFontGlyph { unsigned int Colored : 1; // Flag to indicate glyph is colored and should generally ignore tinting (make it usable with no shift on little-endian as this is used in loops) unsigned int Visible : 1; // Flag to indicate glyph has no visible pixels (e.g. space). Allow early out when rendering. unsigned int Codepoint : 30; // 0x0000..0x10FFFF float AdvanceX; // Distance to next character (= data from font + ImFontConfig::GlyphExtraSpacing.x baked in) float X0, Y0, X1, Y1; // Glyph corners float U0, V0, U1, V1; // Texture coordinates }; // Helper to build glyph ranges from text/string data. Feed your application strings/characters to it then call BuildRanges(). // This is essentially a tightly packed of vector of 64k booleans = 8KB storage. struct ImFontGlyphRangesBuilder { ImVector UsedChars; // Store 1-bit per Unicode code point (0=unused, 1=used) ImFontGlyphRangesBuilder() { Clear(); } inline void Clear() { int size_in_bytes = (IM_UNICODE_CODEPOINT_MAX + 1) / 8; UsedChars.resize(size_in_bytes / (int)sizeof(ImU32)); memset(UsedChars.Data, 0, (size_t)size_in_bytes); } inline bool GetBit(size_t n) const { int off = (int)(n >> 5); ImU32 mask = 1u << (n & 31); return (UsedChars[off] & mask) != 0; } // Get bit n in the array inline void SetBit(size_t n) { int off = (int)(n >> 5); ImU32 mask = 1u << (n & 31); UsedChars[off] |= mask; } // Set bit n in the array inline void AddChar(ImWchar c) { SetBit(c); } // Add character IMGUI_API void AddText(const char* text, const char* text_end = NULL); // Add string (each character of the UTF-8 string are added) IMGUI_API void AddRanges(const ImWchar* ranges); // Add ranges, e.g. builder.AddRanges(ImFontAtlas::GetGlyphRangesDefault()) to force add all of ASCII/Latin+Ext IMGUI_API void BuildRanges(ImVector* out_ranges); // Output new ranges }; // See ImFontAtlas::AddCustomRectXXX functions. struct ImFontAtlasCustomRect { unsigned short Width, Height; // Input // Desired rectangle dimension unsigned short X, Y; // Output // Packed position in Atlas unsigned int GlyphID; // Input // For custom font glyphs only (ID < 0x110000) float GlyphAdvanceX; // Input // For custom font glyphs only: glyph xadvance ImVec2 GlyphOffset; // Input // For custom font glyphs only: glyph display offset ImFont* Font; // Input // For custom font glyphs only: target font ImFontAtlasCustomRect() { Width = Height = 0; X = Y = 0xFFFF; GlyphID = 0; GlyphAdvanceX = 0.0f; GlyphOffset = ImVec2(0, 0); Font = NULL; } bool IsPacked() const { return X != 0xFFFF; } }; // Flags for ImFontAtlas build enum ImFontAtlasFlags_ { ImFontAtlasFlags_None = 0, ImFontAtlasFlags_NoPowerOfTwoHeight = 1 << 0, // Don't round the height to next power of two ImFontAtlasFlags_NoMouseCursors = 1 << 1, // Don't build software mouse cursors into the atlas (save a little texture memory) ImFontAtlasFlags_NoBakedLines = 1 << 2, // Don't build thick line textures into the atlas (save a little texture memory, allow support for point/nearest filtering). The AntiAliasedLinesUseTex features uses them, otherwise they will be rendered using polygons (more expensive for CPU/GPU). }; // Load and rasterize multiple TTF/OTF fonts into a same texture. The font atlas will build a single texture holding: // - One or more fonts. // - Custom graphics data needed to render the shapes needed by Dear ImGui. // - Mouse cursor shapes for software cursor rendering (unless setting 'Flags |= ImFontAtlasFlags_NoMouseCursors' in the font atlas). // It is the user-code responsibility to setup/build the atlas, then upload the pixel data into a texture accessible by your graphics api. // - Optionally, call any of the AddFont*** functions. If you don't call any, the default font embedded in the code will be loaded for you. // - Call GetTexDataAsAlpha8() or GetTexDataAsRGBA32() to build and retrieve pixels data. // - Upload the pixels data into a texture within your graphics system (see imgui_impl_xxxx.cpp examples) // - Call SetTexID(my_tex_id); and pass the pointer/identifier to your texture in a format natural to your graphics API. // This value will be passed back to you during rendering to identify the texture. Read FAQ entry about ImTextureID for more details. // Common pitfalls: // - If you pass a 'glyph_ranges' array to AddFont*** functions, you need to make sure that your array persist up until the // atlas is build (when calling GetTexData*** or Build()). We only copy the pointer, not the data. // - Important: By default, AddFontFromMemoryTTF() takes ownership of the data. Even though we are not writing to it, we will free the pointer on destruction. // You can set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed, // - Even though many functions are suffixed with "TTF", OTF data is supported just as well. // - This is an old API and it is currently awkward for those and various other reasons! We will address them in the future! struct ImFontAtlas { IMGUI_API ImFontAtlas(); IMGUI_API ~ImFontAtlas(); IMGUI_API ImFont* AddFont(const ImFontConfig* font_cfg); IMGUI_API ImFont* AddFontDefault(const ImFontConfig* font_cfg = NULL); IMGUI_API ImFont* AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); IMGUI_API ImFont* AddFontFromMemoryTTF(void* font_data, int font_data_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after destruction of the atlas. Set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed. IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_data_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp. IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter. IMGUI_API void ClearInputData(); // Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts. IMGUI_API void ClearTexData(); // Clear output texture data (CPU side). Saves RAM once the texture has been copied to graphics memory. IMGUI_API void ClearFonts(); // Clear output font data (glyphs storage, UV coordinates). IMGUI_API void Clear(); // Clear all input and output. // Build atlas, retrieve pixel data. // User is in charge of copying the pixels into graphics memory (e.g. create a texture with your engine). Then store your texture handle with SetTexID(). // The pitch is always = Width * BytesPerPixels (1 or 4) // Building in RGBA32 format is provided for convenience and compatibility, but note that unless you manually manipulate or copy color data into // the texture (e.g. when using the AddCustomRect*** api), then the RGB pixels emitted will always be white (~75% of memory/bandwidth waste. IMGUI_API bool Build(); // Build pixels data. This is called automatically for you by the GetTexData*** functions. IMGUI_API void GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 1 byte per-pixel IMGUI_API void GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel = NULL); // 4 bytes-per-pixel bool IsBuilt() const { return Fonts.Size > 0 && TexReady; } // Bit ambiguous: used to detect when user didn't build texture but effectively we should check TexID != 0 except that would be backend dependent... void SetTexID(ImTextureID id) { TexID = id; } //------------------------------------------- // Glyph Ranges //------------------------------------------- // Helpers to retrieve list of common Unicode ranges (2 value per range, values are inclusive, zero-terminated list) // NB: Make sure that your string are UTF-8 and NOT in your local code page. // Read https://github.com/ocornut/imgui/blob/master/docs/FONTS.md/#about-utf-8-encoding for details. // NB: Consider using ImFontGlyphRangesBuilder to build glyph ranges from textual data. IMGUI_API const ImWchar* GetGlyphRangesDefault(); // Basic Latin, Extended Latin IMGUI_API const ImWchar* GetGlyphRangesGreek(); // Default + Greek and Coptic IMGUI_API const ImWchar* GetGlyphRangesKorean(); // Default + Korean characters IMGUI_API const ImWchar* GetGlyphRangesJapanese(); // Default + Hiragana, Katakana, Half-Width, Selection of 2999 Ideographs IMGUI_API const ImWchar* GetGlyphRangesChineseFull(); // Default + Half-Width + Japanese Hiragana/Katakana + full set of about 21000 CJK Unified Ideographs IMGUI_API const ImWchar* GetGlyphRangesChineseSimplifiedCommon();// Default + Half-Width + Japanese Hiragana/Katakana + set of 2500 CJK Unified Ideographs for common simplified Chinese IMGUI_API const ImWchar* GetGlyphRangesCyrillic(); // Default + about 400 Cyrillic characters IMGUI_API const ImWchar* GetGlyphRangesThai(); // Default + Thai characters IMGUI_API const ImWchar* GetGlyphRangesVietnamese(); // Default + Vietnamese characters //------------------------------------------- // [BETA] Custom Rectangles/Glyphs API //------------------------------------------- // You can request arbitrary rectangles to be packed into the atlas, for your own purposes. // - After calling Build(), you can query the rectangle position and render your pixels. // - If you render colored output, set 'atlas->TexPixelsUseColors = true' as this may help some backends decide of prefered texture format. // - You can also request your rectangles to be mapped as font glyph (given a font + Unicode point), // so you can render e.g. custom colorful icons and use them as regular glyphs. // - Read docs/FONTS.md for more details about using colorful icons. // - Note: this API may be redesigned later in order to support multi-monitor varying DPI settings. IMGUI_API int AddCustomRectRegular(int width, int height); IMGUI_API int AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset = ImVec2(0, 0)); ImFontAtlasCustomRect* GetCustomRectByIndex(int index) { IM_ASSERT(index >= 0); return &CustomRects[index]; } // [Internal] IMGUI_API void CalcCustomRectUV(const ImFontAtlasCustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max) const; IMGUI_API bool GetMouseCursorTexData(ImGuiMouseCursor cursor, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]); //------------------------------------------- // Members //------------------------------------------- ImFontAtlasFlags Flags; // Build flags (see ImFontAtlasFlags_) ImTextureID TexID; // User data to refer to the texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure. int TexDesiredWidth; // Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height. int TexGlyphPadding; // Padding between glyphs within texture in pixels. Defaults to 1. If your rendering method doesn't rely on bilinear filtering you may set this to 0 (will also need to set AntiAliasedLinesUseTex = false). bool Locked; // Marked as Locked by ImGui::NewFrame() so attempt to modify the atlas will assert. void* UserData; // Store your own atlas related user-data (if e.g. you have multiple font atlas). // [Internal] // NB: Access texture data via GetTexData*() calls! Which will setup a default font for you. bool TexReady; // Set when texture was built matching current font input bool TexPixelsUseColors; // Tell whether our texture data is known to use colors (rather than just alpha channel), in order to help backend select a format. unsigned char* TexPixelsAlpha8; // 1 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight unsigned int* TexPixelsRGBA32; // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4 int TexWidth; // Texture width calculated during Build(). int TexHeight; // Texture height calculated during Build(). ImVec2 TexUvScale; // = (1.0f/TexWidth, 1.0f/TexHeight) ImVec2 TexUvWhitePixel; // Texture coordinates to a white pixel ImVector Fonts; // Hold all the fonts returned by AddFont*. Fonts[0] is the default font upon calling ImGui::NewFrame(), use ImGui::PushFont()/PopFont() to change the current font. ImVector CustomRects; // Rectangles for packing custom texture data into the atlas. ImVector ConfigData; // Configuration data ImVec4 TexUvLines[IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1]; // UVs for baked anti-aliased lines // [Internal] Font builder const ImFontBuilderIO* FontBuilderIO; // Opaque interface to a font builder (default to stb_truetype, can be changed to use FreeType by defining IMGUI_ENABLE_FREETYPE). unsigned int FontBuilderFlags; // Shared flags (for all fonts) for custom font builder. THIS IS BUILD IMPLEMENTATION DEPENDENT. Per-font override is also available in ImFontConfig. // [Internal] Packing data int PackIdMouseCursors; // Custom texture rectangle ID for white pixel and mouse cursors int PackIdLines; // Custom texture rectangle ID for baked anti-aliased lines // [Obsolete] //typedef ImFontAtlasCustomRect CustomRect; // OBSOLETED in 1.72+ //typedef ImFontGlyphRangesBuilder GlyphRangesBuilder; // OBSOLETED in 1.67+ }; // Font runtime data and rendering // ImFontAtlas automatically loads a default embedded font for you when you call GetTexDataAsAlpha8() or GetTexDataAsRGBA32(). struct ImFont { // Members: Hot ~20/24 bytes (for CalcTextSize) ImVector IndexAdvanceX; // 12-16 // out // // Sparse. Glyphs->AdvanceX in a directly indexable way (cache-friendly for CalcTextSize functions which only this this info, and are often bottleneck in large UI). float FallbackAdvanceX; // 4 // out // = FallbackGlyph->AdvanceX float FontSize; // 4 // in // // Height of characters/line, set during loading (don't change after loading) // Members: Hot ~28/40 bytes (for CalcTextSize + render loop) ImVector IndexLookup; // 12-16 // out // // Sparse. Index glyphs by Unicode code-point. ImVector Glyphs; // 12-16 // out // // All glyphs. const ImFontGlyph* FallbackGlyph; // 4-8 // out // = FindGlyph(FontFallbackChar) // Members: Cold ~32/40 bytes ImFontAtlas* ContainerAtlas; // 4-8 // out // // What we has been loaded into const ImFontConfig* ConfigData; // 4-8 // in // // Pointer within ContainerAtlas->ConfigData short ConfigDataCount; // 2 // in // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont. ImWchar FallbackChar; // 2 // out // = FFFD/'?' // Character used if a glyph isn't found. ImWchar EllipsisChar; // 2 // out // = '...'/'.'// Character used for ellipsis rendering. short EllipsisCharCount; // 1 // out // 1 or 3 float EllipsisWidth; // 4 // out // Width float EllipsisCharStep; // 4 // out // Step between characters when EllipsisCount > 0 bool DirtyLookupTables; // 1 // out // float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale() float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) ImU8 Used4kPagesMap[(IM_UNICODE_CODEPOINT_MAX+1)/4096/8]; // 2 bytes if ImWchar=ImWchar16, 34 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 4K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints. // Methods IMGUI_API ImFont(); IMGUI_API ~ImFont(); IMGUI_API const ImFontGlyph*FindGlyph(ImWchar c) const; IMGUI_API const ImFontGlyph*FindGlyphNoFallback(ImWchar c) const; float GetCharAdvance(ImWchar c) const { return ((int)c < IndexAdvanceX.Size) ? IndexAdvanceX[(int)c] : FallbackAdvanceX; } bool IsLoaded() const { return ContainerAtlas != NULL; } const char* GetDebugName() const { return ConfigData ? ConfigData->Name : ""; } // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable. // 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable. IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end = NULL, const char** remaining = NULL) const; // utf8 IMGUI_API const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const; IMGUI_API void RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, ImWchar c) const; IMGUI_API void RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, bool cpu_fine_clip = false) const; // [Internal] Don't use! IMGUI_API void BuildLookupTable(); IMGUI_API void ClearOutputData(); IMGUI_API void GrowIndex(int new_size); IMGUI_API void AddGlyph(const ImFontConfig* src_cfg, ImWchar c, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x); IMGUI_API void AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built. IMGUI_API void SetGlyphVisible(ImWchar c, bool visible); IMGUI_API bool IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last); }; //----------------------------------------------------------------------------- // [SECTION] Viewports //----------------------------------------------------------------------------- // Flags stored in ImGuiViewport::Flags, giving indications to the platform backends. enum ImGuiViewportFlags_ { ImGuiViewportFlags_None = 0, ImGuiViewportFlags_IsPlatformWindow = 1 << 0, // Represent a Platform Window ImGuiViewportFlags_IsPlatformMonitor = 1 << 1, // Represent a Platform Monitor (unused yet) ImGuiViewportFlags_OwnedByApp = 1 << 2, // Platform Window: is created/managed by the application (rather than a dear imgui backend) }; // - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows. // - In 'docking' branch with multi-viewport enabled, we extend this concept to have multiple active viewports. // - In the future we will extend this concept further to also represent Platform Monitor and support a "no main platform window" operation mode. // - About Main Area vs Work Area: // - Main Area = entire viewport. // - Work Area = entire viewport minus sections used by main menu bars (for platform windows), or by task bar (for platform monitor). // - Windows are generally trying to stay within the Work Area of their host viewport. struct ImGuiViewport { ImGuiID ID; // Unique identifier for the viewport ImGuiViewportFlags Flags; // See ImGuiViewportFlags_ ImVec2 Pos; // Main Area: Position of the viewport (Dear ImGui coordinates are the same as OS desktop/native coordinates) ImVec2 Size; // Main Area: Size of the viewport. ImVec2 WorkPos; // Work Area: Position of the viewport minus task bars, menus bars, status bars (>= Pos) ImVec2 WorkSize; // Work Area: Size of the viewport minus task bars, menu bars, status bars (<= Size) // Platform/Backend Dependent Data void* PlatformHandleRaw; // void* to hold lower-level, platform-native window handle (under Win32 this is expected to be a HWND, unused for other platforms) ImGuiViewport() { memset(this, 0, sizeof(*this)); } // Helpers ImVec2 GetCenter() const { return ImVec2(Pos.x + Size.x * 0.5f, Pos.y + Size.y * 0.5f); } ImVec2 GetWorkCenter() const { return ImVec2(WorkPos.x + WorkSize.x * 0.5f, WorkPos.y + WorkSize.y * 0.5f); } }; //----------------------------------------------------------------------------- // [SECTION] Platform Dependent Interfaces //----------------------------------------------------------------------------- // (Optional) Support for IME (Input Method Editor) via the io.SetPlatformImeDataFn() function. struct ImGuiPlatformImeData { bool WantVisible; // A widget wants the IME to be visible ImVec2 InputPos; // Position of the input cursor float InputLineHeight; // Line height ImGuiPlatformImeData() { memset(this, 0, sizeof(*this)); } }; //----------------------------------------------------------------------------- // [SECTION] Obsolete functions and types // (Will be removed! Read 'API BREAKING CHANGES' section in imgui.cpp for details) // Please keep your copy of dear imgui up to date! Occasionally set '#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS' in imconfig.h to stay ahead. //----------------------------------------------------------------------------- namespace ImGui { #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO IMGUI_API ImGuiKey GetKeyIndex(ImGuiKey key); // map ImGuiKey_* values into legacy native key index. == io.KeyMap[key] #else static inline ImGuiKey GetKeyIndex(ImGuiKey key) { IM_ASSERT(key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END && "ImGuiKey and native_index was merged together and native_index is disabled by IMGUI_DISABLE_OBSOLETE_KEYIO. Please switch to ImGuiKey."); return key; } #endif } #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { // OBSOLETED in 1.90.0 (from September 2023) static inline bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags window_flags = 0) { return BeginChild(id, size, ImGuiChildFlags_FrameStyle, window_flags); } static inline void EndChildFrame() { EndChild(); } //static inline bool BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags window_flags){ return BeginChild(str_id, size_arg, border ? ImGuiChildFlags_Border : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Border //static inline bool BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags window_flags) { return BeginChild(id, size_arg, border ? ImGuiChildFlags_Border : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Border static inline void ShowStackToolWindow(bool* p_open = NULL) { ShowIDStackToolWindow(p_open); } IMGUI_API bool ListBox(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int height_in_items = -1); IMGUI_API bool Combo(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int popup_max_height_in_items = -1); // OBSOLETED in 1.89.7 (from June 2023) IMGUI_API void SetItemAllowOverlap(); // Use SetNextItemAllowOverlap() before item. // OBSOLETED in 1.89.4 (from March 2023) static inline void PushAllowKeyboardFocus(bool tab_stop) { PushTabStop(tab_stop); } static inline void PopAllowKeyboardFocus() { PopTabStop(); } // OBSOLETED in 1.89 (from August 2022) IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); // Use new ImageButton() signature (explicit item id, regular FramePadding) // OBSOLETED in 1.88 (from May 2022) static inline void CaptureKeyboardFromApp(bool want_capture_keyboard = true) { SetNextFrameWantCaptureKeyboard(want_capture_keyboard); } // Renamed as name was misleading + removed default value. static inline void CaptureMouseFromApp(bool want_capture_mouse = true) { SetNextFrameWantCaptureMouse(want_capture_mouse); } // Renamed as name was misleading + removed default value. // Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE) //-- OBSOLETED in 1.86 (from November 2021) //IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Code removed, see 1.90 for last version of the code. Calculate range of visible items for large list of evenly sized items. Prefer using ImGuiListClipper. //-- OBSOLETED in 1.85 (from August 2021) //static inline float GetWindowContentRegionWidth() { return GetWindowContentRegionMax().x - GetWindowContentRegionMin().x; } //-- OBSOLETED in 1.81 (from February 2021) //static inline bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0, 0)) { return BeginListBox(label, size); } //static inline bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1) { float height = GetTextLineHeightWithSpacing() * ((height_in_items < 0 ? ImMin(items_count, 7) : height_in_items) + 0.25f) + GetStyle().FramePadding.y * 2.0f; return BeginListBox(label, ImVec2(0.0f, height)); } // Helper to calculate size from items_count and height_in_items //static inline void ListBoxFooter() { EndListBox(); } //-- OBSOLETED in 1.79 (from August 2020) //static inline void OpenPopupContextItem(const char* str_id = NULL, ImGuiMouseButton mb = 1) { OpenPopupOnItemClick(str_id, mb); } // Bool return value removed. Use IsWindowAppearing() in BeginPopup() instead. Renamed in 1.77, renamed back in 1.79. Sorry! //-- OBSOLETED in 1.78 (from June 2020): Old drag/sliders functions that took a 'float power > 1.0f' argument instead of ImGuiSliderFlags_Logarithmic. See github.com/ocornut/imgui/issues/3361 for details. //IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, float power = 1.0f) // OBSOLETED in 1.78 (from June 2020) //IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, float power = 1.0f); // OBSOLETED in 1.78 (from June 2020) //IMGUI_API bool SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, float power = 1.0f); // OBSOLETED in 1.78 (from June 2020) //IMGUI_API bool SliderScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_min, const void* p_max, const char* format, float power = 1.0f); // OBSOLETED in 1.78 (from June 2020) //static inline bool DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* format, float power = 1.0f) { return DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, format, power); } // OBSOLETED in 1.78 (from June 2020) //static inline bool DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* format, float power = 1.0f) { return DragScalarN(label, ImGuiDataType_Float, v, 2, v_speed, &v_min, &v_max, format, power); } // OBSOLETED in 1.78 (from June 2020) //static inline bool DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* format, float power = 1.0f) { return DragScalarN(label, ImGuiDataType_Float, v, 3, v_speed, &v_min, &v_max, format, power); } // OBSOLETED in 1.78 (from June 2020) //static inline bool DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* format, float power = 1.0f) { return DragScalarN(label, ImGuiDataType_Float, v, 4, v_speed, &v_min, &v_max, format, power); } // OBSOLETED in 1.78 (from June 2020) //static inline bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, float power = 1.0f) { return SliderScalar(label, ImGuiDataType_Float, v, &v_min, &v_max, format, power); } // OBSOLETED in 1.78 (from June 2020) //static inline bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, float power = 1.0f) { return SliderScalarN(label, ImGuiDataType_Float, v, 2, &v_min, &v_max, format, power); } // OBSOLETED in 1.78 (from June 2020) //static inline bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, float power = 1.0f) { return SliderScalarN(label, ImGuiDataType_Float, v, 3, &v_min, &v_max, format, power); } // OBSOLETED in 1.78 (from June 2020) //static inline bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format, float power = 1.0f) { return SliderScalarN(label, ImGuiDataType_Float, v, 4, &v_min, &v_max, format, power); } // OBSOLETED in 1.78 (from June 2020) //-- OBSOLETED in 1.77 and before //static inline bool BeginPopupContextWindow(const char* str_id, ImGuiMouseButton mb, bool over_items) { return BeginPopupContextWindow(str_id, mb | (over_items ? 0 : ImGuiPopupFlags_NoOpenOverItems)); } // OBSOLETED in 1.77 (from June 2020) //static inline void TreeAdvanceToLabelPos() { SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()); } // OBSOLETED in 1.72 (from July 2019) //static inline void SetNextTreeNodeOpen(bool open, ImGuiCond cond = 0) { SetNextItemOpen(open, cond); } // OBSOLETED in 1.71 (from June 2019) //static inline float GetContentRegionAvailWidth() { return GetContentRegionAvail().x; } // OBSOLETED in 1.70 (from May 2019) //static inline ImDrawList* GetOverlayDrawList() { return GetForegroundDrawList(); } // OBSOLETED in 1.69 (from Mar 2019) //static inline void SetScrollHere(float ratio = 0.5f) { SetScrollHereY(ratio); } // OBSOLETED in 1.66 (from Nov 2018) //static inline bool IsItemDeactivatedAfterChange() { return IsItemDeactivatedAfterEdit(); } // OBSOLETED in 1.63 (from Aug 2018) //-- OBSOLETED in 1.60 and before //static inline bool IsAnyWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_AnyWindow); } // OBSOLETED in 1.60 (from Apr 2018) //static inline bool IsAnyWindowHovered() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } // OBSOLETED in 1.60 (between Dec 2017 and Apr 2018) //static inline void ShowTestWindow() { return ShowDemoWindow(); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017) //static inline bool IsRootWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootWindow); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017) //static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017) //static inline void SetNextWindowContentWidth(float w) { SetNextWindowContentSize(ImVec2(w, 0.0f)); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017) //static inline float GetItemsLineHeightWithSpacing() { return GetFrameHeightWithSpacing(); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017) //IMGUI_API bool Begin(char* name, bool* p_open, ImVec2 size_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags=0); // OBSOLETED in 1.52 (between Aug 2017 and Oct 2017): Equivalent of using SetNextWindowSize(size, ImGuiCond_FirstUseEver) and SetNextWindowBgAlpha(). //static inline bool IsRootWindowOrAnyChildHovered() { return IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); } // OBSOLETED in 1.52 (between Aug 2017 and Oct 2017) //static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } // OBSOLETED in 1.52 (between Aug 2017 and Oct 2017) //static inline void SetNextWindowPosCenter(ImGuiCond c=0) { SetNextWindowPos(GetMainViewport()->GetCenter(), c, ImVec2(0.5f,0.5f)); } // OBSOLETED in 1.52 (between Aug 2017 and Oct 2017) //static inline bool IsItemHoveredRect() { return IsItemHovered(ImGuiHoveredFlags_RectOnly); } // OBSOLETED in 1.51 (between Jun 2017 and Aug 2017) //static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // OBSOLETED in 1.51 (between Jun 2017 and Aug 2017): This was misleading and partly broken. You probably want to use the io.WantCaptureMouse flag instead. //static inline bool IsMouseHoveringAnyWindow() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } // OBSOLETED in 1.51 (between Jun 2017 and Aug 2017) //static inline bool IsMouseHoveringWindow() { return IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); } // OBSOLETED in 1.51 (between Jun 2017 and Aug 2017) //-- OBSOLETED in 1.50 and before //static inline bool CollapsingHeader(char* label, const char* str_id, bool framed = true, bool default_open = false) { return CollapsingHeader(label, (default_open ? (1 << 5) : 0)); } // OBSOLETED in 1.49 //static inline ImFont*GetWindowFont() { return GetFont(); } // OBSOLETED in 1.48 //static inline float GetWindowFontSize() { return GetFontSize(); } // OBSOLETED in 1.48 //static inline void SetScrollPosHere() { SetScrollHere(); } // OBSOLETED in 1.42 } //-- OBSOLETED in 1.82 (from Mars 2021): flags for AddRect(), AddRectFilled(), AddImageRounded(), PathRect() //typedef ImDrawFlags ImDrawCornerFlags; //enum ImDrawCornerFlags_ //{ // ImDrawCornerFlags_None = ImDrawFlags_RoundCornersNone, // Was == 0 prior to 1.82, this is now == ImDrawFlags_RoundCornersNone which is != 0 and not implicit // ImDrawCornerFlags_TopLeft = ImDrawFlags_RoundCornersTopLeft, // Was == 0x01 (1 << 0) prior to 1.82. Order matches ImDrawFlags_NoRoundCorner* flag (we exploit this internally). // ImDrawCornerFlags_TopRight = ImDrawFlags_RoundCornersTopRight, // Was == 0x02 (1 << 1) prior to 1.82. // ImDrawCornerFlags_BotLeft = ImDrawFlags_RoundCornersBottomLeft, // Was == 0x04 (1 << 2) prior to 1.82. // ImDrawCornerFlags_BotRight = ImDrawFlags_RoundCornersBottomRight, // Was == 0x08 (1 << 3) prior to 1.82. // ImDrawCornerFlags_All = ImDrawFlags_RoundCornersAll, // Was == 0x0F prior to 1.82 // ImDrawCornerFlags_Top = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_TopRight, // ImDrawCornerFlags_Bot = ImDrawCornerFlags_BotLeft | ImDrawCornerFlags_BotRight, // ImDrawCornerFlags_Left = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotLeft, // ImDrawCornerFlags_Right = ImDrawCornerFlags_TopRight | ImDrawCornerFlags_BotRight, //}; // RENAMED and MERGED both ImGuiKey_ModXXX and ImGuiModFlags_XXX into ImGuiMod_XXX (from September 2022) // RENAMED ImGuiKeyModFlags -> ImGuiModFlags in 1.88 (from April 2022). Exceptionally commented out ahead of obscolescence schedule to reduce confusion and because they were not meant to be used in the first place. typedef ImGuiKeyChord ImGuiModFlags; // == int. We generally use ImGuiKeyChord to mean "a ImGuiKey or-ed with any number of ImGuiMod_XXX value", but you may store only mods in there. enum ImGuiModFlags_ { ImGuiModFlags_None = 0, ImGuiModFlags_Ctrl = ImGuiMod_Ctrl, ImGuiModFlags_Shift = ImGuiMod_Shift, ImGuiModFlags_Alt = ImGuiMod_Alt, ImGuiModFlags_Super = ImGuiMod_Super }; //typedef ImGuiKeyChord ImGuiKeyModFlags; // == int //enum ImGuiKeyModFlags_ { ImGuiKeyModFlags_None = 0, ImGuiKeyModFlags_Ctrl = ImGuiMod_Ctrl, ImGuiKeyModFlags_Shift = ImGuiMod_Shift, ImGuiKeyModFlags_Alt = ImGuiMod_Alt, ImGuiKeyModFlags_Super = ImGuiMod_Super }; #define IM_OFFSETOF(_TYPE,_MEMBER) offsetof(_TYPE, _MEMBER) // OBSOLETED IN 1.90 (now using C++11 standard version) #endif // #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // RENAMED IMGUI_DISABLE_METRICS_WINDOW > IMGUI_DISABLE_DEBUG_TOOLS in 1.88 (from June 2022) #if defined(IMGUI_DISABLE_METRICS_WINDOW) && !defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS) && !defined(IMGUI_DISABLE_DEBUG_TOOLS) #define IMGUI_DISABLE_DEBUG_TOOLS #endif #if defined(IMGUI_DISABLE_METRICS_WINDOW) && defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS) #error IMGUI_DISABLE_METRICS_WINDOW was renamed to IMGUI_DISABLE_DEBUG_TOOLS, please use new name. #endif //----------------------------------------------------------------------------- #if defined(__clang__) #pragma clang diagnostic pop #elif defined(__GNUC__) #pragma GCC diagnostic pop #endif #ifdef _MSC_VER #pragma warning (pop) #endif // Include imgui_user.h at the end of imgui.h // May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included. #ifdef IMGUI_INCLUDE_IMGUI_USER_H #ifdef IMGUI_USER_H_FILENAME #include IMGUI_USER_H_FILENAME #else #include "imgui_user.h" #endif #endif #endif // #ifndef IMGUI_DISABLE RenderKit-ospray-f2a61c2/apps/common/external/imgui/imgui_draw.cpp000066400000000000000000006576441456566705700254170ustar00rootroot00000000000000// dear imgui, v1.90.3 // (drawing and font code) /* Index of this file: // [SECTION] STB libraries implementation // [SECTION] Style functions // [SECTION] ImDrawList // [SECTION] ImDrawListSplitter // [SECTION] ImDrawData // [SECTION] Helpers ShadeVertsXXX functions // [SECTION] ImFontConfig // [SECTION] ImFontAtlas // [SECTION] ImFontAtlas glyph ranges helpers // [SECTION] ImFontGlyphRangesBuilder // [SECTION] ImFont // [SECTION] ImGui Internal Render Helpers // [SECTION] Decompression code // [SECTION] Default font data (ProggyClean.ttf) */ #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif #include "imgui.h" #ifndef IMGUI_DISABLE #include "imgui_internal.h" #ifdef IMGUI_ENABLE_FREETYPE #include "misc/freetype/imgui_freetype.h" #endif #include // vsnprintf, sscanf, printf // Visual Studio warnings #ifdef _MSC_VER #pragma warning (disable: 4127) // condition expression is constant #pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2). #pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). [MSVC Static Analyzer) #endif // Clang/GCC warnings with -Weverything #if defined(__clang__) #if __has_warning("-Wunknown-warning-option") #pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great! #endif #pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' #pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse. #pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants ok. #pragma clang diagnostic ignored "-Wglobal-constructors" // warning: declaration requires a global destructor // similar to above, not sure what the exact difference is. #pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0 #pragma clang diagnostic ignored "-Wcomma" // warning: possible misuse of comma operator here #pragma clang diagnostic ignored "-Wreserved-id-macro" // warning: macro name is a reserved identifier #pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision #pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter #elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value #pragma GCC diagnostic ignored "-Wstack-protector" // warning: stack protector not protecting local variables: variable length buffer #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #endif //------------------------------------------------------------------------- // [SECTION] STB libraries implementation (for stb_truetype and stb_rect_pack) //------------------------------------------------------------------------- // Compile time options: //#define IMGUI_STB_NAMESPACE ImStb //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION #ifdef IMGUI_STB_NAMESPACE namespace IMGUI_STB_NAMESPACE { #endif #ifdef _MSC_VER #pragma warning (push) #pragma warning (disable: 4456) // declaration of 'xx' hides previous local declaration #pragma warning (disable: 6011) // (stb_rectpack) Dereferencing NULL pointer 'cur->next'. #pragma warning (disable: 6385) // (stb_truetype) Reading invalid data from 'buffer': the readable size is '_Old_3`kernel_width' bytes, but '3' bytes may be read. #pragma warning (disable: 28182) // (stb_rectpack) Dereferencing NULL pointer. 'cur' contains the same NULL value as 'cur->next' did. #endif #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-function" #pragma clang diagnostic ignored "-Wmissing-prototypes" #pragma clang diagnostic ignored "-Wimplicit-fallthrough" #pragma clang diagnostic ignored "-Wcast-qual" // warning: cast from 'const xxxx *' to 'xxx *' drops const qualifier #endif #if defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wtype-limits" // warning: comparison is always true due to limited range of data type [-Wtype-limits] #pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers #endif #ifndef STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds) #ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in another compilation unit #define STBRP_STATIC #define STBRP_ASSERT(x) do { IM_ASSERT(x); } while (0) #define STBRP_SORT ImQsort #define STB_RECT_PACK_IMPLEMENTATION #endif #ifdef IMGUI_STB_RECT_PACK_FILENAME #include IMGUI_STB_RECT_PACK_FILENAME #else #include "imstb_rectpack.h" #endif #endif #ifdef IMGUI_ENABLE_STB_TRUETYPE #ifndef STB_TRUETYPE_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds) #ifndef IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION // in case the user already have an implementation in another compilation unit #define STBTT_malloc(x,u) ((void)(u), IM_ALLOC(x)) #define STBTT_free(x,u) ((void)(u), IM_FREE(x)) #define STBTT_assert(x) do { IM_ASSERT(x); } while(0) #define STBTT_fmod(x,y) ImFmod(x,y) #define STBTT_sqrt(x) ImSqrt(x) #define STBTT_pow(x,y) ImPow(x,y) #define STBTT_fabs(x) ImFabs(x) #define STBTT_ifloor(x) ((int)ImFloor(x)) #define STBTT_iceil(x) ((int)ImCeil(x)) #define STBTT_STATIC #define STB_TRUETYPE_IMPLEMENTATION #else #define STBTT_DEF extern #endif #ifdef IMGUI_STB_TRUETYPE_FILENAME #include IMGUI_STB_TRUETYPE_FILENAME #else #include "imstb_truetype.h" #endif #endif #endif // IMGUI_ENABLE_STB_TRUETYPE #if defined(__GNUC__) #pragma GCC diagnostic pop #endif #if defined(__clang__) #pragma clang diagnostic pop #endif #if defined(_MSC_VER) #pragma warning (pop) #endif #ifdef IMGUI_STB_NAMESPACE } // namespace ImStb using namespace IMGUI_STB_NAMESPACE; #endif //----------------------------------------------------------------------------- // [SECTION] Style functions //----------------------------------------------------------------------------- void ImGui::StyleColorsDark(ImGuiStyle* dst) { ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); ImVec4* colors = style->Colors; colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f); colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f); colors[ImGuiCol_Border] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f); colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_FrameBg] = ImVec4(0.16f, 0.29f, 0.48f, 0.54f); colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); colors[ImGuiCol_TitleBg] = ImVec4(0.04f, 0.04f, 0.04f, 1.00f); colors[ImGuiCol_TitleBgActive] = ImVec4(0.16f, 0.29f, 0.48f, 1.00f); colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f); colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f); colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f); colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f); colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f); colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); colors[ImGuiCol_SliderGrab] = ImVec4(0.24f, 0.52f, 0.88f, 1.00f); colors[ImGuiCol_SliderGrabActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); colors[ImGuiCol_ButtonHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f); colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f); colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f); colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); colors[ImGuiCol_Separator] = colors[ImGuiCol_Border]; colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f); colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f); colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.20f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f); colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered]; colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f); colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f); colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f); colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f); colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); colors[ImGuiCol_TableHeaderBg] = ImVec4(0.19f, 0.19f, 0.20f, 1.00f); colors[ImGuiCol_TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.35f, 1.00f); // Prefer using Alpha=1.0 here colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 1.00f); // Prefer using Alpha=1.0 here colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f); colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); } void ImGui::StyleColorsClassic(ImGuiStyle* dst) { ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); ImVec4* colors = style->Colors; colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.85f); colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_PopupBg] = ImVec4(0.11f, 0.11f, 0.14f, 0.92f); colors[ImGuiCol_Border] = ImVec4(0.50f, 0.50f, 0.50f, 0.50f); colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_FrameBg] = ImVec4(0.43f, 0.43f, 0.43f, 0.39f); colors[ImGuiCol_FrameBgHovered] = ImVec4(0.47f, 0.47f, 0.69f, 0.40f); colors[ImGuiCol_FrameBgActive] = ImVec4(0.42f, 0.41f, 0.64f, 0.69f); colors[ImGuiCol_TitleBg] = ImVec4(0.27f, 0.27f, 0.54f, 0.83f); colors[ImGuiCol_TitleBgActive] = ImVec4(0.32f, 0.32f, 0.63f, 0.87f); colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f); colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.80f); colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.25f, 0.30f, 0.60f); colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f); colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f); colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f); colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f); colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f); colors[ImGuiCol_SliderGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f); colors[ImGuiCol_Button] = ImVec4(0.35f, 0.40f, 0.61f, 0.62f); colors[ImGuiCol_ButtonHovered] = ImVec4(0.40f, 0.48f, 0.71f, 0.79f); colors[ImGuiCol_ButtonActive] = ImVec4(0.46f, 0.54f, 0.80f, 1.00f); colors[ImGuiCol_Header] = ImVec4(0.40f, 0.40f, 0.90f, 0.45f); colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.90f, 0.80f); colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.87f, 0.80f); colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 0.60f); colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.60f, 0.70f, 1.00f); colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.70f, 0.90f, 1.00f); colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.10f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.82f, 1.00f, 0.90f); colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f); colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered]; colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f); colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f); colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f); colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); colors[ImGuiCol_TableHeaderBg] = ImVec4(0.27f, 0.27f, 0.38f, 1.00f); colors[ImGuiCol_TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.45f, 1.00f); // Prefer using Alpha=1.0 here colors[ImGuiCol_TableBorderLight] = ImVec4(0.26f, 0.26f, 0.28f, 1.00f); // Prefer using Alpha=1.0 here colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.07f); colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered]; colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); } // Those light colors are better suited with a thicker font than the default one + FrameBorder void ImGui::StyleColorsLight(ImGuiStyle* dst) { ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); ImVec4* colors = style->Colors; colors[ImGuiCol_Text] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); colors[ImGuiCol_WindowBg] = ImVec4(0.94f, 0.94f, 0.94f, 1.00f); colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_PopupBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.98f); colors[ImGuiCol_Border] = ImVec4(0.00f, 0.00f, 0.00f, 0.30f); colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); colors[ImGuiCol_TitleBg] = ImVec4(0.96f, 0.96f, 0.96f, 1.00f); colors[ImGuiCol_TitleBgActive] = ImVec4(0.82f, 0.82f, 0.82f, 1.00f); colors[ImGuiCol_TitleBgCollapsed] = ImVec4(1.00f, 1.00f, 1.00f, 0.51f); colors[ImGuiCol_MenuBarBg] = ImVec4(0.86f, 0.86f, 0.86f, 1.00f); colors[ImGuiCol_ScrollbarBg] = ImVec4(0.98f, 0.98f, 0.98f, 0.53f); colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.69f, 0.69f, 0.69f, 0.80f); colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.49f, 0.49f, 0.49f, 0.80f); colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.49f, 0.49f, 0.49f, 1.00f); colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); colors[ImGuiCol_SliderGrab] = ImVec4(0.26f, 0.59f, 0.98f, 0.78f); colors[ImGuiCol_SliderGrabActive] = ImVec4(0.46f, 0.54f, 0.80f, 0.60f); colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); colors[ImGuiCol_ButtonHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f); colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f); colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f); colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); colors[ImGuiCol_Separator] = ImVec4(0.39f, 0.39f, 0.39f, 0.62f); colors[ImGuiCol_SeparatorHovered] = ImVec4(0.14f, 0.44f, 0.80f, 0.78f); colors[ImGuiCol_SeparatorActive] = ImVec4(0.14f, 0.44f, 0.80f, 1.00f); colors[ImGuiCol_ResizeGrip] = ImVec4(0.35f, 0.35f, 0.35f, 0.17f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.90f); colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered]; colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f); colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f); colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f); colors[ImGuiCol_PlotLines] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f); colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.45f, 0.00f, 1.00f); colors[ImGuiCol_TableHeaderBg] = ImVec4(0.78f, 0.87f, 0.98f, 1.00f); colors[ImGuiCol_TableBorderStrong] = ImVec4(0.57f, 0.57f, 0.64f, 1.00f); // Prefer using Alpha=1.0 here colors[ImGuiCol_TableBorderLight] = ImVec4(0.68f, 0.68f, 0.74f, 1.00f); // Prefer using Alpha=1.0 here colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_TableRowBgAlt] = ImVec4(0.30f, 0.30f, 0.30f, 0.09f); colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered]; colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.70f, 0.70f, 0.70f, 0.70f); colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.20f); colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); } //----------------------------------------------------------------------------- // [SECTION] ImDrawList //----------------------------------------------------------------------------- ImDrawListSharedData::ImDrawListSharedData() { memset(this, 0, sizeof(*this)); for (int i = 0; i < IM_ARRAYSIZE(ArcFastVtx); i++) { const float a = ((float)i * 2 * IM_PI) / (float)IM_ARRAYSIZE(ArcFastVtx); ArcFastVtx[i] = ImVec2(ImCos(a), ImSin(a)); } ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleSegmentMaxError); } void ImDrawListSharedData::SetCircleTessellationMaxError(float max_error) { if (CircleSegmentMaxError == max_error) return; IM_ASSERT(max_error > 0.0f); CircleSegmentMaxError = max_error; for (int i = 0; i < IM_ARRAYSIZE(CircleSegmentCounts); i++) { const float radius = (float)i; CircleSegmentCounts[i] = (ImU8)((i > 0) ? IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleSegmentMaxError) : IM_DRAWLIST_ARCFAST_SAMPLE_MAX); } ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleSegmentMaxError); } // Initialize before use in a new frame. We always have a command ready in the buffer. void ImDrawList::_ResetForNewFrame() { // Verify that the ImDrawCmd fields we want to memcmp() are contiguous in memory. IM_STATIC_ASSERT(offsetof(ImDrawCmd, ClipRect) == 0); IM_STATIC_ASSERT(offsetof(ImDrawCmd, TextureId) == sizeof(ImVec4)); IM_STATIC_ASSERT(offsetof(ImDrawCmd, VtxOffset) == sizeof(ImVec4) + sizeof(ImTextureID)); if (_Splitter._Count > 1) _Splitter.Merge(this); CmdBuffer.resize(0); IdxBuffer.resize(0); VtxBuffer.resize(0); Flags = _Data->InitialFlags; memset(&_CmdHeader, 0, sizeof(_CmdHeader)); _VtxCurrentIdx = 0; _VtxWritePtr = NULL; _IdxWritePtr = NULL; _ClipRectStack.resize(0); _TextureIdStack.resize(0); _Path.resize(0); _Splitter.Clear(); CmdBuffer.push_back(ImDrawCmd()); _FringeScale = 1.0f; } void ImDrawList::_ClearFreeMemory() { CmdBuffer.clear(); IdxBuffer.clear(); VtxBuffer.clear(); Flags = ImDrawListFlags_None; _VtxCurrentIdx = 0; _VtxWritePtr = NULL; _IdxWritePtr = NULL; _ClipRectStack.clear(); _TextureIdStack.clear(); _Path.clear(); _Splitter.ClearFreeMemory(); } ImDrawList* ImDrawList::CloneOutput() const { ImDrawList* dst = IM_NEW(ImDrawList(_Data)); dst->CmdBuffer = CmdBuffer; dst->IdxBuffer = IdxBuffer; dst->VtxBuffer = VtxBuffer; dst->Flags = Flags; return dst; } void ImDrawList::AddDrawCmd() { ImDrawCmd draw_cmd; draw_cmd.ClipRect = _CmdHeader.ClipRect; // Same as calling ImDrawCmd_HeaderCopy() draw_cmd.TextureId = _CmdHeader.TextureId; draw_cmd.VtxOffset = _CmdHeader.VtxOffset; draw_cmd.IdxOffset = IdxBuffer.Size; IM_ASSERT(draw_cmd.ClipRect.x <= draw_cmd.ClipRect.z && draw_cmd.ClipRect.y <= draw_cmd.ClipRect.w); CmdBuffer.push_back(draw_cmd); } // Pop trailing draw command (used before merging or presenting to user) // Note that this leaves the ImDrawList in a state unfit for further commands, as most code assume that CmdBuffer.Size > 0 && CmdBuffer.back().UserCallback == NULL void ImDrawList::_PopUnusedDrawCmd() { while (CmdBuffer.Size > 0) { ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; if (curr_cmd->ElemCount != 0 || curr_cmd->UserCallback != NULL) return;// break; CmdBuffer.pop_back(); } } void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data) { IM_ASSERT_PARANOID(CmdBuffer.Size > 0); ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; IM_ASSERT(curr_cmd->UserCallback == NULL); if (curr_cmd->ElemCount != 0) { AddDrawCmd(); curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; } curr_cmd->UserCallback = callback; curr_cmd->UserCallbackData = callback_data; AddDrawCmd(); // Force a new command after us (see comment below) } // Compare ClipRect, TextureId and VtxOffset with a single memcmp() #define ImDrawCmd_HeaderSize (offsetof(ImDrawCmd, VtxOffset) + sizeof(unsigned int)) #define ImDrawCmd_HeaderCompare(CMD_LHS, CMD_RHS) (memcmp(CMD_LHS, CMD_RHS, ImDrawCmd_HeaderSize)) // Compare ClipRect, TextureId, VtxOffset #define ImDrawCmd_HeaderCopy(CMD_DST, CMD_SRC) (memcpy(CMD_DST, CMD_SRC, ImDrawCmd_HeaderSize)) // Copy ClipRect, TextureId, VtxOffset #define ImDrawCmd_AreSequentialIdxOffset(CMD_0, CMD_1) (CMD_0->IdxOffset + CMD_0->ElemCount == CMD_1->IdxOffset) // Try to merge two last draw commands void ImDrawList::_TryMergeDrawCmds() { IM_ASSERT_PARANOID(CmdBuffer.Size > 0); ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; ImDrawCmd* prev_cmd = curr_cmd - 1; if (ImDrawCmd_HeaderCompare(curr_cmd, prev_cmd) == 0 && ImDrawCmd_AreSequentialIdxOffset(prev_cmd, curr_cmd) && curr_cmd->UserCallback == NULL && prev_cmd->UserCallback == NULL) { prev_cmd->ElemCount += curr_cmd->ElemCount; CmdBuffer.pop_back(); } } // Our scheme may appears a bit unusual, basically we want the most-common calls AddLine AddRect etc. to not have to perform any check so we always have a command ready in the stack. // The cost of figuring out if a new command has to be added or if we can merge is paid in those Update** functions only. void ImDrawList::_OnChangedClipRect() { // If current command is used with different settings we need to add a new command IM_ASSERT_PARANOID(CmdBuffer.Size > 0); ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; if (curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &_CmdHeader.ClipRect, sizeof(ImVec4)) != 0) { AddDrawCmd(); return; } IM_ASSERT(curr_cmd->UserCallback == NULL); // Try to merge with previous command if it matches, else use current command ImDrawCmd* prev_cmd = curr_cmd - 1; if (curr_cmd->ElemCount == 0 && CmdBuffer.Size > 1 && ImDrawCmd_HeaderCompare(&_CmdHeader, prev_cmd) == 0 && ImDrawCmd_AreSequentialIdxOffset(prev_cmd, curr_cmd) && prev_cmd->UserCallback == NULL) { CmdBuffer.pop_back(); return; } curr_cmd->ClipRect = _CmdHeader.ClipRect; } void ImDrawList::_OnChangedTextureID() { // If current command is used with different settings we need to add a new command IM_ASSERT_PARANOID(CmdBuffer.Size > 0); ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; if (curr_cmd->ElemCount != 0 && curr_cmd->TextureId != _CmdHeader.TextureId) { AddDrawCmd(); return; } IM_ASSERT(curr_cmd->UserCallback == NULL); // Try to merge with previous command if it matches, else use current command ImDrawCmd* prev_cmd = curr_cmd - 1; if (curr_cmd->ElemCount == 0 && CmdBuffer.Size > 1 && ImDrawCmd_HeaderCompare(&_CmdHeader, prev_cmd) == 0 && ImDrawCmd_AreSequentialIdxOffset(prev_cmd, curr_cmd) && prev_cmd->UserCallback == NULL) { CmdBuffer.pop_back(); return; } curr_cmd->TextureId = _CmdHeader.TextureId; } void ImDrawList::_OnChangedVtxOffset() { // We don't need to compare curr_cmd->VtxOffset != _CmdHeader.VtxOffset because we know it'll be different at the time we call this. _VtxCurrentIdx = 0; IM_ASSERT_PARANOID(CmdBuffer.Size > 0); ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; //IM_ASSERT(curr_cmd->VtxOffset != _CmdHeader.VtxOffset); // See #3349 if (curr_cmd->ElemCount != 0) { AddDrawCmd(); return; } IM_ASSERT(curr_cmd->UserCallback == NULL); curr_cmd->VtxOffset = _CmdHeader.VtxOffset; } int ImDrawList::_CalcCircleAutoSegmentCount(float radius) const { // Automatic segment count const int radius_idx = (int)(radius + 0.999999f); // ceil to never reduce accuracy if (radius_idx >= 0 && radius_idx < IM_ARRAYSIZE(_Data->CircleSegmentCounts)) return _Data->CircleSegmentCounts[radius_idx]; // Use cached value else return IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleSegmentMaxError); } // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) void ImDrawList::PushClipRect(const ImVec2& cr_min, const ImVec2& cr_max, bool intersect_with_current_clip_rect) { ImVec4 cr(cr_min.x, cr_min.y, cr_max.x, cr_max.y); if (intersect_with_current_clip_rect) { ImVec4 current = _CmdHeader.ClipRect; if (cr.x < current.x) cr.x = current.x; if (cr.y < current.y) cr.y = current.y; if (cr.z > current.z) cr.z = current.z; if (cr.w > current.w) cr.w = current.w; } cr.z = ImMax(cr.x, cr.z); cr.w = ImMax(cr.y, cr.w); _ClipRectStack.push_back(cr); _CmdHeader.ClipRect = cr; _OnChangedClipRect(); } void ImDrawList::PushClipRectFullScreen() { PushClipRect(ImVec2(_Data->ClipRectFullscreen.x, _Data->ClipRectFullscreen.y), ImVec2(_Data->ClipRectFullscreen.z, _Data->ClipRectFullscreen.w)); } void ImDrawList::PopClipRect() { _ClipRectStack.pop_back(); _CmdHeader.ClipRect = (_ClipRectStack.Size == 0) ? _Data->ClipRectFullscreen : _ClipRectStack.Data[_ClipRectStack.Size - 1]; _OnChangedClipRect(); } void ImDrawList::PushTextureID(ImTextureID texture_id) { _TextureIdStack.push_back(texture_id); _CmdHeader.TextureId = texture_id; _OnChangedTextureID(); } void ImDrawList::PopTextureID() { _TextureIdStack.pop_back(); _CmdHeader.TextureId = (_TextureIdStack.Size == 0) ? (ImTextureID)NULL : _TextureIdStack.Data[_TextureIdStack.Size - 1]; _OnChangedTextureID(); } // Reserve space for a number of vertices and indices. // You must finish filling your reserved data before calling PrimReserve() again, as it may reallocate or // submit the intermediate results. PrimUnreserve() can be used to release unused allocations. void ImDrawList::PrimReserve(int idx_count, int vtx_count) { // Large mesh support (when enabled) IM_ASSERT_PARANOID(idx_count >= 0 && vtx_count >= 0); if (sizeof(ImDrawIdx) == 2 && (_VtxCurrentIdx + vtx_count >= (1 << 16)) && (Flags & ImDrawListFlags_AllowVtxOffset)) { // FIXME: In theory we should be testing that vtx_count <64k here. // In practice, RenderText() relies on reserving ahead for a worst case scenario so it is currently useful for us // to not make that check until we rework the text functions to handle clipping and large horizontal lines better. _CmdHeader.VtxOffset = VtxBuffer.Size; _OnChangedVtxOffset(); } ImDrawCmd* draw_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; draw_cmd->ElemCount += idx_count; int vtx_buffer_old_size = VtxBuffer.Size; VtxBuffer.resize(vtx_buffer_old_size + vtx_count); _VtxWritePtr = VtxBuffer.Data + vtx_buffer_old_size; int idx_buffer_old_size = IdxBuffer.Size; IdxBuffer.resize(idx_buffer_old_size + idx_count); _IdxWritePtr = IdxBuffer.Data + idx_buffer_old_size; } // Release the number of reserved vertices/indices from the end of the last reservation made with PrimReserve(). void ImDrawList::PrimUnreserve(int idx_count, int vtx_count) { IM_ASSERT_PARANOID(idx_count >= 0 && vtx_count >= 0); ImDrawCmd* draw_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1]; draw_cmd->ElemCount -= idx_count; VtxBuffer.shrink(VtxBuffer.Size - vtx_count); IdxBuffer.shrink(IdxBuffer.Size - idx_count); } // Fully unrolled with inline call to keep our debug builds decently fast. void ImDrawList::PrimRect(const ImVec2& a, const ImVec2& c, ImU32 col) { ImVec2 b(c.x, a.y), d(a.x, c.y), uv(_Data->TexUvWhitePixel); ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx; _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2); _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3); _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col; _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv; _VtxWritePtr[2].col = col; _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv; _VtxWritePtr[3].col = col; _VtxWritePtr += 4; _VtxCurrentIdx += 4; _IdxWritePtr += 6; } void ImDrawList::PrimRectUV(const ImVec2& a, const ImVec2& c, const ImVec2& uv_a, const ImVec2& uv_c, ImU32 col) { ImVec2 b(c.x, a.y), d(a.x, c.y), uv_b(uv_c.x, uv_a.y), uv_d(uv_a.x, uv_c.y); ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx; _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2); _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3); _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv_a; _VtxWritePtr[0].col = col; _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv_b; _VtxWritePtr[1].col = col; _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv_c; _VtxWritePtr[2].col = col; _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv_d; _VtxWritePtr[3].col = col; _VtxWritePtr += 4; _VtxCurrentIdx += 4; _IdxWritePtr += 6; } void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col) { ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx; _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2); _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3); _VtxWritePtr[0].pos = a; _VtxWritePtr[0].uv = uv_a; _VtxWritePtr[0].col = col; _VtxWritePtr[1].pos = b; _VtxWritePtr[1].uv = uv_b; _VtxWritePtr[1].col = col; _VtxWritePtr[2].pos = c; _VtxWritePtr[2].uv = uv_c; _VtxWritePtr[2].col = col; _VtxWritePtr[3].pos = d; _VtxWritePtr[3].uv = uv_d; _VtxWritePtr[3].col = col; _VtxWritePtr += 4; _VtxCurrentIdx += 4; _IdxWritePtr += 6; } // On AddPolyline() and AddConvexPolyFilled() we intentionally avoid using ImVec2 and superfluous function calls to optimize debug/non-inlined builds. // - Those macros expects l-values and need to be used as their own statement. // - Those macros are intentionally not surrounded by the 'do {} while (0)' idiom because even that translates to runtime with debug compilers. #define IM_NORMALIZE2F_OVER_ZERO(VX,VY) { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = ImRsqrt(d2); VX *= inv_len; VY *= inv_len; } } (void)0 #define IM_FIXNORMAL2F_MAX_INVLEN2 100.0f // 500.0f (see #4053, #3366) #define IM_FIXNORMAL2F(VX,VY) { float d2 = VX*VX + VY*VY; if (d2 > 0.000001f) { float inv_len2 = 1.0f / d2; if (inv_len2 > IM_FIXNORMAL2F_MAX_INVLEN2) inv_len2 = IM_FIXNORMAL2F_MAX_INVLEN2; VX *= inv_len2; VY *= inv_len2; } } (void)0 // TODO: Thickness anti-aliased lines cap are missing their AA fringe. // We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds. void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, ImDrawFlags flags, float thickness) { if (points_count < 2 || (col & IM_COL32_A_MASK) == 0) return; const bool closed = (flags & ImDrawFlags_Closed) != 0; const ImVec2 opaque_uv = _Data->TexUvWhitePixel; const int count = closed ? points_count : points_count - 1; // The number of line segments we need to draw const bool thick_line = (thickness > _FringeScale); if (Flags & ImDrawListFlags_AntiAliasedLines) { // Anti-aliased stroke const float AA_SIZE = _FringeScale; const ImU32 col_trans = col & ~IM_COL32_A_MASK; // Thicknesses <1.0 should behave like thickness 1.0 thickness = ImMax(thickness, 1.0f); const int integer_thickness = (int)thickness; const float fractional_thickness = thickness - integer_thickness; // Do we want to draw this line using a texture? // - For now, only draw integer-width lines using textures to avoid issues with the way scaling occurs, could be improved. // - If AA_SIZE is not 1.0f we cannot use the texture path. const bool use_texture = (Flags & ImDrawListFlags_AntiAliasedLinesUseTex) && (integer_thickness < IM_DRAWLIST_TEX_LINES_WIDTH_MAX) && (fractional_thickness <= 0.00001f) && (AA_SIZE == 1.0f); // We should never hit this, because NewFrame() doesn't set ImDrawListFlags_AntiAliasedLinesUseTex unless ImFontAtlasFlags_NoBakedLines is off IM_ASSERT_PARANOID(!use_texture || !(_Data->Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedLines)); const int idx_count = use_texture ? (count * 6) : (thick_line ? count * 18 : count * 12); const int vtx_count = use_texture ? (points_count * 2) : (thick_line ? points_count * 4 : points_count * 3); PrimReserve(idx_count, vtx_count); // Temporary buffer // The first items are normals at each line point, then after that there are either 2 or 4 temp points for each line point _Data->TempBuffer.reserve_discard(points_count * ((use_texture || !thick_line) ? 3 : 5)); ImVec2* temp_normals = _Data->TempBuffer.Data; ImVec2* temp_points = temp_normals + points_count; // Calculate normals (tangents) for each line segment for (int i1 = 0; i1 < count; i1++) { const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1; float dx = points[i2].x - points[i1].x; float dy = points[i2].y - points[i1].y; IM_NORMALIZE2F_OVER_ZERO(dx, dy); temp_normals[i1].x = dy; temp_normals[i1].y = -dx; } if (!closed) temp_normals[points_count - 1] = temp_normals[points_count - 2]; // If we are drawing a one-pixel-wide line without a texture, or a textured line of any width, we only need 2 or 3 vertices per point if (use_texture || !thick_line) { // [PATH 1] Texture-based lines (thick or non-thick) // [PATH 2] Non texture-based lines (non-thick) // The width of the geometry we need to draw - this is essentially pixels for the line itself, plus "one pixel" for AA. // - In the texture-based path, we don't use AA_SIZE here because the +1 is tied to the generated texture // (see ImFontAtlasBuildRenderLinesTexData() function), and so alternate values won't work without changes to that code. // - In the non texture-based paths, we would allow AA_SIZE to potentially be != 1.0f with a patch (e.g. fringe_scale patch to // allow scaling geometry while preserving one-screen-pixel AA fringe). const float half_draw_size = use_texture ? ((thickness * 0.5f) + 1) : AA_SIZE; // If line is not closed, the first and last points need to be generated differently as there are no normals to blend if (!closed) { temp_points[0] = points[0] + temp_normals[0] * half_draw_size; temp_points[1] = points[0] - temp_normals[0] * half_draw_size; temp_points[(points_count-1)*2+0] = points[points_count-1] + temp_normals[points_count-1] * half_draw_size; temp_points[(points_count-1)*2+1] = points[points_count-1] - temp_normals[points_count-1] * half_draw_size; } // Generate the indices to form a number of triangles for each line segment, and the vertices for the line edges // This takes points n and n+1 and writes into n+1, with the first point in a closed line being generated from the final one (as n+1 wraps) // FIXME-OPT: Merge the different loops, possibly remove the temporary buffer. unsigned int idx1 = _VtxCurrentIdx; // Vertex index for start of line segment for (int i1 = 0; i1 < count; i1++) // i1 is the first point of the line segment { const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1; // i2 is the second point of the line segment const unsigned int idx2 = ((i1 + 1) == points_count) ? _VtxCurrentIdx : (idx1 + (use_texture ? 2 : 3)); // Vertex index for end of segment // Average normals float dm_x = (temp_normals[i1].x + temp_normals[i2].x) * 0.5f; float dm_y = (temp_normals[i1].y + temp_normals[i2].y) * 0.5f; IM_FIXNORMAL2F(dm_x, dm_y); dm_x *= half_draw_size; // dm_x, dm_y are offset to the outer edge of the AA area dm_y *= half_draw_size; // Add temporary vertexes for the outer edges ImVec2* out_vtx = &temp_points[i2 * 2]; out_vtx[0].x = points[i2].x + dm_x; out_vtx[0].y = points[i2].y + dm_y; out_vtx[1].x = points[i2].x - dm_x; out_vtx[1].y = points[i2].y - dm_y; if (use_texture) { // Add indices for two triangles _IdxWritePtr[0] = (ImDrawIdx)(idx2 + 0); _IdxWritePtr[1] = (ImDrawIdx)(idx1 + 0); _IdxWritePtr[2] = (ImDrawIdx)(idx1 + 1); // Right tri _IdxWritePtr[3] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[4] = (ImDrawIdx)(idx1 + 1); _IdxWritePtr[5] = (ImDrawIdx)(idx2 + 0); // Left tri _IdxWritePtr += 6; } else { // Add indexes for four triangles _IdxWritePtr[0] = (ImDrawIdx)(idx2 + 0); _IdxWritePtr[1] = (ImDrawIdx)(idx1 + 0); _IdxWritePtr[2] = (ImDrawIdx)(idx1 + 2); // Right tri 1 _IdxWritePtr[3] = (ImDrawIdx)(idx1 + 2); _IdxWritePtr[4] = (ImDrawIdx)(idx2 + 2); _IdxWritePtr[5] = (ImDrawIdx)(idx2 + 0); // Right tri 2 _IdxWritePtr[6] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[7] = (ImDrawIdx)(idx1 + 1); _IdxWritePtr[8] = (ImDrawIdx)(idx1 + 0); // Left tri 1 _IdxWritePtr[9] = (ImDrawIdx)(idx1 + 0); _IdxWritePtr[10] = (ImDrawIdx)(idx2 + 0); _IdxWritePtr[11] = (ImDrawIdx)(idx2 + 1); // Left tri 2 _IdxWritePtr += 12; } idx1 = idx2; } // Add vertexes for each point on the line if (use_texture) { // If we're using textures we only need to emit the left/right edge vertices ImVec4 tex_uvs = _Data->TexUvLines[integer_thickness]; /*if (fractional_thickness != 0.0f) // Currently always zero when use_texture==false! { const ImVec4 tex_uvs_1 = _Data->TexUvLines[integer_thickness + 1]; tex_uvs.x = tex_uvs.x + (tex_uvs_1.x - tex_uvs.x) * fractional_thickness; // inlined ImLerp() tex_uvs.y = tex_uvs.y + (tex_uvs_1.y - tex_uvs.y) * fractional_thickness; tex_uvs.z = tex_uvs.z + (tex_uvs_1.z - tex_uvs.z) * fractional_thickness; tex_uvs.w = tex_uvs.w + (tex_uvs_1.w - tex_uvs.w) * fractional_thickness; }*/ ImVec2 tex_uv0(tex_uvs.x, tex_uvs.y); ImVec2 tex_uv1(tex_uvs.z, tex_uvs.w); for (int i = 0; i < points_count; i++) { _VtxWritePtr[0].pos = temp_points[i * 2 + 0]; _VtxWritePtr[0].uv = tex_uv0; _VtxWritePtr[0].col = col; // Left-side outer edge _VtxWritePtr[1].pos = temp_points[i * 2 + 1]; _VtxWritePtr[1].uv = tex_uv1; _VtxWritePtr[1].col = col; // Right-side outer edge _VtxWritePtr += 2; } } else { // If we're not using a texture, we need the center vertex as well for (int i = 0; i < points_count; i++) { _VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col; // Center of line _VtxWritePtr[1].pos = temp_points[i * 2 + 0]; _VtxWritePtr[1].uv = opaque_uv; _VtxWritePtr[1].col = col_trans; // Left-side outer edge _VtxWritePtr[2].pos = temp_points[i * 2 + 1]; _VtxWritePtr[2].uv = opaque_uv; _VtxWritePtr[2].col = col_trans; // Right-side outer edge _VtxWritePtr += 3; } } } else { // [PATH 2] Non texture-based lines (thick): we need to draw the solid line core and thus require four vertices per point const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f; // If line is not closed, the first and last points need to be generated differently as there are no normals to blend if (!closed) { const int points_last = points_count - 1; temp_points[0] = points[0] + temp_normals[0] * (half_inner_thickness + AA_SIZE); temp_points[1] = points[0] + temp_normals[0] * (half_inner_thickness); temp_points[2] = points[0] - temp_normals[0] * (half_inner_thickness); temp_points[3] = points[0] - temp_normals[0] * (half_inner_thickness + AA_SIZE); temp_points[points_last * 4 + 0] = points[points_last] + temp_normals[points_last] * (half_inner_thickness + AA_SIZE); temp_points[points_last * 4 + 1] = points[points_last] + temp_normals[points_last] * (half_inner_thickness); temp_points[points_last * 4 + 2] = points[points_last] - temp_normals[points_last] * (half_inner_thickness); temp_points[points_last * 4 + 3] = points[points_last] - temp_normals[points_last] * (half_inner_thickness + AA_SIZE); } // Generate the indices to form a number of triangles for each line segment, and the vertices for the line edges // This takes points n and n+1 and writes into n+1, with the first point in a closed line being generated from the final one (as n+1 wraps) // FIXME-OPT: Merge the different loops, possibly remove the temporary buffer. unsigned int idx1 = _VtxCurrentIdx; // Vertex index for start of line segment for (int i1 = 0; i1 < count; i1++) // i1 is the first point of the line segment { const int i2 = (i1 + 1) == points_count ? 0 : (i1 + 1); // i2 is the second point of the line segment const unsigned int idx2 = (i1 + 1) == points_count ? _VtxCurrentIdx : (idx1 + 4); // Vertex index for end of segment // Average normals float dm_x = (temp_normals[i1].x + temp_normals[i2].x) * 0.5f; float dm_y = (temp_normals[i1].y + temp_normals[i2].y) * 0.5f; IM_FIXNORMAL2F(dm_x, dm_y); float dm_out_x = dm_x * (half_inner_thickness + AA_SIZE); float dm_out_y = dm_y * (half_inner_thickness + AA_SIZE); float dm_in_x = dm_x * half_inner_thickness; float dm_in_y = dm_y * half_inner_thickness; // Add temporary vertices ImVec2* out_vtx = &temp_points[i2 * 4]; out_vtx[0].x = points[i2].x + dm_out_x; out_vtx[0].y = points[i2].y + dm_out_y; out_vtx[1].x = points[i2].x + dm_in_x; out_vtx[1].y = points[i2].y + dm_in_y; out_vtx[2].x = points[i2].x - dm_in_x; out_vtx[2].y = points[i2].y - dm_in_y; out_vtx[3].x = points[i2].x - dm_out_x; out_vtx[3].y = points[i2].y - dm_out_y; // Add indexes _IdxWritePtr[0] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[1] = (ImDrawIdx)(idx1 + 1); _IdxWritePtr[2] = (ImDrawIdx)(idx1 + 2); _IdxWritePtr[3] = (ImDrawIdx)(idx1 + 2); _IdxWritePtr[4] = (ImDrawIdx)(idx2 + 2); _IdxWritePtr[5] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[6] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[7] = (ImDrawIdx)(idx1 + 1); _IdxWritePtr[8] = (ImDrawIdx)(idx1 + 0); _IdxWritePtr[9] = (ImDrawIdx)(idx1 + 0); _IdxWritePtr[10] = (ImDrawIdx)(idx2 + 0); _IdxWritePtr[11] = (ImDrawIdx)(idx2 + 1); _IdxWritePtr[12] = (ImDrawIdx)(idx2 + 2); _IdxWritePtr[13] = (ImDrawIdx)(idx1 + 2); _IdxWritePtr[14] = (ImDrawIdx)(idx1 + 3); _IdxWritePtr[15] = (ImDrawIdx)(idx1 + 3); _IdxWritePtr[16] = (ImDrawIdx)(idx2 + 3); _IdxWritePtr[17] = (ImDrawIdx)(idx2 + 2); _IdxWritePtr += 18; idx1 = idx2; } // Add vertices for (int i = 0; i < points_count; i++) { _VtxWritePtr[0].pos = temp_points[i * 4 + 0]; _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col_trans; _VtxWritePtr[1].pos = temp_points[i * 4 + 1]; _VtxWritePtr[1].uv = opaque_uv; _VtxWritePtr[1].col = col; _VtxWritePtr[2].pos = temp_points[i * 4 + 2]; _VtxWritePtr[2].uv = opaque_uv; _VtxWritePtr[2].col = col; _VtxWritePtr[3].pos = temp_points[i * 4 + 3]; _VtxWritePtr[3].uv = opaque_uv; _VtxWritePtr[3].col = col_trans; _VtxWritePtr += 4; } } _VtxCurrentIdx += (ImDrawIdx)vtx_count; } else { // [PATH 4] Non texture-based, Non anti-aliased lines const int idx_count = count * 6; const int vtx_count = count * 4; // FIXME-OPT: Not sharing edges PrimReserve(idx_count, vtx_count); for (int i1 = 0; i1 < count; i1++) { const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1; const ImVec2& p1 = points[i1]; const ImVec2& p2 = points[i2]; float dx = p2.x - p1.x; float dy = p2.y - p1.y; IM_NORMALIZE2F_OVER_ZERO(dx, dy); dx *= (thickness * 0.5f); dy *= (thickness * 0.5f); _VtxWritePtr[0].pos.x = p1.x + dy; _VtxWritePtr[0].pos.y = p1.y - dx; _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col; _VtxWritePtr[1].pos.x = p2.x + dy; _VtxWritePtr[1].pos.y = p2.y - dx; _VtxWritePtr[1].uv = opaque_uv; _VtxWritePtr[1].col = col; _VtxWritePtr[2].pos.x = p2.x - dy; _VtxWritePtr[2].pos.y = p2.y + dx; _VtxWritePtr[2].uv = opaque_uv; _VtxWritePtr[2].col = col; _VtxWritePtr[3].pos.x = p1.x - dy; _VtxWritePtr[3].pos.y = p1.y + dx; _VtxWritePtr[3].uv = opaque_uv; _VtxWritePtr[3].col = col; _VtxWritePtr += 4; _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + 1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + 2); _IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx + 2); _IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx + 3); _IdxWritePtr += 6; _VtxCurrentIdx += 4; } } } // - We intentionally avoid using ImVec2 and its math operators here to reduce cost to a minimum for debug/non-inlined builds. // - Filled shapes must always use clockwise winding order. The anti-aliasing fringe depends on it. Counter-clockwise shapes will have "inward" anti-aliasing. void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col) { if (points_count < 3 || (col & IM_COL32_A_MASK) == 0) return; const ImVec2 uv = _Data->TexUvWhitePixel; if (Flags & ImDrawListFlags_AntiAliasedFill) { // Anti-aliased Fill const float AA_SIZE = _FringeScale; const ImU32 col_trans = col & ~IM_COL32_A_MASK; const int idx_count = (points_count - 2)*3 + points_count * 6; const int vtx_count = (points_count * 2); PrimReserve(idx_count, vtx_count); // Add indexes for fill unsigned int vtx_inner_idx = _VtxCurrentIdx; unsigned int vtx_outer_idx = _VtxCurrentIdx + 1; for (int i = 2; i < points_count; i++) { _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + ((i - 1) << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_inner_idx + (i << 1)); _IdxWritePtr += 3; } // Compute normals _Data->TempBuffer.reserve_discard(points_count); ImVec2* temp_normals = _Data->TempBuffer.Data; for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++) { const ImVec2& p0 = points[i0]; const ImVec2& p1 = points[i1]; float dx = p1.x - p0.x; float dy = p1.y - p0.y; IM_NORMALIZE2F_OVER_ZERO(dx, dy); temp_normals[i0].x = dy; temp_normals[i0].y = -dx; } for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++) { // Average normals const ImVec2& n0 = temp_normals[i0]; const ImVec2& n1 = temp_normals[i1]; float dm_x = (n0.x + n1.x) * 0.5f; float dm_y = (n0.y + n1.y) * 0.5f; IM_FIXNORMAL2F(dm_x, dm_y); dm_x *= AA_SIZE * 0.5f; dm_y *= AA_SIZE * 0.5f; // Add vertices _VtxWritePtr[0].pos.x = (points[i1].x - dm_x); _VtxWritePtr[0].pos.y = (points[i1].y - dm_y); _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; // Inner _VtxWritePtr[1].pos.x = (points[i1].x + dm_x); _VtxWritePtr[1].pos.y = (points[i1].y + dm_y); _VtxWritePtr[1].uv = uv; _VtxWritePtr[1].col = col_trans; // Outer _VtxWritePtr += 2; // Add indexes for fringes _IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1)); _IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + (i0 << 1)); _IdxWritePtr[2] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1)); _IdxWritePtr[3] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1)); _IdxWritePtr[4] = (ImDrawIdx)(vtx_outer_idx + (i1 << 1)); _IdxWritePtr[5] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1)); _IdxWritePtr += 6; } _VtxCurrentIdx += (ImDrawIdx)vtx_count; } else { // Non Anti-aliased Fill const int idx_count = (points_count - 2)*3; const int vtx_count = points_count; PrimReserve(idx_count, vtx_count); for (int i = 0; i < vtx_count; i++) { _VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = uv; _VtxWritePtr[0].col = col; _VtxWritePtr++; } for (int i = 2; i < points_count; i++) { _IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + i - 1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + i); _IdxWritePtr += 3; } _VtxCurrentIdx += (ImDrawIdx)vtx_count; } } void ImDrawList::_PathArcToFastEx(const ImVec2& center, float radius, int a_min_sample, int a_max_sample, int a_step) { if (radius < 0.5f) { _Path.push_back(center); return; } // Calculate arc auto segment step size if (a_step <= 0) a_step = IM_DRAWLIST_ARCFAST_SAMPLE_MAX / _CalcCircleAutoSegmentCount(radius); // Make sure we never do steps larger than one quarter of the circle a_step = ImClamp(a_step, 1, IM_DRAWLIST_ARCFAST_TABLE_SIZE / 4); const int sample_range = ImAbs(a_max_sample - a_min_sample); const int a_next_step = a_step; int samples = sample_range + 1; bool extra_max_sample = false; if (a_step > 1) { samples = sample_range / a_step + 1; const int overstep = sample_range % a_step; if (overstep > 0) { extra_max_sample = true; samples++; // When we have overstep to avoid awkwardly looking one long line and one tiny one at the end, // distribute first step range evenly between them by reducing first step size. if (sample_range > 0) a_step -= (a_step - overstep) / 2; } } _Path.resize(_Path.Size + samples); ImVec2* out_ptr = _Path.Data + (_Path.Size - samples); int sample_index = a_min_sample; if (sample_index < 0 || sample_index >= IM_DRAWLIST_ARCFAST_SAMPLE_MAX) { sample_index = sample_index % IM_DRAWLIST_ARCFAST_SAMPLE_MAX; if (sample_index < 0) sample_index += IM_DRAWLIST_ARCFAST_SAMPLE_MAX; } if (a_max_sample >= a_min_sample) { for (int a = a_min_sample; a <= a_max_sample; a += a_step, sample_index += a_step, a_step = a_next_step) { // a_step is clamped to IM_DRAWLIST_ARCFAST_SAMPLE_MAX, so we have guaranteed that it will not wrap over range twice or more if (sample_index >= IM_DRAWLIST_ARCFAST_SAMPLE_MAX) sample_index -= IM_DRAWLIST_ARCFAST_SAMPLE_MAX; const ImVec2 s = _Data->ArcFastVtx[sample_index]; out_ptr->x = center.x + s.x * radius; out_ptr->y = center.y + s.y * radius; out_ptr++; } } else { for (int a = a_min_sample; a >= a_max_sample; a -= a_step, sample_index -= a_step, a_step = a_next_step) { // a_step is clamped to IM_DRAWLIST_ARCFAST_SAMPLE_MAX, so we have guaranteed that it will not wrap over range twice or more if (sample_index < 0) sample_index += IM_DRAWLIST_ARCFAST_SAMPLE_MAX; const ImVec2 s = _Data->ArcFastVtx[sample_index]; out_ptr->x = center.x + s.x * radius; out_ptr->y = center.y + s.y * radius; out_ptr++; } } if (extra_max_sample) { int normalized_max_sample = a_max_sample % IM_DRAWLIST_ARCFAST_SAMPLE_MAX; if (normalized_max_sample < 0) normalized_max_sample += IM_DRAWLIST_ARCFAST_SAMPLE_MAX; const ImVec2 s = _Data->ArcFastVtx[normalized_max_sample]; out_ptr->x = center.x + s.x * radius; out_ptr->y = center.y + s.y * radius; out_ptr++; } IM_ASSERT_PARANOID(_Path.Data + _Path.Size == out_ptr); } void ImDrawList::_PathArcToN(const ImVec2& center, float radius, float a_min, float a_max, int num_segments) { if (radius < 0.5f) { _Path.push_back(center); return; } // Note that we are adding a point at both a_min and a_max. // If you are trying to draw a full closed circle you don't want the overlapping points! _Path.reserve(_Path.Size + (num_segments + 1)); for (int i = 0; i <= num_segments; i++) { const float a = a_min + ((float)i / (float)num_segments) * (a_max - a_min); _Path.push_back(ImVec2(center.x + ImCos(a) * radius, center.y + ImSin(a) * radius)); } } // 0: East, 3: South, 6: West, 9: North, 12: East void ImDrawList::PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12) { if (radius < 0.5f) { _Path.push_back(center); return; } _PathArcToFastEx(center, radius, a_min_of_12 * IM_DRAWLIST_ARCFAST_SAMPLE_MAX / 12, a_max_of_12 * IM_DRAWLIST_ARCFAST_SAMPLE_MAX / 12, 0); } void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments) { if (radius < 0.5f) { _Path.push_back(center); return; } if (num_segments > 0) { _PathArcToN(center, radius, a_min, a_max, num_segments); return; } // Automatic segment count if (radius <= _Data->ArcFastRadiusCutoff) { const bool a_is_reverse = a_max < a_min; // We are going to use precomputed values for mid samples. // Determine first and last sample in lookup table that belong to the arc. const float a_min_sample_f = IM_DRAWLIST_ARCFAST_SAMPLE_MAX * a_min / (IM_PI * 2.0f); const float a_max_sample_f = IM_DRAWLIST_ARCFAST_SAMPLE_MAX * a_max / (IM_PI * 2.0f); const int a_min_sample = a_is_reverse ? (int)ImFloor(a_min_sample_f) : (int)ImCeil(a_min_sample_f); const int a_max_sample = a_is_reverse ? (int)ImCeil(a_max_sample_f) : (int)ImFloor(a_max_sample_f); const int a_mid_samples = a_is_reverse ? ImMax(a_min_sample - a_max_sample, 0) : ImMax(a_max_sample - a_min_sample, 0); const float a_min_segment_angle = a_min_sample * IM_PI * 2.0f / IM_DRAWLIST_ARCFAST_SAMPLE_MAX; const float a_max_segment_angle = a_max_sample * IM_PI * 2.0f / IM_DRAWLIST_ARCFAST_SAMPLE_MAX; const bool a_emit_start = ImAbs(a_min_segment_angle - a_min) >= 1e-5f; const bool a_emit_end = ImAbs(a_max - a_max_segment_angle) >= 1e-5f; _Path.reserve(_Path.Size + (a_mid_samples + 1 + (a_emit_start ? 1 : 0) + (a_emit_end ? 1 : 0))); if (a_emit_start) _Path.push_back(ImVec2(center.x + ImCos(a_min) * radius, center.y + ImSin(a_min) * radius)); if (a_mid_samples > 0) _PathArcToFastEx(center, radius, a_min_sample, a_max_sample, 0); if (a_emit_end) _Path.push_back(ImVec2(center.x + ImCos(a_max) * radius, center.y + ImSin(a_max) * radius)); } else { const float arc_length = ImAbs(a_max - a_min); const int circle_segment_count = _CalcCircleAutoSegmentCount(radius); const int arc_segment_count = ImMax((int)ImCeil(circle_segment_count * arc_length / (IM_PI * 2.0f)), (int)(2.0f * IM_PI / arc_length)); _PathArcToN(center, radius, a_min, a_max, arc_segment_count); } } void ImDrawList::PathEllipticalArcTo(const ImVec2& center, float radius_x, float radius_y, float rot, float a_min, float a_max, int num_segments) { if (num_segments <= 0) num_segments = _CalcCircleAutoSegmentCount(ImMax(radius_x, radius_y)); // A bit pessimistic, maybe there's a better computation to do here. _Path.reserve(_Path.Size + (num_segments + 1)); const float cos_rot = ImCos(rot); const float sin_rot = ImSin(rot); for (int i = 0; i <= num_segments; i++) { const float a = a_min + ((float)i / (float)num_segments) * (a_max - a_min); ImVec2 point(ImCos(a) * radius_x, ImSin(a) * radius_y); const float rel_x = (point.x * cos_rot) - (point.y * sin_rot); const float rel_y = (point.x * sin_rot) + (point.y * cos_rot); point.x = rel_x + center.x; point.y = rel_y + center.y; _Path.push_back(point); } } ImVec2 ImBezierCubicCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, float t) { float u = 1.0f - t; float w1 = u * u * u; float w2 = 3 * u * u * t; float w3 = 3 * u * t * t; float w4 = t * t * t; return ImVec2(w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x, w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y); } ImVec2 ImBezierQuadraticCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, float t) { float u = 1.0f - t; float w1 = u * u; float w2 = 2 * u * t; float w3 = t * t; return ImVec2(w1 * p1.x + w2 * p2.x + w3 * p3.x, w1 * p1.y + w2 * p2.y + w3 * p3.y); } // Closely mimics ImBezierCubicClosestPointCasteljau() in imgui.cpp static void PathBezierCubicCurveToCasteljau(ImVector* path, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float tess_tol, int level) { float dx = x4 - x1; float dy = y4 - y1; float d2 = (x2 - x4) * dy - (y2 - y4) * dx; float d3 = (x3 - x4) * dy - (y3 - y4) * dx; d2 = (d2 >= 0) ? d2 : -d2; d3 = (d3 >= 0) ? d3 : -d3; if ((d2 + d3) * (d2 + d3) < tess_tol * (dx * dx + dy * dy)) { path->push_back(ImVec2(x4, y4)); } else if (level < 10) { float x12 = (x1 + x2) * 0.5f, y12 = (y1 + y2) * 0.5f; float x23 = (x2 + x3) * 0.5f, y23 = (y2 + y3) * 0.5f; float x34 = (x3 + x4) * 0.5f, y34 = (y3 + y4) * 0.5f; float x123 = (x12 + x23) * 0.5f, y123 = (y12 + y23) * 0.5f; float x234 = (x23 + x34) * 0.5f, y234 = (y23 + y34) * 0.5f; float x1234 = (x123 + x234) * 0.5f, y1234 = (y123 + y234) * 0.5f; PathBezierCubicCurveToCasteljau(path, x1, y1, x12, y12, x123, y123, x1234, y1234, tess_tol, level + 1); PathBezierCubicCurveToCasteljau(path, x1234, y1234, x234, y234, x34, y34, x4, y4, tess_tol, level + 1); } } static void PathBezierQuadraticCurveToCasteljau(ImVector* path, float x1, float y1, float x2, float y2, float x3, float y3, float tess_tol, int level) { float dx = x3 - x1, dy = y3 - y1; float det = (x2 - x3) * dy - (y2 - y3) * dx; if (det * det * 4.0f < tess_tol * (dx * dx + dy * dy)) { path->push_back(ImVec2(x3, y3)); } else if (level < 10) { float x12 = (x1 + x2) * 0.5f, y12 = (y1 + y2) * 0.5f; float x23 = (x2 + x3) * 0.5f, y23 = (y2 + y3) * 0.5f; float x123 = (x12 + x23) * 0.5f, y123 = (y12 + y23) * 0.5f; PathBezierQuadraticCurveToCasteljau(path, x1, y1, x12, y12, x123, y123, tess_tol, level + 1); PathBezierQuadraticCurveToCasteljau(path, x123, y123, x23, y23, x3, y3, tess_tol, level + 1); } } void ImDrawList::PathBezierCubicCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments) { ImVec2 p1 = _Path.back(); if (num_segments == 0) { IM_ASSERT(_Data->CurveTessellationTol > 0.0f); PathBezierCubicCurveToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, _Data->CurveTessellationTol, 0); // Auto-tessellated } else { float t_step = 1.0f / (float)num_segments; for (int i_step = 1; i_step <= num_segments; i_step++) _Path.push_back(ImBezierCubicCalc(p1, p2, p3, p4, t_step * i_step)); } } void ImDrawList::PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3, int num_segments) { ImVec2 p1 = _Path.back(); if (num_segments == 0) { IM_ASSERT(_Data->CurveTessellationTol > 0.0f); PathBezierQuadraticCurveToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, _Data->CurveTessellationTol, 0);// Auto-tessellated } else { float t_step = 1.0f / (float)num_segments; for (int i_step = 1; i_step <= num_segments; i_step++) _Path.push_back(ImBezierQuadraticCalc(p1, p2, p3, t_step * i_step)); } } static inline ImDrawFlags FixRectCornerFlags(ImDrawFlags flags) { /* IM_STATIC_ASSERT(ImDrawFlags_RoundCornersTopLeft == (1 << 4)); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // Obsoleted in 1.82 (from February 2021). This code was stripped/simplified and mostly commented in 1.90 (from September 2023) // - Legacy Support for hard coded ~0 (used to be a suggested equivalent to ImDrawCornerFlags_All) if (flags == ~0) { return ImDrawFlags_RoundCornersAll; } // - Legacy Support for hard coded 0x01 to 0x0F (matching 15 out of 16 old flags combinations). Read details in older version of this code. if (flags >= 0x01 && flags <= 0x0F) { return (flags << 4); } // We cannot support hard coded 0x00 with 'float rounding > 0.0f' --> replace with ImDrawFlags_RoundCornersNone or use 'float rounding = 0.0f' #endif */ // If this assert triggers, please update your code replacing hardcoded values with new ImDrawFlags_RoundCorners* values. // Note that ImDrawFlags_Closed (== 0x01) is an invalid flag for AddRect(), AddRectFilled(), PathRect() etc. anyway. // See details in 1.82 Changelog as well as 2021/03/12 and 2023/09/08 entries in "API BREAKING CHANGES" section. IM_ASSERT((flags & 0x0F) == 0 && "Misuse of legacy hardcoded ImDrawCornerFlags values!"); if ((flags & ImDrawFlags_RoundCornersMask_) == 0) flags |= ImDrawFlags_RoundCornersAll; return flags; } void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDrawFlags flags) { if (rounding >= 0.5f) { flags = FixRectCornerFlags(flags); rounding = ImMin(rounding, ImFabs(b.x - a.x) * (((flags & ImDrawFlags_RoundCornersTop) == ImDrawFlags_RoundCornersTop) || ((flags & ImDrawFlags_RoundCornersBottom) == ImDrawFlags_RoundCornersBottom) ? 0.5f : 1.0f) - 1.0f); rounding = ImMin(rounding, ImFabs(b.y - a.y) * (((flags & ImDrawFlags_RoundCornersLeft) == ImDrawFlags_RoundCornersLeft) || ((flags & ImDrawFlags_RoundCornersRight) == ImDrawFlags_RoundCornersRight) ? 0.5f : 1.0f) - 1.0f); } if (rounding < 0.5f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone) { PathLineTo(a); PathLineTo(ImVec2(b.x, a.y)); PathLineTo(b); PathLineTo(ImVec2(a.x, b.y)); } else { const float rounding_tl = (flags & ImDrawFlags_RoundCornersTopLeft) ? rounding : 0.0f; const float rounding_tr = (flags & ImDrawFlags_RoundCornersTopRight) ? rounding : 0.0f; const float rounding_br = (flags & ImDrawFlags_RoundCornersBottomRight) ? rounding : 0.0f; const float rounding_bl = (flags & ImDrawFlags_RoundCornersBottomLeft) ? rounding : 0.0f; PathArcToFast(ImVec2(a.x + rounding_tl, a.y + rounding_tl), rounding_tl, 6, 9); PathArcToFast(ImVec2(b.x - rounding_tr, a.y + rounding_tr), rounding_tr, 9, 12); PathArcToFast(ImVec2(b.x - rounding_br, b.y - rounding_br), rounding_br, 0, 3); PathArcToFast(ImVec2(a.x + rounding_bl, b.y - rounding_bl), rounding_bl, 3, 6); } } void ImDrawList::AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness) { if ((col & IM_COL32_A_MASK) == 0) return; PathLineTo(p1 + ImVec2(0.5f, 0.5f)); PathLineTo(p2 + ImVec2(0.5f, 0.5f)); PathStroke(col, 0, thickness); } // p_min = upper-left, p_max = lower-right // Note we don't render 1 pixels sized rectangles properly. void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags, float thickness) { if ((col & IM_COL32_A_MASK) == 0) return; if (Flags & ImDrawListFlags_AntiAliasedLines) PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.50f, 0.50f), rounding, flags); else PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.49f, 0.49f), rounding, flags); // Better looking lower-right corner and rounded non-AA shapes. PathStroke(col, ImDrawFlags_Closed, thickness); } void ImDrawList::AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags) { if ((col & IM_COL32_A_MASK) == 0) return; if (rounding < 0.5f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone) { PrimReserve(6, 4); PrimRect(p_min, p_max, col); } else { PathRect(p_min, p_max, rounding, flags); PathFillConvex(col); } } // p_min = upper-left, p_max = lower-right void ImDrawList::AddRectFilledMultiColor(const ImVec2& p_min, const ImVec2& p_max, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left) { if (((col_upr_left | col_upr_right | col_bot_right | col_bot_left) & IM_COL32_A_MASK) == 0) return; const ImVec2 uv = _Data->TexUvWhitePixel; PrimReserve(6, 4); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 1)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 2)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 2)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 3)); PrimWriteVtx(p_min, uv, col_upr_left); PrimWriteVtx(ImVec2(p_max.x, p_min.y), uv, col_upr_right); PrimWriteVtx(p_max, uv, col_bot_right); PrimWriteVtx(ImVec2(p_min.x, p_max.y), uv, col_bot_left); } void ImDrawList::AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness) { if ((col & IM_COL32_A_MASK) == 0) return; PathLineTo(p1); PathLineTo(p2); PathLineTo(p3); PathLineTo(p4); PathStroke(col, ImDrawFlags_Closed, thickness); } void ImDrawList::AddQuadFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col) { if ((col & IM_COL32_A_MASK) == 0) return; PathLineTo(p1); PathLineTo(p2); PathLineTo(p3); PathLineTo(p4); PathFillConvex(col); } void ImDrawList::AddTriangle(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness) { if ((col & IM_COL32_A_MASK) == 0) return; PathLineTo(p1); PathLineTo(p2); PathLineTo(p3); PathStroke(col, ImDrawFlags_Closed, thickness); } void ImDrawList::AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col) { if ((col & IM_COL32_A_MASK) == 0) return; PathLineTo(p1); PathLineTo(p2); PathLineTo(p3); PathFillConvex(col); } void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness) { if ((col & IM_COL32_A_MASK) == 0 || radius < 0.5f) return; if (num_segments <= 0) { // Use arc with automatic segment count _PathArcToFastEx(center, radius - 0.5f, 0, IM_DRAWLIST_ARCFAST_SAMPLE_MAX, 0); _Path.Size--; } else { // Explicit segment count (still clamp to avoid drawing insanely tessellated shapes) num_segments = ImClamp(num_segments, 3, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX); // Because we are filling a closed shape we remove 1 from the count of segments/points const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1); } PathStroke(col, ImDrawFlags_Closed, thickness); } void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments) { if ((col & IM_COL32_A_MASK) == 0 || radius < 0.5f) return; if (num_segments <= 0) { // Use arc with automatic segment count _PathArcToFastEx(center, radius, 0, IM_DRAWLIST_ARCFAST_SAMPLE_MAX, 0); _Path.Size--; } else { // Explicit segment count (still clamp to avoid drawing insanely tessellated shapes) num_segments = ImClamp(num_segments, 3, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX); // Because we are filling a closed shape we remove 1 from the count of segments/points const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; PathArcTo(center, radius, 0.0f, a_max, num_segments - 1); } PathFillConvex(col); } // Guaranteed to honor 'num_segments' void ImDrawList::AddNgon(const ImVec2& center, float radius, ImU32 col, int num_segments, float thickness) { if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2) return; // Because we are filling a closed shape we remove 1 from the count of segments/points const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1); PathStroke(col, ImDrawFlags_Closed, thickness); } // Guaranteed to honor 'num_segments' void ImDrawList::AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments) { if ((col & IM_COL32_A_MASK) == 0 || num_segments <= 2) return; // Because we are filling a closed shape we remove 1 from the count of segments/points const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments; PathArcTo(center, radius, 0.0f, a_max, num_segments - 1); PathFillConvex(col); } // Ellipse void ImDrawList::AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot, int num_segments, float thickness) { if ((col & IM_COL32_A_MASK) == 0) return; if (num_segments <= 0) num_segments = _CalcCircleAutoSegmentCount(ImMax(radius_x, radius_y)); // A bit pessimistic, maybe there's a better computation to do here. // Because we are filling a closed shape we remove 1 from the count of segments/points const float a_max = IM_PI * 2.0f * ((float)num_segments - 1.0f) / (float)num_segments; PathEllipticalArcTo(center, radius_x, radius_y, rot, 0.0f, a_max, num_segments - 1); PathStroke(col, true, thickness); } void ImDrawList::AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot, int num_segments) { if ((col & IM_COL32_A_MASK) == 0) return; if (num_segments <= 0) num_segments = _CalcCircleAutoSegmentCount(ImMax(radius_x, radius_y)); // A bit pessimistic, maybe there's a better computation to do here. // Because we are filling a closed shape we remove 1 from the count of segments/points const float a_max = IM_PI * 2.0f * ((float)num_segments - 1.0f) / (float)num_segments; PathEllipticalArcTo(center, radius_x, radius_y, rot, 0.0f, a_max, num_segments - 1); PathFillConvex(col); } // Cubic Bezier takes 4 controls points void ImDrawList::AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments) { if ((col & IM_COL32_A_MASK) == 0) return; PathLineTo(p1); PathBezierCubicCurveTo(p2, p3, p4, num_segments); PathStroke(col, 0, thickness); } // Quadratic Bezier takes 3 controls points void ImDrawList::AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col, float thickness, int num_segments) { if ((col & IM_COL32_A_MASK) == 0) return; PathLineTo(p1); PathBezierQuadraticCurveTo(p2, p3, num_segments); PathStroke(col, 0, thickness); } void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect) { if ((col & IM_COL32_A_MASK) == 0) return; if (text_end == NULL) text_end = text_begin + strlen(text_begin); if (text_begin == text_end) return; // Pull default font/size from the shared ImDrawListSharedData instance if (font == NULL) font = _Data->Font; if (font_size == 0.0f) font_size = _Data->FontSize; IM_ASSERT(font->ContainerAtlas->TexID == _CmdHeader.TextureId); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font. ImVec4 clip_rect = _CmdHeader.ClipRect; if (cpu_fine_clip_rect) { clip_rect.x = ImMax(clip_rect.x, cpu_fine_clip_rect->x); clip_rect.y = ImMax(clip_rect.y, cpu_fine_clip_rect->y); clip_rect.z = ImMin(clip_rect.z, cpu_fine_clip_rect->z); clip_rect.w = ImMin(clip_rect.w, cpu_fine_clip_rect->w); } font->RenderText(this, font_size, pos, col, clip_rect, text_begin, text_end, wrap_width, cpu_fine_clip_rect != NULL); } void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end) { AddText(NULL, 0.0f, pos, col, text_begin, text_end); } void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col) { if ((col & IM_COL32_A_MASK) == 0) return; const bool push_texture_id = user_texture_id != _CmdHeader.TextureId; if (push_texture_id) PushTextureID(user_texture_id); PrimReserve(6, 4); PrimRectUV(p_min, p_max, uv_min, uv_max, col); if (push_texture_id) PopTextureID(); } void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& uv1, const ImVec2& uv2, const ImVec2& uv3, const ImVec2& uv4, ImU32 col) { if ((col & IM_COL32_A_MASK) == 0) return; const bool push_texture_id = user_texture_id != _CmdHeader.TextureId; if (push_texture_id) PushTextureID(user_texture_id); PrimReserve(6, 4); PrimQuadUV(p1, p2, p3, p4, uv1, uv2, uv3, uv4, col); if (push_texture_id) PopTextureID(); } void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_min, const ImVec2& p_max, const ImVec2& uv_min, const ImVec2& uv_max, ImU32 col, float rounding, ImDrawFlags flags) { if ((col & IM_COL32_A_MASK) == 0) return; flags = FixRectCornerFlags(flags); if (rounding < 0.5f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone) { AddImage(user_texture_id, p_min, p_max, uv_min, uv_max, col); return; } const bool push_texture_id = user_texture_id != _CmdHeader.TextureId; if (push_texture_id) PushTextureID(user_texture_id); int vert_start_idx = VtxBuffer.Size; PathRect(p_min, p_max, rounding, flags); PathFillConvex(col); int vert_end_idx = VtxBuffer.Size; ImGui::ShadeVertsLinearUV(this, vert_start_idx, vert_end_idx, p_min, p_max, uv_min, uv_max, true); if (push_texture_id) PopTextureID(); } //----------------------------------------------------------------------------- // [SECTION] ImDrawListSplitter //----------------------------------------------------------------------------- // FIXME: This may be a little confusing, trying to be a little too low-level/optimal instead of just doing vector swap.. //----------------------------------------------------------------------------- void ImDrawListSplitter::ClearFreeMemory() { for (int i = 0; i < _Channels.Size; i++) { if (i == _Current) memset(&_Channels[i], 0, sizeof(_Channels[i])); // Current channel is a copy of CmdBuffer/IdxBuffer, don't destruct again _Channels[i]._CmdBuffer.clear(); _Channels[i]._IdxBuffer.clear(); } _Current = 0; _Count = 1; _Channels.clear(); } void ImDrawListSplitter::Split(ImDrawList* draw_list, int channels_count) { IM_UNUSED(draw_list); IM_ASSERT(_Current == 0 && _Count <= 1 && "Nested channel splitting is not supported. Please use separate instances of ImDrawListSplitter."); int old_channels_count = _Channels.Size; if (old_channels_count < channels_count) { _Channels.reserve(channels_count); // Avoid over reserving since this is likely to stay stable _Channels.resize(channels_count); } _Count = channels_count; // Channels[] (24/32 bytes each) hold storage that we'll swap with draw_list->_CmdBuffer/_IdxBuffer // The content of Channels[0] at this point doesn't matter. We clear it to make state tidy in a debugger but we don't strictly need to. // When we switch to the next channel, we'll copy draw_list->_CmdBuffer/_IdxBuffer into Channels[0] and then Channels[1] into draw_list->CmdBuffer/_IdxBuffer memset(&_Channels[0], 0, sizeof(ImDrawChannel)); for (int i = 1; i < channels_count; i++) { if (i >= old_channels_count) { IM_PLACEMENT_NEW(&_Channels[i]) ImDrawChannel(); } else { _Channels[i]._CmdBuffer.resize(0); _Channels[i]._IdxBuffer.resize(0); } } } void ImDrawListSplitter::Merge(ImDrawList* draw_list) { // Note that we never use or rely on _Channels.Size because it is merely a buffer that we never shrink back to 0 to keep all sub-buffers ready for use. if (_Count <= 1) return; SetCurrentChannel(draw_list, 0); draw_list->_PopUnusedDrawCmd(); // Calculate our final buffer sizes. Also fix the incorrect IdxOffset values in each command. int new_cmd_buffer_count = 0; int new_idx_buffer_count = 0; ImDrawCmd* last_cmd = (_Count > 0 && draw_list->CmdBuffer.Size > 0) ? &draw_list->CmdBuffer.back() : NULL; int idx_offset = last_cmd ? last_cmd->IdxOffset + last_cmd->ElemCount : 0; for (int i = 1; i < _Count; i++) { ImDrawChannel& ch = _Channels[i]; if (ch._CmdBuffer.Size > 0 && ch._CmdBuffer.back().ElemCount == 0 && ch._CmdBuffer.back().UserCallback == NULL) // Equivalent of PopUnusedDrawCmd() ch._CmdBuffer.pop_back(); if (ch._CmdBuffer.Size > 0 && last_cmd != NULL) { // Do not include ImDrawCmd_AreSequentialIdxOffset() in the compare as we rebuild IdxOffset values ourselves. // Manipulating IdxOffset (e.g. by reordering draw commands like done by RenderDimmedBackgroundBehindWindow()) is not supported within a splitter. ImDrawCmd* next_cmd = &ch._CmdBuffer[0]; if (ImDrawCmd_HeaderCompare(last_cmd, next_cmd) == 0 && last_cmd->UserCallback == NULL && next_cmd->UserCallback == NULL) { // Merge previous channel last draw command with current channel first draw command if matching. last_cmd->ElemCount += next_cmd->ElemCount; idx_offset += next_cmd->ElemCount; ch._CmdBuffer.erase(ch._CmdBuffer.Data); // FIXME-OPT: Improve for multiple merges. } } if (ch._CmdBuffer.Size > 0) last_cmd = &ch._CmdBuffer.back(); new_cmd_buffer_count += ch._CmdBuffer.Size; new_idx_buffer_count += ch._IdxBuffer.Size; for (int cmd_n = 0; cmd_n < ch._CmdBuffer.Size; cmd_n++) { ch._CmdBuffer.Data[cmd_n].IdxOffset = idx_offset; idx_offset += ch._CmdBuffer.Data[cmd_n].ElemCount; } } draw_list->CmdBuffer.resize(draw_list->CmdBuffer.Size + new_cmd_buffer_count); draw_list->IdxBuffer.resize(draw_list->IdxBuffer.Size + new_idx_buffer_count); // Write commands and indices in order (they are fairly small structures, we don't copy vertices only indices) ImDrawCmd* cmd_write = draw_list->CmdBuffer.Data + draw_list->CmdBuffer.Size - new_cmd_buffer_count; ImDrawIdx* idx_write = draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size - new_idx_buffer_count; for (int i = 1; i < _Count; i++) { ImDrawChannel& ch = _Channels[i]; if (int sz = ch._CmdBuffer.Size) { memcpy(cmd_write, ch._CmdBuffer.Data, sz * sizeof(ImDrawCmd)); cmd_write += sz; } if (int sz = ch._IdxBuffer.Size) { memcpy(idx_write, ch._IdxBuffer.Data, sz * sizeof(ImDrawIdx)); idx_write += sz; } } draw_list->_IdxWritePtr = idx_write; // Ensure there's always a non-callback draw command trailing the command-buffer if (draw_list->CmdBuffer.Size == 0 || draw_list->CmdBuffer.back().UserCallback != NULL) draw_list->AddDrawCmd(); // If current command is used with different settings we need to add a new command ImDrawCmd* curr_cmd = &draw_list->CmdBuffer.Data[draw_list->CmdBuffer.Size - 1]; if (curr_cmd->ElemCount == 0) ImDrawCmd_HeaderCopy(curr_cmd, &draw_list->_CmdHeader); // Copy ClipRect, TextureId, VtxOffset else if (ImDrawCmd_HeaderCompare(curr_cmd, &draw_list->_CmdHeader) != 0) draw_list->AddDrawCmd(); _Count = 1; } void ImDrawListSplitter::SetCurrentChannel(ImDrawList* draw_list, int idx) { IM_ASSERT(idx >= 0 && idx < _Count); if (_Current == idx) return; // Overwrite ImVector (12/16 bytes), four times. This is merely a silly optimization instead of doing .swap() memcpy(&_Channels.Data[_Current]._CmdBuffer, &draw_list->CmdBuffer, sizeof(draw_list->CmdBuffer)); memcpy(&_Channels.Data[_Current]._IdxBuffer, &draw_list->IdxBuffer, sizeof(draw_list->IdxBuffer)); _Current = idx; memcpy(&draw_list->CmdBuffer, &_Channels.Data[idx]._CmdBuffer, sizeof(draw_list->CmdBuffer)); memcpy(&draw_list->IdxBuffer, &_Channels.Data[idx]._IdxBuffer, sizeof(draw_list->IdxBuffer)); draw_list->_IdxWritePtr = draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size; // If current command is used with different settings we need to add a new command ImDrawCmd* curr_cmd = (draw_list->CmdBuffer.Size == 0) ? NULL : &draw_list->CmdBuffer.Data[draw_list->CmdBuffer.Size - 1]; if (curr_cmd == NULL) draw_list->AddDrawCmd(); else if (curr_cmd->ElemCount == 0) ImDrawCmd_HeaderCopy(curr_cmd, &draw_list->_CmdHeader); // Copy ClipRect, TextureId, VtxOffset else if (ImDrawCmd_HeaderCompare(curr_cmd, &draw_list->_CmdHeader) != 0) draw_list->AddDrawCmd(); } //----------------------------------------------------------------------------- // [SECTION] ImDrawData //----------------------------------------------------------------------------- void ImDrawData::Clear() { Valid = false; CmdListsCount = TotalIdxCount = TotalVtxCount = 0; CmdLists.resize(0); // The ImDrawList are NOT owned by ImDrawData but e.g. by ImGuiContext, so we don't clear them. DisplayPos = DisplaySize = FramebufferScale = ImVec2(0.0f, 0.0f); OwnerViewport = NULL; } // Important: 'out_list' is generally going to be draw_data->CmdLists, but may be another temporary list // as long at it is expected that the result will be later merged into draw_data->CmdLists[]. void ImGui::AddDrawListToDrawDataEx(ImDrawData* draw_data, ImVector* out_list, ImDrawList* draw_list) { if (draw_list->CmdBuffer.Size == 0) return; if (draw_list->CmdBuffer.Size == 1 && draw_list->CmdBuffer[0].ElemCount == 0 && draw_list->CmdBuffer[0].UserCallback == NULL) return; // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. // May trigger for you if you are using PrimXXX functions incorrectly. IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size); IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size); if (!(draw_list->Flags & ImDrawListFlags_AllowVtxOffset)) IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window) // If this assert triggers because you are drawing lots of stuff manually: // - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds. // Be mindful that the lower-level ImDrawList API doesn't filter vertices. Use the Metrics/Debugger window to inspect draw list contents. // - If you want large meshes with more than 64K vertices, you can either: // (A) Handle the ImDrawCmd::VtxOffset value in your renderer backend, and set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset'. // Most example backends already support this from 1.71. Pre-1.71 backends won't. // Some graphics API such as GL ES 1/2 don't have a way to offset the starting vertex so it is not supported for them. // (B) Or handle 32-bit indices in your renderer backend, and uncomment '#define ImDrawIdx unsigned int' line in imconfig.h. // Most example backends already support this. For example, the OpenGL example code detect index size at compile-time: // glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); // Your own engine or render API may use different parameters or function calls to specify index sizes. // 2 and 4 bytes indices are generally supported by most graphics API. // - If for some reason neither of those solutions works for you, a workaround is to call BeginChild()/EndChild() before reaching // the 64K limit to split your draw commands in multiple draw lists. if (sizeof(ImDrawIdx) == 2) IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above"); // Add to output list + records state in ImDrawData out_list->push_back(draw_list); draw_data->CmdListsCount++; draw_data->TotalVtxCount += draw_list->VtxBuffer.Size; draw_data->TotalIdxCount += draw_list->IdxBuffer.Size; } void ImDrawData::AddDrawList(ImDrawList* draw_list) { IM_ASSERT(CmdLists.Size == CmdListsCount); draw_list->_PopUnusedDrawCmd(); ImGui::AddDrawListToDrawDataEx(this, &CmdLists, draw_list); } // For backward compatibility: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering! void ImDrawData::DeIndexAllBuffers() { ImVector new_vtx_buffer; TotalVtxCount = TotalIdxCount = 0; for (int i = 0; i < CmdListsCount; i++) { ImDrawList* cmd_list = CmdLists[i]; if (cmd_list->IdxBuffer.empty()) continue; new_vtx_buffer.resize(cmd_list->IdxBuffer.Size); for (int j = 0; j < cmd_list->IdxBuffer.Size; j++) new_vtx_buffer[j] = cmd_list->VtxBuffer[cmd_list->IdxBuffer[j]]; cmd_list->VtxBuffer.swap(new_vtx_buffer); cmd_list->IdxBuffer.resize(0); TotalVtxCount += cmd_list->VtxBuffer.Size; } } // Helper to scale the ClipRect field of each ImDrawCmd. // Use if your final output buffer is at a different scale than draw_data->DisplaySize, // or if there is a difference between your window resolution and framebuffer resolution. void ImDrawData::ScaleClipRects(const ImVec2& fb_scale) { for (ImDrawList* draw_list : CmdLists) for (ImDrawCmd& cmd : draw_list->CmdBuffer) cmd.ClipRect = ImVec4(cmd.ClipRect.x * fb_scale.x, cmd.ClipRect.y * fb_scale.y, cmd.ClipRect.z * fb_scale.x, cmd.ClipRect.w * fb_scale.y); } //----------------------------------------------------------------------------- // [SECTION] Helpers ShadeVertsXXX functions //----------------------------------------------------------------------------- // Generic linear color gradient, write to RGB fields, leave A untouched. void ImGui::ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1) { ImVec2 gradient_extent = gradient_p1 - gradient_p0; float gradient_inv_length2 = 1.0f / ImLengthSqr(gradient_extent); ImDrawVert* vert_start = draw_list->VtxBuffer.Data + vert_start_idx; ImDrawVert* vert_end = draw_list->VtxBuffer.Data + vert_end_idx; const int col0_r = (int)(col0 >> IM_COL32_R_SHIFT) & 0xFF; const int col0_g = (int)(col0 >> IM_COL32_G_SHIFT) & 0xFF; const int col0_b = (int)(col0 >> IM_COL32_B_SHIFT) & 0xFF; const int col_delta_r = ((int)(col1 >> IM_COL32_R_SHIFT) & 0xFF) - col0_r; const int col_delta_g = ((int)(col1 >> IM_COL32_G_SHIFT) & 0xFF) - col0_g; const int col_delta_b = ((int)(col1 >> IM_COL32_B_SHIFT) & 0xFF) - col0_b; for (ImDrawVert* vert = vert_start; vert < vert_end; vert++) { float d = ImDot(vert->pos - gradient_p0, gradient_extent); float t = ImClamp(d * gradient_inv_length2, 0.0f, 1.0f); int r = (int)(col0_r + col_delta_r * t); int g = (int)(col0_g + col_delta_g * t); int b = (int)(col0_b + col_delta_b * t); vert->col = (r << IM_COL32_R_SHIFT) | (g << IM_COL32_G_SHIFT) | (b << IM_COL32_B_SHIFT) | (vert->col & IM_COL32_A_MASK); } } // Distribute UV over (a, b) rectangle void ImGui::ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp) { const ImVec2 size = b - a; const ImVec2 uv_size = uv_b - uv_a; const ImVec2 scale = ImVec2( size.x != 0.0f ? (uv_size.x / size.x) : 0.0f, size.y != 0.0f ? (uv_size.y / size.y) : 0.0f); ImDrawVert* vert_start = draw_list->VtxBuffer.Data + vert_start_idx; ImDrawVert* vert_end = draw_list->VtxBuffer.Data + vert_end_idx; if (clamp) { const ImVec2 min = ImMin(uv_a, uv_b); const ImVec2 max = ImMax(uv_a, uv_b); for (ImDrawVert* vertex = vert_start; vertex < vert_end; ++vertex) vertex->uv = ImClamp(uv_a + ImMul(ImVec2(vertex->pos.x, vertex->pos.y) - a, scale), min, max); } else { for (ImDrawVert* vertex = vert_start; vertex < vert_end; ++vertex) vertex->uv = uv_a + ImMul(ImVec2(vertex->pos.x, vertex->pos.y) - a, scale); } } void ImGui::ShadeVertsTransformPos(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& pivot_in, float cos_a, float sin_a, const ImVec2& pivot_out) { ImDrawVert* vert_start = draw_list->VtxBuffer.Data + vert_start_idx; ImDrawVert* vert_end = draw_list->VtxBuffer.Data + vert_end_idx; for (ImDrawVert* vertex = vert_start; vertex < vert_end; ++vertex) vertex->pos = ImRotate(vertex->pos- pivot_in, cos_a, sin_a) + pivot_out; } //----------------------------------------------------------------------------- // [SECTION] ImFontConfig //----------------------------------------------------------------------------- ImFontConfig::ImFontConfig() { memset(this, 0, sizeof(*this)); FontDataOwnedByAtlas = true; OversampleH = 2; OversampleV = 1; GlyphMaxAdvanceX = FLT_MAX; RasterizerMultiply = 1.0f; RasterizerDensity = 1.0f; EllipsisChar = (ImWchar)-1; } //----------------------------------------------------------------------------- // [SECTION] ImFontAtlas //----------------------------------------------------------------------------- // A work of art lies ahead! (. = white layer, X = black layer, others are blank) // The 2x2 white texels on the top left are the ones we'll use everywhere in Dear ImGui to render filled shapes. // (This is used when io.MouseDrawCursor = true) const int FONT_ATLAS_DEFAULT_TEX_DATA_W = 122; // Actual texture will be 2 times that + 1 spacing. const int FONT_ATLAS_DEFAULT_TEX_DATA_H = 27; static const char FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[FONT_ATLAS_DEFAULT_TEX_DATA_W * FONT_ATLAS_DEFAULT_TEX_DATA_H + 1] = { "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX- XX - XX XX " "..- -X.....X- X.X - X.X -X.....X - X.....X- X..X -X..X X..X" "--- -XXX.XXX- X...X - X...X -X....X - X....X- X..X -X...X X...X" "X - X.X - X.....X - X.....X -X...X - X...X- X..X - X...X X...X " "XX - X.X -X.......X- X.......X -X..X.X - X.X..X- X..X - X...X...X " "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X- X..XXX - X.....X " "X..X - X.X - X.X - X.X -XX X.X - X.X XX- X..X..XXX - X...X " "X...X - X.X - X.X - XX X.X XX - X.X - X.X - X..X..X..XX - X.X " "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X - X..X..X..X.X - X...X " "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X -XXX X..X..X..X..X- X.....X " "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X -X..XX........X..X- X...X...X " "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X -X...X...........X- X...X X...X " "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X - X..............X-X...X X...X" "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X - X.............X-X..X X..X" "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X - X.............X- XX XX " "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X - X............X--------------" "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX - X...........X - " "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------- X..........X - " "X.X X..X - -X.......X- X.......X - XX XX - - X..........X - " "XX X..X - - X.....X - X.....X - X.X X.X - - X........X - " " X..X - - X...X - X...X - X..X X..X - - X........X - " " XX - - X.X - X.X - X...XXXXXXXXXXXXX...X - - XXXXXXXXXX - " "------------- - X - X -X.....................X- ------------------- " " ----------------------------------- X...XXXXXXXXXXXXX...X - " " - X..X X..X - " " - X.X X.X - " " - XX XX - " }; static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_COUNT][3] = { // Pos ........ Size ......... Offset ...... { ImVec2( 0,3), ImVec2(12,19), ImVec2( 0, 0) }, // ImGuiMouseCursor_Arrow { ImVec2(13,0), ImVec2( 7,16), ImVec2( 1, 8) }, // ImGuiMouseCursor_TextInput { ImVec2(31,0), ImVec2(23,23), ImVec2(11,11) }, // ImGuiMouseCursor_ResizeAll { ImVec2(21,0), ImVec2( 9,23), ImVec2( 4,11) }, // ImGuiMouseCursor_ResizeNS { ImVec2(55,18),ImVec2(23, 9), ImVec2(11, 4) }, // ImGuiMouseCursor_ResizeEW { ImVec2(73,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNESW { ImVec2(55,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNWSE { ImVec2(91,0), ImVec2(17,22), ImVec2( 5, 0) }, // ImGuiMouseCursor_Hand { ImVec2(109,0),ImVec2(13,15), ImVec2( 6, 7) }, // ImGuiMouseCursor_NotAllowed }; ImFontAtlas::ImFontAtlas() { memset(this, 0, sizeof(*this)); TexGlyphPadding = 1; PackIdMouseCursors = PackIdLines = -1; } ImFontAtlas::~ImFontAtlas() { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); Clear(); } void ImFontAtlas::ClearInputData() { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); for (ImFontConfig& font_cfg : ConfigData) if (font_cfg.FontData && font_cfg.FontDataOwnedByAtlas) { IM_FREE(font_cfg.FontData); font_cfg.FontData = NULL; } // When clearing this we lose access to the font name and other information used to build the font. for (ImFont* font : Fonts) if (font->ConfigData >= ConfigData.Data && font->ConfigData < ConfigData.Data + ConfigData.Size) { font->ConfigData = NULL; font->ConfigDataCount = 0; } ConfigData.clear(); CustomRects.clear(); PackIdMouseCursors = PackIdLines = -1; // Important: we leave TexReady untouched } void ImFontAtlas::ClearTexData() { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); if (TexPixelsAlpha8) IM_FREE(TexPixelsAlpha8); if (TexPixelsRGBA32) IM_FREE(TexPixelsRGBA32); TexPixelsAlpha8 = NULL; TexPixelsRGBA32 = NULL; TexPixelsUseColors = false; // Important: we leave TexReady untouched } void ImFontAtlas::ClearFonts() { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); Fonts.clear_delete(); TexReady = false; } void ImFontAtlas::Clear() { ClearInputData(); ClearTexData(); ClearFonts(); } void ImFontAtlas::GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel) { // Build atlas on demand if (TexPixelsAlpha8 == NULL) Build(); *out_pixels = TexPixelsAlpha8; if (out_width) *out_width = TexWidth; if (out_height) *out_height = TexHeight; if (out_bytes_per_pixel) *out_bytes_per_pixel = 1; } void ImFontAtlas::GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel) { // Convert to RGBA32 format on demand // Although it is likely to be the most commonly used format, our font rendering is 1 channel / 8 bpp if (!TexPixelsRGBA32) { unsigned char* pixels = NULL; GetTexDataAsAlpha8(&pixels, NULL, NULL); if (pixels) { TexPixelsRGBA32 = (unsigned int*)IM_ALLOC((size_t)TexWidth * (size_t)TexHeight * 4); const unsigned char* src = pixels; unsigned int* dst = TexPixelsRGBA32; for (int n = TexWidth * TexHeight; n > 0; n--) *dst++ = IM_COL32(255, 255, 255, (unsigned int)(*src++)); } } *out_pixels = (unsigned char*)TexPixelsRGBA32; if (out_width) *out_width = TexWidth; if (out_height) *out_height = TexHeight; if (out_bytes_per_pixel) *out_bytes_per_pixel = 4; } ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); IM_ASSERT(font_cfg->FontData != NULL && font_cfg->FontDataSize > 0); IM_ASSERT(font_cfg->SizePixels > 0.0f); // Create new font if (!font_cfg->MergeMode) Fonts.push_back(IM_NEW(ImFont)); else IM_ASSERT(!Fonts.empty() && "Cannot use MergeMode for the first font"); // When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font. ConfigData.push_back(*font_cfg); ImFontConfig& new_font_cfg = ConfigData.back(); if (new_font_cfg.DstFont == NULL) new_font_cfg.DstFont = Fonts.back(); if (!new_font_cfg.FontDataOwnedByAtlas) { new_font_cfg.FontData = IM_ALLOC(new_font_cfg.FontDataSize); new_font_cfg.FontDataOwnedByAtlas = true; memcpy(new_font_cfg.FontData, font_cfg->FontData, (size_t)new_font_cfg.FontDataSize); } if (new_font_cfg.DstFont->EllipsisChar == (ImWchar)-1) new_font_cfg.DstFont->EllipsisChar = font_cfg->EllipsisChar; ImFontAtlasUpdateConfigDataPointers(this); // Invalidate texture TexReady = false; ClearTexData(); return new_font_cfg.DstFont; } // Default font TTF is compressed with stb_compress then base85 encoded (see misc/fonts/binary_to_compressed_c.cpp for encoder) static unsigned int stb_decompress_length(const unsigned char* input); static unsigned int stb_decompress(unsigned char* output, const unsigned char* input, unsigned int length); static const char* GetDefaultCompressedFontDataTTFBase85(); static unsigned int Decode85Byte(char c) { return c >= '\\' ? c-36 : c-35; } static void Decode85(const unsigned char* src, unsigned char* dst) { while (*src) { unsigned int tmp = Decode85Byte(src[0]) + 85 * (Decode85Byte(src[1]) + 85 * (Decode85Byte(src[2]) + 85 * (Decode85Byte(src[3]) + 85 * Decode85Byte(src[4])))); dst[0] = ((tmp >> 0) & 0xFF); dst[1] = ((tmp >> 8) & 0xFF); dst[2] = ((tmp >> 16) & 0xFF); dst[3] = ((tmp >> 24) & 0xFF); // We can't assume little-endianness. src += 5; dst += 4; } } // Load embedded ProggyClean.ttf at size 13, disable oversampling ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template) { ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); if (!font_cfg_template) { font_cfg.OversampleH = font_cfg.OversampleV = 1; font_cfg.PixelSnapH = true; } if (font_cfg.SizePixels <= 0.0f) font_cfg.SizePixels = 13.0f * 1.0f; if (font_cfg.Name[0] == '\0') ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "ProggyClean.ttf, %dpx", (int)font_cfg.SizePixels); font_cfg.EllipsisChar = (ImWchar)0x0085; font_cfg.GlyphOffset.y = 1.0f * IM_TRUNC(font_cfg.SizePixels / 13.0f); // Add +1 offset per 13 units const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85(); const ImWchar* glyph_ranges = font_cfg.GlyphRanges != NULL ? font_cfg.GlyphRanges : GetGlyphRangesDefault(); ImFont* font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_cfg.SizePixels, &font_cfg, glyph_ranges); return font; } ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges) { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); size_t data_size = 0; void* data = ImFileLoadToMemory(filename, "rb", &data_size, 0); if (!data) { IM_ASSERT_USER_ERROR(0, "Could not load font file!"); return NULL; } ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); if (font_cfg.Name[0] == '\0') { // Store a short copy of filename into into the font name for convenience const char* p; for (p = filename + strlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--) {} ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "%s, %.0fpx", p, size_pixels); } return AddFontFromMemoryTTF(data, (int)data_size, size_pixels, &font_cfg, glyph_ranges); } // NB: Transfer ownership of 'ttf_data' to ImFontAtlas, unless font_cfg_template->FontDataOwnedByAtlas == false. Owned TTF buffer will be deleted after Build(). ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* font_data, int font_data_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges) { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); IM_ASSERT(font_cfg.FontData == NULL); IM_ASSERT(font_data_size > 100 && "Incorrect value for font_data_size!"); // Heuristic to prevent accidentally passing a wrong value to font_data_size. font_cfg.FontData = font_data; font_cfg.FontDataSize = font_data_size; font_cfg.SizePixels = size_pixels > 0.0f ? size_pixels : font_cfg.SizePixels; if (glyph_ranges) font_cfg.GlyphRanges = glyph_ranges; return AddFont(&font_cfg); } ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges) { const unsigned int buf_decompressed_size = stb_decompress_length((const unsigned char*)compressed_ttf_data); unsigned char* buf_decompressed_data = (unsigned char*)IM_ALLOC(buf_decompressed_size); stb_decompress(buf_decompressed_data, (const unsigned char*)compressed_ttf_data, (unsigned int)compressed_ttf_size); ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); IM_ASSERT(font_cfg.FontData == NULL); font_cfg.FontDataOwnedByAtlas = true; return AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, size_pixels, &font_cfg, glyph_ranges); } ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* compressed_ttf_data_base85, float size_pixels, const ImFontConfig* font_cfg, const ImWchar* glyph_ranges) { int compressed_ttf_size = (((int)strlen(compressed_ttf_data_base85) + 4) / 5) * 4; void* compressed_ttf = IM_ALLOC((size_t)compressed_ttf_size); Decode85((const unsigned char*)compressed_ttf_data_base85, (unsigned char*)compressed_ttf); ImFont* font = AddFontFromMemoryCompressedTTF(compressed_ttf, compressed_ttf_size, size_pixels, font_cfg, glyph_ranges); IM_FREE(compressed_ttf); return font; } int ImFontAtlas::AddCustomRectRegular(int width, int height) { IM_ASSERT(width > 0 && width <= 0xFFFF); IM_ASSERT(height > 0 && height <= 0xFFFF); ImFontAtlasCustomRect r; r.Width = (unsigned short)width; r.Height = (unsigned short)height; CustomRects.push_back(r); return CustomRects.Size - 1; // Return index } int ImFontAtlas::AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset) { #ifdef IMGUI_USE_WCHAR32 IM_ASSERT(id <= IM_UNICODE_CODEPOINT_MAX); #endif IM_ASSERT(font != NULL); IM_ASSERT(width > 0 && width <= 0xFFFF); IM_ASSERT(height > 0 && height <= 0xFFFF); ImFontAtlasCustomRect r; r.Width = (unsigned short)width; r.Height = (unsigned short)height; r.GlyphID = id; r.GlyphAdvanceX = advance_x; r.GlyphOffset = offset; r.Font = font; CustomRects.push_back(r); return CustomRects.Size - 1; // Return index } void ImFontAtlas::CalcCustomRectUV(const ImFontAtlasCustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max) const { IM_ASSERT(TexWidth > 0 && TexHeight > 0); // Font atlas needs to be built before we can calculate UV coordinates IM_ASSERT(rect->IsPacked()); // Make sure the rectangle has been packed *out_uv_min = ImVec2((float)rect->X * TexUvScale.x, (float)rect->Y * TexUvScale.y); *out_uv_max = ImVec2((float)(rect->X + rect->Width) * TexUvScale.x, (float)(rect->Y + rect->Height) * TexUvScale.y); } bool ImFontAtlas::GetMouseCursorTexData(ImGuiMouseCursor cursor_type, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]) { if (cursor_type <= ImGuiMouseCursor_None || cursor_type >= ImGuiMouseCursor_COUNT) return false; if (Flags & ImFontAtlasFlags_NoMouseCursors) return false; IM_ASSERT(PackIdMouseCursors != -1); ImFontAtlasCustomRect* r = GetCustomRectByIndex(PackIdMouseCursors); ImVec2 pos = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][0] + ImVec2((float)r->X, (float)r->Y); ImVec2 size = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][1]; *out_size = size; *out_offset = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][2]; out_uv_border[0] = (pos) * TexUvScale; out_uv_border[1] = (pos + size) * TexUvScale; pos.x += FONT_ATLAS_DEFAULT_TEX_DATA_W + 1; out_uv_fill[0] = (pos) * TexUvScale; out_uv_fill[1] = (pos + size) * TexUvScale; return true; } bool ImFontAtlas::Build() { IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!"); // Default font is none are specified if (ConfigData.Size == 0) AddFontDefault(); // Select builder // - Note that we do not reassign to atlas->FontBuilderIO, since it is likely to point to static data which // may mess with some hot-reloading schemes. If you need to assign to this (for dynamic selection) AND are // using a hot-reloading scheme that messes up static data, store your own instance of ImFontBuilderIO somewhere // and point to it instead of pointing directly to return value of the GetBuilderXXX functions. const ImFontBuilderIO* builder_io = FontBuilderIO; if (builder_io == NULL) { #ifdef IMGUI_ENABLE_FREETYPE builder_io = ImGuiFreeType::GetBuilderForFreeType(); #elif defined(IMGUI_ENABLE_STB_TRUETYPE) builder_io = ImFontAtlasGetBuilderForStbTruetype(); #else IM_ASSERT(0); // Invalid Build function #endif } // Build return builder_io->FontBuilder_Build(this); } void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_brighten_factor) { for (unsigned int i = 0; i < 256; i++) { unsigned int value = (unsigned int)(i * in_brighten_factor); out_table[i] = value > 255 ? 255 : (value & 0xFF); } } void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride) { IM_ASSERT_PARANOID(w <= stride); unsigned char* data = pixels + x + y * stride; for (int j = h; j > 0; j--, data += stride - w) for (int i = w; i > 0; i--, data++) *data = table[*data]; } #ifdef IMGUI_ENABLE_STB_TRUETYPE // Temporary data for one source font (multiple source fonts can be merged into one destination ImFont) // (C++03 doesn't allow instancing ImVector<> with function-local types so we declare the type here.) struct ImFontBuildSrcData { stbtt_fontinfo FontInfo; stbtt_pack_range PackRange; // Hold the list of codepoints to pack (essentially points to Codepoints.Data) stbrp_rect* Rects; // Rectangle to pack. We first fill in their size and the packer will give us their position. stbtt_packedchar* PackedChars; // Output glyphs const ImWchar* SrcRanges; // Ranges as requested by user (user is allowed to request too much, e.g. 0x0020..0xFFFF) int DstIndex; // Index into atlas->Fonts[] and dst_tmp_array[] int GlyphsHighest; // Highest requested codepoint int GlyphsCount; // Glyph count (excluding missing glyphs and glyphs already set by an earlier source font) ImBitVector GlyphsSet; // Glyph bit map (random access, 1-bit per codepoint. This will be a maximum of 8KB) ImVector GlyphsList; // Glyph codepoints list (flattened version of GlyphsSet) }; // Temporary data for one destination ImFont* (multiple source fonts can be merged into one destination ImFont) struct ImFontBuildDstData { int SrcCount; // Number of source fonts targeting this destination font. int GlyphsHighest; int GlyphsCount; ImBitVector GlyphsSet; // This is used to resolve collision when multiple sources are merged into a same destination font. }; static void UnpackBitVectorToFlatIndexList(const ImBitVector* in, ImVector* out) { IM_ASSERT(sizeof(in->Storage.Data[0]) == sizeof(int)); const ImU32* it_begin = in->Storage.begin(); const ImU32* it_end = in->Storage.end(); for (const ImU32* it = it_begin; it < it_end; it++) if (ImU32 entries_32 = *it) for (ImU32 bit_n = 0; bit_n < 32; bit_n++) if (entries_32 & ((ImU32)1 << bit_n)) out->push_back((int)(((it - it_begin) << 5) + bit_n)); } static bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) { IM_ASSERT(atlas->ConfigData.Size > 0); ImFontAtlasBuildInit(atlas); // Clear atlas atlas->TexID = (ImTextureID)NULL; atlas->TexWidth = atlas->TexHeight = 0; atlas->TexUvScale = ImVec2(0.0f, 0.0f); atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f); atlas->ClearTexData(); // Temporary storage for building ImVector src_tmp_array; ImVector dst_tmp_array; src_tmp_array.resize(atlas->ConfigData.Size); dst_tmp_array.resize(atlas->Fonts.Size); memset(src_tmp_array.Data, 0, (size_t)src_tmp_array.size_in_bytes()); memset(dst_tmp_array.Data, 0, (size_t)dst_tmp_array.size_in_bytes()); // 1. Initialize font loading structure, check font data validity for (int src_i = 0; src_i < atlas->ConfigData.Size; src_i++) { ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; ImFontConfig& cfg = atlas->ConfigData[src_i]; IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas)); // Find index from cfg.DstFont (we allow the user to set cfg.DstFont. Also it makes casual debugging nicer than when storing indices) src_tmp.DstIndex = -1; for (int output_i = 0; output_i < atlas->Fonts.Size && src_tmp.DstIndex == -1; output_i++) if (cfg.DstFont == atlas->Fonts[output_i]) src_tmp.DstIndex = output_i; if (src_tmp.DstIndex == -1) { IM_ASSERT(src_tmp.DstIndex != -1); // cfg.DstFont not pointing within atlas->Fonts[] array? return false; } // Initialize helper structure for font loading and verify that the TTF/OTF data is correct const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)cfg.FontData, cfg.FontNo); IM_ASSERT(font_offset >= 0 && "FontData is incorrect, or FontNo cannot be found."); if (!stbtt_InitFont(&src_tmp.FontInfo, (unsigned char*)cfg.FontData, font_offset)) { IM_ASSERT(0 && "stbtt_InitFont(): failed to parse FontData. It is correct and complete? Check FontDataSize."); return false; } // Measure highest codepoints ImFontBuildDstData& dst_tmp = dst_tmp_array[src_tmp.DstIndex]; src_tmp.SrcRanges = cfg.GlyphRanges ? cfg.GlyphRanges : atlas->GetGlyphRangesDefault(); for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) { // Check for valid range. This may also help detect *some* dangling pointers, because a common // user error is to setup ImFontConfig::GlyphRanges with a pointer to data that isn't persistent. IM_ASSERT(src_range[0] <= src_range[1]); src_tmp.GlyphsHighest = ImMax(src_tmp.GlyphsHighest, (int)src_range[1]); } dst_tmp.SrcCount++; dst_tmp.GlyphsHighest = ImMax(dst_tmp.GlyphsHighest, src_tmp.GlyphsHighest); } // 2. For every requested codepoint, check for their presence in the font data, and handle redundancy or overlaps between source fonts to avoid unused glyphs. int total_glyphs_count = 0; for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) { ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; ImFontBuildDstData& dst_tmp = dst_tmp_array[src_tmp.DstIndex]; src_tmp.GlyphsSet.Create(src_tmp.GlyphsHighest + 1); if (dst_tmp.GlyphsSet.Storage.empty()) dst_tmp.GlyphsSet.Create(dst_tmp.GlyphsHighest + 1); for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) for (unsigned int codepoint = src_range[0]; codepoint <= src_range[1]; codepoint++) { if (dst_tmp.GlyphsSet.TestBit(codepoint)) // Don't overwrite existing glyphs. We could make this an option for MergeMode (e.g. MergeOverwrite==true) continue; if (!stbtt_FindGlyphIndex(&src_tmp.FontInfo, codepoint)) // It is actually in the font? continue; // Add to avail set/counters src_tmp.GlyphsCount++; dst_tmp.GlyphsCount++; src_tmp.GlyphsSet.SetBit(codepoint); dst_tmp.GlyphsSet.SetBit(codepoint); total_glyphs_count++; } } // 3. Unpack our bit map into a flat list (we now have all the Unicode points that we know are requested _and_ available _and_ not overlapping another) for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) { ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; src_tmp.GlyphsList.reserve(src_tmp.GlyphsCount); UnpackBitVectorToFlatIndexList(&src_tmp.GlyphsSet, &src_tmp.GlyphsList); src_tmp.GlyphsSet.Clear(); IM_ASSERT(src_tmp.GlyphsList.Size == src_tmp.GlyphsCount); } for (int dst_i = 0; dst_i < dst_tmp_array.Size; dst_i++) dst_tmp_array[dst_i].GlyphsSet.Clear(); dst_tmp_array.clear(); // Allocate packing character data and flag packed characters buffer as non-packed (x0=y0=x1=y1=0) // (We technically don't need to zero-clear buf_rects, but let's do it for the sake of sanity) ImVector buf_rects; ImVector buf_packedchars; buf_rects.resize(total_glyphs_count); buf_packedchars.resize(total_glyphs_count); memset(buf_rects.Data, 0, (size_t)buf_rects.size_in_bytes()); memset(buf_packedchars.Data, 0, (size_t)buf_packedchars.size_in_bytes()); // 4. Gather glyphs sizes so we can pack them in our virtual canvas. int total_surface = 0; int buf_rects_out_n = 0; int buf_packedchars_out_n = 0; for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) { ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; if (src_tmp.GlyphsCount == 0) continue; src_tmp.Rects = &buf_rects[buf_rects_out_n]; src_tmp.PackedChars = &buf_packedchars[buf_packedchars_out_n]; buf_rects_out_n += src_tmp.GlyphsCount; buf_packedchars_out_n += src_tmp.GlyphsCount; // Convert our ranges in the format stb_truetype wants ImFontConfig& cfg = atlas->ConfigData[src_i]; src_tmp.PackRange.font_size = cfg.SizePixels * cfg.RasterizerDensity; src_tmp.PackRange.first_unicode_codepoint_in_range = 0; src_tmp.PackRange.array_of_unicode_codepoints = src_tmp.GlyphsList.Data; src_tmp.PackRange.num_chars = src_tmp.GlyphsList.Size; src_tmp.PackRange.chardata_for_range = src_tmp.PackedChars; src_tmp.PackRange.h_oversample = (unsigned char)cfg.OversampleH; src_tmp.PackRange.v_oversample = (unsigned char)cfg.OversampleV; // Gather the sizes of all rectangles we will need to pack (this loop is based on stbtt_PackFontRangesGatherRects) const float scale = (cfg.SizePixels > 0.0f) ? stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, cfg.SizePixels * cfg.RasterizerDensity) : stbtt_ScaleForMappingEmToPixels(&src_tmp.FontInfo, -cfg.SizePixels * cfg.RasterizerDensity); const int padding = atlas->TexGlyphPadding; for (int glyph_i = 0; glyph_i < src_tmp.GlyphsList.Size; glyph_i++) { int x0, y0, x1, y1; const int glyph_index_in_font = stbtt_FindGlyphIndex(&src_tmp.FontInfo, src_tmp.GlyphsList[glyph_i]); IM_ASSERT(glyph_index_in_font != 0); stbtt_GetGlyphBitmapBoxSubpixel(&src_tmp.FontInfo, glyph_index_in_font, scale * cfg.OversampleH, scale * cfg.OversampleV, 0, 0, &x0, &y0, &x1, &y1); src_tmp.Rects[glyph_i].w = (stbrp_coord)(x1 - x0 + padding + cfg.OversampleH - 1); src_tmp.Rects[glyph_i].h = (stbrp_coord)(y1 - y0 + padding + cfg.OversampleV - 1); total_surface += src_tmp.Rects[glyph_i].w * src_tmp.Rects[glyph_i].h; } } // We need a width for the skyline algorithm, any width! // The exact width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height. // User can override TexDesiredWidth and TexGlyphPadding if they wish, otherwise we use a simple heuristic to select the width based on expected surface. const int surface_sqrt = (int)ImSqrt((float)total_surface) + 1; atlas->TexHeight = 0; if (atlas->TexDesiredWidth > 0) atlas->TexWidth = atlas->TexDesiredWidth; else atlas->TexWidth = (surface_sqrt >= 4096 * 0.7f) ? 4096 : (surface_sqrt >= 2048 * 0.7f) ? 2048 : (surface_sqrt >= 1024 * 0.7f) ? 1024 : 512; // 5. Start packing // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values). const int TEX_HEIGHT_MAX = 1024 * 32; stbtt_pack_context spc = {}; stbtt_PackBegin(&spc, NULL, atlas->TexWidth, TEX_HEIGHT_MAX, 0, atlas->TexGlyphPadding, NULL); ImFontAtlasBuildPackCustomRects(atlas, spc.pack_info); // 6. Pack each source font. No rendering yet, we are working with rectangles in an infinitely tall texture at this point. for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) { ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; if (src_tmp.GlyphsCount == 0) continue; stbrp_pack_rects((stbrp_context*)spc.pack_info, src_tmp.Rects, src_tmp.GlyphsCount); // Extend texture height and mark missing glyphs as non-packed so we won't render them. // FIXME: We are not handling packing failure here (would happen if we got off TEX_HEIGHT_MAX or if a single if larger than TexWidth?) for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) if (src_tmp.Rects[glyph_i].was_packed) atlas->TexHeight = ImMax(atlas->TexHeight, src_tmp.Rects[glyph_i].y + src_tmp.Rects[glyph_i].h); } // 7. Allocate texture atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight); atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight); atlas->TexPixelsAlpha8 = (unsigned char*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight); memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight); spc.pixels = atlas->TexPixelsAlpha8; spc.height = atlas->TexHeight; // 8. Render/rasterize font characters into the texture for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) { ImFontConfig& cfg = atlas->ConfigData[src_i]; ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; if (src_tmp.GlyphsCount == 0) continue; stbtt_PackFontRangesRenderIntoRects(&spc, &src_tmp.FontInfo, &src_tmp.PackRange, 1, src_tmp.Rects); // Apply multiply operator if (cfg.RasterizerMultiply != 1.0f) { unsigned char multiply_table[256]; ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply); stbrp_rect* r = &src_tmp.Rects[0]; for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++, r++) if (r->was_packed) ImFontAtlasBuildMultiplyRectAlpha8(multiply_table, atlas->TexPixelsAlpha8, r->x, r->y, r->w, r->h, atlas->TexWidth * 1); } src_tmp.Rects = NULL; } // End packing stbtt_PackEnd(&spc); buf_rects.clear(); // 9. Setup ImFont and glyphs for runtime for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) { // When merging fonts with MergeMode=true: // - We can have multiple input fonts writing into a same destination font. // - dst_font->ConfigData is != from cfg which is our source configuration. ImFontBuildSrcData& src_tmp = src_tmp_array[src_i]; ImFontConfig& cfg = atlas->ConfigData[src_i]; ImFont* dst_font = cfg.DstFont; const float font_scale = stbtt_ScaleForPixelHeight(&src_tmp.FontInfo, cfg.SizePixels); int unscaled_ascent, unscaled_descent, unscaled_line_gap; stbtt_GetFontVMetrics(&src_tmp.FontInfo, &unscaled_ascent, &unscaled_descent, &unscaled_line_gap); const float ascent = ImTrunc(unscaled_ascent * font_scale + ((unscaled_ascent > 0.0f) ? +1 : -1)); const float descent = ImTrunc(unscaled_descent * font_scale + ((unscaled_descent > 0.0f) ? +1 : -1)); ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); const float font_off_x = cfg.GlyphOffset.x; const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent); const float inv_rasterization_scale = 1.0f / cfg.RasterizerDensity; for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) { // Register glyph const int codepoint = src_tmp.GlyphsList[glyph_i]; const stbtt_packedchar& pc = src_tmp.PackedChars[glyph_i]; stbtt_aligned_quad q; float unused_x = 0.0f, unused_y = 0.0f; stbtt_GetPackedQuad(src_tmp.PackedChars, atlas->TexWidth, atlas->TexHeight, glyph_i, &unused_x, &unused_y, &q, 0); float x0 = q.x0 * inv_rasterization_scale + font_off_x; float y0 = q.y0 * inv_rasterization_scale + font_off_y; float x1 = q.x1 * inv_rasterization_scale + font_off_x; float y1 = q.y1 * inv_rasterization_scale + font_off_y; dst_font->AddGlyph(&cfg, (ImWchar)codepoint, x0, y0, x1, y1, q.s0, q.t0, q.s1, q.t1, pc.xadvance * inv_rasterization_scale); } } // Cleanup src_tmp_array.clear_destruct(); ImFontAtlasBuildFinish(atlas); return true; } const ImFontBuilderIO* ImFontAtlasGetBuilderForStbTruetype() { static ImFontBuilderIO io; io.FontBuilder_Build = ImFontAtlasBuildWithStbTruetype; return &io; } #endif // IMGUI_ENABLE_STB_TRUETYPE void ImFontAtlasUpdateConfigDataPointers(ImFontAtlas* atlas) { for (ImFontConfig& font_cfg : atlas->ConfigData) { ImFont* font = font_cfg.DstFont; if (!font_cfg.MergeMode) { font->ConfigData = &font_cfg; font->ConfigDataCount = 0; } font->ConfigDataCount++; } } void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent) { if (!font_config->MergeMode) { font->ClearOutputData(); font->FontSize = font_config->SizePixels; IM_ASSERT(font->ConfigData == font_config); font->ContainerAtlas = atlas; font->Ascent = ascent; font->Descent = descent; } } void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opaque) { stbrp_context* pack_context = (stbrp_context*)stbrp_context_opaque; IM_ASSERT(pack_context != NULL); ImVector& user_rects = atlas->CustomRects; IM_ASSERT(user_rects.Size >= 1); // We expect at least the default custom rects to be registered, else something went wrong. #ifdef __GNUC__ if (user_rects.Size < 1) { __builtin_unreachable(); } // Workaround for GCC bug if IM_ASSERT() is defined to conditionally throw (see #5343) #endif ImVector pack_rects; pack_rects.resize(user_rects.Size); memset(pack_rects.Data, 0, (size_t)pack_rects.size_in_bytes()); for (int i = 0; i < user_rects.Size; i++) { pack_rects[i].w = user_rects[i].Width; pack_rects[i].h = user_rects[i].Height; } stbrp_pack_rects(pack_context, &pack_rects[0], pack_rects.Size); for (int i = 0; i < pack_rects.Size; i++) if (pack_rects[i].was_packed) { user_rects[i].X = (unsigned short)pack_rects[i].x; user_rects[i].Y = (unsigned short)pack_rects[i].y; IM_ASSERT(pack_rects[i].w == user_rects[i].Width && pack_rects[i].h == user_rects[i].Height); atlas->TexHeight = ImMax(atlas->TexHeight, pack_rects[i].y + pack_rects[i].h); } } void ImFontAtlasBuildRender8bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned char in_marker_pixel_value) { IM_ASSERT(x >= 0 && x + w <= atlas->TexWidth); IM_ASSERT(y >= 0 && y + h <= atlas->TexHeight); unsigned char* out_pixel = atlas->TexPixelsAlpha8 + x + (y * atlas->TexWidth); for (int off_y = 0; off_y < h; off_y++, out_pixel += atlas->TexWidth, in_str += w) for (int off_x = 0; off_x < w; off_x++) out_pixel[off_x] = (in_str[off_x] == in_marker_char) ? in_marker_pixel_value : 0x00; } void ImFontAtlasBuildRender32bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned int in_marker_pixel_value) { IM_ASSERT(x >= 0 && x + w <= atlas->TexWidth); IM_ASSERT(y >= 0 && y + h <= atlas->TexHeight); unsigned int* out_pixel = atlas->TexPixelsRGBA32 + x + (y * atlas->TexWidth); for (int off_y = 0; off_y < h; off_y++, out_pixel += atlas->TexWidth, in_str += w) for (int off_x = 0; off_x < w; off_x++) out_pixel[off_x] = (in_str[off_x] == in_marker_char) ? in_marker_pixel_value : IM_COL32_BLACK_TRANS; } static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas) { ImFontAtlasCustomRect* r = atlas->GetCustomRectByIndex(atlas->PackIdMouseCursors); IM_ASSERT(r->IsPacked()); const int w = atlas->TexWidth; if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors)) { // Render/copy pixels IM_ASSERT(r->Width == FONT_ATLAS_DEFAULT_TEX_DATA_W * 2 + 1 && r->Height == FONT_ATLAS_DEFAULT_TEX_DATA_H); const int x_for_white = r->X; const int x_for_black = r->X + FONT_ATLAS_DEFAULT_TEX_DATA_W + 1; if (atlas->TexPixelsAlpha8 != NULL) { ImFontAtlasBuildRender8bppRectFromString(atlas, x_for_white, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, '.', 0xFF); ImFontAtlasBuildRender8bppRectFromString(atlas, x_for_black, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, 'X', 0xFF); } else { ImFontAtlasBuildRender32bppRectFromString(atlas, x_for_white, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, '.', IM_COL32_WHITE); ImFontAtlasBuildRender32bppRectFromString(atlas, x_for_black, r->Y, FONT_ATLAS_DEFAULT_TEX_DATA_W, FONT_ATLAS_DEFAULT_TEX_DATA_H, FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS, 'X', IM_COL32_WHITE); } } else { // Render 4 white pixels IM_ASSERT(r->Width == 2 && r->Height == 2); const int offset = (int)r->X + (int)r->Y * w; if (atlas->TexPixelsAlpha8 != NULL) { atlas->TexPixelsAlpha8[offset] = atlas->TexPixelsAlpha8[offset + 1] = atlas->TexPixelsAlpha8[offset + w] = atlas->TexPixelsAlpha8[offset + w + 1] = 0xFF; } else { atlas->TexPixelsRGBA32[offset] = atlas->TexPixelsRGBA32[offset + 1] = atlas->TexPixelsRGBA32[offset + w] = atlas->TexPixelsRGBA32[offset + w + 1] = IM_COL32_WHITE; } } atlas->TexUvWhitePixel = ImVec2((r->X + 0.5f) * atlas->TexUvScale.x, (r->Y + 0.5f) * atlas->TexUvScale.y); } static void ImFontAtlasBuildRenderLinesTexData(ImFontAtlas* atlas) { if (atlas->Flags & ImFontAtlasFlags_NoBakedLines) return; // This generates a triangular shape in the texture, with the various line widths stacked on top of each other to allow interpolation between them ImFontAtlasCustomRect* r = atlas->GetCustomRectByIndex(atlas->PackIdLines); IM_ASSERT(r->IsPacked()); for (unsigned int n = 0; n < IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1; n++) // +1 because of the zero-width row { // Each line consists of at least two empty pixels at the ends, with a line of solid pixels in the middle unsigned int y = n; unsigned int line_width = n; unsigned int pad_left = (r->Width - line_width) / 2; unsigned int pad_right = r->Width - (pad_left + line_width); // Write each slice IM_ASSERT(pad_left + line_width + pad_right == r->Width && y < r->Height); // Make sure we're inside the texture bounds before we start writing pixels if (atlas->TexPixelsAlpha8 != NULL) { unsigned char* write_ptr = &atlas->TexPixelsAlpha8[r->X + ((r->Y + y) * atlas->TexWidth)]; for (unsigned int i = 0; i < pad_left; i++) *(write_ptr + i) = 0x00; for (unsigned int i = 0; i < line_width; i++) *(write_ptr + pad_left + i) = 0xFF; for (unsigned int i = 0; i < pad_right; i++) *(write_ptr + pad_left + line_width + i) = 0x00; } else { unsigned int* write_ptr = &atlas->TexPixelsRGBA32[r->X + ((r->Y + y) * atlas->TexWidth)]; for (unsigned int i = 0; i < pad_left; i++) *(write_ptr + i) = IM_COL32(255, 255, 255, 0); for (unsigned int i = 0; i < line_width; i++) *(write_ptr + pad_left + i) = IM_COL32_WHITE; for (unsigned int i = 0; i < pad_right; i++) *(write_ptr + pad_left + line_width + i) = IM_COL32(255, 255, 255, 0); } // Calculate UVs for this line ImVec2 uv0 = ImVec2((float)(r->X + pad_left - 1), (float)(r->Y + y)) * atlas->TexUvScale; ImVec2 uv1 = ImVec2((float)(r->X + pad_left + line_width + 1), (float)(r->Y + y + 1)) * atlas->TexUvScale; float half_v = (uv0.y + uv1.y) * 0.5f; // Calculate a constant V in the middle of the row to avoid sampling artifacts atlas->TexUvLines[n] = ImVec4(uv0.x, half_v, uv1.x, half_v); } } // Note: this is called / shared by both the stb_truetype and the FreeType builder void ImFontAtlasBuildInit(ImFontAtlas* atlas) { // Round font size // - We started rounding in 1.90 WIP (18991) as our layout system currently doesn't support non-rounded font size well yet. // - Note that using io.FontGlobalScale or SetWindowFontScale(), with are legacy-ish, partially supported features, can still lead to unrounded sizes. // - We may support it better later and remove this rounding. for (ImFontConfig& cfg : atlas->ConfigData) cfg.SizePixels = ImTrunc(cfg.SizePixels); // Register texture region for mouse cursors or standard white pixels if (atlas->PackIdMouseCursors < 0) { if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors)) atlas->PackIdMouseCursors = atlas->AddCustomRectRegular(FONT_ATLAS_DEFAULT_TEX_DATA_W * 2 + 1, FONT_ATLAS_DEFAULT_TEX_DATA_H); else atlas->PackIdMouseCursors = atlas->AddCustomRectRegular(2, 2); } // Register texture region for thick lines // The +2 here is to give space for the end caps, whilst height +1 is to accommodate the fact we have a zero-width row if (atlas->PackIdLines < 0) { if (!(atlas->Flags & ImFontAtlasFlags_NoBakedLines)) atlas->PackIdLines = atlas->AddCustomRectRegular(IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 2, IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1); } } // This is called/shared by both the stb_truetype and the FreeType builder. void ImFontAtlasBuildFinish(ImFontAtlas* atlas) { // Render into our custom data blocks IM_ASSERT(atlas->TexPixelsAlpha8 != NULL || atlas->TexPixelsRGBA32 != NULL); ImFontAtlasBuildRenderDefaultTexData(atlas); ImFontAtlasBuildRenderLinesTexData(atlas); // Register custom rectangle glyphs for (int i = 0; i < atlas->CustomRects.Size; i++) { const ImFontAtlasCustomRect* r = &atlas->CustomRects[i]; if (r->Font == NULL || r->GlyphID == 0) continue; // Will ignore ImFontConfig settings: GlyphMinAdvanceX, GlyphMinAdvanceY, GlyphExtraSpacing, PixelSnapH IM_ASSERT(r->Font->ContainerAtlas == atlas); ImVec2 uv0, uv1; atlas->CalcCustomRectUV(r, &uv0, &uv1); r->Font->AddGlyph(NULL, (ImWchar)r->GlyphID, r->GlyphOffset.x, r->GlyphOffset.y, r->GlyphOffset.x + r->Width, r->GlyphOffset.y + r->Height, uv0.x, uv0.y, uv1.x, uv1.y, r->GlyphAdvanceX); } // Build all fonts lookup tables for (ImFont* font : atlas->Fonts) if (font->DirtyLookupTables) font->BuildLookupTable(); atlas->TexReady = true; } // Retrieve list of range (2 int per range, values are inclusive) const ImWchar* ImFontAtlas::GetGlyphRangesDefault() { static const ImWchar ranges[] = { 0x0020, 0x00FF, // Basic Latin + Latin Supplement 0, }; return &ranges[0]; } const ImWchar* ImFontAtlas::GetGlyphRangesGreek() { static const ImWchar ranges[] = { 0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x0370, 0x03FF, // Greek and Coptic 0, }; return &ranges[0]; } const ImWchar* ImFontAtlas::GetGlyphRangesKorean() { static const ImWchar ranges[] = { 0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x3131, 0x3163, // Korean alphabets 0xAC00, 0xD7A3, // Korean characters 0xFFFD, 0xFFFD, // Invalid 0, }; return &ranges[0]; } const ImWchar* ImFontAtlas::GetGlyphRangesChineseFull() { static const ImWchar ranges[] = { 0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x2000, 0x206F, // General Punctuation 0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana 0x31F0, 0x31FF, // Katakana Phonetic Extensions 0xFF00, 0xFFEF, // Half-width characters 0xFFFD, 0xFFFD, // Invalid 0x4e00, 0x9FAF, // CJK Ideograms 0, }; return &ranges[0]; } static void UnpackAccumulativeOffsetsIntoRanges(int base_codepoint, const short* accumulative_offsets, int accumulative_offsets_count, ImWchar* out_ranges) { for (int n = 0; n < accumulative_offsets_count; n++, out_ranges += 2) { out_ranges[0] = out_ranges[1] = (ImWchar)(base_codepoint + accumulative_offsets[n]); base_codepoint += accumulative_offsets[n]; } out_ranges[0] = 0; } //------------------------------------------------------------------------- // [SECTION] ImFontAtlas glyph ranges helpers //------------------------------------------------------------------------- const ImWchar* ImFontAtlas::GetGlyphRangesChineseSimplifiedCommon() { // Store 2500 regularly used characters for Simplified Chinese. // Sourced from https://zh.wiktionary.org/wiki/%E9%99%84%E5%BD%95:%E7%8E%B0%E4%BB%A3%E6%B1%89%E8%AF%AD%E5%B8%B8%E7%94%A8%E5%AD%97%E8%A1%A8 // This table covers 97.97% of all characters used during the month in July, 1987. // You can use ImFontGlyphRangesBuilder to create your own ranges derived from this, by merging existing ranges or adding new characters. // (Stored as accumulative offsets from the initial unicode codepoint 0x4E00. This encoding is designed to helps us compact the source code size.) static const short accumulative_offsets_from_0x4E00[] = { 0,1,2,4,1,1,1,1,2,1,3,2,1,2,2,1,1,1,1,1,5,2,1,2,3,3,3,2,2,4,1,1,1,2,1,5,2,3,1,2,1,2,1,1,2,1,1,2,2,1,4,1,1,1,1,5,10,1,2,19,2,1,2,1,2,1,2,1,2, 1,5,1,6,3,2,1,2,2,1,1,1,4,8,5,1,1,4,1,1,3,1,2,1,5,1,2,1,1,1,10,1,1,5,2,4,6,1,4,2,2,2,12,2,1,1,6,1,1,1,4,1,1,4,6,5,1,4,2,2,4,10,7,1,1,4,2,4, 2,1,4,3,6,10,12,5,7,2,14,2,9,1,1,6,7,10,4,7,13,1,5,4,8,4,1,1,2,28,5,6,1,1,5,2,5,20,2,2,9,8,11,2,9,17,1,8,6,8,27,4,6,9,20,11,27,6,68,2,2,1,1, 1,2,1,2,2,7,6,11,3,3,1,1,3,1,2,1,1,1,1,1,3,1,1,8,3,4,1,5,7,2,1,4,4,8,4,2,1,2,1,1,4,5,6,3,6,2,12,3,1,3,9,2,4,3,4,1,5,3,3,1,3,7,1,5,1,1,1,1,2, 3,4,5,2,3,2,6,1,1,2,1,7,1,7,3,4,5,15,2,2,1,5,3,22,19,2,1,1,1,1,2,5,1,1,1,6,1,1,12,8,2,9,18,22,4,1,1,5,1,16,1,2,7,10,15,1,1,6,2,4,1,2,4,1,6, 1,1,3,2,4,1,6,4,5,1,2,1,1,2,1,10,3,1,3,2,1,9,3,2,5,7,2,19,4,3,6,1,1,1,1,1,4,3,2,1,1,1,2,5,3,1,1,1,2,2,1,1,2,1,1,2,1,3,1,1,1,3,7,1,4,1,1,2,1, 1,2,1,2,4,4,3,8,1,1,1,2,1,3,5,1,3,1,3,4,6,2,2,14,4,6,6,11,9,1,15,3,1,28,5,2,5,5,3,1,3,4,5,4,6,14,3,2,3,5,21,2,7,20,10,1,2,19,2,4,28,28,2,3, 2,1,14,4,1,26,28,42,12,40,3,52,79,5,14,17,3,2,2,11,3,4,6,3,1,8,2,23,4,5,8,10,4,2,7,3,5,1,1,6,3,1,2,2,2,5,28,1,1,7,7,20,5,3,29,3,17,26,1,8,4, 27,3,6,11,23,5,3,4,6,13,24,16,6,5,10,25,35,7,3,2,3,3,14,3,6,2,6,1,4,2,3,8,2,1,1,3,3,3,4,1,1,13,2,2,4,5,2,1,14,14,1,2,2,1,4,5,2,3,1,14,3,12, 3,17,2,16,5,1,2,1,8,9,3,19,4,2,2,4,17,25,21,20,28,75,1,10,29,103,4,1,2,1,1,4,2,4,1,2,3,24,2,2,2,1,1,2,1,3,8,1,1,1,2,1,1,3,1,1,1,6,1,5,3,1,1, 1,3,4,1,1,5,2,1,5,6,13,9,16,1,1,1,1,3,2,3,2,4,5,2,5,2,2,3,7,13,7,2,2,1,1,1,1,2,3,3,2,1,6,4,9,2,1,14,2,14,2,1,18,3,4,14,4,11,41,15,23,15,23, 176,1,3,4,1,1,1,1,5,3,1,2,3,7,3,1,1,2,1,2,4,4,6,2,4,1,9,7,1,10,5,8,16,29,1,1,2,2,3,1,3,5,2,4,5,4,1,1,2,2,3,3,7,1,6,10,1,17,1,44,4,6,2,1,1,6, 5,4,2,10,1,6,9,2,8,1,24,1,2,13,7,8,8,2,1,4,1,3,1,3,3,5,2,5,10,9,4,9,12,2,1,6,1,10,1,1,7,7,4,10,8,3,1,13,4,3,1,6,1,3,5,2,1,2,17,16,5,2,16,6, 1,4,2,1,3,3,6,8,5,11,11,1,3,3,2,4,6,10,9,5,7,4,7,4,7,1,1,4,2,1,3,6,8,7,1,6,11,5,5,3,24,9,4,2,7,13,5,1,8,82,16,61,1,1,1,4,2,2,16,10,3,8,1,1, 6,4,2,1,3,1,1,1,4,3,8,4,2,2,1,1,1,1,1,6,3,5,1,1,4,6,9,2,1,1,1,2,1,7,2,1,6,1,5,4,4,3,1,8,1,3,3,1,3,2,2,2,2,3,1,6,1,2,1,2,1,3,7,1,8,2,1,2,1,5, 2,5,3,5,10,1,2,1,1,3,2,5,11,3,9,3,5,1,1,5,9,1,2,1,5,7,9,9,8,1,3,3,3,6,8,2,3,2,1,1,32,6,1,2,15,9,3,7,13,1,3,10,13,2,14,1,13,10,2,1,3,10,4,15, 2,15,15,10,1,3,9,6,9,32,25,26,47,7,3,2,3,1,6,3,4,3,2,8,5,4,1,9,4,2,2,19,10,6,2,3,8,1,2,2,4,2,1,9,4,4,4,6,4,8,9,2,3,1,1,1,1,3,5,5,1,3,8,4,6, 2,1,4,12,1,5,3,7,13,2,5,8,1,6,1,2,5,14,6,1,5,2,4,8,15,5,1,23,6,62,2,10,1,1,8,1,2,2,10,4,2,2,9,2,1,1,3,2,3,1,5,3,3,2,1,3,8,1,1,1,11,3,1,1,4, 3,7,1,14,1,2,3,12,5,2,5,1,6,7,5,7,14,11,1,3,1,8,9,12,2,1,11,8,4,4,2,6,10,9,13,1,1,3,1,5,1,3,2,4,4,1,18,2,3,14,11,4,29,4,2,7,1,3,13,9,2,2,5, 3,5,20,7,16,8,5,72,34,6,4,22,12,12,28,45,36,9,7,39,9,191,1,1,1,4,11,8,4,9,2,3,22,1,1,1,1,4,17,1,7,7,1,11,31,10,2,4,8,2,3,2,1,4,2,16,4,32,2, 3,19,13,4,9,1,5,2,14,8,1,1,3,6,19,6,5,1,16,6,2,10,8,5,1,2,3,1,5,5,1,11,6,6,1,3,3,2,6,3,8,1,1,4,10,7,5,7,7,5,8,9,2,1,3,4,1,1,3,1,3,3,2,6,16, 1,4,6,3,1,10,6,1,3,15,2,9,2,10,25,13,9,16,6,2,2,10,11,4,3,9,1,2,6,6,5,4,30,40,1,10,7,12,14,33,6,3,6,7,3,1,3,1,11,14,4,9,5,12,11,49,18,51,31, 140,31,2,2,1,5,1,8,1,10,1,4,4,3,24,1,10,1,3,6,6,16,3,4,5,2,1,4,2,57,10,6,22,2,22,3,7,22,6,10,11,36,18,16,33,36,2,5,5,1,1,1,4,10,1,4,13,2,7, 5,2,9,3,4,1,7,43,3,7,3,9,14,7,9,1,11,1,1,3,7,4,18,13,1,14,1,3,6,10,73,2,2,30,6,1,11,18,19,13,22,3,46,42,37,89,7,3,16,34,2,2,3,9,1,7,1,1,1,2, 2,4,10,7,3,10,3,9,5,28,9,2,6,13,7,3,1,3,10,2,7,2,11,3,6,21,54,85,2,1,4,2,2,1,39,3,21,2,2,5,1,1,1,4,1,1,3,4,15,1,3,2,4,4,2,3,8,2,20,1,8,7,13, 4,1,26,6,2,9,34,4,21,52,10,4,4,1,5,12,2,11,1,7,2,30,12,44,2,30,1,1,3,6,16,9,17,39,82,2,2,24,7,1,7,3,16,9,14,44,2,1,2,1,2,3,5,2,4,1,6,7,5,3, 2,6,1,11,5,11,2,1,18,19,8,1,3,24,29,2,1,3,5,2,2,1,13,6,5,1,46,11,3,5,1,1,5,8,2,10,6,12,6,3,7,11,2,4,16,13,2,5,1,1,2,2,5,2,28,5,2,23,10,8,4, 4,22,39,95,38,8,14,9,5,1,13,5,4,3,13,12,11,1,9,1,27,37,2,5,4,4,63,211,95,2,2,2,1,3,5,2,1,1,2,2,1,1,1,3,2,4,1,2,1,1,5,2,2,1,1,2,3,1,3,1,1,1, 3,1,4,2,1,3,6,1,1,3,7,15,5,3,2,5,3,9,11,4,2,22,1,6,3,8,7,1,4,28,4,16,3,3,25,4,4,27,27,1,4,1,2,2,7,1,3,5,2,28,8,2,14,1,8,6,16,25,3,3,3,14,3, 3,1,1,2,1,4,6,3,8,4,1,1,1,2,3,6,10,6,2,3,18,3,2,5,5,4,3,1,5,2,5,4,23,7,6,12,6,4,17,11,9,5,1,1,10,5,12,1,1,11,26,33,7,3,6,1,17,7,1,5,12,1,11, 2,4,1,8,14,17,23,1,2,1,7,8,16,11,9,6,5,2,6,4,16,2,8,14,1,11,8,9,1,1,1,9,25,4,11,19,7,2,15,2,12,8,52,7,5,19,2,16,4,36,8,1,16,8,24,26,4,6,2,9, 5,4,36,3,28,12,25,15,37,27,17,12,59,38,5,32,127,1,2,9,17,14,4,1,2,1,1,8,11,50,4,14,2,19,16,4,17,5,4,5,26,12,45,2,23,45,104,30,12,8,3,10,2,2, 3,3,1,4,20,7,2,9,6,15,2,20,1,3,16,4,11,15,6,134,2,5,59,1,2,2,2,1,9,17,3,26,137,10,211,59,1,2,4,1,4,1,1,1,2,6,2,3,1,1,2,3,2,3,1,3,4,4,2,3,3, 1,4,3,1,7,2,2,3,1,2,1,3,3,3,2,2,3,2,1,3,14,6,1,3,2,9,6,15,27,9,34,145,1,1,2,1,1,1,1,2,1,1,1,1,2,2,2,3,1,2,1,1,1,2,3,5,8,3,5,2,4,1,3,2,2,2,12, 4,1,1,1,10,4,5,1,20,4,16,1,15,9,5,12,2,9,2,5,4,2,26,19,7,1,26,4,30,12,15,42,1,6,8,172,1,1,4,2,1,1,11,2,2,4,2,1,2,1,10,8,1,2,1,4,5,1,2,5,1,8, 4,1,3,4,2,1,6,2,1,3,4,1,2,1,1,1,1,12,5,7,2,4,3,1,1,1,3,3,6,1,2,2,3,3,3,2,1,2,12,14,11,6,6,4,12,2,8,1,7,10,1,35,7,4,13,15,4,3,23,21,28,52,5, 26,5,6,1,7,10,2,7,53,3,2,1,1,1,2,163,532,1,10,11,1,3,3,4,8,2,8,6,2,2,23,22,4,2,2,4,2,1,3,1,3,3,5,9,8,2,1,2,8,1,10,2,12,21,20,15,105,2,3,1,1, 3,2,3,1,1,2,5,1,4,15,11,19,1,1,1,1,5,4,5,1,1,2,5,3,5,12,1,2,5,1,11,1,1,15,9,1,4,5,3,26,8,2,1,3,1,1,15,19,2,12,1,2,5,2,7,2,19,2,20,6,26,7,5, 2,2,7,34,21,13,70,2,128,1,1,2,1,1,2,1,1,3,2,2,2,15,1,4,1,3,4,42,10,6,1,49,85,8,1,2,1,1,4,4,2,3,6,1,5,7,4,3,211,4,1,2,1,2,5,1,2,4,2,2,6,5,6, 10,3,4,48,100,6,2,16,296,5,27,387,2,2,3,7,16,8,5,38,15,39,21,9,10,3,7,59,13,27,21,47,5,21,6 }; static ImWchar base_ranges[] = // not zero-terminated { 0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x2000, 0x206F, // General Punctuation 0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana 0x31F0, 0x31FF, // Katakana Phonetic Extensions 0xFF00, 0xFFEF, // Half-width characters 0xFFFD, 0xFFFD // Invalid }; static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00) * 2 + 1] = { 0 }; if (!full_ranges[0]) { memcpy(full_ranges, base_ranges, sizeof(base_ranges)); UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_ARRAYSIZE(accumulative_offsets_from_0x4E00), full_ranges + IM_ARRAYSIZE(base_ranges)); } return &full_ranges[0]; } const ImWchar* ImFontAtlas::GetGlyphRangesJapanese() { // 2999 ideograms code points for Japanese // - 2136 Joyo (meaning "for regular use" or "for common use") Kanji code points // - 863 Jinmeiyo (meaning "for personal name") Kanji code points // - Sourced from official information provided by the government agencies of Japan: // - List of Joyo Kanji by the Agency for Cultural Affairs // - https://www.bunka.go.jp/kokugo_nihongo/sisaku/joho/joho/kijun/naikaku/kanji/ // - List of Jinmeiyo Kanji by the Ministry of Justice // - http://www.moj.go.jp/MINJI/minji86.html // - Available under the terms of the Creative Commons Attribution 4.0 International (CC BY 4.0). // - https://creativecommons.org/licenses/by/4.0/legalcode // - You can generate this code by the script at: // - https://github.com/vaiorabbit/everyday_use_kanji // - References: // - List of Joyo Kanji // - (Wikipedia) https://en.wikipedia.org/wiki/List_of_j%C5%8Dy%C5%8D_kanji // - List of Jinmeiyo Kanji // - (Wikipedia) https://en.wikipedia.org/wiki/Jinmeiy%C5%8D_kanji // - Missing 1 Joyo Kanji: U+20B9F (Kun'yomi: Shikaru, On'yomi: Shitsu,shichi), see https://github.com/ocornut/imgui/pull/3627 for details. // You can use ImFontGlyphRangesBuilder to create your own ranges derived from this, by merging existing ranges or adding new characters. // (Stored as accumulative offsets from the initial unicode codepoint 0x4E00. This encoding is designed to helps us compact the source code size.) static const short accumulative_offsets_from_0x4E00[] = { 0,1,2,4,1,1,1,1,2,1,3,3,2,2,1,5,3,5,7,5,6,1,2,1,7,2,6,3,1,8,1,1,4,1,1,18,2,11,2,6,2,1,2,1,5,1,2,1,3,1,2,1,2,3,3,1,1,2,3,1,1,1,12,7,9,1,4,5,1, 1,2,1,10,1,1,9,2,2,4,5,6,9,3,1,1,1,1,9,3,18,5,2,2,2,2,1,6,3,7,1,1,1,1,2,2,4,2,1,23,2,10,4,3,5,2,4,10,2,4,13,1,6,1,9,3,1,1,6,6,7,6,3,1,2,11,3, 2,2,3,2,15,2,2,5,4,3,6,4,1,2,5,2,12,16,6,13,9,13,2,1,1,7,16,4,7,1,19,1,5,1,2,2,7,7,8,2,6,5,4,9,18,7,4,5,9,13,11,8,15,2,1,1,1,2,1,2,2,1,2,2,8, 2,9,3,3,1,1,4,4,1,1,1,4,9,1,4,3,5,5,2,7,5,3,4,8,2,1,13,2,3,3,1,14,1,1,4,5,1,3,6,1,5,2,1,1,3,3,3,3,1,1,2,7,6,6,7,1,4,7,6,1,1,1,1,1,12,3,3,9,5, 2,6,1,5,6,1,2,3,18,2,4,14,4,1,3,6,1,1,6,3,5,5,3,2,2,2,2,12,3,1,4,2,3,2,3,11,1,7,4,1,2,1,3,17,1,9,1,24,1,1,4,2,2,4,1,2,7,1,1,1,3,1,2,2,4,15,1, 1,2,1,1,2,1,5,2,5,20,2,5,9,1,10,8,7,6,1,1,1,1,1,1,6,2,1,2,8,1,1,1,1,5,1,1,3,1,1,1,1,3,1,1,12,4,1,3,1,1,1,1,1,10,3,1,7,5,13,1,2,3,4,6,1,1,30, 2,9,9,1,15,38,11,3,1,8,24,7,1,9,8,10,2,1,9,31,2,13,6,2,9,4,49,5,2,15,2,1,10,2,1,1,1,2,2,6,15,30,35,3,14,18,8,1,16,10,28,12,19,45,38,1,3,2,3, 13,2,1,7,3,6,5,3,4,3,1,5,7,8,1,5,3,18,5,3,6,1,21,4,24,9,24,40,3,14,3,21,3,2,1,2,4,2,3,1,15,15,6,5,1,1,3,1,5,6,1,9,7,3,3,2,1,4,3,8,21,5,16,4, 5,2,10,11,11,3,6,3,2,9,3,6,13,1,2,1,1,1,1,11,12,6,6,1,4,2,6,5,2,1,1,3,3,6,13,3,1,1,5,1,2,3,3,14,2,1,2,2,2,5,1,9,5,1,1,6,12,3,12,3,4,13,2,14, 2,8,1,17,5,1,16,4,2,2,21,8,9,6,23,20,12,25,19,9,38,8,3,21,40,25,33,13,4,3,1,4,1,2,4,1,2,5,26,2,1,1,2,1,3,6,2,1,1,1,1,1,1,2,3,1,1,1,9,2,3,1,1, 1,3,6,3,2,1,1,6,6,1,8,2,2,2,1,4,1,2,3,2,7,3,2,4,1,2,1,2,2,1,1,1,1,1,3,1,2,5,4,10,9,4,9,1,1,1,1,1,1,5,3,2,1,6,4,9,6,1,10,2,31,17,8,3,7,5,40,1, 7,7,1,6,5,2,10,7,8,4,15,39,25,6,28,47,18,10,7,1,3,1,1,2,1,1,1,3,3,3,1,1,1,3,4,2,1,4,1,3,6,10,7,8,6,2,2,1,3,3,2,5,8,7,9,12,2,15,1,1,4,1,2,1,1, 1,3,2,1,3,3,5,6,2,3,2,10,1,4,2,8,1,1,1,11,6,1,21,4,16,3,1,3,1,4,2,3,6,5,1,3,1,1,3,3,4,6,1,1,10,4,2,7,10,4,7,4,2,9,4,3,1,1,1,4,1,8,3,4,1,3,1, 6,1,4,2,1,4,7,2,1,8,1,4,5,1,1,2,2,4,6,2,7,1,10,1,1,3,4,11,10,8,21,4,6,1,3,5,2,1,2,28,5,5,2,3,13,1,2,3,1,4,2,1,5,20,3,8,11,1,3,3,3,1,8,10,9,2, 10,9,2,3,1,1,2,4,1,8,3,6,1,7,8,6,11,1,4,29,8,4,3,1,2,7,13,1,4,1,6,2,6,12,12,2,20,3,2,3,6,4,8,9,2,7,34,5,1,18,6,1,1,4,4,5,7,9,1,2,2,4,3,4,1,7, 2,2,2,6,2,3,25,5,3,6,1,4,6,7,4,2,1,4,2,13,6,4,4,3,1,5,3,4,4,3,2,1,1,4,1,2,1,1,3,1,11,1,6,3,1,7,3,6,2,8,8,6,9,3,4,11,3,2,10,12,2,5,11,1,6,4,5, 3,1,8,5,4,6,6,3,5,1,1,3,2,1,2,2,6,17,12,1,10,1,6,12,1,6,6,19,9,6,16,1,13,4,4,15,7,17,6,11,9,15,12,6,7,2,1,2,2,15,9,3,21,4,6,49,18,7,3,2,3,1, 6,8,2,2,6,2,9,1,3,6,4,4,1,2,16,2,5,2,1,6,2,3,5,3,1,2,5,1,2,1,9,3,1,8,6,4,8,11,3,1,1,1,1,3,1,13,8,4,1,3,2,2,1,4,1,11,1,5,2,1,5,2,5,8,6,1,1,7, 4,3,8,3,2,7,2,1,5,1,5,2,4,7,6,2,8,5,1,11,4,5,3,6,18,1,2,13,3,3,1,21,1,1,4,1,4,1,1,1,8,1,2,2,7,1,2,4,2,2,9,2,1,1,1,4,3,6,3,12,5,1,1,1,5,6,3,2, 4,8,2,2,4,2,7,1,8,9,5,2,3,2,1,3,2,13,7,14,6,5,1,1,2,1,4,2,23,2,1,1,6,3,1,4,1,15,3,1,7,3,9,14,1,3,1,4,1,1,5,8,1,3,8,3,8,15,11,4,14,4,4,2,5,5, 1,7,1,6,14,7,7,8,5,15,4,8,6,5,6,2,1,13,1,20,15,11,9,2,5,6,2,11,2,6,2,5,1,5,8,4,13,19,25,4,1,1,11,1,34,2,5,9,14,6,2,2,6,1,1,14,1,3,14,13,1,6, 12,21,14,14,6,32,17,8,32,9,28,1,2,4,11,8,3,1,14,2,5,15,1,1,1,1,3,6,4,1,3,4,11,3,1,1,11,30,1,5,1,4,1,5,8,1,1,3,2,4,3,17,35,2,6,12,17,3,1,6,2, 1,1,12,2,7,3,3,2,1,16,2,8,3,6,5,4,7,3,3,8,1,9,8,5,1,2,1,3,2,8,1,2,9,12,1,1,2,3,8,3,24,12,4,3,7,5,8,3,3,3,3,3,3,1,23,10,3,1,2,2,6,3,1,16,1,16, 22,3,10,4,11,6,9,7,7,3,6,2,2,2,4,10,2,1,1,2,8,7,1,6,4,1,3,3,3,5,10,12,12,2,3,12,8,15,1,1,16,6,6,1,5,9,11,4,11,4,2,6,12,1,17,5,13,1,4,9,5,1,11, 2,1,8,1,5,7,28,8,3,5,10,2,17,3,38,22,1,2,18,12,10,4,38,18,1,4,44,19,4,1,8,4,1,12,1,4,31,12,1,14,7,75,7,5,10,6,6,13,3,2,11,11,3,2,5,28,15,6,18, 18,5,6,4,3,16,1,7,18,7,36,3,5,3,1,7,1,9,1,10,7,2,4,2,6,2,9,7,4,3,32,12,3,7,10,2,23,16,3,1,12,3,31,4,11,1,3,8,9,5,1,30,15,6,12,3,2,2,11,19,9, 14,2,6,2,3,19,13,17,5,3,3,25,3,14,1,1,1,36,1,3,2,19,3,13,36,9,13,31,6,4,16,34,2,5,4,2,3,3,5,1,1,1,4,3,1,17,3,2,3,5,3,1,3,2,3,5,6,3,12,11,1,3, 1,2,26,7,12,7,2,14,3,3,7,7,11,25,25,28,16,4,36,1,2,1,6,2,1,9,3,27,17,4,3,4,13,4,1,3,2,2,1,10,4,2,4,6,3,8,2,1,18,1,1,24,2,2,4,33,2,3,63,7,1,6, 40,7,3,4,4,2,4,15,18,1,16,1,1,11,2,41,14,1,3,18,13,3,2,4,16,2,17,7,15,24,7,18,13,44,2,2,3,6,1,1,7,5,1,7,1,4,3,3,5,10,8,2,3,1,8,1,1,27,4,2,1, 12,1,2,1,10,6,1,6,7,5,2,3,7,11,5,11,3,6,6,2,3,15,4,9,1,1,2,1,2,11,2,8,12,8,5,4,2,3,1,5,2,2,1,14,1,12,11,4,1,11,17,17,4,3,2,5,5,7,3,1,5,9,9,8, 2,5,6,6,13,13,2,1,2,6,1,2,2,49,4,9,1,2,10,16,7,8,4,3,2,23,4,58,3,29,1,14,19,19,11,11,2,7,5,1,3,4,6,2,18,5,12,12,17,17,3,3,2,4,1,6,2,3,4,3,1, 1,1,1,5,1,1,9,1,3,1,3,6,1,8,1,1,2,6,4,14,3,1,4,11,4,1,3,32,1,2,4,13,4,1,2,4,2,1,3,1,11,1,4,2,1,4,4,6,3,5,1,6,5,7,6,3,23,3,5,3,5,3,3,13,3,9,10, 1,12,10,2,3,18,13,7,160,52,4,2,2,3,2,14,5,4,12,4,6,4,1,20,4,11,6,2,12,27,1,4,1,2,2,7,4,5,2,28,3,7,25,8,3,19,3,6,10,2,2,1,10,2,5,4,1,3,4,1,5, 3,2,6,9,3,6,2,16,3,3,16,4,5,5,3,2,1,2,16,15,8,2,6,21,2,4,1,22,5,8,1,1,21,11,2,1,11,11,19,13,12,4,2,3,2,3,6,1,8,11,1,4,2,9,5,2,1,11,2,9,1,1,2, 14,31,9,3,4,21,14,4,8,1,7,2,2,2,5,1,4,20,3,3,4,10,1,11,9,8,2,1,4,5,14,12,14,2,17,9,6,31,4,14,1,20,13,26,5,2,7,3,6,13,2,4,2,19,6,2,2,18,9,3,5, 12,12,14,4,6,2,3,6,9,5,22,4,5,25,6,4,8,5,2,6,27,2,35,2,16,3,7,8,8,6,6,5,9,17,2,20,6,19,2,13,3,1,1,1,4,17,12,2,14,7,1,4,18,12,38,33,2,10,1,1, 2,13,14,17,11,50,6,33,20,26,74,16,23,45,50,13,38,33,6,6,7,4,4,2,1,3,2,5,8,7,8,9,3,11,21,9,13,1,3,10,6,7,1,2,2,18,5,5,1,9,9,2,68,9,19,13,2,5, 1,4,4,7,4,13,3,9,10,21,17,3,26,2,1,5,2,4,5,4,1,7,4,7,3,4,2,1,6,1,1,20,4,1,9,2,2,1,3,3,2,3,2,1,1,1,20,2,3,1,6,2,3,6,2,4,8,1,3,2,10,3,5,3,4,4, 3,4,16,1,6,1,10,2,4,2,1,1,2,10,11,2,2,3,1,24,31,4,10,10,2,5,12,16,164,15,4,16,7,9,15,19,17,1,2,1,1,5,1,1,1,1,1,3,1,4,3,1,3,1,3,1,2,1,1,3,3,7, 2,8,1,2,2,2,1,3,4,3,7,8,12,92,2,10,3,1,3,14,5,25,16,42,4,7,7,4,2,21,5,27,26,27,21,25,30,31,2,1,5,13,3,22,5,6,6,11,9,12,1,5,9,7,5,5,22,60,3,5, 13,1,1,8,1,1,3,3,2,1,9,3,3,18,4,1,2,3,7,6,3,1,2,3,9,1,3,1,3,2,1,3,1,1,1,2,1,11,3,1,6,9,1,3,2,3,1,2,1,5,1,1,4,3,4,1,2,2,4,4,1,7,2,1,2,2,3,5,13, 18,3,4,14,9,9,4,16,3,7,5,8,2,6,48,28,3,1,1,4,2,14,8,2,9,2,1,15,2,4,3,2,10,16,12,8,7,1,1,3,1,1,1,2,7,4,1,6,4,38,39,16,23,7,15,15,3,2,12,7,21, 37,27,6,5,4,8,2,10,8,8,6,5,1,2,1,3,24,1,16,17,9,23,10,17,6,1,51,55,44,13,294,9,3,6,2,4,2,2,15,1,1,1,13,21,17,68,14,8,9,4,1,4,9,3,11,7,1,1,1, 5,6,3,2,1,1,1,2,3,8,1,2,2,4,1,5,5,2,1,4,3,7,13,4,1,4,1,3,1,1,1,5,5,10,1,6,1,5,2,1,5,2,4,1,4,5,7,3,18,2,9,11,32,4,3,3,2,4,7,11,16,9,11,8,13,38, 32,8,4,2,1,1,2,1,2,4,4,1,1,1,4,1,21,3,11,1,16,1,1,6,1,3,2,4,9,8,57,7,44,1,3,3,13,3,10,1,1,7,5,2,7,21,47,63,3,15,4,7,1,16,1,1,2,8,2,3,42,15,4, 1,29,7,22,10,3,78,16,12,20,18,4,67,11,5,1,3,15,6,21,31,32,27,18,13,71,35,5,142,4,10,1,2,50,19,33,16,35,37,16,19,27,7,1,133,19,1,4,8,7,20,1,4, 4,1,10,3,1,6,1,2,51,5,40,15,24,43,22928,11,1,13,154,70,3,1,1,7,4,10,1,2,1,1,2,1,2,1,2,2,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1, 3,2,1,1,1,1,2,1,1, }; static ImWchar base_ranges[] = // not zero-terminated { 0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x3000, 0x30FF, // CJK Symbols and Punctuations, Hiragana, Katakana 0x31F0, 0x31FF, // Katakana Phonetic Extensions 0xFF00, 0xFFEF, // Half-width characters 0xFFFD, 0xFFFD // Invalid }; static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(accumulative_offsets_from_0x4E00)*2 + 1] = { 0 }; if (!full_ranges[0]) { memcpy(full_ranges, base_ranges, sizeof(base_ranges)); UnpackAccumulativeOffsetsIntoRanges(0x4E00, accumulative_offsets_from_0x4E00, IM_ARRAYSIZE(accumulative_offsets_from_0x4E00), full_ranges + IM_ARRAYSIZE(base_ranges)); } return &full_ranges[0]; } const ImWchar* ImFontAtlas::GetGlyphRangesCyrillic() { static const ImWchar ranges[] = { 0x0020, 0x00FF, // Basic Latin + Latin Supplement 0x0400, 0x052F, // Cyrillic + Cyrillic Supplement 0x2DE0, 0x2DFF, // Cyrillic Extended-A 0xA640, 0xA69F, // Cyrillic Extended-B 0, }; return &ranges[0]; } const ImWchar* ImFontAtlas::GetGlyphRangesThai() { static const ImWchar ranges[] = { 0x0020, 0x00FF, // Basic Latin 0x2010, 0x205E, // Punctuations 0x0E00, 0x0E7F, // Thai 0, }; return &ranges[0]; } const ImWchar* ImFontAtlas::GetGlyphRangesVietnamese() { static const ImWchar ranges[] = { 0x0020, 0x00FF, // Basic Latin 0x0102, 0x0103, 0x0110, 0x0111, 0x0128, 0x0129, 0x0168, 0x0169, 0x01A0, 0x01A1, 0x01AF, 0x01B0, 0x1EA0, 0x1EF9, 0, }; return &ranges[0]; } //----------------------------------------------------------------------------- // [SECTION] ImFontGlyphRangesBuilder //----------------------------------------------------------------------------- void ImFontGlyphRangesBuilder::AddText(const char* text, const char* text_end) { while (text_end ? (text < text_end) : *text) { unsigned int c = 0; int c_len = ImTextCharFromUtf8(&c, text, text_end); text += c_len; if (c_len == 0) break; AddChar((ImWchar)c); } } void ImFontGlyphRangesBuilder::AddRanges(const ImWchar* ranges) { for (; ranges[0]; ranges += 2) for (unsigned int c = ranges[0]; c <= ranges[1] && c <= IM_UNICODE_CODEPOINT_MAX; c++) //-V560 AddChar((ImWchar)c); } void ImFontGlyphRangesBuilder::BuildRanges(ImVector* out_ranges) { const int max_codepoint = IM_UNICODE_CODEPOINT_MAX; for (int n = 0; n <= max_codepoint; n++) if (GetBit(n)) { out_ranges->push_back((ImWchar)n); while (n < max_codepoint && GetBit(n + 1)) n++; out_ranges->push_back((ImWchar)n); } out_ranges->push_back(0); } //----------------------------------------------------------------------------- // [SECTION] ImFont //----------------------------------------------------------------------------- ImFont::ImFont() { FontSize = 0.0f; FallbackAdvanceX = 0.0f; FallbackChar = (ImWchar)-1; EllipsisChar = (ImWchar)-1; EllipsisWidth = EllipsisCharStep = 0.0f; EllipsisCharCount = 0; FallbackGlyph = NULL; ContainerAtlas = NULL; ConfigData = NULL; ConfigDataCount = 0; DirtyLookupTables = false; Scale = 1.0f; Ascent = Descent = 0.0f; MetricsTotalSurface = 0; memset(Used4kPagesMap, 0, sizeof(Used4kPagesMap)); } ImFont::~ImFont() { ClearOutputData(); } void ImFont::ClearOutputData() { FontSize = 0.0f; FallbackAdvanceX = 0.0f; Glyphs.clear(); IndexAdvanceX.clear(); IndexLookup.clear(); FallbackGlyph = NULL; ContainerAtlas = NULL; DirtyLookupTables = true; Ascent = Descent = 0.0f; MetricsTotalSurface = 0; } static ImWchar FindFirstExistingGlyph(ImFont* font, const ImWchar* candidate_chars, int candidate_chars_count) { for (int n = 0; n < candidate_chars_count; n++) if (font->FindGlyphNoFallback(candidate_chars[n]) != NULL) return candidate_chars[n]; return (ImWchar)-1; } void ImFont::BuildLookupTable() { int max_codepoint = 0; for (int i = 0; i != Glyphs.Size; i++) max_codepoint = ImMax(max_codepoint, (int)Glyphs[i].Codepoint); // Build lookup table IM_ASSERT(Glyphs.Size > 0 && "Font has not loaded glyph!"); IM_ASSERT(Glyphs.Size < 0xFFFF); // -1 is reserved IndexAdvanceX.clear(); IndexLookup.clear(); DirtyLookupTables = false; memset(Used4kPagesMap, 0, sizeof(Used4kPagesMap)); GrowIndex(max_codepoint + 1); for (int i = 0; i < Glyphs.Size; i++) { int codepoint = (int)Glyphs[i].Codepoint; IndexAdvanceX[codepoint] = Glyphs[i].AdvanceX; IndexLookup[codepoint] = (ImWchar)i; // Mark 4K page as used const int page_n = codepoint / 4096; Used4kPagesMap[page_n >> 3] |= 1 << (page_n & 7); } // Create a glyph to handle TAB // FIXME: Needs proper TAB handling but it needs to be contextualized (or we could arbitrary say that each string starts at "column 0" ?) if (FindGlyph((ImWchar)' ')) { if (Glyphs.back().Codepoint != '\t') // So we can call this function multiple times (FIXME: Flaky) Glyphs.resize(Glyphs.Size + 1); ImFontGlyph& tab_glyph = Glyphs.back(); tab_glyph = *FindGlyph((ImWchar)' '); tab_glyph.Codepoint = '\t'; tab_glyph.AdvanceX *= IM_TABSIZE; IndexAdvanceX[(int)tab_glyph.Codepoint] = (float)tab_glyph.AdvanceX; IndexLookup[(int)tab_glyph.Codepoint] = (ImWchar)(Glyphs.Size - 1); } // Mark special glyphs as not visible (note that AddGlyph already mark as non-visible glyphs with zero-size polygons) SetGlyphVisible((ImWchar)' ', false); SetGlyphVisible((ImWchar)'\t', false); // Setup Fallback character const ImWchar fallback_chars[] = { (ImWchar)IM_UNICODE_CODEPOINT_INVALID, (ImWchar)'?', (ImWchar)' ' }; FallbackGlyph = FindGlyphNoFallback(FallbackChar); if (FallbackGlyph == NULL) { FallbackChar = FindFirstExistingGlyph(this, fallback_chars, IM_ARRAYSIZE(fallback_chars)); FallbackGlyph = FindGlyphNoFallback(FallbackChar); if (FallbackGlyph == NULL) { FallbackGlyph = &Glyphs.back(); FallbackChar = (ImWchar)FallbackGlyph->Codepoint; } } FallbackAdvanceX = FallbackGlyph->AdvanceX; for (int i = 0; i < max_codepoint + 1; i++) if (IndexAdvanceX[i] < 0.0f) IndexAdvanceX[i] = FallbackAdvanceX; // Setup Ellipsis character. It is required for rendering elided text. We prefer using U+2026 (horizontal ellipsis). // However some old fonts may contain ellipsis at U+0085. Here we auto-detect most suitable ellipsis character. // FIXME: Note that 0x2026 is rarely included in our font ranges. Because of this we are more likely to use three individual dots. const ImWchar ellipsis_chars[] = { (ImWchar)0x2026, (ImWchar)0x0085 }; const ImWchar dots_chars[] = { (ImWchar)'.', (ImWchar)0xFF0E }; if (EllipsisChar == (ImWchar)-1) EllipsisChar = FindFirstExistingGlyph(this, ellipsis_chars, IM_ARRAYSIZE(ellipsis_chars)); const ImWchar dot_char = FindFirstExistingGlyph(this, dots_chars, IM_ARRAYSIZE(dots_chars)); if (EllipsisChar != (ImWchar)-1) { EllipsisCharCount = 1; EllipsisWidth = EllipsisCharStep = FindGlyph(EllipsisChar)->X1; } else if (dot_char != (ImWchar)-1) { const ImFontGlyph* glyph = FindGlyph(dot_char); EllipsisChar = dot_char; EllipsisCharCount = 3; EllipsisCharStep = (glyph->X1 - glyph->X0) + 1.0f; EllipsisWidth = EllipsisCharStep * 3.0f - 1.0f; } } // API is designed this way to avoid exposing the 4K page size // e.g. use with IsGlyphRangeUnused(0, 255) bool ImFont::IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last) { unsigned int page_begin = (c_begin / 4096); unsigned int page_last = (c_last / 4096); for (unsigned int page_n = page_begin; page_n <= page_last; page_n++) if ((page_n >> 3) < sizeof(Used4kPagesMap)) if (Used4kPagesMap[page_n >> 3] & (1 << (page_n & 7))) return false; return true; } void ImFont::SetGlyphVisible(ImWchar c, bool visible) { if (ImFontGlyph* glyph = (ImFontGlyph*)(void*)FindGlyph((ImWchar)c)) glyph->Visible = visible ? 1 : 0; } void ImFont::GrowIndex(int new_size) { IM_ASSERT(IndexAdvanceX.Size == IndexLookup.Size); if (new_size <= IndexLookup.Size) return; IndexAdvanceX.resize(new_size, -1.0f); IndexLookup.resize(new_size, (ImWchar)-1); } // x0/y0/x1/y1 are offset from the character upper-left layout position, in pixels. Therefore x0/y0 are often fairly close to zero. // Not to be mistaken with texture coordinates, which are held by u0/v0/u1/v1 in normalized format (0.0..1.0 on each texture axis). // 'cfg' is not necessarily == 'this->ConfigData' because multiple source fonts+configs can be used to build one target font. void ImFont::AddGlyph(const ImFontConfig* cfg, ImWchar codepoint, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x) { if (cfg != NULL) { // Clamp & recenter if needed const float advance_x_original = advance_x; advance_x = ImClamp(advance_x, cfg->GlyphMinAdvanceX, cfg->GlyphMaxAdvanceX); if (advance_x != advance_x_original) { float char_off_x = cfg->PixelSnapH ? ImTrunc((advance_x - advance_x_original) * 0.5f) : (advance_x - advance_x_original) * 0.5f; x0 += char_off_x; x1 += char_off_x; } // Snap to pixel if (cfg->PixelSnapH) advance_x = IM_ROUND(advance_x); // Bake spacing advance_x += cfg->GlyphExtraSpacing.x; } Glyphs.resize(Glyphs.Size + 1); ImFontGlyph& glyph = Glyphs.back(); glyph.Codepoint = (unsigned int)codepoint; glyph.Visible = (x0 != x1) && (y0 != y1); glyph.Colored = false; glyph.X0 = x0; glyph.Y0 = y0; glyph.X1 = x1; glyph.Y1 = y1; glyph.U0 = u0; glyph.V0 = v0; glyph.U1 = u1; glyph.V1 = v1; glyph.AdvanceX = advance_x; // Compute rough surface usage metrics (+1 to account for average padding, +0.99 to round) // We use (U1-U0)*TexWidth instead of X1-X0 to account for oversampling. float pad = ContainerAtlas->TexGlyphPadding + 0.99f; DirtyLookupTables = true; MetricsTotalSurface += (int)((glyph.U1 - glyph.U0) * ContainerAtlas->TexWidth + pad) * (int)((glyph.V1 - glyph.V0) * ContainerAtlas->TexHeight + pad); } void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst) { IM_ASSERT(IndexLookup.Size > 0); // Currently this can only be called AFTER the font has been built, aka after calling ImFontAtlas::GetTexDataAs*() function. unsigned int index_size = (unsigned int)IndexLookup.Size; if (dst < index_size && IndexLookup.Data[dst] == (ImWchar)-1 && !overwrite_dst) // 'dst' already exists return; if (src >= index_size && dst >= index_size) // both 'dst' and 'src' don't exist -> no-op return; GrowIndex(dst + 1); IndexLookup[dst] = (src < index_size) ? IndexLookup.Data[src] : (ImWchar)-1; IndexAdvanceX[dst] = (src < index_size) ? IndexAdvanceX.Data[src] : 1.0f; } const ImFontGlyph* ImFont::FindGlyph(ImWchar c) const { if (c >= (size_t)IndexLookup.Size) return FallbackGlyph; const ImWchar i = IndexLookup.Data[c]; if (i == (ImWchar)-1) return FallbackGlyph; return &Glyphs.Data[i]; } const ImFontGlyph* ImFont::FindGlyphNoFallback(ImWchar c) const { if (c >= (size_t)IndexLookup.Size) return NULL; const ImWchar i = IndexLookup.Data[c]; if (i == (ImWchar)-1) return NULL; return &Glyphs.Data[i]; } // Wrapping skips upcoming blanks static inline const char* CalcWordWrapNextLineStartA(const char* text, const char* text_end) { while (text < text_end && ImCharIsBlankA(*text)) text++; if (*text == '\n') text++; return text; } // Simple word-wrapping for English, not full-featured. Please submit failing cases! // This will return the next location to wrap from. If no wrapping if necessary, this will fast-forward to e.g. text_end. // FIXME: Much possible improvements (don't cut things like "word !", "word!!!" but cut within "word,,,,", more sensible support for punctuations, support for Unicode punctuations, etc.) const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const { // For references, possible wrap point marked with ^ // "aaa bbb, ccc,ddd. eee fff. ggg!" // ^ ^ ^ ^ ^__ ^ ^ // List of hardcoded separators: .,;!?'" // Skip extra blanks after a line returns (that includes not counting them in width computation) // e.g. "Hello world" --> "Hello" "World" // Cut words that cannot possibly fit within one line. // e.g.: "The tropical fish" with ~5 characters worth of width --> "The tr" "opical" "fish" float line_width = 0.0f; float word_width = 0.0f; float blank_width = 0.0f; wrap_width /= scale; // We work with unscaled widths to avoid scaling every characters const char* word_end = text; const char* prev_word_end = NULL; bool inside_word = true; const char* s = text; IM_ASSERT(text_end != NULL); while (s < text_end) { unsigned int c = (unsigned int)*s; const char* next_s; if (c < 0x80) next_s = s + 1; else next_s = s + ImTextCharFromUtf8(&c, s, text_end); if (c < 32) { if (c == '\n') { line_width = word_width = blank_width = 0.0f; inside_word = true; s = next_s; continue; } if (c == '\r') { s = next_s; continue; } } const float char_width = ((int)c < IndexAdvanceX.Size ? IndexAdvanceX.Data[c] : FallbackAdvanceX); if (ImCharIsBlankW(c)) { if (inside_word) { line_width += blank_width; blank_width = 0.0f; word_end = s; } blank_width += char_width; inside_word = false; } else { word_width += char_width; if (inside_word) { word_end = next_s; } else { prev_word_end = word_end; line_width += word_width + blank_width; word_width = blank_width = 0.0f; } // Allow wrapping after punctuation. inside_word = (c != '.' && c != ',' && c != ';' && c != '!' && c != '?' && c != '\"'); } // We ignore blank width at the end of the line (they can be skipped) if (line_width + word_width > wrap_width) { // Words that cannot possibly fit within an entire line will be cut anywhere. if (word_width < wrap_width) s = prev_word_end ? prev_word_end : word_end; break; } s = next_s; } // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity. // +1 may not be a character start point in UTF-8 but it's ok because caller loops use (text >= word_wrap_eol). if (s == text && text < text_end) return s + 1; return s; } ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining) const { if (!text_end) text_end = text_begin + strlen(text_begin); // FIXME-OPT: Need to avoid this. const float line_height = size; const float scale = size / FontSize; ImVec2 text_size = ImVec2(0, 0); float line_width = 0.0f; const bool word_wrap_enabled = (wrap_width > 0.0f); const char* word_wrap_eol = NULL; const char* s = text_begin; while (s < text_end) { if (word_wrap_enabled) { // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature. if (!word_wrap_eol) word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - line_width); if (s >= word_wrap_eol) { if (text_size.x < line_width) text_size.x = line_width; text_size.y += line_height; line_width = 0.0f; word_wrap_eol = NULL; s = CalcWordWrapNextLineStartA(s, text_end); // Wrapping skips upcoming blanks continue; } } // Decode and advance source const char* prev_s = s; unsigned int c = (unsigned int)*s; if (c < 0x80) s += 1; else s += ImTextCharFromUtf8(&c, s, text_end); if (c < 32) { if (c == '\n') { text_size.x = ImMax(text_size.x, line_width); text_size.y += line_height; line_width = 0.0f; continue; } if (c == '\r') continue; } const float char_width = ((int)c < IndexAdvanceX.Size ? IndexAdvanceX.Data[c] : FallbackAdvanceX) * scale; if (line_width + char_width >= max_width) { s = prev_s; break; } line_width += char_width; } if (text_size.x < line_width) text_size.x = line_width; if (line_width > 0 || text_size.y == 0.0f) text_size.y += line_height; if (remaining) *remaining = s; return text_size; } // Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound. void ImFont::RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, ImWchar c) const { const ImFontGlyph* glyph = FindGlyph(c); if (!glyph || !glyph->Visible) return; if (glyph->Colored) col |= ~IM_COL32_A_MASK; float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f; float x = IM_TRUNC(pos.x); float y = IM_TRUNC(pos.y); draw_list->PrimReserve(6, 4); draw_list->PrimRectUV(ImVec2(x + glyph->X0 * scale, y + glyph->Y0 * scale), ImVec2(x + glyph->X1 * scale, y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col); } // Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound. void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const { if (!text_end) text_end = text_begin + strlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls. // Align to be pixel perfect float x = IM_TRUNC(pos.x); float y = IM_TRUNC(pos.y); if (y > clip_rect.w) return; const float start_x = x; const float scale = size / FontSize; const float line_height = FontSize * scale; const bool word_wrap_enabled = (wrap_width > 0.0f); // Fast-forward to first visible line const char* s = text_begin; if (y + line_height < clip_rect.y) while (y + line_height < clip_rect.y && s < text_end) { const char* line_end = (const char*)memchr(s, '\n', text_end - s); if (word_wrap_enabled) { // FIXME-OPT: This is not optimal as do first do a search for \n before calling CalcWordWrapPositionA(). // If the specs for CalcWordWrapPositionA() were reworked to optionally return on \n we could combine both. // However it is still better than nothing performing the fast-forward! s = CalcWordWrapPositionA(scale, s, line_end ? line_end : text_end, wrap_width); s = CalcWordWrapNextLineStartA(s, text_end); } else { s = line_end ? line_end + 1 : text_end; } y += line_height; } // For large text, scan for the last visible line in order to avoid over-reserving in the call to PrimReserve() // Note that very large horizontal line will still be affected by the issue (e.g. a one megabyte string buffer without a newline will likely crash atm) if (text_end - s > 10000 && !word_wrap_enabled) { const char* s_end = s; float y_end = y; while (y_end < clip_rect.w && s_end < text_end) { s_end = (const char*)memchr(s_end, '\n', text_end - s_end); s_end = s_end ? s_end + 1 : text_end; y_end += line_height; } text_end = s_end; } if (s == text_end) return; // Reserve vertices for remaining worse case (over-reserving is useful and easily amortized) const int vtx_count_max = (int)(text_end - s) * 4; const int idx_count_max = (int)(text_end - s) * 6; const int idx_expected_size = draw_list->IdxBuffer.Size + idx_count_max; draw_list->PrimReserve(idx_count_max, vtx_count_max); ImDrawVert* vtx_write = draw_list->_VtxWritePtr; ImDrawIdx* idx_write = draw_list->_IdxWritePtr; unsigned int vtx_index = draw_list->_VtxCurrentIdx; const ImU32 col_untinted = col | ~IM_COL32_A_MASK; const char* word_wrap_eol = NULL; while (s < text_end) { if (word_wrap_enabled) { // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature. if (!word_wrap_eol) word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - (x - start_x)); if (s >= word_wrap_eol) { x = start_x; y += line_height; word_wrap_eol = NULL; s = CalcWordWrapNextLineStartA(s, text_end); // Wrapping skips upcoming blanks continue; } } // Decode and advance source unsigned int c = (unsigned int)*s; if (c < 0x80) s += 1; else s += ImTextCharFromUtf8(&c, s, text_end); if (c < 32) { if (c == '\n') { x = start_x; y += line_height; if (y > clip_rect.w) break; // break out of main loop continue; } if (c == '\r') continue; } const ImFontGlyph* glyph = FindGlyph((ImWchar)c); if (glyph == NULL) continue; float char_width = glyph->AdvanceX * scale; if (glyph->Visible) { // We don't do a second finer clipping test on the Y axis as we've already skipped anything before clip_rect.y and exit once we pass clip_rect.w float x1 = x + glyph->X0 * scale; float x2 = x + glyph->X1 * scale; float y1 = y + glyph->Y0 * scale; float y2 = y + glyph->Y1 * scale; if (x1 <= clip_rect.z && x2 >= clip_rect.x) { // Render a character float u1 = glyph->U0; float v1 = glyph->V0; float u2 = glyph->U1; float v2 = glyph->V1; // CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis aligned quads. if (cpu_fine_clip) { if (x1 < clip_rect.x) { u1 = u1 + (1.0f - (x2 - clip_rect.x) / (x2 - x1)) * (u2 - u1); x1 = clip_rect.x; } if (y1 < clip_rect.y) { v1 = v1 + (1.0f - (y2 - clip_rect.y) / (y2 - y1)) * (v2 - v1); y1 = clip_rect.y; } if (x2 > clip_rect.z) { u2 = u1 + ((clip_rect.z - x1) / (x2 - x1)) * (u2 - u1); x2 = clip_rect.z; } if (y2 > clip_rect.w) { v2 = v1 + ((clip_rect.w - y1) / (y2 - y1)) * (v2 - v1); y2 = clip_rect.w; } if (y1 >= y2) { x += char_width; continue; } } // Support for untinted glyphs ImU32 glyph_col = glyph->Colored ? col_untinted : col; // We are NOT calling PrimRectUV() here because non-inlined causes too much overhead in a debug builds. Inlined here: { vtx_write[0].pos.x = x1; vtx_write[0].pos.y = y1; vtx_write[0].col = glyph_col; vtx_write[0].uv.x = u1; vtx_write[0].uv.y = v1; vtx_write[1].pos.x = x2; vtx_write[1].pos.y = y1; vtx_write[1].col = glyph_col; vtx_write[1].uv.x = u2; vtx_write[1].uv.y = v1; vtx_write[2].pos.x = x2; vtx_write[2].pos.y = y2; vtx_write[2].col = glyph_col; vtx_write[2].uv.x = u2; vtx_write[2].uv.y = v2; vtx_write[3].pos.x = x1; vtx_write[3].pos.y = y2; vtx_write[3].col = glyph_col; vtx_write[3].uv.x = u1; vtx_write[3].uv.y = v2; idx_write[0] = (ImDrawIdx)(vtx_index); idx_write[1] = (ImDrawIdx)(vtx_index + 1); idx_write[2] = (ImDrawIdx)(vtx_index + 2); idx_write[3] = (ImDrawIdx)(vtx_index); idx_write[4] = (ImDrawIdx)(vtx_index + 2); idx_write[5] = (ImDrawIdx)(vtx_index + 3); vtx_write += 4; vtx_index += 4; idx_write += 6; } } } x += char_width; } // Give back unused vertices (clipped ones, blanks) ~ this is essentially a PrimUnreserve() action. draw_list->VtxBuffer.Size = (int)(vtx_write - draw_list->VtxBuffer.Data); // Same as calling shrink() draw_list->IdxBuffer.Size = (int)(idx_write - draw_list->IdxBuffer.Data); draw_list->CmdBuffer[draw_list->CmdBuffer.Size - 1].ElemCount -= (idx_expected_size - draw_list->IdxBuffer.Size); draw_list->_VtxWritePtr = vtx_write; draw_list->_IdxWritePtr = idx_write; draw_list->_VtxCurrentIdx = vtx_index; } //----------------------------------------------------------------------------- // [SECTION] ImGui Internal Render Helpers //----------------------------------------------------------------------------- // Vaguely redesigned to stop accessing ImGui global state: // - RenderArrow() // - RenderBullet() // - RenderCheckMark() // - RenderArrowPointingAt() // - RenderRectFilledRangeH() // - RenderRectFilledWithHole() //----------------------------------------------------------------------------- // Function in need of a redesign (legacy mess) // - RenderColorRectWithAlphaCheckerboard() //----------------------------------------------------------------------------- // Render an arrow aimed to be aligned with text (p_min is a position in the same space text would be positioned). To e.g. denote expanded/collapsed state void ImGui::RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale) { const float h = draw_list->_Data->FontSize * 1.00f; float r = h * 0.40f * scale; ImVec2 center = pos + ImVec2(h * 0.50f, h * 0.50f * scale); ImVec2 a, b, c; switch (dir) { case ImGuiDir_Up: case ImGuiDir_Down: if (dir == ImGuiDir_Up) r = -r; a = ImVec2(+0.000f, +0.750f) * r; b = ImVec2(-0.866f, -0.750f) * r; c = ImVec2(+0.866f, -0.750f) * r; break; case ImGuiDir_Left: case ImGuiDir_Right: if (dir == ImGuiDir_Left) r = -r; a = ImVec2(+0.750f, +0.000f) * r; b = ImVec2(-0.750f, +0.866f) * r; c = ImVec2(-0.750f, -0.866f) * r; break; case ImGuiDir_None: case ImGuiDir_COUNT: IM_ASSERT(0); break; } draw_list->AddTriangleFilled(center + a, center + b, center + c, col); } void ImGui::RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col) { // FIXME-OPT: This should be baked in font. draw_list->AddCircleFilled(pos, draw_list->_Data->FontSize * 0.20f, col, 8); } void ImGui::RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz) { float thickness = ImMax(sz / 5.0f, 1.0f); sz -= thickness * 0.5f; pos += ImVec2(thickness * 0.25f, thickness * 0.25f); float third = sz / 3.0f; float bx = pos.x + third; float by = pos.y + sz - third * 0.5f; draw_list->PathLineTo(ImVec2(bx - third, by - third)); draw_list->PathLineTo(ImVec2(bx, by)); draw_list->PathLineTo(ImVec2(bx + third * 2.0f, by - third * 2.0f)); draw_list->PathStroke(col, 0, thickness); } // Render an arrow. 'pos' is position of the arrow tip. half_sz.x is length from base to tip. half_sz.y is length on each side. void ImGui::RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col) { switch (direction) { case ImGuiDir_Left: draw_list->AddTriangleFilled(ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), ImVec2(pos.x + half_sz.x, pos.y + half_sz.y), pos, col); return; case ImGuiDir_Right: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), pos, col); return; case ImGuiDir_Up: draw_list->AddTriangleFilled(ImVec2(pos.x + half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), pos, col); return; case ImGuiDir_Down: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), pos, col); return; case ImGuiDir_None: case ImGuiDir_COUNT: break; // Fix warnings } } static inline float ImAcos01(float x) { if (x <= 0.0f) return IM_PI * 0.5f; if (x >= 1.0f) return 0.0f; return ImAcos(x); //return (-0.69813170079773212f * x * x - 0.87266462599716477f) * x + 1.5707963267948966f; // Cheap approximation, may be enough for what we do. } // FIXME: Cleanup and move code to ImDrawList. void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding) { if (x_end_norm == x_start_norm) return; if (x_start_norm > x_end_norm) ImSwap(x_start_norm, x_end_norm); ImVec2 p0 = ImVec2(ImLerp(rect.Min.x, rect.Max.x, x_start_norm), rect.Min.y); ImVec2 p1 = ImVec2(ImLerp(rect.Min.x, rect.Max.x, x_end_norm), rect.Max.y); if (rounding == 0.0f) { draw_list->AddRectFilled(p0, p1, col, 0.0f); return; } rounding = ImClamp(ImMin((rect.Max.x - rect.Min.x) * 0.5f, (rect.Max.y - rect.Min.y) * 0.5f) - 1.0f, 0.0f, rounding); const float inv_rounding = 1.0f / rounding; const float arc0_b = ImAcos01(1.0f - (p0.x - rect.Min.x) * inv_rounding); const float arc0_e = ImAcos01(1.0f - (p1.x - rect.Min.x) * inv_rounding); const float half_pi = IM_PI * 0.5f; // We will == compare to this because we know this is the exact value ImAcos01 can return. const float x0 = ImMax(p0.x, rect.Min.x + rounding); if (arc0_b == arc0_e) { draw_list->PathLineTo(ImVec2(x0, p1.y)); draw_list->PathLineTo(ImVec2(x0, p0.y)); } else if (arc0_b == 0.0f && arc0_e == half_pi) { draw_list->PathArcToFast(ImVec2(x0, p1.y - rounding), rounding, 3, 6); // BL draw_list->PathArcToFast(ImVec2(x0, p0.y + rounding), rounding, 6, 9); // TR } else { draw_list->PathArcTo(ImVec2(x0, p1.y - rounding), rounding, IM_PI - arc0_e, IM_PI - arc0_b, 3); // BL draw_list->PathArcTo(ImVec2(x0, p0.y + rounding), rounding, IM_PI + arc0_b, IM_PI + arc0_e, 3); // TR } if (p1.x > rect.Min.x + rounding) { const float arc1_b = ImAcos01(1.0f - (rect.Max.x - p1.x) * inv_rounding); const float arc1_e = ImAcos01(1.0f - (rect.Max.x - p0.x) * inv_rounding); const float x1 = ImMin(p1.x, rect.Max.x - rounding); if (arc1_b == arc1_e) { draw_list->PathLineTo(ImVec2(x1, p0.y)); draw_list->PathLineTo(ImVec2(x1, p1.y)); } else if (arc1_b == 0.0f && arc1_e == half_pi) { draw_list->PathArcToFast(ImVec2(x1, p0.y + rounding), rounding, 9, 12); // TR draw_list->PathArcToFast(ImVec2(x1, p1.y - rounding), rounding, 0, 3); // BR } else { draw_list->PathArcTo(ImVec2(x1, p0.y + rounding), rounding, -arc1_e, -arc1_b, 3); // TR draw_list->PathArcTo(ImVec2(x1, p1.y - rounding), rounding, +arc1_b, +arc1_e, 3); // BR } } draw_list->PathFillConvex(col); } void ImGui::RenderRectFilledWithHole(ImDrawList* draw_list, const ImRect& outer, const ImRect& inner, ImU32 col, float rounding) { const bool fill_L = (inner.Min.x > outer.Min.x); const bool fill_R = (inner.Max.x < outer.Max.x); const bool fill_U = (inner.Min.y > outer.Min.y); const bool fill_D = (inner.Max.y < outer.Max.y); if (fill_L) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Min.y), ImVec2(inner.Min.x, inner.Max.y), col, rounding, ImDrawFlags_RoundCornersNone | (fill_U ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomLeft)); if (fill_R) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Min.y), ImVec2(outer.Max.x, inner.Max.y), col, rounding, ImDrawFlags_RoundCornersNone | (fill_U ? 0 : ImDrawFlags_RoundCornersTopRight) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomRight)); if (fill_U) draw_list->AddRectFilled(ImVec2(inner.Min.x, outer.Min.y), ImVec2(inner.Max.x, inner.Min.y), col, rounding, ImDrawFlags_RoundCornersNone | (fill_L ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersTopRight)); if (fill_D) draw_list->AddRectFilled(ImVec2(inner.Min.x, inner.Max.y), ImVec2(inner.Max.x, outer.Max.y), col, rounding, ImDrawFlags_RoundCornersNone | (fill_L ? 0 : ImDrawFlags_RoundCornersBottomLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersBottomRight)); if (fill_L && fill_U) draw_list->AddRectFilled(ImVec2(outer.Min.x, outer.Min.y), ImVec2(inner.Min.x, inner.Min.y), col, rounding, ImDrawFlags_RoundCornersTopLeft); if (fill_R && fill_U) draw_list->AddRectFilled(ImVec2(inner.Max.x, outer.Min.y), ImVec2(outer.Max.x, inner.Min.y), col, rounding, ImDrawFlags_RoundCornersTopRight); if (fill_L && fill_D) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Max.y), ImVec2(inner.Min.x, outer.Max.y), col, rounding, ImDrawFlags_RoundCornersBottomLeft); if (fill_R && fill_D) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Max.y), ImVec2(outer.Max.x, outer.Max.y), col, rounding, ImDrawFlags_RoundCornersBottomRight); } // Helper for ColorPicker4() // NB: This is rather brittle and will show artifact when rounding this enabled if rounded corners overlap multiple cells. Caller currently responsible for avoiding that. // Spent a non reasonable amount of time trying to getting this right for ColorButton with rounding+anti-aliasing+ImGuiColorEditFlags_HalfAlphaPreview flag + various grid sizes and offsets, and eventually gave up... probably more reasonable to disable rounding altogether. // FIXME: uses ImGui::GetColorU32 void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 col, float grid_step, ImVec2 grid_off, float rounding, ImDrawFlags flags) { if ((flags & ImDrawFlags_RoundCornersMask_) == 0) flags = ImDrawFlags_RoundCornersDefault_; if (((col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) < 0xFF) { ImU32 col_bg1 = GetColorU32(ImAlphaBlendColors(IM_COL32(204, 204, 204, 255), col)); ImU32 col_bg2 = GetColorU32(ImAlphaBlendColors(IM_COL32(128, 128, 128, 255), col)); draw_list->AddRectFilled(p_min, p_max, col_bg1, rounding, flags); int yi = 0; for (float y = p_min.y + grid_off.y; y < p_max.y; y += grid_step, yi++) { float y1 = ImClamp(y, p_min.y, p_max.y), y2 = ImMin(y + grid_step, p_max.y); if (y2 <= y1) continue; for (float x = p_min.x + grid_off.x + (yi & 1) * grid_step; x < p_max.x; x += grid_step * 2.0f) { float x1 = ImClamp(x, p_min.x, p_max.x), x2 = ImMin(x + grid_step, p_max.x); if (x2 <= x1) continue; ImDrawFlags cell_flags = ImDrawFlags_RoundCornersNone; if (y1 <= p_min.y) { if (x1 <= p_min.x) cell_flags |= ImDrawFlags_RoundCornersTopLeft; if (x2 >= p_max.x) cell_flags |= ImDrawFlags_RoundCornersTopRight; } if (y2 >= p_max.y) { if (x1 <= p_min.x) cell_flags |= ImDrawFlags_RoundCornersBottomLeft; if (x2 >= p_max.x) cell_flags |= ImDrawFlags_RoundCornersBottomRight; } // Combine flags cell_flags = (flags == ImDrawFlags_RoundCornersNone || cell_flags == ImDrawFlags_RoundCornersNone) ? ImDrawFlags_RoundCornersNone : (cell_flags & flags); draw_list->AddRectFilled(ImVec2(x1, y1), ImVec2(x2, y2), col_bg2, rounding, cell_flags); } } } else { draw_list->AddRectFilled(p_min, p_max, col, rounding, flags); } } //----------------------------------------------------------------------------- // [SECTION] Decompression code //----------------------------------------------------------------------------- // Compressed with stb_compress() then converted to a C array and encoded as base85. // Use the program in misc/fonts/binary_to_compressed_c.cpp to create the array from a TTF file. // The purpose of encoding as base85 instead of "0x00,0x01,..." style is only save on _source code_ size. // Decompression from stb.h (public domain) by Sean Barrett https://github.com/nothings/stb/blob/master/stb.h //----------------------------------------------------------------------------- static unsigned int stb_decompress_length(const unsigned char *input) { return (input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]; } static unsigned char *stb__barrier_out_e, *stb__barrier_out_b; static const unsigned char *stb__barrier_in_b; static unsigned char *stb__dout; static void stb__match(const unsigned char *data, unsigned int length) { // INVERSE of memmove... write each byte before copying the next... IM_ASSERT(stb__dout + length <= stb__barrier_out_e); if (stb__dout + length > stb__barrier_out_e) { stb__dout += length; return; } if (data < stb__barrier_out_b) { stb__dout = stb__barrier_out_e+1; return; } while (length--) *stb__dout++ = *data++; } static void stb__lit(const unsigned char *data, unsigned int length) { IM_ASSERT(stb__dout + length <= stb__barrier_out_e); if (stb__dout + length > stb__barrier_out_e) { stb__dout += length; return; } if (data < stb__barrier_in_b) { stb__dout = stb__barrier_out_e+1; return; } memcpy(stb__dout, data, length); stb__dout += length; } #define stb__in2(x) ((i[x] << 8) + i[(x)+1]) #define stb__in3(x) ((i[x] << 16) + stb__in2((x)+1)) #define stb__in4(x) ((i[x] << 24) + stb__in3((x)+1)) static const unsigned char *stb_decompress_token(const unsigned char *i) { if (*i >= 0x20) { // use fewer if's for cases that expand small if (*i >= 0x80) stb__match(stb__dout-i[1]-1, i[0] - 0x80 + 1), i += 2; else if (*i >= 0x40) stb__match(stb__dout-(stb__in2(0) - 0x4000 + 1), i[2]+1), i += 3; else /* *i >= 0x20 */ stb__lit(i+1, i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1); } else { // more ifs for cases that expand large, since overhead is amortized if (*i >= 0x18) stb__match(stb__dout-(stb__in3(0) - 0x180000 + 1), i[3]+1), i += 4; else if (*i >= 0x10) stb__match(stb__dout-(stb__in3(0) - 0x100000 + 1), stb__in2(3)+1), i += 5; else if (*i >= 0x08) stb__lit(i+2, stb__in2(0) - 0x0800 + 1), i += 2 + (stb__in2(0) - 0x0800 + 1); else if (*i == 0x07) stb__lit(i+3, stb__in2(1) + 1), i += 3 + (stb__in2(1) + 1); else if (*i == 0x06) stb__match(stb__dout-(stb__in3(1)+1), i[4]+1), i += 5; else if (*i == 0x04) stb__match(stb__dout-(stb__in3(1)+1), stb__in2(4)+1), i += 6; } return i; } static unsigned int stb_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen) { const unsigned long ADLER_MOD = 65521; unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16; unsigned long blocklen = buflen % 5552; unsigned long i; while (buflen) { for (i=0; i + 7 < blocklen; i += 8) { s1 += buffer[0], s2 += s1; s1 += buffer[1], s2 += s1; s1 += buffer[2], s2 += s1; s1 += buffer[3], s2 += s1; s1 += buffer[4], s2 += s1; s1 += buffer[5], s2 += s1; s1 += buffer[6], s2 += s1; s1 += buffer[7], s2 += s1; buffer += 8; } for (; i < blocklen; ++i) s1 += *buffer++, s2 += s1; s1 %= ADLER_MOD, s2 %= ADLER_MOD; buflen -= blocklen; blocklen = 5552; } return (unsigned int)(s2 << 16) + (unsigned int)s1; } static unsigned int stb_decompress(unsigned char *output, const unsigned char *i, unsigned int /*length*/) { if (stb__in4(0) != 0x57bC0000) return 0; if (stb__in4(4) != 0) return 0; // error! stream is > 4GB const unsigned int olen = stb_decompress_length(i); stb__barrier_in_b = i; stb__barrier_out_e = output + olen; stb__barrier_out_b = output; i += 16; stb__dout = output; for (;;) { const unsigned char *old_i = i; i = stb_decompress_token(i); if (i == old_i) { if (*i == 0x05 && i[1] == 0xfa) { IM_ASSERT(stb__dout == output + olen); if (stb__dout != output + olen) return 0; if (stb_adler32(1, output, olen) != (unsigned int) stb__in4(2)) return 0; return olen; } else { IM_ASSERT(0); /* NOTREACHED */ return 0; } } IM_ASSERT(stb__dout <= output + olen); if (stb__dout > output + olen) return 0; } } //----------------------------------------------------------------------------- // [SECTION] Default font data (ProggyClean.ttf) //----------------------------------------------------------------------------- // ProggyClean.ttf // Copyright (c) 2004, 2005 Tristan Grimmer // MIT license (see License.txt in http://www.proggyfonts.net/index.php?menu=download) // Download and more information at http://www.proggyfonts.net or http://upperboundsinteractive.com/fonts.php //----------------------------------------------------------------------------- // File: 'ProggyClean.ttf' (41208 bytes) // Exported using misc/fonts/binary_to_compressed_c.cpp (with compression + base85 string encoding). // The purpose of encoding as base85 instead of "0x00,0x01,..." style is only save on _source code_ size. //----------------------------------------------------------------------------- static const char proggy_clean_ttf_compressed_data_base85[11980 + 1] = "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/" "2*>]b(MC;$jPfY.;h^`IWM9Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1=Ke$$'5F%)]0^#0X@U.a$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;--VsM.M0rJfLH2eTM`*oJMHRC`N" "kfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`�j@'DbG&#^$PG.Ll+DNa&VZ>1i%h1S9u5o@YaaW$e+bROPOpxTO7Stwi1::iB1q)C_=dV26J;2,]7op$]uQr@_V7$q^%lQwtuHY]=DX,n3L#0PHDO4f9>dC@O>HBuKPpP*E,N+b3L#lpR/MrTEH.IAQk.a>D[.e;mc." "x]Ip.PH^'/aqUO/$1WxLoW0[iLAw=4h(9.`G" "CRUxHPeR`5Mjol(dUWxZa(>STrPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?Ggv:[7MI2k).'2($5FNP&EQ(,)" "U]W]+fh18.vsai00);D3@4ku5P?DP8aJt+;qUM]=+b'8@;mViBKx0DE[-auGl8:PJ&Dj+M6OC]O^((##]`0i)drT;-7X`=-H3[igUnPG-NZlo.#k@h#=Ork$m>a>$-?Tm$UV(?#P6YY#" "'/###xe7q.73rI3*pP/$1>s9)W,JrM7SN]'/4C#v$U`0#V.[0>xQsH$fEmPMgY2u7Kh(G%siIfLSoS+MK2eTM$=5,M8p`A.;_R%#u[K#$x4AG8.kK/HSB==-'Ie/QTtG?-.*^N-4B/ZM" "_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0+WomX2u7lqM2iEumMTcsF?-aT=Z-97UEnXglEn1K-bnEO`gu" "Ft(c%=;Am_Qs@jLooI&NX;]0#j4#F14;gl8-GQpgwhrq8'=l_f-b49'UOqkLu7-##oDY2L(te+Mch&gLYtJ,MEtJfLh'x'M=$CS-ZZ%P]8bZ>#S?YY#%Q&q'3^Fw&?D)UDNrocM3A76/" "/oL?#h7gl85[qW/NDOk%16ij;+:1a'iNIdb-ou8.P*w,v5#EI$TWS>Pot-R*H'-SEpA:g)f+O$%%`kA#G=8RMmG1&O`>to8bC]T&$,n.LoO>29sp3dt-52U%VM#q7'DHpg+#Z9%H[Ket`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO" "j%2n8)),?ILR5^.Ibn<-X-Mq7[a82Lq:F&#ce+S9wsCK*x`569E8ew'He]h:sI[2LM$[guka3ZRd6:t%IG:;$%YiJ:Nq=?eAw;/:nnDq0(CYcMpG)qLN4$##&J-XTt,%OVU4)S1+R-#dg0/Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%" "LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$MhLbxfc$mj`,O;&%W2m`Zh:/)Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.*'&0D[Ca]J9gp8,kAW]" "%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(et" "Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:" "a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>Q&#WIo)0@F%q7c#4XAXN-U&VBpqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<-+k?'(^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3M" "D?@f&1'BW-)Ju#bmmWCMkk&#TR`C,5d>g)F;t,4:@_l8G/5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX(" "P?^@Po3$##`MSs?DWBZ/S>+4%>fX,VWv/w'KD`LP5IbH;rTV>n3cEK8U#bX]l-/V+^lj3;vlMb&[5YQ8#pekX9JP3XUC72L,,?+Ni&co7ApnO*5NK,((W-i:$,kp'UDAO(G0Sq7MVjJs" "bIu)'Z,*[>br5fX^:FPAWr-m2KgLQ_nN6'8uTGT5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q" "h4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//,]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aege0jT6'N#(q%.O=?2S]u*(m<-" "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i" "sZ88+dKQ)W6>J%CL`.d*(B`-n8D9oK-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P r+$%CE=68>K8r0=dSC%%(@p7" ".m7jilQ02'0-VWAgTlGW'b)Tq7VT9q^*^$$.:&N@@" "$&)WHtPm*5_rO0&e%K&#-30j(E4#'Zb.o/(Tpm$>K'f@[PvFl,hfINTNU6u'0pao7%XUp9]5.>%h`8_=VYbxuel.NTSsJfLacFu3B'lQSu/m6-Oqem8T+oE--$0a/k]uj9EwsG>%veR*" "hv^BFpQj:K'#SJ,sB-'#](j.Lg92rTw-*n%@/;39rrJF,l#qV%OrtBeC6/,;qB3ebNW[?,Hqj2L.1NP&GjUR=1D8QaS3Up&@*9wP?+lo7b?@%'k4`p0Z$22%K3+iCZj?XJN4Nm&+YF]u" "@-W$U%VEQ/,,>>#)D#%8cY#YZ?=,`Wdxu/ae&#" "w6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$so8lKN%5/$(vdfq7+ebA#" "u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoFDoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8" "6e%B/:=>)N4xeW.*wft-;$'58-ESqr#U`'6AQ]m&6/`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*c&#" "b0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/TQ:(Z^xBdLjLV#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hL&#SfD07&6D@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5" "_>@kXQtMacfD.m-VAb8;IReM3$wf0''hra*so568'Ip&vRs849'MRYSp%:t:h5qSgwpEr$B>Q,;s(C#$)`svQuF$##-D,##,g68@2[T;.XSdN9Qe)rpt._K-#5wF)sP'##p#C0c%-Gb%" "hd+<-j'Ai*x&&HMkT]C'OSl##5RG[JXaHN;d'uA#x._U;.`PU@(Z3dt4r152@:v,'R.Sj'w#0<-;kPI)FfJ&#AYJ&#//)>-k=m=*XnK$>=)72L]0I%>.G690a:$##<,);?;72#?x9+d;" "^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmLq9wI>P(9mI[>kC-ekLC/R&CH+s'B;K-M6$EB%is00:" "+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3$U4O]GKx'm9)b@p7YsvK3w^YR-" "CdQ*:Ir<($u&)#(&?L9Rg3H)4fiEp^iI9O8KnTj,]H?D*r7'M;PwZ9K0E^k&-cpI;.p/6_vwoFMV<->#%Xi.LxVnrU(4&8/P+:hLSKj$#U%]49t'I:rgMi'FL@a:0Y-uA[39',(vbma*" "hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdFTi1O*H&#(AL8[_P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IXSsDiWP,##P`%/L-" "S(qw%sf/@%#B6;/U7K]uZbi^Oc^2n%t<)'mEVE''n`WnJra$^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdFl*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/Coh58KKhLj" "M=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO&#$(>.Z-I&J(Q0Hd5Q%7Co-b`-cP)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8WlA2);Sa" ">gXm8YB`1d@K#n]76-a$U,mF%Ul:#/'xoFM9QX-$.QN'>" "[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`P&#eb#.3i)rtB61(o'$?X3B2Qft^ae_5tKL9MUe9b*sLEQ95C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@I" "wOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs,eD9>XW8?N]o+(*pgC%/72LV-uW%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_KEBFkO'oU]^=[-792#ok,)" "i]lR8qQ2oA8wcRCZ^7w/Njh;?.stX?Q1>S1q4Bn$)K1<-rGdO'$Wr.Lc.CG)$/*JL4tNR/,SVO3,aUw'DJN:)Ss;wGn9A32ijw%FL+Z0Fn.U9;reSq)bmI32U==5ALuG&#Vf1398/pVo" "1*c-(aY168o<`JsSbk-,1N;$>0:OUas(3:8Z972LSfF8eb=c-;>SPw7.6hn3m`9^Xkn(r.qS[0;T%&Qc=+STRxX'q1BNk3&*eu2;&8q$&x>Q#Q7^Tf+6<(d%ZVmj2bDi%.3L2n+4W'$P" "iDDG)g,r%+?,$@?uou5tSe2aN_AQU*'IAO" "URQ##V^Fv-XFbGM7Fl(N<3DhLGF%q.1rC$#:T__&Pi68%0xi_&[qFJ(77j_&JWoF.V735&T,[R*:xFR*K5>>#`bW-?4Ne_&6Ne_&6Ne_&n`kr-#GJcM6X;uM6X;uM(.a..^2TkL%oR(#" ";u.T%fAr%4tJ8&><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4T" "w$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4" "A1OY5EI0;6Ibgr6M$HS7Q<)58C5w,;WoA*#[%T*#`1g*#d=#+#hI5+#lUG+#pbY+#tnl+#x$),#&1;,#*=M,#.I`,#2Ur,#6b.-#;w[H#iQtA#m^0B#qjBB#uvTB##-hB#'9$C#+E6C#" "/QHC#3^ZC#7jmC#;v)D#?,)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP" "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp" "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#"; static const char* GetDefaultCompressedFontDataTTFBase85() { return proggy_clean_ttf_compressed_data_base85; } #endif // #ifndef IMGUI_DISABLE RenderKit-ospray-f2a61c2/apps/common/external/imgui/imgui_impl_glfw.cpp000066400000000000000000001333031456566705700264170ustar00rootroot00000000000000// dear imgui: Platform Backend for GLFW // This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..) // (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) // (Requires: GLFW 3.1+. Prefer GLFW 3.3+ or GLFW 3.4+ for full feature support.) // Implemented features: // [X] Platform: Clipboard support. // [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only). // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+). // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // Learn about Dear ImGui: // - FAQ https://dearimgui.com/faq // - Getting Started https://dearimgui.com/getting-started // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). // - Introduction, links and more at the top of imgui.cpp // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2023-12-19: Emscripten: Added ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback() to register canvas selector and auto-resize GLFW window. // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys. // 2023-07-18: Inputs: Revert ignoring mouse data on GLFW_CURSOR_DISABLED as it can be used differently. User may set ImGuiConfigFLags_NoMouse if desired. (#5625, #6609) // 2023-06-12: Accept glfwGetTime() not returning a monotonically increasing value. This seems to happens on some Windows setup when peripherals disconnect, and is likely to also happen on browser + Emscripten. (#6491) // 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen/ImGuiMouseSource_Pen on Windows ONLY, using a custom WndProc hook. (#2702) // 2023-03-16: Inputs: Fixed key modifiers handling on secondary viewports (docking branch). Broken on 2023/01/04. (#6248, #6034) // 2023-03-14: Emscripten: Avoid using glfwGetError() and glfwGetGamepadState() which are not correctly implemented in Emscripten emulation. (#6240) // 2023-02-03: Emscripten: Registering custom low-level mouse wheel handler to get more accurate scrolling impulses on Emscripten. (#4019, #6096) // 2023-01-04: Inputs: Fixed mods state on Linux when using Alt-GR text input (e.g. German keyboard layout), could lead to broken text input. Revert a 2022/01/17 change were we resumed using mods provided by GLFW, turns out they were faulty. // 2022-11-22: Perform a dummy glfwGetError() read to cancel missing names with glfwGetKeyName(). (#5908) // 2022-10-18: Perform a dummy glfwGetError() read to cancel missing mouse cursors errors. Using GLFW_VERSION_COMBINED directly. (#5785) // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. // 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported). // 2022-09-01: Inputs: Honor GLFW_CURSOR_DISABLED by not setting mouse position *EDIT* Reverted 2023-07-18. // 2022-04-30: Inputs: Fixed ImGui_ImplGlfw_TranslateUntranslatedKey() for lower case letters on OSX. // 2022-03-23: Inputs: Fixed a regression in 1.87 which resulted in keyboard modifiers events being reported incorrectly on Linux/X11. // 2022-02-07: Added ImGui_ImplGlfw_InstallCallbacks()/ImGui_ImplGlfw_RestoreCallbacks() helpers to facilitate user installing callbacks after initializing backend. // 2022-01-26: Inputs: replaced short-lived io.AddKeyModsEvent() (added two weeks ago) with io.AddKeyEvent() using ImGuiKey_ModXXX flags. Sorry for the confusion. // 2021-01-20: Inputs: calling new io.AddKeyAnalogEvent() for gamepad support, instead of writing directly to io.NavInputs[]. // 2022-01-17: Inputs: calling new io.AddMousePosEvent(), io.AddMouseButtonEvent(), io.AddMouseWheelEvent() API (1.87+). // 2022-01-17: Inputs: always update key mods next and before key event (not in NewFrame) to fix input queue with very low framerates. // 2022-01-12: *BREAKING CHANGE*: Now using glfwSetCursorPosCallback(). If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetCursorPosCallback() and forward it to the backend via ImGui_ImplGlfw_CursorPosCallback(). // 2022-01-10: Inputs: calling new io.AddKeyEvent(), io.AddKeyModsEvent() + io.SetKeyEventNativeData() API (1.87+). Support for full ImGuiKey range. // 2022-01-05: Inputs: Converting GLFW untranslated keycodes back to translated keycodes (in the ImGui_ImplGlfw_KeyCallback() function) in order to match the behavior of every other backend, and facilitate the use of GLFW with lettered-shortcuts API. // 2021-08-17: *BREAKING CHANGE*: Now using glfwSetWindowFocusCallback() to calling io.AddFocusEvent(). If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() and forward it to the backend via ImGui_ImplGlfw_WindowFocusCallback(). // 2021-07-29: *BREAKING CHANGE*: Now using glfwSetCursorEnterCallback(). MousePos is correctly reported when the host platform window is hovered but not focused. If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() callback and forward it to the backend via ImGui_ImplGlfw_CursorEnterCallback(). // 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). // 2020-01-17: Inputs: Disable error callback while assigning mouse cursors because some X11 setup don't have them and it generates errors. // 2019-12-05: Inputs: Added support for new mouse cursors added in GLFW 3.4+ (resizing cursors, not allowed cursor). // 2019-10-18: Misc: Previously installed user callbacks are now restored on shutdown. // 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter. // 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter(). // 2019-03-12: Misc: Preserve DisplayFramebufferScale when main window is minimized. // 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window. // 2018-11-07: Inputs: When installing our GLFW callbacks, we save user's previously installed ones - if any - and chain call them. // 2018-08-01: Inputs: Workaround for Emscripten which doesn't seem to handle focus related calls. // 2018-06-29: Inputs: Added support for the ImGuiMouseCursor_Hand cursor. // 2018-06-08: Misc: Extracted imgui_impl_glfw.cpp/.h away from the old combined GLFW+OpenGL/Vulkan examples. // 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value, passed to glfwSetCursor()). // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. // 2018-01-25: Inputs: Added gamepad support if ImGuiConfigFlags_NavEnableGamepad is set. // 2018-01-25: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). // 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. // 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert. // 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1). // 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers. #include "imgui.h" #ifndef IMGUI_DISABLE #include "imgui_impl_glfw.h" // Clang warnings with -Weverything #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast #pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness #endif // GLFW #include #ifdef _WIN32 #undef APIENTRY #define GLFW_EXPOSE_NATIVE_WIN32 #include // for glfwGetWin32Window() #endif #ifdef __APPLE__ #define GLFW_EXPOSE_NATIVE_COCOA #include // for glfwGetCocoaWindow() #endif #ifdef __EMSCRIPTEN__ #include #include #endif // We gather version tests as define in order to easily see which features are version-dependent. #define GLFW_VERSION_COMBINED (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 + GLFW_VERSION_REVISION) #ifdef GLFW_RESIZE_NESW_CURSOR // Let's be nice to people who pulled GLFW between 2019-04-16 (3.4 define) and 2019-11-29 (cursors defines) // FIXME: Remove when GLFW 3.4 is released? #define GLFW_HAS_NEW_CURSORS (GLFW_VERSION_COMBINED >= 3400) // 3.4+ GLFW_RESIZE_ALL_CURSOR, GLFW_RESIZE_NESW_CURSOR, GLFW_RESIZE_NWSE_CURSOR, GLFW_NOT_ALLOWED_CURSOR #else #define GLFW_HAS_NEW_CURSORS (0) #endif #define GLFW_HAS_GAMEPAD_API (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetGamepadState() new api #define GLFW_HAS_GETKEYNAME (GLFW_VERSION_COMBINED >= 3200) // 3.2+ glfwGetKeyName() #define GLFW_HAS_GETERROR (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetError() // GLFW data enum GlfwClientApi { GlfwClientApi_Unknown, GlfwClientApi_OpenGL, GlfwClientApi_Vulkan }; struct ImGui_ImplGlfw_Data { GLFWwindow* Window; GlfwClientApi ClientApi; double Time; GLFWwindow* MouseWindow; GLFWcursor* MouseCursors[ImGuiMouseCursor_COUNT]; ImVec2 LastValidMousePos; bool InstalledCallbacks; bool CallbacksChainForAllWindows; #ifdef __EMSCRIPTEN__ const char* CanvasSelector; #endif // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. GLFWwindowfocusfun PrevUserCallbackWindowFocus; GLFWcursorposfun PrevUserCallbackCursorPos; GLFWcursorenterfun PrevUserCallbackCursorEnter; GLFWmousebuttonfun PrevUserCallbackMousebutton; GLFWscrollfun PrevUserCallbackScroll; GLFWkeyfun PrevUserCallbackKey; GLFWcharfun PrevUserCallbackChar; GLFWmonitorfun PrevUserCallbackMonitor; #ifdef _WIN32 WNDPROC GlfwWndProc; #endif ImGui_ImplGlfw_Data() { memset((void*)this, 0, sizeof(*this)); } }; // Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui contexts // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. // FIXME: multi-context support is not well tested and probably dysfunctional in this backend. // - Because glfwPollEvents() process all windows and some events may be called outside of it, you will need to register your own callbacks // (passing install_callbacks=false in ImGui_ImplGlfw_InitXXX functions), set the current dear imgui context and then call our callbacks. // - Otherwise we may need to store a GLFWWindow* -> ImGuiContext* map and handle this in the backend, adding a little bit of extra complexity to it. // FIXME: some shared resources (mouse cursor shape, gamepad) are mishandled when using multi-context. static ImGui_ImplGlfw_Data* ImGui_ImplGlfw_GetBackendData() { return ImGui::GetCurrentContext() ? (ImGui_ImplGlfw_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr; } // Functions static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data) { return glfwGetClipboardString((GLFWwindow*)user_data); } static void ImGui_ImplGlfw_SetClipboardText(void* user_data, const char* text) { glfwSetClipboardString((GLFWwindow*)user_data, text); } static ImGuiKey ImGui_ImplGlfw_KeyToImGuiKey(int key) { switch (key) { case GLFW_KEY_TAB: return ImGuiKey_Tab; case GLFW_KEY_LEFT: return ImGuiKey_LeftArrow; case GLFW_KEY_RIGHT: return ImGuiKey_RightArrow; case GLFW_KEY_UP: return ImGuiKey_UpArrow; case GLFW_KEY_DOWN: return ImGuiKey_DownArrow; case GLFW_KEY_PAGE_UP: return ImGuiKey_PageUp; case GLFW_KEY_PAGE_DOWN: return ImGuiKey_PageDown; case GLFW_KEY_HOME: return ImGuiKey_Home; case GLFW_KEY_END: return ImGuiKey_End; case GLFW_KEY_INSERT: return ImGuiKey_Insert; case GLFW_KEY_DELETE: return ImGuiKey_Delete; case GLFW_KEY_BACKSPACE: return ImGuiKey_Backspace; case GLFW_KEY_SPACE: return ImGuiKey_Space; case GLFW_KEY_ENTER: return ImGuiKey_Enter; case GLFW_KEY_ESCAPE: return ImGuiKey_Escape; case GLFW_KEY_APOSTROPHE: return ImGuiKey_Apostrophe; case GLFW_KEY_COMMA: return ImGuiKey_Comma; case GLFW_KEY_MINUS: return ImGuiKey_Minus; case GLFW_KEY_PERIOD: return ImGuiKey_Period; case GLFW_KEY_SLASH: return ImGuiKey_Slash; case GLFW_KEY_SEMICOLON: return ImGuiKey_Semicolon; case GLFW_KEY_EQUAL: return ImGuiKey_Equal; case GLFW_KEY_LEFT_BRACKET: return ImGuiKey_LeftBracket; case GLFW_KEY_BACKSLASH: return ImGuiKey_Backslash; case GLFW_KEY_RIGHT_BRACKET: return ImGuiKey_RightBracket; case GLFW_KEY_GRAVE_ACCENT: return ImGuiKey_GraveAccent; case GLFW_KEY_CAPS_LOCK: return ImGuiKey_CapsLock; case GLFW_KEY_SCROLL_LOCK: return ImGuiKey_ScrollLock; case GLFW_KEY_NUM_LOCK: return ImGuiKey_NumLock; case GLFW_KEY_PRINT_SCREEN: return ImGuiKey_PrintScreen; case GLFW_KEY_PAUSE: return ImGuiKey_Pause; case GLFW_KEY_KP_0: return ImGuiKey_Keypad0; case GLFW_KEY_KP_1: return ImGuiKey_Keypad1; case GLFW_KEY_KP_2: return ImGuiKey_Keypad2; case GLFW_KEY_KP_3: return ImGuiKey_Keypad3; case GLFW_KEY_KP_4: return ImGuiKey_Keypad4; case GLFW_KEY_KP_5: return ImGuiKey_Keypad5; case GLFW_KEY_KP_6: return ImGuiKey_Keypad6; case GLFW_KEY_KP_7: return ImGuiKey_Keypad7; case GLFW_KEY_KP_8: return ImGuiKey_Keypad8; case GLFW_KEY_KP_9: return ImGuiKey_Keypad9; case GLFW_KEY_KP_DECIMAL: return ImGuiKey_KeypadDecimal; case GLFW_KEY_KP_DIVIDE: return ImGuiKey_KeypadDivide; case GLFW_KEY_KP_MULTIPLY: return ImGuiKey_KeypadMultiply; case GLFW_KEY_KP_SUBTRACT: return ImGuiKey_KeypadSubtract; case GLFW_KEY_KP_ADD: return ImGuiKey_KeypadAdd; case GLFW_KEY_KP_ENTER: return ImGuiKey_KeypadEnter; case GLFW_KEY_KP_EQUAL: return ImGuiKey_KeypadEqual; case GLFW_KEY_LEFT_SHIFT: return ImGuiKey_LeftShift; case GLFW_KEY_LEFT_CONTROL: return ImGuiKey_LeftCtrl; case GLFW_KEY_LEFT_ALT: return ImGuiKey_LeftAlt; case GLFW_KEY_LEFT_SUPER: return ImGuiKey_LeftSuper; case GLFW_KEY_RIGHT_SHIFT: return ImGuiKey_RightShift; case GLFW_KEY_RIGHT_CONTROL: return ImGuiKey_RightCtrl; case GLFW_KEY_RIGHT_ALT: return ImGuiKey_RightAlt; case GLFW_KEY_RIGHT_SUPER: return ImGuiKey_RightSuper; case GLFW_KEY_MENU: return ImGuiKey_Menu; case GLFW_KEY_0: return ImGuiKey_0; case GLFW_KEY_1: return ImGuiKey_1; case GLFW_KEY_2: return ImGuiKey_2; case GLFW_KEY_3: return ImGuiKey_3; case GLFW_KEY_4: return ImGuiKey_4; case GLFW_KEY_5: return ImGuiKey_5; case GLFW_KEY_6: return ImGuiKey_6; case GLFW_KEY_7: return ImGuiKey_7; case GLFW_KEY_8: return ImGuiKey_8; case GLFW_KEY_9: return ImGuiKey_9; case GLFW_KEY_A: return ImGuiKey_A; case GLFW_KEY_B: return ImGuiKey_B; case GLFW_KEY_C: return ImGuiKey_C; case GLFW_KEY_D: return ImGuiKey_D; case GLFW_KEY_E: return ImGuiKey_E; case GLFW_KEY_F: return ImGuiKey_F; case GLFW_KEY_G: return ImGuiKey_G; case GLFW_KEY_H: return ImGuiKey_H; case GLFW_KEY_I: return ImGuiKey_I; case GLFW_KEY_J: return ImGuiKey_J; case GLFW_KEY_K: return ImGuiKey_K; case GLFW_KEY_L: return ImGuiKey_L; case GLFW_KEY_M: return ImGuiKey_M; case GLFW_KEY_N: return ImGuiKey_N; case GLFW_KEY_O: return ImGuiKey_O; case GLFW_KEY_P: return ImGuiKey_P; case GLFW_KEY_Q: return ImGuiKey_Q; case GLFW_KEY_R: return ImGuiKey_R; case GLFW_KEY_S: return ImGuiKey_S; case GLFW_KEY_T: return ImGuiKey_T; case GLFW_KEY_U: return ImGuiKey_U; case GLFW_KEY_V: return ImGuiKey_V; case GLFW_KEY_W: return ImGuiKey_W; case GLFW_KEY_X: return ImGuiKey_X; case GLFW_KEY_Y: return ImGuiKey_Y; case GLFW_KEY_Z: return ImGuiKey_Z; case GLFW_KEY_F1: return ImGuiKey_F1; case GLFW_KEY_F2: return ImGuiKey_F2; case GLFW_KEY_F3: return ImGuiKey_F3; case GLFW_KEY_F4: return ImGuiKey_F4; case GLFW_KEY_F5: return ImGuiKey_F5; case GLFW_KEY_F6: return ImGuiKey_F6; case GLFW_KEY_F7: return ImGuiKey_F7; case GLFW_KEY_F8: return ImGuiKey_F8; case GLFW_KEY_F9: return ImGuiKey_F9; case GLFW_KEY_F10: return ImGuiKey_F10; case GLFW_KEY_F11: return ImGuiKey_F11; case GLFW_KEY_F12: return ImGuiKey_F12; case GLFW_KEY_F13: return ImGuiKey_F13; case GLFW_KEY_F14: return ImGuiKey_F14; case GLFW_KEY_F15: return ImGuiKey_F15; case GLFW_KEY_F16: return ImGuiKey_F16; case GLFW_KEY_F17: return ImGuiKey_F17; case GLFW_KEY_F18: return ImGuiKey_F18; case GLFW_KEY_F19: return ImGuiKey_F19; case GLFW_KEY_F20: return ImGuiKey_F20; case GLFW_KEY_F21: return ImGuiKey_F21; case GLFW_KEY_F22: return ImGuiKey_F22; case GLFW_KEY_F23: return ImGuiKey_F23; case GLFW_KEY_F24: return ImGuiKey_F24; default: return ImGuiKey_None; } } // X11 does not include current pressed/released modifier key in 'mods' flags submitted by GLFW // See https://github.com/ocornut/imgui/issues/6034 and https://github.com/glfw/glfw/issues/1630 static void ImGui_ImplGlfw_UpdateKeyModifiers(GLFWwindow* window) { ImGuiIO& io = ImGui::GetIO(); io.AddKeyEvent(ImGuiMod_Ctrl, (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS)); io.AddKeyEvent(ImGuiMod_Shift, (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS)); io.AddKeyEvent(ImGuiMod_Alt, (glfwGetKey(window, GLFW_KEY_LEFT_ALT) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS)); io.AddKeyEvent(ImGuiMod_Super, (glfwGetKey(window, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS) || (glfwGetKey(window, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS)); } static bool ImGui_ImplGlfw_ShouldChainCallback(GLFWwindow* window) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); return bd->CallbacksChainForAllWindows ? true : (window == bd->Window); } void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); if (bd->PrevUserCallbackMousebutton != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) bd->PrevUserCallbackMousebutton(window, button, action, mods); ImGui_ImplGlfw_UpdateKeyModifiers(window); ImGuiIO& io = ImGui::GetIO(); if (button >= 0 && button < ImGuiMouseButton_COUNT) io.AddMouseButtonEvent(button, action == GLFW_PRESS); } void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); if (bd->PrevUserCallbackScroll != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) bd->PrevUserCallbackScroll(window, xoffset, yoffset); #ifdef __EMSCRIPTEN__ // Ignore GLFW events: will be processed in ImGui_ImplEmscripten_WheelCallback(). return; #endif ImGuiIO& io = ImGui::GetIO(); io.AddMouseWheelEvent((float)xoffset, (float)yoffset); } static int ImGui_ImplGlfw_TranslateUntranslatedKey(int key, int scancode) { #if GLFW_HAS_GETKEYNAME && !defined(__EMSCRIPTEN__) // GLFW 3.1+ attempts to "untranslate" keys, which goes the opposite of what every other framework does, making using lettered shortcuts difficult. // (It had reasons to do so: namely GLFW is/was more likely to be used for WASD-type game controls rather than lettered shortcuts, but IHMO the 3.1 change could have been done differently) // See https://github.com/glfw/glfw/issues/1502 for details. // Adding a workaround to undo this (so our keys are translated->untranslated->translated, likely a lossy process). // This won't cover edge cases but this is at least going to cover common cases. if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_EQUAL) return key; GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr); const char* key_name = glfwGetKeyName(key, scancode); glfwSetErrorCallback(prev_error_callback); #if GLFW_HAS_GETERROR && !defined(__EMSCRIPTEN__) // Eat errors (see #5908) (void)glfwGetError(nullptr); #endif if (key_name && key_name[0] != 0 && key_name[1] == 0) { const char char_names[] = "`-=[]\\,;\'./"; const int char_keys[] = { GLFW_KEY_GRAVE_ACCENT, GLFW_KEY_MINUS, GLFW_KEY_EQUAL, GLFW_KEY_LEFT_BRACKET, GLFW_KEY_RIGHT_BRACKET, GLFW_KEY_BACKSLASH, GLFW_KEY_COMMA, GLFW_KEY_SEMICOLON, GLFW_KEY_APOSTROPHE, GLFW_KEY_PERIOD, GLFW_KEY_SLASH, 0 }; IM_ASSERT(IM_ARRAYSIZE(char_names) == IM_ARRAYSIZE(char_keys)); if (key_name[0] >= '0' && key_name[0] <= '9') { key = GLFW_KEY_0 + (key_name[0] - '0'); } else if (key_name[0] >= 'A' && key_name[0] <= 'Z') { key = GLFW_KEY_A + (key_name[0] - 'A'); } else if (key_name[0] >= 'a' && key_name[0] <= 'z') { key = GLFW_KEY_A + (key_name[0] - 'a'); } else if (const char* p = strchr(char_names, key_name[0])) { key = char_keys[p - char_names]; } } // if (action == GLFW_PRESS) printf("key %d scancode %d name '%s'\n", key, scancode, key_name); #else IM_UNUSED(scancode); #endif return key; } void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int keycode, int scancode, int action, int mods) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); if (bd->PrevUserCallbackKey != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) bd->PrevUserCallbackKey(window, keycode, scancode, action, mods); if (action != GLFW_PRESS && action != GLFW_RELEASE) return; ImGui_ImplGlfw_UpdateKeyModifiers(window); keycode = ImGui_ImplGlfw_TranslateUntranslatedKey(keycode, scancode); ImGuiIO& io = ImGui::GetIO(); ImGuiKey imgui_key = ImGui_ImplGlfw_KeyToImGuiKey(keycode); io.AddKeyEvent(imgui_key, (action == GLFW_PRESS)); io.SetKeyEventNativeData(imgui_key, keycode, scancode); // To support legacy indexing (<1.87 user code) } void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); if (bd->PrevUserCallbackWindowFocus != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) bd->PrevUserCallbackWindowFocus(window, focused); ImGuiIO& io = ImGui::GetIO(); io.AddFocusEvent(focused != 0); } void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); if (bd->PrevUserCallbackCursorPos != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) bd->PrevUserCallbackCursorPos(window, x, y); ImGuiIO& io = ImGui::GetIO(); io.AddMousePosEvent((float)x, (float)y); bd->LastValidMousePos = ImVec2((float)x, (float)y); } // Workaround: X11 seems to send spurious Leave/Enter events which would make us lose our position, // so we back it up and restore on Leave/Enter (see https://github.com/ocornut/imgui/issues/4984) void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); if (bd->PrevUserCallbackCursorEnter != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) bd->PrevUserCallbackCursorEnter(window, entered); ImGuiIO& io = ImGui::GetIO(); if (entered) { bd->MouseWindow = window; io.AddMousePosEvent(bd->LastValidMousePos.x, bd->LastValidMousePos.y); } else if (!entered && bd->MouseWindow == window) { bd->LastValidMousePos = io.MousePos; bd->MouseWindow = nullptr; io.AddMousePosEvent(-FLT_MAX, -FLT_MAX); } } void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); if (bd->PrevUserCallbackChar != nullptr && ImGui_ImplGlfw_ShouldChainCallback(window)) bd->PrevUserCallbackChar(window, c); ImGuiIO& io = ImGui::GetIO(); io.AddInputCharacter(c); } void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int) { // Unused in 'master' branch but 'docking' branch will use this, so we declare it ahead of it so if you have to install callbacks you can install this one too. } #ifdef __EMSCRIPTEN__ static EM_BOOL ImGui_ImplEmscripten_WheelCallback(int, const EmscriptenWheelEvent* ev, void*) { // Mimic Emscripten_HandleWheel() in SDL. // Corresponding equivalent in GLFW JS emulation layer has incorrect quantizing preventing small values. See #6096 float multiplier = 0.0f; if (ev->deltaMode == DOM_DELTA_PIXEL) { multiplier = 1.0f / 100.0f; } // 100 pixels make up a step. else if (ev->deltaMode == DOM_DELTA_LINE) { multiplier = 1.0f / 3.0f; } // 3 lines make up a step. else if (ev->deltaMode == DOM_DELTA_PAGE) { multiplier = 80.0f; } // A page makes up 80 steps. float wheel_x = ev->deltaX * -multiplier; float wheel_y = ev->deltaY * -multiplier; ImGuiIO& io = ImGui::GetIO(); io.AddMouseWheelEvent(wheel_x, wheel_y); //IMGUI_DEBUG_LOG("[Emsc] mode %d dx: %.2f, dy: %.2f, dz: %.2f --> feed %.2f %.2f\n", (int)ev->deltaMode, ev->deltaX, ev->deltaY, ev->deltaZ, wheel_x, wheel_y); return EM_TRUE; } #endif #ifdef _WIN32 // GLFW doesn't allow to distinguish Mouse vs TouchScreen vs Pen. // Add support for Win32 (based on imgui_impl_win32), because we rely on _TouchScreen info to trickle inputs differently. static ImGuiMouseSource GetMouseSourceFromMessageExtraInfo() { LPARAM extra_info = ::GetMessageExtraInfo(); if ((extra_info & 0xFFFFFF80) == 0xFF515700) return ImGuiMouseSource_Pen; if ((extra_info & 0xFFFFFF80) == 0xFF515780) return ImGuiMouseSource_TouchScreen; return ImGuiMouseSource_Mouse; } static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); switch (msg) { case WM_MOUSEMOVE: case WM_NCMOUSEMOVE: case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_LBUTTONUP: case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: case WM_RBUTTONUP: case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: case WM_MBUTTONUP: case WM_XBUTTONDOWN: case WM_XBUTTONDBLCLK: case WM_XBUTTONUP: ImGui::GetIO().AddMouseSourceEvent(GetMouseSourceFromMessageExtraInfo()); break; } return ::CallWindowProcW(bd->GlfwWndProc, hWnd, msg, wParam, lParam); } #endif void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); IM_ASSERT(bd->InstalledCallbacks == false && "Callbacks already installed!"); IM_ASSERT(bd->Window == window); bd->PrevUserCallbackWindowFocus = glfwSetWindowFocusCallback(window, ImGui_ImplGlfw_WindowFocusCallback); bd->PrevUserCallbackCursorEnter = glfwSetCursorEnterCallback(window, ImGui_ImplGlfw_CursorEnterCallback); bd->PrevUserCallbackCursorPos = glfwSetCursorPosCallback(window, ImGui_ImplGlfw_CursorPosCallback); bd->PrevUserCallbackMousebutton = glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback); bd->PrevUserCallbackScroll = glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback); bd->PrevUserCallbackKey = glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback); bd->PrevUserCallbackChar = glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback); bd->PrevUserCallbackMonitor = glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback); bd->InstalledCallbacks = true; } void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); IM_ASSERT(bd->InstalledCallbacks == true && "Callbacks not installed!"); IM_ASSERT(bd->Window == window); glfwSetWindowFocusCallback(window, bd->PrevUserCallbackWindowFocus); glfwSetCursorEnterCallback(window, bd->PrevUserCallbackCursorEnter); glfwSetCursorPosCallback(window, bd->PrevUserCallbackCursorPos); glfwSetMouseButtonCallback(window, bd->PrevUserCallbackMousebutton); glfwSetScrollCallback(window, bd->PrevUserCallbackScroll); glfwSetKeyCallback(window, bd->PrevUserCallbackKey); glfwSetCharCallback(window, bd->PrevUserCallbackChar); glfwSetMonitorCallback(bd->PrevUserCallbackMonitor); bd->InstalledCallbacks = false; bd->PrevUserCallbackWindowFocus = nullptr; bd->PrevUserCallbackCursorEnter = nullptr; bd->PrevUserCallbackCursorPos = nullptr; bd->PrevUserCallbackMousebutton = nullptr; bd->PrevUserCallbackScroll = nullptr; bd->PrevUserCallbackKey = nullptr; bd->PrevUserCallbackChar = nullptr; bd->PrevUserCallbackMonitor = nullptr; } // Set to 'true' to enable chaining installed callbacks for all windows (including secondary viewports created by backends or by user. // This is 'false' by default meaning we only chain callbacks for the main viewport. // We cannot set this to 'true' by default because user callbacks code may be not testing the 'window' parameter of their callback. // If you set this to 'true' your user callback code will need to make sure you are testing the 'window' parameter. void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows) { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); bd->CallbacksChainForAllWindows = chain_for_all_windows; } static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, GlfwClientApi client_api) { ImGuiIO& io = ImGui::GetIO(); IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); //printf("GLFW_VERSION: %d.%d.%d (%d)", GLFW_VERSION_MAJOR, GLFW_VERSION_MINOR, GLFW_VERSION_REVISION, GLFW_VERSION_COMBINED); // Setup backend capabilities flags ImGui_ImplGlfw_Data* bd = IM_NEW(ImGui_ImplGlfw_Data)(); io.BackendPlatformUserData = (void*)bd; io.BackendPlatformName = "imgui_impl_glfw"; io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) bd->Window = window; bd->Time = 0.0; io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText; io.ClipboardUserData = bd->Window; // Create mouse cursors // (By design, on X11 cursors are user configurable and some cursors may be missing. When a cursor doesn't exist, // GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting. // Missing cursors will return nullptr and our _UpdateMouseCursor() function will use the Arrow cursor instead.) GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr); bd->MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); bd->MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR); bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR); bd->MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR); bd->MouseCursors[ImGuiMouseCursor_Hand] = glfwCreateStandardCursor(GLFW_HAND_CURSOR); #if GLFW_HAS_NEW_CURSORS bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_RESIZE_ALL_CURSOR); bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_RESIZE_NESW_CURSOR); bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_RESIZE_NWSE_CURSOR); bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_NOT_ALLOWED_CURSOR); #else bd->MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); #endif glfwSetErrorCallback(prev_error_callback); #if GLFW_HAS_GETERROR && !defined(__EMSCRIPTEN__) // Eat errors (see #5908) (void)glfwGetError(nullptr); #endif // Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any. if (install_callbacks) ImGui_ImplGlfw_InstallCallbacks(window); // Register Emscripten Wheel callback to workaround issue in Emscripten GLFW Emulation (#6096) // We intentionally do not check 'if (install_callbacks)' here, as some users may set it to false and call GLFW callback themselves. // FIXME: May break chaining in case user registered their own Emscripten callback? #ifdef __EMSCRIPTEN__ emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, ImGui_ImplEmscripten_WheelCallback); #endif // Set platform dependent data in viewport ImGuiViewport* main_viewport = ImGui::GetMainViewport(); #ifdef _WIN32 main_viewport->PlatformHandleRaw = glfwGetWin32Window(bd->Window); #elif defined(__APPLE__) main_viewport->PlatformHandleRaw = (void*)glfwGetCocoaWindow(bd->Window); #else IM_UNUSED(main_viewport); #endif // Windows: register a WndProc hook so we can intercept some messages. #ifdef _WIN32 bd->GlfwWndProc = (WNDPROC)::GetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC); IM_ASSERT(bd->GlfwWndProc != nullptr); ::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)ImGui_ImplGlfw_WndProc); #endif bd->ClientApi = client_api; return true; } bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks) { return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_OpenGL); } bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks) { return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_Vulkan); } bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks) { return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_Unknown); } void ImGui_ImplGlfw_Shutdown() { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); if (bd->InstalledCallbacks) ImGui_ImplGlfw_RestoreCallbacks(bd->Window); #ifdef __EMSCRIPTEN__ emscripten_set_wheel_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, false, nullptr); #endif for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) glfwDestroyCursor(bd->MouseCursors[cursor_n]); // Windows: register a WndProc hook so we can intercept some messages. #ifdef _WIN32 ImGuiViewport* main_viewport = ImGui::GetMainViewport(); ::SetWindowLongPtrW((HWND)main_viewport->PlatformHandleRaw, GWLP_WNDPROC, (LONG_PTR)bd->GlfwWndProc); bd->GlfwWndProc = nullptr; #endif io.BackendPlatformName = nullptr; io.BackendPlatformUserData = nullptr; io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad); IM_DELETE(bd); } static void ImGui_ImplGlfw_UpdateMouseData() { ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); ImGuiIO& io = ImGui::GetIO(); // (those braces are here to reduce diff with multi-viewports support in 'docking' branch) { GLFWwindow* window = bd->Window; #ifdef __EMSCRIPTEN__ const bool is_window_focused = true; #else const bool is_window_focused = glfwGetWindowAttrib(window, GLFW_FOCUSED) != 0; #endif if (is_window_focused) { // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) if (io.WantSetMousePos) glfwSetCursorPos(window, (double)io.MousePos.x, (double)io.MousePos.y); // (Optional) Fallback to provide mouse position when focused (ImGui_ImplGlfw_CursorPosCallback already provides this when hovered or captured) if (bd->MouseWindow == nullptr) { double mouse_x, mouse_y; glfwGetCursorPos(window, &mouse_x, &mouse_y); bd->LastValidMousePos = ImVec2((float)mouse_x, (float)mouse_y); io.AddMousePosEvent((float)mouse_x, (float)mouse_y); } } } } static void ImGui_ImplGlfw_UpdateMouseCursor() { ImGuiIO& io = ImGui::GetIO(); ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(bd->Window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED) return; ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); // (those braces are here to reduce diff with multi-viewports support in 'docking' branch) { GLFWwindow* window = bd->Window; if (imgui_cursor == ImGuiMouseCursor_None || io.MouseDrawCursor) { // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); } else { // Show OS mouse cursor // FIXME-PLATFORM: Unfocused windows seems to fail changing the mouse cursor with GLFW 3.2, but 3.3 works here. glfwSetCursor(window, bd->MouseCursors[imgui_cursor] ? bd->MouseCursors[imgui_cursor] : bd->MouseCursors[ImGuiMouseCursor_Arrow]); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); } } } // Update gamepad inputs static inline float Saturate(float v) { return v < 0.0f ? 0.0f : v > 1.0f ? 1.0f : v; } static void ImGui_ImplGlfw_UpdateGamepads() { ImGuiIO& io = ImGui::GetIO(); if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. return; io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; #if GLFW_HAS_GAMEPAD_API && !defined(__EMSCRIPTEN__) GLFWgamepadstate gamepad; if (!glfwGetGamepadState(GLFW_JOYSTICK_1, &gamepad)) return; #define MAP_BUTTON(KEY_NO, BUTTON_NO, _UNUSED) do { io.AddKeyEvent(KEY_NO, gamepad.buttons[BUTTON_NO] != 0); } while (0) #define MAP_ANALOG(KEY_NO, AXIS_NO, _UNUSED, V0, V1) do { float v = gamepad.axes[AXIS_NO]; v = (v - V0) / (V1 - V0); io.AddKeyAnalogEvent(KEY_NO, v > 0.10f, Saturate(v)); } while (0) #else int axes_count = 0, buttons_count = 0; const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &axes_count); const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &buttons_count); if (axes_count == 0 || buttons_count == 0) return; #define MAP_BUTTON(KEY_NO, _UNUSED, BUTTON_NO) do { io.AddKeyEvent(KEY_NO, (buttons_count > BUTTON_NO && buttons[BUTTON_NO] == GLFW_PRESS)); } while (0) #define MAP_ANALOG(KEY_NO, _UNUSED, AXIS_NO, V0, V1) do { float v = (axes_count > AXIS_NO) ? axes[AXIS_NO] : V0; v = (v - V0) / (V1 - V0); io.AddKeyAnalogEvent(KEY_NO, v > 0.10f, Saturate(v)); } while (0) #endif io.BackendFlags |= ImGuiBackendFlags_HasGamepad; MAP_BUTTON(ImGuiKey_GamepadStart, GLFW_GAMEPAD_BUTTON_START, 7); MAP_BUTTON(ImGuiKey_GamepadBack, GLFW_GAMEPAD_BUTTON_BACK, 6); MAP_BUTTON(ImGuiKey_GamepadFaceLeft, GLFW_GAMEPAD_BUTTON_X, 2); // Xbox X, PS Square MAP_BUTTON(ImGuiKey_GamepadFaceRight, GLFW_GAMEPAD_BUTTON_B, 1); // Xbox B, PS Circle MAP_BUTTON(ImGuiKey_GamepadFaceUp, GLFW_GAMEPAD_BUTTON_Y, 3); // Xbox Y, PS Triangle MAP_BUTTON(ImGuiKey_GamepadFaceDown, GLFW_GAMEPAD_BUTTON_A, 0); // Xbox A, PS Cross MAP_BUTTON(ImGuiKey_GamepadDpadLeft, GLFW_GAMEPAD_BUTTON_DPAD_LEFT, 13); MAP_BUTTON(ImGuiKey_GamepadDpadRight, GLFW_GAMEPAD_BUTTON_DPAD_RIGHT, 11); MAP_BUTTON(ImGuiKey_GamepadDpadUp, GLFW_GAMEPAD_BUTTON_DPAD_UP, 10); MAP_BUTTON(ImGuiKey_GamepadDpadDown, GLFW_GAMEPAD_BUTTON_DPAD_DOWN, 12); MAP_BUTTON(ImGuiKey_GamepadL1, GLFW_GAMEPAD_BUTTON_LEFT_BUMPER, 4); MAP_BUTTON(ImGuiKey_GamepadR1, GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER, 5); MAP_ANALOG(ImGuiKey_GamepadL2, GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, 4, -0.75f, +1.0f); MAP_ANALOG(ImGuiKey_GamepadR2, GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, 5, -0.75f, +1.0f); MAP_BUTTON(ImGuiKey_GamepadL3, GLFW_GAMEPAD_BUTTON_LEFT_THUMB, 8); MAP_BUTTON(ImGuiKey_GamepadR3, GLFW_GAMEPAD_BUTTON_RIGHT_THUMB, 9); MAP_ANALOG(ImGuiKey_GamepadLStickLeft, GLFW_GAMEPAD_AXIS_LEFT_X, 0, -0.25f, -1.0f); MAP_ANALOG(ImGuiKey_GamepadLStickRight, GLFW_GAMEPAD_AXIS_LEFT_X, 0, +0.25f, +1.0f); MAP_ANALOG(ImGuiKey_GamepadLStickUp, GLFW_GAMEPAD_AXIS_LEFT_Y, 1, -0.25f, -1.0f); MAP_ANALOG(ImGuiKey_GamepadLStickDown, GLFW_GAMEPAD_AXIS_LEFT_Y, 1, +0.25f, +1.0f); MAP_ANALOG(ImGuiKey_GamepadRStickLeft, GLFW_GAMEPAD_AXIS_RIGHT_X, 2, -0.25f, -1.0f); MAP_ANALOG(ImGuiKey_GamepadRStickRight, GLFW_GAMEPAD_AXIS_RIGHT_X, 2, +0.25f, +1.0f); MAP_ANALOG(ImGuiKey_GamepadRStickUp, GLFW_GAMEPAD_AXIS_RIGHT_Y, 3, -0.25f, -1.0f); MAP_ANALOG(ImGuiKey_GamepadRStickDown, GLFW_GAMEPAD_AXIS_RIGHT_Y, 3, +0.25f, +1.0f); #undef MAP_BUTTON #undef MAP_ANALOG } void ImGui_ImplGlfw_NewFrame() { ImGuiIO& io = ImGui::GetIO(); ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplGlfw_InitForXXX()?"); // Setup display size (every frame to accommodate for window resizing) int w, h; int display_w, display_h; glfwGetWindowSize(bd->Window, &w, &h); glfwGetFramebufferSize(bd->Window, &display_w, &display_h); io.DisplaySize = ImVec2((float)w, (float)h); if (w > 0 && h > 0) io.DisplayFramebufferScale = ImVec2((float)display_w / (float)w, (float)display_h / (float)h); // Setup time step // (Accept glfwGetTime() not returning a monotonically increasing value. Seems to happens on disconnecting peripherals and probably on VMs and Emscripten, see #6491, #6189, #6114, #3644) double current_time = glfwGetTime(); if (current_time <= bd->Time) current_time = bd->Time + 0.00001f; io.DeltaTime = bd->Time > 0.0 ? (float)(current_time - bd->Time) : (float)(1.0f / 60.0f); bd->Time = current_time; ImGui_ImplGlfw_UpdateMouseData(); ImGui_ImplGlfw_UpdateMouseCursor(); // Update game controllers (if enabled and available) ImGui_ImplGlfw_UpdateGamepads(); } #ifdef __EMSCRIPTEN__ static EM_BOOL ImGui_ImplGlfw_OnCanvasSizeChange(int event_type, const EmscriptenUiEvent* event, void* user_data) { ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data; double canvas_width, canvas_height; emscripten_get_element_css_size(bd->CanvasSelector, &canvas_width, &canvas_height); glfwSetWindowSize(bd->Window, (int)canvas_width, (int)canvas_height); return true; } static EM_BOOL ImGui_ImplEmscripten_FullscreenChangeCallback(int event_type, const EmscriptenFullscreenChangeEvent* event, void* user_data) { ImGui_ImplGlfw_Data* bd = (ImGui_ImplGlfw_Data*)user_data; double canvas_width, canvas_height; emscripten_get_element_css_size(bd->CanvasSelector, &canvas_width, &canvas_height); glfwSetWindowSize(bd->Window, (int)canvas_width, (int)canvas_height); return true; } // 'canvas_selector' is a CSS selector. The event listener is applied to the first element that matches the query. // STRING MUST PERSIST FOR THE APPLICATION DURATION. PLEASE USE A STRING LITERAL OR ENSURE POINTER WILL STAY VALID. void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector) { IM_ASSERT(canvas_selector != nullptr); ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplGlfw_InitForXXX()?"); bd->CanvasSelector = canvas_selector; emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, bd, false, ImGui_ImplGlfw_OnCanvasSizeChange); emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, bd, false, ImGui_ImplEmscripten_FullscreenChangeCallback); // Change the size of the GLFW window according to the size of the canvas ImGui_ImplGlfw_OnCanvasSizeChange(EMSCRIPTEN_EVENT_RESIZE, {}, bd); } #endif //----------------------------------------------------------------------------- #if defined(__clang__) #pragma clang diagnostic pop #endif #endif // #ifndef IMGUI_DISABLE RenderKit-ospray-f2a61c2/apps/common/external/imgui/imgui_impl_glfw.h000066400000000000000000000076541456566705700260750ustar00rootroot00000000000000// dear imgui: Platform Backend for GLFW // This needs to be used along with a Renderer (e.g. OpenGL3, Vulkan, WebGPU..) // (Info: GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) // Implemented features: // [X] Platform: Clipboard support. // [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen (Windows only). // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy GLFW_KEY_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set] // [X] Platform: Gamepad support. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange' (note: the resizing cursors requires GLFW 3.4+). // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // Learn about Dear ImGui: // - FAQ https://dearimgui.com/faq // - Getting Started https://dearimgui.com/getting-started // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). // - Introduction, links and more at the top of imgui.cpp #pragma once #include "imgui.h" // IMGUI_IMPL_API #ifndef IMGUI_DISABLE struct GLFWwindow; struct GLFWmonitor; IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOpenGL(GLFWwindow* window, bool install_callbacks); IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForVulkan(GLFWwindow* window, bool install_callbacks); IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForOther(GLFWwindow* window, bool install_callbacks); IMGUI_IMPL_API void ImGui_ImplGlfw_Shutdown(); IMGUI_IMPL_API void ImGui_ImplGlfw_NewFrame(); // Emscripten related initialization phase methods #ifdef __EMSCRIPTEN__ IMGUI_IMPL_API void ImGui_ImplGlfw_InstallEmscriptenCanvasResizeCallback(const char* canvas_selector); #endif // GLFW callbacks install // - When calling Init with 'install_callbacks=true': ImGui_ImplGlfw_InstallCallbacks() is called. GLFW callbacks will be installed for you. They will chain-call user's previously installed callbacks, if any. // - When calling Init with 'install_callbacks=false': GLFW callbacks won't be installed. You will need to call individual function yourself from your own GLFW callbacks. IMGUI_IMPL_API void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window); IMGUI_IMPL_API void ImGui_ImplGlfw_RestoreCallbacks(GLFWwindow* window); // GFLW callbacks options: // - Set 'chain_for_all_windows=true' to enable chaining callbacks for all windows (including secondary viewports created by backends or by user) IMGUI_IMPL_API void ImGui_ImplGlfw_SetCallbacksChainForAllWindows(bool chain_for_all_windows); // GLFW callbacks (individual callbacks to call yourself if you didn't install callbacks) IMGUI_IMPL_API void ImGui_ImplGlfw_WindowFocusCallback(GLFWwindow* window, int focused); // Since 1.84 IMGUI_IMPL_API void ImGui_ImplGlfw_CursorEnterCallback(GLFWwindow* window, int entered); // Since 1.84 IMGUI_IMPL_API void ImGui_ImplGlfw_CursorPosCallback(GLFWwindow* window, double x, double y); // Since 1.87 IMGUI_IMPL_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); IMGUI_IMPL_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); IMGUI_IMPL_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); IMGUI_IMPL_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c); IMGUI_IMPL_API void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor* monitor, int event); #endif // #ifndef IMGUI_DISABLE RenderKit-ospray-f2a61c2/apps/common/external/imgui/imgui_impl_opengl3.cpp000066400000000000000000001336611456566705700270360ustar00rootroot00000000000000// dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline // - Desktop GL: 2.x 3.x 4.x // - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0) // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..) // Implemented features: // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! // [x] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only). // About WebGL/ES: // - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES. // - This is done automatically on iOS, Android and Emscripten targets. // - For other targets, the define needs to be visible from the imgui_impl_opengl3.cpp compilation unit. If unsure, define globally or in imconfig.h. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // Learn about Dear ImGui: // - FAQ https://dearimgui.com/faq // - Getting Started https://dearimgui.com/getting-started // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). // - Introduction, links and more at the top of imgui.cpp // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2024-01-09: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" and variants, fixing regression on distros missing a symlink. // 2023-11-08: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" instead of "libGL.so.1", accommodating for NetBSD systems having only "libGL.so.3" available. (#6983) // 2023-10-05: OpenGL: Rename symbols in our internal loader so that LTO compilation with another copy of gl3w is possible. (#6875, #6668, #4445) // 2023-06-20: OpenGL: Fixed erroneous use glGetIntegerv(GL_CONTEXT_PROFILE_MASK) on contexts lower than 3.2. (#6539, #6333) // 2023-05-09: OpenGL: Support for glBindSampler() backup/restore on ES3. (#6375) // 2023-04-18: OpenGL: Restore front and back polygon mode separately when supported by context. (#6333) // 2023-03-23: OpenGL: Properly restoring "no shader program bound" if it was the case prior to running the rendering function. (#6267, #6220, #6224) // 2023-03-15: OpenGL: Fixed GL loader crash when GL_VERSION returns NULL. (#6154, #4445, #3530) // 2023-03-06: OpenGL: Fixed restoration of a potentially deleted OpenGL program, by calling glIsProgram(). (#6220, #6224) // 2022-11-09: OpenGL: Reverted use of glBufferSubData(), too many corruptions issues + old issues seemingly can't be reproed with Intel drivers nowadays (revert 2021-12-15 and 2022-05-23 changes). // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. // 2022-09-27: OpenGL: Added ability to '#define IMGUI_IMPL_OPENGL_DEBUG'. // 2022-05-23: OpenGL: Reworking 2021-12-15 "Using buffer orphaning" so it only happens on Intel GPU, seems to cause problems otherwise. (#4468, #4825, #4832, #5127). // 2022-05-13: OpenGL: Fixed state corruption on OpenGL ES 2.0 due to not preserving GL_ELEMENT_ARRAY_BUFFER_BINDING and vertex attribute states. // 2021-12-15: OpenGL: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports with some Intel HD drivers. // 2021-08-23: OpenGL: Fixed ES 3.0 shader ("#version 300 es") use normal precision floats to avoid wobbly rendering at HD resolutions. // 2021-08-19: OpenGL: Embed and use our own minimal GL loader (imgui_impl_opengl3_loader.h), removing requirement and support for third-party loader. // 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). // 2021-06-25: OpenGL: Use OES_vertex_array extension on Emscripten + backup/restore current state. // 2021-06-21: OpenGL: Destroy individual vertex/fragment shader objects right after they are linked into the main shader. // 2021-05-24: OpenGL: Access GL_CLIP_ORIGIN when "GL_ARB_clip_control" extension is detected, inside of just OpenGL 4.5 version. // 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) // 2021-04-06: OpenGL: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5 or greater. // 2021-02-18: OpenGL: Change blending equation to preserve alpha in output buffer. // 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state. // 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state. // 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x) // 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader. // 2020-07-10: OpenGL: Added support for glad2 OpenGL loader. // 2020-05-08: OpenGL: Made default GLSL version 150 (instead of 130) on OSX. // 2020-04-21: OpenGL: Fixed handling of glClipControl(GL_UPPER_LEFT) by inverting projection matrix. // 2020-04-12: OpenGL: Fixed context version check mistakenly testing for 4.0+ instead of 3.2+ to enable ImGuiBackendFlags_RendererHasVtxOffset. // 2020-03-24: OpenGL: Added support for glbinding 2.x OpenGL loader. // 2020-01-07: OpenGL: Added support for glbinding 3.x OpenGL loader. // 2019-10-25: OpenGL: Using a combination of GL define and runtime GL version to decide whether to use glDrawElementsBaseVertex(). Fix building with pre-3.2 GL loaders. // 2019-09-22: OpenGL: Detect default GL loader using __has_include compiler facility. // 2019-09-16: OpenGL: Tweak initialization code to allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() before the first NewFrame() call. // 2019-05-29: OpenGL: Desktop GL only: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. // 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2019-03-29: OpenGL: Not calling glBindBuffer more than necessary in the render loop. // 2019-03-15: OpenGL: Added a GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized GL function loaders early. // 2019-03-03: OpenGL: Fix support for ES 2.0 (WebGL 1.0). // 2019-02-20: OpenGL: Fix for OSX not supporting OpenGL 4.5, we don't try to read GL_CLIP_ORIGIN even if defined by the headers/loader. // 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display. // 2019-02-01: OpenGL: Using GLSL 410 shaders for any version over 410 (e.g. 430, 450). // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. // 2018-11-13: OpenGL: Support for GL 4.5's glClipControl(GL_UPPER_LEFT) / GL_CLIP_ORIGIN. // 2018-08-29: OpenGL: Added support for more OpenGL loaders: glew and glad, with comments indicative that any loader can be used. // 2018-08-09: OpenGL: Default to OpenGL ES 3 on iOS and Android. GLSL version default to "#version 300 ES". // 2018-07-30: OpenGL: Support for GLSL 300 ES and 410 core. Fixes for Emscripten compilation. // 2018-07-10: OpenGL: Support for more GLSL versions (based on the GLSL version string). Added error output when shaders fail to compile/link. // 2018-06-08: Misc: Extracted imgui_impl_opengl3.cpp/.h away from the old combined GLFW/SDL+OpenGL3 examples. // 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. // 2018-05-25: OpenGL: Removed unnecessary backup/restore of GL_ELEMENT_ARRAY_BUFFER_BINDING since this is part of the VAO state. // 2018-05-14: OpenGL: Making the call to glBindSampler() optional so 3.2 context won't fail if the function is a nullptr pointer. // 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplOpenGL3_Init() so user can override the GLSL version e.g. "#version 150". // 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself. // 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150. // 2017-09-01: OpenGL: Save and restore current bound sampler. Save and restore current polygon mode. // 2017-05-01: OpenGL: Fixed save and restore of current blend func state. // 2017-05-01: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE. // 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle. // 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752) //---------------------------------------- // OpenGL GLSL GLSL // version version string //---------------------------------------- // 2.0 110 "#version 110" // 2.1 120 "#version 120" // 3.0 130 "#version 130" // 3.1 140 "#version 140" // 3.2 150 "#version 150" // 3.3 330 "#version 330 core" // 4.0 400 "#version 400 core" // 4.1 410 "#version 410 core" // 4.2 420 "#version 410 core" // 4.3 430 "#version 430 core" // ES 2.0 100 "#version 100" = WebGL 1.0 // ES 3.0 300 "#version 300 es" = WebGL 2.0 //---------------------------------------- #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif #include "imgui.h" #ifndef IMGUI_DISABLE #include "imgui_impl_opengl3.h" #include #include // intptr_t #if defined(__APPLE__) #include #endif // Clang/GCC warnings with -Weverything #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast #pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness #pragma clang diagnostic ignored "-Wunused-macros" // warning: macro is not used #pragma clang diagnostic ignored "-Wnonportable-system-include-path" #pragma clang diagnostic ignored "-Wcast-function-type" // warning: cast between incompatible function types (for loader) #endif #if defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' #pragma GCC diagnostic ignored "-Wcast-function-type" // warning: cast between incompatible function types (for loader) #endif // GL includes #if defined(IMGUI_IMPL_OPENGL_ES2) #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) #include // Use GL ES 2 #else #include // Use GL ES 2 #endif #if defined(__EMSCRIPTEN__) #ifndef GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES #endif #include #endif #elif defined(IMGUI_IMPL_OPENGL_ES3) #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) #include // Use GL ES 3 #else #include // Use GL ES 3 #endif #elif !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM) // Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers. // Helper libraries are often used for this purpose! Here we are using our own minimal custom loader based on gl3w. // In the rest of your app/engine, you can use another loader of your choice (gl3w, glew, glad, glbinding, glext, glLoadGen, etc.). // If you happen to be developing a new feature for this backend (imgui_impl_opengl3.cpp): // - You may need to regenerate imgui_impl_opengl3_loader.h to add new symbols. See https://github.com/dearimgui/gl3w_stripped // - You can temporarily use an unstripped version. See https://github.com/dearimgui/gl3w_stripped/releases // Changes to this backend using new APIs should be accompanied by a regenerated stripped loader version. #define IMGL3W_IMPL #include "imgui_impl_opengl3_loader.h" #endif // Vertex arrays are not supported on ES2/WebGL1 unless Emscripten which uses an extension #ifndef IMGUI_IMPL_OPENGL_ES2 #define IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY #elif defined(__EMSCRIPTEN__) #define IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY #define glBindVertexArray glBindVertexArrayOES #define glGenVertexArrays glGenVertexArraysOES #define glDeleteVertexArrays glDeleteVertexArraysOES #define GL_VERTEX_ARRAY_BINDING GL_VERTEX_ARRAY_BINDING_OES #endif // Desktop GL 2.0+ has glPolygonMode() which GL ES and WebGL don't have. #ifdef GL_POLYGON_MODE #define IMGUI_IMPL_HAS_POLYGON_MODE #endif // Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have. #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_2) #define IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET #endif // Desktop GL 3.3+ and GL ES 3.0+ have glBindSampler() #if !defined(IMGUI_IMPL_OPENGL_ES2) && (defined(IMGUI_IMPL_OPENGL_ES3) || defined(GL_VERSION_3_3)) #define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER #endif // Desktop GL 3.1+ has GL_PRIMITIVE_RESTART state #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_1) #define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART #endif // Desktop GL use extension detection #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) #define IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS #endif // [Debugging] //#define IMGUI_IMPL_OPENGL_DEBUG #ifdef IMGUI_IMPL_OPENGL_DEBUG #include #define GL_CALL(_CALL) do { _CALL; GLenum gl_err = glGetError(); if (gl_err != 0) fprintf(stderr, "GL error 0x%x returned from '%s'.\n", gl_err, #_CALL); } while (0) // Call with error check #else #define GL_CALL(_CALL) _CALL // Call without error check #endif // OpenGL Data struct ImGui_ImplOpenGL3_Data { GLuint GlVersion; // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2) char GlslVersionString[32]; // Specified by user or detected based on compile time GL settings. bool GlProfileIsES2; bool GlProfileIsES3; bool GlProfileIsCompat; GLint GlProfileMask; GLuint FontTexture; GLuint ShaderHandle; GLint AttribLocationTex; // Uniforms location GLint AttribLocationProjMtx; GLuint AttribLocationVtxPos; // Vertex attributes location GLuint AttribLocationVtxUV; GLuint AttribLocationVtxColor; unsigned int VboHandle, ElementsHandle; GLsizeiptr VertexBufferSize; GLsizeiptr IndexBufferSize; bool HasClipOrigin; bool UseBufferSubData; ImGui_ImplOpenGL3_Data() { memset((void*)this, 0, sizeof(*this)); } }; // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData() { return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; } // OpenGL vertex attribute state (for ES 1.0 and ES 2.0 only) #ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY struct ImGui_ImplOpenGL3_VtxAttribState { GLint Enabled, Size, Type, Normalized, Stride; GLvoid* Ptr; void GetState(GLint index) { glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &Enabled); glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_SIZE, &Size); glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_TYPE, &Type); glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &Normalized); glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &Stride); glGetVertexAttribPointerv(index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &Ptr); } void SetState(GLint index) { glVertexAttribPointer(index, Size, Type, (GLboolean)Normalized, Stride, Ptr); if (Enabled) glEnableVertexAttribArray(index); else glDisableVertexAttribArray(index); } }; #endif // Functions bool ImGui_ImplOpenGL3_Init(const char* glsl_version) { ImGuiIO& io = ImGui::GetIO(); IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); // Initialize our loader #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM) if (imgl3wInit() != 0) { fprintf(stderr, "Failed to initialize OpenGL loader!\n"); return false; } #endif // Setup backend capabilities flags ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)(); io.BackendRendererUserData = (void*)bd; io.BackendRendererName = "imgui_impl_opengl3"; // Query for GL version (e.g. 320 for GL 3.2) #if defined(IMGUI_IMPL_OPENGL_ES2) // GLES 2 bd->GlVersion = 200; bd->GlProfileIsES2 = true; #else // Desktop or GLES 3 GLint major = 0; GLint minor = 0; glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MINOR_VERSION, &minor); if (major == 0 && minor == 0) { // Query GL_VERSION in desktop GL 2.x, the string will start with "." const char* gl_version = (const char*)glGetString(GL_VERSION); sscanf(gl_version, "%d.%d", &major, &minor); } bd->GlVersion = (GLuint)(major * 100 + minor * 10); #if defined(GL_CONTEXT_PROFILE_MASK) if (bd->GlVersion >= 320) glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &bd->GlProfileMask); bd->GlProfileIsCompat = (bd->GlProfileMask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0; #endif #if defined(IMGUI_IMPL_OPENGL_ES3) bd->GlProfileIsES3 = true; #endif bd->UseBufferSubData = false; /* // Query vendor to enable glBufferSubData kludge #ifdef _WIN32 if (const char* vendor = (const char*)glGetString(GL_VENDOR)) if (strncmp(vendor, "Intel", 5) == 0) bd->UseBufferSubData = true; #endif */ #endif #ifdef IMGUI_IMPL_OPENGL_DEBUG printf("GlVersion = %d\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2 = %d, GlProfileIsES3 = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG] #endif #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET if (bd->GlVersion >= 320) io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. #endif // Store GLSL version string so we can refer to it later in case we recreate shaders. // Note: GLSL version is NOT the same as GL version. Leave this to nullptr if unsure. if (glsl_version == nullptr) { #if defined(IMGUI_IMPL_OPENGL_ES2) glsl_version = "#version 100"; #elif defined(IMGUI_IMPL_OPENGL_ES3) glsl_version = "#version 300 es"; #elif defined(__APPLE__) glsl_version = "#version 150"; #else glsl_version = "#version 130"; #endif } IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(bd->GlslVersionString)); strcpy(bd->GlslVersionString, glsl_version); strcat(bd->GlslVersionString, "\n"); // Make an arbitrary GL call (we don't actually need the result) // IF YOU GET A CRASH HERE: it probably means the OpenGL function loader didn't do its job. Let us know! GLint current_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); // Detect extensions we support bd->HasClipOrigin = (bd->GlVersion >= 450); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS GLint num_extensions = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); for (GLint i = 0; i < num_extensions; i++) { const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i); if (extension != nullptr && strcmp(extension, "GL_ARB_clip_control") == 0) bd->HasClipOrigin = true; } #endif return true; } void ImGui_ImplOpenGL3_Shutdown() { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); ImGui_ImplOpenGL3_DestroyDeviceObjects(); io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset; IM_DELETE(bd); } void ImGui_ImplOpenGL3_NewFrame() { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplOpenGL3_Init()?"); if (!bd->ShaderHandle) ImGui_ImplOpenGL3_CreateDeviceObjects(); } static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); glEnable(GL_SCISSOR_TEST); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART if (bd->GlVersion >= 310) glDisable(GL_PRIMITIVE_RESTART); #endif #ifdef IMGUI_IMPL_HAS_POLYGON_MODE glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); #endif // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT) #if defined(GL_CLIP_ORIGIN) bool clip_origin_lower_left = true; if (bd->HasClipOrigin) { GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)¤t_clip_origin); if (current_clip_origin == GL_UPPER_LEFT) clip_origin_lower_left = false; } #endif // Setup viewport, orthographic projection matrix // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. GL_CALL(glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height)); float L = draw_data->DisplayPos.x; float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; float T = draw_data->DisplayPos.y; float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; #if defined(GL_CLIP_ORIGIN) if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left #endif const float ortho_projection[4][4] = { { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, { 0.0f, 0.0f, -1.0f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f }, }; glUseProgram(bd->ShaderHandle); glUniform1i(bd->AttribLocationTex, 0); glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER if (bd->GlVersion >= 330 || bd->GlProfileIsES3) glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 and GL ES 3.0 may set that otherwise. #endif (void)vertex_array_object; #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY glBindVertexArray(vertex_array_object); #endif // Bind vertex/index buffers and setup attributes for ImDrawVert GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, bd->VboHandle)); GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bd->ElementsHandle)); GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxPos)); GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxUV)); GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxColor)); GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, pos))); GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, uv))); GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, col))); } // OpenGL3 Render function. // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly. // This is in order to be able to run within an OpenGL engine that doesn't do so. void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); if (fb_width <= 0 || fb_height <= 0) return; ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); // Backup GL state GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture); glActiveTexture(GL_TEXTURE0); GLuint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&last_program); GLuint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&last_texture); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER GLuint last_sampler; if (bd->GlVersion >= 330 || bd->GlProfileIsES3) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; } #endif GLuint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&last_array_buffer); #ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY // This is part of VAO on OpenGL 3.0+ and OpenGL ES 3.0+. GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer); ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_pos; last_vtx_attrib_state_pos.GetState(bd->AttribLocationVtxPos); ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_uv; last_vtx_attrib_state_uv.GetState(bd->AttribLocationVtxUV); ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_color; last_vtx_attrib_state_color.GetState(bd->AttribLocationVtxColor); #endif #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object); #endif #ifdef IMGUI_IMPL_HAS_POLYGON_MODE GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); #endif GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb); GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb); GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha); GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha); GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb); GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha); GLboolean last_enable_blend = glIsEnabled(GL_BLEND); GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE); GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); GLboolean last_enable_stencil_test = glIsEnabled(GL_STENCIL_TEST); GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART GLboolean last_enable_primitive_restart = (bd->GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE; #endif // Setup desired GL state // Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts) // The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound. GLuint vertex_array_object = 0; #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY GL_CALL(glGenVertexArrays(1, &vertex_array_object)); #endif ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object); // Will project scissor/clipping rectangles into framebuffer space ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2) // Render command lists for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; // Upload vertex/index buffers // - OpenGL drivers are in a very sorry state nowadays.... // During 2021 we attempted to switch from glBufferData() to orphaning+glBufferSubData() following reports // of leaks on Intel GPU when using multi-viewports on Windows. // - After this we kept hearing of various display corruptions issues. We started disabling on non-Intel GPU, but issues still got reported on Intel. // - We are now back to using exclusively glBufferData(). So bd->UseBufferSubData IS ALWAYS FALSE in this code. // We are keeping the old code path for a while in case people finding new issues may want to test the bd->UseBufferSubData path. // - See https://github.com/ocornut/imgui/issues/4468 and please report any corruption issues. const GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert); const GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx); if (bd->UseBufferSubData) { if (bd->VertexBufferSize < vtx_buffer_size) { bd->VertexBufferSize = vtx_buffer_size; GL_CALL(glBufferData(GL_ARRAY_BUFFER, bd->VertexBufferSize, nullptr, GL_STREAM_DRAW)); } if (bd->IndexBufferSize < idx_buffer_size) { bd->IndexBufferSize = idx_buffer_size; GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, bd->IndexBufferSize, nullptr, GL_STREAM_DRAW)); } GL_CALL(glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data)); GL_CALL(glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data)); } else { GL_CALL(glBufferData(GL_ARRAY_BUFFER, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW)); GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW)); } for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; if (pcmd->UserCallback != nullptr) { // User callback, registered via ImDrawList::AddCallback() // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object); else pcmd->UserCallback(cmd_list, pcmd); } else { // Project scissor/clipping rectangles into framebuffer space ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y); ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y); if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) continue; // Apply scissor/clipping rectangle (Y is inverted in OpenGL) GL_CALL(glScissor((int)clip_min.x, (int)((float)fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y))); // Bind texture, Draw GL_CALL(glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID())); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET if (bd->GlVersion >= 320) GL_CALL(glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset)); else #endif GL_CALL(glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)))); } } } // Destroy the temporary VAO #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY GL_CALL(glDeleteVertexArrays(1, &vertex_array_object)); #endif // Restore modified GL state // This "glIsProgram()" check is required because if the program is "pending deletion" at the time of binding backup, it will have been deleted by now and will cause an OpenGL error. See #6220. if (last_program == 0 || glIsProgram(last_program)) glUseProgram(last_program); glBindTexture(GL_TEXTURE_2D, last_texture); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER if (bd->GlVersion >= 330 || bd->GlProfileIsES3) glBindSampler(0, last_sampler); #endif glActiveTexture(last_active_texture); #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY glBindVertexArray(last_vertex_array_object); #endif glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); #ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer); last_vtx_attrib_state_pos.SetState(bd->AttribLocationVtxPos); last_vtx_attrib_state_uv.SetState(bd->AttribLocationVtxUV); last_vtx_attrib_state_color.SetState(bd->AttribLocationVtxColor); #endif glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha); glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha); if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND); if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); if (last_enable_stencil_test) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST); if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART if (bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); } #endif #ifdef IMGUI_IMPL_HAS_POLYGON_MODE // Desktop OpenGL 3.0 and OpenGL 3.1 had separate polygon draw modes for front-facing and back-facing faces of polygons if (bd->GlVersion <= 310 || bd->GlProfileIsCompat) { glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]); } else { glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); } #endif // IMGUI_IMPL_HAS_POLYGON_MODE glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); (void)bd; // Not all compilation paths use this } bool ImGui_ImplOpenGL3_CreateFontsTexture() { ImGuiIO& io = ImGui::GetIO(); ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); // Build texture atlas unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. // Upload texture to graphics system // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling) GLint last_texture; GL_CALL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture)); GL_CALL(glGenTextures(1, &bd->FontTexture)); GL_CALL(glBindTexture(GL_TEXTURE_2D, bd->FontTexture)); GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); #ifdef GL_UNPACK_ROW_LENGTH // Not on WebGL/ES GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0)); #endif GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); // Store our identifier io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture); // Restore state GL_CALL(glBindTexture(GL_TEXTURE_2D, last_texture)); return true; } void ImGui_ImplOpenGL3_DestroyFontsTexture() { ImGuiIO& io = ImGui::GetIO(); ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); if (bd->FontTexture) { glDeleteTextures(1, &bd->FontTexture); io.Fonts->SetTexID(0); bd->FontTexture = 0; } } // If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file. static bool CheckShader(GLuint handle, const char* desc) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); GLint status = 0, log_length = 0; glGetShaderiv(handle, GL_COMPILE_STATUS, &status); glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length); if ((GLboolean)status == GL_FALSE) fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s! With GLSL: %s\n", desc, bd->GlslVersionString); if (log_length > 1) { ImVector buf; buf.resize((int)(log_length + 1)); glGetShaderInfoLog(handle, log_length, nullptr, (GLchar*)buf.begin()); fprintf(stderr, "%s\n", buf.begin()); } return (GLboolean)status == GL_TRUE; } // If you get an error please report on GitHub. You may try different GL context version or GLSL version. static bool CheckProgram(GLuint handle, const char* desc) { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); GLint status = 0, log_length = 0; glGetProgramiv(handle, GL_LINK_STATUS, &status); glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length); if ((GLboolean)status == GL_FALSE) fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! With GLSL %s\n", desc, bd->GlslVersionString); if (log_length > 1) { ImVector buf; buf.resize((int)(log_length + 1)); glGetProgramInfoLog(handle, log_length, nullptr, (GLchar*)buf.begin()); fprintf(stderr, "%s\n", buf.begin()); } return (GLboolean)status == GL_TRUE; } bool ImGui_ImplOpenGL3_CreateDeviceObjects() { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); // Backup GL state GLint last_texture, last_array_buffer; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); #endif // Parse GLSL version string int glsl_version = 130; sscanf(bd->GlslVersionString, "#version %d", &glsl_version); const GLchar* vertex_shader_glsl_120 = "uniform mat4 ProjMtx;\n" "attribute vec2 Position;\n" "attribute vec2 UV;\n" "attribute vec4 Color;\n" "varying vec2 Frag_UV;\n" "varying vec4 Frag_Color;\n" "void main()\n" "{\n" " Frag_UV = UV;\n" " Frag_Color = Color;\n" " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" "}\n"; const GLchar* vertex_shader_glsl_130 = "uniform mat4 ProjMtx;\n" "in vec2 Position;\n" "in vec2 UV;\n" "in vec4 Color;\n" "out vec2 Frag_UV;\n" "out vec4 Frag_Color;\n" "void main()\n" "{\n" " Frag_UV = UV;\n" " Frag_Color = Color;\n" " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" "}\n"; const GLchar* vertex_shader_glsl_300_es = "precision highp float;\n" "layout (location = 0) in vec2 Position;\n" "layout (location = 1) in vec2 UV;\n" "layout (location = 2) in vec4 Color;\n" "uniform mat4 ProjMtx;\n" "out vec2 Frag_UV;\n" "out vec4 Frag_Color;\n" "void main()\n" "{\n" " Frag_UV = UV;\n" " Frag_Color = Color;\n" " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" "}\n"; const GLchar* vertex_shader_glsl_410_core = "layout (location = 0) in vec2 Position;\n" "layout (location = 1) in vec2 UV;\n" "layout (location = 2) in vec4 Color;\n" "uniform mat4 ProjMtx;\n" "out vec2 Frag_UV;\n" "out vec4 Frag_Color;\n" "void main()\n" "{\n" " Frag_UV = UV;\n" " Frag_Color = Color;\n" " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" "}\n"; const GLchar* fragment_shader_glsl_120 = "#ifdef GL_ES\n" " precision mediump float;\n" "#endif\n" "uniform sampler2D Texture;\n" "varying vec2 Frag_UV;\n" "varying vec4 Frag_Color;\n" "void main()\n" "{\n" " gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n" "}\n"; const GLchar* fragment_shader_glsl_130 = "uniform sampler2D Texture;\n" "in vec2 Frag_UV;\n" "in vec4 Frag_Color;\n" "out vec4 Out_Color;\n" "void main()\n" "{\n" " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" "}\n"; const GLchar* fragment_shader_glsl_300_es = "precision mediump float;\n" "uniform sampler2D Texture;\n" "in vec2 Frag_UV;\n" "in vec4 Frag_Color;\n" "layout (location = 0) out vec4 Out_Color;\n" "void main()\n" "{\n" " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" "}\n"; const GLchar* fragment_shader_glsl_410_core = "in vec2 Frag_UV;\n" "in vec4 Frag_Color;\n" "uniform sampler2D Texture;\n" "layout (location = 0) out vec4 Out_Color;\n" "void main()\n" "{\n" " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" "}\n"; // Select shaders matching our GLSL versions const GLchar* vertex_shader = nullptr; const GLchar* fragment_shader = nullptr; if (glsl_version < 130) { vertex_shader = vertex_shader_glsl_120; fragment_shader = fragment_shader_glsl_120; } else if (glsl_version >= 410) { vertex_shader = vertex_shader_glsl_410_core; fragment_shader = fragment_shader_glsl_410_core; } else if (glsl_version == 300) { vertex_shader = vertex_shader_glsl_300_es; fragment_shader = fragment_shader_glsl_300_es; } else { vertex_shader = vertex_shader_glsl_130; fragment_shader = fragment_shader_glsl_130; } // Create shaders const GLchar* vertex_shader_with_version[2] = { bd->GlslVersionString, vertex_shader }; GLuint vert_handle = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vert_handle, 2, vertex_shader_with_version, nullptr); glCompileShader(vert_handle); CheckShader(vert_handle, "vertex shader"); const GLchar* fragment_shader_with_version[2] = { bd->GlslVersionString, fragment_shader }; GLuint frag_handle = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(frag_handle, 2, fragment_shader_with_version, nullptr); glCompileShader(frag_handle); CheckShader(frag_handle, "fragment shader"); // Link bd->ShaderHandle = glCreateProgram(); glAttachShader(bd->ShaderHandle, vert_handle); glAttachShader(bd->ShaderHandle, frag_handle); glLinkProgram(bd->ShaderHandle); CheckProgram(bd->ShaderHandle, "shader program"); glDetachShader(bd->ShaderHandle, vert_handle); glDetachShader(bd->ShaderHandle, frag_handle); glDeleteShader(vert_handle); glDeleteShader(frag_handle); bd->AttribLocationTex = glGetUniformLocation(bd->ShaderHandle, "Texture"); bd->AttribLocationProjMtx = glGetUniformLocation(bd->ShaderHandle, "ProjMtx"); bd->AttribLocationVtxPos = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Position"); bd->AttribLocationVtxUV = (GLuint)glGetAttribLocation(bd->ShaderHandle, "UV"); bd->AttribLocationVtxColor = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Color"); // Create buffers glGenBuffers(1, &bd->VboHandle); glGenBuffers(1, &bd->ElementsHandle); ImGui_ImplOpenGL3_CreateFontsTexture(); // Restore modified GL state glBindTexture(GL_TEXTURE_2D, last_texture); glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY glBindVertexArray(last_vertex_array); #endif return true; } void ImGui_ImplOpenGL3_DestroyDeviceObjects() { ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData(); if (bd->VboHandle) { glDeleteBuffers(1, &bd->VboHandle); bd->VboHandle = 0; } if (bd->ElementsHandle) { glDeleteBuffers(1, &bd->ElementsHandle); bd->ElementsHandle = 0; } if (bd->ShaderHandle) { glDeleteProgram(bd->ShaderHandle); bd->ShaderHandle = 0; } ImGui_ImplOpenGL3_DestroyFontsTexture(); } //----------------------------------------------------------------------------- #if defined(__GNUC__) #pragma GCC diagnostic pop #endif #if defined(__clang__) #pragma clang diagnostic pop #endif #endif // #ifndef IMGUI_DISABLE RenderKit-ospray-f2a61c2/apps/common/external/imgui/imgui_impl_opengl3.h000066400000000000000000000065121456566705700264750ustar00rootroot00000000000000// dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline // - Desktop GL: 2.x 3.x 4.x // - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0) // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..) // Implemented features: // [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID! // [x] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only). // About WebGL/ES: // - You need to '#define IMGUI_IMPL_OPENGL_ES2' or '#define IMGUI_IMPL_OPENGL_ES3' to use WebGL or OpenGL ES. // - This is done automatically on iOS, Android and Emscripten targets. // - For other targets, the define needs to be visible from the imgui_impl_opengl3.cpp compilation unit. If unsure, define globally or in imconfig.h. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. // Learn about Dear ImGui: // - FAQ https://dearimgui.com/faq // - Getting Started https://dearimgui.com/getting-started // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). // - Introduction, links and more at the top of imgui.cpp // About GLSL version: // The 'glsl_version' initialization parameter should be nullptr (default) or a "#version XXX" string. // On computer platform the GLSL version default to "#version 130". On OpenGL ES 3 platform it defaults to "#version 300 es" // Only override if your GL version doesn't handle this GLSL version. See GLSL version table at the top of imgui_impl_opengl3.cpp. #pragma once #include "imgui.h" // IMGUI_IMPL_API #ifndef IMGUI_DISABLE // Backend API IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = nullptr); IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown(); IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame(); IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); // (Optional) Called by Init/NewFrame/Shutdown IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture(); IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture(); IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects(); IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects(); // Specific OpenGL ES versions //#define IMGUI_IMPL_OPENGL_ES2 // Auto-detected on Emscripten //#define IMGUI_IMPL_OPENGL_ES3 // Auto-detected on iOS/Android // You can explicitly select GLES2 or GLES3 API by using one of the '#define IMGUI_IMPL_OPENGL_LOADER_XXX' in imconfig.h or compiler command-line. #if !defined(IMGUI_IMPL_OPENGL_ES2) \ && !defined(IMGUI_IMPL_OPENGL_ES3) // Try to detect GLES on matching platforms #if defined(__APPLE__) #include #endif #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) || (defined(__ANDROID__)) #define IMGUI_IMPL_OPENGL_ES3 // iOS, Android -> GL ES 3, "#version 300 es" #elif defined(__EMSCRIPTEN__) || defined(__amigaos4__) #define IMGUI_IMPL_OPENGL_ES2 // Emscripten -> GL ES 2, "#version 100" #else // Otherwise imgui_impl_opengl3_loader.h will be used. #endif #endif #endif // #ifndef IMGUI_DISABLE RenderKit-ospray-f2a61c2/apps/common/external/imgui/imgui_impl_opengl3_loader.h000066400000000000000000001067651456566705700300360ustar00rootroot00000000000000//----------------------------------------------------------------------------- // About imgui_impl_opengl3_loader.h: // // We embed our own OpenGL loader to not require user to provide their own or to have to use ours, // which proved to be endless problems for users. // Our loader is custom-generated, based on gl3w but automatically filtered to only include // enums/functions that we use in our imgui_impl_opengl3.cpp source file in order to be small. // // YOU SHOULD NOT NEED TO INCLUDE/USE THIS DIRECTLY. THIS IS USED BY imgui_impl_opengl3.cpp ONLY. // THE REST OF YOUR APP SHOULD USE A DIFFERENT GL LOADER: ANY GL LOADER OF YOUR CHOICE. // // IF YOU GET BUILD ERRORS IN THIS FILE (commonly macro redefinitions or function redefinitions): // IT LIKELY MEANS THAT YOU ARE BUILDING 'imgui_impl_opengl3.cpp' OR INCUDING 'imgui_impl_opengl3_loader.h' // IN THE SAME COMPILATION UNIT AS ONE OF YOUR FILE WHICH IS USING A THIRD-PARTY OPENGL LOADER. // (e.g. COULD HAPPEN IF YOU ARE DOING A UNITY/JUMBO BUILD, OR INCLUDING .CPP FILES FROM OTHERS) // YOU SHOULD NOT BUILD BOTH IN THE SAME COMPILATION UNIT. // BUT IF YOU REALLY WANT TO, you can '#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM' and imgui_impl_opengl3.cpp // WILL NOT BE USING OUR LOADER, AND INSTEAD EXPECT ANOTHER/YOUR LOADER TO BE AVAILABLE IN THE COMPILATION UNIT. // // Regenerate with: // python gl3w_gen.py --output ../imgui/backends/imgui_impl_opengl3_loader.h --ref ../imgui/backends/imgui_impl_opengl3.cpp ./extra_symbols.txt // // More info: // https://github.com/dearimgui/gl3w_stripped // https://github.com/ocornut/imgui/issues/4445 //----------------------------------------------------------------------------- /* * This file was generated with gl3w_gen.py, part of imgl3w * (hosted at https://github.com/dearimgui/gl3w_stripped) * * This is free and unencumbered software released into the public domain. * * Anyone is free to copy, modify, publish, use, compile, sell, or * distribute this software, either in source code form or as a compiled * binary, for any purpose, commercial or non-commercial, and by any * means. * * In jurisdictions that recognize copyright laws, the author or authors * of this software dedicate any and all copyright interest in the * software to the public domain. We make this dedication for the benefit * of the public at large and to the detriment of our heirs and * successors. We intend this dedication to be an overt act of * relinquishment in perpetuity of all present and future rights to this * software under copyright law. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __gl3w_h_ #define __gl3w_h_ // Adapted from KHR/khrplatform.h to avoid including entire file. #ifndef __khrplatform_h_ typedef float khronos_float_t; typedef signed char khronos_int8_t; typedef unsigned char khronos_uint8_t; typedef signed short int khronos_int16_t; typedef unsigned short int khronos_uint16_t; #ifdef _WIN64 typedef signed long long int khronos_intptr_t; typedef signed long long int khronos_ssize_t; #else typedef signed long int khronos_intptr_t; typedef signed long int khronos_ssize_t; #endif #if defined(_MSC_VER) && !defined(__clang__) typedef signed __int64 khronos_int64_t; typedef unsigned __int64 khronos_uint64_t; #elif (defined(__clang__) || defined(__GNUC__)) && (__cplusplus < 201100) #include typedef int64_t khronos_int64_t; typedef uint64_t khronos_uint64_t; #else typedef signed long long khronos_int64_t; typedef unsigned long long khronos_uint64_t; #endif #endif // __khrplatform_h_ #ifndef __gl_glcorearb_h_ #define __gl_glcorearb_h_ 1 #ifdef __cplusplus extern "C" { #endif /* ** Copyright 2013-2020 The Khronos Group Inc. ** SPDX-License-Identifier: MIT ** ** This header is generated from the Khronos OpenGL / OpenGL ES XML ** API Registry. The current version of the Registry, generator scripts ** used to make the header, and the header can be found at ** https://github.com/KhronosGroup/OpenGL-Registry */ #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN 1 #endif #include #endif #ifndef APIENTRY #define APIENTRY #endif #ifndef APIENTRYP #define APIENTRYP APIENTRY * #endif #ifndef GLAPI #define GLAPI extern #endif /* glcorearb.h is for use with OpenGL core profile implementations. ** It should should be placed in the same directory as gl.h and ** included as . ** ** glcorearb.h includes only APIs in the latest OpenGL core profile ** implementation together with APIs in newer ARB extensions which ** can be supported by the core profile. It does not, and never will ** include functionality removed from the core profile, such as ** fixed-function vertex and fragment processing. ** ** Do not #include both and either of or ** in the same source file. */ /* Generated C header for: * API: gl * Profile: core * Versions considered: .* * Versions emitted: .* * Default extensions included: glcore * Additional extensions included: _nomatch_^ * Extensions removed: _nomatch_^ */ #ifndef GL_VERSION_1_0 typedef void GLvoid; typedef unsigned int GLenum; typedef khronos_float_t GLfloat; typedef int GLint; typedef int GLsizei; typedef unsigned int GLbitfield; typedef double GLdouble; typedef unsigned int GLuint; typedef unsigned char GLboolean; typedef khronos_uint8_t GLubyte; #define GL_COLOR_BUFFER_BIT 0x00004000 #define GL_FALSE 0 #define GL_TRUE 1 #define GL_TRIANGLES 0x0004 #define GL_ONE 1 #define GL_SRC_ALPHA 0x0302 #define GL_ONE_MINUS_SRC_ALPHA 0x0303 #define GL_FRONT 0x0404 #define GL_BACK 0x0405 #define GL_FRONT_AND_BACK 0x0408 #define GL_POLYGON_MODE 0x0B40 #define GL_CULL_FACE 0x0B44 #define GL_DEPTH_TEST 0x0B71 #define GL_STENCIL_TEST 0x0B90 #define GL_VIEWPORT 0x0BA2 #define GL_BLEND 0x0BE2 #define GL_SCISSOR_BOX 0x0C10 #define GL_SCISSOR_TEST 0x0C11 #define GL_UNPACK_ROW_LENGTH 0x0CF2 #define GL_PACK_ALIGNMENT 0x0D05 #define GL_TEXTURE_2D 0x0DE1 #define GL_UNSIGNED_BYTE 0x1401 #define GL_UNSIGNED_SHORT 0x1403 #define GL_UNSIGNED_INT 0x1405 #define GL_FLOAT 0x1406 #define GL_RGBA 0x1908 #define GL_FILL 0x1B02 #define GL_VENDOR 0x1F00 #define GL_RENDERER 0x1F01 #define GL_VERSION 0x1F02 #define GL_EXTENSIONS 0x1F03 #define GL_LINEAR 0x2601 #define GL_TEXTURE_MAG_FILTER 0x2800 #define GL_TEXTURE_MIN_FILTER 0x2801 typedef void (APIENTRYP PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode); typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height); typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask); typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap); typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap); typedef void (APIENTRYP PFNGLFLUSHPROC) (void); typedef void (APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param); typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void); typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data); typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGPROC) (GLenum name); typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC) (GLenum cap); typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height); #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glPolygonMode (GLenum face, GLenum mode); GLAPI void APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); GLAPI void APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); GLAPI void APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); GLAPI void APIENTRY glClear (GLbitfield mask); GLAPI void APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); GLAPI void APIENTRY glDisable (GLenum cap); GLAPI void APIENTRY glEnable (GLenum cap); GLAPI void APIENTRY glFlush (void); GLAPI void APIENTRY glPixelStorei (GLenum pname, GLint param); GLAPI void APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); GLAPI GLenum APIENTRY glGetError (void); GLAPI void APIENTRY glGetIntegerv (GLenum pname, GLint *data); GLAPI const GLubyte *APIENTRY glGetString (GLenum name); GLAPI GLboolean APIENTRY glIsEnabled (GLenum cap); GLAPI void APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); #endif #endif /* GL_VERSION_1_0 */ #ifndef GL_VERSION_1_1 typedef khronos_float_t GLclampf; typedef double GLclampd; #define GL_TEXTURE_BINDING_2D 0x8069 typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices); typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture); typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures); typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures); #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices); GLAPI void APIENTRY glBindTexture (GLenum target, GLuint texture); GLAPI void APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); GLAPI void APIENTRY glGenTextures (GLsizei n, GLuint *textures); #endif #endif /* GL_VERSION_1_1 */ #ifndef GL_VERSION_1_3 #define GL_TEXTURE0 0x84C0 #define GL_ACTIVE_TEXTURE 0x84E0 typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture); #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glActiveTexture (GLenum texture); #endif #endif /* GL_VERSION_1_3 */ #ifndef GL_VERSION_1_4 #define GL_BLEND_DST_RGB 0x80C8 #define GL_BLEND_SRC_RGB 0x80C9 #define GL_BLEND_DST_ALPHA 0x80CA #define GL_BLEND_SRC_ALPHA 0x80CB #define GL_FUNC_ADD 0x8006 typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode); #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); GLAPI void APIENTRY glBlendEquation (GLenum mode); #endif #endif /* GL_VERSION_1_4 */ #ifndef GL_VERSION_1_5 typedef khronos_ssize_t GLsizeiptr; typedef khronos_intptr_t GLintptr; #define GL_ARRAY_BUFFER 0x8892 #define GL_ELEMENT_ARRAY_BUFFER 0x8893 #define GL_ARRAY_BUFFER_BINDING 0x8894 #define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 #define GL_STREAM_DRAW 0x88E0 typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage); typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer); GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers); GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers); GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage); GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); #endif #endif /* GL_VERSION_1_5 */ #ifndef GL_VERSION_2_0 typedef char GLchar; typedef khronos_int16_t GLshort; typedef khronos_int8_t GLbyte; typedef khronos_uint16_t GLushort; #define GL_BLEND_EQUATION_RGB 0x8009 #define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 #define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 #define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 #define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 #define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 #define GL_BLEND_EQUATION_ALPHA 0x883D #define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A #define GL_FRAGMENT_SHADER 0x8B30 #define GL_VERTEX_SHADER 0x8B31 #define GL_COMPILE_STATUS 0x8B81 #define GL_LINK_STATUS 0x8B82 #define GL_INFO_LOG_LENGTH 0x8B84 #define GL_CURRENT_PROGRAM 0x8B8D #define GL_UPPER_LEFT 0x8CA2 typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha); typedef void (APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); typedef void (APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader); typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC) (void); typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC) (GLenum type); typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program); typedef void (APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader); typedef void (APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index); typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name); typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); typedef void (APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer); typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC) (GLuint program); typedef void (APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program); typedef void (APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); typedef void (APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program); typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0); typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); GLAPI void APIENTRY glAttachShader (GLuint program, GLuint shader); GLAPI void APIENTRY glCompileShader (GLuint shader); GLAPI GLuint APIENTRY glCreateProgram (void); GLAPI GLuint APIENTRY glCreateShader (GLenum type); GLAPI void APIENTRY glDeleteProgram (GLuint program); GLAPI void APIENTRY glDeleteShader (GLuint shader); GLAPI void APIENTRY glDetachShader (GLuint program, GLuint shader); GLAPI void APIENTRY glDisableVertexAttribArray (GLuint index); GLAPI void APIENTRY glEnableVertexAttribArray (GLuint index); GLAPI GLint APIENTRY glGetAttribLocation (GLuint program, const GLchar *name); GLAPI void APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params); GLAPI void APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); GLAPI void APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params); GLAPI void APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); GLAPI GLint APIENTRY glGetUniformLocation (GLuint program, const GLchar *name); GLAPI void APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params); GLAPI void APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer); GLAPI GLboolean APIENTRY glIsProgram (GLuint program); GLAPI void APIENTRY glLinkProgram (GLuint program); GLAPI void APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); GLAPI void APIENTRY glUseProgram (GLuint program); GLAPI void APIENTRY glUniform1i (GLint location, GLint v0); GLAPI void APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); GLAPI void APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); #endif #endif /* GL_VERSION_2_0 */ #ifndef GL_VERSION_3_0 typedef khronos_uint16_t GLhalf; #define GL_MAJOR_VERSION 0x821B #define GL_MINOR_VERSION 0x821C #define GL_NUM_EXTENSIONS 0x821D #define GL_FRAMEBUFFER_SRGB 0x8DB9 #define GL_VERTEX_ARRAY_BINDING 0x85B5 typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data); typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data); typedef const GLubyte *(APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index); typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array); typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays); typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays); #ifdef GL_GLEXT_PROTOTYPES GLAPI const GLubyte *APIENTRY glGetStringi (GLenum name, GLuint index); GLAPI void APIENTRY glBindVertexArray (GLuint array); GLAPI void APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays); GLAPI void APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays); #endif #endif /* GL_VERSION_3_0 */ #ifndef GL_VERSION_3_1 #define GL_VERSION_3_1 1 #define GL_PRIMITIVE_RESTART 0x8F9D #endif /* GL_VERSION_3_1 */ #ifndef GL_VERSION_3_2 #define GL_VERSION_3_2 1 typedef struct __GLsync *GLsync; typedef khronos_uint64_t GLuint64; typedef khronos_int64_t GLint64; #define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 #define GL_CONTEXT_PROFILE_MASK 0x9126 typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data); #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); #endif #endif /* GL_VERSION_3_2 */ #ifndef GL_VERSION_3_3 #define GL_VERSION_3_3 1 #define GL_SAMPLER_BINDING 0x8919 typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler); #endif #endif /* GL_VERSION_3_3 */ #ifndef GL_VERSION_4_1 typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfloat *data); typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data); #endif /* GL_VERSION_4_1 */ #ifndef GL_VERSION_4_3 typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); #endif /* GL_VERSION_4_3 */ #ifndef GL_VERSION_4_5 #define GL_CLIP_ORIGIN 0x935C typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint *param); typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI64_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint64 *param); #endif /* GL_VERSION_4_5 */ #ifndef GL_ARB_bindless_texture typedef khronos_uint64_t GLuint64EXT; #endif /* GL_ARB_bindless_texture */ #ifndef GL_ARB_cl_event struct _cl_context; struct _cl_event; #endif /* GL_ARB_cl_event */ #ifndef GL_ARB_clip_control #define GL_ARB_clip_control 1 #endif /* GL_ARB_clip_control */ #ifndef GL_ARB_debug_output typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); #endif /* GL_ARB_debug_output */ #ifndef GL_EXT_EGL_image_storage typedef void *GLeglImageOES; #endif /* GL_EXT_EGL_image_storage */ #ifndef GL_EXT_direct_state_access typedef void (APIENTRYP PFNGLGETFLOATI_VEXTPROC) (GLenum pname, GLuint index, GLfloat *params); typedef void (APIENTRYP PFNGLGETDOUBLEI_VEXTPROC) (GLenum pname, GLuint index, GLdouble *params); typedef void (APIENTRYP PFNGLGETPOINTERI_VEXTPROC) (GLenum pname, GLuint index, void **params); typedef void (APIENTRYP PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, GLint *param); typedef void (APIENTRYP PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) (GLuint vaobj, GLuint index, GLenum pname, void **param); #endif /* GL_EXT_direct_state_access */ #ifndef GL_NV_draw_vulkan_image typedef void (APIENTRY *GLVULKANPROCNV)(void); #endif /* GL_NV_draw_vulkan_image */ #ifndef GL_NV_gpu_shader5 typedef khronos_int64_t GLint64EXT; #endif /* GL_NV_gpu_shader5 */ #ifndef GL_NV_vertex_buffer_unified_memory typedef void (APIENTRYP PFNGLGETINTEGERUI64I_VNVPROC) (GLenum value, GLuint index, GLuint64EXT *result); #endif /* GL_NV_vertex_buffer_unified_memory */ #ifdef __cplusplus } #endif #endif #ifndef GL3W_API #define GL3W_API #endif #ifndef __gl_h_ #define __gl_h_ #endif #ifdef __cplusplus extern "C" { #endif #define GL3W_OK 0 #define GL3W_ERROR_INIT -1 #define GL3W_ERROR_LIBRARY_OPEN -2 #define GL3W_ERROR_OPENGL_VERSION -3 typedef void (*GL3WglProc)(void); typedef GL3WglProc (*GL3WGetProcAddressProc)(const char *proc); /* gl3w api */ GL3W_API int imgl3wInit(void); GL3W_API int imgl3wInit2(GL3WGetProcAddressProc proc); GL3W_API int imgl3wIsSupported(int major, int minor); GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc); /* gl3w internal state */ union ImGL3WProcs { GL3WglProc ptr[59]; struct { PFNGLACTIVETEXTUREPROC ActiveTexture; PFNGLATTACHSHADERPROC AttachShader; PFNGLBINDBUFFERPROC BindBuffer; PFNGLBINDSAMPLERPROC BindSampler; PFNGLBINDTEXTUREPROC BindTexture; PFNGLBINDVERTEXARRAYPROC BindVertexArray; PFNGLBLENDEQUATIONPROC BlendEquation; PFNGLBLENDEQUATIONSEPARATEPROC BlendEquationSeparate; PFNGLBLENDFUNCSEPARATEPROC BlendFuncSeparate; PFNGLBUFFERDATAPROC BufferData; PFNGLBUFFERSUBDATAPROC BufferSubData; PFNGLCLEARPROC Clear; PFNGLCLEARCOLORPROC ClearColor; PFNGLCOMPILESHADERPROC CompileShader; PFNGLCREATEPROGRAMPROC CreateProgram; PFNGLCREATESHADERPROC CreateShader; PFNGLDELETEBUFFERSPROC DeleteBuffers; PFNGLDELETEPROGRAMPROC DeleteProgram; PFNGLDELETESHADERPROC DeleteShader; PFNGLDELETETEXTURESPROC DeleteTextures; PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays; PFNGLDETACHSHADERPROC DetachShader; PFNGLDISABLEPROC Disable; PFNGLDISABLEVERTEXATTRIBARRAYPROC DisableVertexAttribArray; PFNGLDRAWELEMENTSPROC DrawElements; PFNGLDRAWELEMENTSBASEVERTEXPROC DrawElementsBaseVertex; PFNGLENABLEPROC Enable; PFNGLENABLEVERTEXATTRIBARRAYPROC EnableVertexAttribArray; PFNGLFLUSHPROC Flush; PFNGLGENBUFFERSPROC GenBuffers; PFNGLGENTEXTURESPROC GenTextures; PFNGLGENVERTEXARRAYSPROC GenVertexArrays; PFNGLGETATTRIBLOCATIONPROC GetAttribLocation; PFNGLGETERRORPROC GetError; PFNGLGETINTEGERVPROC GetIntegerv; PFNGLGETPROGRAMINFOLOGPROC GetProgramInfoLog; PFNGLGETPROGRAMIVPROC GetProgramiv; PFNGLGETSHADERINFOLOGPROC GetShaderInfoLog; PFNGLGETSHADERIVPROC GetShaderiv; PFNGLGETSTRINGPROC GetString; PFNGLGETSTRINGIPROC GetStringi; PFNGLGETUNIFORMLOCATIONPROC GetUniformLocation; PFNGLGETVERTEXATTRIBPOINTERVPROC GetVertexAttribPointerv; PFNGLGETVERTEXATTRIBIVPROC GetVertexAttribiv; PFNGLISENABLEDPROC IsEnabled; PFNGLISPROGRAMPROC IsProgram; PFNGLLINKPROGRAMPROC LinkProgram; PFNGLPIXELSTOREIPROC PixelStorei; PFNGLPOLYGONMODEPROC PolygonMode; PFNGLREADPIXELSPROC ReadPixels; PFNGLSCISSORPROC Scissor; PFNGLSHADERSOURCEPROC ShaderSource; PFNGLTEXIMAGE2DPROC TexImage2D; PFNGLTEXPARAMETERIPROC TexParameteri; PFNGLUNIFORM1IPROC Uniform1i; PFNGLUNIFORMMATRIX4FVPROC UniformMatrix4fv; PFNGLUSEPROGRAMPROC UseProgram; PFNGLVERTEXATTRIBPOINTERPROC VertexAttribPointer; PFNGLVIEWPORTPROC Viewport; } gl; }; GL3W_API extern union ImGL3WProcs imgl3wProcs; /* OpenGL functions */ #define glActiveTexture imgl3wProcs.gl.ActiveTexture #define glAttachShader imgl3wProcs.gl.AttachShader #define glBindBuffer imgl3wProcs.gl.BindBuffer #define glBindSampler imgl3wProcs.gl.BindSampler #define glBindTexture imgl3wProcs.gl.BindTexture #define glBindVertexArray imgl3wProcs.gl.BindVertexArray #define glBlendEquation imgl3wProcs.gl.BlendEquation #define glBlendEquationSeparate imgl3wProcs.gl.BlendEquationSeparate #define glBlendFuncSeparate imgl3wProcs.gl.BlendFuncSeparate #define glBufferData imgl3wProcs.gl.BufferData #define glBufferSubData imgl3wProcs.gl.BufferSubData #define glClear imgl3wProcs.gl.Clear #define glClearColor imgl3wProcs.gl.ClearColor #define glCompileShader imgl3wProcs.gl.CompileShader #define glCreateProgram imgl3wProcs.gl.CreateProgram #define glCreateShader imgl3wProcs.gl.CreateShader #define glDeleteBuffers imgl3wProcs.gl.DeleteBuffers #define glDeleteProgram imgl3wProcs.gl.DeleteProgram #define glDeleteShader imgl3wProcs.gl.DeleteShader #define glDeleteTextures imgl3wProcs.gl.DeleteTextures #define glDeleteVertexArrays imgl3wProcs.gl.DeleteVertexArrays #define glDetachShader imgl3wProcs.gl.DetachShader #define glDisable imgl3wProcs.gl.Disable #define glDisableVertexAttribArray imgl3wProcs.gl.DisableVertexAttribArray #define glDrawElements imgl3wProcs.gl.DrawElements #define glDrawElementsBaseVertex imgl3wProcs.gl.DrawElementsBaseVertex #define glEnable imgl3wProcs.gl.Enable #define glEnableVertexAttribArray imgl3wProcs.gl.EnableVertexAttribArray #define glFlush imgl3wProcs.gl.Flush #define glGenBuffers imgl3wProcs.gl.GenBuffers #define glGenTextures imgl3wProcs.gl.GenTextures #define glGenVertexArrays imgl3wProcs.gl.GenVertexArrays #define glGetAttribLocation imgl3wProcs.gl.GetAttribLocation #define glGetError imgl3wProcs.gl.GetError #define glGetIntegerv imgl3wProcs.gl.GetIntegerv #define glGetProgramInfoLog imgl3wProcs.gl.GetProgramInfoLog #define glGetProgramiv imgl3wProcs.gl.GetProgramiv #define glGetShaderInfoLog imgl3wProcs.gl.GetShaderInfoLog #define glGetShaderiv imgl3wProcs.gl.GetShaderiv #define glGetString imgl3wProcs.gl.GetString #define glGetStringi imgl3wProcs.gl.GetStringi #define glGetUniformLocation imgl3wProcs.gl.GetUniformLocation #define glGetVertexAttribPointerv imgl3wProcs.gl.GetVertexAttribPointerv #define glGetVertexAttribiv imgl3wProcs.gl.GetVertexAttribiv #define glIsEnabled imgl3wProcs.gl.IsEnabled #define glIsProgram imgl3wProcs.gl.IsProgram #define glLinkProgram imgl3wProcs.gl.LinkProgram #define glPixelStorei imgl3wProcs.gl.PixelStorei #define glPolygonMode imgl3wProcs.gl.PolygonMode #define glReadPixels imgl3wProcs.gl.ReadPixels #define glScissor imgl3wProcs.gl.Scissor #define glShaderSource imgl3wProcs.gl.ShaderSource #define glTexImage2D imgl3wProcs.gl.TexImage2D #define glTexParameteri imgl3wProcs.gl.TexParameteri #define glUniform1i imgl3wProcs.gl.Uniform1i #define glUniformMatrix4fv imgl3wProcs.gl.UniformMatrix4fv #define glUseProgram imgl3wProcs.gl.UseProgram #define glVertexAttribPointer imgl3wProcs.gl.VertexAttribPointer #define glViewport imgl3wProcs.gl.Viewport #ifdef __cplusplus } #endif #endif #ifdef IMGL3W_IMPL #ifdef __cplusplus extern "C" { #endif #include #define GL3W_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #if defined(_WIN32) #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN 1 #endif #include static HMODULE libgl; typedef PROC(__stdcall* GL3WglGetProcAddr)(LPCSTR); static GL3WglGetProcAddr wgl_get_proc_address; static int open_libgl(void) { libgl = LoadLibraryA("opengl32.dll"); if (!libgl) return GL3W_ERROR_LIBRARY_OPEN; wgl_get_proc_address = (GL3WglGetProcAddr)GetProcAddress(libgl, "wglGetProcAddress"); return GL3W_OK; } static void close_libgl(void) { FreeLibrary(libgl); } static GL3WglProc get_proc(const char *proc) { GL3WglProc res; res = (GL3WglProc)wgl_get_proc_address(proc); if (!res) res = (GL3WglProc)GetProcAddress(libgl, proc); return res; } #elif defined(__APPLE__) #include static void *libgl; static int open_libgl(void) { libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY | RTLD_LOCAL); if (!libgl) return GL3W_ERROR_LIBRARY_OPEN; return GL3W_OK; } static void close_libgl(void) { dlclose(libgl); } static GL3WglProc get_proc(const char *proc) { GL3WglProc res; *(void **)(&res) = dlsym(libgl, proc); return res; } #else #include static void *libgl; static GL3WglProc (*glx_get_proc_address)(const GLubyte *); static int open_libgl(void) { // While most systems use libGL.so.1, NetBSD seems to use that libGL.so.3. See https://github.com/ocornut/imgui/issues/6983 libgl = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL); if (!libgl) libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL); if (!libgl) libgl = dlopen("libGL.so.3", RTLD_LAZY | RTLD_LOCAL); if (!libgl) return GL3W_ERROR_LIBRARY_OPEN; *(void **)(&glx_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB"); return GL3W_OK; } static void close_libgl(void) { dlclose(libgl); } static GL3WglProc get_proc(const char *proc) { GL3WglProc res; res = glx_get_proc_address((const GLubyte *)proc); if (!res) *(void **)(&res) = dlsym(libgl, proc); return res; } #endif static struct { int major, minor; } version; static int parse_version(void) { if (!glGetIntegerv) return GL3W_ERROR_INIT; glGetIntegerv(GL_MAJOR_VERSION, &version.major); glGetIntegerv(GL_MINOR_VERSION, &version.minor); if (version.major == 0 && version.minor == 0) { // Query GL_VERSION in desktop GL 2.x, the string will start with "." if (const char* gl_version = (const char*)glGetString(GL_VERSION)) sscanf(gl_version, "%d.%d", &version.major, &version.minor); } if (version.major < 2) return GL3W_ERROR_OPENGL_VERSION; return GL3W_OK; } static void load_procs(GL3WGetProcAddressProc proc); int imgl3wInit(void) { int res = open_libgl(); if (res) return res; atexit(close_libgl); return imgl3wInit2(get_proc); } int imgl3wInit2(GL3WGetProcAddressProc proc) { load_procs(proc); return parse_version(); } int imgl3wIsSupported(int major, int minor) { if (major < 2) return 0; if (version.major == major) return version.minor >= minor; return version.major >= major; } GL3WglProc imgl3wGetProcAddress(const char *proc) { return get_proc(proc); } static const char *proc_names[] = { "glActiveTexture", "glAttachShader", "glBindBuffer", "glBindSampler", "glBindTexture", "glBindVertexArray", "glBlendEquation", "glBlendEquationSeparate", "glBlendFuncSeparate", "glBufferData", "glBufferSubData", "glClear", "glClearColor", "glCompileShader", "glCreateProgram", "glCreateShader", "glDeleteBuffers", "glDeleteProgram", "glDeleteShader", "glDeleteTextures", "glDeleteVertexArrays", "glDetachShader", "glDisable", "glDisableVertexAttribArray", "glDrawElements", "glDrawElementsBaseVertex", "glEnable", "glEnableVertexAttribArray", "glFlush", "glGenBuffers", "glGenTextures", "glGenVertexArrays", "glGetAttribLocation", "glGetError", "glGetIntegerv", "glGetProgramInfoLog", "glGetProgramiv", "glGetShaderInfoLog", "glGetShaderiv", "glGetString", "glGetStringi", "glGetUniformLocation", "glGetVertexAttribPointerv", "glGetVertexAttribiv", "glIsEnabled", "glIsProgram", "glLinkProgram", "glPixelStorei", "glPolygonMode", "glReadPixels", "glScissor", "glShaderSource", "glTexImage2D", "glTexParameteri", "glUniform1i", "glUniformMatrix4fv", "glUseProgram", "glVertexAttribPointer", "glViewport", }; GL3W_API union ImGL3WProcs imgl3wProcs; static void load_procs(GL3WGetProcAddressProc proc) { size_t i; for (i = 0; i < GL3W_ARRAY_SIZE(proc_names); i++) imgl3wProcs.ptr[i] = proc(proc_names[i]); } #ifdef __cplusplus } #endif #endif RenderKit-ospray-f2a61c2/apps/common/external/imgui/imgui_internal.h000066400000000000000000010012011456566705700257100ustar00rootroot00000000000000// dear imgui, v1.90.3 // (internal structures/api) // You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility. /* Index of this file: // [SECTION] Header mess // [SECTION] Forward declarations // [SECTION] Context pointer // [SECTION] STB libraries includes // [SECTION] Macros // [SECTION] Generic helpers // [SECTION] ImDrawList support // [SECTION] Widgets support: flags, enums, data structures // [SECTION] Data types support // [SECTION] Popup support // [SECTION] Inputs support // [SECTION] Clipper support // [SECTION] Navigation support // [SECTION] Typing-select support // [SECTION] Columns support // [SECTION] Multi-select support // [SECTION] Docking support // [SECTION] Viewport support // [SECTION] Settings support // [SECTION] Localization support // [SECTION] Metrics, Debug tools // [SECTION] Generic context hooks // [SECTION] ImGuiContext (main imgui context) // [SECTION] ImGuiWindowTempData, ImGuiWindow // [SECTION] Tab bar, Tab item support // [SECTION] Table support // [SECTION] ImGui internal API // [SECTION] ImFontAtlas internal API // [SECTION] Test Engine specific hooks (imgui_test_engine) */ #pragma once #ifndef IMGUI_DISABLE //----------------------------------------------------------------------------- // [SECTION] Header mess //----------------------------------------------------------------------------- #ifndef IMGUI_VERSION #include "imgui.h" #endif #include // FILE*, sscanf #include // NULL, malloc, free, qsort, atoi, atof #include // sqrtf, fabsf, fmodf, powf, floorf, ceilf, cosf, sinf #include // INT_MIN, INT_MAX // Enable SSE intrinsics if available #if (defined __SSE__ || defined __x86_64__ || defined _M_X64 || (defined(_M_IX86_FP) && (_M_IX86_FP >= 1))) && !defined(IMGUI_DISABLE_SSE) #define IMGUI_ENABLE_SSE #include #endif // Visual Studio warnings #ifdef _MSC_VER #pragma warning (push) #pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport) #pragma warning (disable: 26812) // The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). [MSVC Static Analyzer) #pragma warning (disable: 26495) // [Static Analyzer] Variable 'XXX' is uninitialized. Always initialize a member variable (type.6). #if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later #pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types #endif #endif // Clang/GCC warnings with -Weverything #if defined(__clang__) #pragma clang diagnostic push #if __has_warning("-Wunknown-warning-option") #pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' #endif #pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' #pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants ok, for ImFloor() #pragma clang diagnostic ignored "-Wunused-function" // for stb_textedit.h #pragma clang diagnostic ignored "-Wmissing-prototypes" // for stb_textedit.h #pragma clang diagnostic ignored "-Wold-style-cast" #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" #pragma clang diagnostic ignored "-Wdouble-promotion" #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision #pragma clang diagnostic ignored "-Wmissing-noreturn" // warning: function 'xxx' could be declared with attribute 'noreturn' #elif defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #endif // In 1.89.4, we moved the implementation of "courtesy maths operators" from imgui_internal.h in imgui.h // As they are frequently requested, we do not want to encourage to many people using imgui_internal.h #if defined(IMGUI_DEFINE_MATH_OPERATORS) && !defined(IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED) #error Please '#define IMGUI_DEFINE_MATH_OPERATORS' _BEFORE_ including imgui.h! #endif // Legacy defines #ifdef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS // Renamed in 1.74 #error Use IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS #endif #ifdef IMGUI_DISABLE_MATH_FUNCTIONS // Renamed in 1.74 #error Use IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS #endif // Enable stb_truetype by default unless FreeType is enabled. // You can compile with both by defining both IMGUI_ENABLE_FREETYPE and IMGUI_ENABLE_STB_TRUETYPE together. #ifndef IMGUI_ENABLE_FREETYPE #define IMGUI_ENABLE_STB_TRUETYPE #endif //----------------------------------------------------------------------------- // [SECTION] Forward declarations //----------------------------------------------------------------------------- struct ImBitVector; // Store 1-bit per value struct ImRect; // An axis-aligned rectangle (2 points) struct ImDrawDataBuilder; // Helper to build a ImDrawData instance struct ImDrawListSharedData; // Data shared between all ImDrawList instances struct ImGuiColorMod; // Stacked color modifier, backup of modified data so we can restore it struct ImGuiContext; // Main Dear ImGui context struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine struct ImGuiDataVarInfo; // Variable information (e.g. to avoid style variables from an enum) struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum struct ImGuiGroupData; // Stacked storage data for BeginGroup()/EndGroup() struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box struct ImGuiInputTextDeactivateData;// Short term storage to backup text of a deactivating InputText() while another is stealing active id struct ImGuiLastItemData; // Status storage for last submitted items struct ImGuiLocEntry; // A localization entry. struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only struct ImGuiNavItemData; // Result of a gamepad/keyboard directional navigation move query result struct ImGuiNavTreeNodeData; // Temporary storage for last TreeNode() being a Left arrow landing candidate. struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions struct ImGuiNextWindowData; // Storage for SetNextWindow** functions struct ImGuiNextItemData; // Storage for SetNextItem** functions struct ImGuiOldColumnData; // Storage data for a single column for legacy Columns() api struct ImGuiOldColumns; // Storage data for a columns set for legacy Columns() api struct ImGuiPopupData; // Storage for current popup stack struct ImGuiSettingsHandler; // Storage for one type registered in the .ini file struct ImGuiStackSizes; // Storage of stack sizes for debugging/asserting struct ImGuiStyleMod; // Stacked style modifier, backup of modified data so we can restore it struct ImGuiTabBar; // Storage for a tab bar struct ImGuiTabItem; // Storage for a tab item (within a tab bar) struct ImGuiTable; // Storage for a table struct ImGuiTableColumn; // Storage for one column of a table struct ImGuiTableInstanceData; // Storage for one instance of a same table struct ImGuiTableTempData; // Temporary storage for one table (one per table in the stack), shared between tables. struct ImGuiTableSettings; // Storage for a table .ini settings struct ImGuiTableColumnsSettings; // Storage for a column .ini settings struct ImGuiTypingSelectState; // Storage for GetTypingSelectRequest() struct ImGuiTypingSelectRequest; // Storage for GetTypingSelectRequest() (aimed to be public) struct ImGuiWindow; // Storage for one window struct ImGuiWindowTempData; // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame, in practice we currently keep it for each window) struct ImGuiWindowSettings; // Storage for a window .ini settings (we keep one of those even if the actual window wasn't instanced during this session) // Enumerations // Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists. enum ImGuiLocKey : int; // -> enum ImGuiLocKey // Enum: a localization entry for translation. typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // Enum: Horizontal or vertical // Flags typedef int ImGuiActivateFlags; // -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later) typedef int ImGuiDebugLogFlags; // -> enum ImGuiDebugLogFlags_ // Flags: for ShowDebugLogWindow(), g.DebugLogFlags typedef int ImGuiFocusRequestFlags; // -> enum ImGuiFocusRequestFlags_ // Flags: for FocusWindow(); typedef int ImGuiInputFlags; // -> enum ImGuiInputFlags_ // Flags: for IsKeyPressed(), IsMouseClicked(), SetKeyOwner(), SetItemKeyOwner() etc. typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag(), g.LastItemData.InFlags typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for g.LastItemData.StatusFlags typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns() typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight() typedef int ImGuiNavMoveFlags; // -> enum ImGuiNavMoveFlags_ // Flags: for navigation requests typedef int ImGuiNextItemDataFlags; // -> enum ImGuiNextItemDataFlags_ // Flags: for SetNextItemXXX() functions typedef int ImGuiNextWindowDataFlags; // -> enum ImGuiNextWindowDataFlags_// Flags: for SetNextWindowXXX() functions typedef int ImGuiScrollFlags; // -> enum ImGuiScrollFlags_ // Flags: for ScrollToItem() and navigation requests typedef int ImGuiSeparatorFlags; // -> enum ImGuiSeparatorFlags_ // Flags: for SeparatorEx() typedef int ImGuiTextFlags; // -> enum ImGuiTextFlags_ // Flags: for TextEx() typedef int ImGuiTooltipFlags; // -> enum ImGuiTooltipFlags_ // Flags: for BeginTooltipEx() typedef int ImGuiTypingSelectFlags; // -> enum ImGuiTypingSelectFlags_ // Flags: for GetTypingSelectRequest() typedef void (*ImGuiErrorLogCallback)(void* user_data, const char* fmt, ...); //----------------------------------------------------------------------------- // [SECTION] Context pointer // See implementation of this variable in imgui.cpp for comments and details. //----------------------------------------------------------------------------- #ifndef GImGui extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer #endif //------------------------------------------------------------------------- // [SECTION] STB libraries includes //------------------------------------------------------------------------- namespace ImStb { #undef IMSTB_TEXTEDIT_STRING #undef IMSTB_TEXTEDIT_CHARTYPE #define IMSTB_TEXTEDIT_STRING ImGuiInputTextState #define IMSTB_TEXTEDIT_CHARTYPE ImWchar #define IMSTB_TEXTEDIT_GETWIDTH_NEWLINE (-1.0f) #define IMSTB_TEXTEDIT_UNDOSTATECOUNT 99 #define IMSTB_TEXTEDIT_UNDOCHARCOUNT 999 #include "imstb_textedit.h" } // namespace ImStb //----------------------------------------------------------------------------- // [SECTION] Macros //----------------------------------------------------------------------------- // Debug Printing Into TTY // (since IMGUI_VERSION_NUM >= 18729: IMGUI_DEBUG_LOG was reworked into IMGUI_DEBUG_PRINTF (and removed framecount from it). If you were using a #define IMGUI_DEBUG_LOG please rename) #ifndef IMGUI_DEBUG_PRINTF #ifndef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS #define IMGUI_DEBUG_PRINTF(_FMT,...) printf(_FMT, __VA_ARGS__) #else #define IMGUI_DEBUG_PRINTF(_FMT,...) ((void)0) #endif #endif // Debug Logging for ShowDebugLogWindow(). This is designed for relatively rare events so please don't spam. #ifndef IMGUI_DISABLE_DEBUG_TOOLS #define IMGUI_DEBUG_LOG(...) ImGui::DebugLog(__VA_ARGS__) #else #define IMGUI_DEBUG_LOG(...) ((void)0) #endif #define IMGUI_DEBUG_LOG_ACTIVEID(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventActiveId) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_FOCUS(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventFocus) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_POPUP(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_NAV(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventNav) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_SELECTION(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_CLIPPER(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventClipper) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_IO(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) #define IMGUI_DEBUG_LOG_INPUTROUTING(...) do{if (g.DebugLogFlags & ImGuiDebugLogFlags_EventInputRouting)IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) // Static Asserts #define IM_STATIC_ASSERT(_COND) static_assert(_COND, "") // "Paranoid" Debug Asserts are meant to only be enabled during specific debugging/work, otherwise would slow down the code too much. // We currently don't have many of those so the effect is currently negligible, but onward intent to add more aggressive ones in the code. //#define IMGUI_DEBUG_PARANOID #ifdef IMGUI_DEBUG_PARANOID #define IM_ASSERT_PARANOID(_EXPR) IM_ASSERT(_EXPR) #else #define IM_ASSERT_PARANOID(_EXPR) #endif // Error handling // Down the line in some frameworks/languages we would like to have a way to redirect those to the programmer and recover from more faults. #ifndef IM_ASSERT_USER_ERROR #define IM_ASSERT_USER_ERROR(_EXP,_MSG) IM_ASSERT((_EXP) && _MSG) // Recoverable User Error #endif // Misc Macros #define IM_PI 3.14159265358979323846f #ifdef _WIN32 #define IM_NEWLINE "\r\n" // Play it nice with Windows users (Update: since 2018-05, Notepad finally appears to support Unix-style carriage returns!) #else #define IM_NEWLINE "\n" #endif #ifndef IM_TABSIZE // Until we move this to runtime and/or add proper tab support, at least allow users to compile-time override #define IM_TABSIZE (4) #endif #define IM_MEMALIGN(_OFF,_ALIGN) (((_OFF) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1)) // Memory align e.g. IM_ALIGN(0,4)=0, IM_ALIGN(1,4)=4, IM_ALIGN(4,4)=4, IM_ALIGN(5,4)=8 #define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose #define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255 #define IM_TRUNC(_VAL) ((float)(int)(_VAL)) // ImTrunc() is not inlined in MSVC debug builds #define IM_ROUND(_VAL) ((float)(int)((_VAL) + 0.5f)) // #define IM_STRINGIFY_HELPER(_X) #_X #define IM_STRINGIFY(_X) IM_STRINGIFY_HELPER(_X) // Preprocessor idiom to stringify e.g. an integer. #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #define IM_FLOOR IM_TRUNC #endif // Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall #ifdef _MSC_VER #define IMGUI_CDECL __cdecl #else #define IMGUI_CDECL #endif // Warnings #if defined(_MSC_VER) && !defined(__clang__) #define IM_MSVC_WARNING_SUPPRESS(XXXX) __pragma(warning(suppress: XXXX)) #else #define IM_MSVC_WARNING_SUPPRESS(XXXX) #endif // Debug Tools // Use 'Metrics/Debugger->Tools->Item Picker' to break into the call-stack of a specific item. // This will call IM_DEBUG_BREAK() which you may redefine yourself. See https://github.com/scottt/debugbreak for more reference. #ifndef IM_DEBUG_BREAK #if defined (_MSC_VER) #define IM_DEBUG_BREAK() __debugbreak() #elif defined(__clang__) #define IM_DEBUG_BREAK() __builtin_debugtrap() #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) #define IM_DEBUG_BREAK() __asm__ volatile("int3;nop") #elif defined(__GNUC__) && defined(__thumb__) #define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xde01") #elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__) #define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xe7f001f0") #else #define IM_DEBUG_BREAK() IM_ASSERT(0) // It is expected that you define IM_DEBUG_BREAK() into something that will break nicely in a debugger! #endif #endif // #ifndef IM_DEBUG_BREAK // Format specifiers, printing 64-bit hasn't been decently standardized... // In a real application you should be using PRId64 and PRIu64 from (non-windows) and on Windows define them yourself. #if defined(_MSC_VER) && !defined(__clang__) #define IM_PRId64 "I64d" #define IM_PRIu64 "I64u" #define IM_PRIX64 "I64X" #else #define IM_PRId64 "lld" #define IM_PRIu64 "llu" #define IM_PRIX64 "llX" #endif //----------------------------------------------------------------------------- // [SECTION] Generic helpers // Note that the ImXXX helpers functions are lower-level than ImGui functions. // ImGui functions or the ImGui context are never called/used from other ImXXX functions. //----------------------------------------------------------------------------- // - Helpers: Hashing // - Helpers: Sorting // - Helpers: Bit manipulation // - Helpers: String // - Helpers: Formatting // - Helpers: UTF-8 <> wchar conversions // - Helpers: ImVec2/ImVec4 operators // - Helpers: Maths // - Helpers: Geometry // - Helper: ImVec1 // - Helper: ImVec2ih // - Helper: ImRect // - Helper: ImBitArray // - Helper: ImBitVector // - Helper: ImSpan<>, ImSpanAllocator<> // - Helper: ImPool<> // - Helper: ImChunkStream<> // - Helper: ImGuiTextIndex //----------------------------------------------------------------------------- // Helpers: Hashing IMGUI_API ImGuiID ImHashData(const void* data, size_t data_size, ImGuiID seed = 0); IMGUI_API ImGuiID ImHashStr(const char* data, size_t data_size = 0, ImGuiID seed = 0); // Helpers: Sorting #ifndef ImQsort static inline void ImQsort(void* base, size_t count, size_t size_of_element, int(IMGUI_CDECL *compare_func)(void const*, void const*)) { if (count > 1) qsort(base, count, size_of_element, compare_func); } #endif // Helpers: Color Blending IMGUI_API ImU32 ImAlphaBlendColors(ImU32 col_a, ImU32 col_b); // Helpers: Bit manipulation static inline bool ImIsPowerOfTwo(int v) { return v != 0 && (v & (v - 1)) == 0; } static inline bool ImIsPowerOfTwo(ImU64 v) { return v != 0 && (v & (v - 1)) == 0; } static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; } // Helpers: String IMGUI_API int ImStricmp(const char* str1, const char* str2); // Case insensitive compare. IMGUI_API int ImStrnicmp(const char* str1, const char* str2, size_t count); // Case insensitive compare to a certain count. IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count); // Copy to a certain count and always zero terminate (strncpy doesn't). IMGUI_API char* ImStrdup(const char* str); // Duplicate a string. IMGUI_API char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* str); // Copy in provided buffer, recreate buffer if needed. IMGUI_API const char* ImStrchrRange(const char* str_begin, const char* str_end, char c); // Find first occurrence of 'c' in string range. IMGUI_API const char* ImStreolRange(const char* str, const char* str_end); // End end-of-line IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end); // Find a substring in a string range. IMGUI_API void ImStrTrimBlanks(char* str); // Remove leading and trailing blanks from a buffer. IMGUI_API const char* ImStrSkipBlank(const char* str); // Find first non-blank character. IMGUI_API int ImStrlenW(const ImWchar* str); // Computer string length (ImWchar string) IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line (ImWchar string) IM_MSVC_RUNTIME_CHECKS_OFF static inline char ImToUpper(char c) { return (c >= 'a' && c <= 'z') ? c &= ~32 : c; } static inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; } static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; } IM_MSVC_RUNTIME_CHECKS_RESTORE // Helpers: Formatting IMGUI_API int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) IM_FMTARGS(3); IMGUI_API int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args) IM_FMTLIST(3); IMGUI_API void ImFormatStringToTempBuffer(const char** out_buf, const char** out_buf_end, const char* fmt, ...) IM_FMTARGS(3); IMGUI_API void ImFormatStringToTempBufferV(const char** out_buf, const char** out_buf_end, const char* fmt, va_list args) IM_FMTLIST(3); IMGUI_API const char* ImParseFormatFindStart(const char* format); IMGUI_API const char* ImParseFormatFindEnd(const char* format); IMGUI_API const char* ImParseFormatTrimDecorations(const char* format, char* buf, size_t buf_size); IMGUI_API void ImParseFormatSanitizeForPrinting(const char* fmt_in, char* fmt_out, size_t fmt_out_size); IMGUI_API const char* ImParseFormatSanitizeForScanning(const char* fmt_in, char* fmt_out, size_t fmt_out_size); IMGUI_API int ImParseFormatPrecision(const char* format, int default_value); // Helpers: UTF-8 <> wchar conversions IMGUI_API const char* ImTextCharToUtf8(char out_buf[5], unsigned int c); // return out_buf IMGUI_API int ImTextStrToUtf8(char* out_buf, int out_buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count IMGUI_API int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end); // read one character. return input UTF-8 bytes count IMGUI_API int ImTextStrFromUtf8(ImWchar* out_buf, int out_buf_size, const char* in_text, const char* in_text_end, const char** in_remaining = NULL); // return input UTF-8 bytes count IMGUI_API int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end); // return number of UTF-8 code-points (NOT bytes count) IMGUI_API int ImTextCountUtf8BytesFromChar(const char* in_text, const char* in_text_end); // return number of bytes to express one char in UTF-8 IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end); // return number of bytes to express string in UTF-8 IMGUI_API const char* ImTextFindPreviousUtf8Codepoint(const char* in_text_start, const char* in_text_curr); // return previous UTF-8 code-point. // Helpers: File System #ifdef IMGUI_DISABLE_FILE_FUNCTIONS #define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS typedef void* ImFileHandle; static inline ImFileHandle ImFileOpen(const char*, const char*) { return NULL; } static inline bool ImFileClose(ImFileHandle) { return false; } static inline ImU64 ImFileGetSize(ImFileHandle) { return (ImU64)-1; } static inline ImU64 ImFileRead(void*, ImU64, ImU64, ImFileHandle) { return 0; } static inline ImU64 ImFileWrite(const void*, ImU64, ImU64, ImFileHandle) { return 0; } #endif #ifndef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS typedef FILE* ImFileHandle; IMGUI_API ImFileHandle ImFileOpen(const char* filename, const char* mode); IMGUI_API bool ImFileClose(ImFileHandle file); IMGUI_API ImU64 ImFileGetSize(ImFileHandle file); IMGUI_API ImU64 ImFileRead(void* data, ImU64 size, ImU64 count, ImFileHandle file); IMGUI_API ImU64 ImFileWrite(const void* data, ImU64 size, ImU64 count, ImFileHandle file); #else #define IMGUI_DISABLE_TTY_FUNCTIONS // Can't use stdout, fflush if we are not using default file functions #endif IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* mode, size_t* out_file_size = NULL, int padding_bytes = 0); // Helpers: Maths IM_MSVC_RUNTIME_CHECKS_OFF // - Wrapper for standard libs functions. (Note that imgui_demo.cpp does _not_ use them to keep the code easy to copy) #ifndef IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS #define ImFabs(X) fabsf(X) #define ImSqrt(X) sqrtf(X) #define ImFmod(X, Y) fmodf((X), (Y)) #define ImCos(X) cosf(X) #define ImSin(X) sinf(X) #define ImAcos(X) acosf(X) #define ImAtan2(Y, X) atan2f((Y), (X)) #define ImAtof(STR) atof(STR) #define ImCeil(X) ceilf(X) static inline float ImPow(float x, float y) { return powf(x, y); } // DragBehaviorT/SliderBehaviorT uses ImPow with either float/double and need the precision static inline double ImPow(double x, double y) { return pow(x, y); } static inline float ImLog(float x) { return logf(x); } // DragBehaviorT/SliderBehaviorT uses ImLog with either float/double and need the precision static inline double ImLog(double x) { return log(x); } static inline int ImAbs(int x) { return x < 0 ? -x : x; } static inline float ImAbs(float x) { return fabsf(x); } static inline double ImAbs(double x) { return fabs(x); } static inline float ImSign(float x) { return (x < 0.0f) ? -1.0f : (x > 0.0f) ? 1.0f : 0.0f; } // Sign operator - returns -1, 0 or 1 based on sign of argument static inline double ImSign(double x) { return (x < 0.0) ? -1.0 : (x > 0.0) ? 1.0 : 0.0; } #ifdef IMGUI_ENABLE_SSE static inline float ImRsqrt(float x) { return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(x))); } #else static inline float ImRsqrt(float x) { return 1.0f / sqrtf(x); } #endif static inline double ImRsqrt(double x) { return 1.0 / sqrt(x); } #endif // - ImMin/ImMax/ImClamp/ImLerp/ImSwap are used by widgets which support variety of types: signed/unsigned int/long long float/double // (Exceptionally using templates here but we could also redefine them for those types) template static inline T ImMin(T lhs, T rhs) { return lhs < rhs ? lhs : rhs; } template static inline T ImMax(T lhs, T rhs) { return lhs >= rhs ? lhs : rhs; } template static inline T ImClamp(T v, T mn, T mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } template static inline T ImLerp(T a, T b, float t) { return (T)(a + (b - a) * t); } template static inline void ImSwap(T& a, T& b) { T tmp = a; a = b; b = tmp; } template static inline T ImAddClampOverflow(T a, T b, T mn, T mx) { if (b < 0 && (a < mn - b)) return mn; if (b > 0 && (a > mx - b)) return mx; return a + b; } template static inline T ImSubClampOverflow(T a, T b, T mn, T mx) { if (b > 0 && (a < mn + b)) return mn; if (b < 0 && (a > mx + b)) return mx; return a - b; } // - Misc maths helpers static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x < rhs.x ? lhs.x : rhs.x, lhs.y < rhs.y ? lhs.y : rhs.y); } static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x >= rhs.x ? lhs.x : rhs.x, lhs.y >= rhs.y ? lhs.y : rhs.y); } static inline ImVec2 ImClamp(const ImVec2& v, const ImVec2& mn, ImVec2 mx) { return ImVec2((v.x < mn.x) ? mn.x : (v.x > mx.x) ? mx.x : v.x, (v.y < mn.y) ? mn.y : (v.y > mx.y) ? mx.y : v.y); } static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, float t) { return ImVec2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t); } static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVec2& t) { return ImVec2(a.x + (b.x - a.x) * t.x, a.y + (b.y - a.y) * t.y); } static inline ImVec4 ImLerp(const ImVec4& a, const ImVec4& b, float t) { return ImVec4(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t, a.w + (b.w - a.w) * t); } static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; } static inline float ImLengthSqr(const ImVec2& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y); } static inline float ImLengthSqr(const ImVec4& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y) + (lhs.z * lhs.z) + (lhs.w * lhs.w); } static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = (lhs.x * lhs.x) + (lhs.y * lhs.y); if (d > 0.0f) return ImRsqrt(d); return fail_value; } static inline float ImTrunc(float f) { return (float)(int)(f); } static inline ImVec2 ImTrunc(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); } static inline float ImFloor(float f) { return (float)((f >= 0 || (float)(int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf() static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2(ImFloor(v.x), ImFloor(v.y)); } static inline int ImModPositive(int a, int b) { return (a + b) % b; } static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; } static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); } static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; } static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); } static inline bool ImIsFloatAboveGuaranteedIntegerPrecision(float f) { return f <= -16777216 || f >= 16777216; } static inline float ImExponentialMovingAverage(float avg, float sample, int n) { avg -= avg / n; avg += sample / n; return avg; } IM_MSVC_RUNTIME_CHECKS_RESTORE // Helpers: Geometry IMGUI_API ImVec2 ImBezierCubicCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, float t); IMGUI_API ImVec2 ImBezierCubicClosestPoint(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, int num_segments); // For curves with explicit number of segments IMGUI_API ImVec2 ImBezierCubicClosestPointCasteljau(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, const ImVec2& p, float tess_tol);// For auto-tessellated curves you can use tess_tol = style.CurveTessellationTol IMGUI_API ImVec2 ImBezierQuadraticCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, float t); IMGUI_API ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p); IMGUI_API bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p); IMGUI_API ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p); IMGUI_API void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w); inline float ImTriangleArea(const ImVec2& a, const ImVec2& b, const ImVec2& c) { return ImFabs((a.x * (b.y - c.y)) + (b.x * (c.y - a.y)) + (c.x * (a.y - b.y))) * 0.5f; } // Helper: ImVec1 (1D vector) // (this odd construct is used to facilitate the transition between 1D and 2D, and the maintenance of some branches/patches) IM_MSVC_RUNTIME_CHECKS_OFF struct ImVec1 { float x; constexpr ImVec1() : x(0.0f) { } constexpr ImVec1(float _x) : x(_x) { } }; // Helper: ImVec2ih (2D vector, half-size integer, for long-term packed storage) struct ImVec2ih { short x, y; constexpr ImVec2ih() : x(0), y(0) {} constexpr ImVec2ih(short _x, short _y) : x(_x), y(_y) {} constexpr explicit ImVec2ih(const ImVec2& rhs) : x((short)rhs.x), y((short)rhs.y) {} }; // Helper: ImRect (2D axis aligned bounding-box) // NB: we can't rely on ImVec2 math operators being available here! struct IMGUI_API ImRect { ImVec2 Min; // Upper-left ImVec2 Max; // Lower-right constexpr ImRect() : Min(0.0f, 0.0f), Max(0.0f, 0.0f) {} constexpr ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {} constexpr ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {} constexpr ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {} ImVec2 GetCenter() const { return ImVec2((Min.x + Max.x) * 0.5f, (Min.y + Max.y) * 0.5f); } ImVec2 GetSize() const { return ImVec2(Max.x - Min.x, Max.y - Min.y); } float GetWidth() const { return Max.x - Min.x; } float GetHeight() const { return Max.y - Min.y; } float GetArea() const { return (Max.x - Min.x) * (Max.y - Min.y); } ImVec2 GetTL() const { return Min; } // Top-left ImVec2 GetTR() const { return ImVec2(Max.x, Min.y); } // Top-right ImVec2 GetBL() const { return ImVec2(Min.x, Max.y); } // Bottom-left ImVec2 GetBR() const { return Max; } // Bottom-right bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; } bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x <= Max.x && r.Max.y <= Max.y; } bool ContainsWithPad(const ImVec2& p, const ImVec2& pad) const { return p.x >= Min.x - pad.x && p.y >= Min.y - pad.y && p.x < Max.x + pad.x && p.y < Max.y + pad.y; } bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; } void Add(const ImVec2& p) { if (Min.x > p.x) Min.x = p.x; if (Min.y > p.y) Min.y = p.y; if (Max.x < p.x) Max.x = p.x; if (Max.y < p.y) Max.y = p.y; } void Add(const ImRect& r) { if (Min.x > r.Min.x) Min.x = r.Min.x; if (Min.y > r.Min.y) Min.y = r.Min.y; if (Max.x < r.Max.x) Max.x = r.Max.x; if (Max.y < r.Max.y) Max.y = r.Max.y; } void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; } void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; } void Translate(const ImVec2& d) { Min.x += d.x; Min.y += d.y; Max.x += d.x; Max.y += d.y; } void TranslateX(float dx) { Min.x += dx; Max.x += dx; } void TranslateY(float dy) { Min.y += dy; Max.y += dy; } void ClipWith(const ImRect& r) { Min = ImMax(Min, r.Min); Max = ImMin(Max, r.Max); } // Simple version, may lead to an inverted rectangle, which is fine for Contains/Overlaps test but not for display. void ClipWithFull(const ImRect& r) { Min = ImClamp(Min, r.Min, r.Max); Max = ImClamp(Max, r.Min, r.Max); } // Full version, ensure both points are fully clipped. void Floor() { Min.x = IM_TRUNC(Min.x); Min.y = IM_TRUNC(Min.y); Max.x = IM_TRUNC(Max.x); Max.y = IM_TRUNC(Max.y); } bool IsInverted() const { return Min.x > Max.x || Min.y > Max.y; } ImVec4 ToVec4() const { return ImVec4(Min.x, Min.y, Max.x, Max.y); } }; // Helper: ImBitArray #define IM_BITARRAY_TESTBIT(_ARRAY, _N) ((_ARRAY[(_N) >> 5] & ((ImU32)1 << ((_N) & 31))) != 0) // Macro version of ImBitArrayTestBit(): ensure args have side-effect or are costly! #define IM_BITARRAY_CLEARBIT(_ARRAY, _N) ((_ARRAY[(_N) >> 5] &= ~((ImU32)1 << ((_N) & 31)))) // Macro version of ImBitArrayClearBit(): ensure args have side-effect or are costly! inline size_t ImBitArrayGetStorageSizeInBytes(int bitcount) { return (size_t)((bitcount + 31) >> 5) << 2; } inline void ImBitArrayClearAllBits(ImU32* arr, int bitcount){ memset(arr, 0, ImBitArrayGetStorageSizeInBytes(bitcount)); } inline bool ImBitArrayTestBit(const ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); return (arr[n >> 5] & mask) != 0; } inline void ImBitArrayClearBit(ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); arr[n >> 5] &= ~mask; } inline void ImBitArraySetBit(ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); arr[n >> 5] |= mask; } inline void ImBitArraySetBitRange(ImU32* arr, int n, int n2) // Works on range [n..n2) { n2--; while (n <= n2) { int a_mod = (n & 31); int b_mod = (n2 > (n | 31) ? 31 : (n2 & 31)) + 1; ImU32 mask = (ImU32)(((ImU64)1 << b_mod) - 1) & ~(ImU32)(((ImU64)1 << a_mod) - 1); arr[n >> 5] |= mask; n = (n + 32) & ~31; } } typedef ImU32* ImBitArrayPtr; // Name for use in structs // Helper: ImBitArray class (wrapper over ImBitArray functions) // Store 1-bit per value. template struct ImBitArray { ImU32 Storage[(BITCOUNT + 31) >> 5]; ImBitArray() { ClearAllBits(); } void ClearAllBits() { memset(Storage, 0, sizeof(Storage)); } void SetAllBits() { memset(Storage, 255, sizeof(Storage)); } bool TestBit(int n) const { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return IM_BITARRAY_TESTBIT(Storage, n); } void SetBit(int n) { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArraySetBit(Storage, n); } void ClearBit(int n) { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); ImBitArrayClearBit(Storage, n); } void SetBitRange(int n, int n2) { n += OFFSET; n2 += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT && n2 > n && n2 <= BITCOUNT); ImBitArraySetBitRange(Storage, n, n2); } // Works on range [n..n2) bool operator[](int n) const { n += OFFSET; IM_ASSERT(n >= 0 && n < BITCOUNT); return IM_BITARRAY_TESTBIT(Storage, n); } }; // Helper: ImBitVector // Store 1-bit per value. struct IMGUI_API ImBitVector { ImVector Storage; void Create(int sz) { Storage.resize((sz + 31) >> 5); memset(Storage.Data, 0, (size_t)Storage.Size * sizeof(Storage.Data[0])); } void Clear() { Storage.clear(); } bool TestBit(int n) const { IM_ASSERT(n < (Storage.Size << 5)); return IM_BITARRAY_TESTBIT(Storage.Data, n); } void SetBit(int n) { IM_ASSERT(n < (Storage.Size << 5)); ImBitArraySetBit(Storage.Data, n); } void ClearBit(int n) { IM_ASSERT(n < (Storage.Size << 5)); ImBitArrayClearBit(Storage.Data, n); } }; IM_MSVC_RUNTIME_CHECKS_RESTORE // Helper: ImSpan<> // Pointing to a span of data we don't own. template struct ImSpan { T* Data; T* DataEnd; // Constructors, destructor inline ImSpan() { Data = DataEnd = NULL; } inline ImSpan(T* data, int size) { Data = data; DataEnd = data + size; } inline ImSpan(T* data, T* data_end) { Data = data; DataEnd = data_end; } inline void set(T* data, int size) { Data = data; DataEnd = data + size; } inline void set(T* data, T* data_end) { Data = data; DataEnd = data_end; } inline int size() const { return (int)(ptrdiff_t)(DataEnd - Data); } inline int size_in_bytes() const { return (int)(ptrdiff_t)(DataEnd - Data) * (int)sizeof(T); } inline T& operator[](int i) { T* p = Data + i; IM_ASSERT(p >= Data && p < DataEnd); return *p; } inline const T& operator[](int i) const { const T* p = Data + i; IM_ASSERT(p >= Data && p < DataEnd); return *p; } inline T* begin() { return Data; } inline const T* begin() const { return Data; } inline T* end() { return DataEnd; } inline const T* end() const { return DataEnd; } // Utilities inline int index_from_ptr(const T* it) const { IM_ASSERT(it >= Data && it < DataEnd); const ptrdiff_t off = it - Data; return (int)off; } }; // Helper: ImSpanAllocator<> // Facilitate storing multiple chunks into a single large block (the "arena") // - Usage: call Reserve() N times, allocate GetArenaSizeInBytes() worth, pass it to SetArenaBasePtr(), call GetSpan() N times to retrieve the aligned ranges. template struct ImSpanAllocator { char* BasePtr; int CurrOff; int CurrIdx; int Offsets[CHUNKS]; int Sizes[CHUNKS]; ImSpanAllocator() { memset(this, 0, sizeof(*this)); } inline void Reserve(int n, size_t sz, int a=4) { IM_ASSERT(n == CurrIdx && n < CHUNKS); CurrOff = IM_MEMALIGN(CurrOff, a); Offsets[n] = CurrOff; Sizes[n] = (int)sz; CurrIdx++; CurrOff += (int)sz; } inline int GetArenaSizeInBytes() { return CurrOff; } inline void SetArenaBasePtr(void* base_ptr) { BasePtr = (char*)base_ptr; } inline void* GetSpanPtrBegin(int n) { IM_ASSERT(n >= 0 && n < CHUNKS && CurrIdx == CHUNKS); return (void*)(BasePtr + Offsets[n]); } inline void* GetSpanPtrEnd(int n) { IM_ASSERT(n >= 0 && n < CHUNKS && CurrIdx == CHUNKS); return (void*)(BasePtr + Offsets[n] + Sizes[n]); } template inline void GetSpan(int n, ImSpan* span) { span->set((T*)GetSpanPtrBegin(n), (T*)GetSpanPtrEnd(n)); } }; // Helper: ImPool<> // Basic keyed storage for contiguous instances, slow/amortized insertion, O(1) indexable, O(Log N) queries by ID over a dense/hot buffer, // Honor constructor/destructor. Add/remove invalidate all pointers. Indexes have the same lifetime as the associated object. typedef int ImPoolIdx; template struct ImPool { ImVector Buf; // Contiguous data ImGuiStorage Map; // ID->Index ImPoolIdx FreeIdx; // Next free idx to use ImPoolIdx AliveCount; // Number of active/alive items (for display purpose) ImPool() { FreeIdx = AliveCount = 0; } ~ImPool() { Clear(); } T* GetByKey(ImGuiID key) { int idx = Map.GetInt(key, -1); return (idx != -1) ? &Buf[idx] : NULL; } T* GetByIndex(ImPoolIdx n) { return &Buf[n]; } ImPoolIdx GetIndex(const T* p) const { IM_ASSERT(p >= Buf.Data && p < Buf.Data + Buf.Size); return (ImPoolIdx)(p - Buf.Data); } T* GetOrAddByKey(ImGuiID key) { int* p_idx = Map.GetIntRef(key, -1); if (*p_idx != -1) return &Buf[*p_idx]; *p_idx = FreeIdx; return Add(); } bool Contains(const T* p) const { return (p >= Buf.Data && p < Buf.Data + Buf.Size); } void Clear() { for (int n = 0; n < Map.Data.Size; n++) { int idx = Map.Data[n].val_i; if (idx != -1) Buf[idx].~T(); } Map.Clear(); Buf.clear(); FreeIdx = AliveCount = 0; } T* Add() { int idx = FreeIdx; if (idx == Buf.Size) { Buf.resize(Buf.Size + 1); FreeIdx++; } else { FreeIdx = *(int*)&Buf[idx]; } IM_PLACEMENT_NEW(&Buf[idx]) T(); AliveCount++; return &Buf[idx]; } void Remove(ImGuiID key, const T* p) { Remove(key, GetIndex(p)); } void Remove(ImGuiID key, ImPoolIdx idx) { Buf[idx].~T(); *(int*)&Buf[idx] = FreeIdx; FreeIdx = idx; Map.SetInt(key, -1); AliveCount--; } void Reserve(int capacity) { Buf.reserve(capacity); Map.Data.reserve(capacity); } // To iterate a ImPool: for (int n = 0; n < pool.GetMapSize(); n++) if (T* t = pool.TryGetMapData(n)) { ... } // Can be avoided if you know .Remove() has never been called on the pool, or AliveCount == GetMapSize() int GetAliveCount() const { return AliveCount; } // Number of active/alive items in the pool (for display purpose) int GetBufSize() const { return Buf.Size; } int GetMapSize() const { return Map.Data.Size; } // It is the map we need iterate to find valid items, since we don't have "alive" storage anywhere T* TryGetMapData(ImPoolIdx n) { int idx = Map.Data[n].val_i; if (idx == -1) return NULL; return GetByIndex(idx); } }; // Helper: ImChunkStream<> // Build and iterate a contiguous stream of variable-sized structures. // This is used by Settings to store persistent data while reducing allocation count. // We store the chunk size first, and align the final size on 4 bytes boundaries. // The tedious/zealous amount of casting is to avoid -Wcast-align warnings. template struct ImChunkStream { ImVector Buf; void clear() { Buf.clear(); } bool empty() const { return Buf.Size == 0; } int size() const { return Buf.Size; } T* alloc_chunk(size_t sz) { size_t HDR_SZ = 4; sz = IM_MEMALIGN(HDR_SZ + sz, 4u); int off = Buf.Size; Buf.resize(off + (int)sz); ((int*)(void*)(Buf.Data + off))[0] = (int)sz; return (T*)(void*)(Buf.Data + off + (int)HDR_SZ); } T* begin() { size_t HDR_SZ = 4; if (!Buf.Data) return NULL; return (T*)(void*)(Buf.Data + HDR_SZ); } T* next_chunk(T* p) { size_t HDR_SZ = 4; IM_ASSERT(p >= begin() && p < end()); p = (T*)(void*)((char*)(void*)p + chunk_size(p)); if (p == (T*)(void*)((char*)end() + HDR_SZ)) return (T*)0; IM_ASSERT(p < end()); return p; } int chunk_size(const T* p) { return ((const int*)p)[-1]; } T* end() { return (T*)(void*)(Buf.Data + Buf.Size); } int offset_from_ptr(const T* p) { IM_ASSERT(p >= begin() && p < end()); const ptrdiff_t off = (const char*)p - Buf.Data; return (int)off; } T* ptr_from_offset(int off) { IM_ASSERT(off >= 4 && off < Buf.Size); return (T*)(void*)(Buf.Data + off); } void swap(ImChunkStream& rhs) { rhs.Buf.swap(Buf); } }; // Helper: ImGuiTextIndex<> // Maintain a line index for a text buffer. This is a strong candidate to be moved into the public API. struct ImGuiTextIndex { ImVector LineOffsets; int EndOffset = 0; // Because we don't own text buffer we need to maintain EndOffset (may bake in LineOffsets?) void clear() { LineOffsets.clear(); EndOffset = 0; } int size() { return LineOffsets.Size; } const char* get_line_begin(const char* base, int n) { return base + LineOffsets[n]; } const char* get_line_end(const char* base, int n) { return base + (n + 1 < LineOffsets.Size ? (LineOffsets[n + 1] - 1) : EndOffset); } void append(const char* base, int old_size, int new_size); }; //----------------------------------------------------------------------------- // [SECTION] ImDrawList support //----------------------------------------------------------------------------- // ImDrawList: Helper function to calculate a circle's segment count given its radius and a "maximum error" value. // Estimation of number of circle segment based on error is derived using method described in https://stackoverflow.com/a/2244088/15194693 // Number of segments (N) is calculated using equation: // N = ceil ( pi / acos(1 - error / r) ) where r > 0, error <= r // Our equation is significantly simpler that one in the post thanks for choosing segment that is // perpendicular to X axis. Follow steps in the article from this starting condition and you will // will get this result. // // Rendering circles with an odd number of segments, while mathematically correct will produce // asymmetrical results on the raster grid. Therefore we're rounding N to next even number (7->8, 8->8, 9->10 etc.) #define IM_ROUNDUP_TO_EVEN(_V) ((((_V) + 1) / 2) * 2) #define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN 4 #define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX 512 #define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(_RAD,_MAXERROR) ImClamp(IM_ROUNDUP_TO_EVEN((int)ImCeil(IM_PI / ImAcos(1 - ImMin((_MAXERROR), (_RAD)) / (_RAD)))), IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MIN, IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_MAX) // Raw equation from IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC rewritten for 'r' and 'error'. #define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(_N,_MAXERROR) ((_MAXERROR) / (1 - ImCos(IM_PI / ImMax((float)(_N), IM_PI)))) #define IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_ERROR(_N,_RAD) ((1 - ImCos(IM_PI / ImMax((float)(_N), IM_PI))) / (_RAD)) // ImDrawList: Lookup table size for adaptive arc drawing, cover full circle. #ifndef IM_DRAWLIST_ARCFAST_TABLE_SIZE #define IM_DRAWLIST_ARCFAST_TABLE_SIZE 48 // Number of samples in lookup table. #endif #define IM_DRAWLIST_ARCFAST_SAMPLE_MAX IM_DRAWLIST_ARCFAST_TABLE_SIZE // Sample index _PathArcToFastEx() for 360 angle. // Data shared between all ImDrawList instances // You may want to create your own instance of this if you want to use ImDrawList completely without ImGui. In that case, watch out for future changes to this structure. struct IMGUI_API ImDrawListSharedData { ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas ImFont* Font; // Current/default font (optional, for simplified AddText overload) float FontSize; // Current/default font size (optional, for simplified AddText overload) float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen() ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards) // [Internal] Temp write buffer ImVector TempBuffer; // [Internal] Lookup tables ImVec2 ArcFastVtx[IM_DRAWLIST_ARCFAST_TABLE_SIZE]; // Sample points on the quarter of the circle. float ArcFastRadiusCutoff; // Cutoff radius after which arc drawing will fallback to slower PathArcTo() ImU8 CircleSegmentCounts[64]; // Precomputed segment count for given radius before we calculate it dynamically (to avoid calculation overhead) const ImVec4* TexUvLines; // UV of anti-aliased lines in the atlas ImDrawListSharedData(); void SetCircleTessellationMaxError(float max_error); }; struct ImDrawDataBuilder { ImVector* Layers[2]; // Pointers to global layers for: regular, tooltip. LayersP[0] is owned by DrawData. ImVector LayerData1; ImDrawDataBuilder() { memset(this, 0, sizeof(*this)); } }; //----------------------------------------------------------------------------- // [SECTION] Widgets support: flags, enums, data structures //----------------------------------------------------------------------------- // Flags used by upcoming items // - input: PushItemFlag() manipulates g.CurrentItemFlags, ItemAdd() calls may add extra flags. // - output: stored in g.LastItemData.InFlags // Current window shared by all windows. // This is going to be exposed in imgui.h when stabilized enough. enum ImGuiItemFlags_ { // Controlled by user ImGuiItemFlags_None = 0, ImGuiItemFlags_NoTabStop = 1 << 0, // false // Disable keyboard tabbing. This is a "lighter" version of ImGuiItemFlags_NoNav. ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings. ImGuiItemFlags_Disabled = 1 << 2, // false // Disable interactions but doesn't affect visuals. See BeginDisabled()/EndDisabled(). See github.com/ocornut/imgui/issues/211 ImGuiItemFlags_NoNav = 1 << 3, // false // Disable any form of focusing (keyboard/gamepad directional navigation and SetKeyboardFocusHere() calls) ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false // Disable item being a candidate for default focus (e.g. used by title bar items) ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // Disable MenuItem/Selectable() automatically closing their popup window ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets) ImGuiItemFlags_ReadOnly = 1 << 7, // false // [ALPHA] Allow hovering interactions but underlying value is not changed. ImGuiItemFlags_NoWindowHoverableCheck = 1 << 8, // false // Disable hoverable check in ItemHoverable() ImGuiItemFlags_AllowOverlap = 1 << 9, // false // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame. // Controlled by widget code ImGuiItemFlags_Inputable = 1 << 10, // false // [WIP] Auto-activate input mode when tab focused. Currently only used and supported by a few items before it becomes a generic feature. ImGuiItemFlags_HasSelectionUserData = 1 << 11, // false // Set by SetNextItemSelectionUserData() }; // Status flags for an already submitted item // - output: stored in g.LastItemData.StatusFlags enum ImGuiItemStatusFlags_ { ImGuiItemStatusFlags_None = 0, ImGuiItemStatusFlags_HoveredRect = 1 << 0, // Mouse position is within item rectangle (does NOT mean that the window is in correct z-order and can be hovered!, this is only one part of the most-common IsItemHovered test) ImGuiItemStatusFlags_HasDisplayRect = 1 << 1, // g.LastItemData.DisplayRect is valid ImGuiItemStatusFlags_Edited = 1 << 2, // Value exposed by item was edited in the current frame (should match the bool return value of most widgets) ImGuiItemStatusFlags_ToggledSelection = 1 << 3, // Set when Selectable(), TreeNode() reports toggling a selection. We can't report "Selected", only state changes, in order to easily handle clipping with less issues. ImGuiItemStatusFlags_ToggledOpen = 1 << 4, // Set when TreeNode() reports toggling their open state. ImGuiItemStatusFlags_HasDeactivated = 1 << 5, // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag. ImGuiItemStatusFlags_Deactivated = 1 << 6, // Only valid if ImGuiItemStatusFlags_HasDeactivated is set. ImGuiItemStatusFlags_HoveredWindow = 1 << 7, // Override the HoveredWindow test to allow cross-window hover testing. ImGuiItemStatusFlags_Visible = 1 << 8, // [WIP] Set when item is overlapping the current clipping rectangle (Used internally. Please don't use yet: API/system will change as we refactor Itemadd()). ImGuiItemStatusFlags_HasClipRect = 1 << 9, // g.LastItemData.ClipRect is valid // Additional status + semantic for ImGuiTestEngine #ifdef IMGUI_ENABLE_TEST_ENGINE ImGuiItemStatusFlags_Openable = 1 << 20, // Item is an openable (e.g. TreeNode) ImGuiItemStatusFlags_Opened = 1 << 21, // Opened status ImGuiItemStatusFlags_Checkable = 1 << 22, // Item is a checkable (e.g. CheckBox, MenuItem) ImGuiItemStatusFlags_Checked = 1 << 23, // Checked status ImGuiItemStatusFlags_Inputable = 1 << 24, // Item is a text-inputable (e.g. InputText, SliderXXX, DragXXX) #endif }; // Extend ImGuiHoveredFlags_ enum ImGuiHoveredFlagsPrivate_ { ImGuiHoveredFlags_DelayMask_ = ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_NoSharedDelay, ImGuiHoveredFlags_AllowedMaskForIsWindowHovered = ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_AnyWindow | ImGuiHoveredFlags_NoPopupHierarchy | ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_Stationary, ImGuiHoveredFlags_AllowedMaskForIsItemHovered = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped | ImGuiHoveredFlags_AllowWhenDisabled | ImGuiHoveredFlags_NoNavOverride | ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayMask_, }; // Extend ImGuiInputTextFlags_ enum ImGuiInputTextFlagsPrivate_ { // [Internal] ImGuiInputTextFlags_Multiline = 1 << 26, // For internal use by InputTextMultiline() ImGuiInputTextFlags_NoMarkEdited = 1 << 27, // For internal use by functions using InputText() before reformatting data ImGuiInputTextFlags_MergedItem = 1 << 28, // For internal use by TempInputText(), will skip calling ItemAdd(). Require bounding-box to strictly match. }; // Extend ImGuiButtonFlags_ enum ImGuiButtonFlagsPrivate_ { ImGuiButtonFlags_PressedOnClick = 1 << 4, // return true on click (mouse down event) ImGuiButtonFlags_PressedOnClickRelease = 1 << 5, // [Default] return true on click + release on same item <-- this is what the majority of Button are using ImGuiButtonFlags_PressedOnClickReleaseAnywhere = 1 << 6, // return true on click + release even if the release event is not done while hovering the item ImGuiButtonFlags_PressedOnRelease = 1 << 7, // return true on release (default requires click+release) ImGuiButtonFlags_PressedOnDoubleClick = 1 << 8, // return true on double-click (default requires click+release) ImGuiButtonFlags_PressedOnDragDropHold = 1 << 9, // return true when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers) ImGuiButtonFlags_Repeat = 1 << 10, // hold to repeat ImGuiButtonFlags_FlattenChildren = 1 << 11, // allow interactions even if a child window is overlapping ImGuiButtonFlags_AllowOverlap = 1 << 12, // require previous frame HoveredId to either match id or be null before being usable. ImGuiButtonFlags_DontClosePopups = 1 << 13, // disable automatically closing parent popup on press // [UNUSED] //ImGuiButtonFlags_Disabled = 1 << 14, // disable interactions -> use BeginDisabled() or ImGuiItemFlags_Disabled ImGuiButtonFlags_AlignTextBaseLine = 1 << 15, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine ImGuiButtonFlags_NoKeyModifiers = 1 << 16, // disable mouse interaction if a key modifier is held ImGuiButtonFlags_NoHoldingActiveId = 1 << 17, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) ImGuiButtonFlags_NoNavFocus = 1 << 18, // don't override navigation focus when activated (FIXME: this is essentially used everytime an item uses ImGuiItemFlags_NoNav, but because legacy specs don't requires LastItemData to be set ButtonBehavior(), we can't poll g.LastItemData.InFlags) ImGuiButtonFlags_NoHoveredOnFocus = 1 << 19, // don't report as hovered when nav focus is on this item ImGuiButtonFlags_NoSetKeyOwner = 1 << 20, // don't set key/input owner on the initial click (note: mouse buttons are keys! often, the key in question will be ImGuiKey_MouseLeft!) ImGuiButtonFlags_NoTestKeyOwner = 1 << 21, // don't test key/input owner when polling the key (note: mouse buttons are keys! often, the key in question will be ImGuiKey_MouseLeft!) ImGuiButtonFlags_PressedOnMask_ = ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_PressedOnDragDropHold, ImGuiButtonFlags_PressedOnDefault_ = ImGuiButtonFlags_PressedOnClickRelease, }; // Extend ImGuiComboFlags_ enum ImGuiComboFlagsPrivate_ { ImGuiComboFlags_CustomPreview = 1 << 20, // enable BeginComboPreview() }; // Extend ImGuiSliderFlags_ enum ImGuiSliderFlagsPrivate_ { ImGuiSliderFlags_Vertical = 1 << 20, // Should this slider be orientated vertically? ImGuiSliderFlags_ReadOnly = 1 << 21, // Consider using g.NextItemData.ItemFlags |= ImGuiItemFlags_ReadOnly instead. }; // Extend ImGuiSelectableFlags_ enum ImGuiSelectableFlagsPrivate_ { // NB: need to be in sync with last value of ImGuiSelectableFlags_ ImGuiSelectableFlags_NoHoldingActiveID = 1 << 20, ImGuiSelectableFlags_SelectOnNav = 1 << 21, // (WIP) Auto-select when moved into. This is not exposed in public API as to handle multi-select and modifiers we will need user to explicitly control focus scope. May be replaced with a BeginSelection() API. ImGuiSelectableFlags_SelectOnClick = 1 << 22, // Override button behavior to react on Click (default is Click+Release) ImGuiSelectableFlags_SelectOnRelease = 1 << 23, // Override button behavior to react on Release (default is Click+Release) ImGuiSelectableFlags_SpanAvailWidth = 1 << 24, // Span all avail width even if we declared less for layout purpose. FIXME: We may be able to remove this (added in 6251d379, 2bcafc86 for menus) ImGuiSelectableFlags_SetNavIdOnHover = 1 << 25, // Set Nav/Focus ID on mouse hover (used by MenuItem) ImGuiSelectableFlags_NoPadWithHalfSpacing = 1 << 26, // Disable padding each side with ItemSpacing * 0.5f ImGuiSelectableFlags_NoSetKeyOwner = 1 << 27, // Don't set key/input owner on the initial click (note: mouse buttons are keys! often, the key in question will be ImGuiKey_MouseLeft!) }; // Extend ImGuiTreeNodeFlags_ enum ImGuiTreeNodeFlagsPrivate_ { ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 20, ImGuiTreeNodeFlags_UpsideDownArrow = 1 << 21,// (FIXME-WIP) Turn Down arrow into an Up arrow, but reversed trees (#6517) }; enum ImGuiSeparatorFlags_ { ImGuiSeparatorFlags_None = 0, ImGuiSeparatorFlags_Horizontal = 1 << 0, // Axis default to current layout type, so generally Horizontal unless e.g. in a menu bar ImGuiSeparatorFlags_Vertical = 1 << 1, ImGuiSeparatorFlags_SpanAllColumns = 1 << 2, // Make separator cover all columns of a legacy Columns() set. }; // Flags for FocusWindow(). This is not called ImGuiFocusFlags to avoid confusion with public-facing ImGuiFocusedFlags. // FIXME: Once we finishing replacing more uses of GetTopMostPopupModal()+IsWindowWithinBeginStackOf() // and FindBlockingModal() with this, we may want to change the flag to be opt-out instead of opt-in. enum ImGuiFocusRequestFlags_ { ImGuiFocusRequestFlags_None = 0, ImGuiFocusRequestFlags_RestoreFocusedChild = 1 << 0, // Find last focused child (if any) and focus it instead. ImGuiFocusRequestFlags_UnlessBelowModal = 1 << 1, // Do not set focus if the window is below a modal. }; enum ImGuiTextFlags_ { ImGuiTextFlags_None = 0, ImGuiTextFlags_NoWidthForLargeClippedText = 1 << 0, }; enum ImGuiTooltipFlags_ { ImGuiTooltipFlags_None = 0, ImGuiTooltipFlags_OverridePrevious = 1 << 1, // Clear/ignore previously submitted tooltip (defaults to append) }; // FIXME: this is in development, not exposed/functional as a generic feature yet. // Horizontal/Vertical enums are fixed to 0/1 so they may be used to index ImVec2 enum ImGuiLayoutType_ { ImGuiLayoutType_Horizontal = 0, ImGuiLayoutType_Vertical = 1 }; enum ImGuiLogType { ImGuiLogType_None = 0, ImGuiLogType_TTY, ImGuiLogType_File, ImGuiLogType_Buffer, ImGuiLogType_Clipboard, }; // X/Y enums are fixed to 0/1 so they may be used to index ImVec2 enum ImGuiAxis { ImGuiAxis_None = -1, ImGuiAxis_X = 0, ImGuiAxis_Y = 1 }; enum ImGuiPlotType { ImGuiPlotType_Lines, ImGuiPlotType_Histogram, }; // Stacked color modifier, backup of modified data so we can restore it struct ImGuiColorMod { ImGuiCol Col; ImVec4 BackupValue; }; // Stacked style modifier, backup of modified data so we can restore it. Data type inferred from the variable. struct ImGuiStyleMod { ImGuiStyleVar VarIdx; union { int BackupInt[2]; float BackupFloat[2]; }; ImGuiStyleMod(ImGuiStyleVar idx, int v) { VarIdx = idx; BackupInt[0] = v; } ImGuiStyleMod(ImGuiStyleVar idx, float v) { VarIdx = idx; BackupFloat[0] = v; } ImGuiStyleMod(ImGuiStyleVar idx, ImVec2 v) { VarIdx = idx; BackupFloat[0] = v.x; BackupFloat[1] = v.y; } }; // Storage data for BeginComboPreview()/EndComboPreview() struct IMGUI_API ImGuiComboPreviewData { ImRect PreviewRect; ImVec2 BackupCursorPos; ImVec2 BackupCursorMaxPos; ImVec2 BackupCursorPosPrevLine; float BackupPrevLineTextBaseOffset; ImGuiLayoutType BackupLayout; ImGuiComboPreviewData() { memset(this, 0, sizeof(*this)); } }; // Stacked storage data for BeginGroup()/EndGroup() struct IMGUI_API ImGuiGroupData { ImGuiID WindowID; ImVec2 BackupCursorPos; ImVec2 BackupCursorMaxPos; ImVec2 BackupCursorPosPrevLine; ImVec1 BackupIndent; ImVec1 BackupGroupOffset; ImVec2 BackupCurrLineSize; float BackupCurrLineTextBaseOffset; ImGuiID BackupActiveIdIsAlive; bool BackupActiveIdPreviousFrameIsAlive; bool BackupHoveredIdIsAlive; bool BackupIsSameLine; bool EmitItem; }; // Simple column measurement, currently used for MenuItem() only.. This is very short-sighted/throw-away code and NOT a generic helper. struct IMGUI_API ImGuiMenuColumns { ImU32 TotalWidth; ImU32 NextTotalWidth; ImU16 Spacing; ImU16 OffsetIcon; // Always zero for now ImU16 OffsetLabel; // Offsets are locked in Update() ImU16 OffsetShortcut; ImU16 OffsetMark; ImU16 Widths[4]; // Width of: Icon, Label, Shortcut, Mark (accumulators for current frame) ImGuiMenuColumns() { memset(this, 0, sizeof(*this)); } void Update(float spacing, bool window_reappearing); float DeclColumns(float w_icon, float w_label, float w_shortcut, float w_mark); void CalcNextTotalWidth(bool update_offsets); }; // Internal temporary state for deactivating InputText() instances. struct IMGUI_API ImGuiInputTextDeactivatedState { ImGuiID ID; // widget id owning the text state (which just got deactivated) ImVector TextA; // text buffer ImGuiInputTextDeactivatedState() { memset(this, 0, sizeof(*this)); } void ClearFreeMemory() { ID = 0; TextA.clear(); } }; // Internal state of the currently focused/edited text input box // For a given item ID, access with ImGui::GetInputTextState() struct IMGUI_API ImGuiInputTextState { ImGuiContext* Ctx; // parent UI context (needs to be set explicitly by parent). ImGuiID ID; // widget id owning the text state int CurLenW, CurLenA; // we need to maintain our buffer length in both UTF-8 and wchar format. UTF-8 length is valid even if TextA is not. ImVector TextW; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer. ImVector TextA; // temporary UTF8 buffer for callbacks and other operations. this is not updated in every code-path! size=capacity. ImVector InitialTextA; // value to revert to when pressing Escape = backup of end-user buffer at the time of focus (in UTF-8, unaltered) bool TextAIsValid; // temporary UTF8 buffer is not initially valid before we make the widget active (until then we pull the data from user argument) int BufCapacityA; // end-user buffer capacity float ScrollX; // horizontal scrolling/offset ImStb::STB_TexteditState Stb; // state for stb_textedit.h float CursorAnim; // timer for cursor blink, reset on every user action so the cursor reappears immediately bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!) bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection bool Edited; // edited this frame ImGuiInputTextFlags Flags; // copy of InputText() flags. may be used to check if e.g. ImGuiInputTextFlags_Password is set. bool ReloadUserBuf; // force a reload of user buf so it may be modified externally. may be automatic in future version. int ReloadSelectionStart; // POSITIONS ARE IN IMWCHAR units *NOT* UTF-8 this is why this is not exposed yet. int ReloadSelectionEnd; ImGuiInputTextState() { memset(this, 0, sizeof(*this)); } void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); } void ClearFreeMemory() { TextW.clear(); TextA.clear(); InitialTextA.clear(); } int GetUndoAvailCount() const { return Stb.undostate.undo_point; } int GetRedoAvailCount() const { return IMSTB_TEXTEDIT_UNDOSTATECOUNT - Stb.undostate.redo_point; } void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation // Cursor & Selection void CursorAnimReset() { CursorAnim = -0.30f; } // After a user-input the cursor stays on for a while without blinking void CursorClamp() { Stb.cursor = ImMin(Stb.cursor, CurLenW); Stb.select_start = ImMin(Stb.select_start, CurLenW); Stb.select_end = ImMin(Stb.select_end, CurLenW); } bool HasSelection() const { return Stb.select_start != Stb.select_end; } void ClearSelection() { Stb.select_start = Stb.select_end = Stb.cursor; } int GetCursorPos() const { return Stb.cursor; } int GetSelectionStart() const { return Stb.select_start; } int GetSelectionEnd() const { return Stb.select_end; } void SelectAll() { Stb.select_start = 0; Stb.cursor = Stb.select_end = CurLenW; Stb.has_preferred_x = 0; } // Reload user buf (WIP #2890) // If you modify underlying user-passed const char* while active you need to call this (InputText V2 may lift this) // strcpy(my_buf, "hello"); // if (ImGuiInputTextState* state = ImGui::GetInputTextState(id)) // id may be ImGui::GetItemID() is last item // state->ReloadUserBufAndSelectAll(); void ReloadUserBufAndSelectAll() { ReloadUserBuf = true; ReloadSelectionStart = 0; ReloadSelectionEnd = INT_MAX; } void ReloadUserBufAndKeepSelection() { ReloadUserBuf = true; ReloadSelectionStart = Stb.select_start; ReloadSelectionEnd = Stb.select_end; } void ReloadUserBufAndMoveToEnd() { ReloadUserBuf = true; ReloadSelectionStart = ReloadSelectionEnd = INT_MAX; } }; enum ImGuiNextWindowDataFlags_ { ImGuiNextWindowDataFlags_None = 0, ImGuiNextWindowDataFlags_HasPos = 1 << 0, ImGuiNextWindowDataFlags_HasSize = 1 << 1, ImGuiNextWindowDataFlags_HasContentSize = 1 << 2, ImGuiNextWindowDataFlags_HasCollapsed = 1 << 3, ImGuiNextWindowDataFlags_HasSizeConstraint = 1 << 4, ImGuiNextWindowDataFlags_HasFocus = 1 << 5, ImGuiNextWindowDataFlags_HasBgAlpha = 1 << 6, ImGuiNextWindowDataFlags_HasScroll = 1 << 7, ImGuiNextWindowDataFlags_HasChildFlags = 1 << 8, }; // Storage for SetNexWindow** functions struct ImGuiNextWindowData { ImGuiNextWindowDataFlags Flags; ImGuiCond PosCond; ImGuiCond SizeCond; ImGuiCond CollapsedCond; ImVec2 PosVal; ImVec2 PosPivotVal; ImVec2 SizeVal; ImVec2 ContentSizeVal; ImVec2 ScrollVal; ImGuiChildFlags ChildFlags; bool CollapsedVal; ImRect SizeConstraintRect; ImGuiSizeCallback SizeCallback; void* SizeCallbackUserData; float BgAlphaVal; // Override background alpha ImVec2 MenuBarOffsetMinVal; // (Always on) This is not exposed publicly, so we don't clear it and it doesn't have a corresponding flag (could we? for consistency?) ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); } inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; } }; // Multi-Selection item index or identifier when using SetNextItemSelectionUserData()/BeginMultiSelect() // (Most users are likely to use this store an item INDEX but this may be used to store a POINTER as well.) typedef ImS64 ImGuiSelectionUserData; enum ImGuiNextItemDataFlags_ { ImGuiNextItemDataFlags_None = 0, ImGuiNextItemDataFlags_HasWidth = 1 << 0, ImGuiNextItemDataFlags_HasOpen = 1 << 1, ImGuiNextItemDataFlags_HasShortcut = 1 << 2, }; struct ImGuiNextItemData { ImGuiNextItemDataFlags Flags; ImGuiItemFlags ItemFlags; // Currently only tested/used for ImGuiItemFlags_AllowOverlap. // Non-flags members are NOT cleared by ItemAdd() meaning they are still valid during NavProcessItem() ImGuiSelectionUserData SelectionUserData; // Set by SetNextItemSelectionUserData() (note that NULL/0 is a valid value, we use -1 == ImGuiSelectionUserData_Invalid to mark invalid values) float Width; // Set by SetNextItemWidth() ImGuiKeyChord Shortcut; // Set by SetNextItemShortcut() bool OpenVal; // Set by SetNextItemOpen() ImGuiCond OpenCond : 8; ImGuiNextItemData() { memset(this, 0, sizeof(*this)); SelectionUserData = -1; } inline void ClearFlags() { Flags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()! }; // Status storage for the last submitted item struct ImGuiLastItemData { ImGuiID ID; ImGuiItemFlags InFlags; // See ImGuiItemFlags_ ImGuiItemStatusFlags StatusFlags; // See ImGuiItemStatusFlags_ ImRect Rect; // Full rectangle ImRect NavRect; // Navigation scoring rectangle (not displayed) // Rarely used fields are not explicitly cleared, only valid when the corresponding ImGuiItemStatusFlags is set. ImRect DisplayRect; // Display rectangle (ONLY VALID IF ImGuiItemStatusFlags_HasDisplayRect is set) ImRect ClipRect; // Clip rectangle at the time of submitting item (ONLY VALID IF ImGuiItemStatusFlags_HasClipRect is set) ImGuiLastItemData() { memset(this, 0, sizeof(*this)); } }; // Store data emitted by TreeNode() for usage by TreePop() to implement ImGuiTreeNodeFlags_NavLeftJumpsBackHere. // This is the minimum amount of data that we need to perform the equivalent of NavApplyItemToResult() and which we can't infer in TreePop() // Only stored when the node is a potential candidate for landing on a Left arrow jump. struct ImGuiNavTreeNodeData { ImGuiID ID; ImGuiItemFlags InFlags; ImRect NavRect; }; struct IMGUI_API ImGuiStackSizes { short SizeOfIDStack; short SizeOfColorStack; short SizeOfStyleVarStack; short SizeOfFontStack; short SizeOfFocusScopeStack; short SizeOfGroupStack; short SizeOfItemFlagsStack; short SizeOfBeginPopupStack; short SizeOfDisabledStack; ImGuiStackSizes() { memset(this, 0, sizeof(*this)); } void SetToContextState(ImGuiContext* ctx); void CompareWithContextState(ImGuiContext* ctx); }; // Data saved for each window pushed into the stack struct ImGuiWindowStackData { ImGuiWindow* Window; ImGuiLastItemData ParentLastItemDataBackup; ImGuiStackSizes StackSizesOnBegin; // Store size of various stacks for asserting }; struct ImGuiShrinkWidthItem { int Index; float Width; float InitialWidth; }; struct ImGuiPtrOrIndex { void* Ptr; // Either field can be set, not both. e.g. Dock node tab bars are loose while BeginTabBar() ones are in a pool. int Index; // Usually index in a main pool. ImGuiPtrOrIndex(void* ptr) { Ptr = ptr; Index = -1; } ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; } }; //----------------------------------------------------------------------------- // [SECTION] Data types support //----------------------------------------------------------------------------- struct ImGuiDataVarInfo { ImGuiDataType Type; ImU32 Count; // 1+ ImU32 Offset; // Offset in parent structure void* GetVarPtr(void* parent) const { return (void*)((unsigned char*)parent + Offset); } }; struct ImGuiDataTypeTempStorage { ImU8 Data[8]; // Can fit any data up to ImGuiDataType_COUNT }; // Type information associated to one ImGuiDataType. Retrieve with DataTypeGetInfo(). struct ImGuiDataTypeInfo { size_t Size; // Size in bytes const char* Name; // Short descriptive name for the type, for debugging const char* PrintFmt; // Default printf format for the type const char* ScanFmt; // Default scanf format for the type }; // Extend ImGuiDataType_ enum ImGuiDataTypePrivate_ { ImGuiDataType_String = ImGuiDataType_COUNT + 1, ImGuiDataType_Pointer, ImGuiDataType_ID, }; //----------------------------------------------------------------------------- // [SECTION] Popup support //----------------------------------------------------------------------------- enum ImGuiPopupPositionPolicy { ImGuiPopupPositionPolicy_Default, ImGuiPopupPositionPolicy_ComboBox, ImGuiPopupPositionPolicy_Tooltip, }; // Storage for popup stacks (g.OpenPopupStack and g.BeginPopupStack) struct ImGuiPopupData { ImGuiID PopupId; // Set on OpenPopup() ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() ImGuiWindow* BackupNavWindow;// Set on OpenPopup(), a NavWindow that will be restored on popup close int ParentNavLayer; // Resolved on BeginPopup(). Actually a ImGuiNavLayer type (declared down below), initialized to -1 which is not part of an enum, but serves well-enough as "not any of layers" value int OpenFrameCount; // Set on OpenPopup() ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) ImVec2 OpenPopupPos; // Set on OpenPopup(), preferred popup position (typically == OpenMousePos when using mouse) ImVec2 OpenMousePos; // Set on OpenPopup(), copy of mouse position at the time of opening popup ImGuiPopupData() { memset(this, 0, sizeof(*this)); ParentNavLayer = OpenFrameCount = -1; } }; //----------------------------------------------------------------------------- // [SECTION] Inputs support //----------------------------------------------------------------------------- // Bit array for named keys typedef ImBitArray ImBitArrayForNamedKeys; // [Internal] Key ranges #define ImGuiKey_LegacyNativeKey_BEGIN 0 #define ImGuiKey_LegacyNativeKey_END 512 #define ImGuiKey_Keyboard_BEGIN (ImGuiKey_NamedKey_BEGIN) #define ImGuiKey_Keyboard_END (ImGuiKey_GamepadStart) #define ImGuiKey_Gamepad_BEGIN (ImGuiKey_GamepadStart) #define ImGuiKey_Gamepad_END (ImGuiKey_GamepadRStickDown + 1) #define ImGuiKey_Mouse_BEGIN (ImGuiKey_MouseLeft) #define ImGuiKey_Mouse_END (ImGuiKey_MouseWheelY + 1) #define ImGuiKey_Aliases_BEGIN (ImGuiKey_Mouse_BEGIN) #define ImGuiKey_Aliases_END (ImGuiKey_Mouse_END) // [Internal] Named shortcuts for Navigation #define ImGuiKey_NavKeyboardTweakSlow ImGuiMod_Ctrl #define ImGuiKey_NavKeyboardTweakFast ImGuiMod_Shift #define ImGuiKey_NavGamepadTweakSlow ImGuiKey_GamepadL1 #define ImGuiKey_NavGamepadTweakFast ImGuiKey_GamepadR1 #define ImGuiKey_NavGamepadActivate ImGuiKey_GamepadFaceDown #define ImGuiKey_NavGamepadCancel ImGuiKey_GamepadFaceRight #define ImGuiKey_NavGamepadMenu ImGuiKey_GamepadFaceLeft #define ImGuiKey_NavGamepadInput ImGuiKey_GamepadFaceUp enum ImGuiInputEventType { ImGuiInputEventType_None = 0, ImGuiInputEventType_MousePos, ImGuiInputEventType_MouseWheel, ImGuiInputEventType_MouseButton, ImGuiInputEventType_Key, ImGuiInputEventType_Text, ImGuiInputEventType_Focus, ImGuiInputEventType_COUNT }; enum ImGuiInputSource { ImGuiInputSource_None = 0, ImGuiInputSource_Mouse, // Note: may be Mouse or TouchScreen or Pen. See io.MouseSource to distinguish them. ImGuiInputSource_Keyboard, ImGuiInputSource_Gamepad, ImGuiInputSource_Clipboard, // Currently only used by InputText() ImGuiInputSource_COUNT }; // FIXME: Structures in the union below need to be declared as anonymous unions appears to be an extension? // Using ImVec2() would fail on Clang 'union member 'MousePos' has a non-trivial default constructor' struct ImGuiInputEventMousePos { float PosX, PosY; ImGuiMouseSource MouseSource; }; struct ImGuiInputEventMouseWheel { float WheelX, WheelY; ImGuiMouseSource MouseSource; }; struct ImGuiInputEventMouseButton { int Button; bool Down; ImGuiMouseSource MouseSource; }; struct ImGuiInputEventKey { ImGuiKey Key; bool Down; float AnalogValue; }; struct ImGuiInputEventText { unsigned int Char; }; struct ImGuiInputEventAppFocused { bool Focused; }; struct ImGuiInputEvent { ImGuiInputEventType Type; ImGuiInputSource Source; ImU32 EventId; // Unique, sequential increasing integer to identify an event (if you need to correlate them to other data). union { ImGuiInputEventMousePos MousePos; // if Type == ImGuiInputEventType_MousePos ImGuiInputEventMouseWheel MouseWheel; // if Type == ImGuiInputEventType_MouseWheel ImGuiInputEventMouseButton MouseButton; // if Type == ImGuiInputEventType_MouseButton ImGuiInputEventKey Key; // if Type == ImGuiInputEventType_Key ImGuiInputEventText Text; // if Type == ImGuiInputEventType_Text ImGuiInputEventAppFocused AppFocused; // if Type == ImGuiInputEventType_Focus }; bool AddedByTestEngine; ImGuiInputEvent() { memset(this, 0, sizeof(*this)); } }; // Input function taking an 'ImGuiID owner_id' argument defaults to (ImGuiKeyOwner_Any == 0) aka don't test ownership, which matches legacy behavior. #define ImGuiKeyOwner_Any ((ImGuiID)0) // Accept key that have an owner, UNLESS a call to SetKeyOwner() explicitly used ImGuiInputFlags_LockThisFrame or ImGuiInputFlags_LockUntilRelease. #define ImGuiKeyOwner_None ((ImGuiID)-1) // Require key to have no owner. typedef ImS16 ImGuiKeyRoutingIndex; // Routing table entry (sizeof() == 16 bytes) struct ImGuiKeyRoutingData { ImGuiKeyRoutingIndex NextEntryIndex; ImU16 Mods; // Technically we'd only need 4-bits but for simplify we store ImGuiMod_ values which need 16-bits. ImGuiMod_Shortcut is already translated to Ctrl/Super. ImU8 RoutingCurrScore; // [DEBUG] For debug display ImU8 RoutingNextScore; // Lower is better (0: perfect score) ImGuiID RoutingCurr; ImGuiID RoutingNext; ImGuiKeyRoutingData() { NextEntryIndex = -1; Mods = 0; RoutingCurrScore = RoutingNextScore = 255; RoutingCurr = RoutingNext = ImGuiKeyOwner_None; } }; // Routing table: maintain a desired owner for each possible key-chord (key + mods), and setup owner in NewFrame() when mods are matching. // Stored in main context (1 instance) struct ImGuiKeyRoutingTable { ImGuiKeyRoutingIndex Index[ImGuiKey_NamedKey_COUNT]; // Index of first entry in Entries[] ImVector Entries; ImVector EntriesNext; // Double-buffer to avoid reallocation (could use a shared buffer) ImGuiKeyRoutingTable() { Clear(); } void Clear() { for (int n = 0; n < IM_ARRAYSIZE(Index); n++) Index[n] = -1; Entries.clear(); EntriesNext.clear(); } }; // This extends ImGuiKeyData but only for named keys (legacy keys don't support the new features) // Stored in main context (1 per named key). In the future it might be merged into ImGuiKeyData. struct ImGuiKeyOwnerData { ImGuiID OwnerCurr; ImGuiID OwnerNext; bool LockThisFrame; // Reading this key requires explicit owner id (until end of frame). Set by ImGuiInputFlags_LockThisFrame. bool LockUntilRelease; // Reading this key requires explicit owner id (until key is released). Set by ImGuiInputFlags_LockUntilRelease. When this is true LockThisFrame is always true as well. ImGuiKeyOwnerData() { OwnerCurr = OwnerNext = ImGuiKeyOwner_None; LockThisFrame = LockUntilRelease = false; } }; // Flags for extended versions of IsKeyPressed(), IsMouseClicked(), Shortcut(), SetKeyOwner(), SetItemKeyOwner() // Don't mistake with ImGuiInputTextFlags! (which is for ImGui::InputText() function) enum ImGuiInputFlags_ { // Flags for IsKeyPressed(), IsKeyChordPressed(), IsMouseClicked(), Shortcut() ImGuiInputFlags_None = 0, // Repeat mode ImGuiInputFlags_Repeat = 1 << 0, // Enable repeat. Return true on successive repeats. Default for legacy IsKeyPressed(). NOT Default for legacy IsMouseClicked(). MUST BE == 1. ImGuiInputFlags_RepeatRateDefault = 1 << 1, // Repeat rate: Regular (default) ImGuiInputFlags_RepeatRateNavMove = 1 << 2, // Repeat rate: Fast ImGuiInputFlags_RepeatRateNavTweak = 1 << 3, // Repeat rate: Faster // Repeat mode: Specify when repeating key pressed can be interrupted. // In theory ImGuiInputFlags_RepeatUntilOtherKeyPress may be a desirable default, but it would break too many behavior so everything is opt-in. ImGuiInputFlags_RepeatUntilRelease = 1 << 4, // Stop repeating when released (default for all functions except Shortcut). This only exists to allow overriding Shortcut() default behavior. ImGuiInputFlags_RepeatUntilKeyModsChange = 1 << 5, // Stop repeating when released OR if keyboard mods are changed (default for Shortcut) ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone = 1 << 6, // Stop repeating when released OR if keyboard mods are leaving the None state. Allows going from Mod+Key to Key by releasing Mod. ImGuiInputFlags_RepeatUntilOtherKeyPress = 1 << 7, // Stop repeating when released OR if any other keyboard key is pressed during the repeat // Flags for SetItemKeyOwner() ImGuiInputFlags_CondHovered = 1 << 8, // Only set if item is hovered (default to both) ImGuiInputFlags_CondActive = 1 << 9, // Only set if item is active (default to both) ImGuiInputFlags_CondDefault_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive, // Flags for SetKeyOwner(), SetItemKeyOwner() // Locking is useful to make input-owner-aware code steal keys from non-input-owner-aware code. If all code is input-owner-aware locking would never be necessary. ImGuiInputFlags_LockThisFrame = 1 << 10, // Further accesses to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared at end of frame. ImGuiInputFlags_LockUntilRelease = 1 << 11, // Further accesses to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared when the key is released or at end of each frame if key is released. // Routing policies for Shortcut() + low-level SetShortcutRouting() // - The general idea is that several callers register interest in a shortcut, and only one owner gets it. // Parent -> call Shortcut(Ctrl+S) // When Parent is focused, Parent gets the shortcut. // Child1 -> call Shortcut(Ctrl+S) // When Child1 is focused, Child1 gets the shortcut (Child1 overrides Parent shortcuts) // Child2 -> no call // When Child2 is focused, Parent gets the shortcut. // The whole system is order independent, so if Child1 does it calls before Parent results will be identical. // This is an important property as it facilitate working with foreign code or larger codebase. // - Visualize registered routes in 'Metrics->Inputs' and submitted routes in 'Debug Log->InputRouting'. // - When a policy (except for _RouteAlways *) is set, Shortcut() will register itself with SetShortcutRouting(), // allowing the system to decide where to route the input among other route-aware calls. // (* Using ImGuiInputFlags_RouteAlways is roughly equivalent to calling IsKeyChordPressed(key)). // - Shortcut() uses ImGuiInputFlags_RouteFocused by default. Meaning that a Shortcut() call will register // a route and only succeed when parent window is in the focus-stack and if no-one with a higher priority // is claiming the same shortcut. // - You can chain two unrelated windows in the focus stack using SetWindowParentWindowForFocusRoute(). // - Priorities: GlobalHigh > Focused (when owner is active item) > Global > Focused (when focused window) > GlobalLow. // - Can select only 1 policy among all available. ImGuiInputFlags_RouteFocused = 1 << 12, // (Default) Honor focus route: Accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window. ImGuiInputFlags_RouteGlobalLow = 1 << 13, // Register route globally (lowest priority: unless a focused window or active item registered the route) -> recommended Global priority IF you need a Global priority. ImGuiInputFlags_RouteGlobal = 1 << 14, // Register route globally (medium priority: unless an active item registered the route, e.g. CTRL+A registered by InputText will take priority over this). ImGuiInputFlags_RouteGlobalHigh = 1 << 15, // Register route globally (higher priority: unlikely you need to use that: will interfere with every active items, e.g. CTRL+A registered by InputText will be overriden by this) ImGuiInputFlags_RouteAlways = 1 << 16, // Do not register route, poll keys directly. // Routing polices: extra options ImGuiInputFlags_RouteUnlessBgFocused= 1 << 17, // Global routes will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications. // [Internal] Mask of which function support which flags ImGuiInputFlags_RepeatRateMask_ = ImGuiInputFlags_RepeatRateDefault | ImGuiInputFlags_RepeatRateNavMove | ImGuiInputFlags_RepeatRateNavTweak, ImGuiInputFlags_RepeatUntilMask_ = ImGuiInputFlags_RepeatUntilRelease | ImGuiInputFlags_RepeatUntilKeyModsChange | ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone | ImGuiInputFlags_RepeatUntilOtherKeyPress, ImGuiInputFlags_RepeatMask_ = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_, ImGuiInputFlags_CondMask_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive, ImGuiInputFlags_RouteMask_ = ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteGlobalLow | ImGuiInputFlags_RouteGlobalHigh, // _Always not part of this! ImGuiInputFlags_SupportedByIsKeyPressed = ImGuiInputFlags_RepeatMask_, ImGuiInputFlags_SupportedByIsMouseClicked = ImGuiInputFlags_Repeat, ImGuiInputFlags_SupportedByShortcut = ImGuiInputFlags_RepeatMask_ | ImGuiInputFlags_RouteMask_ | ImGuiInputFlags_RouteAlways | ImGuiInputFlags_RouteUnlessBgFocused, ImGuiInputFlags_SupportedBySetKeyOwner = ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease, ImGuiInputFlags_SupportedBySetItemKeyOwner = ImGuiInputFlags_SupportedBySetKeyOwner | ImGuiInputFlags_CondMask_, }; //----------------------------------------------------------------------------- // [SECTION] Clipper support //----------------------------------------------------------------------------- // Note that Max is exclusive, so perhaps should be using a Begin/End convention. struct ImGuiListClipperRange { int Min; int Max; bool PosToIndexConvert; // Begin/End are absolute position (will be converted to indices later) ImS8 PosToIndexOffsetMin; // Add to Min after converting to indices ImS8 PosToIndexOffsetMax; // Add to Min after converting to indices static ImGuiListClipperRange FromIndices(int min, int max) { ImGuiListClipperRange r = { min, max, false, 0, 0 }; return r; } static ImGuiListClipperRange FromPositions(float y1, float y2, int off_min, int off_max) { ImGuiListClipperRange r = { (int)y1, (int)y2, true, (ImS8)off_min, (ImS8)off_max }; return r; } }; // Temporary clipper data, buffers shared/reused between instances struct ImGuiListClipperData { ImGuiListClipper* ListClipper; float LossynessOffset; int StepNo; int ItemsFrozen; ImVector Ranges; ImGuiListClipperData() { memset(this, 0, sizeof(*this)); } void Reset(ImGuiListClipper* clipper) { ListClipper = clipper; StepNo = ItemsFrozen = 0; Ranges.resize(0); } }; //----------------------------------------------------------------------------- // [SECTION] Navigation support //----------------------------------------------------------------------------- enum ImGuiActivateFlags_ { ImGuiActivateFlags_None = 0, ImGuiActivateFlags_PreferInput = 1 << 0, // Favor activation that requires keyboard text input (e.g. for Slider/Drag). Default for Enter key. ImGuiActivateFlags_PreferTweak = 1 << 1, // Favor activation for tweaking with arrows or gamepad (e.g. for Slider/Drag). Default for Space key and if keyboard is not used. ImGuiActivateFlags_TryToPreserveState = 1 << 2, // Request widget to preserve state if it can (e.g. InputText will try to preserve cursor/selection) ImGuiActivateFlags_FromTabbing = 1 << 3, // Activation requested by a tabbing request ImGuiActivateFlags_FromShortcut = 1 << 4, // Activation requested by an item shortcut via SetNextItemShortcut() function. }; // Early work-in-progress API for ScrollToItem() enum ImGuiScrollFlags_ { ImGuiScrollFlags_None = 0, ImGuiScrollFlags_KeepVisibleEdgeX = 1 << 0, // If item is not visible: scroll as little as possible on X axis to bring item back into view [default for X axis] ImGuiScrollFlags_KeepVisibleEdgeY = 1 << 1, // If item is not visible: scroll as little as possible on Y axis to bring item back into view [default for Y axis for windows that are already visible] ImGuiScrollFlags_KeepVisibleCenterX = 1 << 2, // If item is not visible: scroll to make the item centered on X axis [rarely used] ImGuiScrollFlags_KeepVisibleCenterY = 1 << 3, // If item is not visible: scroll to make the item centered on Y axis ImGuiScrollFlags_AlwaysCenterX = 1 << 4, // Always center the result item on X axis [rarely used] ImGuiScrollFlags_AlwaysCenterY = 1 << 5, // Always center the result item on Y axis [default for Y axis for appearing window) ImGuiScrollFlags_NoScrollParent = 1 << 6, // Disable forwarding scrolling to parent window if required to keep item/rect visible (only scroll window the function was applied to). ImGuiScrollFlags_MaskX_ = ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleCenterX | ImGuiScrollFlags_AlwaysCenterX, ImGuiScrollFlags_MaskY_ = ImGuiScrollFlags_KeepVisibleEdgeY | ImGuiScrollFlags_KeepVisibleCenterY | ImGuiScrollFlags_AlwaysCenterY, }; enum ImGuiNavHighlightFlags_ { ImGuiNavHighlightFlags_None = 0, ImGuiNavHighlightFlags_Compact = 1 << 1, // Compact highlight, no padding ImGuiNavHighlightFlags_AlwaysDraw = 1 << 2, // Draw rectangular highlight if (g.NavId == id) _even_ when using the mouse. ImGuiNavHighlightFlags_NoRounding = 1 << 3, }; enum ImGuiNavMoveFlags_ { ImGuiNavMoveFlags_None = 0, ImGuiNavMoveFlags_LoopX = 1 << 0, // On failed request, restart from opposite side ImGuiNavMoveFlags_LoopY = 1 << 1, ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left) ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful but provided for completeness ImGuiNavMoveFlags_WrapMask_ = ImGuiNavMoveFlags_LoopX | ImGuiNavMoveFlags_LoopY | ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_WrapY, ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place) ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, // Store alternate result in NavMoveResultLocalVisible that only comprise elements that are already fully visible (used by PageUp/PageDown) ImGuiNavMoveFlags_ScrollToEdgeY = 1 << 6, // Force scrolling to min/max (used by Home/End) // FIXME-NAV: Aim to remove or reword, probably unnecessary ImGuiNavMoveFlags_Forwarded = 1 << 7, ImGuiNavMoveFlags_DebugNoResult = 1 << 8, // Dummy scoring for debug purpose, don't apply result ImGuiNavMoveFlags_FocusApi = 1 << 9, // Requests from focus API can land/focus/activate items even if they are marked with _NoTabStop (see NavProcessItemForTabbingRequest() for details) ImGuiNavMoveFlags_IsTabbing = 1 << 10, // == Focus + Activate if item is Inputable + DontChangeNavHighlight ImGuiNavMoveFlags_IsPageMove = 1 << 11, // Identify a PageDown/PageUp request. ImGuiNavMoveFlags_Activate = 1 << 12, // Activate/select target item. ImGuiNavMoveFlags_NoSelect = 1 << 13, // Don't trigger selection by not setting g.NavJustMovedTo ImGuiNavMoveFlags_NoSetNavHighlight = 1 << 14, // Do not alter the visible state of keyboard vs mouse nav highlight }; enum ImGuiNavLayer { ImGuiNavLayer_Main = 0, // Main scrolling layer ImGuiNavLayer_Menu = 1, // Menu layer (access with Alt) ImGuiNavLayer_COUNT }; struct ImGuiNavItemData { ImGuiWindow* Window; // Init,Move // Best candidate window (result->ItemWindow->RootWindowForNav == request->Window) ImGuiID ID; // Init,Move // Best candidate item ID ImGuiID FocusScopeId; // Init,Move // Best candidate focus scope ID ImRect RectRel; // Init,Move // Best candidate bounding box in window relative space ImGuiItemFlags InFlags; // ????,Move // Best candidate item flags ImGuiSelectionUserData SelectionUserData;//I+Mov // Best candidate SetNextItemSelectionData() value. float DistBox; // Move // Best candidate box distance to current NavId float DistCenter; // Move // Best candidate center distance to current NavId float DistAxial; // Move // Best candidate axial distance to current NavId ImGuiNavItemData() { Clear(); } void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; SelectionUserData = -1; DistBox = DistCenter = DistAxial = FLT_MAX; } }; struct ImGuiFocusScopeData { ImGuiID ID; ImGuiID WindowID; }; //----------------------------------------------------------------------------- // [SECTION] Typing-select support //----------------------------------------------------------------------------- // Flags for GetTypingSelectRequest() enum ImGuiTypingSelectFlags_ { ImGuiTypingSelectFlags_None = 0, ImGuiTypingSelectFlags_AllowBackspace = 1 << 0, // Backspace to delete character inputs. If using: ensure GetTypingSelectRequest() is not called more than once per frame (filter by e.g. focus state) ImGuiTypingSelectFlags_AllowSingleCharMode = 1 << 1, // Allow "single char" search mode which is activated when pressing the same character multiple times. }; // Returned by GetTypingSelectRequest(), designed to eventually be public. struct IMGUI_API ImGuiTypingSelectRequest { ImGuiTypingSelectFlags Flags; // Flags passed to GetTypingSelectRequest() int SearchBufferLen; const char* SearchBuffer; // Search buffer contents (use full string. unless SingleCharMode is set, in which case use SingleCharSize). bool SelectRequest; // Set when buffer was modified this frame, requesting a selection. bool SingleCharMode; // Notify when buffer contains same character repeated, to implement special mode. In this situation it preferred to not display any on-screen search indication. ImS8 SingleCharSize; // Length in bytes of first letter codepoint (1 for ascii, 2-4 for UTF-8). If (SearchBufferLen==RepeatCharSize) only 1 letter has been input. }; // Storage for GetTypingSelectRequest() struct IMGUI_API ImGuiTypingSelectState { ImGuiTypingSelectRequest Request; // User-facing data char SearchBuffer[64]; // Search buffer: no need to make dynamic as this search is very transient. ImGuiID FocusScope; int LastRequestFrame = 0; float LastRequestTime = 0.0f; bool SingleCharModeLock = false; // After a certain single char repeat count we lock into SingleCharMode. Two benefits: 1) buffer never fill, 2) we can provide an immediate SingleChar mode without timer elapsing. ImGuiTypingSelectState() { memset(this, 0, sizeof(*this)); } void Clear() { SearchBuffer[0] = 0; SingleCharModeLock = false; } // We preserve remaining data for easier debugging }; //----------------------------------------------------------------------------- // [SECTION] Columns support //----------------------------------------------------------------------------- // Flags for internal's BeginColumns(). This is an obsolete API. Prefer using BeginTable() nowadays! enum ImGuiOldColumnFlags_ { ImGuiOldColumnFlags_None = 0, ImGuiOldColumnFlags_NoBorder = 1 << 0, // Disable column dividers ImGuiOldColumnFlags_NoResize = 1 << 1, // Disable resizing columns when clicking on the dividers ImGuiOldColumnFlags_NoPreserveWidths = 1 << 2, // Disable column width preservation when adjusting columns ImGuiOldColumnFlags_NoForceWithinWindow = 1 << 3, // Disable forcing columns to fit within window ImGuiOldColumnFlags_GrowParentContentsSize = 1 << 4, // Restore pre-1.51 behavior of extending the parent window contents size but _without affecting the columns width at all_. Will eventually remove. // Obsolete names (will be removed) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS //ImGuiColumnsFlags_None = ImGuiOldColumnFlags_None, //ImGuiColumnsFlags_NoBorder = ImGuiOldColumnFlags_NoBorder, //ImGuiColumnsFlags_NoResize = ImGuiOldColumnFlags_NoResize, //ImGuiColumnsFlags_NoPreserveWidths = ImGuiOldColumnFlags_NoPreserveWidths, //ImGuiColumnsFlags_NoForceWithinWindow = ImGuiOldColumnFlags_NoForceWithinWindow, //ImGuiColumnsFlags_GrowParentContentsSize = ImGuiOldColumnFlags_GrowParentContentsSize, #endif }; struct ImGuiOldColumnData { float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) float OffsetNormBeforeResize; ImGuiOldColumnFlags Flags; // Not exposed ImRect ClipRect; ImGuiOldColumnData() { memset(this, 0, sizeof(*this)); } }; struct ImGuiOldColumns { ImGuiID ID; ImGuiOldColumnFlags Flags; bool IsFirstFrame; bool IsBeingResized; int Current; int Count; float OffMinX, OffMaxX; // Offsets from HostWorkRect.Min.x float LineMinY, LineMaxY; float HostCursorPosY; // Backup of CursorPos at the time of BeginColumns() float HostCursorMaxPosX; // Backup of CursorMaxPos at the time of BeginColumns() ImRect HostInitialClipRect; // Backup of ClipRect at the time of BeginColumns() ImRect HostBackupClipRect; // Backup of ClipRect during PushColumnsBackground()/PopColumnsBackground() ImRect HostBackupParentWorkRect;//Backup of WorkRect at the time of BeginColumns() ImVector Columns; ImDrawListSplitter Splitter; ImGuiOldColumns() { memset(this, 0, sizeof(*this)); } }; //----------------------------------------------------------------------------- // [SECTION] Multi-select support //----------------------------------------------------------------------------- // We always assume that -1 is an invalid value (which works for indices and pointers) #define ImGuiSelectionUserData_Invalid ((ImGuiSelectionUserData)-1) #ifdef IMGUI_HAS_MULTI_SELECT // #endif // #ifdef IMGUI_HAS_MULTI_SELECT //----------------------------------------------------------------------------- // [SECTION] Docking support //----------------------------------------------------------------------------- #ifdef IMGUI_HAS_DOCK // #endif // #ifdef IMGUI_HAS_DOCK //----------------------------------------------------------------------------- // [SECTION] Viewport support //----------------------------------------------------------------------------- // ImGuiViewport Private/Internals fields (cardinal sin: we are using inheritance!) // Every instance of ImGuiViewport is in fact a ImGuiViewportP. struct ImGuiViewportP : public ImGuiViewport { int BgFgDrawListsLastFrame[2]; // Last frame number the background (0) and foreground (1) draw lists were used ImDrawList* BgFgDrawLists[2]; // Convenience background (0) and foreground (1) draw lists. We use them to draw software mouser cursor when io.MouseDrawCursor is set and to draw most debug overlays. ImDrawData DrawDataP; ImDrawDataBuilder DrawDataBuilder; // Temporary data while building final ImDrawData ImVec2 WorkOffsetMin; // Work Area: Offset from Pos to top-left corner of Work Area. Generally (0,0) or (0,+main_menu_bar_height). Work Area is Full Area but without menu-bars/status-bars (so WorkArea always fit inside Pos/Size!) ImVec2 WorkOffsetMax; // Work Area: Offset from Pos+Size to bottom-right corner of Work Area. Generally (0,0) or (0,-status_bar_height). ImVec2 BuildWorkOffsetMin; // Work Area: Offset being built during current frame. Generally >= 0.0f. ImVec2 BuildWorkOffsetMax; // Work Area: Offset being built during current frame. Generally <= 0.0f. ImGuiViewportP() { BgFgDrawListsLastFrame[0] = BgFgDrawListsLastFrame[1] = -1; BgFgDrawLists[0] = BgFgDrawLists[1] = NULL; } ~ImGuiViewportP() { if (BgFgDrawLists[0]) IM_DELETE(BgFgDrawLists[0]); if (BgFgDrawLists[1]) IM_DELETE(BgFgDrawLists[1]); } // Calculate work rect pos/size given a set of offset (we have 1 pair of offset for rect locked from last frame data, and 1 pair for currently building rect) ImVec2 CalcWorkRectPos(const ImVec2& off_min) const { return ImVec2(Pos.x + off_min.x, Pos.y + off_min.y); } ImVec2 CalcWorkRectSize(const ImVec2& off_min, const ImVec2& off_max) const { return ImVec2(ImMax(0.0f, Size.x - off_min.x + off_max.x), ImMax(0.0f, Size.y - off_min.y + off_max.y)); } void UpdateWorkRect() { WorkPos = CalcWorkRectPos(WorkOffsetMin); WorkSize = CalcWorkRectSize(WorkOffsetMin, WorkOffsetMax); } // Update public fields // Helpers to retrieve ImRect (we don't need to store BuildWorkRect as every access tend to change it, hence the code asymmetry) ImRect GetMainRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); } ImRect GetWorkRect() const { return ImRect(WorkPos.x, WorkPos.y, WorkPos.x + WorkSize.x, WorkPos.y + WorkSize.y); } ImRect GetBuildWorkRect() const { ImVec2 pos = CalcWorkRectPos(BuildWorkOffsetMin); ImVec2 size = CalcWorkRectSize(BuildWorkOffsetMin, BuildWorkOffsetMax); return ImRect(pos.x, pos.y, pos.x + size.x, pos.y + size.y); } }; //----------------------------------------------------------------------------- // [SECTION] Settings support //----------------------------------------------------------------------------- // Windows data saved in imgui.ini file // Because we never destroy or rename ImGuiWindowSettings, we can store the names in a separate buffer easily. // (this is designed to be stored in a ImChunkStream buffer, with the variable-length Name following our structure) struct ImGuiWindowSettings { ImGuiID ID; ImVec2ih Pos; ImVec2ih Size; bool Collapsed; bool IsChild; bool WantApply; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context) bool WantDelete; // Set to invalidate/delete the settings entry ImGuiWindowSettings() { memset(this, 0, sizeof(*this)); } char* GetName() { return (char*)(this + 1); } }; struct ImGuiSettingsHandler { const char* TypeName; // Short description stored in .ini file. Disallowed characters: '[' ']' ImGuiID TypeHash; // == ImHashStr(TypeName) void (*ClearAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler); // Clear all settings data void (*ReadInitFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler); // Read: Called before reading (in registration order) void* (*ReadOpenFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, const char* name); // Read: Called when entering into a new ini entry e.g. "[Window][Name]" void (*ReadLineFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, void* entry, const char* line); // Read: Called for every line of text within an ini entry void (*ApplyAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler); // Read: Called after reading (in registration order) void (*WriteAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* out_buf); // Write: Output every entries into 'out_buf' void* UserData; ImGuiSettingsHandler() { memset(this, 0, sizeof(*this)); } }; //----------------------------------------------------------------------------- // [SECTION] Localization support //----------------------------------------------------------------------------- // This is experimental and not officially supported, it'll probably fall short of features, if/when it does we may backtrack. enum ImGuiLocKey : int { ImGuiLocKey_VersionStr, ImGuiLocKey_TableSizeOne, ImGuiLocKey_TableSizeAllFit, ImGuiLocKey_TableSizeAllDefault, ImGuiLocKey_TableResetOrder, ImGuiLocKey_WindowingMainMenuBar, ImGuiLocKey_WindowingPopup, ImGuiLocKey_WindowingUntitled, ImGuiLocKey_COUNT }; struct ImGuiLocEntry { ImGuiLocKey Key; const char* Text; }; //----------------------------------------------------------------------------- // [SECTION] Metrics, Debug Tools //----------------------------------------------------------------------------- enum ImGuiDebugLogFlags_ { // Event types ImGuiDebugLogFlags_None = 0, ImGuiDebugLogFlags_EventActiveId = 1 << 0, ImGuiDebugLogFlags_EventFocus = 1 << 1, ImGuiDebugLogFlags_EventPopup = 1 << 2, ImGuiDebugLogFlags_EventNav = 1 << 3, ImGuiDebugLogFlags_EventClipper = 1 << 4, ImGuiDebugLogFlags_EventSelection = 1 << 5, ImGuiDebugLogFlags_EventIO = 1 << 6, ImGuiDebugLogFlags_EventInputRouting = 1 << 7, ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO | ImGuiDebugLogFlags_EventInputRouting, ImGuiDebugLogFlags_OutputToTTY = 1 << 20, // Also send output to TTY ImGuiDebugLogFlags_OutputToTestEngine = 1 << 21, // Also send output to Test Engine }; struct ImGuiDebugAllocEntry { int FrameCount; ImS16 AllocCount; ImS16 FreeCount; }; struct ImGuiDebugAllocInfo { int TotalAllocCount; // Number of call to MemAlloc(). int TotalFreeCount; ImS16 LastEntriesIdx; // Current index in buffer ImGuiDebugAllocEntry LastEntriesBuf[6]; // Track last 6 frames that had allocations ImGuiDebugAllocInfo() { memset(this, 0, sizeof(*this)); } }; struct ImGuiMetricsConfig { bool ShowDebugLog = false; bool ShowIDStackTool = false; bool ShowWindowsRects = false; bool ShowWindowsBeginOrder = false; bool ShowTablesRects = false; bool ShowDrawCmdMesh = true; bool ShowDrawCmdBoundingBoxes = true; bool ShowTextEncodingViewer = false; bool ShowAtlasTintedWithTextColor = false; int ShowWindowsRectsType = -1; int ShowTablesRectsType = -1; int HighlightMonitorIdx = -1; ImGuiID HighlightViewportID = 0; }; struct ImGuiStackLevelInfo { ImGuiID ID; ImS8 QueryFrameCount; // >= 1: Query in progress bool QuerySuccess; // Obtained result from DebugHookIdInfo() ImGuiDataType DataType : 8; char Desc[57]; // Arbitrarily sized buffer to hold a result (FIXME: could replace Results[] with a chunk stream?) FIXME: Now that we added CTRL+C this should be fixed. ImGuiStackLevelInfo() { memset(this, 0, sizeof(*this)); } }; // State for ID Stack tool queries struct ImGuiIDStackTool { int LastActiveFrame; int StackLevel; // -1: query stack and resize Results, >= 0: individual stack level ImGuiID QueryId; // ID to query details for ImVector Results; bool CopyToClipboardOnCtrlC; float CopyToClipboardLastTime; ImGuiIDStackTool() { memset(this, 0, sizeof(*this)); CopyToClipboardLastTime = -FLT_MAX; } }; //----------------------------------------------------------------------------- // [SECTION] Generic context hooks //----------------------------------------------------------------------------- typedef void (*ImGuiContextHookCallback)(ImGuiContext* ctx, ImGuiContextHook* hook); enum ImGuiContextHookType { ImGuiContextHookType_NewFramePre, ImGuiContextHookType_NewFramePost, ImGuiContextHookType_EndFramePre, ImGuiContextHookType_EndFramePost, ImGuiContextHookType_RenderPre, ImGuiContextHookType_RenderPost, ImGuiContextHookType_Shutdown, ImGuiContextHookType_PendingRemoval_ }; struct ImGuiContextHook { ImGuiID HookId; // A unique ID assigned by AddContextHook() ImGuiContextHookType Type; ImGuiID Owner; ImGuiContextHookCallback Callback; void* UserData; ImGuiContextHook() { memset(this, 0, sizeof(*this)); } }; //----------------------------------------------------------------------------- // [SECTION] ImGuiContext (main Dear ImGui context) //----------------------------------------------------------------------------- struct ImGuiContext { bool Initialized; bool FontAtlasOwnedByContext; // IO.Fonts-> is owned by the ImGuiContext and will be destructed along with it. ImGuiIO IO; ImGuiStyle Style; ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window. float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height. ImDrawListSharedData DrawListSharedData; double Time; int FrameCount; int FrameCountEnded; int FrameCountRendered; bool WithinFrameScope; // Set by NewFrame(), cleared by EndFrame() bool WithinFrameScopeWithImplicitWindow; // Set by NewFrame(), cleared by EndFrame() when the implicit debug window has been pushed bool WithinEndChild; // Set within EndChild() bool GcCompactAll; // Request full GC bool TestEngineHookItems; // Will call test engine hooks: ImGuiTestEngineHook_ItemAdd(), ImGuiTestEngineHook_ItemInfo(), ImGuiTestEngineHook_Log() void* TestEngine; // Test engine user data // Inputs ImVector InputEventsQueue; // Input events which will be trickled/written into IO structure. ImVector InputEventsTrail; // Past input events processed in NewFrame(). This is to allow domain-specific application to access e.g mouse/pen trail. ImGuiMouseSource InputEventsNextMouseSource; ImU32 InputEventsNextEventId; // Windows state ImVector Windows; // Windows, sorted in display order, back to front ImVector WindowsFocusOrder; // Root windows, sorted in focus order, back to front. ImVector WindowsTempSortBuffer; // Temporary buffer used in EndFrame() to reorder windows so parents are kept before their child ImVector CurrentWindowStack; ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow* int WindowsActiveCount; // Number of unique windows submitted by frame ImVec2 WindowsHoverPadding; // Padding around resizable windows for which hovering on counts as hovering the window == ImMax(style.TouchExtraPadding, WINDOWS_HOVER_PADDING) ImGuiID DebugBreakInWindow; // Set to break in Begin() call. ImGuiWindow* CurrentWindow; // Window being drawn into ImGuiWindow* HoveredWindow; // Window the mouse is hovering. Will typically catch mouse inputs. ImGuiWindow* HoveredWindowUnderMovingWindow; // Hovered window ignoring MovingWindow. Only set if MovingWindow is set. ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actual window that is moved is generally MovingWindow->RootWindow. ImGuiWindow* WheelingWindow; // Track the window we started mouse-wheeling on. Until a timer elapse or mouse has moved, generally keep scrolling the same window even if during the course of scrolling the mouse ends up hovering a child window. ImVec2 WheelingWindowRefMousePos; int WheelingWindowStartFrame; // This may be set one frame before WheelingWindow is != NULL int WheelingWindowScrolledFrame; float WheelingWindowReleaseTimer; ImVec2 WheelingWindowWheelRemainder; ImVec2 WheelingAxisAvg; // Item/widgets state and tracking information ImGuiID DebugHookIdInfo; // Will call core hooks: DebugHookIdInfo() from GetID functions, used by ID Stack Tool [next HoveredId/ActiveId to not pull in an extra cache-line] ImGuiID HoveredId; // Hovered widget, filled during the frame ImGuiID HoveredIdPreviousFrame; bool HoveredIdAllowOverlap; bool HoveredIdDisabled; // At least one widget passed the rect test, but has been discarded by disabled flag or popup inhibit. May be true even if HoveredId == 0. float HoveredIdTimer; // Measure contiguous hovering time float HoveredIdNotActiveTimer; // Measure contiguous hovering time where the item has not been active ImGuiID ActiveId; // Active widget ImGuiID ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame) float ActiveIdTimer; bool ActiveIdIsJustActivated; // Set at the time of activation for one frame bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always) bool ActiveIdNoClearOnFocusLoss; // Disable losing active id if the active id window gets unfocused. bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch. bool ActiveIdHasBeenEditedBefore; // Was the value associated to the widget Edited over the course of the Active state. bool ActiveIdHasBeenEditedThisFrame; bool ActiveIdFromShortcut; int ActiveIdMouseButton : 8; ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; ImGuiInputSource ActiveIdSource; // Activating source: ImGuiInputSource_Mouse OR ImGuiInputSource_Keyboard OR ImGuiInputSource_Gamepad ImGuiID ActiveIdPreviousFrame; bool ActiveIdPreviousFrameIsAlive; bool ActiveIdPreviousFrameHasBeenEditedBefore; ImGuiWindow* ActiveIdPreviousFrameWindow; ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation. float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation. // [EXPERIMENTAL] Key/Input Ownership + Shortcut Routing system // - The idea is that instead of "eating" a given key, we can link to an owner. // - Input query can then read input by specifying ImGuiKeyOwner_Any (== 0), ImGuiKeyOwner_None (== -1) or a custom ID. // - Routing is requested ahead of time for a given chord (Key + Mods) and granted in NewFrame(). double LastKeyModsChangeTime; // Record the last time key mods changed (affect repeat delay when using shortcut logic) double LastKeyModsChangeFromNoneTime; // Record the last time key mods changed away from being 0 (affect repeat delay when using shortcut logic) double LastKeyboardKeyPressTime; // Record the last time a keyboard key (ignore mouse/gamepad ones) was pressed. ImBitArrayForNamedKeys KeysMayBeCharInput; // Lookup to tell if a key can emit char input, see IsKeyChordPotentiallyCharInput(). sizeof() = 20 bytes ImGuiKeyOwnerData KeysOwnerData[ImGuiKey_NamedKey_COUNT]; ImGuiKeyRoutingTable KeysRoutingTable; ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it) bool ActiveIdUsingAllKeyboardKeys; // Active widget will want to read all keyboard keys inputs. (FIXME: This is a shortcut for not taking ownership of 100+ keys but perhaps best to not have the inconsistency) ImGuiKeyChord DebugBreakInShortcutRouting; // Set to break in SetShortcutRouting()/Shortcut() calls. #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO ImU32 ActiveIdUsingNavInputMask; // If you used this. Since (IMGUI_VERSION_NUM >= 18804) : 'g.ActiveIdUsingNavInputMask |= (1 << ImGuiNavInput_Cancel);' becomes 'SetKeyOwner(ImGuiKey_Escape, g.ActiveId) and/or SetKeyOwner(ImGuiKey_NavGamepadCancel, g.ActiveId);' #endif // Next window/item data ImGuiID CurrentFocusScopeId; // Value for currently appending items == g.FocusScopeStack.back(). Not to be mistaken with g.NavFocusScopeId. ImGuiItemFlags CurrentItemFlags; // Value for currently appending items == g.ItemFlagsStack.back() ImGuiID DebugLocateId; // Storage for DebugLocateItemOnHover() feature: this is read by ItemAdd() so we keep it in a hot/cached location ImGuiNextItemData NextItemData; // Storage for SetNextItem** functions ImGuiLastItemData LastItemData; // Storage for last submitted item (setup by ItemAdd) ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions bool DebugShowGroupRects; // Shared stacks ImGuiCol DebugFlashStyleColorIdx; // (Keep close to ColorStack to share cache line) ImVector ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin() ImVector StyleVarStack; // Stack for PushStyleVar()/PopStyleVar() - inherited by Begin() ImVector FontStack; // Stack for PushFont()/PopFont() - inherited by Begin() ImVector FocusScopeStack; // Stack for PushFocusScope()/PopFocusScope() - inherited by BeginChild(), pushed into by Begin() ImVector ItemFlagsStack; // Stack for PushItemFlag()/PopItemFlag() - inherited by Begin() ImVector GroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin() ImVector OpenPopupStack; // Which popups are open (persistent) ImVector BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame) ImVector NavTreeNodeStack; // Stack for TreeNode() when a NavLeft requested is emitted. // Viewports ImVector Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData. // Gamepad/keyboard Navigation ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow' ImGuiID NavId; // Focused item for navigation ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope) ImVector NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain. ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem() ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0 ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat) ImGuiActivateFlags NavActivateFlags; ImGuiID NavHighlightActivatedId; float NavHighlightActivatedTimer; ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest). ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest). ImGuiKeyChord NavJustMovedToKeyMods; ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame. ImGuiActivateFlags NavNextActivateFlags; ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Mouse ImGuiNavLayer NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. ImGuiSelectionUserData NavLastValidSelectionUserData; // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data. bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default) bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover) bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again. // Navigation: Init & Move Requests bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd() bool NavInitRequest; // Init request for appearing window to select first item bool NavInitRequestFromMove; ImGuiNavItemData NavInitResult; // Init request result (first item of the window, or one for which SetItemDefaultFocus() was called) bool NavMoveSubmitted; // Move request submitted, will process result on next NewFrame() bool NavMoveScoringItems; // Move request submitted, still scoring incoming items bool NavMoveForwardToNextFrame; ImGuiNavMoveFlags NavMoveFlags; ImGuiScrollFlags NavMoveScrollFlags; ImGuiKeyChord NavMoveKeyMods; ImGuiDir NavMoveDir; // Direction of the move request (left/right/up/down) ImGuiDir NavMoveDirForDebug; ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename? ImRect NavScoringRect; // Rectangle used for scoring, in screen space. Based of window->NavRectRel[], modified for directional navigation scoring. ImRect NavScoringNoClipRect; // Some nav operations (such as PageUp/PageDown) enforce a region which clipper will attempt to always keep submitted int NavScoringDebugCount; // Metrics for debugging int NavTabbingDir; // Generally -1 or +1, 0 when tabbing without a nav id int NavTabbingCounter; // >0 when counting items for tabbing ImGuiNavItemData NavMoveResultLocal; // Best move request candidate within NavWindow ImGuiNavItemData NavMoveResultLocalVisible; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag) ImGuiNavItemData NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag) ImGuiNavItemData NavTabbingResultFirst; // First tabbing request candidate within NavWindow and flattened hierarchy // Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize) ImGuiKeyChord ConfigNavWindowingKeyNext; // = ImGuiMod_Ctrl | ImGuiKey_Tab, for reconfiguration (see #4828) ImGuiKeyChord ConfigNavWindowingKeyPrev; // = ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab ImGuiWindow* NavWindowingTarget; // Target window when doing CTRL+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most! ImGuiWindow* NavWindowingTargetAnim; // Record of last valid NavWindowingTarget until DimBgRatio and NavWindowingHighlightAlpha becomes 0.0f, so the fade-out can stay on it. ImGuiWindow* NavWindowingListWindow; // Internal window actually listing the CTRL+Tab contents float NavWindowingTimer; float NavWindowingHighlightAlpha; bool NavWindowingToggleLayer; ImGuiKey NavWindowingToggleKey; ImVec2 NavWindowingAccumDeltaPos; ImVec2 NavWindowingAccumDeltaSize; // Render float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list) // Drag and Drop bool DragDropActive; bool DragDropWithinSource; // Set when within a BeginDragDropXXX/EndDragDropXXX block for a drag source. bool DragDropWithinTarget; // Set when within a BeginDragDropXXX/EndDragDropXXX block for a drag target. ImGuiDragDropFlags DragDropSourceFlags; int DragDropSourceFrameCount; int DragDropMouseButton; ImGuiPayload DragDropPayload; ImRect DragDropTargetRect; // Store rectangle of current target candidate (we favor small targets when overlapping) ImRect DragDropTargetClipRect; // Store ClipRect at the time of item's drawing ImGuiID DragDropTargetId; ImGuiDragDropFlags DragDropAcceptFlags; float DragDropAcceptIdCurrRectSurface; // Target item surface (we resolve overlapping targets by prioritizing the smaller surface) ImGuiID DragDropAcceptIdCurr; // Target item id (set at the time of accepting the payload) ImGuiID DragDropAcceptIdPrev; // Target item id from previous frame (we need to store this to allow for overlapping drag and drop targets) int DragDropAcceptFrameCount; // Last time a target expressed a desire to accept the source ImGuiID DragDropHoldJustPressedId; // Set when holding a payload just made ButtonBehavior() return a press. ImVector DragDropPayloadBufHeap; // We don't expose the ImVector<> directly, ImGuiPayload only holds pointer+size unsigned char DragDropPayloadBufLocal[16]; // Local buffer for small payloads // Clipper int ClipperTempDataStacked; ImVector ClipperTempData; // Tables ImGuiTable* CurrentTable; ImGuiID DebugBreakInTable; // Set to break in BeginTable() call. int TablesTempDataStacked; // Temporary table data size (because we leave previous instances undestructed, we generally don't use TablesTempData.Size) ImVector TablesTempData; // Temporary table data (buffers reused/shared across instances, support nesting) ImPool Tables; // Persistent table data ImVector TablesLastTimeActive; // Last used timestamp of each tables (SOA, for efficient GC) ImVector DrawChannelsTempMergeBuffer; // Tab bars ImGuiTabBar* CurrentTabBar; ImPool TabBars; ImVector CurrentTabBarStack; ImVector ShrinkWidthBuffer; // Hover Delay system ImGuiID HoverItemDelayId; ImGuiID HoverItemDelayIdPreviousFrame; float HoverItemDelayTimer; // Currently used by IsItemHovered() float HoverItemDelayClearTimer; // Currently used by IsItemHovered(): grace time before g.TooltipHoverTimer gets cleared. ImGuiID HoverItemUnlockedStationaryId; // Mouse has once been stationary on this item. Only reset after departing the item. ImGuiID HoverWindowUnlockedStationaryId; // Mouse has once been stationary on this window. Only reset after departing the window. // Mouse state ImGuiMouseCursor MouseCursor; float MouseStationaryTimer; // Time the mouse has been stationary (with some loose heuristic) ImVec2 MouseLastValidPos; // Widget state ImGuiInputTextState InputTextState; ImGuiInputTextDeactivatedState InputTextDeactivatedState; ImFont InputTextPasswordFont; ImGuiID TempInputId; // Temporary text input when CTRL+clicking on a slider, etc. int BeginMenuDepth; int BeginComboDepth; ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets ImGuiID ColorEditCurrentID; // Set temporarily while inside of the parent-most ColorEdit4/ColorPicker4 (because they call each others). ImGuiID ColorEditSavedID; // ID we are saving/restoring HS for float ColorEditSavedHue; // Backup of last Hue associated to LastColor, so we can restore Hue in lossy RGB<>HSV round trips float ColorEditSavedSat; // Backup of last Saturation associated to LastColor, so we can restore Saturation in lossy RGB<>HSV round trips ImU32 ColorEditSavedColor; // RGB value with alpha set to 0. ImVec4 ColorPickerRef; // Initial/reference color at the time of opening the color picker. ImGuiComboPreviewData ComboPreviewData; ImRect WindowResizeBorderExpectedRect; // Expected border rect, switch to relative edit if moving bool WindowResizeRelativeMode; float SliderGrabClickOffset; float SliderCurrentAccum; // Accumulated slider delta when using navigation controls. bool SliderCurrentAccumDirty; // Has the accumulated slider delta changed since last time we tried to apply it? bool DragCurrentAccumDirty; float DragCurrentAccum; // Accumulator for dragging modification. Always high-precision, not rounded by end-user precision settings float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio float ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage? float DisabledAlphaBackup; // Backup for style.Alpha for BeginDisabled() short DisabledStackSize; short LockMarkEdited; short TooltipOverrideCount; ImVector ClipboardHandlerData; // If no custom clipboard handler is defined ImVector MenusIdSubmittedThisFrame; // A list of menu IDs that were rendered at least once ImGuiTypingSelectState TypingSelectState; // State for GetTypingSelectRequest() // Platform support ImGuiPlatformImeData PlatformImeData; // Data updated by current frame ImGuiPlatformImeData PlatformImeDataPrev; // Previous frame data (when changing we will call io.SetPlatformImeDataFn // Settings bool SettingsLoaded; float SettingsDirtyTimer; // Save .ini Settings to memory when time reaches zero ImGuiTextBuffer SettingsIniData; // In memory .ini settings ImVector SettingsHandlers; // List of .ini settings handlers ImChunkStream SettingsWindows; // ImGuiWindow .ini settings entries ImChunkStream SettingsTables; // ImGuiTable .ini settings entries ImVector Hooks; // Hooks for extensions (e.g. test engine) ImGuiID HookIdNext; // Next available HookId // Localization const char* LocalizationTable[ImGuiLocKey_COUNT]; // Capture/Logging bool LogEnabled; // Currently capturing ImGuiLogType LogType; // Capture target ImFileHandle LogFile; // If != NULL log to stdout/ file ImGuiTextBuffer LogBuffer; // Accumulation buffer when log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators. const char* LogNextPrefix; const char* LogNextSuffix; float LogLinePosY; bool LogLineFirstItem; int LogDepthRef; int LogDepthToExpand; int LogDepthToExpandDefault; // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call. // Debug Tools // (some of the highly frequently used data are interleaved in other structures above: DebugBreakXXX fields, DebugHookIdInfo, DebugLocateId etc.) ImGuiDebugLogFlags DebugLogFlags; ImGuiTextBuffer DebugLogBuf; ImGuiTextIndex DebugLogIndex; ImGuiDebugLogFlags DebugLogAutoDisableFlags; ImU8 DebugLogAutoDisableFrames; ImU8 DebugLocateFrames; // For DebugLocateItemOnHover(). This is used together with DebugLocateId which is in a hot/cached spot above. bool DebugBreakInLocateId; // Debug break in ItemAdd() call for g.DebugLocateId. ImGuiKeyChord DebugBreakKeyChord; // = ImGuiKey_Pause ImS8 DebugBeginReturnValueCullDepth; // Cycle between 0..9 then wrap around. bool DebugItemPickerActive; // Item picker is active (started with DebugStartItemPicker()) ImU8 DebugItemPickerMouseButton; ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this ID float DebugFlashStyleColorTime; ImVec4 DebugFlashStyleColorBackup; ImGuiMetricsConfig DebugMetricsConfig; ImGuiIDStackTool DebugIDStackTool; ImGuiDebugAllocInfo DebugAllocInfo; // Misc float FramerateSecPerFrame[60]; // Calculate estimate of framerate for user over the last 60 frames.. int FramerateSecPerFrameIdx; int FramerateSecPerFrameCount; float FramerateSecPerFrameAccum; int WantCaptureMouseNextFrame; // Explicit capture override via SetNextFrameWantCaptureMouse()/SetNextFrameWantCaptureKeyboard(). Default to -1. int WantCaptureKeyboardNextFrame; // " int WantTextInputNextFrame; ImVector TempBuffer; // Temporary text buffer char TempKeychordName[64]; ImGuiContext(ImFontAtlas* shared_font_atlas) { IO.Ctx = this; InputTextState.Ctx = this; Initialized = false; FontAtlasOwnedByContext = shared_font_atlas ? false : true; Font = NULL; FontSize = FontBaseSize = 0.0f; IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)(); Time = 0.0f; FrameCount = 0; FrameCountEnded = FrameCountRendered = -1; WithinFrameScope = WithinFrameScopeWithImplicitWindow = WithinEndChild = false; GcCompactAll = false; TestEngineHookItems = false; TestEngine = NULL; InputEventsNextMouseSource = ImGuiMouseSource_Mouse; InputEventsNextEventId = 1; WindowsActiveCount = 0; CurrentWindow = NULL; HoveredWindow = NULL; HoveredWindowUnderMovingWindow = NULL; MovingWindow = NULL; WheelingWindow = NULL; WheelingWindowStartFrame = WheelingWindowScrolledFrame = -1; WheelingWindowReleaseTimer = 0.0f; DebugHookIdInfo = 0; HoveredId = HoveredIdPreviousFrame = 0; HoveredIdAllowOverlap = false; HoveredIdDisabled = false; HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f; ActiveId = 0; ActiveIdIsAlive = 0; ActiveIdTimer = 0.0f; ActiveIdIsJustActivated = false; ActiveIdAllowOverlap = false; ActiveIdNoClearOnFocusLoss = false; ActiveIdHasBeenPressedBefore = false; ActiveIdHasBeenEditedBefore = false; ActiveIdHasBeenEditedThisFrame = false; ActiveIdFromShortcut = false; ActiveIdClickOffset = ImVec2(-1, -1); ActiveIdWindow = NULL; ActiveIdSource = ImGuiInputSource_None; ActiveIdMouseButton = -1; ActiveIdPreviousFrame = 0; ActiveIdPreviousFrameIsAlive = false; ActiveIdPreviousFrameHasBeenEditedBefore = false; ActiveIdPreviousFrameWindow = NULL; LastActiveId = 0; LastActiveIdTimer = 0.0f; LastKeyboardKeyPressTime = LastKeyModsChangeTime = LastKeyModsChangeFromNoneTime = -1.0; ActiveIdUsingNavDirMask = 0x00; ActiveIdUsingAllKeyboardKeys = false; #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO ActiveIdUsingNavInputMask = 0x00; #endif CurrentFocusScopeId = 0; CurrentItemFlags = ImGuiItemFlags_None; DebugShowGroupRects = false; NavWindow = NULL; NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0; NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0; NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None; NavHighlightActivatedId = 0; NavHighlightActivatedTimer = 0.0f; NavJustMovedToKeyMods = ImGuiMod_None; NavInputSource = ImGuiInputSource_Keyboard; NavLayer = ImGuiNavLayer_Main; NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid; NavIdIsAlive = false; NavMousePosDirty = false; NavDisableHighlight = true; NavDisableMouseHover = false; NavAnyRequest = false; NavInitRequest = false; NavInitRequestFromMove = false; NavMoveSubmitted = false; NavMoveScoringItems = false; NavMoveForwardToNextFrame = false; NavMoveFlags = ImGuiNavMoveFlags_None; NavMoveScrollFlags = ImGuiScrollFlags_None; NavMoveKeyMods = ImGuiMod_None; NavMoveDir = NavMoveDirForDebug = NavMoveClipDir = ImGuiDir_None; NavScoringDebugCount = 0; NavTabbingDir = 0; NavTabbingCounter = 0; ConfigNavWindowingKeyNext = ImGuiMod_Ctrl | ImGuiKey_Tab; ConfigNavWindowingKeyPrev = ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab; NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL; NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f; NavWindowingToggleLayer = false; NavWindowingToggleKey = ImGuiKey_None; DimBgRatio = 0.0f; DragDropActive = DragDropWithinSource = DragDropWithinTarget = false; DragDropSourceFlags = ImGuiDragDropFlags_None; DragDropSourceFrameCount = -1; DragDropMouseButton = -1; DragDropTargetId = 0; DragDropAcceptFlags = ImGuiDragDropFlags_None; DragDropAcceptIdCurrRectSurface = 0.0f; DragDropAcceptIdPrev = DragDropAcceptIdCurr = 0; DragDropAcceptFrameCount = -1; DragDropHoldJustPressedId = 0; memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal)); ClipperTempDataStacked = 0; CurrentTable = NULL; TablesTempDataStacked = 0; CurrentTabBar = NULL; HoverItemDelayId = HoverItemDelayIdPreviousFrame = HoverItemUnlockedStationaryId = HoverWindowUnlockedStationaryId = 0; HoverItemDelayTimer = HoverItemDelayClearTimer = 0.0f; MouseCursor = ImGuiMouseCursor_Arrow; MouseStationaryTimer = 0.0f; TempInputId = 0; BeginMenuDepth = BeginComboDepth = 0; ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_; ColorEditCurrentID = ColorEditSavedID = 0; ColorEditSavedHue = ColorEditSavedSat = 0.0f; ColorEditSavedColor = 0; WindowResizeRelativeMode = false; SliderGrabClickOffset = 0.0f; SliderCurrentAccum = 0.0f; SliderCurrentAccumDirty = false; DragCurrentAccumDirty = false; DragCurrentAccum = 0.0f; DragSpeedDefaultRatio = 1.0f / 100.0f; ScrollbarClickDeltaToGrabCenter = 0.0f; DisabledAlphaBackup = 0.0f; DisabledStackSize = 0; LockMarkEdited = 0; TooltipOverrideCount = 0; PlatformImeData.InputPos = ImVec2(0.0f, 0.0f); PlatformImeDataPrev.InputPos = ImVec2(-1.0f, -1.0f); // Different to ensure initial submission SettingsLoaded = false; SettingsDirtyTimer = 0.0f; HookIdNext = 0; memset(LocalizationTable, 0, sizeof(LocalizationTable)); LogEnabled = false; LogType = ImGuiLogType_None; LogNextPrefix = LogNextSuffix = NULL; LogFile = NULL; LogLinePosY = FLT_MAX; LogLineFirstItem = false; LogDepthRef = 0; LogDepthToExpand = LogDepthToExpandDefault = 2; DebugLogFlags = ImGuiDebugLogFlags_OutputToTTY; DebugLocateId = 0; DebugLogAutoDisableFlags = ImGuiDebugLogFlags_None; DebugLogAutoDisableFrames = 0; DebugLocateFrames = 0; DebugBeginReturnValueCullDepth = -1; DebugItemPickerActive = false; DebugItemPickerMouseButton = ImGuiMouseButton_Left; DebugItemPickerBreakId = 0; DebugFlashStyleColorTime = 0.0f; DebugFlashStyleColorIdx = ImGuiCol_COUNT; // Same as DebugBreakClearData(). Those fields are scattered in their respective subsystem to stay in hot-data locations DebugBreakInWindow = 0; DebugBreakInTable = 0; DebugBreakInLocateId = false; DebugBreakKeyChord = ImGuiKey_Pause; DebugBreakInShortcutRouting = ImGuiKey_None; memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame)); FramerateSecPerFrameIdx = FramerateSecPerFrameCount = 0; FramerateSecPerFrameAccum = 0.0f; WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1; memset(TempKeychordName, 0, sizeof(TempKeychordName)); } }; //----------------------------------------------------------------------------- // [SECTION] ImGuiWindowTempData, ImGuiWindow //----------------------------------------------------------------------------- // Transient per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the DC variable name in ImGuiWindow. // (That's theory, in practice the delimitation between ImGuiWindow and ImGuiWindowTempData is quite tenuous and could be reconsidered..) // (This doesn't need a constructor because we zero-clear it as part of ImGuiWindow and all frame-temporary data are setup on Begin) struct IMGUI_API ImGuiWindowTempData { // Layout ImVec2 CursorPos; // Current emitting position, in absolute coordinates. ImVec2 CursorPosPrevLine; ImVec2 CursorStartPos; // Initial position after Begin(), generally ~ window position + WindowPadding. ImVec2 CursorMaxPos; // Used to implicitly calculate ContentSize at the beginning of next frame, for scrolling range and auto-resize. Always growing during the frame. ImVec2 IdealMaxPos; // Used to implicitly calculate ContentSizeIdeal at the beginning of next frame, for auto-resize only. Always growing during the frame. ImVec2 CurrLineSize; ImVec2 PrevLineSize; float CurrLineTextBaseOffset; // Baseline offset (0.0f by default on a new line, generally == style.FramePadding.y when a framed item has been added). float PrevLineTextBaseOffset; bool IsSameLine; bool IsSetPos; ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. ImVec1 GroupOffset; ImVec2 CursorStartPosLossyness;// Record the loss of precision of CursorStartPos due to really large scrolling amount. This is used by clipper to compensate and fix the most common use case of large scroll area. // Keyboard/Gamepad navigation ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) short NavLayersActiveMask; // Which layers have been written to (result from previous frame) short NavLayersActiveMaskNext;// Which layers have been written to (accumulator for current frame) bool NavIsScrollPushableX; // Set when current work location may be scrolled horizontally when moving left / right. This is generally always true UNLESS within a column. bool NavHideHighlightOneFrame; bool NavWindowHasScrollY; // Set per window when scrolling can be used (== ScrollMax.y > 0.0f) // Miscellaneous bool MenuBarAppending; // FIXME: Remove this ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs. ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items measurement int TreeDepth; // Current tree depth. ImU32 TreeJumpToParentOnPopMask; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31.. Could be turned into a ImU64 if necessary. ImVector ChildWindows; ImGuiStorage* StateStorage; // Current persistent per-window storage (store e.g. tree node open/close state) ImGuiOldColumns* CurrentColumns; // Current columns set int CurrentTableIdx; // Current table index (into g.Tables) ImGuiLayoutType LayoutType; ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin() // Local parameters stacks // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. float ItemWidth; // Current item width (>0.0: width in pixels, <0.0: align xx pixels to the right of window). float TextWrapPos; // Current text wrap pos. ImVector ItemWidthStack; // Store item widths to restore (attention: .back() is not == ItemWidth) ImVector TextWrapPosStack; // Store text wrap pos to restore (attention: .back() is not == TextWrapPos) }; // Storage for one window struct IMGUI_API ImGuiWindow { ImGuiContext* Ctx; // Parent UI context (needs to be set explicitly by parent). char* Name; // Window name, owned by the window. ImGuiID ID; // == ImHashStr(Name) ImGuiWindowFlags Flags; // See enum ImGuiWindowFlags_ ImGuiChildFlags ChildFlags; // Set when window is a child window. See enum ImGuiChildFlags_ ImGuiViewportP* Viewport; // Always set in Begin(). Inactive windows may have a NULL value here if their viewport was discarded. ImVec2 Pos; // Position (always rounded-up to nearest pixel) ImVec2 Size; // Current size (==SizeFull or collapsed title bar size) ImVec2 SizeFull; // Size when non collapsed ImVec2 ContentSize; // Size of contents/scrollable client area (calculated from the extents reach of the cursor) from previous frame. Does not include window decoration or window padding. ImVec2 ContentSizeIdeal; ImVec2 ContentSizeExplicit; // Size of contents/scrollable client area explicitly request by the user via SetNextWindowContentSize(). ImVec2 WindowPadding; // Window padding at the time of Begin(). float WindowRounding; // Window rounding at the time of Begin(). May be clamped lower to avoid rendering artifacts with title bar, menu bar etc. float WindowBorderSize; // Window border size at the time of Begin(). float DecoOuterSizeX1, DecoOuterSizeY1; // Left/Up offsets. Sum of non-scrolling outer decorations (X1 generally == 0.0f. Y1 generally = TitleBarHeight + MenuBarHeight). Locked during Begin(). float DecoOuterSizeX2, DecoOuterSizeY2; // Right/Down offsets (X2 generally == ScrollbarSize.x, Y2 == ScrollbarSizes.y). float DecoInnerSizeX1, DecoInnerSizeY1; // Applied AFTER/OVER InnerRect. Specialized for Tables as they use specialized form of clipping and frozen rows/columns are inside InnerRect (and not part of regular decoration sizes). int NameBufLen; // Size of buffer storing Name. May be larger than strlen(Name)! ImGuiID MoveId; // == window->GetID("#MOVE") ImGuiID ChildId; // ID of corresponding item in parent window (for navigation to return from child window to parent window) ImVec2 Scroll; ImVec2 ScrollMax; ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change) ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered ImVec2 ScrollTargetEdgeSnapDist; // 0.0f = no snapping, >0.0f snapping threshold ImVec2 ScrollbarSizes; // Size taken by each scrollbars on their smaller axis. Pay attention! ScrollbarSizes.x == width of the vertical scrollbar, ScrollbarSizes.y = height of the horizontal scrollbar. bool ScrollbarX, ScrollbarY; // Are scrollbars visible? bool Active; // Set to true on Begin(), unless Collapsed bool WasActive; bool WriteAccessed; // Set to true when any widget access the current window bool Collapsed; // Set when collapsing window to become only title-bar bool WantCollapseToggle; bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed) bool Appearing; // Set during the frame where the window is appearing (or re-appearing) bool Hidden; // Do not display (== HiddenFrames*** > 0) bool IsFallbackWindow; // Set on the "Debug##Default" window. bool IsExplicitChild; // Set when passed _ChildWindow, left to false by BeginDocked() bool HasCloseButton; // Set when the window has a close button (p_open != NULL) signed char ResizeBorderHovered; // Current border being hovered for resize (-1: none, otherwise 0-3) signed char ResizeBorderHeld; // Current border being held for resize (-1: none, otherwise 0-3) short BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) short BeginCountPreviousFrame; // Number of Begin() during the previous frame short BeginOrderWithinParent; // Begin() order within immediate parent window, if we are a child window. Otherwise 0. short BeginOrderWithinContext; // Begin() order within entire imgui context. This is mostly used for debugging submission order related issues. short FocusOrder; // Order within WindowsFocusOrder[], altered when windows are focused. ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) ImS8 AutoFitFramesX, AutoFitFramesY; bool AutoFitOnlyGrows; ImGuiDir AutoPosLastDirection; ImS8 HiddenFramesCanSkipItems; // Hide the window for N frames ImS8 HiddenFramesCannotSkipItems; // Hide the window for N frames while allowing items to be submitted so we can measure their size ImS8 HiddenFramesForRenderOnly; // Hide the window until frame N at Render() time only ImS8 DisableInputsFrames; // Disable window interactions for N frames ImGuiCond SetWindowPosAllowFlags : 8; // store acceptable condition flags for SetNextWindowPos() use. ImGuiCond SetWindowSizeAllowFlags : 8; // store acceptable condition flags for SetNextWindowSize() use. ImGuiCond SetWindowCollapsedAllowFlags : 8; // store acceptable condition flags for SetNextWindowCollapsed() use. ImVec2 SetWindowPosVal; // store window position when using a non-zero Pivot (position set needs to be processed when we know the window size) ImVec2 SetWindowPosPivot; // store window pivot for positioning. ImVec2(0, 0) when positioning from top-left corner; ImVec2(0.5f, 0.5f) for centering; ImVec2(1, 1) for bottom right. ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack. (In theory this should be in the TempData structure) ImGuiWindowTempData DC; // Temporary per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the "DC" variable name. // The best way to understand what those rectangles are is to use the 'Metrics->Tools->Show Windows Rectangles' viewer. // The main 'OuterRect', omitted as a field, is window->Rect(). ImRect OuterRectClipped; // == Window->Rect() just after setup in Begin(). == window->Rect() for root window. ImRect InnerRect; // Inner rectangle (omit title bar, menu bar, scroll bar) ImRect InnerClipRect; // == InnerRect shrunk by WindowPadding*0.5f on each side, clipped within viewport or parent clip rect. ImRect WorkRect; // Initially covers the whole scrolling region. Reduced by containers e.g columns/tables when active. Shrunk by WindowPadding*1.0f on each side. This is meant to replace ContentRegionRect over time (from 1.71+ onward). ImRect ParentWorkRect; // Backup of WorkRect before entering a container such as columns/tables. Used by e.g. SpanAllColumns functions to easily access. Stacked containers are responsible for maintaining this. // FIXME-WORKRECT: Could be a stack? ImRect ClipRect; // Current clipping/scissoring rectangle, evolve as we are using PushClipRect(), etc. == DrawList->clip_rect_stack.back(). ImRect ContentRegionRect; // FIXME: This is currently confusing/misleading. It is essentially WorkRect but not handling of scrolling. We currently rely on it as right/bottom aligned sizing operation need some size to rely on. ImVec2ih HitTestHoleSize; // Define an optional rectangular hole where mouse will pass-through the window. ImVec2ih HitTestHoleOffset; int LastFrameActive; // Last frame number the window was Active. float LastTimeActive; // Last timestamp the window was Active (using float as we don't need high precision there) float ItemWidthDefault; ImGuiStorage StateStorage; ImVector ColumnsStorage; float FontWindowScale; // User scale multiplier per-window, via SetWindowFontScale() int SettingsOffset; // Offset into SettingsWindows[] (offsets are always valid as we only grow the array from the back) ImDrawList* DrawList; // == &DrawListInst (for backward compatibility reason with code using imgui_internal.h we keep this a pointer) ImDrawList DrawListInst; ImGuiWindow* ParentWindow; // If we are a child _or_ popup _or_ docked window, this is pointing to our parent. Otherwise NULL. ImGuiWindow* ParentWindowInBeginStack; ImGuiWindow* RootWindow; // Point to ourself or first ancestor that is not a child window. Doesn't cross through popups/dock nodes. ImGuiWindow* RootWindowPopupTree; // Point to ourself or first ancestor that is not a child window. Cross through popups parent<>child. ImGuiWindow* RootWindowForTitleBarHighlight; // Point to ourself or first ancestor which will display TitleBgActive color when this window is active. ImGuiWindow* RootWindowForNav; // Point to ourself or first ancestor which doesn't have the NavFlattened flag. ImGuiWindow* ParentWindowForFocusRoute; // Set to manual link a window to its logical parent so that Shortcut() chain are honoerd (e.g. Tool linked to Document) ImGuiWindow* NavLastChildNavWindow; // When going to the menu bar, we remember the child window we came from. (This could probably be made implicit if we kept g.Windows sorted by last focused including child window.) ImGuiID NavLastIds[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1) ImRect NavRectRel[ImGuiNavLayer_COUNT]; // Reference rectangle, in window relative space ImVec2 NavPreferredScoringPosRel[ImGuiNavLayer_COUNT]; // Preferred X/Y position updated when moving on a given axis, reset to FLT_MAX. ImGuiID NavRootFocusScopeId; // Focus Scope ID at the time of Begin() int MemoryDrawListIdxCapacity; // Backup of last idx/vtx count, so when waking up the window we can preallocate and avoid iterative alloc/copy int MemoryDrawListVtxCapacity; bool MemoryCompacted; // Set when window extraneous data have been garbage collected public: ImGuiWindow(ImGuiContext* context, const char* name); ~ImGuiWindow(); ImGuiID GetID(const char* str, const char* str_end = NULL); ImGuiID GetID(const void* ptr); ImGuiID GetID(int n); ImGuiID GetIDFromRectangle(const ImRect& r_abs); // We don't use g.FontSize because the window may be != g.CurrentWindow. ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); } float CalcFontSize() const { ImGuiContext& g = *Ctx; float scale = g.FontBaseSize * FontWindowScale; if (ParentWindow) scale *= ParentWindow->FontWindowScale; return scale; } float TitleBarHeight() const { ImGuiContext& g = *Ctx; return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + g.Style.FramePadding.y * 2.0f; } ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); } float MenuBarHeight() const { ImGuiContext& g = *Ctx; return (Flags & ImGuiWindowFlags_MenuBar) ? DC.MenuBarOffset.y + CalcFontSize() + g.Style.FramePadding.y * 2.0f : 0.0f; } ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); } }; //----------------------------------------------------------------------------- // [SECTION] Tab bar, Tab item support //----------------------------------------------------------------------------- // Extend ImGuiTabBarFlags_ enum ImGuiTabBarFlagsPrivate_ { ImGuiTabBarFlags_DockNode = 1 << 20, // Part of a dock node [we don't use this in the master branch but it facilitate branch syncing to keep this around] ImGuiTabBarFlags_IsFocused = 1 << 21, ImGuiTabBarFlags_SaveSettings = 1 << 22, // FIXME: Settings are handled by the docking system, this only request the tab bar to mark settings dirty when reordering tabs }; // Extend ImGuiTabItemFlags_ enum ImGuiTabItemFlagsPrivate_ { ImGuiTabItemFlags_SectionMask_ = ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing, ImGuiTabItemFlags_NoCloseButton = 1 << 20, // Track whether p_open was set or not (we'll need this info on the next frame to recompute ContentWidth during layout) ImGuiTabItemFlags_Button = 1 << 21, // Used by TabItemButton, change the tab item behavior to mimic a button }; // Storage for one active tab item (sizeof() 40 bytes) struct ImGuiTabItem { ImGuiID ID; ImGuiTabItemFlags Flags; int LastFrameVisible; int LastFrameSelected; // This allows us to infer an ordered list of the last activated tabs with little maintenance float Offset; // Position relative to beginning of tab float Width; // Width currently displayed float ContentWidth; // Width of label, stored during BeginTabItem() call float RequestedWidth; // Width optionally requested by caller, -1.0f is unused ImS32 NameOffset; // When Window==NULL, offset to name within parent ImGuiTabBar::TabsNames ImS16 BeginOrder; // BeginTabItem() order, used to re-order tabs after toggling ImGuiTabBarFlags_Reorderable ImS16 IndexDuringLayout; // Index only used during TabBarLayout(). Tabs gets reordered so 'Tabs[n].IndexDuringLayout == n' but may mismatch during additions. bool WantClose; // Marked as closed by SetTabItemClosed() ImGuiTabItem() { memset(this, 0, sizeof(*this)); LastFrameVisible = LastFrameSelected = -1; RequestedWidth = -1.0f; NameOffset = -1; BeginOrder = IndexDuringLayout = -1; } }; // Storage for a tab bar (sizeof() 152 bytes) struct IMGUI_API ImGuiTabBar { ImVector Tabs; ImGuiTabBarFlags Flags; ImGuiID ID; // Zero for tab-bars used by docking ImGuiID SelectedTabId; // Selected tab/window ImGuiID NextSelectedTabId; // Next selected tab/window. Will also trigger a scrolling animation ImGuiID VisibleTabId; // Can occasionally be != SelectedTabId (e.g. when previewing contents for CTRL+TAB preview) int CurrFrameVisible; int PrevFrameVisible; ImRect BarRect; float CurrTabsContentsHeight; float PrevTabsContentsHeight; // Record the height of contents submitted below the tab bar float WidthAllTabs; // Actual width of all tabs (locked during layout) float WidthAllTabsIdeal; // Ideal width if all tabs were visible and not clipped float ScrollingAnim; float ScrollingTarget; float ScrollingTargetDistToVisibility; float ScrollingSpeed; float ScrollingRectMinX; float ScrollingRectMaxX; float SeparatorMinX; float SeparatorMaxX; ImGuiID ReorderRequestTabId; ImS16 ReorderRequestOffset; ImS8 BeginCount; bool WantLayout; bool VisibleTabWasSubmitted; bool TabsAddedNew; // Set to true when a new tab item or button has been added to the tab bar during last frame ImS16 TabsActiveCount; // Number of tabs submitted this frame. ImS16 LastTabItemIdx; // Index of last BeginTabItem() tab for use by EndTabItem() float ItemSpacingY; ImVec2 FramePadding; // style.FramePadding locked at the time of BeginTabBar() ImVec2 BackupCursorPos; ImGuiTextBuffer TabsNames; // For non-docking tab bar we re-append names in a contiguous buffer. ImGuiTabBar(); }; //----------------------------------------------------------------------------- // [SECTION] Table support //----------------------------------------------------------------------------- #define IM_COL32_DISABLE IM_COL32(0,0,0,1) // Special sentinel code which cannot be used as a regular color. #define IMGUI_TABLE_MAX_COLUMNS 512 // May be further lifted // Our current column maximum is 64 but we may raise that in the future. typedef ImS16 ImGuiTableColumnIdx; typedef ImU16 ImGuiTableDrawChannelIdx; // [Internal] sizeof() ~ 112 // We use the terminology "Enabled" to refer to a column that is not Hidden by user/api. // We use the terminology "Clipped" to refer to a column that is out of sight because of scrolling/clipping. // This is in contrast with some user-facing api such as IsItemVisible() / IsRectVisible() which use "Visible" to mean "not clipped". struct ImGuiTableColumn { ImGuiTableColumnFlags Flags; // Flags after some patching (not directly same as provided by user). See ImGuiTableColumnFlags_ float WidthGiven; // Final/actual width visible == (MaxX - MinX), locked in TableUpdateLayout(). May be > WidthRequest to honor minimum width, may be < WidthRequest to honor shrinking columns down in tight space. float MinX; // Absolute positions float MaxX; float WidthRequest; // Master width absolute value when !(Flags & _WidthStretch). When Stretch this is derived every frame from StretchWeight in TableUpdateLayout() float WidthAuto; // Automatic width float StretchWeight; // Master width weight when (Flags & _WidthStretch). Often around ~1.0f initially. float InitStretchWeightOrWidth; // Value passed to TableSetupColumn(). For Width it is a content width (_without padding_). ImRect ClipRect; // Clipping rectangle for the column ImGuiID UserID; // Optional, value passed to TableSetupColumn() float WorkMinX; // Contents region min ~(MinX + CellPaddingX + CellSpacingX1) == cursor start position when entering column float WorkMaxX; // Contents region max ~(MaxX - CellPaddingX - CellSpacingX2) float ItemWidth; // Current item width for the column, preserved across rows float ContentMaxXFrozen; // Contents maximum position for frozen rows (apart from headers), from which we can infer content width. float ContentMaxXUnfrozen; float ContentMaxXHeadersUsed; // Contents maximum position for headers rows (regardless of freezing). TableHeader() automatically softclip itself + report ideal desired size, to avoid creating extraneous draw calls float ContentMaxXHeadersIdeal; ImS16 NameOffset; // Offset into parent ColumnsNames[] ImGuiTableColumnIdx DisplayOrder; // Index within Table's IndexToDisplayOrder[] (column may be reordered by users) ImGuiTableColumnIdx IndexWithinEnabledSet; // Index within enabled/visible set (<= IndexToDisplayOrder) ImGuiTableColumnIdx PrevEnabledColumn; // Index of prev enabled/visible column within Columns[], -1 if first enabled/visible column ImGuiTableColumnIdx NextEnabledColumn; // Index of next enabled/visible column within Columns[], -1 if last enabled/visible column ImGuiTableColumnIdx SortOrder; // Index of this column within sort specs, -1 if not sorting on this column, 0 for single-sort, may be >0 on multi-sort ImGuiTableDrawChannelIdx DrawChannelCurrent; // Index within DrawSplitter.Channels[] ImGuiTableDrawChannelIdx DrawChannelFrozen; // Draw channels for frozen rows (often headers) ImGuiTableDrawChannelIdx DrawChannelUnfrozen; // Draw channels for unfrozen rows bool IsEnabled; // IsUserEnabled && (Flags & ImGuiTableColumnFlags_Disabled) == 0 bool IsUserEnabled; // Is the column not marked Hidden by the user? (unrelated to being off view, e.g. clipped by scrolling). bool IsUserEnabledNextFrame; bool IsVisibleX; // Is actually in view (e.g. overlapping the host window clipping rectangle, not scrolled). bool IsVisibleY; bool IsRequestOutput; // Return value for TableSetColumnIndex() / TableNextColumn(): whether we request user to output contents or not. bool IsSkipItems; // Do we want item submissions to this column to be completely ignored (no layout will happen). bool IsPreserveWidthAuto; ImS8 NavLayerCurrent; // ImGuiNavLayer in 1 byte ImU8 AutoFitQueue; // Queue of 8 values for the next 8 frames to request auto-fit ImU8 CannotSkipItemsQueue; // Queue of 8 values for the next 8 frames to disable Clipped/SkipItem ImU8 SortDirection : 2; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending ImU8 SortDirectionsAvailCount : 2; // Number of available sort directions (0 to 3) ImU8 SortDirectionsAvailMask : 4; // Mask of available sort directions (1-bit each) ImU8 SortDirectionsAvailList; // Ordered list of available sort directions (2-bits each, total 8-bits) ImGuiTableColumn() { memset(this, 0, sizeof(*this)); StretchWeight = WidthRequest = -1.0f; NameOffset = -1; DisplayOrder = IndexWithinEnabledSet = -1; PrevEnabledColumn = NextEnabledColumn = -1; SortOrder = -1; SortDirection = ImGuiSortDirection_None; DrawChannelCurrent = DrawChannelFrozen = DrawChannelUnfrozen = (ImU8)-1; } }; // Transient cell data stored per row. // sizeof() ~ 6 struct ImGuiTableCellData { ImU32 BgColor; // Actual color ImGuiTableColumnIdx Column; // Column number }; // Per-instance data that needs preserving across frames (seemingly most others do not need to be preserved aside from debug needs. Does that means they could be moved to ImGuiTableTempData?) // sizeof() ~ 24 bytes struct ImGuiTableInstanceData { ImGuiID TableInstanceID; float LastOuterHeight; // Outer height from last frame float LastTopHeadersRowHeight; // Height of first consecutive header rows from last frame (FIXME: this is used assuming consecutive headers are in same frozen set) float LastFrozenHeight; // Height of frozen section from last frame int HoveredRowLast; // Index of row which was hovered last frame. int HoveredRowNext; // Index of row hovered this frame, set after encountering it. ImGuiTableInstanceData() { TableInstanceID = 0; LastOuterHeight = LastTopHeadersRowHeight = LastFrozenHeight = 0.0f; HoveredRowLast = HoveredRowNext = -1; } }; // FIXME-TABLE: more transient data could be stored in a stacked ImGuiTableTempData: e.g. SortSpecs, incoming RowData // sizeof() ~ 580 bytes + heap allocs described in TableBeginInitMemory() struct IMGUI_API ImGuiTable { ImGuiID ID; ImGuiTableFlags Flags; void* RawData; // Single allocation to hold Columns[], DisplayOrderToIndex[] and RowCellData[] ImGuiTableTempData* TempData; // Transient data while table is active. Point within g.CurrentTableStack[] ImSpan Columns; // Point within RawData[] ImSpan DisplayOrderToIndex; // Point within RawData[]. Store display order of columns (when not reordered, the values are 0...Count-1) ImSpan RowCellData; // Point within RawData[]. Store cells background requests for current row. ImBitArrayPtr EnabledMaskByDisplayOrder; // Column DisplayOrder -> IsEnabled map ImBitArrayPtr EnabledMaskByIndex; // Column Index -> IsEnabled map (== not hidden by user/api) in a format adequate for iterating column without touching cold data ImBitArrayPtr VisibleMaskByIndex; // Column Index -> IsVisibleX|IsVisibleY map (== not hidden by user/api && not hidden by scrolling/cliprect) ImGuiTableFlags SettingsLoadedFlags; // Which data were loaded from the .ini file (e.g. when order is not altered we won't save order) int SettingsOffset; // Offset in g.SettingsTables int LastFrameActive; int ColumnsCount; // Number of columns declared in BeginTable() int CurrentRow; int CurrentColumn; ImS16 InstanceCurrent; // Count of BeginTable() calls with same ID in the same frame (generally 0). This is a little bit similar to BeginCount for a window, but multiple table with same ID look are multiple tables, they are just synched. ImS16 InstanceInteracted; // Mark which instance (generally 0) of the same ID is being interacted with float RowPosY1; float RowPosY2; float RowMinHeight; // Height submitted to TableNextRow() float RowCellPaddingY; // Top and bottom padding. Reloaded during row change. float RowTextBaseline; float RowIndentOffsetX; ImGuiTableRowFlags RowFlags : 16; // Current row flags, see ImGuiTableRowFlags_ ImGuiTableRowFlags LastRowFlags : 16; int RowBgColorCounter; // Counter for alternating background colors (can be fast-forwarded by e.g clipper), not same as CurrentRow because header rows typically don't increase this. ImU32 RowBgColor[2]; // Background color override for current row. ImU32 BorderColorStrong; ImU32 BorderColorLight; float BorderX1; float BorderX2; float HostIndentX; float MinColumnWidth; float OuterPaddingX; float CellPaddingX; // Padding from each borders. Locked in BeginTable()/Layout. float CellSpacingX1; // Spacing between non-bordered cells. Locked in BeginTable()/Layout. float CellSpacingX2; float InnerWidth; // User value passed to BeginTable(), see comments at the top of BeginTable() for details. float ColumnsGivenWidth; // Sum of current column width float ColumnsAutoFitWidth; // Sum of ideal column width in order nothing to be clipped, used for auto-fitting and content width submission in outer window float ColumnsStretchSumWeights; // Sum of weight of all enabled stretching columns float ResizedColumnNextWidth; float ResizeLockMinContentsX2; // Lock minimum contents width while resizing down in order to not create feedback loops. But we allow growing the table. float RefScale; // Reference scale to be able to rescale columns on font/dpi changes. float AngledHeadersHeight; // Set by TableAngledHeadersRow(), used in TableUpdateLayout() float AngledHeadersSlope; // Set by TableAngledHeadersRow(), used in TableUpdateLayout() ImRect OuterRect; // Note: for non-scrolling table, OuterRect.Max.y is often FLT_MAX until EndTable(), unless a height has been specified in BeginTable(). ImRect InnerRect; // InnerRect but without decoration. As with OuterRect, for non-scrolling tables, InnerRect.Max.y is ImRect WorkRect; ImRect InnerClipRect; ImRect BgClipRect; // We use this to cpu-clip cell background color fill, evolve during the frame as we cross frozen rows boundaries ImRect Bg0ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG0/1 channel. This tends to be == OuterWindow->ClipRect at BeginTable() because output in BG0/BG1 is cpu-clipped ImRect Bg2ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG2 channel. This tends to be a correct, tight-fit, because output to BG2 are done by widgets relying on regular ClipRect. ImRect HostClipRect; // This is used to check if we can eventually merge our columns draw calls into the current draw call of the current window. ImRect HostBackupInnerClipRect; // Backup of InnerWindow->ClipRect during PushTableBackground()/PopTableBackground() ImGuiWindow* OuterWindow; // Parent window for the table ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window) ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names ImDrawListSplitter* DrawSplitter; // Shortcut to TempData->DrawSplitter while in table. Isolate draw commands per columns to avoid switching clip rect constantly ImGuiTableInstanceData InstanceDataFirst; ImVector InstanceDataExtra; // FIXME-OPT: Using a small-vector pattern would be good. ImGuiTableColumnSortSpecs SortSpecsSingle; ImVector SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would be good. ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs() ImGuiTableColumnIdx SortSpecsCount; ImGuiTableColumnIdx ColumnsEnabledCount; // Number of enabled columns (<= ColumnsCount) ImGuiTableColumnIdx ColumnsEnabledFixedCount; // Number of enabled columns (<= ColumnsCount) ImGuiTableColumnIdx DeclColumnsCount; // Count calls to TableSetupColumn() ImGuiTableColumnIdx AngledHeadersCount; // Count columns with angled headers ImGuiTableColumnIdx HoveredColumnBody; // Index of column whose visible region is being hovered. Important: == ColumnsCount when hovering empty region after the right-most column! ImGuiTableColumnIdx HoveredColumnBorder; // Index of column whose right-border is being hovered (for resizing). ImGuiTableColumnIdx HighlightColumnHeader; // Index of column which should be highlighted. ImGuiTableColumnIdx AutoFitSingleColumn; // Index of single column requesting auto-fit. ImGuiTableColumnIdx ResizedColumn; // Index of column being resized. Reset when InstanceCurrent==0. ImGuiTableColumnIdx LastResizedColumn; // Index of column being resized from previous frame. ImGuiTableColumnIdx HeldHeaderColumn; // Index of column header being held. ImGuiTableColumnIdx ReorderColumn; // Index of column being reordered. (not cleared) ImGuiTableColumnIdx ReorderColumnDir; // -1 or +1 ImGuiTableColumnIdx LeftMostEnabledColumn; // Index of left-most non-hidden column. ImGuiTableColumnIdx RightMostEnabledColumn; // Index of right-most non-hidden column. ImGuiTableColumnIdx LeftMostStretchedColumn; // Index of left-most stretched column. ImGuiTableColumnIdx RightMostStretchedColumn; // Index of right-most stretched column. ImGuiTableColumnIdx ContextPopupColumn; // Column right-clicked on, of -1 if opening context menu from a neutral/empty spot ImGuiTableColumnIdx FreezeRowsRequest; // Requested frozen rows count ImGuiTableColumnIdx FreezeRowsCount; // Actual frozen row count (== FreezeRowsRequest, or == 0 when no scrolling offset) ImGuiTableColumnIdx FreezeColumnsRequest; // Requested frozen columns count ImGuiTableColumnIdx FreezeColumnsCount; // Actual frozen columns count (== FreezeColumnsRequest, or == 0 when no scrolling offset) ImGuiTableColumnIdx RowCellDataCurrent; // Index of current RowCellData[] entry in current row ImGuiTableDrawChannelIdx DummyDrawChannel; // Redirect non-visible columns here. ImGuiTableDrawChannelIdx Bg2DrawChannelCurrent; // For Selectable() and other widgets drawing across columns after the freezing line. Index within DrawSplitter.Channels[] ImGuiTableDrawChannelIdx Bg2DrawChannelUnfrozen; bool IsLayoutLocked; // Set by TableUpdateLayout() which is called when beginning the first row. bool IsInsideRow; // Set when inside TableBeginRow()/TableEndRow(). bool IsInitializing; bool IsSortSpecsDirty; bool IsUsingHeaders; // Set when the first row had the ImGuiTableRowFlags_Headers flag. bool IsContextPopupOpen; // Set when default context menu is open (also see: ContextPopupColumn, InstanceInteracted). bool DisableDefaultContextMenu; // Disable default context menu contents. You may submit your own using TableBeginContextMenuPopup()/EndPopup() bool IsSettingsRequestLoad; bool IsSettingsDirty; // Set when table settings have changed and needs to be reported into ImGuiTableSetttings data. bool IsDefaultDisplayOrder; // Set when display order is unchanged from default (DisplayOrder contains 0...Count-1) bool IsResetAllRequest; bool IsResetDisplayOrderRequest; bool IsUnfrozenRows; // Set when we got past the frozen row. bool IsDefaultSizingPolicy; // Set if user didn't explicitly set a sizing policy in BeginTable() bool IsActiveIdAliveBeforeTable; bool IsActiveIdInTable; bool HasScrollbarYCurr; // Whether ANY instance of this table had a vertical scrollbar during the current frame. bool HasScrollbarYPrev; // Whether ANY instance of this table had a vertical scrollbar during the previous. bool MemoryCompacted; bool HostSkipItems; // Backup of InnerWindow->SkipItem at the end of BeginTable(), because we will overwrite InnerWindow->SkipItem on a per-column basis ImGuiTable() { memset(this, 0, sizeof(*this)); LastFrameActive = -1; } ~ImGuiTable() { IM_FREE(RawData); } }; // Transient data that are only needed between BeginTable() and EndTable(), those buffers are shared (1 per level of stacked table). // - Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure. // - We also leave out of this structure data that tend to be particularly useful for debugging/metrics. // sizeof() ~ 120 bytes. struct IMGUI_API ImGuiTableTempData { int TableIndex; // Index in g.Tables.Buf[] pool float LastTimeActive; // Last timestamp this structure was used float AngledheadersExtraWidth; // Used in EndTable() ImVec2 UserOuterSize; // outer_size.x passed to BeginTable() ImDrawListSplitter DrawSplitter; ImRect HostBackupWorkRect; // Backup of InnerWindow->WorkRect at the end of BeginTable() ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable() ImVec2 HostBackupPrevLineSize; // Backup of InnerWindow->DC.PrevLineSize at the end of BeginTable() ImVec2 HostBackupCurrLineSize; // Backup of InnerWindow->DC.CurrLineSize at the end of BeginTable() ImVec2 HostBackupCursorMaxPos; // Backup of InnerWindow->DC.CursorMaxPos at the end of BeginTable() ImVec1 HostBackupColumnsOffset; // Backup of OuterWindow->DC.ColumnsOffset at the end of BeginTable() float HostBackupItemWidth; // Backup of OuterWindow->DC.ItemWidth at the end of BeginTable() int HostBackupItemWidthStackSize;//Backup of OuterWindow->DC.ItemWidthStack.Size at the end of BeginTable() ImGuiTableTempData() { memset(this, 0, sizeof(*this)); LastTimeActive = -1.0f; } }; // sizeof() ~ 12 struct ImGuiTableColumnSettings { float WidthOrWeight; ImGuiID UserID; ImGuiTableColumnIdx Index; ImGuiTableColumnIdx DisplayOrder; ImGuiTableColumnIdx SortOrder; ImU8 SortDirection : 2; ImU8 IsEnabled : 1; // "Visible" in ini file ImU8 IsStretch : 1; ImGuiTableColumnSettings() { WidthOrWeight = 0.0f; UserID = 0; Index = -1; DisplayOrder = SortOrder = -1; SortDirection = ImGuiSortDirection_None; IsEnabled = 1; IsStretch = 0; } }; // This is designed to be stored in a single ImChunkStream (1 header followed by N ImGuiTableColumnSettings, etc.) struct ImGuiTableSettings { ImGuiID ID; // Set to 0 to invalidate/delete the setting ImGuiTableFlags SaveFlags; // Indicate data we want to save using the Resizable/Reorderable/Sortable/Hideable flags (could be using its own flags..) float RefScale; // Reference scale to be able to rescale columns on font/dpi changes. ImGuiTableColumnIdx ColumnsCount; ImGuiTableColumnIdx ColumnsCountMax; // Maximum number of columns this settings instance can store, we can recycle a settings instance with lower number of columns but not higher bool WantApply; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context) ImGuiTableSettings() { memset(this, 0, sizeof(*this)); } ImGuiTableColumnSettings* GetColumnSettings() { return (ImGuiTableColumnSettings*)(this + 1); } }; //----------------------------------------------------------------------------- // [SECTION] ImGui internal API // No guarantee of forward compatibility here! //----------------------------------------------------------------------------- namespace ImGui { // Windows // We should always have a CurrentWindow in the stack (there is an implicit "Debug" window) // If this ever crash because g.CurrentWindow is NULL it means that either // - ImGui::NewFrame() has never been called, which is illegal. // - You are calling ImGui functions after ImGui::EndFrame()/ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal. inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; } inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; } IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id); IMGUI_API ImGuiWindow* FindWindowByName(const char* name); IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window); IMGUI_API ImVec2 CalcWindowNextAutoFitSize(ImGuiWindow* window); IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent, bool popup_hierarchy); IMGUI_API bool IsWindowWithinBeginStackOf(ImGuiWindow* window, ImGuiWindow* potential_parent); IMGUI_API bool IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below); IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window); IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0); IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0); IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0); IMGUI_API void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size); IMGUI_API void SetWindowHiddenAndSkipItemsForCurrentFrame(ImGuiWindow* window); inline void SetWindowParentWindowForFocusRoute(ImGuiWindow* window, ImGuiWindow* parent_window) { window->ParentWindowForFocusRoute = parent_window; } inline ImRect WindowRectAbsToRel(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x - off.x, r.Min.y - off.y, r.Max.x - off.x, r.Max.y - off.y); } inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); } inline ImVec2 WindowPosRelToAbs(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x + off.x, p.y + off.y); } // Windows: Display Order and Focus Order IMGUI_API void FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags = 0); IMGUI_API void FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window, ImGuiViewport* filter_viewport, ImGuiFocusRequestFlags flags); IMGUI_API void BringWindowToFocusFront(ImGuiWindow* window); IMGUI_API void BringWindowToDisplayFront(ImGuiWindow* window); IMGUI_API void BringWindowToDisplayBack(ImGuiWindow* window); IMGUI_API void BringWindowToDisplayBehind(ImGuiWindow* window, ImGuiWindow* above_window); IMGUI_API int FindWindowDisplayIndex(ImGuiWindow* window); IMGUI_API ImGuiWindow* FindBottomMostVisibleWindowWithinBeginStack(ImGuiWindow* window); // Fonts, drawing IMGUI_API void SetCurrentFont(ImFont* font); inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; } inline ImDrawList* GetForegroundDrawList(ImGuiWindow* window) { IM_UNUSED(window); return GetForegroundDrawList(); } // This seemingly unnecessary wrapper simplifies compatibility between the 'master' and 'docking' branches. IMGUI_API ImDrawList* GetBackgroundDrawList(ImGuiViewport* viewport); // get background draw list for the given viewport. this draw list will be the first rendering one. Useful to quickly draw shapes/text behind dear imgui contents. IMGUI_API ImDrawList* GetForegroundDrawList(ImGuiViewport* viewport); // get foreground draw list for the given viewport. this draw list will be the last rendered one. Useful to quickly draw shapes/text over dear imgui contents. IMGUI_API void AddDrawListToDrawDataEx(ImDrawData* draw_data, ImVector* out_list, ImDrawList* draw_list); // Init IMGUI_API void Initialize(); IMGUI_API void Shutdown(); // Since 1.60 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext(). // NewFrame IMGUI_API void UpdateInputEvents(bool trickle_fast_inputs); IMGUI_API void UpdateHoveredWindowAndCaptureFlags(); IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window); IMGUI_API void UpdateMouseMovingWindowNewFrame(); IMGUI_API void UpdateMouseMovingWindowEndFrame(); // Generic context hooks IMGUI_API ImGuiID AddContextHook(ImGuiContext* context, const ImGuiContextHook* hook); IMGUI_API void RemoveContextHook(ImGuiContext* context, ImGuiID hook_to_remove); IMGUI_API void CallContextHooks(ImGuiContext* context, ImGuiContextHookType type); // Viewports IMGUI_API void SetWindowViewport(ImGuiWindow* window, ImGuiViewportP* viewport); // Settings IMGUI_API void MarkIniSettingsDirty(); IMGUI_API void MarkIniSettingsDirty(ImGuiWindow* window); IMGUI_API void ClearIniSettings(); IMGUI_API void AddSettingsHandler(const ImGuiSettingsHandler* handler); IMGUI_API void RemoveSettingsHandler(const char* type_name); IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name); // Settings - Windows IMGUI_API ImGuiWindowSettings* CreateNewWindowSettings(const char* name); IMGUI_API ImGuiWindowSettings* FindWindowSettingsByID(ImGuiID id); IMGUI_API ImGuiWindowSettings* FindWindowSettingsByWindow(ImGuiWindow* window); IMGUI_API void ClearWindowSettings(const char* name); // Localization IMGUI_API void LocalizeRegisterEntries(const ImGuiLocEntry* entries, int count); inline const char* LocalizeGetMsg(ImGuiLocKey key) { ImGuiContext& g = *GImGui; const char* msg = g.LocalizationTable[key]; return msg ? msg : "*Missing Text*"; } // Scrolling IMGUI_API void SetScrollX(ImGuiWindow* window, float scroll_x); IMGUI_API void SetScrollY(ImGuiWindow* window, float scroll_y); IMGUI_API void SetScrollFromPosX(ImGuiWindow* window, float local_x, float center_x_ratio); IMGUI_API void SetScrollFromPosY(ImGuiWindow* window, float local_y, float center_y_ratio); // Early work-in-progress API (ScrollToItem() will become public) IMGUI_API void ScrollToItem(ImGuiScrollFlags flags = 0); IMGUI_API void ScrollToRect(ImGuiWindow* window, const ImRect& rect, ImGuiScrollFlags flags = 0); IMGUI_API ImVec2 ScrollToRectEx(ImGuiWindow* window, const ImRect& rect, ImGuiScrollFlags flags = 0); //#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS inline void ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& rect) { ScrollToRect(window, rect, ImGuiScrollFlags_KeepVisibleEdgeY); } //#endif // Basic Accessors inline ImGuiItemStatusFlags GetItemStatusFlags(){ ImGuiContext& g = *GImGui; return g.LastItemData.StatusFlags; } inline ImGuiItemFlags GetItemFlags() { ImGuiContext& g = *GImGui; return g.LastItemData.InFlags; } inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; } inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; } IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window); IMGUI_API void ClearActiveID(); IMGUI_API ImGuiID GetHoveredID(); IMGUI_API void SetHoveredID(ImGuiID id); IMGUI_API void KeepAliveID(ImGuiID id); IMGUI_API void MarkItemEdited(ImGuiID id); // Mark data associated to given item as "edited", used by IsItemDeactivatedAfterEdit() function. IMGUI_API void PushOverrideID(ImGuiID id); // Push given value as-is at the top of the ID stack (whereas PushID combines old and new hashes) IMGUI_API ImGuiID GetIDWithSeed(const char* str_id_begin, const char* str_id_end, ImGuiID seed); IMGUI_API ImGuiID GetIDWithSeed(int n, ImGuiID seed); // Basic Helpers for widget code IMGUI_API void ItemSize(const ImVec2& size, float text_baseline_y = -1.0f); inline void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f) { ItemSize(bb.GetSize(), text_baseline_y); } // FIXME: This is a misleading API since we expect CursorPos to be bb.Min. IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL, ImGuiItemFlags extra_flags = 0); IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flags); IMGUI_API bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags = 0); IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id); IMGUI_API void SetLastItemData(ImGuiID item_id, ImGuiItemFlags in_flags, ImGuiItemStatusFlags status_flags, const ImRect& item_rect); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); IMGUI_API void PushMultiItemsWidths(int components, float width_full); IMGUI_API bool IsItemToggledSelection(); // Was the last item selection toggled? (after Selectable(), TreeNode() etc. We only returns toggle _event_ in order to handle clipping correctly) IMGUI_API ImVec2 GetContentRegionMaxAbs(); IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess); // Parameter stacks (shared) IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); IMGUI_API void PopItemFlag(); IMGUI_API const ImGuiDataVarInfo* GetStyleVarInfo(ImGuiStyleVar idx); // Logging/Capture IMGUI_API void LogBegin(ImGuiLogType type, int auto_open_depth); // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name. IMGUI_API void LogToBuffer(int auto_open_depth = -1); // Start logging/capturing to internal buffer IMGUI_API void LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end = NULL); IMGUI_API void LogSetNextTextDecoration(const char* prefix, const char* suffix); // Popups, Modals, Tooltips IMGUI_API bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags); IMGUI_API void OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags = ImGuiPopupFlags_None); IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup); IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup); IMGUI_API void ClosePopupsExceptModals(); IMGUI_API bool IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags); IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags); IMGUI_API bool BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags); IMGUI_API bool BeginTooltipHidden(); IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window); IMGUI_API ImGuiWindow* GetTopMostPopupModal(); IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal(); IMGUI_API ImGuiWindow* FindBlockingModal(ImGuiWindow* window); IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window); IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy); // Menus IMGUI_API bool BeginViewportSideBar(const char* name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags); IMGUI_API bool BeginMenuEx(const char* label, const char* icon, bool enabled = true); IMGUI_API bool MenuItemEx(const char* label, const char* icon, const char* shortcut = NULL, bool selected = false, bool enabled = true); // Combos IMGUI_API bool BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags); IMGUI_API bool BeginComboPreview(); IMGUI_API void EndComboPreview(); // Gamepad/Keyboard Navigation IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit); IMGUI_API void NavInitRequestApplyResult(); IMGUI_API bool NavMoveRequestButNoResultYet(); IMGUI_API void NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags); IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags); IMGUI_API void NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result); IMGUI_API void NavMoveRequestResolveWithPastTreeNode(ImGuiNavItemData* result, ImGuiNavTreeNodeData* tree_node_data); IMGUI_API void NavMoveRequestCancel(); IMGUI_API void NavMoveRequestApplyResult(); IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags); IMGUI_API void NavHighlightActivated(ImGuiID id); IMGUI_API void NavClearPreferredPosForAxis(ImGuiAxis axis); IMGUI_API void NavRestoreHighlightAfterMove(); IMGUI_API void NavUpdateCurrentWindowIsScrollPushableX(); IMGUI_API void SetNavWindow(ImGuiWindow* window); IMGUI_API void SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel); IMGUI_API void SetNavFocusScope(ImGuiID focus_scope_id); // Focus/Activation // This should be part of a larger set of API: FocusItem(offset = -1), FocusItemByID(id), ActivateItem(offset = -1), ActivateItemByID(id) etc. which are // much harder to design and implement than expected. I have a couple of private branches on this matter but it's not simple. For now implementing the easy ones. IMGUI_API void FocusItem(); // Focus last item (no selection/activation). IMGUI_API void ActivateItemByID(ImGuiID id); // Activate an item by ID (button, checkbox, tree node etc.). Activation is queued and processed on the next frame when the item is encountered again. // Inputs // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions. inline bool IsNamedKey(ImGuiKey key) { return key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END; } inline bool IsNamedKeyOrModKey(ImGuiKey key) { return (key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END) || key == ImGuiMod_Ctrl || key == ImGuiMod_Shift || key == ImGuiMod_Alt || key == ImGuiMod_Super || key == ImGuiMod_Shortcut; } inline bool IsLegacyKey(ImGuiKey key) { return key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_LegacyNativeKey_END; } inline bool IsKeyboardKey(ImGuiKey key) { return key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END; } inline bool IsGamepadKey(ImGuiKey key) { return key >= ImGuiKey_Gamepad_BEGIN && key < ImGuiKey_Gamepad_END; } inline bool IsMouseKey(ImGuiKey key) { return key >= ImGuiKey_Mouse_BEGIN && key < ImGuiKey_Mouse_END; } inline bool IsAliasKey(ImGuiKey key) { return key >= ImGuiKey_Aliases_BEGIN && key < ImGuiKey_Aliases_END; } inline bool IsModKey(ImGuiKey key) { return key >= ImGuiKey_LeftCtrl && key <= ImGuiKey_RightSuper; } ImGuiKeyChord FixupKeyChord(ImGuiContext* ctx, ImGuiKeyChord key_chord); inline ImGuiKey ConvertSingleModFlagToKey(ImGuiContext* ctx, ImGuiKey key) { ImGuiContext& g = *ctx; if (key == ImGuiMod_Ctrl) return ImGuiKey_ReservedForModCtrl; if (key == ImGuiMod_Shift) return ImGuiKey_ReservedForModShift; if (key == ImGuiMod_Alt) return ImGuiKey_ReservedForModAlt; if (key == ImGuiMod_Super) return ImGuiKey_ReservedForModSuper; if (key == ImGuiMod_Shortcut) return (g.IO.ConfigMacOSXBehaviors ? ImGuiKey_ReservedForModSuper : ImGuiKey_ReservedForModCtrl); return key; } IMGUI_API ImGuiKeyData* GetKeyData(ImGuiContext* ctx, ImGuiKey key); inline ImGuiKeyData* GetKeyData(ImGuiKey key) { ImGuiContext& g = *GImGui; return GetKeyData(&g, key); } IMGUI_API const char* GetKeyChordName(ImGuiKeyChord key_chord); inline ImGuiKey MouseButtonToKey(ImGuiMouseButton button) { IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT); return (ImGuiKey)(ImGuiKey_MouseLeft + button); } IMGUI_API bool IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_threshold = -1.0f); IMGUI_API ImVec2 GetKeyMagnitude2d(ImGuiKey key_left, ImGuiKey key_right, ImGuiKey key_up, ImGuiKey key_down); IMGUI_API float GetNavTweakPressedAmount(ImGuiAxis axis); IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate); IMGUI_API void GetTypematicRepeatRate(ImGuiInputFlags flags, float* repeat_delay, float* repeat_rate); IMGUI_API void TeleportMousePos(const ImVec2& pos); IMGUI_API void SetActiveIdUsingAllKeyboardKeys(); inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; } // [EXPERIMENTAL] Low-Level: Key/Input Ownership // - The idea is that instead of "eating" a given input, we can link to an owner id. // - Ownership is most often claimed as a result of reacting to a press/down event (but occasionally may be claimed ahead). // - Input queries can then read input by specifying ImGuiKeyOwner_Any (== 0), ImGuiKeyOwner_None (== -1) or a custom ID. // - Legacy input queries (without specifying an owner or _Any or _None) are equivalent to using ImGuiKeyOwner_Any (== 0). // - Input ownership is automatically released on the frame after a key is released. Therefore: // - for ownership registration happening as a result of a down/press event, the SetKeyOwner() call may be done once (common case). // - for ownership registration happening ahead of a down/press event, the SetKeyOwner() call needs to be made every frame (happens if e.g. claiming ownership on hover). // - SetItemKeyOwner() is a shortcut for common simple case. A custom widget will probably want to call SetKeyOwner() multiple times directly based on its interaction state. // - This is marked experimental because not all widgets are fully honoring the Set/Test idioms. We will need to move forward step by step. // Please open a GitHub Issue to submit your usage scenario or if there's a use case you need solved. IMGUI_API ImGuiID GetKeyOwner(ImGuiKey key); IMGUI_API void SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags = 0); IMGUI_API void SetKeyOwnersForKeyChord(ImGuiKeyChord key, ImGuiID owner_id, ImGuiInputFlags flags = 0); IMGUI_API void SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags = 0); // Set key owner to last item if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'. IMGUI_API bool TestKeyOwner(ImGuiKey key, ImGuiID owner_id); // Test that key is either not owned, either owned by 'owner_id' inline ImGuiKeyOwnerData* GetKeyOwnerData(ImGuiContext* ctx, ImGuiKey key) { if (key & ImGuiMod_Mask_) key = ConvertSingleModFlagToKey(ctx, key); IM_ASSERT(IsNamedKey(key)); return &ctx->KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN]; } // [EXPERIMENTAL] High-Level: Input Access functions w/ support for Key/Input Ownership // - Important: legacy IsKeyPressed(ImGuiKey, bool repeat=true) _DEFAULTS_ to repeat, new IsKeyPressed() requires _EXPLICIT_ ImGuiInputFlags_Repeat flag. // - Expected to be later promoted to public API, the prototypes are designed to replace existing ones (since owner_id can default to Any == 0) // - Specifying a value for 'ImGuiID owner' will test that EITHER the key is NOT owned (UNLESS locked), EITHER the key is owned by 'owner'. // Legacy functions use ImGuiKeyOwner_Any meaning that they typically ignore ownership, unless a call to SetKeyOwner() explicitly used ImGuiInputFlags_LockThisFrame or ImGuiInputFlags_LockUntilRelease. // - Binding generators may want to ignore those for now, or suffix them with Ex() until we decide if this gets moved into public API. IMGUI_API bool IsKeyDown(ImGuiKey key, ImGuiID owner_id); IMGUI_API bool IsKeyPressed(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags = 0); // Important: when transitioning from old to new IsKeyPressed(): old API has "bool repeat = true", so would default to repeat. New API requiress explicit ImGuiInputFlags_Repeat. IMGUI_API bool IsKeyReleased(ImGuiKey key, ImGuiID owner_id); IMGUI_API bool IsMouseDown(ImGuiMouseButton button, ImGuiID owner_id); IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, ImGuiID owner_id, ImGuiInputFlags flags = 0); IMGUI_API bool IsMouseReleased(ImGuiMouseButton button, ImGuiID owner_id); IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button, ImGuiID owner_id); // [EXPERIMENTAL] Shortcut Routing // - ImGuiKeyChord = a ImGuiKey optionally OR-red with ImGuiMod_Alt/ImGuiMod_Ctrl/ImGuiMod_Shift/ImGuiMod_Super. // ImGuiKey_C (accepted by functions taking ImGuiKey or ImGuiKeyChord) // ImGuiKey_C | ImGuiMod_Ctrl (accepted by functions taking ImGuiKeyChord) // ONLY ImGuiMod_XXX values are legal to 'OR' with an ImGuiKey. You CANNOT 'OR' two ImGuiKey values. // - When using one of the routing flags (e.g. ImGuiInputFlags_RouteFocused): routes requested ahead of time given a chord (key + modifiers) and a routing policy. // - Routes are resolved during NewFrame(): if keyboard modifiers are matching current ones: SetKeyOwner() is called + route is granted for the frame. // - Route is granted to a single owner. When multiple requests are made we have policies to select the winning route. // - Multiple read sites may use the same owner id and will all get the granted route. // - For routing: when owner_id is 0 we use the current Focus Scope ID as a default owner in order to identify our location. // - TL;DR; // - IsKeyChordPressed() compares mods + call IsKeyPressed() -> function has no side-effect. // - Shortcut() submits a route then if currently can be routed calls IsKeyChordPressed() -> function has (desirable) side-effects. IMGUI_API bool IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags = 0); IMGUI_API void SetNextItemShortcut(ImGuiKeyChord key_chord); IMGUI_API bool Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id = 0, ImGuiInputFlags flags = 0); IMGUI_API bool SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags = 0); // owner_id needs to be explicit and cannot be 0 IMGUI_API bool TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id); IMGUI_API ImGuiKeyRoutingData* GetShortcutRoutingData(ImGuiKeyChord key_chord); // [EXPERIMENTAL] Focus Scope // This is generally used to identify a unique input location (for e.g. a selection set) // There is one per window (automatically set in Begin), but: // - Selection patterns generally need to react (e.g. clear a selection) when landing on one item of the set. // So in order to identify a set multiple lists in same window may each need a focus scope. // If you imagine an hypothetical BeginSelectionGroup()/EndSelectionGroup() api, it would likely call PushFocusScope()/EndFocusScope() // - Shortcut routing also use focus scope as a default location identifier if an owner is not provided. // We don't use the ID Stack for this as it is common to want them separate. IMGUI_API void PushFocusScope(ImGuiID id); IMGUI_API void PopFocusScope(); inline ImGuiID GetCurrentFocusScope() { ImGuiContext& g = *GImGui; return g.CurrentFocusScopeId; } // Focus scope we are outputting into, set by PushFocusScope() // Drag and Drop IMGUI_API bool IsDragDropActive(); IMGUI_API bool BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id); IMGUI_API void ClearDragDrop(); IMGUI_API bool IsDragDropPayloadBeingAccepted(); IMGUI_API void RenderDragDropTargetRect(const ImRect& bb, const ImRect& item_clip_rect); // Typing-Select API IMGUI_API ImGuiTypingSelectRequest* GetTypingSelectRequest(ImGuiTypingSelectFlags flags = ImGuiTypingSelectFlags_None); IMGUI_API int TypingSelectFindMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx); IMGUI_API int TypingSelectFindNextSingleCharMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx); IMGUI_API int TypingSelectFindBestLeadingMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data); // Internal Columns API (this is not exposed because we will encourage transitioning to the Tables API) IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect); IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiOldColumnFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). IMGUI_API void EndColumns(); // close columns IMGUI_API void PushColumnClipRect(int column_index); IMGUI_API void PushColumnsBackground(); IMGUI_API void PopColumnsBackground(); IMGUI_API ImGuiID GetColumnsID(const char* str_id, int count); IMGUI_API ImGuiOldColumns* FindOrCreateColumns(ImGuiWindow* window, ImGuiID id); IMGUI_API float GetColumnOffsetFromNorm(const ImGuiOldColumns* columns, float offset_norm); IMGUI_API float GetColumnNormFromOffset(const ImGuiOldColumns* columns, float offset); // Tables: Candidates for public API IMGUI_API void TableOpenContextMenu(int column_n = -1); IMGUI_API void TableSetColumnWidth(int column_n, float width); IMGUI_API void TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_direction, bool append_to_sort_specs); IMGUI_API int TableGetHoveredColumn(); // May use (TableGetColumnFlags() & ImGuiTableColumnFlags_IsHovered) instead. Return hovered column. return -1 when table is not hovered. return columns_count if the unused space at the right of visible columns is hovered. IMGUI_API int TableGetHoveredRow(); // Retrieve *PREVIOUS FRAME* hovered row. This difference with TableGetHoveredColumn() is the reason why this is not public yet. IMGUI_API float TableGetHeaderRowHeight(); IMGUI_API float TableGetHeaderAngledMaxLabelWidth(); IMGUI_API void TablePushBackgroundChannel(); IMGUI_API void TablePopBackgroundChannel(); IMGUI_API void TableAngledHeadersRowEx(float angle, float label_width = 0.0f); // Tables: Internals inline ImGuiTable* GetCurrentTable() { ImGuiContext& g = *GImGui; return g.CurrentTable; } IMGUI_API ImGuiTable* TableFindByID(ImGuiID id); IMGUI_API bool BeginTableEx(const char* name, ImGuiID id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0, 0), float inner_width = 0.0f); IMGUI_API void TableBeginInitMemory(ImGuiTable* table, int columns_count); IMGUI_API void TableBeginApplyRequests(ImGuiTable* table); IMGUI_API void TableSetupDrawChannels(ImGuiTable* table); IMGUI_API void TableUpdateLayout(ImGuiTable* table); IMGUI_API void TableUpdateBorders(ImGuiTable* table); IMGUI_API void TableUpdateColumnsWeightFromWidth(ImGuiTable* table); IMGUI_API void TableDrawBorders(ImGuiTable* table); IMGUI_API void TableDrawDefaultContextMenu(ImGuiTable* table, ImGuiTableFlags flags_for_section_to_display); IMGUI_API bool TableBeginContextMenuPopup(ImGuiTable* table); IMGUI_API void TableMergeDrawChannels(ImGuiTable* table); inline ImGuiTableInstanceData* TableGetInstanceData(ImGuiTable* table, int instance_no) { if (instance_no == 0) return &table->InstanceDataFirst; return &table->InstanceDataExtra[instance_no - 1]; } inline ImGuiID TableGetInstanceID(ImGuiTable* table, int instance_no) { return TableGetInstanceData(table, instance_no)->TableInstanceID; } IMGUI_API void TableSortSpecsSanitize(ImGuiTable* table); IMGUI_API void TableSortSpecsBuild(ImGuiTable* table); IMGUI_API ImGuiSortDirection TableGetColumnNextSortDirection(ImGuiTableColumn* column); IMGUI_API void TableFixColumnSortDirection(ImGuiTable* table, ImGuiTableColumn* column); IMGUI_API float TableGetColumnWidthAuto(ImGuiTable* table, ImGuiTableColumn* column); IMGUI_API void TableBeginRow(ImGuiTable* table); IMGUI_API void TableEndRow(ImGuiTable* table); IMGUI_API void TableBeginCell(ImGuiTable* table, int column_n); IMGUI_API void TableEndCell(ImGuiTable* table); IMGUI_API ImRect TableGetCellBgRect(const ImGuiTable* table, int column_n); IMGUI_API const char* TableGetColumnName(const ImGuiTable* table, int column_n); IMGUI_API ImGuiID TableGetColumnResizeID(ImGuiTable* table, int column_n, int instance_no = 0); IMGUI_API float TableGetMaxColumnWidth(const ImGuiTable* table, int column_n); IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n); IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table); IMGUI_API void TableRemove(ImGuiTable* table); IMGUI_API void TableGcCompactTransientBuffers(ImGuiTable* table); IMGUI_API void TableGcCompactTransientBuffers(ImGuiTableTempData* table); IMGUI_API void TableGcCompactSettings(); // Tables: Settings IMGUI_API void TableLoadSettings(ImGuiTable* table); IMGUI_API void TableSaveSettings(ImGuiTable* table); IMGUI_API void TableResetSettings(ImGuiTable* table); IMGUI_API ImGuiTableSettings* TableGetBoundSettings(ImGuiTable* table); IMGUI_API void TableSettingsAddSettingsHandler(); IMGUI_API ImGuiTableSettings* TableSettingsCreate(ImGuiID id, int columns_count); IMGUI_API ImGuiTableSettings* TableSettingsFindByID(ImGuiID id); // Tab Bars inline ImGuiTabBar* GetCurrentTabBar() { ImGuiContext& g = *GImGui; return g.CurrentTabBar; } IMGUI_API bool BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags); IMGUI_API ImGuiTabItem* TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id); IMGUI_API ImGuiTabItem* TabBarFindTabByOrder(ImGuiTabBar* tab_bar, int order); IMGUI_API ImGuiTabItem* TabBarGetCurrentTab(ImGuiTabBar* tab_bar); inline int TabBarGetTabOrder(ImGuiTabBar* tab_bar, ImGuiTabItem* tab) { return tab_bar->Tabs.index_from_ptr(tab); } IMGUI_API const char* TabBarGetTabName(ImGuiTabBar* tab_bar, ImGuiTabItem* tab); IMGUI_API void TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id); IMGUI_API void TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab); IMGUI_API void TabBarQueueFocus(ImGuiTabBar* tab_bar, ImGuiTabItem* tab); IMGUI_API void TabBarQueueReorder(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, int offset); IMGUI_API void TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, ImVec2 mouse_pos); IMGUI_API bool TabBarProcessReorder(ImGuiTabBar* tab_bar); IMGUI_API bool TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags, ImGuiWindow* docked_window); IMGUI_API ImVec2 TabItemCalcSize(const char* label, bool has_close_button_or_unsaved_marker); IMGUI_API ImVec2 TabItemCalcSize(ImGuiWindow* window); IMGUI_API void TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImU32 col); IMGUI_API void TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char* label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped); // Render helpers // AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT. // NB: All position are in absolute pixels coordinates (we are never using window coordinates internally) IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width); IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL); IMGUI_API void RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL); IMGUI_API void RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end, const ImVec2* text_size_if_known); IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f); IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0); IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_None); // Navigation highlight IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. IMGUI_API void RenderMouseCursor(ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor, ImU32 col_fill, ImU32 col_border, ImU32 col_shadow); // Render helpers (those functions don't access any ImGui state!) IMGUI_API void RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale = 1.0f); IMGUI_API void RenderBullet(ImDrawList* draw_list, ImVec2 pos, ImU32 col); IMGUI_API void RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float sz); IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col); IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding); IMGUI_API void RenderRectFilledWithHole(ImDrawList* draw_list, const ImRect& outer, const ImRect& inner, ImU32 col, float rounding); // Widgets IMGUI_API void TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags flags = 0); IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0, 0), ImGuiButtonFlags flags = 0); IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0); IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags = 0); IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags, float thickness = 1.0f); IMGUI_API void SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_width); IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value); IMGUI_API bool CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value); // Widgets: Window Decorations IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos); IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2& pos); IMGUI_API void Scrollbar(ImGuiAxis axis); IMGUI_API bool ScrollbarEx(const ImRect& bb, ImGuiID id, ImGuiAxis axis, ImS64* p_scroll_v, ImS64 avail_v, ImS64 contents_v, ImDrawFlags flags); IMGUI_API ImRect GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis); IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis); IMGUI_API ImGuiID GetWindowResizeCornerID(ImGuiWindow* window, int n); // 0..3: corners IMGUI_API ImGuiID GetWindowResizeBorderID(ImGuiWindow* window, ImGuiDir dir); // Widgets low-level behaviors IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0); IMGUI_API bool DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags); IMGUI_API bool SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb); IMGUI_API bool SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f, float hover_visibility_delay = 0.0f, ImU32 bg_col = 0); IMGUI_API bool TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end = NULL); IMGUI_API void TreePushOverrideID(ImGuiID id); IMGUI_API void TreeNodeSetOpen(ImGuiID id, bool open); IMGUI_API bool TreeNodeUpdateNextOpen(ImGuiID id, ImGuiTreeNodeFlags flags); // Return open state. Consume previous SetNextItemOpen() data, if any. May return true when logging. IMGUI_API void SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_data); // Template functions are instantiated in imgui_widgets.cpp for a finite number of types. // To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036). // e.g. " extern template IMGUI_API float RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, float v); " template IMGUI_API float ScaleRatioFromValueT(ImGuiDataType data_type, T v, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size); template IMGUI_API T ScaleValueFromRatioT(ImGuiDataType data_type, float t, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size); template IMGUI_API bool DragBehaviorT(ImGuiDataType data_type, T* v, float v_speed, T v_min, T v_max, const char* format, ImGuiSliderFlags flags); template IMGUI_API bool SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, T* v, T v_min, T v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb); template IMGUI_API T RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, T v); template IMGUI_API bool CheckboxFlagsT(const char* label, T* flags, T flags_value); // Data type helpers IMGUI_API const ImGuiDataTypeInfo* DataTypeGetInfo(ImGuiDataType data_type); IMGUI_API int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format); IMGUI_API void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg_1, const void* arg_2); IMGUI_API bool DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void* p_data, const char* format); IMGUI_API int DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2); IMGUI_API bool DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max); // InputText IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API void InputTextDeactivateHook(ImGuiID id); IMGUI_API bool TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags); IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL); inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.ActiveId == id && g.TempInputId == id); } inline ImGuiInputTextState* GetInputTextState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.InputTextState.ID == id) ? &g.InputTextState : NULL; } // Get input text state if active // Color IMGUI_API void ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags); IMGUI_API void ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags); IMGUI_API void ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags); // Plot IMGUI_API int PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, const ImVec2& size_arg); // Shade functions (write over already created vertices) IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1); IMGUI_API void ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp); IMGUI_API void ShadeVertsTransformPos(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& pivot_in, float cos_a, float sin_a, const ImVec2& pivot_out); // Garbage collection IMGUI_API void GcCompactTransientMiscBuffers(); IMGUI_API void GcCompactTransientWindowBuffers(ImGuiWindow* window); IMGUI_API void GcAwakeTransientWindowBuffers(ImGuiWindow* window); // Debug Log IMGUI_API void DebugLog(const char* fmt, ...) IM_FMTARGS(1); IMGUI_API void DebugLogV(const char* fmt, va_list args) IM_FMTLIST(1); IMGUI_API void DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size); // size >= 0 : alloc, size = -1 : free // Debug Tools IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL); IMGUI_API void ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL); IMGUI_API void ErrorCheckUsingSetCursorPosToExtendParentBoundaries(); IMGUI_API void DebugDrawCursorPos(ImU32 col = IM_COL32(255, 0, 0, 255)); IMGUI_API void DebugDrawLineExtents(ImU32 col = IM_COL32(255, 0, 0, 255)); IMGUI_API void DebugDrawItemRect(ImU32 col = IM_COL32(255, 0, 0, 255)); IMGUI_API void DebugLocateItem(ImGuiID target_id); // Call sparingly: only 1 at the same time! IMGUI_API void DebugLocateItemOnHover(ImGuiID target_id); // Only call on reaction to a mouse Hover: because only 1 at the same time! IMGUI_API void DebugLocateItemResolveWithLastItem(); IMGUI_API void DebugBreakClearData(); IMGUI_API bool DebugBreakButton(const char* label, const char* description_of_location); IMGUI_API void DebugBreakButtonTooltip(bool keyboard_only, const char* description_of_location); inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; } IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); IMGUI_API void DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* data_id, const void* data_id_end); IMGUI_API void DebugNodeColumns(ImGuiOldColumns* columns); IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, const ImDrawList* draw_list, const char* label); IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb); IMGUI_API void DebugNodeFont(ImFont* font); IMGUI_API void DebugNodeFontGlyph(ImFont* font, const ImFontGlyph* glyph); IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label); IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label); IMGUI_API void DebugNodeTable(ImGuiTable* table); IMGUI_API void DebugNodeTableSettings(ImGuiTableSettings* settings); IMGUI_API void DebugNodeInputTextState(ImGuiInputTextState* state); IMGUI_API void DebugNodeTypingSelectState(ImGuiTypingSelectState* state); IMGUI_API void DebugNodeWindow(ImGuiWindow* window, const char* label); IMGUI_API void DebugNodeWindowSettings(ImGuiWindowSettings* settings); IMGUI_API void DebugNodeWindowsList(ImVector* windows, const char* label); IMGUI_API void DebugNodeWindowsListByBeginStackParent(ImGuiWindow** windows, int windows_size, ImGuiWindow* parent_in_begin_stack); IMGUI_API void DebugNodeViewport(ImGuiViewportP* viewport); IMGUI_API void DebugRenderKeyboardPreview(ImDrawList* draw_list); IMGUI_API void DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport, const ImRect& bb); // Obsolete functions #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS inline void SetItemUsingMouseWheel() { SetItemKeyOwner(ImGuiKey_MouseWheelY); } // Changed in 1.89 inline bool TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags = 0) { return TreeNodeUpdateNextOpen(id, flags); } // Renamed in 1.89 // Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets which used FocusableItemRegister(): // (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool tab_focused = FocusableItemRegister(...)' // (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Focused) != 0' // (New) IMGUI_VERSION_NUM >= 18413: using 'ItemAdd(..., ImGuiItemFlags_Inputable)' and 'bool tab_focused = (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput))' //inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) // -> pass ImGuiItemAddFlags_Inputable flag to ItemAdd() //inline void FocusableItemUnregister(ImGuiWindow* window) // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem #endif #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { IM_ASSERT(IsNamedKey(key)); return IsKeyPressed(key, repeat); } // Removed in 1.87: Mapping from named key is always identity! #endif } // namespace ImGui //----------------------------------------------------------------------------- // [SECTION] ImFontAtlas internal API //----------------------------------------------------------------------------- // This structure is likely to evolve as we add support for incremental atlas updates struct ImFontBuilderIO { bool (*FontBuilder_Build)(ImFontAtlas* atlas); }; // Helper for font builder #ifdef IMGUI_ENABLE_STB_TRUETYPE IMGUI_API const ImFontBuilderIO* ImFontAtlasGetBuilderForStbTruetype(); #endif IMGUI_API void ImFontAtlasUpdateConfigDataPointers(ImFontAtlas* atlas); IMGUI_API void ImFontAtlasBuildInit(ImFontAtlas* atlas); IMGUI_API void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent); IMGUI_API void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opaque); IMGUI_API void ImFontAtlasBuildFinish(ImFontAtlas* atlas); IMGUI_API void ImFontAtlasBuildRender8bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned char in_marker_pixel_value); IMGUI_API void ImFontAtlasBuildRender32bppRectFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char, unsigned int in_marker_pixel_value); IMGUI_API void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_multiply_factor); IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride); //----------------------------------------------------------------------------- // [SECTION] Test Engine specific hooks (imgui_test_engine) //----------------------------------------------------------------------------- #ifdef IMGUI_ENABLE_TEST_ENGINE extern void ImGuiTestEngineHook_ItemAdd(ImGuiContext* ctx, ImGuiID id, const ImRect& bb, const ImGuiLastItemData* item_data); // item_data may be NULL extern void ImGuiTestEngineHook_ItemInfo(ImGuiContext* ctx, ImGuiID id, const char* label, ImGuiItemStatusFlags flags); extern void ImGuiTestEngineHook_Log(ImGuiContext* ctx, const char* fmt, ...); extern const char* ImGuiTestEngine_FindItemDebugLabel(ImGuiContext* ctx, ImGuiID id); // In IMGUI_VERSION_NUM >= 18934: changed IMGUI_TEST_ENGINE_ITEM_ADD(bb,id) to IMGUI_TEST_ENGINE_ITEM_ADD(id,bb,item_data); #define IMGUI_TEST_ENGINE_ITEM_ADD(_ID,_BB,_ITEM_DATA) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemAdd(&g, _ID, _BB, _ITEM_DATA) // Register item bounding box #define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional) #define IMGUI_TEST_ENGINE_LOG(_FMT,...) if (g.TestEngineHookItems) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log #else #define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) ((void)0) #define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) ((void)g) #endif //----------------------------------------------------------------------------- #if defined(__clang__) #pragma clang diagnostic pop #elif defined(__GNUC__) #pragma GCC diagnostic pop #endif #ifdef _MSC_VER #pragma warning (pop) #endif #endif // #ifndef IMGUI_DISABLE RenderKit-ospray-f2a61c2/apps/common/external/imgui/imgui_tables.cpp000066400000000000000000007152231456566705700257200ustar00rootroot00000000000000// dear imgui, v1.90.3 // (tables and columns code) /* Index of this file: // [SECTION] Commentary // [SECTION] Header mess // [SECTION] Tables: Main code // [SECTION] Tables: Simple accessors // [SECTION] Tables: Row changes // [SECTION] Tables: Columns changes // [SECTION] Tables: Columns width management // [SECTION] Tables: Drawing // [SECTION] Tables: Sorting // [SECTION] Tables: Headers // [SECTION] Tables: Context Menu // [SECTION] Tables: Settings (.ini data) // [SECTION] Tables: Garbage Collection // [SECTION] Tables: Debugging // [SECTION] Columns, BeginColumns, EndColumns, etc. */ // Navigating this file: // - In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot. // - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments. //----------------------------------------------------------------------------- // [SECTION] Commentary //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Typical tables call flow: (root level is generally public API): //----------------------------------------------------------------------------- // - BeginTable() user begin into a table // | BeginChild() - (if ScrollX/ScrollY is set) // | TableBeginInitMemory() - first time table is used // | TableResetSettings() - on settings reset // | TableLoadSettings() - on settings load // | TableBeginApplyRequests() - apply queued resizing/reordering/hiding requests // | - TableSetColumnWidth() - apply resizing width (for mouse resize, often requested by previous frame) // | - TableUpdateColumnsWeightFromWidth()- recompute columns weights (of stretch columns) from their respective width // - TableSetupColumn() user submit columns details (optional) // - TableSetupScrollFreeze() user submit scroll freeze information (optional) //----------------------------------------------------------------------------- // - TableUpdateLayout() [Internal] followup to BeginTable(): setup everything: widths, columns positions, clipping rectangles. Automatically called by the FIRST call to TableNextRow() or TableHeadersRow(). // | TableSetupDrawChannels() - setup ImDrawList channels // | TableUpdateBorders() - detect hovering columns for resize, ahead of contents submission // | TableBeginContextMenuPopup() // | - TableDrawDefaultContextMenu() - draw right-click context menu contents //----------------------------------------------------------------------------- // - TableHeadersRow() or TableHeader() user submit a headers row (optional) // | TableSortSpecsClickColumn() - when left-clicked: alter sort order and sort direction // | TableOpenContextMenu() - when right-clicked: trigger opening of the default context menu // - TableGetSortSpecs() user queries updated sort specs (optional, generally after submitting headers) // - TableNextRow() user begin into a new row (also automatically called by TableHeadersRow()) // | TableEndRow() - finish existing row // | TableBeginRow() - add a new row // - TableSetColumnIndex() / TableNextColumn() user begin into a cell // | TableEndCell() - close existing column/cell // | TableBeginCell() - enter into current column/cell // - [...] user emit contents //----------------------------------------------------------------------------- // - EndTable() user ends the table // | TableDrawBorders() - draw outer borders, inner vertical borders // | TableMergeDrawChannels() - merge draw channels if clipping isn't required // | EndChild() - (if ScrollX/ScrollY is set) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // TABLE SIZING //----------------------------------------------------------------------------- // (Read carefully because this is subtle but it does make sense!) //----------------------------------------------------------------------------- // About 'outer_size': // Its meaning needs to differ slightly depending on if we are using ScrollX/ScrollY flags. // Default value is ImVec2(0.0f, 0.0f). // X // - outer_size.x <= 0.0f -> Right-align from window/work-rect right-most edge. With -FLT_MIN or 0.0f will align exactly on right-most edge. // - outer_size.x > 0.0f -> Set Fixed width. // Y with ScrollX/ScrollY disabled: we output table directly in current window // - outer_size.y < 0.0f -> Bottom-align (but will auto extend, unless _NoHostExtendY is set). Not meaningful if parent window can vertically scroll. // - outer_size.y = 0.0f -> No minimum height (but will auto extend, unless _NoHostExtendY is set) // - outer_size.y > 0.0f -> Set Minimum height (but will auto extend, unless _NoHostExtendY is set) // Y with ScrollX/ScrollY enabled: using a child window for scrolling // - outer_size.y < 0.0f -> Bottom-align. Not meaningful if parent window can vertically scroll. // - outer_size.y = 0.0f -> Bottom-align, consistent with BeginChild(). Not recommended unless table is last item in parent window. // - outer_size.y > 0.0f -> Set Exact height. Recommended when using Scrolling on any axis. //----------------------------------------------------------------------------- // Outer size is also affected by the NoHostExtendX/NoHostExtendY flags. // Important to note how the two flags have slightly different behaviors! // - ImGuiTableFlags_NoHostExtendX -> Make outer width auto-fit to columns (overriding outer_size.x value). Only available when ScrollX/ScrollY are disabled and Stretch columns are not used. // - ImGuiTableFlags_NoHostExtendY -> Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit). Only available when ScrollX/ScrollY is disabled. Data below the limit will be clipped and not visible. // In theory ImGuiTableFlags_NoHostExtendY could be the default and any non-scrolling tables with outer_size.y != 0.0f would use exact height. // This would be consistent but perhaps less useful and more confusing (as vertically clipped items are not useful and not easily noticeable). //----------------------------------------------------------------------------- // About 'inner_width': // With ScrollX disabled: // - inner_width -> *ignored* // With ScrollX enabled: // - inner_width < 0.0f -> *illegal* fit in known width (right align from outer_size.x) <-- weird // - inner_width = 0.0f -> fit in outer_width: Fixed size columns will take space they need (if avail, otherwise shrink down), Stretch columns becomes Fixed columns. // - inner_width > 0.0f -> override scrolling width, generally to be larger than outer_size.x. Fixed column take space they need (if avail, otherwise shrink down), Stretch columns share remaining space! //----------------------------------------------------------------------------- // Details: // - If you want to use Stretch columns with ScrollX, you generally need to specify 'inner_width' otherwise the concept // of "available space" doesn't make sense. // - Even if not really useful, we allow 'inner_width < outer_size.x' for consistency and to facilitate understanding // of what the value does. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // COLUMNS SIZING POLICIES // (Reference: ImGuiTableFlags_SizingXXX flags and ImGuiTableColumnFlags_WidthXXX flags) //----------------------------------------------------------------------------- // About overriding column sizing policy and width/weight with TableSetupColumn(): // We use a default parameter of -1 for 'init_width'/'init_weight'. // - with ImGuiTableColumnFlags_WidthFixed, init_width <= 0 (default) --> width is automatic // - with ImGuiTableColumnFlags_WidthFixed, init_width > 0 (explicit) --> width is custom // - with ImGuiTableColumnFlags_WidthStretch, init_weight <= 0 (default) --> weight is 1.0f // - with ImGuiTableColumnFlags_WidthStretch, init_weight > 0 (explicit) --> weight is custom // Widths are specified _without_ CellPadding. If you specify a width of 100.0f, the column will be cover (100.0f + Padding * 2.0f) // and you can fit a 100.0f wide item in it without clipping and with padding honored. //----------------------------------------------------------------------------- // About default sizing policy (if you don't specify a ImGuiTableColumnFlags_WidthXXXX flag) // - with Table policy ImGuiTableFlags_SizingFixedFit --> default Column policy is ImGuiTableColumnFlags_WidthFixed, default Width is equal to contents width // - with Table policy ImGuiTableFlags_SizingFixedSame --> default Column policy is ImGuiTableColumnFlags_WidthFixed, default Width is max of all contents width // - with Table policy ImGuiTableFlags_SizingStretchSame --> default Column policy is ImGuiTableColumnFlags_WidthStretch, default Weight is 1.0f // - with Table policy ImGuiTableFlags_SizingStretchWeight --> default Column policy is ImGuiTableColumnFlags_WidthStretch, default Weight is proportional to contents // Default Width and default Weight can be overridden when calling TableSetupColumn(). //----------------------------------------------------------------------------- // About mixing Fixed/Auto and Stretch columns together: // - the typical use of mixing sizing policies is: any number of LEADING Fixed columns, followed by one or two TRAILING Stretch columns. // - using mixed policies with ScrollX does not make much sense, as using Stretch columns with ScrollX does not make much sense in the first place! // that is, unless 'inner_width' is passed to BeginTable() to explicitly provide a total width to layout columns in. // - when using ImGuiTableFlags_SizingFixedSame with mixed columns, only the Fixed/Auto columns will match their widths to the width of the maximum contents. // - when using ImGuiTableFlags_SizingStretchSame with mixed columns, only the Stretch columns will match their weights/widths. //----------------------------------------------------------------------------- // About using column width: // If a column is manually resizable or has a width specified with TableSetupColumn(): // - you may use GetContentRegionAvail().x to query the width available in a given column. // - right-side alignment features such as SetNextItemWidth(-x) or PushItemWidth(-x) will rely on this width. // If the column is not resizable and has no width specified with TableSetupColumn(): // - its width will be automatic and be set to the max of items submitted. // - therefore you generally cannot have ALL items of the columns use e.g. SetNextItemWidth(-FLT_MIN). // - but if the column has one or more items of known/fixed size, this will become the reference width used by SetNextItemWidth(-FLT_MIN). //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // TABLES CLIPPING/CULLING //----------------------------------------------------------------------------- // About clipping/culling of Rows in Tables: // - For large numbers of rows, it is recommended you use ImGuiListClipper to submit only visible rows. // ImGuiListClipper is reliant on the fact that rows are of equal height. // See 'Demo->Tables->Vertical Scrolling' or 'Demo->Tables->Advanced' for a demo of using the clipper. // - Note that auto-resizing columns don't play well with using the clipper. // By default a table with _ScrollX but without _Resizable will have column auto-resize. // So, if you want to use the clipper, make sure to either enable _Resizable, either setup columns width explicitly with _WidthFixed. //----------------------------------------------------------------------------- // About clipping/culling of Columns in Tables: // - Both TableSetColumnIndex() and TableNextColumn() return true when the column is visible or performing // width measurements. Otherwise, you may skip submitting the contents of a cell/column, BUT ONLY if you know // it is not going to contribute to row height. // In many situations, you may skip submitting contents for every column but one (e.g. the first one). // - Case A: column is not hidden by user, and at least partially in sight (most common case). // - Case B: column is clipped / out of sight (because of scrolling or parent ClipRect): TableNextColumn() return false as a hint but we still allow layout output. // - Case C: column is hidden explicitly by the user (e.g. via the context menu, or _DefaultHide column flag, etc.). // // [A] [B] [C] // TableNextColumn(): true false false -> [userland] when TableNextColumn() / TableSetColumnIndex() returns false, user can skip submitting items but only if the column doesn't contribute to row height. // SkipItems: false false true -> [internal] when SkipItems is true, most widgets will early out if submitted, resulting is no layout output. // ClipRect: normal zero-width zero-width -> [internal] when ClipRect is zero, ItemAdd() will return false and most widgets will early out mid-way. // ImDrawList output: normal dummy dummy -> [internal] when using the dummy channel, ImDrawList submissions (if any) will be wasted (because cliprect is zero-width anyway). // // - We need to distinguish those cases because non-hidden columns that are clipped outside of scrolling bounds should still contribute their height to the row. // However, in the majority of cases, the contribution to row height is the same for all columns, or the tallest cells are known by the programmer. //----------------------------------------------------------------------------- // About clipping/culling of whole Tables: // - Scrolling tables with a known outer size can be clipped earlier as BeginTable() will return false. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // [SECTION] Header mess //----------------------------------------------------------------------------- #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif #include "imgui.h" #ifndef IMGUI_DISABLE #include "imgui_internal.h" // System includes #include // intptr_t // Visual Studio warnings #ifdef _MSC_VER #pragma warning (disable: 4127) // condition expression is constant #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later #pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types #endif #pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2). #pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). #endif // Clang/GCC warnings with -Weverything #if defined(__clang__) #if __has_warning("-Wunknown-warning-option") #pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great! #endif #pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' #pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse. #pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok. #pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code. #pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0 #pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. #pragma clang diagnostic ignored "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') #pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision #elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #endif //----------------------------------------------------------------------------- // [SECTION] Tables: Main code //----------------------------------------------------------------------------- // - TableFixFlags() [Internal] // - TableFindByID() [Internal] // - BeginTable() // - BeginTableEx() [Internal] // - TableBeginInitMemory() [Internal] // - TableBeginApplyRequests() [Internal] // - TableSetupColumnFlags() [Internal] // - TableUpdateLayout() [Internal] // - TableUpdateBorders() [Internal] // - EndTable() // - TableSetupColumn() // - TableSetupScrollFreeze() //----------------------------------------------------------------------------- // Configuration static const int TABLE_DRAW_CHANNEL_BG0 = 0; static const int TABLE_DRAW_CHANNEL_BG2_FROZEN = 1; static const int TABLE_DRAW_CHANNEL_NOCLIP = 2; // When using ImGuiTableFlags_NoClip (this becomes the last visible channel) static const float TABLE_BORDER_SIZE = 1.0f; // FIXME-TABLE: Currently hard-coded because of clipping assumptions with outer borders rendering. static const float TABLE_RESIZE_SEPARATOR_HALF_THICKNESS = 4.0f; // Extend outside inner borders. static const float TABLE_RESIZE_SEPARATOR_FEEDBACK_TIMER = 0.06f; // Delay/timer before making the hover feedback (color+cursor) visible because tables/columns tends to be more cramped. // Helper inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags, ImGuiWindow* outer_window) { // Adjust flags: set default sizing policy if ((flags & ImGuiTableFlags_SizingMask_) == 0) flags |= ((flags & ImGuiTableFlags_ScrollX) || (outer_window->Flags & ImGuiWindowFlags_AlwaysAutoResize)) ? ImGuiTableFlags_SizingFixedFit : ImGuiTableFlags_SizingStretchSame; // Adjust flags: enable NoKeepColumnsVisible when using ImGuiTableFlags_SizingFixedSame if ((flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedSame) flags |= ImGuiTableFlags_NoKeepColumnsVisible; // Adjust flags: enforce borders when resizable if (flags & ImGuiTableFlags_Resizable) flags |= ImGuiTableFlags_BordersInnerV; // Adjust flags: disable NoHostExtendX/NoHostExtendY if we have any scrolling going on if (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) flags &= ~(ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_NoHostExtendY); // Adjust flags: NoBordersInBodyUntilResize takes priority over NoBordersInBody if (flags & ImGuiTableFlags_NoBordersInBodyUntilResize) flags &= ~ImGuiTableFlags_NoBordersInBody; // Adjust flags: disable saved settings if there's nothing to save if ((flags & (ImGuiTableFlags_Resizable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Sortable)) == 0) flags |= ImGuiTableFlags_NoSavedSettings; // Inherit _NoSavedSettings from top-level window (child windows always have _NoSavedSettings set) if (outer_window->RootWindow->Flags & ImGuiWindowFlags_NoSavedSettings) flags |= ImGuiTableFlags_NoSavedSettings; return flags; } ImGuiTable* ImGui::TableFindByID(ImGuiID id) { ImGuiContext& g = *GImGui; return g.Tables.GetByKey(id); } // Read about "TABLE SIZING" at the top of this file. bool ImGui::BeginTable(const char* str_id, int columns_count, ImGuiTableFlags flags, const ImVec2& outer_size, float inner_width) { ImGuiID id = GetID(str_id); return BeginTableEx(str_id, id, columns_count, flags, outer_size, inner_width); } bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImGuiTableFlags flags, const ImVec2& outer_size, float inner_width) { ImGuiContext& g = *GImGui; ImGuiWindow* outer_window = GetCurrentWindow(); if (outer_window->SkipItems) // Consistent with other tables + beneficial side effect that assert on miscalling EndTable() will be more visible. return false; // Sanity checks IM_ASSERT(columns_count > 0 && columns_count < IMGUI_TABLE_MAX_COLUMNS); if (flags & ImGuiTableFlags_ScrollX) IM_ASSERT(inner_width >= 0.0f); // If an outer size is specified ahead we will be able to early out when not visible. Exact clipping criteria may evolve. const bool use_child_window = (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0; const ImVec2 avail_size = GetContentRegionAvail(); const ImVec2 actual_outer_size = CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f); const ImRect outer_rect(outer_window->DC.CursorPos, outer_window->DC.CursorPos + actual_outer_size); const bool outer_window_is_measuring_size = (outer_window->AutoFitFramesX > 0) || (outer_window->AutoFitFramesY > 0); // Doesn't apply to AlwaysAutoResize windows! if (use_child_window && IsClippedEx(outer_rect, 0) && !outer_window_is_measuring_size) { ItemSize(outer_rect); return false; } // [DEBUG] Debug break requested by user if (g.DebugBreakInTable == id) IM_DEBUG_BREAK(); // Acquire storage for the table ImGuiTable* table = g.Tables.GetOrAddByKey(id); const ImGuiTableFlags table_last_flags = table->Flags; // Acquire temporary buffers const int table_idx = g.Tables.GetIndex(table); if (++g.TablesTempDataStacked > g.TablesTempData.Size) g.TablesTempData.resize(g.TablesTempDataStacked, ImGuiTableTempData()); ImGuiTableTempData* temp_data = table->TempData = &g.TablesTempData[g.TablesTempDataStacked - 1]; temp_data->TableIndex = table_idx; table->DrawSplitter = &table->TempData->DrawSplitter; table->DrawSplitter->Clear(); // Fix flags table->IsDefaultSizingPolicy = (flags & ImGuiTableFlags_SizingMask_) == 0; flags = TableFixFlags(flags, outer_window); // Initialize const int previous_frame_active = table->LastFrameActive; const int instance_no = (previous_frame_active != g.FrameCount) ? 0 : table->InstanceCurrent + 1; table->ID = id; table->Flags = flags; table->LastFrameActive = g.FrameCount; table->OuterWindow = table->InnerWindow = outer_window; table->ColumnsCount = columns_count; table->IsLayoutLocked = false; table->InnerWidth = inner_width; temp_data->UserOuterSize = outer_size; // Instance data (for instance 0, TableID == TableInstanceID) ImGuiID instance_id; table->InstanceCurrent = (ImS16)instance_no; if (instance_no > 0) { IM_ASSERT(table->ColumnsCount == columns_count && "BeginTable(): Cannot change columns count mid-frame while preserving same ID"); if (table->InstanceDataExtra.Size < instance_no) table->InstanceDataExtra.push_back(ImGuiTableInstanceData()); instance_id = GetIDWithSeed(instance_no, GetIDWithSeed("##Instances", NULL, id)); // Push "##Instances" followed by (int)instance_no in ID stack. } else { instance_id = id; } ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); table_instance->TableInstanceID = instance_id; // When not using a child window, WorkRect.Max will grow as we append contents. if (use_child_window) { // Ensure no vertical scrollbar appears if we only want horizontal one, to make flag consistent // (we have no other way to disable vertical scrollbar of a window while keeping the horizontal one showing) ImVec2 override_content_size(FLT_MAX, FLT_MAX); if ((flags & ImGuiTableFlags_ScrollX) && !(flags & ImGuiTableFlags_ScrollY)) override_content_size.y = FLT_MIN; // Ensure specified width (when not specified, Stretched columns will act as if the width == OuterWidth and // never lead to any scrolling). We don't handle inner_width < 0.0f, we could potentially use it to right-align // based on the right side of the child window work rect, which would require knowing ahead if we are going to // have decoration taking horizontal spaces (typically a vertical scrollbar). if ((flags & ImGuiTableFlags_ScrollX) && inner_width > 0.0f) override_content_size.x = inner_width; if (override_content_size.x != FLT_MAX || override_content_size.y != FLT_MAX) SetNextWindowContentSize(ImVec2(override_content_size.x != FLT_MAX ? override_content_size.x : 0.0f, override_content_size.y != FLT_MAX ? override_content_size.y : 0.0f)); // Reset scroll if we are reactivating it if ((table_last_flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) == 0) SetNextWindowScroll(ImVec2(0.0f, 0.0f)); // Create scrolling region (without border and zero window padding) ImGuiWindowFlags child_flags = (flags & ImGuiTableFlags_ScrollX) ? ImGuiWindowFlags_HorizontalScrollbar : ImGuiWindowFlags_None; BeginChildEx(name, instance_id, outer_rect.GetSize(), false, child_flags); table->InnerWindow = g.CurrentWindow; table->WorkRect = table->InnerWindow->WorkRect; table->OuterRect = table->InnerWindow->Rect(); table->InnerRect = table->InnerWindow->InnerRect; IM_ASSERT(table->InnerWindow->WindowPadding.x == 0.0f && table->InnerWindow->WindowPadding.y == 0.0f && table->InnerWindow->WindowBorderSize == 0.0f); // Allow submitting when host is measuring if (table->InnerWindow->SkipItems && outer_window_is_measuring_size) table->InnerWindow->SkipItems = false; // When using multiple instances, ensure they have the same amount of horizontal decorations (aka vertical scrollbar) so stretched columns can be aligned) if (instance_no == 0) { table->HasScrollbarYPrev = table->HasScrollbarYCurr; table->HasScrollbarYCurr = false; } table->HasScrollbarYCurr |= table->InnerWindow->ScrollbarY; } else { // For non-scrolling tables, WorkRect == OuterRect == InnerRect. // But at this point we do NOT have a correct value for .Max.y (unless a height has been explicitly passed in). It will only be updated in EndTable(). table->WorkRect = table->OuterRect = table->InnerRect = outer_rect; } // Push a standardized ID for both child-using and not-child-using tables PushOverrideID(id); if (instance_no > 0) PushOverrideID(instance_id); // FIXME: Somehow this is not resolved by stack-tool, even tho GetIDWithSeed() submitted the symbol. // Backup a copy of host window members we will modify ImGuiWindow* inner_window = table->InnerWindow; table->HostIndentX = inner_window->DC.Indent.x; table->HostClipRect = inner_window->ClipRect; table->HostSkipItems = inner_window->SkipItems; temp_data->HostBackupWorkRect = inner_window->WorkRect; temp_data->HostBackupParentWorkRect = inner_window->ParentWorkRect; temp_data->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset; temp_data->HostBackupPrevLineSize = inner_window->DC.PrevLineSize; temp_data->HostBackupCurrLineSize = inner_window->DC.CurrLineSize; temp_data->HostBackupCursorMaxPos = inner_window->DC.CursorMaxPos; temp_data->HostBackupItemWidth = outer_window->DC.ItemWidth; temp_data->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size; inner_window->DC.PrevLineSize = inner_window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); // Make left and top borders not overlap our contents by offsetting HostClipRect (#6765) // (we normally shouldn't alter HostClipRect as we rely on TableMergeDrawChannels() expanding non-clipped column toward the // limits of that rectangle, in order for ImDrawListSplitter::Merge() to merge the draw commands. However since the overlap // problem only affect scrolling tables in this case we can get away with doing it without extra cost). if (inner_window != outer_window) { if (flags & ImGuiTableFlags_BordersOuterV) table->HostClipRect.Min.x = ImMin(table->HostClipRect.Min.x + TABLE_BORDER_SIZE, table->HostClipRect.Max.x); if (flags & ImGuiTableFlags_BordersOuterH) table->HostClipRect.Min.y = ImMin(table->HostClipRect.Min.y + TABLE_BORDER_SIZE, table->HostClipRect.Max.y); } // Padding and Spacing // - None ........Content..... Pad .....Content........ // - PadOuter | Pad ..Content..... Pad .....Content.. Pad | // - PadInner ........Content.. Pad | Pad ..Content........ // - PadOuter+PadInner | Pad ..Content.. Pad | Pad ..Content.. Pad | const bool pad_outer_x = (flags & ImGuiTableFlags_NoPadOuterX) ? false : (flags & ImGuiTableFlags_PadOuterX) ? true : (flags & ImGuiTableFlags_BordersOuterV) != 0; const bool pad_inner_x = (flags & ImGuiTableFlags_NoPadInnerX) ? false : true; const float inner_spacing_for_border = (flags & ImGuiTableFlags_BordersInnerV) ? TABLE_BORDER_SIZE : 0.0f; const float inner_spacing_explicit = (pad_inner_x && (flags & ImGuiTableFlags_BordersInnerV) == 0) ? g.Style.CellPadding.x : 0.0f; const float inner_padding_explicit = (pad_inner_x && (flags & ImGuiTableFlags_BordersInnerV) != 0) ? g.Style.CellPadding.x : 0.0f; table->CellSpacingX1 = inner_spacing_explicit + inner_spacing_for_border; table->CellSpacingX2 = inner_spacing_explicit; table->CellPaddingX = inner_padding_explicit; const float outer_padding_for_border = (flags & ImGuiTableFlags_BordersOuterV) ? TABLE_BORDER_SIZE : 0.0f; const float outer_padding_explicit = pad_outer_x ? g.Style.CellPadding.x : 0.0f; table->OuterPaddingX = (outer_padding_for_border + outer_padding_explicit) - table->CellPaddingX; table->CurrentColumn = -1; table->CurrentRow = -1; table->RowBgColorCounter = 0; table->LastRowFlags = ImGuiTableRowFlags_None; table->InnerClipRect = (inner_window == outer_window) ? table->WorkRect : inner_window->ClipRect; table->InnerClipRect.ClipWith(table->WorkRect); // We need this to honor inner_width table->InnerClipRect.ClipWithFull(table->HostClipRect); table->InnerClipRect.Max.y = (flags & ImGuiTableFlags_NoHostExtendY) ? ImMin(table->InnerClipRect.Max.y, inner_window->WorkRect.Max.y) : inner_window->ClipRect.Max.y; table->RowPosY1 = table->RowPosY2 = table->WorkRect.Min.y; // This is needed somehow table->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow() table->RowCellPaddingY = 0.0f; table->FreezeRowsRequest = table->FreezeRowsCount = 0; // This will be setup by TableSetupScrollFreeze(), if any table->FreezeColumnsRequest = table->FreezeColumnsCount = 0; table->IsUnfrozenRows = true; table->DeclColumnsCount = table->AngledHeadersCount = 0; if (previous_frame_active + 1 < g.FrameCount) table->IsActiveIdInTable = false; temp_data->AngledheadersExtraWidth = 0.0f; // Using opaque colors facilitate overlapping lines of the grid, otherwise we'd need to improve TableDrawBorders() table->BorderColorStrong = GetColorU32(ImGuiCol_TableBorderStrong); table->BorderColorLight = GetColorU32(ImGuiCol_TableBorderLight); // Make table current g.CurrentTable = table; outer_window->DC.NavIsScrollPushableX = false; // Shortcut for NavUpdateCurrentWindowIsScrollPushableX(); outer_window->DC.CurrentTableIdx = table_idx; if (inner_window != outer_window) // So EndChild() within the inner window can restore the table properly. inner_window->DC.CurrentTableIdx = table_idx; if ((table_last_flags & ImGuiTableFlags_Reorderable) && (flags & ImGuiTableFlags_Reorderable) == 0) table->IsResetDisplayOrderRequest = true; // Mark as used to avoid GC if (table_idx >= g.TablesLastTimeActive.Size) g.TablesLastTimeActive.resize(table_idx + 1, -1.0f); g.TablesLastTimeActive[table_idx] = (float)g.Time; temp_data->LastTimeActive = (float)g.Time; table->MemoryCompacted = false; // Setup memory buffer (clear data if columns count changed) ImGuiTableColumn* old_columns_to_preserve = NULL; void* old_columns_raw_data = NULL; const int old_columns_count = table->Columns.size(); if (old_columns_count != 0 && old_columns_count != columns_count) { // Attempt to preserve width on column count change (#4046) old_columns_to_preserve = table->Columns.Data; old_columns_raw_data = table->RawData; table->RawData = NULL; } if (table->RawData == NULL) { TableBeginInitMemory(table, columns_count); table->IsInitializing = table->IsSettingsRequestLoad = true; } if (table->IsResetAllRequest) TableResetSettings(table); if (table->IsInitializing) { // Initialize table->SettingsOffset = -1; table->IsSortSpecsDirty = true; table->InstanceInteracted = -1; table->ContextPopupColumn = -1; table->ReorderColumn = table->ResizedColumn = table->LastResizedColumn = -1; table->AutoFitSingleColumn = -1; table->HoveredColumnBody = table->HoveredColumnBorder = -1; for (int n = 0; n < columns_count; n++) { ImGuiTableColumn* column = &table->Columns[n]; if (old_columns_to_preserve && n < old_columns_count) { // FIXME: We don't attempt to preserve column order in this path. *column = old_columns_to_preserve[n]; } else { float width_auto = column->WidthAuto; *column = ImGuiTableColumn(); column->WidthAuto = width_auto; column->IsPreserveWidthAuto = true; // Preserve WidthAuto when reinitializing a live table: not technically necessary but remove a visible flicker column->IsEnabled = column->IsUserEnabled = column->IsUserEnabledNextFrame = true; } column->DisplayOrder = table->DisplayOrderToIndex[n] = (ImGuiTableColumnIdx)n; } } if (old_columns_raw_data) IM_FREE(old_columns_raw_data); // Load settings if (table->IsSettingsRequestLoad) TableLoadSettings(table); // Handle DPI/font resize // This is designed to facilitate DPI changes with the assumption that e.g. style.CellPadding has been scaled as well. // It will also react to changing fonts with mixed results. It doesn't need to be perfect but merely provide a decent transition. // FIXME-DPI: Provide consistent standards for reference size. Perhaps using g.CurrentDpiScale would be more self explanatory. // This is will lead us to non-rounded WidthRequest in columns, which should work but is a poorly tested path. const float new_ref_scale_unit = g.FontSize; // g.Font->GetCharAdvance('A') ? if (table->RefScale != 0.0f && table->RefScale != new_ref_scale_unit) { const float scale_factor = new_ref_scale_unit / table->RefScale; //IMGUI_DEBUG_PRINT("[table] %08X RefScaleUnit %.3f -> %.3f, scaling width by %.3f\n", table->ID, table->RefScaleUnit, new_ref_scale_unit, scale_factor); for (int n = 0; n < columns_count; n++) table->Columns[n].WidthRequest = table->Columns[n].WidthRequest * scale_factor; } table->RefScale = new_ref_scale_unit; // Disable output until user calls TableNextRow() or TableNextColumn() leading to the TableUpdateLayout() call.. // This is not strictly necessary but will reduce cases were "out of table" output will be misleading to the user. // Because we cannot safely assert in EndTable() when no rows have been created, this seems like our best option. inner_window->SkipItems = true; // Clear names // At this point the ->NameOffset field of each column will be invalid until TableUpdateLayout() or the first call to TableSetupColumn() if (table->ColumnsNames.Buf.Size > 0) table->ColumnsNames.Buf.resize(0); // Apply queued resizing/reordering/hiding requests TableBeginApplyRequests(table); return true; } // For reference, the average total _allocation count_ for a table is: // + 0 (for ImGuiTable instance, we are pooling allocations in g.Tables[]) // + 1 (for table->RawData allocated below) // + 1 (for table->ColumnsNames, if names are used) // Shared allocations for the maximum number of simultaneously nested tables (generally a very small number) // + 1 (for table->Splitter._Channels) // + 2 * active_channels_count (for ImDrawCmd and ImDrawIdx buffers inside channels) // Where active_channels_count is variable but often == columns_count or == columns_count + 1, see TableSetupDrawChannels() for details. // Unused channels don't perform their +2 allocations. void ImGui::TableBeginInitMemory(ImGuiTable* table, int columns_count) { // Allocate single buffer for our arrays const int columns_bit_array_size = (int)ImBitArrayGetStorageSizeInBytes(columns_count); ImSpanAllocator<6> span_allocator; span_allocator.Reserve(0, columns_count * sizeof(ImGuiTableColumn)); span_allocator.Reserve(1, columns_count * sizeof(ImGuiTableColumnIdx)); span_allocator.Reserve(2, columns_count * sizeof(ImGuiTableCellData), 4); for (int n = 3; n < 6; n++) span_allocator.Reserve(n, columns_bit_array_size); table->RawData = IM_ALLOC(span_allocator.GetArenaSizeInBytes()); memset(table->RawData, 0, span_allocator.GetArenaSizeInBytes()); span_allocator.SetArenaBasePtr(table->RawData); span_allocator.GetSpan(0, &table->Columns); span_allocator.GetSpan(1, &table->DisplayOrderToIndex); span_allocator.GetSpan(2, &table->RowCellData); table->EnabledMaskByDisplayOrder = (ImU32*)span_allocator.GetSpanPtrBegin(3); table->EnabledMaskByIndex = (ImU32*)span_allocator.GetSpanPtrBegin(4); table->VisibleMaskByIndex = (ImU32*)span_allocator.GetSpanPtrBegin(5); } // Apply queued resizing/reordering/hiding requests void ImGui::TableBeginApplyRequests(ImGuiTable* table) { // Handle resizing request // (We process this in the TableBegin() of the first instance of each table) // FIXME-TABLE: Contains columns if our work area doesn't allow for scrolling? if (table->InstanceCurrent == 0) { if (table->ResizedColumn != -1 && table->ResizedColumnNextWidth != FLT_MAX) TableSetColumnWidth(table->ResizedColumn, table->ResizedColumnNextWidth); table->LastResizedColumn = table->ResizedColumn; table->ResizedColumnNextWidth = FLT_MAX; table->ResizedColumn = -1; // Process auto-fit for single column, which is a special case for stretch columns and fixed columns with FixedSame policy. // FIXME-TABLE: Would be nice to redistribute available stretch space accordingly to other weights, instead of giving it all to siblings. if (table->AutoFitSingleColumn != -1) { TableSetColumnWidth(table->AutoFitSingleColumn, table->Columns[table->AutoFitSingleColumn].WidthAuto); table->AutoFitSingleColumn = -1; } } // Handle reordering request // Note: we don't clear ReorderColumn after handling the request. if (table->InstanceCurrent == 0) { if (table->HeldHeaderColumn == -1 && table->ReorderColumn != -1) table->ReorderColumn = -1; table->HeldHeaderColumn = -1; if (table->ReorderColumn != -1 && table->ReorderColumnDir != 0) { // We need to handle reordering across hidden columns. // In the configuration below, moving C to the right of E will lead to: // ... C [D] E ---> ... [D] E C (Column name/index) // ... 2 3 4 ... 2 3 4 (Display order) const int reorder_dir = table->ReorderColumnDir; IM_ASSERT(reorder_dir == -1 || reorder_dir == +1); IM_ASSERT(table->Flags & ImGuiTableFlags_Reorderable); ImGuiTableColumn* src_column = &table->Columns[table->ReorderColumn]; ImGuiTableColumn* dst_column = &table->Columns[(reorder_dir == -1) ? src_column->PrevEnabledColumn : src_column->NextEnabledColumn]; IM_UNUSED(dst_column); const int src_order = src_column->DisplayOrder; const int dst_order = dst_column->DisplayOrder; src_column->DisplayOrder = (ImGuiTableColumnIdx)dst_order; for (int order_n = src_order + reorder_dir; order_n != dst_order + reorder_dir; order_n += reorder_dir) table->Columns[table->DisplayOrderToIndex[order_n]].DisplayOrder -= (ImGuiTableColumnIdx)reorder_dir; IM_ASSERT(dst_column->DisplayOrder == dst_order - reorder_dir); // Display order is stored in both columns->IndexDisplayOrder and table->DisplayOrder[]. Rebuild later from the former. for (int column_n = 0; column_n < table->ColumnsCount; column_n++) table->DisplayOrderToIndex[table->Columns[column_n].DisplayOrder] = (ImGuiTableColumnIdx)column_n; table->ReorderColumnDir = 0; table->IsSettingsDirty = true; } } // Handle display order reset request if (table->IsResetDisplayOrderRequest) { for (int n = 0; n < table->ColumnsCount; n++) table->DisplayOrderToIndex[n] = table->Columns[n].DisplayOrder = (ImGuiTableColumnIdx)n; table->IsResetDisplayOrderRequest = false; table->IsSettingsDirty = true; } } // Adjust flags: default width mode + stretch columns are not allowed when auto extending static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, ImGuiTableColumnFlags flags_in) { ImGuiTableColumnFlags flags = flags_in; // Sizing Policy if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0) { const ImGuiTableFlags table_sizing_policy = (table->Flags & ImGuiTableFlags_SizingMask_); if (table_sizing_policy == ImGuiTableFlags_SizingFixedFit || table_sizing_policy == ImGuiTableFlags_SizingFixedSame) flags |= ImGuiTableColumnFlags_WidthFixed; else flags |= ImGuiTableColumnFlags_WidthStretch; } else { IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiTableColumnFlags_WidthMask_)); // Check that only 1 of each set is used. } // Resize if ((table->Flags & ImGuiTableFlags_Resizable) == 0) flags |= ImGuiTableColumnFlags_NoResize; // Sorting if ((flags & ImGuiTableColumnFlags_NoSortAscending) && (flags & ImGuiTableColumnFlags_NoSortDescending)) flags |= ImGuiTableColumnFlags_NoSort; // Indentation if ((flags & ImGuiTableColumnFlags_IndentMask_) == 0) flags |= (table->Columns.index_from_ptr(column) == 0) ? ImGuiTableColumnFlags_IndentEnable : ImGuiTableColumnFlags_IndentDisable; // Alignment //if ((flags & ImGuiTableColumnFlags_AlignMask_) == 0) // flags |= ImGuiTableColumnFlags_AlignCenter; //IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiTableColumnFlags_AlignMask_)); // Check that only 1 of each set is used. // Preserve status flags column->Flags = flags | (column->Flags & ImGuiTableColumnFlags_StatusMask_); // Build an ordered list of available sort directions column->SortDirectionsAvailCount = column->SortDirectionsAvailMask = column->SortDirectionsAvailList = 0; if (table->Flags & ImGuiTableFlags_Sortable) { int count = 0, mask = 0, list = 0; if ((flags & ImGuiTableColumnFlags_PreferSortAscending) != 0 && (flags & ImGuiTableColumnFlags_NoSortAscending) == 0) { mask |= 1 << ImGuiSortDirection_Ascending; list |= ImGuiSortDirection_Ascending << (count << 1); count++; } if ((flags & ImGuiTableColumnFlags_PreferSortDescending) != 0 && (flags & ImGuiTableColumnFlags_NoSortDescending) == 0) { mask |= 1 << ImGuiSortDirection_Descending; list |= ImGuiSortDirection_Descending << (count << 1); count++; } if ((flags & ImGuiTableColumnFlags_PreferSortAscending) == 0 && (flags & ImGuiTableColumnFlags_NoSortAscending) == 0) { mask |= 1 << ImGuiSortDirection_Ascending; list |= ImGuiSortDirection_Ascending << (count << 1); count++; } if ((flags & ImGuiTableColumnFlags_PreferSortDescending) == 0 && (flags & ImGuiTableColumnFlags_NoSortDescending) == 0) { mask |= 1 << ImGuiSortDirection_Descending; list |= ImGuiSortDirection_Descending << (count << 1); count++; } if ((table->Flags & ImGuiTableFlags_SortTristate) || count == 0) { mask |= 1 << ImGuiSortDirection_None; count++; } column->SortDirectionsAvailList = (ImU8)list; column->SortDirectionsAvailMask = (ImU8)mask; column->SortDirectionsAvailCount = (ImU8)count; ImGui::TableFixColumnSortDirection(table, column); } } // Layout columns for the frame. This is in essence the followup to BeginTable() and this is our largest function. // Runs on the first call to TableNextRow(), to give a chance for TableSetupColumn() and other TableSetupXXXXX() functions to be called first. // FIXME-TABLE: Our width (and therefore our WorkRect) will be minimal in the first frame for _WidthAuto columns. // Increase feedback side-effect with widgets relying on WorkRect.Max.x... Maybe provide a default distribution for _WidthAuto columns? void ImGui::TableUpdateLayout(ImGuiTable* table) { ImGuiContext& g = *GImGui; IM_ASSERT(table->IsLayoutLocked == false); const ImGuiTableFlags table_sizing_policy = (table->Flags & ImGuiTableFlags_SizingMask_); table->IsDefaultDisplayOrder = true; table->ColumnsEnabledCount = 0; ImBitArrayClearAllBits(table->EnabledMaskByIndex, table->ColumnsCount); ImBitArrayClearAllBits(table->EnabledMaskByDisplayOrder, table->ColumnsCount); table->LeftMostEnabledColumn = -1; table->MinColumnWidth = ImMax(1.0f, g.Style.FramePadding.x * 1.0f); // g.Style.ColumnsMinSpacing; // FIXME-TABLE // [Part 1] Apply/lock Enabled and Order states. Calculate auto/ideal width for columns. Count fixed/stretch columns. // Process columns in their visible orders as we are building the Prev/Next indices. int count_fixed = 0; // Number of columns that have fixed sizing policies int count_stretch = 0; // Number of columns that have stretch sizing policies int prev_visible_column_idx = -1; bool has_auto_fit_request = false; bool has_resizable = false; float stretch_sum_width_auto = 0.0f; float fixed_max_width_auto = 0.0f; for (int order_n = 0; order_n < table->ColumnsCount; order_n++) { const int column_n = table->DisplayOrderToIndex[order_n]; if (column_n != order_n) table->IsDefaultDisplayOrder = false; ImGuiTableColumn* column = &table->Columns[column_n]; // Clear column setup if not submitted by user. Currently we make it mandatory to call TableSetupColumn() every frame. // It would easily work without but we're not ready to guarantee it since e.g. names need resubmission anyway. // We take a slight shortcut but in theory we could be calling TableSetupColumn() here with dummy values, it should yield the same effect. if (table->DeclColumnsCount <= column_n) { TableSetupColumnFlags(table, column, ImGuiTableColumnFlags_None); column->NameOffset = -1; column->UserID = 0; column->InitStretchWeightOrWidth = -1.0f; } // Update Enabled state, mark settings and sort specs dirty if (!(table->Flags & ImGuiTableFlags_Hideable) || (column->Flags & ImGuiTableColumnFlags_NoHide)) column->IsUserEnabledNextFrame = true; if (column->IsUserEnabled != column->IsUserEnabledNextFrame) { column->IsUserEnabled = column->IsUserEnabledNextFrame; table->IsSettingsDirty = true; } column->IsEnabled = column->IsUserEnabled && (column->Flags & ImGuiTableColumnFlags_Disabled) == 0; if (column->SortOrder != -1 && !column->IsEnabled) table->IsSortSpecsDirty = true; if (column->SortOrder > 0 && !(table->Flags & ImGuiTableFlags_SortMulti)) table->IsSortSpecsDirty = true; // Auto-fit unsized columns const bool start_auto_fit = (column->Flags & ImGuiTableColumnFlags_WidthFixed) ? (column->WidthRequest < 0.0f) : (column->StretchWeight < 0.0f); if (start_auto_fit) column->AutoFitQueue = column->CannotSkipItemsQueue = (1 << 3) - 1; // Fit for three frames if (!column->IsEnabled) { column->IndexWithinEnabledSet = -1; continue; } // Mark as enabled and link to previous/next enabled column column->PrevEnabledColumn = (ImGuiTableColumnIdx)prev_visible_column_idx; column->NextEnabledColumn = -1; if (prev_visible_column_idx != -1) table->Columns[prev_visible_column_idx].NextEnabledColumn = (ImGuiTableColumnIdx)column_n; else table->LeftMostEnabledColumn = (ImGuiTableColumnIdx)column_n; column->IndexWithinEnabledSet = table->ColumnsEnabledCount++; ImBitArraySetBit(table->EnabledMaskByIndex, column_n); ImBitArraySetBit(table->EnabledMaskByDisplayOrder, column->DisplayOrder); prev_visible_column_idx = column_n; IM_ASSERT(column->IndexWithinEnabledSet <= column->DisplayOrder); // Calculate ideal/auto column width (that's the width required for all contents to be visible without clipping) // Combine width from regular rows + width from headers unless requested not to. if (!column->IsPreserveWidthAuto) column->WidthAuto = TableGetColumnWidthAuto(table, column); // Non-resizable columns keep their requested width (apply user value regardless of IsPreserveWidthAuto) const bool column_is_resizable = (column->Flags & ImGuiTableColumnFlags_NoResize) == 0; if (column_is_resizable) has_resizable = true; if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && column->InitStretchWeightOrWidth > 0.0f && !column_is_resizable) column->WidthAuto = column->InitStretchWeightOrWidth; if (column->AutoFitQueue != 0x00) has_auto_fit_request = true; if (column->Flags & ImGuiTableColumnFlags_WidthStretch) { stretch_sum_width_auto += column->WidthAuto; count_stretch++; } else { fixed_max_width_auto = ImMax(fixed_max_width_auto, column->WidthAuto); count_fixed++; } } if ((table->Flags & ImGuiTableFlags_Sortable) && table->SortSpecsCount == 0 && !(table->Flags & ImGuiTableFlags_SortTristate)) table->IsSortSpecsDirty = true; table->RightMostEnabledColumn = (ImGuiTableColumnIdx)prev_visible_column_idx; IM_ASSERT(table->LeftMostEnabledColumn >= 0 && table->RightMostEnabledColumn >= 0); // [Part 2] Disable child window clipping while fitting columns. This is not strictly necessary but makes it possible to avoid // the column fitting having to wait until the first visible frame of the child container (may or not be a good thing). Also see #6510. // FIXME-TABLE: for always auto-resizing columns may not want to do that all the time. if (has_auto_fit_request && table->OuterWindow != table->InnerWindow) table->InnerWindow->SkipItems = false; if (has_auto_fit_request) table->IsSettingsDirty = true; // [Part 3] Fix column flags and record a few extra information. float sum_width_requests = 0.0f; // Sum of all width for fixed and auto-resize columns, excluding width contributed by Stretch columns but including spacing/padding. float stretch_sum_weights = 0.0f; // Sum of all weights for stretch columns. table->LeftMostStretchedColumn = table->RightMostStretchedColumn = -1; for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByIndex, column_n)) continue; ImGuiTableColumn* column = &table->Columns[column_n]; const bool column_is_resizable = (column->Flags & ImGuiTableColumnFlags_NoResize) == 0; if (column->Flags & ImGuiTableColumnFlags_WidthFixed) { // Apply same widths policy float width_auto = column->WidthAuto; if (table_sizing_policy == ImGuiTableFlags_SizingFixedSame && (column->AutoFitQueue != 0x00 || !column_is_resizable)) width_auto = fixed_max_width_auto; // Apply automatic width // Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!) if (column->AutoFitQueue != 0x00) column->WidthRequest = width_auto; else if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !column_is_resizable && column->IsRequestOutput) column->WidthRequest = width_auto; // FIXME-TABLE: Increase minimum size during init frame to avoid biasing auto-fitting widgets // (e.g. TextWrapped) too much. Otherwise what tends to happen is that TextWrapped would output a very // large height (= first frame scrollbar display very off + clipper would skip lots of items). // This is merely making the side-effect less extreme, but doesn't properly fixes it. // FIXME: Move this to ->WidthGiven to avoid temporary lossyless? // FIXME: This break IsPreserveWidthAuto from not flickering if the stored WidthAuto was smaller. if (column->AutoFitQueue > 0x01 && table->IsInitializing && !column->IsPreserveWidthAuto) column->WidthRequest = ImMax(column->WidthRequest, table->MinColumnWidth * 4.0f); // FIXME-TABLE: Another constant/scale? sum_width_requests += column->WidthRequest; } else { // Initialize stretch weight if (column->AutoFitQueue != 0x00 || column->StretchWeight < 0.0f || !column_is_resizable) { if (column->InitStretchWeightOrWidth > 0.0f) column->StretchWeight = column->InitStretchWeightOrWidth; else if (table_sizing_policy == ImGuiTableFlags_SizingStretchProp) column->StretchWeight = (column->WidthAuto / stretch_sum_width_auto) * count_stretch; else column->StretchWeight = 1.0f; } stretch_sum_weights += column->StretchWeight; if (table->LeftMostStretchedColumn == -1 || table->Columns[table->LeftMostStretchedColumn].DisplayOrder > column->DisplayOrder) table->LeftMostStretchedColumn = (ImGuiTableColumnIdx)column_n; if (table->RightMostStretchedColumn == -1 || table->Columns[table->RightMostStretchedColumn].DisplayOrder < column->DisplayOrder) table->RightMostStretchedColumn = (ImGuiTableColumnIdx)column_n; } column->IsPreserveWidthAuto = false; sum_width_requests += table->CellPaddingX * 2.0f; } table->ColumnsEnabledFixedCount = (ImGuiTableColumnIdx)count_fixed; table->ColumnsStretchSumWeights = stretch_sum_weights; // [Part 4] Apply final widths based on requested widths const ImRect work_rect = table->WorkRect; const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1); const float width_removed = (table->HasScrollbarYPrev && !table->InnerWindow->ScrollbarY) ? g.Style.ScrollbarSize : 0.0f; // To synchronize decoration width of synched tables with mismatching scrollbar state (#5920) const float width_avail = ImMax(1.0f, (((table->Flags & ImGuiTableFlags_ScrollX) && table->InnerWidth == 0.0f) ? table->InnerClipRect.GetWidth() : work_rect.GetWidth()) - width_removed); const float width_avail_for_stretched_columns = width_avail - width_spacings - sum_width_requests; float width_remaining_for_stretched_columns = width_avail_for_stretched_columns; table->ColumnsGivenWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount; for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByIndex, column_n)) continue; ImGuiTableColumn* column = &table->Columns[column_n]; // Allocate width for stretched/weighted columns (StretchWeight gets converted into WidthRequest) if (column->Flags & ImGuiTableColumnFlags_WidthStretch) { float weight_ratio = column->StretchWeight / stretch_sum_weights; column->WidthRequest = IM_TRUNC(ImMax(width_avail_for_stretched_columns * weight_ratio, table->MinColumnWidth) + 0.01f); width_remaining_for_stretched_columns -= column->WidthRequest; } // [Resize Rule 1] The right-most Visible column is not resizable if there is at least one Stretch column // See additional comments in TableSetColumnWidth(). if (column->NextEnabledColumn == -1 && table->LeftMostStretchedColumn != -1) column->Flags |= ImGuiTableColumnFlags_NoDirectResize_; // Assign final width, record width in case we will need to shrink column->WidthGiven = ImTrunc(ImMax(column->WidthRequest, table->MinColumnWidth)); table->ColumnsGivenWidth += column->WidthGiven; } // [Part 5] Redistribute stretch remainder width due to rounding (remainder width is < 1.0f * number of Stretch column). // Using right-to-left distribution (more likely to match resizing cursor). if (width_remaining_for_stretched_columns >= 1.0f && !(table->Flags & ImGuiTableFlags_PreciseWidths)) for (int order_n = table->ColumnsCount - 1; stretch_sum_weights > 0.0f && width_remaining_for_stretched_columns >= 1.0f && order_n >= 0; order_n--) { if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByDisplayOrder, order_n)) continue; ImGuiTableColumn* column = &table->Columns[table->DisplayOrderToIndex[order_n]]; if (!(column->Flags & ImGuiTableColumnFlags_WidthStretch)) continue; column->WidthRequest += 1.0f; column->WidthGiven += 1.0f; width_remaining_for_stretched_columns -= 1.0f; } // Determine if table is hovered which will be used to flag columns as hovered. // - In principle we'd like to use the equivalent of IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), // but because our item is partially submitted at this point we use ItemHoverable() and a workaround (temporarily // clear ActiveId, which is equivalent to the change provided by _AllowWhenBLockedByActiveItem). // - This allows columns to be marked as hovered when e.g. clicking a button inside the column, or using drag and drop. ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); table_instance->HoveredRowLast = table_instance->HoveredRowNext; table_instance->HoveredRowNext = -1; table->HoveredColumnBody = table->HoveredColumnBorder = -1; const ImRect mouse_hit_rect(table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.Max.x, ImMax(table->OuterRect.Max.y, table->OuterRect.Min.y + table_instance->LastOuterHeight)); const ImGuiID backup_active_id = g.ActiveId; g.ActiveId = 0; const bool is_hovering_table = ItemHoverable(mouse_hit_rect, 0, ImGuiItemFlags_None); g.ActiveId = backup_active_id; // Determine skewed MousePos.x to support angled headers. float mouse_skewed_x = g.IO.MousePos.x; if (table->AngledHeadersHeight > 0.0f) if (g.IO.MousePos.y >= table->OuterRect.Min.y && g.IO.MousePos.y <= table->OuterRect.Min.y + table->AngledHeadersHeight) mouse_skewed_x += ImTrunc((table->OuterRect.Min.y + table->AngledHeadersHeight - g.IO.MousePos.y) * table->AngledHeadersSlope); // [Part 6] Setup final position, offset, skip/clip states and clipping rectangles, detect hovered column // Process columns in their visible orders as we are comparing the visible order and adjusting host_clip_rect while looping. int visible_n = 0; bool has_at_least_one_column_requesting_output = false; bool offset_x_frozen = (table->FreezeColumnsCount > 0); float offset_x = ((table->FreezeColumnsCount > 0) ? table->OuterRect.Min.x : work_rect.Min.x) + table->OuterPaddingX - table->CellSpacingX1; ImRect host_clip_rect = table->InnerClipRect; //host_clip_rect.Max.x += table->CellPaddingX + table->CellSpacingX2; ImBitArrayClearAllBits(table->VisibleMaskByIndex, table->ColumnsCount); for (int order_n = 0; order_n < table->ColumnsCount; order_n++) { const int column_n = table->DisplayOrderToIndex[order_n]; ImGuiTableColumn* column = &table->Columns[column_n]; column->NavLayerCurrent = (ImS8)(table->FreezeRowsCount > 0 ? ImGuiNavLayer_Menu : ImGuiNavLayer_Main); // Use Count NOT request so Header line changes layer when frozen if (offset_x_frozen && table->FreezeColumnsCount == visible_n) { offset_x += work_rect.Min.x - table->OuterRect.Min.x; offset_x_frozen = false; } // Clear status flags column->Flags &= ~ImGuiTableColumnFlags_StatusMask_; if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByDisplayOrder, order_n)) { // Hidden column: clear a few fields and we are done with it for the remainder of the function. // We set a zero-width clip rect but set Min.y/Max.y properly to not interfere with the clipper. column->MinX = column->MaxX = column->WorkMinX = column->ClipRect.Min.x = column->ClipRect.Max.x = offset_x; column->WidthGiven = 0.0f; column->ClipRect.Min.y = work_rect.Min.y; column->ClipRect.Max.y = FLT_MAX; column->ClipRect.ClipWithFull(host_clip_rect); column->IsVisibleX = column->IsVisibleY = column->IsRequestOutput = false; column->IsSkipItems = true; column->ItemWidth = 1.0f; continue; } // Detect hovered column if (is_hovering_table && mouse_skewed_x >= column->ClipRect.Min.x && mouse_skewed_x < column->ClipRect.Max.x) table->HoveredColumnBody = (ImGuiTableColumnIdx)column_n; // Lock start position column->MinX = offset_x; // Lock width based on start position and minimum/maximum width for this position float max_width = TableGetMaxColumnWidth(table, column_n); column->WidthGiven = ImMin(column->WidthGiven, max_width); column->WidthGiven = ImMax(column->WidthGiven, ImMin(column->WidthRequest, table->MinColumnWidth)); column->MaxX = offset_x + column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f; // Lock other positions // - ClipRect.Min.x: Because merging draw commands doesn't compare min boundaries, we make ClipRect.Min.x match left bounds to be consistent regardless of merging. // - ClipRect.Max.x: using WorkMaxX instead of MaxX (aka including padding) makes things more consistent when resizing down, tho slightly detrimental to visibility in very-small column. // - ClipRect.Max.x: using MaxX makes it easier for header to receive hover highlight with no discontinuity and display sorting arrow. // - FIXME-TABLE: We want equal width columns to have equal (ClipRect.Max.x - WorkMinX) width, which means ClipRect.max.x cannot stray off host_clip_rect.Max.x else right-most column may appear shorter. column->WorkMinX = column->MinX + table->CellPaddingX + table->CellSpacingX1; column->WorkMaxX = column->MaxX - table->CellPaddingX - table->CellSpacingX2; // Expected max column->ItemWidth = ImTrunc(column->WidthGiven * 0.65f); column->ClipRect.Min.x = column->MinX; column->ClipRect.Min.y = work_rect.Min.y; column->ClipRect.Max.x = column->MaxX; //column->WorkMaxX; column->ClipRect.Max.y = FLT_MAX; column->ClipRect.ClipWithFull(host_clip_rect); // Mark column as Clipped (not in sight) // Note that scrolling tables (where inner_window != outer_window) handle Y clipped earlier in BeginTable() so IsVisibleY really only applies to non-scrolling tables. // FIXME-TABLE: Because InnerClipRect.Max.y is conservatively ==outer_window->ClipRect.Max.y, we never can mark columns _Above_ the scroll line as not IsVisibleY. // Taking advantage of LastOuterHeight would yield good results there... // FIXME-TABLE: Y clipping is disabled because it effectively means not submitting will reduce contents width which is fed to outer_window->DC.CursorMaxPos.x, // and this may be used (e.g. typically by outer_window using AlwaysAutoResize or outer_window's horizontal scrollbar, but could be something else). // Possible solution to preserve last known content width for clipped column. Test 'table_reported_size' fails when enabling Y clipping and window is resized small. column->IsVisibleX = (column->ClipRect.Max.x > column->ClipRect.Min.x); column->IsVisibleY = true; // (column->ClipRect.Max.y > column->ClipRect.Min.y); const bool is_visible = column->IsVisibleX; //&& column->IsVisibleY; if (is_visible) ImBitArraySetBit(table->VisibleMaskByIndex, column_n); // Mark column as requesting output from user. Note that fixed + non-resizable sets are auto-fitting at all times and therefore always request output. column->IsRequestOutput = is_visible || column->AutoFitQueue != 0 || column->CannotSkipItemsQueue != 0; // Mark column as SkipItems (ignoring all items/layout) // (table->HostSkipItems is a copy of inner_window->SkipItems before we cleared it above in Part 2) column->IsSkipItems = !column->IsEnabled || table->HostSkipItems; if (column->IsSkipItems) IM_ASSERT(!is_visible); if (column->IsRequestOutput && !column->IsSkipItems) has_at_least_one_column_requesting_output = true; // Update status flags column->Flags |= ImGuiTableColumnFlags_IsEnabled; if (is_visible) column->Flags |= ImGuiTableColumnFlags_IsVisible; if (column->SortOrder != -1) column->Flags |= ImGuiTableColumnFlags_IsSorted; if (table->HoveredColumnBody == column_n) column->Flags |= ImGuiTableColumnFlags_IsHovered; // Alignment // FIXME-TABLE: This align based on the whole column width, not per-cell, and therefore isn't useful in // many cases (to be able to honor this we might be able to store a log of cells width, per row, for // visible rows, but nav/programmatic scroll would have visible artifacts.) //if (column->Flags & ImGuiTableColumnFlags_AlignRight) // column->WorkMinX = ImMax(column->WorkMinX, column->MaxX - column->ContentWidthRowsUnfrozen); //else if (column->Flags & ImGuiTableColumnFlags_AlignCenter) // column->WorkMinX = ImLerp(column->WorkMinX, ImMax(column->StartX, column->MaxX - column->ContentWidthRowsUnfrozen), 0.5f); // Reset content width variables column->ContentMaxXFrozen = column->ContentMaxXUnfrozen = column->WorkMinX; column->ContentMaxXHeadersUsed = column->ContentMaxXHeadersIdeal = column->WorkMinX; // Don't decrement auto-fit counters until container window got a chance to submit its items if (table->HostSkipItems == false) { column->AutoFitQueue >>= 1; column->CannotSkipItemsQueue >>= 1; } if (visible_n < table->FreezeColumnsCount) host_clip_rect.Min.x = ImClamp(column->MaxX + TABLE_BORDER_SIZE, host_clip_rect.Min.x, host_clip_rect.Max.x); offset_x += column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f; visible_n++; } // In case the table is visible (e.g. decorations) but all columns clipped, we keep a column visible. // Else if give no chance to a clipper-savy user to submit rows and therefore total contents height used by scrollbar. if (has_at_least_one_column_requesting_output == false) { table->Columns[table->LeftMostEnabledColumn].IsRequestOutput = true; table->Columns[table->LeftMostEnabledColumn].IsSkipItems = false; } // [Part 7] Detect/store when we are hovering the unused space after the right-most column (so e.g. context menus can react on it) // Clear Resizable flag if none of our column are actually resizable (either via an explicit _NoResize flag, either // because of using _WidthAuto/_WidthStretch). This will hide the resizing option from the context menu. const float unused_x1 = ImMax(table->WorkRect.Min.x, table->Columns[table->RightMostEnabledColumn].ClipRect.Max.x); if (is_hovering_table && table->HoveredColumnBody == -1) if (mouse_skewed_x >= unused_x1) table->HoveredColumnBody = (ImGuiTableColumnIdx)table->ColumnsCount; if (has_resizable == false && (table->Flags & ImGuiTableFlags_Resizable)) table->Flags &= ~ImGuiTableFlags_Resizable; table->IsActiveIdAliveBeforeTable = (g.ActiveIdIsAlive != 0); // [Part 8] Lock actual OuterRect/WorkRect right-most position. // This is done late to handle the case of fixed-columns tables not claiming more widths that they need. // Because of this we are careful with uses of WorkRect and InnerClipRect before this point. if (table->RightMostStretchedColumn != -1) table->Flags &= ~ImGuiTableFlags_NoHostExtendX; if (table->Flags & ImGuiTableFlags_NoHostExtendX) { table->OuterRect.Max.x = table->WorkRect.Max.x = unused_x1; table->InnerClipRect.Max.x = ImMin(table->InnerClipRect.Max.x, unused_x1); } table->InnerWindow->ParentWorkRect = table->WorkRect; table->BorderX1 = table->InnerClipRect.Min.x; table->BorderX2 = table->InnerClipRect.Max.x; // Setup window's WorkRect.Max.y for GetContentRegionAvail(). Other values will be updated in each TableBeginCell() call. float window_content_max_y; if (table->Flags & ImGuiTableFlags_NoHostExtendY) window_content_max_y = table->OuterRect.Max.y; else window_content_max_y = ImMax(table->InnerWindow->ContentRegionRect.Max.y, (table->Flags & ImGuiTableFlags_ScrollY) ? 0.0f : table->OuterRect.Max.y); table->InnerWindow->WorkRect.Max.y = ImClamp(window_content_max_y - g.Style.CellPadding.y, table->InnerWindow->WorkRect.Min.y, table->InnerWindow->WorkRect.Max.y); // [Part 9] Allocate draw channels and setup background cliprect TableSetupDrawChannels(table); // [Part 10] Hit testing on borders if (table->Flags & ImGuiTableFlags_Resizable) TableUpdateBorders(table); table_instance->LastTopHeadersRowHeight = 0.0f; table->IsLayoutLocked = true; table->IsUsingHeaders = false; // Highlight header table->HighlightColumnHeader = -1; if (table->IsContextPopupOpen && table->ContextPopupColumn != -1 && table->InstanceInteracted == table->InstanceCurrent) table->HighlightColumnHeader = table->ContextPopupColumn; else if ((table->Flags & ImGuiTableFlags_HighlightHoveredColumn) && table->HoveredColumnBody != -1 && table->HoveredColumnBody != table->ColumnsCount && table->HoveredColumnBorder == -1) if (g.ActiveId == 0 || (table->IsActiveIdInTable || g.DragDropActive)) table->HighlightColumnHeader = table->HoveredColumnBody; // [Part 11] Default context menu // - To append to this menu: you can call TableBeginContextMenuPopup()/.../EndPopup(). // - To modify or replace this: set table->IsContextPopupNoDefaultContents = true, then call TableBeginContextMenuPopup()/.../EndPopup(). // - You may call TableDrawDefaultContextMenu() with selected flags to display specific sections of the default menu, // e.g. TableDrawDefaultContextMenu(table, table->Flags & ~ImGuiTableFlags_Hideable) will display everything EXCEPT columns visibility options. if (table->DisableDefaultContextMenu == false && TableBeginContextMenuPopup(table)) { TableDrawDefaultContextMenu(table, table->Flags); EndPopup(); } // [Part 12] Sanitize and build sort specs before we have a chance to use them for display. // This path will only be exercised when sort specs are modified before header rows (e.g. init or visibility change) if (table->IsSortSpecsDirty && (table->Flags & ImGuiTableFlags_Sortable)) TableSortSpecsBuild(table); // [Part 13] Setup inner window decoration size (for scrolling / nav tracking to properly take account of frozen rows/columns) if (table->FreezeColumnsRequest > 0) table->InnerWindow->DecoInnerSizeX1 = table->Columns[table->DisplayOrderToIndex[table->FreezeColumnsRequest - 1]].MaxX - table->OuterRect.Min.x; if (table->FreezeRowsRequest > 0) table->InnerWindow->DecoInnerSizeY1 = table_instance->LastFrozenHeight; table_instance->LastFrozenHeight = 0.0f; // Initial state ImGuiWindow* inner_window = table->InnerWindow; if (table->Flags & ImGuiTableFlags_NoClip) table->DrawSplitter->SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP); else inner_window->DrawList->PushClipRect(inner_window->ClipRect.Min, inner_window->ClipRect.Max, false); } // Process hit-testing on resizing borders. Actual size change will be applied in EndTable() // - Set table->HoveredColumnBorder with a short delay/timer to reduce visual feedback noise. void ImGui::TableUpdateBorders(ImGuiTable* table) { ImGuiContext& g = *GImGui; IM_ASSERT(table->Flags & ImGuiTableFlags_Resizable); // At this point OuterRect height may be zero or under actual final height, so we rely on temporal coherency and // use the final height from last frame. Because this is only affecting _interaction_ with columns, it is not // really problematic (whereas the actual visual will be displayed in EndTable() and using the current frame height). // Actual columns highlight/render will be performed in EndTable() and not be affected. ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); const float hit_half_width = TABLE_RESIZE_SEPARATOR_HALF_THICKNESS; const float hit_y1 = (table->FreezeRowsCount >= 1 ? table->OuterRect.Min.y : table->WorkRect.Min.y) + table->AngledHeadersHeight; const float hit_y2_body = ImMax(table->OuterRect.Max.y, hit_y1 + table_instance->LastOuterHeight); const float hit_y2_head = hit_y1 + table_instance->LastTopHeadersRowHeight; for (int order_n = 0; order_n < table->ColumnsCount; order_n++) { if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByDisplayOrder, order_n)) continue; const int column_n = table->DisplayOrderToIndex[order_n]; ImGuiTableColumn* column = &table->Columns[column_n]; if (column->Flags & (ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoDirectResize_)) continue; // ImGuiTableFlags_NoBordersInBodyUntilResize will be honored in TableDrawBorders() const float border_y2_hit = (table->Flags & ImGuiTableFlags_NoBordersInBody) ? hit_y2_head : hit_y2_body; if ((table->Flags & ImGuiTableFlags_NoBordersInBody) && table->IsUsingHeaders == false) continue; if (!column->IsVisibleX && table->LastResizedColumn != column_n) continue; ImGuiID column_id = TableGetColumnResizeID(table, column_n, table->InstanceCurrent); ImRect hit_rect(column->MaxX - hit_half_width, hit_y1, column->MaxX + hit_half_width, border_y2_hit); ItemAdd(hit_rect, column_id, NULL, ImGuiItemFlags_NoNav); //GetForegroundDrawList()->AddRect(hit_rect.Min, hit_rect.Max, IM_COL32(255, 0, 0, 100)); bool hovered = false, held = false; bool pressed = ButtonBehavior(hit_rect, column_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_NoNavFocus); if (pressed && IsMouseDoubleClicked(0)) { TableSetColumnWidthAutoSingle(table, column_n); ClearActiveID(); held = false; } if (held) { if (table->LastResizedColumn == -1) table->ResizeLockMinContentsX2 = table->RightMostEnabledColumn != -1 ? table->Columns[table->RightMostEnabledColumn].MaxX : -FLT_MAX; table->ResizedColumn = (ImGuiTableColumnIdx)column_n; table->InstanceInteracted = table->InstanceCurrent; } if ((hovered && g.HoveredIdTimer > TABLE_RESIZE_SEPARATOR_FEEDBACK_TIMER) || held) { table->HoveredColumnBorder = (ImGuiTableColumnIdx)column_n; SetMouseCursor(ImGuiMouseCursor_ResizeEW); } } } void ImGui::EndTable() { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; IM_ASSERT(table != NULL && "Only call EndTable() if BeginTable() returns true!"); // This assert would be very useful to catch a common error... unfortunately it would probably trigger in some // cases, and for consistency user may sometimes output empty tables (and still benefit from e.g. outer border) //IM_ASSERT(table->IsLayoutLocked && "Table unused: never called TableNextRow(), is that the intent?"); // If the user never got to call TableNextRow() or TableNextColumn(), we call layout ourselves to ensure all our // code paths are consistent (instead of just hoping that TableBegin/TableEnd will work), get borders drawn, etc. if (!table->IsLayoutLocked) TableUpdateLayout(table); const ImGuiTableFlags flags = table->Flags; ImGuiWindow* inner_window = table->InnerWindow; ImGuiWindow* outer_window = table->OuterWindow; ImGuiTableTempData* temp_data = table->TempData; IM_ASSERT(inner_window == g.CurrentWindow); IM_ASSERT(outer_window == inner_window || outer_window == inner_window->ParentWindow); if (table->IsInsideRow) TableEndRow(table); // Context menu in columns body if (flags & ImGuiTableFlags_ContextMenuInBody) if (table->HoveredColumnBody != -1 && !IsAnyItemHovered() && IsMouseReleased(ImGuiMouseButton_Right)) TableOpenContextMenu((int)table->HoveredColumnBody); // Finalize table height ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); inner_window->DC.PrevLineSize = temp_data->HostBackupPrevLineSize; inner_window->DC.CurrLineSize = temp_data->HostBackupCurrLineSize; inner_window->DC.CursorMaxPos = temp_data->HostBackupCursorMaxPos; const float inner_content_max_y = table->RowPosY2; IM_ASSERT(table->RowPosY2 == inner_window->DC.CursorPos.y); if (inner_window != outer_window) inner_window->DC.CursorMaxPos.y = inner_content_max_y; else if (!(flags & ImGuiTableFlags_NoHostExtendY)) table->OuterRect.Max.y = table->InnerRect.Max.y = ImMax(table->OuterRect.Max.y, inner_content_max_y); // Patch OuterRect/InnerRect height table->WorkRect.Max.y = ImMax(table->WorkRect.Max.y, table->OuterRect.Max.y); table_instance->LastOuterHeight = table->OuterRect.GetHeight(); // Setup inner scrolling range // FIXME: This ideally should be done earlier, in BeginTable() SetNextWindowContentSize call, just like writing to inner_window->DC.CursorMaxPos.y, // but since the later is likely to be impossible to do we'd rather update both axises together. if (table->Flags & ImGuiTableFlags_ScrollX) { const float outer_padding_for_border = (table->Flags & ImGuiTableFlags_BordersOuterV) ? TABLE_BORDER_SIZE : 0.0f; float max_pos_x = table->InnerWindow->DC.CursorMaxPos.x; if (table->RightMostEnabledColumn != -1) max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].WorkMaxX + table->CellPaddingX + table->OuterPaddingX - outer_padding_for_border); if (table->ResizedColumn != -1) max_pos_x = ImMax(max_pos_x, table->ResizeLockMinContentsX2); table->InnerWindow->DC.CursorMaxPos.x = max_pos_x + table->TempData->AngledheadersExtraWidth; } // Pop clipping rect if (!(flags & ImGuiTableFlags_NoClip)) inner_window->DrawList->PopClipRect(); inner_window->ClipRect = inner_window->DrawList->_ClipRectStack.back(); // Draw borders if ((flags & ImGuiTableFlags_Borders) != 0) TableDrawBorders(table); #if 0 // Strip out dummy channel draw calls // We have no way to prevent user submitting direct ImDrawList calls into a hidden column (but ImGui:: calls will be clipped out) // Pros: remove draw calls which will have no effect. since they'll have zero-size cliprect they may be early out anyway. // Cons: making it harder for users watching metrics/debugger to spot the wasted vertices. if (table->DummyDrawChannel != (ImGuiTableColumnIdx)-1) { ImDrawChannel* dummy_channel = &table->DrawSplitter._Channels[table->DummyDrawChannel]; dummy_channel->_CmdBuffer.resize(0); dummy_channel->_IdxBuffer.resize(0); } #endif // Flatten channels and merge draw calls ImDrawListSplitter* splitter = table->DrawSplitter; splitter->SetCurrentChannel(inner_window->DrawList, 0); if ((table->Flags & ImGuiTableFlags_NoClip) == 0) TableMergeDrawChannels(table); splitter->Merge(inner_window->DrawList); // Update ColumnsAutoFitWidth to get us ahead for host using our size to auto-resize without waiting for next BeginTable() float auto_fit_width_for_fixed = 0.0f; float auto_fit_width_for_stretched = 0.0f; float auto_fit_width_for_stretched_min = 0.0f; for (int column_n = 0; column_n < table->ColumnsCount; column_n++) if (IM_BITARRAY_TESTBIT(table->EnabledMaskByIndex, column_n)) { ImGuiTableColumn* column = &table->Columns[column_n]; float column_width_request = ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !(column->Flags & ImGuiTableColumnFlags_NoResize)) ? column->WidthRequest : TableGetColumnWidthAuto(table, column); if (column->Flags & ImGuiTableColumnFlags_WidthFixed) auto_fit_width_for_fixed += column_width_request; else auto_fit_width_for_stretched += column_width_request; if ((column->Flags & ImGuiTableColumnFlags_WidthStretch) && (column->Flags & ImGuiTableColumnFlags_NoResize) != 0) auto_fit_width_for_stretched_min = ImMax(auto_fit_width_for_stretched_min, column_width_request / (column->StretchWeight / table->ColumnsStretchSumWeights)); } const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1); table->ColumnsAutoFitWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount + auto_fit_width_for_fixed + ImMax(auto_fit_width_for_stretched, auto_fit_width_for_stretched_min); // Update scroll if ((table->Flags & ImGuiTableFlags_ScrollX) == 0 && inner_window != outer_window) { inner_window->Scroll.x = 0.0f; } else if (table->LastResizedColumn != -1 && table->ResizedColumn == -1 && inner_window->ScrollbarX && table->InstanceInteracted == table->InstanceCurrent) { // When releasing a column being resized, scroll to keep the resulting column in sight const float neighbor_width_to_keep_visible = table->MinColumnWidth + table->CellPaddingX * 2.0f; ImGuiTableColumn* column = &table->Columns[table->LastResizedColumn]; if (column->MaxX < table->InnerClipRect.Min.x) SetScrollFromPosX(inner_window, column->MaxX - inner_window->Pos.x - neighbor_width_to_keep_visible, 1.0f); else if (column->MaxX > table->InnerClipRect.Max.x) SetScrollFromPosX(inner_window, column->MaxX - inner_window->Pos.x + neighbor_width_to_keep_visible, 1.0f); } // Apply resizing/dragging at the end of the frame if (table->ResizedColumn != -1 && table->InstanceCurrent == table->InstanceInteracted) { ImGuiTableColumn* column = &table->Columns[table->ResizedColumn]; const float new_x2 = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + TABLE_RESIZE_SEPARATOR_HALF_THICKNESS); const float new_width = ImTrunc(new_x2 - column->MinX - table->CellSpacingX1 - table->CellPaddingX * 2.0f); table->ResizedColumnNextWidth = new_width; } table->IsActiveIdInTable = (g.ActiveIdIsAlive != 0 && table->IsActiveIdAliveBeforeTable == false); // Pop from id stack IM_ASSERT_USER_ERROR(inner_window->IDStack.back() == table_instance->TableInstanceID, "Mismatching PushID/PopID!"); IM_ASSERT_USER_ERROR(outer_window->DC.ItemWidthStack.Size >= temp_data->HostBackupItemWidthStackSize, "Too many PopItemWidth!"); if (table->InstanceCurrent > 0) PopID(); PopID(); // Restore window data that we modified const ImVec2 backup_outer_max_pos = outer_window->DC.CursorMaxPos; inner_window->WorkRect = temp_data->HostBackupWorkRect; inner_window->ParentWorkRect = temp_data->HostBackupParentWorkRect; inner_window->SkipItems = table->HostSkipItems; outer_window->DC.CursorPos = table->OuterRect.Min; outer_window->DC.ItemWidth = temp_data->HostBackupItemWidth; outer_window->DC.ItemWidthStack.Size = temp_data->HostBackupItemWidthStackSize; outer_window->DC.ColumnsOffset = temp_data->HostBackupColumnsOffset; // Layout in outer window // (FIXME: To allow auto-fit and allow desirable effect of SameLine() we dissociate 'used' vs 'ideal' size by overriding // CursorPosPrevLine and CursorMaxPos manually. That should be a more general layout feature, see same problem e.g. #3414) if (inner_window != outer_window) { EndChild(); } else { ItemSize(table->OuterRect.GetSize()); ItemAdd(table->OuterRect, 0); } // Override declared contents width/height to enable auto-resize while not needlessly adding a scrollbar if (table->Flags & ImGuiTableFlags_NoHostExtendX) { // FIXME-TABLE: Could we remove this section? // ColumnsAutoFitWidth may be one frame ahead here since for Fixed+NoResize is calculated from latest contents IM_ASSERT((table->Flags & ImGuiTableFlags_ScrollX) == 0); outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth); } else if (temp_data->UserOuterSize.x <= 0.0f) { const float decoration_size = table->TempData->AngledheadersExtraWidth + ((table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.x : 0.0f); outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth + decoration_size - temp_data->UserOuterSize.x); outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth)); } else { outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->OuterRect.Max.x); } if (temp_data->UserOuterSize.y <= 0.0f) { const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollY) ? inner_window->ScrollbarSizes.y : 0.0f; outer_window->DC.IdealMaxPos.y = ImMax(outer_window->DC.IdealMaxPos.y, inner_content_max_y + decoration_size - temp_data->UserOuterSize.y); outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, inner_content_max_y)); } else { // OuterRect.Max.y may already have been pushed downward from the initial value (unless ImGuiTableFlags_NoHostExtendY is set) outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, table->OuterRect.Max.y); } // Save settings if (table->IsSettingsDirty) TableSaveSettings(table); table->IsInitializing = false; // Clear or restore current table, if any IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table); IM_ASSERT(g.TablesTempDataStacked > 0); temp_data = (--g.TablesTempDataStacked > 0) ? &g.TablesTempData[g.TablesTempDataStacked - 1] : NULL; g.CurrentTable = temp_data ? g.Tables.GetByIndex(temp_data->TableIndex) : NULL; if (g.CurrentTable) { g.CurrentTable->TempData = temp_data; g.CurrentTable->DrawSplitter = &temp_data->DrawSplitter; } outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1; NavUpdateCurrentWindowIsScrollPushableX(); } // See "COLUMNS SIZING POLICIES" comments at the top of this file // If (init_width_or_weight <= 0.0f) it is ignored void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, float init_width_or_weight, ImGuiID user_id) { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!"); IM_ASSERT(table->IsLayoutLocked == false && "Need to call call TableSetupColumn() before first row!"); IM_ASSERT((flags & ImGuiTableColumnFlags_StatusMask_) == 0 && "Illegal to pass StatusMask values to TableSetupColumn()"); if (table->DeclColumnsCount >= table->ColumnsCount) { IM_ASSERT_USER_ERROR(table->DeclColumnsCount < table->ColumnsCount, "Called TableSetupColumn() too many times!"); return; } ImGuiTableColumn* column = &table->Columns[table->DeclColumnsCount]; table->DeclColumnsCount++; // Assert when passing a width or weight if policy is entirely left to default, to avoid storing width into weight and vice-versa. // Give a grace to users of ImGuiTableFlags_ScrollX. if (table->IsDefaultSizingPolicy && (flags & ImGuiTableColumnFlags_WidthMask_) == 0 && (flags & ImGuiTableFlags_ScrollX) == 0) IM_ASSERT(init_width_or_weight <= 0.0f && "Can only specify width/weight if sizing policy is set explicitly in either Table or Column."); // When passing a width automatically enforce WidthFixed policy // (whereas TableSetupColumnFlags would default to WidthAuto if table is not Resizable) if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0 && init_width_or_weight > 0.0f) if ((table->Flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedFit || (table->Flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedSame) flags |= ImGuiTableColumnFlags_WidthFixed; if (flags & ImGuiTableColumnFlags_AngledHeader) { flags |= ImGuiTableColumnFlags_NoHeaderLabel; table->AngledHeadersCount++; } TableSetupColumnFlags(table, column, flags); column->UserID = user_id; flags = column->Flags; // Initialize defaults column->InitStretchWeightOrWidth = init_width_or_weight; if (table->IsInitializing) { // Init width or weight if (column->WidthRequest < 0.0f && column->StretchWeight < 0.0f) { if ((flags & ImGuiTableColumnFlags_WidthFixed) && init_width_or_weight > 0.0f) column->WidthRequest = init_width_or_weight; if (flags & ImGuiTableColumnFlags_WidthStretch) column->StretchWeight = (init_width_or_weight > 0.0f) ? init_width_or_weight : -1.0f; // Disable auto-fit if an explicit width/weight has been specified if (init_width_or_weight > 0.0f) column->AutoFitQueue = 0x00; } // Init default visibility/sort state if ((flags & ImGuiTableColumnFlags_DefaultHide) && (table->SettingsLoadedFlags & ImGuiTableFlags_Hideable) == 0) column->IsUserEnabled = column->IsUserEnabledNextFrame = false; if (flags & ImGuiTableColumnFlags_DefaultSort && (table->SettingsLoadedFlags & ImGuiTableFlags_Sortable) == 0) { column->SortOrder = 0; // Multiple columns using _DefaultSort will be reassigned unique SortOrder values when building the sort specs. column->SortDirection = (column->Flags & ImGuiTableColumnFlags_PreferSortDescending) ? (ImS8)ImGuiSortDirection_Descending : (ImU8)(ImGuiSortDirection_Ascending); } } // Store name (append with zero-terminator in contiguous buffer) column->NameOffset = -1; if (label != NULL && label[0] != 0) { column->NameOffset = (ImS16)table->ColumnsNames.size(); table->ColumnsNames.append(label, label + strlen(label) + 1); } } // [Public] void ImGui::TableSetupScrollFreeze(int columns, int rows) { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!"); IM_ASSERT(table->IsLayoutLocked == false && "Need to call TableSetupColumn() before first row!"); IM_ASSERT(columns >= 0 && columns < IMGUI_TABLE_MAX_COLUMNS); IM_ASSERT(rows >= 0 && rows < 128); // Arbitrary limit table->FreezeColumnsRequest = (table->Flags & ImGuiTableFlags_ScrollX) ? (ImGuiTableColumnIdx)ImMin(columns, table->ColumnsCount) : 0; table->FreezeColumnsCount = (table->InnerWindow->Scroll.x != 0.0f) ? table->FreezeColumnsRequest : 0; table->FreezeRowsRequest = (table->Flags & ImGuiTableFlags_ScrollY) ? (ImGuiTableColumnIdx)rows : 0; table->FreezeRowsCount = (table->InnerWindow->Scroll.y != 0.0f) ? table->FreezeRowsRequest : 0; table->IsUnfrozenRows = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b // Ensure frozen columns are ordered in their section. We still allow multiple frozen columns to be reordered. // FIXME-TABLE: This work for preserving 2143 into 21|43. How about 4321 turning into 21|43? (preserve relative order in each section) for (int column_n = 0; column_n < table->FreezeColumnsRequest; column_n++) { int order_n = table->DisplayOrderToIndex[column_n]; if (order_n != column_n && order_n >= table->FreezeColumnsRequest) { ImSwap(table->Columns[table->DisplayOrderToIndex[order_n]].DisplayOrder, table->Columns[table->DisplayOrderToIndex[column_n]].DisplayOrder); ImSwap(table->DisplayOrderToIndex[order_n], table->DisplayOrderToIndex[column_n]); } } } //----------------------------------------------------------------------------- // [SECTION] Tables: Simple accessors //----------------------------------------------------------------------------- // - TableGetColumnCount() // - TableGetColumnName() // - TableGetColumnName() [Internal] // - TableSetColumnEnabled() // - TableGetColumnFlags() // - TableGetCellBgRect() [Internal] // - TableGetColumnResizeID() [Internal] // - TableGetHoveredColumn() [Internal] // - TableGetHoveredRow() [Internal] // - TableSetBgColor() //----------------------------------------------------------------------------- int ImGui::TableGetColumnCount() { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; return table ? table->ColumnsCount : 0; } const char* ImGui::TableGetColumnName(int column_n) { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; if (!table) return NULL; if (column_n < 0) column_n = table->CurrentColumn; return TableGetColumnName(table, column_n); } const char* ImGui::TableGetColumnName(const ImGuiTable* table, int column_n) { if (table->IsLayoutLocked == false && column_n >= table->DeclColumnsCount) return ""; // NameOffset is invalid at this point const ImGuiTableColumn* column = &table->Columns[column_n]; if (column->NameOffset == -1) return ""; return &table->ColumnsNames.Buf[column->NameOffset]; } // Change user accessible enabled/disabled state of a column (often perceived as "showing/hiding" from users point of view) // Note that end-user can use the context menu to change this themselves (right-click in headers, or right-click in columns body with ImGuiTableFlags_ContextMenuInBody) // - Require table to have the ImGuiTableFlags_Hideable flag because we are manipulating user accessible state. // - Request will be applied during next layout, which happens on the first call to TableNextRow() after BeginTable(). // - For the getter you can test (TableGetColumnFlags() & ImGuiTableColumnFlags_IsEnabled) != 0. // - Alternative: the ImGuiTableColumnFlags_Disabled is an overriding/master disable flag which will also hide the column from context menu. void ImGui::TableSetColumnEnabled(int column_n, bool enabled) { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; IM_ASSERT(table != NULL); if (!table) return; IM_ASSERT(table->Flags & ImGuiTableFlags_Hideable); // See comments above if (column_n < 0) column_n = table->CurrentColumn; IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount); ImGuiTableColumn* column = &table->Columns[column_n]; column->IsUserEnabledNextFrame = enabled; } // We allow querying for an extra column in order to poll the IsHovered state of the right-most section ImGuiTableColumnFlags ImGui::TableGetColumnFlags(int column_n) { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; if (!table) return ImGuiTableColumnFlags_None; if (column_n < 0) column_n = table->CurrentColumn; if (column_n == table->ColumnsCount) return (table->HoveredColumnBody == column_n) ? ImGuiTableColumnFlags_IsHovered : ImGuiTableColumnFlags_None; return table->Columns[column_n].Flags; } // Return the cell rectangle based on currently known height. // - Important: we generally don't know our row height until the end of the row, so Max.y will be incorrect in many situations. // The only case where this is correct is if we provided a min_row_height to TableNextRow() and don't go below it, or in TableEndRow() when we locked that height. // - Important: if ImGuiTableFlags_PadOuterX is set but ImGuiTableFlags_PadInnerX is not set, the outer-most left and right // columns report a small offset so their CellBgRect can extend up to the outer border. // FIXME: But the rendering code in TableEndRow() nullifies that with clamping required for scrolling. ImRect ImGui::TableGetCellBgRect(const ImGuiTable* table, int column_n) { const ImGuiTableColumn* column = &table->Columns[column_n]; float x1 = column->MinX; float x2 = column->MaxX; //if (column->PrevEnabledColumn == -1) // x1 -= table->OuterPaddingX; //if (column->NextEnabledColumn == -1) // x2 += table->OuterPaddingX; x1 = ImMax(x1, table->WorkRect.Min.x); x2 = ImMin(x2, table->WorkRect.Max.x); return ImRect(x1, table->RowPosY1, x2, table->RowPosY2); } // Return the resizing ID for the right-side of the given column. ImGuiID ImGui::TableGetColumnResizeID(ImGuiTable* table, int column_n, int instance_no) { IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount); ImGuiID instance_id = TableGetInstanceID(table, instance_no); return instance_id + 1 + column_n; // FIXME: #6140: still not ideal } // Return -1 when table is not hovered. return columns_count if hovering the unused space at the right of the right-most visible column. int ImGui::TableGetHoveredColumn() { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; if (!table) return -1; return (int)table->HoveredColumnBody; } // Return -1 when table is not hovered. Return maxrow+1 if in table but below last submitted row. // *IMPORTANT* Unlike TableGetHoveredColumn(), this has a one frame latency in updating the value. // This difference with is the reason why this is not public yet. int ImGui::TableGetHoveredRow() { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; if (!table) return -1; ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); return (int)table_instance->HoveredRowLast; } void ImGui::TableSetBgColor(ImGuiTableBgTarget target, ImU32 color, int column_n) { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; IM_ASSERT(target != ImGuiTableBgTarget_None); if (color == IM_COL32_DISABLE) color = 0; // We cannot draw neither the cell or row background immediately as we don't know the row height at this point in time. switch (target) { case ImGuiTableBgTarget_CellBg: { if (table->RowPosY1 > table->InnerClipRect.Max.y) // Discard return; if (column_n == -1) column_n = table->CurrentColumn; if (!IM_BITARRAY_TESTBIT(table->VisibleMaskByIndex, column_n)) return; if (table->RowCellDataCurrent < 0 || table->RowCellData[table->RowCellDataCurrent].Column != column_n) table->RowCellDataCurrent++; ImGuiTableCellData* cell_data = &table->RowCellData[table->RowCellDataCurrent]; cell_data->BgColor = color; cell_data->Column = (ImGuiTableColumnIdx)column_n; break; } case ImGuiTableBgTarget_RowBg0: case ImGuiTableBgTarget_RowBg1: { if (table->RowPosY1 > table->InnerClipRect.Max.y) // Discard return; IM_ASSERT(column_n == -1); int bg_idx = (target == ImGuiTableBgTarget_RowBg1) ? 1 : 0; table->RowBgColor[bg_idx] = color; break; } default: IM_ASSERT(0); } } //------------------------------------------------------------------------- // [SECTION] Tables: Row changes //------------------------------------------------------------------------- // - TableGetRowIndex() // - TableNextRow() // - TableBeginRow() [Internal] // - TableEndRow() [Internal] //------------------------------------------------------------------------- // [Public] Note: for row coloring we use ->RowBgColorCounter which is the same value without counting header rows int ImGui::TableGetRowIndex() { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; if (!table) return 0; return table->CurrentRow; } // [Public] Starts into the first cell of a new row void ImGui::TableNextRow(ImGuiTableRowFlags row_flags, float row_min_height) { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; if (!table->IsLayoutLocked) TableUpdateLayout(table); if (table->IsInsideRow) TableEndRow(table); table->LastRowFlags = table->RowFlags; table->RowFlags = row_flags; table->RowCellPaddingY = g.Style.CellPadding.y; table->RowMinHeight = row_min_height; TableBeginRow(table); // We honor min_row_height requested by user, but cannot guarantee per-row maximum height, // because that would essentially require a unique clipping rectangle per-cell. table->RowPosY2 += table->RowCellPaddingY * 2.0f; table->RowPosY2 = ImMax(table->RowPosY2, table->RowPosY1 + row_min_height); // Disable output until user calls TableNextColumn() table->InnerWindow->SkipItems = true; } // [Internal] Only called by TableNextRow() void ImGui::TableBeginRow(ImGuiTable* table) { ImGuiWindow* window = table->InnerWindow; IM_ASSERT(!table->IsInsideRow); // New row table->CurrentRow++; table->CurrentColumn = -1; table->RowBgColor[0] = table->RowBgColor[1] = IM_COL32_DISABLE; table->RowCellDataCurrent = -1; table->IsInsideRow = true; // Begin frozen rows float next_y1 = table->RowPosY2; if (table->CurrentRow == 0 && table->FreezeRowsCount > 0) next_y1 = window->DC.CursorPos.y = table->OuterRect.Min.y; table->RowPosY1 = table->RowPosY2 = next_y1; table->RowTextBaseline = 0.0f; table->RowIndentOffsetX = window->DC.Indent.x - table->HostIndentX; // Lock indent window->DC.PrevLineTextBaseOffset = 0.0f; window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x, window->DC.CursorPos.y + table->RowCellPaddingY); // This allows users to call SameLine() to share LineSize between columns. window->DC.PrevLineSize = window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); // This allows users to call SameLine() to share LineSize between columns, and to call it from first column too. window->DC.IsSameLine = window->DC.IsSetPos = false; window->DC.CursorMaxPos.y = next_y1; // Making the header BG color non-transparent will allow us to overlay it multiple times when handling smooth dragging. if (table->RowFlags & ImGuiTableRowFlags_Headers) { TableSetBgColor(ImGuiTableBgTarget_RowBg0, GetColorU32(ImGuiCol_TableHeaderBg)); if (table->CurrentRow == 0) table->IsUsingHeaders = true; } } // [Internal] Called by TableNextRow() void ImGui::TableEndRow(ImGuiTable* table) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(window == table->InnerWindow); IM_ASSERT(table->IsInsideRow); if (table->CurrentColumn != -1) TableEndCell(table); // Logging if (g.LogEnabled) LogRenderedText(NULL, "|"); // Position cursor at the bottom of our row so it can be used for e.g. clipping calculation. However it is // likely that the next call to TableBeginCell() will reposition the cursor to take account of vertical padding. window->DC.CursorPos.y = table->RowPosY2; // Row background fill const float bg_y1 = table->RowPosY1; const float bg_y2 = table->RowPosY2; const bool unfreeze_rows_actual = (table->CurrentRow + 1 == table->FreezeRowsCount); const bool unfreeze_rows_request = (table->CurrentRow + 1 == table->FreezeRowsRequest); ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); if ((table->RowFlags & ImGuiTableRowFlags_Headers) && (table->CurrentRow == 0 || (table->LastRowFlags & ImGuiTableRowFlags_Headers))) table_instance->LastTopHeadersRowHeight += bg_y2 - bg_y1; const bool is_visible = (bg_y2 >= table->InnerClipRect.Min.y && bg_y1 <= table->InnerClipRect.Max.y); if (is_visible) { // Update data for TableGetHoveredRow() if (table->HoveredColumnBody != -1 && g.IO.MousePos.y >= bg_y1 && g.IO.MousePos.y < bg_y2) table_instance->HoveredRowNext = table->CurrentRow; // Decide of background color for the row ImU32 bg_col0 = 0; ImU32 bg_col1 = 0; if (table->RowBgColor[0] != IM_COL32_DISABLE) bg_col0 = table->RowBgColor[0]; else if (table->Flags & ImGuiTableFlags_RowBg) bg_col0 = GetColorU32((table->RowBgColorCounter & 1) ? ImGuiCol_TableRowBgAlt : ImGuiCol_TableRowBg); if (table->RowBgColor[1] != IM_COL32_DISABLE) bg_col1 = table->RowBgColor[1]; // Decide of top border color ImU32 top_border_col = 0; const float border_size = TABLE_BORDER_SIZE; if (table->CurrentRow > 0 && (table->Flags & ImGuiTableFlags_BordersInnerH)) top_border_col = (table->LastRowFlags & ImGuiTableRowFlags_Headers) ? table->BorderColorStrong : table->BorderColorLight; const bool draw_cell_bg_color = table->RowCellDataCurrent >= 0; const bool draw_strong_bottom_border = unfreeze_rows_actual; if ((bg_col0 | bg_col1 | top_border_col) != 0 || draw_strong_bottom_border || draw_cell_bg_color) { // In theory we could call SetWindowClipRectBeforeSetChannel() but since we know TableEndRow() is // always followed by a change of clipping rectangle we perform the smallest overwrite possible here. if ((table->Flags & ImGuiTableFlags_NoClip) == 0) window->DrawList->_CmdHeader.ClipRect = table->Bg0ClipRectForDrawCmd.ToVec4(); table->DrawSplitter->SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_BG0); } // Draw row background // We soft/cpu clip this so all backgrounds and borders can share the same clipping rectangle if (bg_col0 || bg_col1) { ImRect row_rect(table->WorkRect.Min.x, bg_y1, table->WorkRect.Max.x, bg_y2); row_rect.ClipWith(table->BgClipRect); if (bg_col0 != 0 && row_rect.Min.y < row_rect.Max.y) window->DrawList->AddRectFilled(row_rect.Min, row_rect.Max, bg_col0); if (bg_col1 != 0 && row_rect.Min.y < row_rect.Max.y) window->DrawList->AddRectFilled(row_rect.Min, row_rect.Max, bg_col1); } // Draw cell background color if (draw_cell_bg_color) { ImGuiTableCellData* cell_data_end = &table->RowCellData[table->RowCellDataCurrent]; for (ImGuiTableCellData* cell_data = &table->RowCellData[0]; cell_data <= cell_data_end; cell_data++) { // As we render the BG here we need to clip things (for layout we would not) // FIXME: This cancels the OuterPadding addition done by TableGetCellBgRect(), need to keep it while rendering correctly while scrolling. const ImGuiTableColumn* column = &table->Columns[cell_data->Column]; ImRect cell_bg_rect = TableGetCellBgRect(table, cell_data->Column); cell_bg_rect.ClipWith(table->BgClipRect); cell_bg_rect.Min.x = ImMax(cell_bg_rect.Min.x, column->ClipRect.Min.x); // So that first column after frozen one gets clipped when scrolling cell_bg_rect.Max.x = ImMin(cell_bg_rect.Max.x, column->MaxX); window->DrawList->AddRectFilled(cell_bg_rect.Min, cell_bg_rect.Max, cell_data->BgColor); } } // Draw top border if (top_border_col && bg_y1 >= table->BgClipRect.Min.y && bg_y1 < table->BgClipRect.Max.y) window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y1), ImVec2(table->BorderX2, bg_y1), top_border_col, border_size); // Draw bottom border at the row unfreezing mark (always strong) if (draw_strong_bottom_border && bg_y2 >= table->BgClipRect.Min.y && bg_y2 < table->BgClipRect.Max.y) window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y2), ImVec2(table->BorderX2, bg_y2), table->BorderColorStrong, border_size); } // End frozen rows (when we are past the last frozen row line, teleport cursor and alter clipping rectangle) // We need to do that in TableEndRow() instead of TableBeginRow() so the list clipper can mark end of row and // get the new cursor position. if (unfreeze_rows_request) for (int column_n = 0; column_n < table->ColumnsCount; column_n++) table->Columns[column_n].NavLayerCurrent = ImGuiNavLayer_Main; if (unfreeze_rows_actual) { IM_ASSERT(table->IsUnfrozenRows == false); const float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y); table->IsUnfrozenRows = true; table_instance->LastFrozenHeight = y0 - table->OuterRect.Min.y; // BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y); table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y; table->Bg2DrawChannelCurrent = table->Bg2DrawChannelUnfrozen; IM_ASSERT(table->Bg2ClipRectForDrawCmd.Min.y <= table->Bg2ClipRectForDrawCmd.Max.y); float row_height = table->RowPosY2 - table->RowPosY1; table->RowPosY2 = window->DC.CursorPos.y = table->WorkRect.Min.y + table->RowPosY2 - table->OuterRect.Min.y; table->RowPosY1 = table->RowPosY2 - row_height; for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { ImGuiTableColumn* column = &table->Columns[column_n]; column->DrawChannelCurrent = column->DrawChannelUnfrozen; column->ClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y; } // Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y SetWindowClipRectBeforeSetChannel(window, table->Columns[0].ClipRect); table->DrawSplitter->SetCurrentChannel(window->DrawList, table->Columns[0].DrawChannelCurrent); } if (!(table->RowFlags & ImGuiTableRowFlags_Headers)) table->RowBgColorCounter++; table->IsInsideRow = false; } //------------------------------------------------------------------------- // [SECTION] Tables: Columns changes //------------------------------------------------------------------------- // - TableGetColumnIndex() // - TableSetColumnIndex() // - TableNextColumn() // - TableBeginCell() [Internal] // - TableEndCell() [Internal] //------------------------------------------------------------------------- int ImGui::TableGetColumnIndex() { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; if (!table) return 0; return table->CurrentColumn; } // [Public] Append into a specific column bool ImGui::TableSetColumnIndex(int column_n) { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; if (!table) return false; if (table->CurrentColumn != column_n) { if (table->CurrentColumn != -1) TableEndCell(table); IM_ASSERT(column_n >= 0 && table->ColumnsCount); TableBeginCell(table, column_n); } // Return whether the column is visible. User may choose to skip submitting items based on this return value, // however they shouldn't skip submitting for columns that may have the tallest contribution to row height. return table->Columns[column_n].IsRequestOutput; } // [Public] Append into the next column, wrap and create a new row when already on last column bool ImGui::TableNextColumn() { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; if (!table) return false; if (table->IsInsideRow && table->CurrentColumn + 1 < table->ColumnsCount) { if (table->CurrentColumn != -1) TableEndCell(table); TableBeginCell(table, table->CurrentColumn + 1); } else { TableNextRow(); TableBeginCell(table, 0); } // Return whether the column is visible. User may choose to skip submitting items based on this return value, // however they shouldn't skip submitting for columns that may have the tallest contribution to row height. return table->Columns[table->CurrentColumn].IsRequestOutput; } // [Internal] Called by TableSetColumnIndex()/TableNextColumn() // This is called very frequently, so we need to be mindful of unnecessary overhead. // FIXME-TABLE FIXME-OPT: Could probably shortcut some things for non-active or clipped columns. void ImGui::TableBeginCell(ImGuiTable* table, int column_n) { ImGuiContext& g = *GImGui; ImGuiTableColumn* column = &table->Columns[column_n]; ImGuiWindow* window = table->InnerWindow; table->CurrentColumn = column_n; // Start position is roughly ~~ CellRect.Min + CellPadding + Indent float start_x = column->WorkMinX; if (column->Flags & ImGuiTableColumnFlags_IndentEnable) start_x += table->RowIndentOffsetX; // ~~ += window.DC.Indent.x - table->HostIndentX, except we locked it for the row. window->DC.CursorPos.x = start_x; window->DC.CursorPos.y = table->RowPosY1 + table->RowCellPaddingY; window->DC.CursorMaxPos.x = window->DC.CursorPos.x; window->DC.ColumnsOffset.x = start_x - window->Pos.x - window->DC.Indent.x; // FIXME-WORKRECT window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x; // PrevLine.y is preserved. This allows users to call SameLine() to share LineSize between columns. window->DC.CurrLineTextBaseOffset = table->RowTextBaseline; window->DC.NavLayerCurrent = (ImGuiNavLayer)column->NavLayerCurrent; // Note how WorkRect.Max.y is only set once during layout window->WorkRect.Min.y = window->DC.CursorPos.y; window->WorkRect.Min.x = column->WorkMinX; window->WorkRect.Max.x = column->WorkMaxX; window->DC.ItemWidth = column->ItemWidth; window->SkipItems = column->IsSkipItems; if (column->IsSkipItems) { g.LastItemData.ID = 0; g.LastItemData.StatusFlags = 0; } if (table->Flags & ImGuiTableFlags_NoClip) { // FIXME: if we end up drawing all borders/bg in EndTable, could remove this and just assert that channel hasn't changed. table->DrawSplitter->SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP); //IM_ASSERT(table->DrawSplitter._Current == TABLE_DRAW_CHANNEL_NOCLIP); } else { // FIXME-TABLE: Could avoid this if draw channel is dummy channel? SetWindowClipRectBeforeSetChannel(window, column->ClipRect); table->DrawSplitter->SetCurrentChannel(window->DrawList, column->DrawChannelCurrent); } // Logging if (g.LogEnabled && !column->IsSkipItems) { LogRenderedText(&window->DC.CursorPos, "|"); g.LogLinePosY = FLT_MAX; } } // [Internal] Called by TableNextRow()/TableSetColumnIndex()/TableNextColumn() void ImGui::TableEndCell(ImGuiTable* table) { ImGuiTableColumn* column = &table->Columns[table->CurrentColumn]; ImGuiWindow* window = table->InnerWindow; if (window->DC.IsSetPos) ErrorCheckUsingSetCursorPosToExtendParentBoundaries(); // Report maximum position so we can infer content size per column. float* p_max_pos_x; if (table->RowFlags & ImGuiTableRowFlags_Headers) p_max_pos_x = &column->ContentMaxXHeadersUsed; // Useful in case user submit contents in header row that is not a TableHeader() call else p_max_pos_x = table->IsUnfrozenRows ? &column->ContentMaxXUnfrozen : &column->ContentMaxXFrozen; *p_max_pos_x = ImMax(*p_max_pos_x, window->DC.CursorMaxPos.x); if (column->IsEnabled) table->RowPosY2 = ImMax(table->RowPosY2, window->DC.CursorMaxPos.y + table->RowCellPaddingY); column->ItemWidth = window->DC.ItemWidth; // Propagate text baseline for the entire row // FIXME-TABLE: Here we propagate text baseline from the last line of the cell.. instead of the first one. table->RowTextBaseline = ImMax(table->RowTextBaseline, window->DC.PrevLineTextBaseOffset); } //------------------------------------------------------------------------- // [SECTION] Tables: Columns width management //------------------------------------------------------------------------- // - TableGetMaxColumnWidth() [Internal] // - TableGetColumnWidthAuto() [Internal] // - TableSetColumnWidth() // - TableSetColumnWidthAutoSingle() [Internal] // - TableSetColumnWidthAutoAll() [Internal] // - TableUpdateColumnsWeightFromWidth() [Internal] //------------------------------------------------------------------------- // Maximum column content width given current layout. Use column->MinX so this value on a per-column basis. float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n) { const ImGuiTableColumn* column = &table->Columns[column_n]; float max_width = FLT_MAX; const float min_column_distance = table->MinColumnWidth + table->CellPaddingX * 2.0f + table->CellSpacingX1 + table->CellSpacingX2; if (table->Flags & ImGuiTableFlags_ScrollX) { // Frozen columns can't reach beyond visible width else scrolling will naturally break. // (we use DisplayOrder as within a set of multiple frozen column reordering is possible) if (column->DisplayOrder < table->FreezeColumnsRequest) { max_width = (table->InnerClipRect.Max.x - (table->FreezeColumnsRequest - column->DisplayOrder) * min_column_distance) - column->MinX; max_width = max_width - table->OuterPaddingX - table->CellPaddingX - table->CellSpacingX2; } } else if ((table->Flags & ImGuiTableFlags_NoKeepColumnsVisible) == 0) { // If horizontal scrolling if disabled, we apply a final lossless shrinking of columns in order to make // sure they are all visible. Because of this we also know that all of the columns will always fit in // table->WorkRect and therefore in table->InnerRect (because ScrollX is off) // FIXME-TABLE: This is solved incorrectly but also quite a difficult problem to fix as we also want ClipRect width to match. // See "table_width_distrib" and "table_width_keep_visible" tests max_width = table->WorkRect.Max.x - (table->ColumnsEnabledCount - column->IndexWithinEnabledSet - 1) * min_column_distance - column->MinX; //max_width -= table->CellSpacingX1; max_width -= table->CellSpacingX2; max_width -= table->CellPaddingX * 2.0f; max_width -= table->OuterPaddingX; } return max_width; } // Note this is meant to be stored in column->WidthAuto, please generally use the WidthAuto field float ImGui::TableGetColumnWidthAuto(ImGuiTable* table, ImGuiTableColumn* column) { const float content_width_body = ImMax(column->ContentMaxXFrozen, column->ContentMaxXUnfrozen) - column->WorkMinX; const float content_width_headers = column->ContentMaxXHeadersIdeal - column->WorkMinX; float width_auto = content_width_body; if (!(column->Flags & ImGuiTableColumnFlags_NoHeaderWidth)) width_auto = ImMax(width_auto, content_width_headers); // Non-resizable fixed columns preserve their requested width if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && column->InitStretchWeightOrWidth > 0.0f) if (!(table->Flags & ImGuiTableFlags_Resizable) || (column->Flags & ImGuiTableColumnFlags_NoResize)) width_auto = column->InitStretchWeightOrWidth; return ImMax(width_auto, table->MinColumnWidth); } // 'width' = inner column width, without padding void ImGui::TableSetColumnWidth(int column_n, float width) { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; IM_ASSERT(table != NULL && table->IsLayoutLocked == false); IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount); ImGuiTableColumn* column_0 = &table->Columns[column_n]; float column_0_width = width; // Apply constraints early // Compare both requested and actual given width to avoid overwriting requested width when column is stuck (minimum size, bounded) IM_ASSERT(table->MinColumnWidth > 0.0f); const float min_width = table->MinColumnWidth; const float max_width = ImMax(min_width, TableGetMaxColumnWidth(table, column_n)); column_0_width = ImClamp(column_0_width, min_width, max_width); if (column_0->WidthGiven == column_0_width || column_0->WidthRequest == column_0_width) return; //IMGUI_DEBUG_PRINT("TableSetColumnWidth(%d, %.1f->%.1f)\n", column_0_idx, column_0->WidthGiven, column_0_width); ImGuiTableColumn* column_1 = (column_0->NextEnabledColumn != -1) ? &table->Columns[column_0->NextEnabledColumn] : NULL; // In this surprisingly not simple because of how we support mixing Fixed and multiple Stretch columns. // - All fixed: easy. // - All stretch: easy. // - One or more fixed + one stretch: easy. // - One or more fixed + more than one stretch: tricky. // Qt when manual resize is enabled only supports a single _trailing_ stretch column, we support more cases here. // When forwarding resize from Wn| to Fn+1| we need to be considerate of the _NoResize flag on Fn+1. // FIXME-TABLE: Find a way to rewrite all of this so interactions feel more consistent for the user. // Scenarios: // - F1 F2 F3 resize from F1| or F2| --> ok: alter ->WidthRequested of Fixed column. Subsequent columns will be offset. // - F1 F2 F3 resize from F3| --> ok: alter ->WidthRequested of Fixed column. If active, ScrollX extent can be altered. // - F1 F2 W3 resize from F1| or F2| --> ok: alter ->WidthRequested of Fixed column. If active, ScrollX extent can be altered, but it doesn't make much sense as the Stretch column will always be minimal size. // - F1 F2 W3 resize from W3| --> ok: no-op (disabled by Resize Rule 1) // - W1 W2 W3 resize from W1| or W2| --> ok // - W1 W2 W3 resize from W3| --> ok: no-op (disabled by Resize Rule 1) // - W1 F2 F3 resize from F3| --> ok: no-op (disabled by Resize Rule 1) // - W1 F2 resize from F2| --> ok: no-op (disabled by Resize Rule 1) // - W1 W2 F3 resize from W1| or W2| --> ok // - W1 F2 W3 resize from W1| or F2| --> ok // - F1 W2 F3 resize from W2| --> ok // - F1 W3 F2 resize from W3| --> ok // - W1 F2 F3 resize from W1| --> ok: equivalent to resizing |F2. F3 will not move. // - W1 F2 F3 resize from F2| --> ok // All resizes from a Wx columns are locking other columns. // Possible improvements: // - W1 W2 W3 resize W1| --> to not be stuck, both W2 and W3 would stretch down. Seems possible to fix. Would be most beneficial to simplify resize of all-weighted columns. // - W3 F1 F2 resize W3| --> to not be stuck past F1|, both F1 and F2 would need to stretch down, which would be lossy or ambiguous. Seems hard to fix. // [Resize Rule 1] Can't resize from right of right-most visible column if there is any Stretch column. Implemented in TableUpdateLayout(). // If we have all Fixed columns OR resizing a Fixed column that doesn't come after a Stretch one, we can do an offsetting resize. // This is the preferred resize path if (column_0->Flags & ImGuiTableColumnFlags_WidthFixed) if (!column_1 || table->LeftMostStretchedColumn == -1 || table->Columns[table->LeftMostStretchedColumn].DisplayOrder >= column_0->DisplayOrder) { column_0->WidthRequest = column_0_width; table->IsSettingsDirty = true; return; } // We can also use previous column if there's no next one (this is used when doing an auto-fit on the right-most stretch column) if (column_1 == NULL) column_1 = (column_0->PrevEnabledColumn != -1) ? &table->Columns[column_0->PrevEnabledColumn] : NULL; if (column_1 == NULL) return; // Resizing from right-side of a Stretch column before a Fixed column forward sizing to left-side of fixed column. // (old_a + old_b == new_a + new_b) --> (new_a == old_a + old_b - new_b) float column_1_width = ImMax(column_1->WidthRequest - (column_0_width - column_0->WidthRequest), min_width); column_0_width = column_0->WidthRequest + column_1->WidthRequest - column_1_width; IM_ASSERT(column_0_width > 0.0f && column_1_width > 0.0f); column_0->WidthRequest = column_0_width; column_1->WidthRequest = column_1_width; if ((column_0->Flags | column_1->Flags) & ImGuiTableColumnFlags_WidthStretch) TableUpdateColumnsWeightFromWidth(table); table->IsSettingsDirty = true; } // Disable clipping then auto-fit, will take 2 frames // (we don't take a shortcut for unclipped columns to reduce inconsistencies when e.g. resizing multiple columns) void ImGui::TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n) { // Single auto width uses auto-fit ImGuiTableColumn* column = &table->Columns[column_n]; if (!column->IsEnabled) return; column->CannotSkipItemsQueue = (1 << 0); table->AutoFitSingleColumn = (ImGuiTableColumnIdx)column_n; } void ImGui::TableSetColumnWidthAutoAll(ImGuiTable* table) { for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { ImGuiTableColumn* column = &table->Columns[column_n]; if (!column->IsEnabled && !(column->Flags & ImGuiTableColumnFlags_WidthStretch)) // Cannot reset weight of hidden stretch column continue; column->CannotSkipItemsQueue = (1 << 0); column->AutoFitQueue = (1 << 1); } } void ImGui::TableUpdateColumnsWeightFromWidth(ImGuiTable* table) { IM_ASSERT(table->LeftMostStretchedColumn != -1 && table->RightMostStretchedColumn != -1); // Measure existing quantities float visible_weight = 0.0f; float visible_width = 0.0f; for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { ImGuiTableColumn* column = &table->Columns[column_n]; if (!column->IsEnabled || !(column->Flags & ImGuiTableColumnFlags_WidthStretch)) continue; IM_ASSERT(column->StretchWeight > 0.0f); visible_weight += column->StretchWeight; visible_width += column->WidthRequest; } IM_ASSERT(visible_weight > 0.0f && visible_width > 0.0f); // Apply new weights for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { ImGuiTableColumn* column = &table->Columns[column_n]; if (!column->IsEnabled || !(column->Flags & ImGuiTableColumnFlags_WidthStretch)) continue; column->StretchWeight = (column->WidthRequest / visible_width) * visible_weight; IM_ASSERT(column->StretchWeight > 0.0f); } } //------------------------------------------------------------------------- // [SECTION] Tables: Drawing //------------------------------------------------------------------------- // - TablePushBackgroundChannel() [Internal] // - TablePopBackgroundChannel() [Internal] // - TableSetupDrawChannels() [Internal] // - TableMergeDrawChannels() [Internal] // - TableGetColumnBorderCol() [Internal] // - TableDrawBorders() [Internal] //------------------------------------------------------------------------- // Bg2 is used by Selectable (and possibly other widgets) to render to the background. // Unlike our Bg0/1 channel which we uses for RowBg/CellBg/Borders and where we guarantee all shapes to be CPU-clipped, the Bg2 channel being widgets-facing will rely on regular ClipRect. void ImGui::TablePushBackgroundChannel() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiTable* table = g.CurrentTable; // Optimization: avoid SetCurrentChannel() + PushClipRect() table->HostBackupInnerClipRect = window->ClipRect; SetWindowClipRectBeforeSetChannel(window, table->Bg2ClipRectForDrawCmd); table->DrawSplitter->SetCurrentChannel(window->DrawList, table->Bg2DrawChannelCurrent); } void ImGui::TablePopBackgroundChannel() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiTable* table = g.CurrentTable; ImGuiTableColumn* column = &table->Columns[table->CurrentColumn]; // Optimization: avoid PopClipRect() + SetCurrentChannel() SetWindowClipRectBeforeSetChannel(window, table->HostBackupInnerClipRect); table->DrawSplitter->SetCurrentChannel(window->DrawList, column->DrawChannelCurrent); } // Allocate draw channels. Called by TableUpdateLayout() // - We allocate them following storage order instead of display order so reordering columns won't needlessly // increase overall dormant memory cost. // - We isolate headers draw commands in their own channels instead of just altering clip rects. // This is in order to facilitate merging of draw commands. // - After crossing FreezeRowsCount, all columns see their current draw channel changed to a second set of channels. // - We only use the dummy draw channel so we can push a null clipping rectangle into it without affecting other // channels, while simplifying per-row/per-cell overhead. It will be empty and discarded when merged. // - We allocate 1 or 2 background draw channels. This is because we know TablePushBackgroundChannel() is only used for // horizontal spanning. If we allowed vertical spanning we'd need one background draw channel per merge group (1-4). // Draw channel allocation (before merging): // - NoClip --> 2+D+1 channels: bg0/1 + bg2 + foreground (same clip rect == always 1 draw call) // - Clip --> 2+D+N channels // - FreezeRows --> 2+D+N*2 (unless scrolling value is zero) // - FreezeRows || FreezeColunns --> 3+D+N*2 (unless scrolling value is zero) // Where D is 1 if any column is clipped or hidden (dummy channel) otherwise 0. void ImGui::TableSetupDrawChannels(ImGuiTable* table) { const int freeze_row_multiplier = (table->FreezeRowsCount > 0) ? 2 : 1; const int channels_for_row = (table->Flags & ImGuiTableFlags_NoClip) ? 1 : table->ColumnsEnabledCount; const int channels_for_bg = 1 + 1 * freeze_row_multiplier; const int channels_for_dummy = (table->ColumnsEnabledCount < table->ColumnsCount || (memcmp(table->VisibleMaskByIndex, table->EnabledMaskByIndex, ImBitArrayGetStorageSizeInBytes(table->ColumnsCount)) != 0)) ? +1 : 0; const int channels_total = channels_for_bg + (channels_for_row * freeze_row_multiplier) + channels_for_dummy; table->DrawSplitter->Split(table->InnerWindow->DrawList, channels_total); table->DummyDrawChannel = (ImGuiTableDrawChannelIdx)((channels_for_dummy > 0) ? channels_total - 1 : -1); table->Bg2DrawChannelCurrent = TABLE_DRAW_CHANNEL_BG2_FROZEN; table->Bg2DrawChannelUnfrozen = (ImGuiTableDrawChannelIdx)((table->FreezeRowsCount > 0) ? 2 + channels_for_row : TABLE_DRAW_CHANNEL_BG2_FROZEN); int draw_channel_current = 2; for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { ImGuiTableColumn* column = &table->Columns[column_n]; if (column->IsVisibleX && column->IsVisibleY) { column->DrawChannelFrozen = (ImGuiTableDrawChannelIdx)(draw_channel_current); column->DrawChannelUnfrozen = (ImGuiTableDrawChannelIdx)(draw_channel_current + (table->FreezeRowsCount > 0 ? channels_for_row + 1 : 0)); if (!(table->Flags & ImGuiTableFlags_NoClip)) draw_channel_current++; } else { column->DrawChannelFrozen = column->DrawChannelUnfrozen = table->DummyDrawChannel; } column->DrawChannelCurrent = column->DrawChannelFrozen; } // Initial draw cmd starts with a BgClipRect that matches the one of its host, to facilitate merge draw commands by default. // All our cell highlight are manually clipped with BgClipRect. When unfreezing it will be made smaller to fit scrolling rect. // (This technically isn't part of setting up draw channels, but is reasonably related to be done here) table->BgClipRect = table->InnerClipRect; table->Bg0ClipRectForDrawCmd = table->OuterWindow->ClipRect; table->Bg2ClipRectForDrawCmd = table->HostClipRect; IM_ASSERT(table->BgClipRect.Min.y <= table->BgClipRect.Max.y); } // This function reorder draw channels based on matching clip rectangle, to facilitate merging them. Called by EndTable(). // For simplicity we call it TableMergeDrawChannels() but in fact it only reorder channels + overwrite ClipRect, // actual merging is done by table->DrawSplitter.Merge() which is called right after TableMergeDrawChannels(). // // Columns where the contents didn't stray off their local clip rectangle can be merged. To achieve // this we merge their clip rect and make them contiguous in the channel list, so they can be merged // by the call to DrawSplitter.Merge() following to the call to this function. // We reorder draw commands by arranging them into a maximum of 4 distinct groups: // // 1 group: 2 groups: 2 groups: 4 groups: // [ 0. ] no freeze [ 0. ] row freeze [ 01 ] col freeze [ 01 ] row+col freeze // [ .. ] or no scroll [ 2. ] and v-scroll [ .. ] and h-scroll [ 23 ] and v+h-scroll // // Each column itself can use 1 channel (row freeze disabled) or 2 channels (row freeze enabled). // When the contents of a column didn't stray off its limit, we move its channels into the corresponding group // based on its position (within frozen rows/columns groups or not). // At the end of the operation our 1-4 groups will each have a ImDrawCmd using the same ClipRect. // This function assume that each column are pointing to a distinct draw channel, // otherwise merge_group->ChannelsCount will not match set bit count of merge_group->ChannelsMask. // // Column channels will not be merged into one of the 1-4 groups in the following cases: // - The contents stray off its clipping rectangle (we only compare the MaxX value, not the MinX value). // Direct ImDrawList calls won't be taken into account by default, if you use them make sure the ImGui:: bounds // matches, by e.g. calling SetCursorScreenPos(). // - The channel uses more than one draw command itself. We drop all our attempt at merging stuff here.. // we could do better but it's going to be rare and probably not worth the hassle. // Columns for which the draw channel(s) haven't been merged with other will use their own ImDrawCmd. // // This function is particularly tricky to understand.. take a breath. void ImGui::TableMergeDrawChannels(ImGuiTable* table) { ImGuiContext& g = *GImGui; ImDrawListSplitter* splitter = table->DrawSplitter; const bool has_freeze_v = (table->FreezeRowsCount > 0); const bool has_freeze_h = (table->FreezeColumnsCount > 0); IM_ASSERT(splitter->_Current == 0); // Track which groups we are going to attempt to merge, and which channels goes into each group. struct MergeGroup { ImRect ClipRect; int ChannelsCount = 0; ImBitArrayPtr ChannelsMask = NULL; }; int merge_group_mask = 0x00; MergeGroup merge_groups[4]; // Use a reusable temp buffer for the merge masks as they are dynamically sized. const int max_draw_channels = (4 + table->ColumnsCount * 2); const int size_for_masks_bitarrays_one = (int)ImBitArrayGetStorageSizeInBytes(max_draw_channels); g.TempBuffer.reserve(size_for_masks_bitarrays_one * 5); memset(g.TempBuffer.Data, 0, size_for_masks_bitarrays_one * 5); for (int n = 0; n < IM_ARRAYSIZE(merge_groups); n++) merge_groups[n].ChannelsMask = (ImBitArrayPtr)(void*)(g.TempBuffer.Data + (size_for_masks_bitarrays_one * n)); ImBitArrayPtr remaining_mask = (ImBitArrayPtr)(void*)(g.TempBuffer.Data + (size_for_masks_bitarrays_one * 4)); // 1. Scan channels and take note of those which can be merged for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { if (!IM_BITARRAY_TESTBIT(table->VisibleMaskByIndex, column_n)) continue; ImGuiTableColumn* column = &table->Columns[column_n]; const int merge_group_sub_count = has_freeze_v ? 2 : 1; for (int merge_group_sub_n = 0; merge_group_sub_n < merge_group_sub_count; merge_group_sub_n++) { const int channel_no = (merge_group_sub_n == 0) ? column->DrawChannelFrozen : column->DrawChannelUnfrozen; // Don't attempt to merge if there are multiple draw calls within the column ImDrawChannel* src_channel = &splitter->_Channels[channel_no]; if (src_channel->_CmdBuffer.Size > 0 && src_channel->_CmdBuffer.back().ElemCount == 0 && src_channel->_CmdBuffer.back().UserCallback == NULL) // Equivalent of PopUnusedDrawCmd() src_channel->_CmdBuffer.pop_back(); if (src_channel->_CmdBuffer.Size != 1) continue; // Find out the width of this merge group and check if it will fit in our column // (note that we assume that rendering didn't stray on the left direction. we should need a CursorMinPos to detect it) if (!(column->Flags & ImGuiTableColumnFlags_NoClip)) { float content_max_x; if (!has_freeze_v) content_max_x = ImMax(column->ContentMaxXUnfrozen, column->ContentMaxXHeadersUsed); // No row freeze else if (merge_group_sub_n == 0) content_max_x = ImMax(column->ContentMaxXFrozen, column->ContentMaxXHeadersUsed); // Row freeze: use width before freeze else content_max_x = column->ContentMaxXUnfrozen; // Row freeze: use width after freeze if (content_max_x > column->ClipRect.Max.x) continue; } const int merge_group_n = (has_freeze_h && column_n < table->FreezeColumnsCount ? 0 : 1) + (has_freeze_v && merge_group_sub_n == 0 ? 0 : 2); IM_ASSERT(channel_no < max_draw_channels); MergeGroup* merge_group = &merge_groups[merge_group_n]; if (merge_group->ChannelsCount == 0) merge_group->ClipRect = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX); ImBitArraySetBit(merge_group->ChannelsMask, channel_no); merge_group->ChannelsCount++; merge_group->ClipRect.Add(src_channel->_CmdBuffer[0].ClipRect); merge_group_mask |= (1 << merge_group_n); } // Invalidate current draw channel // (we don't clear DrawChannelFrozen/DrawChannelUnfrozen solely to facilitate debugging/later inspection of data) column->DrawChannelCurrent = (ImGuiTableDrawChannelIdx)-1; } // [DEBUG] Display merge groups #if 0 if (g.IO.KeyShift) for (int merge_group_n = 0; merge_group_n < IM_ARRAYSIZE(merge_groups); merge_group_n++) { MergeGroup* merge_group = &merge_groups[merge_group_n]; if (merge_group->ChannelsCount == 0) continue; char buf[32]; ImFormatString(buf, 32, "MG%d:%d", merge_group_n, merge_group->ChannelsCount); ImVec2 text_pos = merge_group->ClipRect.Min + ImVec2(4, 4); ImVec2 text_size = CalcTextSize(buf, NULL); GetForegroundDrawList()->AddRectFilled(text_pos, text_pos + text_size, IM_COL32(0, 0, 0, 255)); GetForegroundDrawList()->AddText(text_pos, IM_COL32(255, 255, 0, 255), buf, NULL); GetForegroundDrawList()->AddRect(merge_group->ClipRect.Min, merge_group->ClipRect.Max, IM_COL32(255, 255, 0, 255)); } #endif // 2. Rewrite channel list in our preferred order if (merge_group_mask != 0) { // We skip channel 0 (Bg0/Bg1) and 1 (Bg2 frozen) from the shuffling since they won't move - see channels allocation in TableSetupDrawChannels(). const int LEADING_DRAW_CHANNELS = 2; g.DrawChannelsTempMergeBuffer.resize(splitter->_Count - LEADING_DRAW_CHANNELS); // Use shared temporary storage so the allocation gets amortized ImDrawChannel* dst_tmp = g.DrawChannelsTempMergeBuffer.Data; ImBitArraySetBitRange(remaining_mask, LEADING_DRAW_CHANNELS, splitter->_Count); ImBitArrayClearBit(remaining_mask, table->Bg2DrawChannelUnfrozen); IM_ASSERT(has_freeze_v == false || table->Bg2DrawChannelUnfrozen != TABLE_DRAW_CHANNEL_BG2_FROZEN); int remaining_count = splitter->_Count - (has_freeze_v ? LEADING_DRAW_CHANNELS + 1 : LEADING_DRAW_CHANNELS); //ImRect host_rect = (table->InnerWindow == table->OuterWindow) ? table->InnerClipRect : table->HostClipRect; ImRect host_rect = table->HostClipRect; for (int merge_group_n = 0; merge_group_n < IM_ARRAYSIZE(merge_groups); merge_group_n++) { if (int merge_channels_count = merge_groups[merge_group_n].ChannelsCount) { MergeGroup* merge_group = &merge_groups[merge_group_n]; ImRect merge_clip_rect = merge_group->ClipRect; // Extend outer-most clip limits to match those of host, so draw calls can be merged even if // outer-most columns have some outer padding offsetting them from their parent ClipRect. // The principal cases this is dealing with are: // - On a same-window table (not scrolling = single group), all fitting columns ClipRect -> will extend and match host ClipRect -> will merge // - Columns can use padding and have left-most ClipRect.Min.x and right-most ClipRect.Max.x != from host ClipRect -> will extend and match host ClipRect -> will merge // FIXME-TABLE FIXME-WORKRECT: We are wasting a merge opportunity on tables without scrolling if column doesn't fit // within host clip rect, solely because of the half-padding difference between window->WorkRect and window->InnerClipRect. if ((merge_group_n & 1) == 0 || !has_freeze_h) merge_clip_rect.Min.x = ImMin(merge_clip_rect.Min.x, host_rect.Min.x); if ((merge_group_n & 2) == 0 || !has_freeze_v) merge_clip_rect.Min.y = ImMin(merge_clip_rect.Min.y, host_rect.Min.y); if ((merge_group_n & 1) != 0) merge_clip_rect.Max.x = ImMax(merge_clip_rect.Max.x, host_rect.Max.x); if ((merge_group_n & 2) != 0 && (table->Flags & ImGuiTableFlags_NoHostExtendY) == 0) merge_clip_rect.Max.y = ImMax(merge_clip_rect.Max.y, host_rect.Max.y); //GetForegroundDrawList()->AddRect(merge_group->ClipRect.Min, merge_group->ClipRect.Max, IM_COL32(255, 0, 0, 200), 0.0f, 0, 1.0f); // [DEBUG] //GetForegroundDrawList()->AddLine(merge_group->ClipRect.Min, merge_clip_rect.Min, IM_COL32(255, 100, 0, 200)); //GetForegroundDrawList()->AddLine(merge_group->ClipRect.Max, merge_clip_rect.Max, IM_COL32(255, 100, 0, 200)); remaining_count -= merge_group->ChannelsCount; for (int n = 0; n < (size_for_masks_bitarrays_one >> 2); n++) remaining_mask[n] &= ~merge_group->ChannelsMask[n]; for (int n = 0; n < splitter->_Count && merge_channels_count != 0; n++) { // Copy + overwrite new clip rect if (!IM_BITARRAY_TESTBIT(merge_group->ChannelsMask, n)) continue; IM_BITARRAY_CLEARBIT(merge_group->ChannelsMask, n); merge_channels_count--; ImDrawChannel* channel = &splitter->_Channels[n]; IM_ASSERT(channel->_CmdBuffer.Size == 1 && merge_clip_rect.Contains(ImRect(channel->_CmdBuffer[0].ClipRect))); channel->_CmdBuffer[0].ClipRect = merge_clip_rect.ToVec4(); memcpy(dst_tmp++, channel, sizeof(ImDrawChannel)); } } // Make sure Bg2DrawChannelUnfrozen appears in the middle of our groups (whereas Bg0/Bg1 and Bg2 frozen are fixed to 0 and 1) if (merge_group_n == 1 && has_freeze_v) memcpy(dst_tmp++, &splitter->_Channels[table->Bg2DrawChannelUnfrozen], sizeof(ImDrawChannel)); } // Append unmergeable channels that we didn't reorder at the end of the list for (int n = 0; n < splitter->_Count && remaining_count != 0; n++) { if (!IM_BITARRAY_TESTBIT(remaining_mask, n)) continue; ImDrawChannel* channel = &splitter->_Channels[n]; memcpy(dst_tmp++, channel, sizeof(ImDrawChannel)); remaining_count--; } IM_ASSERT(dst_tmp == g.DrawChannelsTempMergeBuffer.Data + g.DrawChannelsTempMergeBuffer.Size); memcpy(splitter->_Channels.Data + LEADING_DRAW_CHANNELS, g.DrawChannelsTempMergeBuffer.Data, (splitter->_Count - LEADING_DRAW_CHANNELS) * sizeof(ImDrawChannel)); } } static ImU32 TableGetColumnBorderCol(ImGuiTable* table, int order_n, int column_n) { const bool is_hovered = (table->HoveredColumnBorder == column_n); const bool is_resized = (table->ResizedColumn == column_n) && (table->InstanceInteracted == table->InstanceCurrent); const bool is_frozen_separator = (table->FreezeColumnsCount == order_n + 1); if (is_resized || is_hovered) return ImGui::GetColorU32(is_resized ? ImGuiCol_SeparatorActive : ImGuiCol_SeparatorHovered); if (is_frozen_separator || (table->Flags & (ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_NoBordersInBodyUntilResize))) return table->BorderColorStrong; return table->BorderColorLight; } // FIXME-TABLE: This is a mess, need to redesign how we render borders (as some are also done in TableEndRow) void ImGui::TableDrawBorders(ImGuiTable* table) { ImGuiWindow* inner_window = table->InnerWindow; if (!table->OuterWindow->ClipRect.Overlaps(table->OuterRect)) return; ImDrawList* inner_drawlist = inner_window->DrawList; table->DrawSplitter->SetCurrentChannel(inner_drawlist, TABLE_DRAW_CHANNEL_BG0); inner_drawlist->PushClipRect(table->Bg0ClipRectForDrawCmd.Min, table->Bg0ClipRectForDrawCmd.Max, false); // Draw inner border and resizing feedback ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); const float border_size = TABLE_BORDER_SIZE; const float draw_y1 = ImMax(table->InnerRect.Min.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table->AngledHeadersHeight) + ((table->Flags & ImGuiTableFlags_BordersOuterH) ? 1.0f : 0.0f); const float draw_y2_body = table->InnerRect.Max.y; const float draw_y2_head = table->IsUsingHeaders ? ImMin(table->InnerRect.Max.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table_instance->LastTopHeadersRowHeight) : draw_y1; if (table->Flags & ImGuiTableFlags_BordersInnerV) { for (int order_n = 0; order_n < table->ColumnsCount; order_n++) { if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByDisplayOrder, order_n)) continue; const int column_n = table->DisplayOrderToIndex[order_n]; ImGuiTableColumn* column = &table->Columns[column_n]; const bool is_hovered = (table->HoveredColumnBorder == column_n); const bool is_resized = (table->ResizedColumn == column_n) && (table->InstanceInteracted == table->InstanceCurrent); const bool is_resizable = (column->Flags & (ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_NoDirectResize_)) == 0; const bool is_frozen_separator = (table->FreezeColumnsCount == order_n + 1); if (column->MaxX > table->InnerClipRect.Max.x && !is_resized) continue; // Decide whether right-most column is visible if (column->NextEnabledColumn == -1 && !is_resizable) if ((table->Flags & ImGuiTableFlags_SizingMask_) != ImGuiTableFlags_SizingFixedSame || (table->Flags & ImGuiTableFlags_NoHostExtendX)) continue; if (column->MaxX <= column->ClipRect.Min.x) // FIXME-TABLE FIXME-STYLE: Assume BorderSize==1, this is problematic if we want to increase the border size.. continue; // Draw in outer window so right-most column won't be clipped // Always draw full height border when being resized/hovered, or on the delimitation of frozen column scrolling. float draw_y2 = (is_hovered || is_resized || is_frozen_separator || (table->Flags & (ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_NoBordersInBodyUntilResize)) == 0) ? draw_y2_body : draw_y2_head; if (draw_y2 > draw_y1) inner_drawlist->AddLine(ImVec2(column->MaxX, draw_y1), ImVec2(column->MaxX, draw_y2), TableGetColumnBorderCol(table, order_n, column_n), border_size); } } // Draw outer border // FIXME: could use AddRect or explicit VLine/HLine helper? if (table->Flags & ImGuiTableFlags_BordersOuter) { // Display outer border offset by 1 which is a simple way to display it without adding an extra draw call // (Without the offset, in outer_window it would be rendered behind cells, because child windows are above their // parent. In inner_window, it won't reach out over scrollbars. Another weird solution would be to display part // of it in inner window, and the part that's over scrollbars in the outer window..) // Either solution currently won't allow us to use a larger border size: the border would clipped. const ImRect outer_border = table->OuterRect; const ImU32 outer_col = table->BorderColorStrong; if ((table->Flags & ImGuiTableFlags_BordersOuter) == ImGuiTableFlags_BordersOuter) { inner_drawlist->AddRect(outer_border.Min, outer_border.Max + ImVec2(1, 1), outer_col, 0.0f, 0, border_size); } else if (table->Flags & ImGuiTableFlags_BordersOuterV) { inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Min.x, outer_border.Max.y), outer_col, border_size); inner_drawlist->AddLine(ImVec2(outer_border.Max.x, outer_border.Min.y), outer_border.Max, outer_col, border_size); } else if (table->Flags & ImGuiTableFlags_BordersOuterH) { inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Max.x, outer_border.Min.y), outer_col, border_size); inner_drawlist->AddLine(ImVec2(outer_border.Min.x, outer_border.Max.y), outer_border.Max, outer_col, border_size); } } if ((table->Flags & ImGuiTableFlags_BordersInnerH) && table->RowPosY2 < table->OuterRect.Max.y) { // Draw bottom-most row border between it is above outer border. const float border_y = table->RowPosY2; if (border_y >= table->BgClipRect.Min.y && border_y < table->BgClipRect.Max.y) inner_drawlist->AddLine(ImVec2(table->BorderX1, border_y), ImVec2(table->BorderX2, border_y), table->BorderColorLight, border_size); } inner_drawlist->PopClipRect(); } //------------------------------------------------------------------------- // [SECTION] Tables: Sorting //------------------------------------------------------------------------- // - TableGetSortSpecs() // - TableFixColumnSortDirection() [Internal] // - TableGetColumnNextSortDirection() [Internal] // - TableSetColumnSortDirection() [Internal] // - TableSortSpecsSanitize() [Internal] // - TableSortSpecsBuild() [Internal] //------------------------------------------------------------------------- // Return NULL if no sort specs (most often when ImGuiTableFlags_Sortable is not set) // When 'sort_specs->SpecsDirty == true' you should sort your data. It will be true when sorting specs have // changed since last call, or the first time. Make sure to set 'SpecsDirty = false' after sorting, // else you may wastefully sort your data every frame! // Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable()! ImGuiTableSortSpecs* ImGui::TableGetSortSpecs() { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; IM_ASSERT(table != NULL); if (!(table->Flags & ImGuiTableFlags_Sortable)) return NULL; // Require layout (in case TableHeadersRow() hasn't been called) as it may alter IsSortSpecsDirty in some paths. if (!table->IsLayoutLocked) TableUpdateLayout(table); TableSortSpecsBuild(table); return &table->SortSpecs; } static inline ImGuiSortDirection TableGetColumnAvailSortDirection(ImGuiTableColumn* column, int n) { IM_ASSERT(n < column->SortDirectionsAvailCount); return (column->SortDirectionsAvailList >> (n << 1)) & 0x03; } // Fix sort direction if currently set on a value which is unavailable (e.g. activating NoSortAscending/NoSortDescending) void ImGui::TableFixColumnSortDirection(ImGuiTable* table, ImGuiTableColumn* column) { if (column->SortOrder == -1 || (column->SortDirectionsAvailMask & (1 << column->SortDirection)) != 0) return; column->SortDirection = (ImU8)TableGetColumnAvailSortDirection(column, 0); table->IsSortSpecsDirty = true; } // Calculate next sort direction that would be set after clicking the column // - If the PreferSortDescending flag is set, we will default to a Descending direction on the first click. // - Note that the PreferSortAscending flag is never checked, it is essentially the default and therefore a no-op. IM_STATIC_ASSERT(ImGuiSortDirection_None == 0 && ImGuiSortDirection_Ascending == 1 && ImGuiSortDirection_Descending == 2); ImGuiSortDirection ImGui::TableGetColumnNextSortDirection(ImGuiTableColumn* column) { IM_ASSERT(column->SortDirectionsAvailCount > 0); if (column->SortOrder == -1) return TableGetColumnAvailSortDirection(column, 0); for (int n = 0; n < 3; n++) if (column->SortDirection == TableGetColumnAvailSortDirection(column, n)) return TableGetColumnAvailSortDirection(column, (n + 1) % column->SortDirectionsAvailCount); IM_ASSERT(0); return ImGuiSortDirection_None; } // Note that the NoSortAscending/NoSortDescending flags are processed in TableSortSpecsSanitize(), and they may change/revert // the value of SortDirection. We could technically also do it here but it would be unnecessary and duplicate code. void ImGui::TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_direction, bool append_to_sort_specs) { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; if (!(table->Flags & ImGuiTableFlags_SortMulti)) append_to_sort_specs = false; if (!(table->Flags & ImGuiTableFlags_SortTristate)) IM_ASSERT(sort_direction != ImGuiSortDirection_None); ImGuiTableColumnIdx sort_order_max = 0; if (append_to_sort_specs) for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++) sort_order_max = ImMax(sort_order_max, table->Columns[other_column_n].SortOrder); ImGuiTableColumn* column = &table->Columns[column_n]; column->SortDirection = (ImU8)sort_direction; if (column->SortDirection == ImGuiSortDirection_None) column->SortOrder = -1; else if (column->SortOrder == -1 || !append_to_sort_specs) column->SortOrder = append_to_sort_specs ? sort_order_max + 1 : 0; for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++) { ImGuiTableColumn* other_column = &table->Columns[other_column_n]; if (other_column != column && !append_to_sort_specs) other_column->SortOrder = -1; TableFixColumnSortDirection(table, other_column); } table->IsSettingsDirty = true; table->IsSortSpecsDirty = true; } void ImGui::TableSortSpecsSanitize(ImGuiTable* table) { IM_ASSERT(table->Flags & ImGuiTableFlags_Sortable); // Clear SortOrder from hidden column and verify that there's no gap or duplicate. int sort_order_count = 0; ImU64 sort_order_mask = 0x00; for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { ImGuiTableColumn* column = &table->Columns[column_n]; if (column->SortOrder != -1 && !column->IsEnabled) column->SortOrder = -1; if (column->SortOrder == -1) continue; sort_order_count++; sort_order_mask |= ((ImU64)1 << column->SortOrder); IM_ASSERT(sort_order_count < (int)sizeof(sort_order_mask) * 8); } const bool need_fix_linearize = ((ImU64)1 << sort_order_count) != (sort_order_mask + 1); const bool need_fix_single_sort_order = (sort_order_count > 1) && !(table->Flags & ImGuiTableFlags_SortMulti); if (need_fix_linearize || need_fix_single_sort_order) { ImU64 fixed_mask = 0x00; for (int sort_n = 0; sort_n < sort_order_count; sort_n++) { // Fix: Rewrite sort order fields if needed so they have no gap or duplicate. // (e.g. SortOrder 0 disappeared, SortOrder 1..2 exists --> rewrite then as SortOrder 0..1) int column_with_smallest_sort_order = -1; for (int column_n = 0; column_n < table->ColumnsCount; column_n++) if ((fixed_mask & ((ImU64)1 << (ImU64)column_n)) == 0 && table->Columns[column_n].SortOrder != -1) if (column_with_smallest_sort_order == -1 || table->Columns[column_n].SortOrder < table->Columns[column_with_smallest_sort_order].SortOrder) column_with_smallest_sort_order = column_n; IM_ASSERT(column_with_smallest_sort_order != -1); fixed_mask |= ((ImU64)1 << column_with_smallest_sort_order); table->Columns[column_with_smallest_sort_order].SortOrder = (ImGuiTableColumnIdx)sort_n; // Fix: Make sure only one column has a SortOrder if ImGuiTableFlags_MultiSortable is not set. if (need_fix_single_sort_order) { sort_order_count = 1; for (int column_n = 0; column_n < table->ColumnsCount; column_n++) if (column_n != column_with_smallest_sort_order) table->Columns[column_n].SortOrder = -1; break; } } } // Fallback default sort order (if no column with the ImGuiTableColumnFlags_DefaultSort flag) if (sort_order_count == 0 && !(table->Flags & ImGuiTableFlags_SortTristate)) for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { ImGuiTableColumn* column = &table->Columns[column_n]; if (column->IsEnabled && !(column->Flags & ImGuiTableColumnFlags_NoSort)) { sort_order_count = 1; column->SortOrder = 0; column->SortDirection = (ImU8)TableGetColumnAvailSortDirection(column, 0); break; } } table->SortSpecsCount = (ImGuiTableColumnIdx)sort_order_count; } void ImGui::TableSortSpecsBuild(ImGuiTable* table) { bool dirty = table->IsSortSpecsDirty; if (dirty) { TableSortSpecsSanitize(table); table->SortSpecsMulti.resize(table->SortSpecsCount <= 1 ? 0 : table->SortSpecsCount); table->SortSpecs.SpecsDirty = true; // Mark as dirty for user table->IsSortSpecsDirty = false; // Mark as not dirty for us } // Write output ImGuiTableColumnSortSpecs* sort_specs = (table->SortSpecsCount == 0) ? NULL : (table->SortSpecsCount == 1) ? &table->SortSpecsSingle : table->SortSpecsMulti.Data; if (dirty && sort_specs != NULL) for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { ImGuiTableColumn* column = &table->Columns[column_n]; if (column->SortOrder == -1) continue; IM_ASSERT(column->SortOrder < table->SortSpecsCount); ImGuiTableColumnSortSpecs* sort_spec = &sort_specs[column->SortOrder]; sort_spec->ColumnUserID = column->UserID; sort_spec->ColumnIndex = (ImGuiTableColumnIdx)column_n; sort_spec->SortOrder = (ImGuiTableColumnIdx)column->SortOrder; sort_spec->SortDirection = column->SortDirection; } table->SortSpecs.Specs = sort_specs; table->SortSpecs.SpecsCount = table->SortSpecsCount; } //------------------------------------------------------------------------- // [SECTION] Tables: Headers //------------------------------------------------------------------------- // - TableGetHeaderRowHeight() [Internal] // - TableHeadersRow() // - TableHeader() // - TableAngledHeadersRow() // - TableAngledHeadersRowEx() [Internal] //------------------------------------------------------------------------- float ImGui::TableGetHeaderRowHeight() { // Caring for a minor edge case: // Calculate row height, for the unlikely case that some labels may be taller than others. // If we didn't do that, uneven header height would highlight but smaller one before the tallest wouldn't catch input for all height. // In your custom header row you may omit this all together and just call TableNextRow() without a height... ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; float row_height = g.FontSize; for (int column_n = 0; column_n < table->ColumnsCount; column_n++) if (IM_BITARRAY_TESTBIT(table->EnabledMaskByIndex, column_n)) if ((table->Columns[column_n].Flags & ImGuiTableColumnFlags_NoHeaderLabel) == 0) row_height = ImMax(row_height, CalcTextSize(TableGetColumnName(table, column_n)).y); return row_height + g.Style.CellPadding.y * 2.0f; } float ImGui::TableGetHeaderAngledMaxLabelWidth() { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; float width = 0.0f; for (int column_n = 0; column_n < table->ColumnsCount; column_n++) if (IM_BITARRAY_TESTBIT(table->EnabledMaskByIndex, column_n)) if (table->Columns[column_n].Flags & ImGuiTableColumnFlags_AngledHeader) width = ImMax(width, CalcTextSize(TableGetColumnName(table, column_n), NULL, true).x); return width + g.Style.CellPadding.x * 2.0f; } // [Public] This is a helper to output TableHeader() calls based on the column names declared in TableSetupColumn(). // The intent is that advanced users willing to create customized headers would not need to use this helper // and can create their own! For example: TableHeader() may be preceeded by Checkbox() or other custom widgets. // See 'Demo->Tables->Custom headers' for a demonstration of implementing a custom version of this. // This code is constructed to not make much use of internal functions, as it is intended to be a template to copy. // FIXME-TABLE: TableOpenContextMenu() and TableGetHeaderRowHeight() are not public. void ImGui::TableHeadersRow() { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; IM_ASSERT(table != NULL && "Need to call TableHeadersRow() after BeginTable()!"); // Layout if not already done (this is automatically done by TableNextRow, we do it here solely to facilitate stepping in debugger as it is frequent to step in TableUpdateLayout) if (!table->IsLayoutLocked) TableUpdateLayout(table); // Open row const float row_height = TableGetHeaderRowHeight(); TableNextRow(ImGuiTableRowFlags_Headers, row_height); const float row_y1 = GetCursorScreenPos().y; if (table->HostSkipItems) // Merely an optimization, you may skip in your own code. return; const int columns_count = TableGetColumnCount(); for (int column_n = 0; column_n < columns_count; column_n++) { if (!TableSetColumnIndex(column_n)) continue; // Push an id to allow unnamed labels (generally accidental, but let's behave nicely with them) // In your own code you may omit the PushID/PopID all-together, provided you know they won't collide. const char* name = (TableGetColumnFlags(column_n) & ImGuiTableColumnFlags_NoHeaderLabel) ? "" : TableGetColumnName(column_n); PushID(column_n); TableHeader(name); PopID(); } // Allow opening popup from the right-most section after the last column. ImVec2 mouse_pos = ImGui::GetMousePos(); if (IsMouseReleased(1) && TableGetHoveredColumn() == columns_count) if (mouse_pos.y >= row_y1 && mouse_pos.y < row_y1 + row_height) TableOpenContextMenu(columns_count); // Will open a non-column-specific popup. } // Emit a column header (text + optional sort order) // We cpu-clip text here so that all columns headers can be merged into a same draw call. // Note that because of how we cpu-clip and display sorting indicators, you _cannot_ use SameLine() after a TableHeader() void ImGui::TableHeader(const char* label) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (window->SkipItems) return; ImGuiTable* table = g.CurrentTable; IM_ASSERT(table != NULL && "Need to call TableHeader() after BeginTable()!"); IM_ASSERT(table->CurrentColumn != -1); const int column_n = table->CurrentColumn; ImGuiTableColumn* column = &table->Columns[column_n]; // Label if (label == NULL) label = ""; const char* label_end = FindRenderedTextEnd(label); ImVec2 label_size = CalcTextSize(label, label_end, true); ImVec2 label_pos = window->DC.CursorPos; // If we already got a row height, there's use that. // FIXME-TABLE: Padding problem if the correct outer-padding CellBgRect strays off our ClipRect? ImRect cell_r = TableGetCellBgRect(table, column_n); float label_height = ImMax(label_size.y, table->RowMinHeight - table->RowCellPaddingY * 2.0f); // Calculate ideal size for sort order arrow float w_arrow = 0.0f; float w_sort_text = 0.0f; bool sort_arrow = false; char sort_order_suf[4] = ""; const float ARROW_SCALE = 0.65f; if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort)) { w_arrow = ImTrunc(g.FontSize * ARROW_SCALE + g.Style.FramePadding.x); if (column->SortOrder != -1) sort_arrow = true; if (column->SortOrder > 0) { ImFormatString(sort_order_suf, IM_ARRAYSIZE(sort_order_suf), "%d", column->SortOrder + 1); w_sort_text = g.Style.ItemInnerSpacing.x + CalcTextSize(sort_order_suf).x; } } // We feed our unclipped width to the column without writing on CursorMaxPos, so that column is still considered for merging. float max_pos_x = label_pos.x + label_size.x + w_sort_text + w_arrow; column->ContentMaxXHeadersUsed = ImMax(column->ContentMaxXHeadersUsed, sort_arrow ? cell_r.Max.x : ImMin(max_pos_x, cell_r.Max.x)); column->ContentMaxXHeadersIdeal = ImMax(column->ContentMaxXHeadersIdeal, max_pos_x); // Keep header highlighted when context menu is open. ImGuiID id = window->GetID(label); ImRect bb(cell_r.Min.x, cell_r.Min.y, cell_r.Max.x, ImMax(cell_r.Max.y, cell_r.Min.y + label_height + g.Style.CellPadding.y * 2.0f)); ItemSize(ImVec2(0.0f, label_height)); // Don't declare unclipped width, it'll be fed ContentMaxPosHeadersIdeal if (!ItemAdd(bb, id)) return; //GetForegroundDrawList()->AddRect(cell_r.Min, cell_r.Max, IM_COL32(255, 0, 0, 255)); // [DEBUG] //GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 0, 0, 255)); // [DEBUG] // Using AllowOverlap mode because we cover the whole cell, and we want user to be able to submit subsequent items. const bool highlight = (table->HighlightColumnHeader == column_n); bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_AllowOverlap); if (held || hovered || highlight) { const ImU32 col = GetColorU32(held ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); //RenderFrame(bb.Min, bb.Max, col, false, 0.0f); TableSetBgColor(ImGuiTableBgTarget_CellBg, col, table->CurrentColumn); } else { // Submit single cell bg color in the case we didn't submit a full header row if ((table->RowFlags & ImGuiTableRowFlags_Headers) == 0) TableSetBgColor(ImGuiTableBgTarget_CellBg, GetColorU32(ImGuiCol_TableHeaderBg), table->CurrentColumn); } RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_Compact | ImGuiNavHighlightFlags_NoRounding); if (held) table->HeldHeaderColumn = (ImGuiTableColumnIdx)column_n; window->DC.CursorPos.y -= g.Style.ItemSpacing.y * 0.5f; // Drag and drop to re-order columns. // FIXME-TABLE: Scroll request while reordering a column and it lands out of the scrolling zone. if (held && (table->Flags & ImGuiTableFlags_Reorderable) && IsMouseDragging(0) && !g.DragDropActive) { // While moving a column it will jump on the other side of the mouse, so we also test for MouseDelta.x table->ReorderColumn = (ImGuiTableColumnIdx)column_n; table->InstanceInteracted = table->InstanceCurrent; // We don't reorder: through the frozen<>unfrozen line, or through a column that is marked with ImGuiTableColumnFlags_NoReorder. if (g.IO.MouseDelta.x < 0.0f && g.IO.MousePos.x < cell_r.Min.x) if (ImGuiTableColumn* prev_column = (column->PrevEnabledColumn != -1) ? &table->Columns[column->PrevEnabledColumn] : NULL) if (!((column->Flags | prev_column->Flags) & ImGuiTableColumnFlags_NoReorder)) if ((column->IndexWithinEnabledSet < table->FreezeColumnsRequest) == (prev_column->IndexWithinEnabledSet < table->FreezeColumnsRequest)) table->ReorderColumnDir = -1; if (g.IO.MouseDelta.x > 0.0f && g.IO.MousePos.x > cell_r.Max.x) if (ImGuiTableColumn* next_column = (column->NextEnabledColumn != -1) ? &table->Columns[column->NextEnabledColumn] : NULL) if (!((column->Flags | next_column->Flags) & ImGuiTableColumnFlags_NoReorder)) if ((column->IndexWithinEnabledSet < table->FreezeColumnsRequest) == (next_column->IndexWithinEnabledSet < table->FreezeColumnsRequest)) table->ReorderColumnDir = +1; } // Sort order arrow const float ellipsis_max = ImMax(cell_r.Max.x - w_arrow - w_sort_text, label_pos.x); if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort)) { if (column->SortOrder != -1) { float x = ImMax(cell_r.Min.x, cell_r.Max.x - w_arrow - w_sort_text); float y = label_pos.y; if (column->SortOrder > 0) { PushStyleColor(ImGuiCol_Text, GetColorU32(ImGuiCol_Text, 0.70f)); RenderText(ImVec2(x + g.Style.ItemInnerSpacing.x, y), sort_order_suf); PopStyleColor(); x += w_sort_text; } RenderArrow(window->DrawList, ImVec2(x, y), GetColorU32(ImGuiCol_Text), column->SortDirection == ImGuiSortDirection_Ascending ? ImGuiDir_Up : ImGuiDir_Down, ARROW_SCALE); } // Handle clicking on column header to adjust Sort Order if (pressed && table->ReorderColumn != column_n) { ImGuiSortDirection sort_direction = TableGetColumnNextSortDirection(column); TableSetColumnSortDirection(column_n, sort_direction, g.IO.KeyShift); } } // Render clipped label. Clipping here ensure that in the majority of situations, all our header cells will // be merged into a single draw call. //window->DrawList->AddCircleFilled(ImVec2(ellipsis_max, label_pos.y), 40, IM_COL32_WHITE); RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, label_pos.y + label_height + g.Style.FramePadding.y), ellipsis_max, ellipsis_max, label, label_end, &label_size); const bool text_clipped = label_size.x > (ellipsis_max - label_pos.x); if (text_clipped && hovered && g.ActiveId == 0) SetItemTooltip("%.*s", (int)(label_end - label), label); // We don't use BeginPopupContextItem() because we want the popup to stay up even after the column is hidden if (IsMouseReleased(1) && IsItemHovered()) TableOpenContextMenu(column_n); } // Unlike TableHeadersRow() it is not expected that you can reimplement or customize this with custom widgets. // FIXME: highlight without ImGuiTableFlags_HighlightHoveredColumn // FIXME: No hit-testing/button on the angled header. void ImGui::TableAngledHeadersRow() { ImGuiContext& g = *GImGui; TableAngledHeadersRowEx(g.Style.TableAngledHeadersAngle, 0.0f); } void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width) { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; ImGuiWindow* window = g.CurrentWindow; ImDrawList* draw_list = window->DrawList; IM_ASSERT(table != NULL && "Need to call TableHeadersRow() after BeginTable()!"); IM_ASSERT(table->CurrentRow == -1 && "Must be first row"); if (max_label_width == 0.0f) max_label_width = TableGetHeaderAngledMaxLabelWidth(); // Angle argument expressed in (-IM_PI/2 .. +IM_PI/2) as it is easier to think about for user. const bool flip_label = (angle < 0.0f); angle -= IM_PI * 0.5f; const float cos_a = ImCos(angle); const float sin_a = ImSin(angle); const float label_cos_a = flip_label ? ImCos(angle + IM_PI) : cos_a; const float label_sin_a = flip_label ? ImSin(angle + IM_PI) : sin_a; const ImVec2 unit_right = ImVec2(cos_a, sin_a); // Calculate our base metrics and set angled headers data _before_ the first call to TableNextRow() // FIXME-STYLE: Would it be better for user to submit 'max_label_width' or 'row_height' ? One can be derived from the other. const float header_height = table->RowCellPaddingY * 2.0f + g.FontSize; const float row_height = ImFabs(ImRotate(ImVec2(max_label_width, flip_label ? +header_height : -header_height), cos_a, sin_a).y); const ImVec2 header_angled_vector = unit_right * (row_height / -sin_a); table->AngledHeadersHeight = row_height; table->AngledHeadersSlope = (sin_a != 0.0f) ? (cos_a / sin_a) : 0.0f; // Declare row, override and draw our own background TableNextRow(ImGuiTableRowFlags_Headers, row_height); TableNextColumn(); table->DrawSplitter->SetCurrentChannel(draw_list, TABLE_DRAW_CHANNEL_BG0); float clip_rect_min_x = table->BgClipRect.Min.x; if (table->FreezeColumnsCount > 0) clip_rect_min_x = ImMax(clip_rect_min_x, table->Columns[table->FreezeColumnsCount - 1].MaxX); TableSetBgColor(ImGuiTableBgTarget_RowBg0, 0); // Cancel PushClipRect(table->BgClipRect.Min, table->BgClipRect.Max, false); // Span all columns draw_list->AddRectFilled(table->BgClipRect.Min, table->BgClipRect.Max, GetColorU32(ImGuiCol_TableHeaderBg, 0.25f)); // FIXME-STYLE: Change row background with an arbitrary color. PushClipRect(ImVec2(clip_rect_min_x, table->BgClipRect.Min.y), table->BgClipRect.Max, true); // Span all columns const ImRect row_r(table->WorkRect.Min.x, table->BgClipRect.Min.y, table->WorkRect.Max.x, window->DC.CursorPos.y + row_height); const ImGuiID row_id = GetID("##AngledHeaders"); ButtonBehavior(row_r, row_id, NULL, NULL); KeepAliveID(row_id); ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); int highlight_column_n = table->HighlightColumnHeader; if (highlight_column_n == -1 && table->HoveredColumnBody != -1) if (table_instance->HoveredRowLast == 0 && table->HoveredColumnBorder == -1 && (g.ActiveId == 0 || g.ActiveId == row_id || (table->IsActiveIdInTable || g.DragDropActive))) highlight_column_n = table->HoveredColumnBody; float max_x = 0.0f; for (int pass = 0; pass < 2; pass++) for (int order_n = 0; order_n < table->ColumnsCount; order_n++) { if (!IM_BITARRAY_TESTBIT(table->EnabledMaskByDisplayOrder, order_n)) continue; const int column_n = table->DisplayOrderToIndex[order_n]; ImGuiTableColumn* column = &table->Columns[column_n]; if ((column->Flags & ImGuiTableColumnFlags_AngledHeader) == 0) // Note: can't rely on ImGuiTableColumnFlags_IsVisible test here. continue; ImVec2 bg_shape[4]; bg_shape[0] = ImVec2(column->MaxX, row_r.Max.y); bg_shape[1] = ImVec2(column->MinX, row_r.Max.y); bg_shape[2] = bg_shape[1] + header_angled_vector; bg_shape[3] = bg_shape[0] + header_angled_vector; if (pass == 0) { // Draw shape draw_list->AddQuadFilled(bg_shape[0], bg_shape[1], bg_shape[2], bg_shape[3], GetColorU32(ImGuiCol_TableHeaderBg)); if (column_n == highlight_column_n) draw_list->AddQuadFilled(bg_shape[0], bg_shape[1], bg_shape[2], bg_shape[3], GetColorU32(ImGuiCol_Header)); // Highlight on hover //draw_list->AddQuad(bg_shape[0], bg_shape[1], bg_shape[2], bg_shape[3], GetColorU32(ImGuiCol_TableBorderLight), 1.0f); max_x = ImMax(max_x, bg_shape[3].x); // Draw label (first draw at an offset where RenderTextXXX() function won't meddle with applying current ClipRect, then transform to final offset) // FIXME: May be worth tidying up all those operations to make them easier to understand. const char* label_name = TableGetColumnName(table, column_n); const float clip_width = max_label_width - (sin_a * table->RowCellPaddingY); ImRect label_r(window->ClipRect.Min, window->ClipRect.Min + ImVec2(clip_width + (flip_label ? 0.0f : table->CellPaddingX), header_height + table->RowCellPaddingY)); ImVec2 label_size = CalcTextSize(label_name, NULL, true); ImVec2 label_off = ImVec2(flip_label ? ImMax(0.0f, max_label_width - label_size.x - table->CellPaddingX) : table->CellPaddingX, table->RowCellPaddingY); int vtx_idx_begin = draw_list->_VtxCurrentIdx; RenderTextEllipsis(draw_list, label_r.Min + label_off, label_r.Max, label_r.Max.x, label_r.Max.x, label_name, NULL, &label_size); //if (g.IO.KeyShift) { draw_list->AddRect(label_r.Min, label_r.Max, IM_COL32(0, 255, 0, 255), 0.0f, 0, 2.0f); } int vtx_idx_end = draw_list->_VtxCurrentIdx; // Rotate and offset label ImVec2 pivot_in = label_r.GetBL(); ImVec2 pivot_out = ImVec2(column->WorkMinX, row_r.Max.y) + (flip_label ? (unit_right * clip_width) : ImVec2(header_height, 0.0f)); ShadeVertsTransformPos(draw_list, vtx_idx_begin, vtx_idx_end, pivot_in, label_cos_a, label_sin_a, pivot_out); // Rotate and offset } if (pass == 1) { // Draw border draw_list->AddLine(bg_shape[0], bg_shape[3], TableGetColumnBorderCol(table, order_n, column_n)); } } PopClipRect(); PopClipRect(); table->TempData->AngledheadersExtraWidth = ImMax(0.0f, max_x - table->Columns[table->RightMostEnabledColumn].MaxX); } //------------------------------------------------------------------------- // [SECTION] Tables: Context Menu //------------------------------------------------------------------------- // - TableOpenContextMenu() [Internal] // - TableBeginContextMenuPopup() [Internal] // - TableDrawDefaultContextMenu() [Internal] //------------------------------------------------------------------------- // Use -1 to open menu not specific to a given column. void ImGui::TableOpenContextMenu(int column_n) { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; if (column_n == -1 && table->CurrentColumn != -1) // When called within a column automatically use this one (for consistency) column_n = table->CurrentColumn; if (column_n == table->ColumnsCount) // To facilitate using with TableGetHoveredColumn() column_n = -1; IM_ASSERT(column_n >= -1 && column_n < table->ColumnsCount); if (table->Flags & (ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable)) { table->IsContextPopupOpen = true; table->ContextPopupColumn = (ImGuiTableColumnIdx)column_n; table->InstanceInteracted = table->InstanceCurrent; const ImGuiID context_menu_id = ImHashStr("##ContextMenu", 0, table->ID); OpenPopupEx(context_menu_id, ImGuiPopupFlags_None); } } bool ImGui::TableBeginContextMenuPopup(ImGuiTable* table) { if (!table->IsContextPopupOpen || table->InstanceCurrent != table->InstanceInteracted) return false; const ImGuiID context_menu_id = ImHashStr("##ContextMenu", 0, table->ID); if (BeginPopupEx(context_menu_id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings)) return true; table->IsContextPopupOpen = false; return false; } // Output context menu into current window (generally a popup) // FIXME-TABLE: Ideally this should be writable by the user. Full programmatic access to that data? // Sections to display are pulled from 'flags_for_section_to_display', which is typically == table->Flags. // - ImGuiTableFlags_Resizable -> display Sizing menu items // - ImGuiTableFlags_Reorderable -> display "Reset Order" ////- ImGuiTableFlags_Sortable -> display sorting options (disabled) // - ImGuiTableFlags_Hideable -> display columns visibility menu items // It means if you have a custom context menus you can call this section and omit some sections, and add your own. void ImGui::TableDrawDefaultContextMenu(ImGuiTable* table, ImGuiTableFlags flags_for_section_to_display) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (window->SkipItems) return; bool want_separator = false; const int column_n = (table->ContextPopupColumn >= 0 && table->ContextPopupColumn < table->ColumnsCount) ? table->ContextPopupColumn : -1; ImGuiTableColumn* column = (column_n != -1) ? &table->Columns[column_n] : NULL; // Sizing if (flags_for_section_to_display & ImGuiTableFlags_Resizable) { if (column != NULL) { const bool can_resize = !(column->Flags & ImGuiTableColumnFlags_NoResize) && column->IsEnabled; if (MenuItem(LocalizeGetMsg(ImGuiLocKey_TableSizeOne), NULL, false, can_resize)) // "###SizeOne" TableSetColumnWidthAutoSingle(table, column_n); } const char* size_all_desc; if (table->ColumnsEnabledFixedCount == table->ColumnsEnabledCount && (table->Flags & ImGuiTableFlags_SizingMask_) != ImGuiTableFlags_SizingFixedSame) size_all_desc = LocalizeGetMsg(ImGuiLocKey_TableSizeAllFit); // "###SizeAll" All fixed else size_all_desc = LocalizeGetMsg(ImGuiLocKey_TableSizeAllDefault); // "###SizeAll" All stretch or mixed if (MenuItem(size_all_desc, NULL)) TableSetColumnWidthAutoAll(table); want_separator = true; } // Ordering if (flags_for_section_to_display & ImGuiTableFlags_Reorderable) { if (MenuItem(LocalizeGetMsg(ImGuiLocKey_TableResetOrder), NULL, false, !table->IsDefaultDisplayOrder)) table->IsResetDisplayOrderRequest = true; want_separator = true; } // Reset all (should work but seems unnecessary/noisy to expose?) //if (MenuItem("Reset all")) // table->IsResetAllRequest = true; // Sorting // (modify TableOpenContextMenu() to add _Sortable flag if enabling this) #if 0 if ((flags_for_section_to_display & ImGuiTableFlags_Sortable) && column != NULL && (column->Flags & ImGuiTableColumnFlags_NoSort) == 0) { if (want_separator) Separator(); want_separator = true; bool append_to_sort_specs = g.IO.KeyShift; if (MenuItem("Sort in Ascending Order", NULL, column->SortOrder != -1 && column->SortDirection == ImGuiSortDirection_Ascending, (column->Flags & ImGuiTableColumnFlags_NoSortAscending) == 0)) TableSetColumnSortDirection(table, column_n, ImGuiSortDirection_Ascending, append_to_sort_specs); if (MenuItem("Sort in Descending Order", NULL, column->SortOrder != -1 && column->SortDirection == ImGuiSortDirection_Descending, (column->Flags & ImGuiTableColumnFlags_NoSortDescending) == 0)) TableSetColumnSortDirection(table, column_n, ImGuiSortDirection_Descending, append_to_sort_specs); } #endif // Hiding / Visibility if (flags_for_section_to_display & ImGuiTableFlags_Hideable) { if (want_separator) Separator(); want_separator = true; PushItemFlag(ImGuiItemFlags_SelectableDontClosePopup, true); for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++) { ImGuiTableColumn* other_column = &table->Columns[other_column_n]; if (other_column->Flags & ImGuiTableColumnFlags_Disabled) continue; const char* name = TableGetColumnName(table, other_column_n); if (name == NULL || name[0] == 0) name = ""; // Make sure we can't hide the last active column bool menu_item_active = (other_column->Flags & ImGuiTableColumnFlags_NoHide) ? false : true; if (other_column->IsUserEnabled && table->ColumnsEnabledCount <= 1) menu_item_active = false; if (MenuItem(name, NULL, other_column->IsUserEnabled, menu_item_active)) other_column->IsUserEnabledNextFrame = !other_column->IsUserEnabled; } PopItemFlag(); } } //------------------------------------------------------------------------- // [SECTION] Tables: Settings (.ini data) //------------------------------------------------------------------------- // FIXME: The binding/finding/creating flow are too confusing. //------------------------------------------------------------------------- // - TableSettingsInit() [Internal] // - TableSettingsCalcChunkSize() [Internal] // - TableSettingsCreate() [Internal] // - TableSettingsFindByID() [Internal] // - TableGetBoundSettings() [Internal] // - TableResetSettings() // - TableSaveSettings() [Internal] // - TableLoadSettings() [Internal] // - TableSettingsHandler_ClearAll() [Internal] // - TableSettingsHandler_ApplyAll() [Internal] // - TableSettingsHandler_ReadOpen() [Internal] // - TableSettingsHandler_ReadLine() [Internal] // - TableSettingsHandler_WriteAll() [Internal] // - TableSettingsInstallHandler() [Internal] //------------------------------------------------------------------------- // [Init] 1: TableSettingsHandler_ReadXXXX() Load and parse .ini file into TableSettings. // [Main] 2: TableLoadSettings() When table is created, bind Table to TableSettings, serialize TableSettings data into Table. // [Main] 3: TableSaveSettings() When table properties are modified, serialize Table data into bound or new TableSettings, mark .ini as dirty. // [Main] 4: TableSettingsHandler_WriteAll() When .ini file is dirty (which can come from other source), save TableSettings into .ini file. //------------------------------------------------------------------------- // Clear and initialize empty settings instance static void TableSettingsInit(ImGuiTableSettings* settings, ImGuiID id, int columns_count, int columns_count_max) { IM_PLACEMENT_NEW(settings) ImGuiTableSettings(); ImGuiTableColumnSettings* settings_column = settings->GetColumnSettings(); for (int n = 0; n < columns_count_max; n++, settings_column++) IM_PLACEMENT_NEW(settings_column) ImGuiTableColumnSettings(); settings->ID = id; settings->ColumnsCount = (ImGuiTableColumnIdx)columns_count; settings->ColumnsCountMax = (ImGuiTableColumnIdx)columns_count_max; settings->WantApply = true; } static size_t TableSettingsCalcChunkSize(int columns_count) { return sizeof(ImGuiTableSettings) + (size_t)columns_count * sizeof(ImGuiTableColumnSettings); } ImGuiTableSettings* ImGui::TableSettingsCreate(ImGuiID id, int columns_count) { ImGuiContext& g = *GImGui; ImGuiTableSettings* settings = g.SettingsTables.alloc_chunk(TableSettingsCalcChunkSize(columns_count)); TableSettingsInit(settings, id, columns_count, columns_count); return settings; } // Find existing settings ImGuiTableSettings* ImGui::TableSettingsFindByID(ImGuiID id) { // FIXME-OPT: Might want to store a lookup map for this? ImGuiContext& g = *GImGui; for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings)) if (settings->ID == id) return settings; return NULL; } // Get settings for a given table, NULL if none ImGuiTableSettings* ImGui::TableGetBoundSettings(ImGuiTable* table) { if (table->SettingsOffset != -1) { ImGuiContext& g = *GImGui; ImGuiTableSettings* settings = g.SettingsTables.ptr_from_offset(table->SettingsOffset); IM_ASSERT(settings->ID == table->ID); if (settings->ColumnsCountMax >= table->ColumnsCount) return settings; // OK settings->ID = 0; // Invalidate storage, we won't fit because of a count change } return NULL; } // Restore initial state of table (with or without saved settings) void ImGui::TableResetSettings(ImGuiTable* table) { table->IsInitializing = table->IsSettingsDirty = true; table->IsResetAllRequest = false; table->IsSettingsRequestLoad = false; // Don't reload from ini table->SettingsLoadedFlags = ImGuiTableFlags_None; // Mark as nothing loaded so our initialized data becomes authoritative } void ImGui::TableSaveSettings(ImGuiTable* table) { table->IsSettingsDirty = false; if (table->Flags & ImGuiTableFlags_NoSavedSettings) return; // Bind or create settings data ImGuiContext& g = *GImGui; ImGuiTableSettings* settings = TableGetBoundSettings(table); if (settings == NULL) { settings = TableSettingsCreate(table->ID, table->ColumnsCount); table->SettingsOffset = g.SettingsTables.offset_from_ptr(settings); } settings->ColumnsCount = (ImGuiTableColumnIdx)table->ColumnsCount; // Serialize ImGuiTable/ImGuiTableColumn into ImGuiTableSettings/ImGuiTableColumnSettings IM_ASSERT(settings->ID == table->ID); IM_ASSERT(settings->ColumnsCount == table->ColumnsCount && settings->ColumnsCountMax >= settings->ColumnsCount); ImGuiTableColumn* column = table->Columns.Data; ImGuiTableColumnSettings* column_settings = settings->GetColumnSettings(); bool save_ref_scale = false; settings->SaveFlags = ImGuiTableFlags_None; for (int n = 0; n < table->ColumnsCount; n++, column++, column_settings++) { const float width_or_weight = (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? column->StretchWeight : column->WidthRequest; column_settings->WidthOrWeight = width_or_weight; column_settings->Index = (ImGuiTableColumnIdx)n; column_settings->DisplayOrder = column->DisplayOrder; column_settings->SortOrder = column->SortOrder; column_settings->SortDirection = column->SortDirection; column_settings->IsEnabled = column->IsUserEnabled; column_settings->IsStretch = (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? 1 : 0; if ((column->Flags & ImGuiTableColumnFlags_WidthStretch) == 0) save_ref_scale = true; // We skip saving some data in the .ini file when they are unnecessary to restore our state. // Note that fixed width where initial width was derived from auto-fit will always be saved as InitStretchWeightOrWidth will be 0.0f. // FIXME-TABLE: We don't have logic to easily compare SortOrder to DefaultSortOrder yet so it's always saved when present. if (width_or_weight != column->InitStretchWeightOrWidth) settings->SaveFlags |= ImGuiTableFlags_Resizable; if (column->DisplayOrder != n) settings->SaveFlags |= ImGuiTableFlags_Reorderable; if (column->SortOrder != -1) settings->SaveFlags |= ImGuiTableFlags_Sortable; if (column->IsUserEnabled != ((column->Flags & ImGuiTableColumnFlags_DefaultHide) == 0)) settings->SaveFlags |= ImGuiTableFlags_Hideable; } settings->SaveFlags &= table->Flags; settings->RefScale = save_ref_scale ? table->RefScale : 0.0f; MarkIniSettingsDirty(); } void ImGui::TableLoadSettings(ImGuiTable* table) { ImGuiContext& g = *GImGui; table->IsSettingsRequestLoad = false; if (table->Flags & ImGuiTableFlags_NoSavedSettings) return; // Bind settings ImGuiTableSettings* settings; if (table->SettingsOffset == -1) { settings = TableSettingsFindByID(table->ID); if (settings == NULL) return; if (settings->ColumnsCount != table->ColumnsCount) // Allow settings if columns count changed. We could otherwise decide to return... table->IsSettingsDirty = true; table->SettingsOffset = g.SettingsTables.offset_from_ptr(settings); } else { settings = TableGetBoundSettings(table); } table->SettingsLoadedFlags = settings->SaveFlags; table->RefScale = settings->RefScale; // Serialize ImGuiTableSettings/ImGuiTableColumnSettings into ImGuiTable/ImGuiTableColumn ImGuiTableColumnSettings* column_settings = settings->GetColumnSettings(); ImU64 display_order_mask = 0; for (int data_n = 0; data_n < settings->ColumnsCount; data_n++, column_settings++) { int column_n = column_settings->Index; if (column_n < 0 || column_n >= table->ColumnsCount) continue; ImGuiTableColumn* column = &table->Columns[column_n]; if (settings->SaveFlags & ImGuiTableFlags_Resizable) { if (column_settings->IsStretch) column->StretchWeight = column_settings->WidthOrWeight; else column->WidthRequest = column_settings->WidthOrWeight; column->AutoFitQueue = 0x00; } if (settings->SaveFlags & ImGuiTableFlags_Reorderable) column->DisplayOrder = column_settings->DisplayOrder; else column->DisplayOrder = (ImGuiTableColumnIdx)column_n; display_order_mask |= (ImU64)1 << column->DisplayOrder; column->IsUserEnabled = column->IsUserEnabledNextFrame = column_settings->IsEnabled; column->SortOrder = column_settings->SortOrder; column->SortDirection = column_settings->SortDirection; } // Validate and fix invalid display order data const ImU64 expected_display_order_mask = (settings->ColumnsCount == 64) ? ~0 : ((ImU64)1 << settings->ColumnsCount) - 1; if (display_order_mask != expected_display_order_mask) for (int column_n = 0; column_n < table->ColumnsCount; column_n++) table->Columns[column_n].DisplayOrder = (ImGuiTableColumnIdx)column_n; // Rebuild index for (int column_n = 0; column_n < table->ColumnsCount; column_n++) table->DisplayOrderToIndex[table->Columns[column_n].DisplayOrder] = (ImGuiTableColumnIdx)column_n; } static void TableSettingsHandler_ClearAll(ImGuiContext* ctx, ImGuiSettingsHandler*) { ImGuiContext& g = *ctx; for (int i = 0; i != g.Tables.GetMapSize(); i++) if (ImGuiTable* table = g.Tables.TryGetMapData(i)) table->SettingsOffset = -1; g.SettingsTables.clear(); } // Apply to existing windows (if any) static void TableSettingsHandler_ApplyAll(ImGuiContext* ctx, ImGuiSettingsHandler*) { ImGuiContext& g = *ctx; for (int i = 0; i != g.Tables.GetMapSize(); i++) if (ImGuiTable* table = g.Tables.TryGetMapData(i)) { table->IsSettingsRequestLoad = true; table->SettingsOffset = -1; } } static void* TableSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name) { ImGuiID id = 0; int columns_count = 0; if (sscanf(name, "0x%08X,%d", &id, &columns_count) < 2) return NULL; if (ImGuiTableSettings* settings = ImGui::TableSettingsFindByID(id)) { if (settings->ColumnsCountMax >= columns_count) { TableSettingsInit(settings, id, columns_count, settings->ColumnsCountMax); // Recycle return settings; } settings->ID = 0; // Invalidate storage, we won't fit because of a count change } return ImGui::TableSettingsCreate(id, columns_count); } static void TableSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line) { // "Column 0 UserID=0x42AD2D21 Width=100 Visible=1 Order=0 Sort=0v" ImGuiTableSettings* settings = (ImGuiTableSettings*)entry; float f = 0.0f; int column_n = 0, r = 0, n = 0; if (sscanf(line, "RefScale=%f", &f) == 1) { settings->RefScale = f; return; } if (sscanf(line, "Column %d%n", &column_n, &r) == 1) { if (column_n < 0 || column_n >= settings->ColumnsCount) return; line = ImStrSkipBlank(line + r); char c = 0; ImGuiTableColumnSettings* column = settings->GetColumnSettings() + column_n; column->Index = (ImGuiTableColumnIdx)column_n; if (sscanf(line, "UserID=0x%08X%n", (ImU32*)&n, &r)==1) { line = ImStrSkipBlank(line + r); column->UserID = (ImGuiID)n; } if (sscanf(line, "Width=%d%n", &n, &r) == 1) { line = ImStrSkipBlank(line + r); column->WidthOrWeight = (float)n; column->IsStretch = 0; settings->SaveFlags |= ImGuiTableFlags_Resizable; } if (sscanf(line, "Weight=%f%n", &f, &r) == 1) { line = ImStrSkipBlank(line + r); column->WidthOrWeight = f; column->IsStretch = 1; settings->SaveFlags |= ImGuiTableFlags_Resizable; } if (sscanf(line, "Visible=%d%n", &n, &r) == 1) { line = ImStrSkipBlank(line + r); column->IsEnabled = (ImU8)n; settings->SaveFlags |= ImGuiTableFlags_Hideable; } if (sscanf(line, "Order=%d%n", &n, &r) == 1) { line = ImStrSkipBlank(line + r); column->DisplayOrder = (ImGuiTableColumnIdx)n; settings->SaveFlags |= ImGuiTableFlags_Reorderable; } if (sscanf(line, "Sort=%d%c%n", &n, &c, &r) == 2) { line = ImStrSkipBlank(line + r); column->SortOrder = (ImGuiTableColumnIdx)n; column->SortDirection = (c == '^') ? ImGuiSortDirection_Descending : ImGuiSortDirection_Ascending; settings->SaveFlags |= ImGuiTableFlags_Sortable; } } } static void TableSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) { ImGuiContext& g = *ctx; for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings)) { if (settings->ID == 0) // Skip ditched settings continue; // TableSaveSettings() may clear some of those flags when we establish that the data can be stripped // (e.g. Order was unchanged) const bool save_size = (settings->SaveFlags & ImGuiTableFlags_Resizable) != 0; const bool save_visible = (settings->SaveFlags & ImGuiTableFlags_Hideable) != 0; const bool save_order = (settings->SaveFlags & ImGuiTableFlags_Reorderable) != 0; const bool save_sort = (settings->SaveFlags & ImGuiTableFlags_Sortable) != 0; if (!save_size && !save_visible && !save_order && !save_sort) continue; buf->reserve(buf->size() + 30 + settings->ColumnsCount * 50); // ballpark reserve buf->appendf("[%s][0x%08X,%d]\n", handler->TypeName, settings->ID, settings->ColumnsCount); if (settings->RefScale != 0.0f) buf->appendf("RefScale=%g\n", settings->RefScale); ImGuiTableColumnSettings* column = settings->GetColumnSettings(); for (int column_n = 0; column_n < settings->ColumnsCount; column_n++, column++) { // "Column 0 UserID=0x42AD2D21 Width=100 Visible=1 Order=0 Sort=0v" bool save_column = column->UserID != 0 || save_size || save_visible || save_order || (save_sort && column->SortOrder != -1); if (!save_column) continue; buf->appendf("Column %-2d", column_n); if (column->UserID != 0) { buf->appendf(" UserID=%08X", column->UserID); } if (save_size && column->IsStretch) { buf->appendf(" Weight=%.4f", column->WidthOrWeight); } if (save_size && !column->IsStretch) { buf->appendf(" Width=%d", (int)column->WidthOrWeight); } if (save_visible) { buf->appendf(" Visible=%d", column->IsEnabled); } if (save_order) { buf->appendf(" Order=%d", column->DisplayOrder); } if (save_sort && column->SortOrder != -1) { buf->appendf(" Sort=%d%c", column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? 'v' : '^'); } buf->append("\n"); } buf->append("\n"); } } void ImGui::TableSettingsAddSettingsHandler() { ImGuiSettingsHandler ini_handler; ini_handler.TypeName = "Table"; ini_handler.TypeHash = ImHashStr("Table"); ini_handler.ClearAllFn = TableSettingsHandler_ClearAll; ini_handler.ReadOpenFn = TableSettingsHandler_ReadOpen; ini_handler.ReadLineFn = TableSettingsHandler_ReadLine; ini_handler.ApplyAllFn = TableSettingsHandler_ApplyAll; ini_handler.WriteAllFn = TableSettingsHandler_WriteAll; AddSettingsHandler(&ini_handler); } //------------------------------------------------------------------------- // [SECTION] Tables: Garbage Collection //------------------------------------------------------------------------- // - TableRemove() [Internal] // - TableGcCompactTransientBuffers() [Internal] // - TableGcCompactSettings() [Internal] //------------------------------------------------------------------------- // Remove Table (currently only used by TestEngine) void ImGui::TableRemove(ImGuiTable* table) { //IMGUI_DEBUG_PRINT("TableRemove() id=0x%08X\n", table->ID); ImGuiContext& g = *GImGui; int table_idx = g.Tables.GetIndex(table); //memset(table->RawData.Data, 0, table->RawData.size_in_bytes()); //memset(table, 0, sizeof(ImGuiTable)); g.Tables.Remove(table->ID, table); g.TablesLastTimeActive[table_idx] = -1.0f; } // Free up/compact internal Table buffers for when it gets unused void ImGui::TableGcCompactTransientBuffers(ImGuiTable* table) { //IMGUI_DEBUG_PRINT("TableGcCompactTransientBuffers() id=0x%08X\n", table->ID); ImGuiContext& g = *GImGui; IM_ASSERT(table->MemoryCompacted == false); table->SortSpecs.Specs = NULL; table->SortSpecsMulti.clear(); table->IsSortSpecsDirty = true; // FIXME: In theory shouldn't have to leak into user performing a sort on resume. table->ColumnsNames.clear(); table->MemoryCompacted = true; for (int n = 0; n < table->ColumnsCount; n++) table->Columns[n].NameOffset = -1; g.TablesLastTimeActive[g.Tables.GetIndex(table)] = -1.0f; } void ImGui::TableGcCompactTransientBuffers(ImGuiTableTempData* temp_data) { temp_data->DrawSplitter.ClearFreeMemory(); temp_data->LastTimeActive = -1.0f; } // Compact and remove unused settings data (currently only used by TestEngine) void ImGui::TableGcCompactSettings() { ImGuiContext& g = *GImGui; int required_memory = 0; for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings)) if (settings->ID != 0) required_memory += (int)TableSettingsCalcChunkSize(settings->ColumnsCount); if (required_memory == g.SettingsTables.Buf.Size) return; ImChunkStream new_chunk_stream; new_chunk_stream.Buf.reserve(required_memory); for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings)) if (settings->ID != 0) memcpy(new_chunk_stream.alloc_chunk(TableSettingsCalcChunkSize(settings->ColumnsCount)), settings, TableSettingsCalcChunkSize(settings->ColumnsCount)); g.SettingsTables.swap(new_chunk_stream); } //------------------------------------------------------------------------- // [SECTION] Tables: Debugging //------------------------------------------------------------------------- // - DebugNodeTable() [Internal] //------------------------------------------------------------------------- #ifndef IMGUI_DISABLE_DEBUG_TOOLS static const char* DebugNodeTableGetSizingPolicyDesc(ImGuiTableFlags sizing_policy) { sizing_policy &= ImGuiTableFlags_SizingMask_; if (sizing_policy == ImGuiTableFlags_SizingFixedFit) { return "FixedFit"; } if (sizing_policy == ImGuiTableFlags_SizingFixedSame) { return "FixedSame"; } if (sizing_policy == ImGuiTableFlags_SizingStretchProp) { return "StretchProp"; } if (sizing_policy == ImGuiTableFlags_SizingStretchSame) { return "StretchSame"; } return "N/A"; } void ImGui::DebugNodeTable(ImGuiTable* table) { ImGuiContext& g = *GImGui; const bool is_active = (table->LastFrameActive >= g.FrameCount - 2); // Note that fully clipped early out scrolling tables will appear as inactive here. if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); } bool open = TreeNode(table, "Table 0x%08X (%d columns, in '%s')%s", table->ID, table->ColumnsCount, table->OuterWindow->Name, is_active ? "" : " *Inactive*"); if (!is_active) { PopStyleColor(); } if (IsItemHovered()) GetForegroundDrawList()->AddRect(table->OuterRect.Min, table->OuterRect.Max, IM_COL32(255, 255, 0, 255)); if (IsItemVisible() && table->HoveredColumnBody != -1) GetForegroundDrawList()->AddRect(GetItemRectMin(), GetItemRectMax(), IM_COL32(255, 255, 0, 255)); if (!open) return; if (table->InstanceCurrent > 0) Text("** %d instances of same table! Some data below will refer to last instance.", table->InstanceCurrent + 1); if (g.IO.ConfigDebugIsDebuggerPresent) { if (DebugBreakButton("**DebugBreak**", "in BeginTable()")) g.DebugBreakInTable = table->ID; SameLine(); } bool clear_settings = SmallButton("Clear settings"); BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f) Sizing: '%s'", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight(), DebugNodeTableGetSizingPolicyDesc(table->Flags)); BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : ""); BulletText("CellPaddingX: %.1f, CellSpacingX: %.1f/%.1f, OuterPaddingX: %.1f", table->CellPaddingX, table->CellSpacingX1, table->CellSpacingX2, table->OuterPaddingX); BulletText("HoveredColumnBody: %d, HoveredColumnBorder: %d", table->HoveredColumnBody, table->HoveredColumnBorder); BulletText("ResizedColumn: %d, ReorderColumn: %d, HeldHeaderColumn: %d", table->ResizedColumn, table->ReorderColumn, table->HeldHeaderColumn); for (int n = 0; n < table->InstanceCurrent + 1; n++) { ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, n); BulletText("Instance %d: HoveredRow: %d, LastOuterHeight: %.2f", n, table_instance->HoveredRowLast, table_instance->LastOuterHeight); } //BulletText("BgDrawChannels: %d/%d", 0, table->BgDrawChannelUnfrozen); float sum_weights = 0.0f; for (int n = 0; n < table->ColumnsCount; n++) if (table->Columns[n].Flags & ImGuiTableColumnFlags_WidthStretch) sum_weights += table->Columns[n].StretchWeight; for (int n = 0; n < table->ColumnsCount; n++) { ImGuiTableColumn* column = &table->Columns[n]; const char* name = TableGetColumnName(table, n); char buf[512]; ImFormatString(buf, IM_ARRAYSIZE(buf), "Column %d order %d '%s': offset %+.2f to %+.2f%s\n" "Enabled: %d, VisibleX/Y: %d/%d, RequestOutput: %d, SkipItems: %d, DrawChannels: %d,%d\n" "WidthGiven: %.1f, Request/Auto: %.1f/%.1f, StretchWeight: %.3f (%.1f%%)\n" "MinX: %.1f, MaxX: %.1f (%+.1f), ClipRect: %.1f to %.1f (+%.1f)\n" "ContentWidth: %.1f,%.1f, HeadersUsed/Ideal %.1f/%.1f\n" "Sort: %d%s, UserID: 0x%08X, Flags: 0x%04X: %s%s%s..", n, column->DisplayOrder, name, column->MinX - table->WorkRect.Min.x, column->MaxX - table->WorkRect.Min.x, (n < table->FreezeColumnsRequest) ? " (Frozen)" : "", column->IsEnabled, column->IsVisibleX, column->IsVisibleY, column->IsRequestOutput, column->IsSkipItems, column->DrawChannelFrozen, column->DrawChannelUnfrozen, column->WidthGiven, column->WidthRequest, column->WidthAuto, column->StretchWeight, column->StretchWeight > 0.0f ? (column->StretchWeight / sum_weights) * 100.0f : 0.0f, column->MinX, column->MaxX, column->MaxX - column->MinX, column->ClipRect.Min.x, column->ClipRect.Max.x, column->ClipRect.Max.x - column->ClipRect.Min.x, column->ContentMaxXFrozen - column->WorkMinX, column->ContentMaxXUnfrozen - column->WorkMinX, column->ContentMaxXHeadersUsed - column->WorkMinX, column->ContentMaxXHeadersIdeal - column->WorkMinX, column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? " (Asc)" : (column->SortDirection == ImGuiSortDirection_Descending) ? " (Des)" : "", column->UserID, column->Flags, (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? "WidthStretch " : "", (column->Flags & ImGuiTableColumnFlags_WidthFixed) ? "WidthFixed " : "", (column->Flags & ImGuiTableColumnFlags_NoResize) ? "NoResize " : ""); Bullet(); Selectable(buf); if (IsItemHovered()) { ImRect r(column->MinX, table->OuterRect.Min.y, column->MaxX, table->OuterRect.Max.y); GetForegroundDrawList()->AddRect(r.Min, r.Max, IM_COL32(255, 255, 0, 255)); } } if (ImGuiTableSettings* settings = TableGetBoundSettings(table)) DebugNodeTableSettings(settings); if (clear_settings) table->IsResetAllRequest = true; TreePop(); } void ImGui::DebugNodeTableSettings(ImGuiTableSettings* settings) { if (!TreeNode((void*)(intptr_t)settings->ID, "Settings 0x%08X (%d columns)", settings->ID, settings->ColumnsCount)) return; BulletText("SaveFlags: 0x%08X", settings->SaveFlags); BulletText("ColumnsCount: %d (max %d)", settings->ColumnsCount, settings->ColumnsCountMax); for (int n = 0; n < settings->ColumnsCount; n++) { ImGuiTableColumnSettings* column_settings = &settings->GetColumnSettings()[n]; ImGuiSortDirection sort_dir = (column_settings->SortOrder != -1) ? (ImGuiSortDirection)column_settings->SortDirection : ImGuiSortDirection_None; BulletText("Column %d Order %d SortOrder %d %s Vis %d %s %7.3f UserID 0x%08X", n, column_settings->DisplayOrder, column_settings->SortOrder, (sort_dir == ImGuiSortDirection_Ascending) ? "Asc" : (sort_dir == ImGuiSortDirection_Descending) ? "Des" : "---", column_settings->IsEnabled, column_settings->IsStretch ? "Weight" : "Width ", column_settings->WidthOrWeight, column_settings->UserID); } TreePop(); } #else // #ifndef IMGUI_DISABLE_DEBUG_TOOLS void ImGui::DebugNodeTable(ImGuiTable*) {} void ImGui::DebugNodeTableSettings(ImGuiTableSettings*) {} #endif //------------------------------------------------------------------------- // [SECTION] Columns, BeginColumns, EndColumns, etc. // (This is a legacy API, prefer using BeginTable/EndTable!) //------------------------------------------------------------------------- // FIXME: sizing is lossy when columns width is very small (default width may turn negative etc.) //------------------------------------------------------------------------- // - SetWindowClipRectBeforeSetChannel() [Internal] // - GetColumnIndex() // - GetColumnsCount() // - GetColumnOffset() // - GetColumnWidth() // - SetColumnOffset() // - SetColumnWidth() // - PushColumnClipRect() [Internal] // - PushColumnsBackground() [Internal] // - PopColumnsBackground() [Internal] // - FindOrCreateColumns() [Internal] // - GetColumnsID() [Internal] // - BeginColumns() // - NextColumn() // - EndColumns() // - Columns() //------------------------------------------------------------------------- // [Internal] Small optimization to avoid calls to PopClipRect/SetCurrentChannel/PushClipRect in sequences, // they would meddle many times with the underlying ImDrawCmd. // Instead, we do a preemptive overwrite of clipping rectangle _without_ altering the command-buffer and let // the subsequent single call to SetCurrentChannel() does it things once. void ImGui::SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect) { ImVec4 clip_rect_vec4 = clip_rect.ToVec4(); window->ClipRect = clip_rect; window->DrawList->_CmdHeader.ClipRect = clip_rect_vec4; window->DrawList->_ClipRectStack.Data[window->DrawList->_ClipRectStack.Size - 1] = clip_rect_vec4; } int ImGui::GetColumnIndex() { ImGuiWindow* window = GetCurrentWindowRead(); return window->DC.CurrentColumns ? window->DC.CurrentColumns->Current : 0; } int ImGui::GetColumnsCount() { ImGuiWindow* window = GetCurrentWindowRead(); return window->DC.CurrentColumns ? window->DC.CurrentColumns->Count : 1; } float ImGui::GetColumnOffsetFromNorm(const ImGuiOldColumns* columns, float offset_norm) { return offset_norm * (columns->OffMaxX - columns->OffMinX); } float ImGui::GetColumnNormFromOffset(const ImGuiOldColumns* columns, float offset) { return offset / (columns->OffMaxX - columns->OffMinX); } static const float COLUMNS_HIT_RECT_HALF_WIDTH = 4.0f; static float GetDraggedColumnOffset(ImGuiOldColumns* columns, int column_index) { // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning. ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(column_index > 0); // We are not supposed to drag column 0. IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index)); float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + COLUMNS_HIT_RECT_HALF_WIDTH - window->Pos.x; x = ImMax(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing); if ((columns->Flags & ImGuiOldColumnFlags_NoPreserveWidths)) x = ImMin(x, ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing); return x; } float ImGui::GetColumnOffset(int column_index) { ImGuiWindow* window = GetCurrentWindowRead(); ImGuiOldColumns* columns = window->DC.CurrentColumns; if (columns == NULL) return 0.0f; if (column_index < 0) column_index = columns->Current; IM_ASSERT(column_index < columns->Columns.Size); const float t = columns->Columns[column_index].OffsetNorm; const float x_offset = ImLerp(columns->OffMinX, columns->OffMaxX, t); return x_offset; } static float GetColumnWidthEx(ImGuiOldColumns* columns, int column_index, bool before_resize = false) { if (column_index < 0) column_index = columns->Current; float offset_norm; if (before_resize) offset_norm = columns->Columns[column_index + 1].OffsetNormBeforeResize - columns->Columns[column_index].OffsetNormBeforeResize; else offset_norm = columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm; return ImGui::GetColumnOffsetFromNorm(columns, offset_norm); } float ImGui::GetColumnWidth(int column_index) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiOldColumns* columns = window->DC.CurrentColumns; if (columns == NULL) return GetContentRegionAvail().x; if (column_index < 0) column_index = columns->Current; return GetColumnOffsetFromNorm(columns, columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm); } void ImGui::SetColumnOffset(int column_index, float offset) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiOldColumns* columns = window->DC.CurrentColumns; IM_ASSERT(columns != NULL); if (column_index < 0) column_index = columns->Current; IM_ASSERT(column_index < columns->Columns.Size); const bool preserve_width = !(columns->Flags & ImGuiOldColumnFlags_NoPreserveWidths) && (column_index < columns->Count - 1); const float width = preserve_width ? GetColumnWidthEx(columns, column_index, columns->IsBeingResized) : 0.0f; if (!(columns->Flags & ImGuiOldColumnFlags_NoForceWithinWindow)) offset = ImMin(offset, columns->OffMaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index)); columns->Columns[column_index].OffsetNorm = GetColumnNormFromOffset(columns, offset - columns->OffMinX); if (preserve_width) SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); } void ImGui::SetColumnWidth(int column_index, float width) { ImGuiWindow* window = GetCurrentWindowRead(); ImGuiOldColumns* columns = window->DC.CurrentColumns; IM_ASSERT(columns != NULL); if (column_index < 0) column_index = columns->Current; SetColumnOffset(column_index + 1, GetColumnOffset(column_index) + width); } void ImGui::PushColumnClipRect(int column_index) { ImGuiWindow* window = GetCurrentWindowRead(); ImGuiOldColumns* columns = window->DC.CurrentColumns; if (column_index < 0) column_index = columns->Current; ImGuiOldColumnData* column = &columns->Columns[column_index]; PushClipRect(column->ClipRect.Min, column->ClipRect.Max, false); } // Get into the columns background draw command (which is generally the same draw command as before we called BeginColumns) void ImGui::PushColumnsBackground() { ImGuiWindow* window = GetCurrentWindowRead(); ImGuiOldColumns* columns = window->DC.CurrentColumns; if (columns->Count == 1) return; // Optimization: avoid SetCurrentChannel() + PushClipRect() columns->HostBackupClipRect = window->ClipRect; SetWindowClipRectBeforeSetChannel(window, columns->HostInitialClipRect); columns->Splitter.SetCurrentChannel(window->DrawList, 0); } void ImGui::PopColumnsBackground() { ImGuiWindow* window = GetCurrentWindowRead(); ImGuiOldColumns* columns = window->DC.CurrentColumns; if (columns->Count == 1) return; // Optimization: avoid PopClipRect() + SetCurrentChannel() SetWindowClipRectBeforeSetChannel(window, columns->HostBackupClipRect); columns->Splitter.SetCurrentChannel(window->DrawList, columns->Current + 1); } ImGuiOldColumns* ImGui::FindOrCreateColumns(ImGuiWindow* window, ImGuiID id) { // We have few columns per window so for now we don't need bother much with turning this into a faster lookup. for (int n = 0; n < window->ColumnsStorage.Size; n++) if (window->ColumnsStorage[n].ID == id) return &window->ColumnsStorage[n]; window->ColumnsStorage.push_back(ImGuiOldColumns()); ImGuiOldColumns* columns = &window->ColumnsStorage.back(); columns->ID = id; return columns; } ImGuiID ImGui::GetColumnsID(const char* str_id, int columns_count) { ImGuiWindow* window = GetCurrentWindow(); // Differentiate column ID with an arbitrary prefix for cases where users name their columns set the same as another widget. // In addition, when an identifier isn't explicitly provided we include the number of columns in the hash to make it uniquer. PushID(0x11223347 + (str_id ? 0 : columns_count)); ImGuiID id = window->GetID(str_id ? str_id : "columns"); PopID(); return id; } void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiOldColumnFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(columns_count >= 1); IM_ASSERT(window->DC.CurrentColumns == NULL); // Nested columns are currently not supported // Acquire storage for the columns set ImGuiID id = GetColumnsID(str_id, columns_count); ImGuiOldColumns* columns = FindOrCreateColumns(window, id); IM_ASSERT(columns->ID == id); columns->Current = 0; columns->Count = columns_count; columns->Flags = flags; window->DC.CurrentColumns = columns; window->DC.NavIsScrollPushableX = false; // Shortcut for NavUpdateCurrentWindowIsScrollPushableX(); columns->HostCursorPosY = window->DC.CursorPos.y; columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x; columns->HostInitialClipRect = window->ClipRect; columns->HostBackupParentWorkRect = window->ParentWorkRect; window->ParentWorkRect = window->WorkRect; // Set state for first column // We aim so that the right-most column will have the same clipping width as other after being clipped by parent ClipRect const float column_padding = g.Style.ItemSpacing.x; const float half_clip_extend_x = ImTrunc(ImMax(window->WindowPadding.x * 0.5f, window->WindowBorderSize)); const float max_1 = window->WorkRect.Max.x + column_padding - ImMax(column_padding - window->WindowPadding.x, 0.0f); const float max_2 = window->WorkRect.Max.x + half_clip_extend_x; columns->OffMinX = window->DC.Indent.x - column_padding + ImMax(column_padding - window->WindowPadding.x, 0.0f); columns->OffMaxX = ImMax(ImMin(max_1, max_2) - window->Pos.x, columns->OffMinX + 1.0f); columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y; // Clear data if columns count changed if (columns->Columns.Size != 0 && columns->Columns.Size != columns_count + 1) columns->Columns.resize(0); // Initialize default widths columns->IsFirstFrame = (columns->Columns.Size == 0); if (columns->Columns.Size == 0) { columns->Columns.reserve(columns_count + 1); for (int n = 0; n < columns_count + 1; n++) { ImGuiOldColumnData column; column.OffsetNorm = n / (float)columns_count; columns->Columns.push_back(column); } } for (int n = 0; n < columns_count; n++) { // Compute clipping rectangle ImGuiOldColumnData* column = &columns->Columns[n]; float clip_x1 = IM_ROUND(window->Pos.x + GetColumnOffset(n)); float clip_x2 = IM_ROUND(window->Pos.x + GetColumnOffset(n + 1) - 1.0f); column->ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); column->ClipRect.ClipWithFull(window->ClipRect); } if (columns->Count > 1) { columns->Splitter.Split(window->DrawList, 1 + columns->Count); columns->Splitter.SetCurrentChannel(window->DrawList, 1); PushColumnClipRect(0); } // We don't generally store Indent.x inside ColumnsOffset because it may be manipulated by the user. float offset_0 = GetColumnOffset(columns->Current); float offset_1 = GetColumnOffset(columns->Current + 1); float width = offset_1 - offset_0; PushItemWidth(width * 0.65f); window->DC.ColumnsOffset.x = ImMax(column_padding - window->WindowPadding.x, 0.0f); window->DC.CursorPos.x = IM_TRUNC(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding; window->WorkRect.Max.y = window->ContentRegionRect.Max.y; } void ImGui::NextColumn() { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems || window->DC.CurrentColumns == NULL) return; ImGuiContext& g = *GImGui; ImGuiOldColumns* columns = window->DC.CurrentColumns; if (columns->Count == 1) { window->DC.CursorPos.x = IM_TRUNC(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); IM_ASSERT(columns->Current == 0); return; } // Next column if (++columns->Current == columns->Count) columns->Current = 0; PopItemWidth(); // Optimization: avoid PopClipRect() + SetCurrentChannel() + PushClipRect() // (which would needlessly attempt to update commands in the wrong channel, then pop or overwrite them), ImGuiOldColumnData* column = &columns->Columns[columns->Current]; SetWindowClipRectBeforeSetChannel(window, column->ClipRect); columns->Splitter.SetCurrentChannel(window->DrawList, columns->Current + 1); const float column_padding = g.Style.ItemSpacing.x; columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y); if (columns->Current > 0) { // Columns 1+ ignore IndentX (by canceling it out) // FIXME-COLUMNS: Unnecessary, could be locked? window->DC.ColumnsOffset.x = GetColumnOffset(columns->Current) - window->DC.Indent.x + column_padding; } else { // New row/line: column 0 honor IndentX. window->DC.ColumnsOffset.x = ImMax(column_padding - window->WindowPadding.x, 0.0f); window->DC.IsSameLine = false; columns->LineMinY = columns->LineMaxY; } window->DC.CursorPos.x = IM_TRUNC(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); window->DC.CursorPos.y = columns->LineMinY; window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); window->DC.CurrLineTextBaseOffset = 0.0f; // FIXME-COLUMNS: Share code with BeginColumns() - move code on columns setup. float offset_0 = GetColumnOffset(columns->Current); float offset_1 = GetColumnOffset(columns->Current + 1); float width = offset_1 - offset_0; PushItemWidth(width * 0.65f); window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding; } void ImGui::EndColumns() { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); ImGuiOldColumns* columns = window->DC.CurrentColumns; IM_ASSERT(columns != NULL); PopItemWidth(); if (columns->Count > 1) { PopClipRect(); columns->Splitter.Merge(window->DrawList); } const ImGuiOldColumnFlags flags = columns->Flags; columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y); window->DC.CursorPos.y = columns->LineMaxY; if (!(flags & ImGuiOldColumnFlags_GrowParentContentsSize)) window->DC.CursorMaxPos.x = columns->HostCursorMaxPosX; // Restore cursor max pos, as columns don't grow parent // Draw columns borders and handle resize // The IsBeingResized flag ensure we preserve pre-resize columns width so back-and-forth are not lossy bool is_being_resized = false; if (!(flags & ImGuiOldColumnFlags_NoBorder) && !window->SkipItems) { // We clip Y boundaries CPU side because very long triangles are mishandled by some GPU drivers. const float y1 = ImMax(columns->HostCursorPosY, window->ClipRect.Min.y); const float y2 = ImMin(window->DC.CursorPos.y, window->ClipRect.Max.y); int dragging_column = -1; for (int n = 1; n < columns->Count; n++) { ImGuiOldColumnData* column = &columns->Columns[n]; float x = window->Pos.x + GetColumnOffset(n); const ImGuiID column_id = columns->ID + ImGuiID(n); const float column_hit_hw = COLUMNS_HIT_RECT_HALF_WIDTH; const ImRect column_hit_rect(ImVec2(x - column_hit_hw, y1), ImVec2(x + column_hit_hw, y2)); if (!ItemAdd(column_hit_rect, column_id, NULL, ImGuiItemFlags_NoNav)) continue; bool hovered = false, held = false; if (!(flags & ImGuiOldColumnFlags_NoResize)) { ButtonBehavior(column_hit_rect, column_id, &hovered, &held); if (hovered || held) g.MouseCursor = ImGuiMouseCursor_ResizeEW; if (held && !(column->Flags & ImGuiOldColumnFlags_NoResize)) dragging_column = n; } // Draw column const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); const float xi = IM_TRUNC(x); window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col); } // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame. if (dragging_column != -1) { if (!columns->IsBeingResized) for (int n = 0; n < columns->Count + 1; n++) columns->Columns[n].OffsetNormBeforeResize = columns->Columns[n].OffsetNorm; columns->IsBeingResized = is_being_resized = true; float x = GetDraggedColumnOffset(columns, dragging_column); SetColumnOffset(dragging_column, x); } } columns->IsBeingResized = is_being_resized; window->WorkRect = window->ParentWorkRect; window->ParentWorkRect = columns->HostBackupParentWorkRect; window->DC.CurrentColumns = NULL; window->DC.ColumnsOffset.x = 0.0f; window->DC.CursorPos.x = IM_TRUNC(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); NavUpdateCurrentWindowIsScrollPushableX(); } void ImGui::Columns(int columns_count, const char* id, bool border) { ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(columns_count >= 1); ImGuiOldColumnFlags flags = (border ? 0 : ImGuiOldColumnFlags_NoBorder); //flags |= ImGuiOldColumnFlags_NoPreserveWidths; // NB: Legacy behavior ImGuiOldColumns* columns = window->DC.CurrentColumns; if (columns != NULL && columns->Count == columns_count && columns->Flags == flags) return; if (columns != NULL) EndColumns(); if (columns_count != 1) BeginColumns(id, columns_count, flags); } //------------------------------------------------------------------------- #endif // #ifndef IMGUI_DISABLE RenderKit-ospray-f2a61c2/apps/common/external/imgui/imgui_widgets.cpp000066400000000000000000015416401456566705700261150ustar00rootroot00000000000000// dear imgui, v1.90.3 // (widgets code) /* Index of this file: // [SECTION] Forward Declarations // [SECTION] Widgets: Text, etc. // [SECTION] Widgets: Main (Button, Image, Checkbox, RadioButton, ProgressBar, Bullet, etc.) // [SECTION] Widgets: Low-level Layout helpers (Spacing, Dummy, NewLine, Separator, etc.) // [SECTION] Widgets: ComboBox // [SECTION] Data Type and Data Formatting Helpers // [SECTION] Widgets: DragScalar, DragFloat, DragInt, etc. // [SECTION] Widgets: SliderScalar, SliderFloat, SliderInt, etc. // [SECTION] Widgets: InputScalar, InputFloat, InputInt, etc. // [SECTION] Widgets: InputText, InputTextMultiline // [SECTION] Widgets: ColorEdit, ColorPicker, ColorButton, etc. // [SECTION] Widgets: TreeNode, CollapsingHeader, etc. // [SECTION] Widgets: Selectable // [SECTION] Widgets: Typing-Select support // [SECTION] Widgets: Multi-Select support // [SECTION] Widgets: ListBox // [SECTION] Widgets: PlotLines, PlotHistogram // [SECTION] Widgets: Value helpers // [SECTION] Widgets: MenuItem, BeginMenu, EndMenu, etc. // [SECTION] Widgets: BeginTabBar, EndTabBar, etc. // [SECTION] Widgets: BeginTabItem, EndTabItem, etc. // [SECTION] Widgets: Columns, BeginColumns, EndColumns, etc. */ #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif #include "imgui.h" #ifndef IMGUI_DISABLE #include "imgui_internal.h" // System includes #include // intptr_t //------------------------------------------------------------------------- // Warnings //------------------------------------------------------------------------- // Visual Studio warnings #ifdef _MSC_VER #pragma warning (disable: 4127) // condition expression is constant #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later #pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types #endif #pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2). #pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). #endif // Clang/GCC warnings with -Weverything #if defined(__clang__) #if __has_warning("-Wunknown-warning-option") #pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great! #endif #pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx' #pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse. #pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants (typically 0.0f) is ok. #pragma clang diagnostic ignored "-Wformat-nonliteral" // warning: format string is not a string literal // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code. #pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0 #pragma clang diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function // using printf() is a misery with this as C++ va_arg ellipsis changes float to double. #pragma clang diagnostic ignored "-Wenum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') #pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision #elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked #pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead #pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated #endif //------------------------------------------------------------------------- // Data //------------------------------------------------------------------------- // Widgets static const float DRAGDROP_HOLD_TO_OPEN_TIMER = 0.70f; // Time for drag-hold to activate items accepting the ImGuiButtonFlags_PressedOnDragDropHold button behavior. static const float DRAG_MOUSE_THRESHOLD_FACTOR = 0.50f; // Multiplier for the default value of io.MouseDragThreshold to make DragFloat/DragInt react faster to mouse drags. // Those MIN/MAX values are not define because we need to point to them static const signed char IM_S8_MIN = -128; static const signed char IM_S8_MAX = 127; static const unsigned char IM_U8_MIN = 0; static const unsigned char IM_U8_MAX = 0xFF; static const signed short IM_S16_MIN = -32768; static const signed short IM_S16_MAX = 32767; static const unsigned short IM_U16_MIN = 0; static const unsigned short IM_U16_MAX = 0xFFFF; static const ImS32 IM_S32_MIN = INT_MIN; // (-2147483647 - 1), (0x80000000); static const ImS32 IM_S32_MAX = INT_MAX; // (2147483647), (0x7FFFFFFF) static const ImU32 IM_U32_MIN = 0; static const ImU32 IM_U32_MAX = UINT_MAX; // (0xFFFFFFFF) #ifdef LLONG_MIN static const ImS64 IM_S64_MIN = LLONG_MIN; // (-9223372036854775807ll - 1ll); static const ImS64 IM_S64_MAX = LLONG_MAX; // (9223372036854775807ll); #else static const ImS64 IM_S64_MIN = -9223372036854775807LL - 1; static const ImS64 IM_S64_MAX = 9223372036854775807LL; #endif static const ImU64 IM_U64_MIN = 0; #ifdef ULLONG_MAX static const ImU64 IM_U64_MAX = ULLONG_MAX; // (0xFFFFFFFFFFFFFFFFull); #else static const ImU64 IM_U64_MAX = (2ULL * 9223372036854775807LL + 1); #endif //------------------------------------------------------------------------- // [SECTION] Forward Declarations //------------------------------------------------------------------------- // For InputTextEx() static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, ImGuiInputSource input_source); static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end); static ImVec2 InputTextCalcTextSizeW(ImGuiContext* ctx, const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false); //------------------------------------------------------------------------- // [SECTION] Widgets: Text, etc. //------------------------------------------------------------------------- // - TextEx() [Internal] // - TextUnformatted() // - Text() // - TextV() // - TextColored() // - TextColoredV() // - TextDisabled() // - TextDisabledV() // - TextWrapped() // - TextWrappedV() // - LabelText() // - LabelTextV() // - BulletText() // - BulletTextV() //------------------------------------------------------------------------- void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; ImGuiContext& g = *GImGui; // Accept null ranges if (text == text_end) text = text_end = ""; // Calculate length const char* text_begin = text; if (text_end == NULL) text_end = text + strlen(text); // FIXME-OPT const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); const float wrap_pos_x = window->DC.TextWrapPos; const bool wrap_enabled = (wrap_pos_x >= 0.0f); if (text_end - text <= 2000 || wrap_enabled) { // Common case const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f; const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width); ImRect bb(text_pos, text_pos + text_size); ItemSize(text_size, 0.0f); if (!ItemAdd(bb, 0)) return; // Render (we don't hide text after ## in this end-user function) RenderTextWrapped(bb.Min, text_begin, text_end, wrap_width); } else { // Long text! // Perform manual coarse clipping to optimize for long multi-line text // - From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled. // - We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line. // - We use memchr(), pay attention that well optimized versions of those str/mem functions are much faster than a casually written loop. const char* line = text; const float line_height = GetTextLineHeight(); ImVec2 text_size(0, 0); // Lines to skip (can't skip when logging text) ImVec2 pos = text_pos; if (!g.LogEnabled) { int lines_skippable = (int)((window->ClipRect.Min.y - text_pos.y) / line_height); if (lines_skippable > 0) { int lines_skipped = 0; while (line < text_end && lines_skipped < lines_skippable) { const char* line_end = (const char*)memchr(line, '\n', text_end - line); if (!line_end) line_end = text_end; if ((flags & ImGuiTextFlags_NoWidthForLargeClippedText) == 0) text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x); line = line_end + 1; lines_skipped++; } pos.y += lines_skipped * line_height; } } // Lines to render if (line < text_end) { ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height)); while (line < text_end) { if (IsClippedEx(line_rect, 0)) break; const char* line_end = (const char*)memchr(line, '\n', text_end - line); if (!line_end) line_end = text_end; text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x); RenderText(pos, line, line_end, false); line = line_end + 1; line_rect.Min.y += line_height; line_rect.Max.y += line_height; pos.y += line_height; } // Count remaining lines int lines_skipped = 0; while (line < text_end) { const char* line_end = (const char*)memchr(line, '\n', text_end - line); if (!line_end) line_end = text_end; if ((flags & ImGuiTextFlags_NoWidthForLargeClippedText) == 0) text_size.x = ImMax(text_size.x, CalcTextSize(line, line_end).x); line = line_end + 1; lines_skipped++; } pos.y += lines_skipped * line_height; } text_size.y = (pos - text_pos).y; ImRect bb(text_pos, text_pos + text_size); ItemSize(text_size, 0.0f); ItemAdd(bb, 0); } } void ImGui::TextUnformatted(const char* text, const char* text_end) { TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText); } void ImGui::Text(const char* fmt, ...) { va_list args; va_start(args, fmt); TextV(fmt, args); va_end(args); } void ImGui::TextV(const char* fmt, va_list args) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; const char* text, *text_end; ImFormatStringToTempBufferV(&text, &text_end, fmt, args); TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText); } void ImGui::TextColored(const ImVec4& col, const char* fmt, ...) { va_list args; va_start(args, fmt); TextColoredV(col, fmt, args); va_end(args); } void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args) { PushStyleColor(ImGuiCol_Text, col); TextV(fmt, args); PopStyleColor(); } void ImGui::TextDisabled(const char* fmt, ...) { va_list args; va_start(args, fmt); TextDisabledV(fmt, args); va_end(args); } void ImGui::TextDisabledV(const char* fmt, va_list args) { ImGuiContext& g = *GImGui; PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); TextV(fmt, args); PopStyleColor(); } void ImGui::TextWrapped(const char* fmt, ...) { va_list args; va_start(args, fmt); TextWrappedV(fmt, args); va_end(args); } void ImGui::TextWrappedV(const char* fmt, va_list args) { ImGuiContext& g = *GImGui; const bool need_backup = (g.CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position if one is already set if (need_backup) PushTextWrapPos(0.0f); TextV(fmt, args); if (need_backup) PopTextWrapPos(); } void ImGui::LabelText(const char* label, const char* fmt, ...) { va_list args; va_start(args, fmt); LabelTextV(label, fmt, args); va_end(args); } // Add a label+text combo aligned to other label+value widgets void ImGui::LabelTextV(const char* label, const char* fmt, va_list args) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const float w = CalcItemWidth(); const char* value_text_begin, *value_text_end; ImFormatStringToTempBufferV(&value_text_begin, &value_text_end, fmt, args); const ImVec2 value_size = CalcTextSize(value_text_begin, value_text_end, false); const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImVec2 pos = window->DC.CursorPos; const ImRect value_bb(pos, pos + ImVec2(w, value_size.y + style.FramePadding.y * 2)); const ImRect total_bb(pos, pos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), ImMax(value_size.y, label_size.y) + style.FramePadding.y * 2)); ItemSize(total_bb, style.FramePadding.y); if (!ItemAdd(total_bb, 0)) return; // Render RenderTextClipped(value_bb.Min + style.FramePadding, value_bb.Max, value_text_begin, value_text_end, &value_size, ImVec2(0.0f, 0.0f)); if (label_size.x > 0.0f) RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label); } void ImGui::BulletText(const char* fmt, ...) { va_list args; va_start(args, fmt); BulletTextV(fmt, args); va_end(args); } // Text with a little bullet aligned to the typical tree node. void ImGui::BulletTextV(const char* fmt, va_list args) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const char* text_begin, *text_end; ImFormatStringToTempBufferV(&text_begin, &text_end, fmt, args); const ImVec2 label_size = CalcTextSize(text_begin, text_end, false); const ImVec2 total_size = ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x * 2) : 0.0f), label_size.y); // Empty text doesn't add padding ImVec2 pos = window->DC.CursorPos; pos.y += window->DC.CurrLineTextBaseOffset; ItemSize(total_size, 0.0f); const ImRect bb(pos, pos + total_size); if (!ItemAdd(bb, 0)) return; // Render ImU32 text_col = GetColorU32(ImGuiCol_Text); RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize * 0.5f, g.FontSize * 0.5f), text_col); RenderText(bb.Min + ImVec2(g.FontSize + style.FramePadding.x * 2, 0.0f), text_begin, text_end, false); } //------------------------------------------------------------------------- // [SECTION] Widgets: Main //------------------------------------------------------------------------- // - ButtonBehavior() [Internal] // - Button() // - SmallButton() // - InvisibleButton() // - ArrowButton() // - CloseButton() [Internal] // - CollapseButton() [Internal] // - GetWindowScrollbarID() [Internal] // - GetWindowScrollbarRect() [Internal] // - Scrollbar() [Internal] // - ScrollbarEx() [Internal] // - Image() // - ImageButton() // - Checkbox() // - CheckboxFlagsT() [Internal] // - CheckboxFlags() // - RadioButton() // - ProgressBar() // - Bullet() //------------------------------------------------------------------------- // The ButtonBehavior() function is key to many interactions and used by many/most widgets. // Because we handle so many cases (keyboard/gamepad navigation, drag and drop) and many specific behavior (via ImGuiButtonFlags_), // this code is a little complex. // By far the most common path is interacting with the Mouse using the default ImGuiButtonFlags_PressedOnClickRelease button behavior. // See the series of events below and the corresponding state reported by dear imgui: //------------------------------------------------------------------------------------------------------------------------------------------------ // with PressedOnClickRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() // Frame N+0 (mouse is outside bb) - - - - - - // Frame N+1 (mouse moves inside bb) - true - - - - // Frame N+2 (mouse button is down) - true true true - true // Frame N+3 (mouse button is down) - true true - - - // Frame N+4 (mouse moves outside bb) - - true - - - // Frame N+5 (mouse moves inside bb) - true true - - - // Frame N+6 (mouse button is released) true true - - true - // Frame N+7 (mouse button is released) - true - - - - // Frame N+8 (mouse moves outside bb) - - - - - - //------------------------------------------------------------------------------------------------------------------------------------------------ // with PressedOnClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() // Frame N+2 (mouse button is down) true true true true - true // Frame N+3 (mouse button is down) - true true - - - // Frame N+6 (mouse button is released) - true - - true - // Frame N+7 (mouse button is released) - true - - - - //------------------------------------------------------------------------------------------------------------------------------------------------ // with PressedOnRelease: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() // Frame N+2 (mouse button is down) - true - - - true // Frame N+3 (mouse button is down) - true - - - - // Frame N+6 (mouse button is released) true true - - - - // Frame N+7 (mouse button is released) - true - - - - //------------------------------------------------------------------------------------------------------------------------------------------------ // with PressedOnDoubleClick: return-value IsItemHovered() IsItemActive() IsItemActivated() IsItemDeactivated() IsItemClicked() // Frame N+0 (mouse button is down) - true - - - true // Frame N+1 (mouse button is down) - true - - - - // Frame N+2 (mouse button is released) - true - - - - // Frame N+3 (mouse button is released) - true - - - - // Frame N+4 (mouse button is down) true true true true - true // Frame N+5 (mouse button is down) - true true - - - // Frame N+6 (mouse button is released) - true - - true - // Frame N+7 (mouse button is released) - true - - - - //------------------------------------------------------------------------------------------------------------------------------------------------ // Note that some combinations are supported, // - PressedOnDragDropHold can generally be associated with any flag. // - PressedOnDoubleClick can be associated by PressedOnClickRelease/PressedOnRelease, in which case the second release event won't be reported. //------------------------------------------------------------------------------------------------------------------------------------------------ // The behavior of the return-value changes when ImGuiButtonFlags_Repeat is set: // Repeat+ Repeat+ Repeat+ Repeat+ // PressedOnClickRelease PressedOnClick PressedOnRelease PressedOnDoubleClick //------------------------------------------------------------------------------------------------------------------------------------------------- // Frame N+0 (mouse button is down) - true - true // ... - - - - // Frame N + RepeatDelay true true - true // ... - - - - // Frame N + RepeatDelay + RepeatRate*N true true - true //------------------------------------------------------------------------------------------------------------------------------------------------- // FIXME: For refactor we could output flags, incl mouse hovered vs nav keyboard vs nav triggered etc. // And better standardize how widgets use 'GetColor32((held && hovered) ? ... : hovered ? ...)' vs 'GetColor32(held ? ... : hovered ? ...);' // For mouse feedback we typically prefer the 'held && hovered' test, but for nav feedback not always. Outputting hovered=true on Activation may be misleading. bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); // Default only reacts to left mouse button if ((flags & ImGuiButtonFlags_MouseButtonMask_) == 0) flags |= ImGuiButtonFlags_MouseButtonDefault_; // Default behavior requires click + release inside bounding box if ((flags & ImGuiButtonFlags_PressedOnMask_) == 0) flags |= ImGuiButtonFlags_PressedOnDefault_; // Default behavior inherited from item flags // Note that _both_ ButtonFlags and ItemFlags are valid sources, so copy one into the item_flags and only check that. ImGuiItemFlags item_flags = (g.LastItemData.ID == id ? g.LastItemData.InFlags : g.CurrentItemFlags); if (flags & ImGuiButtonFlags_AllowOverlap) item_flags |= ImGuiItemFlags_AllowOverlap; if (flags & ImGuiButtonFlags_Repeat) item_flags |= ImGuiItemFlags_ButtonRepeat; ImGuiWindow* backup_hovered_window = g.HoveredWindow; const bool flatten_hovered_children = (flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredWindow && g.HoveredWindow->RootWindow == window; if (flatten_hovered_children) g.HoveredWindow = window; #ifdef IMGUI_ENABLE_TEST_ENGINE // Alternate registration spot, for when caller didn't use ItemAdd() if (id != 0 && g.LastItemData.ID != id) IMGUI_TEST_ENGINE_ITEM_ADD(id, bb, NULL); #endif bool pressed = false; bool hovered = ItemHoverable(bb, id, item_flags); // Special mode for Drag and Drop where holding button pressed for a long time while dragging another item triggers the button if (g.DragDropActive && (flags & ImGuiButtonFlags_PressedOnDragDropHold) && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoHoldToOpenOthers)) if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) { hovered = true; SetHoveredID(id); if (g.HoveredIdTimer - g.IO.DeltaTime <= DRAGDROP_HOLD_TO_OPEN_TIMER && g.HoveredIdTimer >= DRAGDROP_HOLD_TO_OPEN_TIMER) { pressed = true; g.DragDropHoldJustPressedId = id; FocusWindow(window); } } if (flatten_hovered_children) g.HoveredWindow = backup_hovered_window; // Mouse handling const ImGuiID test_owner_id = (flags & ImGuiButtonFlags_NoTestKeyOwner) ? ImGuiKeyOwner_Any : id; if (hovered) { // Poll mouse buttons // - 'mouse_button_clicked' is generally carried into ActiveIdMouseButton when setting ActiveId. // - Technically we only need some values in one code path, but since this is gated by hovered test this is fine. int mouse_button_clicked = -1; int mouse_button_released = -1; for (int button = 0; button < 3; button++) if (flags & (ImGuiButtonFlags_MouseButtonLeft << button)) // Handle ImGuiButtonFlags_MouseButtonRight and ImGuiButtonFlags_MouseButtonMiddle here. { if (IsMouseClicked(button, test_owner_id) && mouse_button_clicked == -1) { mouse_button_clicked = button; } if (IsMouseReleased(button, test_owner_id) && mouse_button_released == -1) { mouse_button_released = button; } } // Process initial action if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt)) { if (mouse_button_clicked != -1 && g.ActiveId != id) { if (!(flags & ImGuiButtonFlags_NoSetKeyOwner)) SetKeyOwner(MouseButtonToKey(mouse_button_clicked), id); if (flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClickReleaseAnywhere)) { SetActiveID(id, window); g.ActiveIdMouseButton = mouse_button_clicked; if (!(flags & ImGuiButtonFlags_NoNavFocus)) SetFocusID(id, window); FocusWindow(window); } if ((flags & ImGuiButtonFlags_PressedOnClick) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseClickedCount[mouse_button_clicked] == 2)) { pressed = true; if (flags & ImGuiButtonFlags_NoHoldingActiveId) ClearActiveID(); else SetActiveID(id, window); // Hold on ID if (!(flags & ImGuiButtonFlags_NoNavFocus)) SetFocusID(id, window); g.ActiveIdMouseButton = mouse_button_clicked; FocusWindow(window); } } if (flags & ImGuiButtonFlags_PressedOnRelease) { if (mouse_button_released != -1) { const bool has_repeated_at_least_once = (item_flags & ImGuiItemFlags_ButtonRepeat) && g.IO.MouseDownDurationPrev[mouse_button_released] >= g.IO.KeyRepeatDelay; // Repeat mode trumps on release behavior if (!has_repeated_at_least_once) pressed = true; if (!(flags & ImGuiButtonFlags_NoNavFocus)) SetFocusID(id, window); ClearActiveID(); } } // 'Repeat' mode acts when held regardless of _PressedOn flags (see table above). // Relies on repeat logic of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings. if (g.ActiveId == id && (item_flags & ImGuiItemFlags_ButtonRepeat)) if (g.IO.MouseDownDuration[g.ActiveIdMouseButton] > 0.0f && IsMouseClicked(g.ActiveIdMouseButton, test_owner_id, ImGuiInputFlags_Repeat)) pressed = true; } if (pressed) g.NavDisableHighlight = true; } // Gamepad/Keyboard handling // We report navigated and navigation-activated items as hovered but we don't set g.HoveredId to not interfere with mouse. if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover) if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus)) hovered = true; if (g.NavActivateDownId == id) { bool nav_activated_by_code = (g.NavActivateId == id); bool nav_activated_by_inputs = (g.NavActivatePressedId == id); if (!nav_activated_by_inputs && (item_flags & ImGuiItemFlags_ButtonRepeat)) { // Avoid pressing multiple keys from triggering excessive amount of repeat events const ImGuiKeyData* key1 = GetKeyData(ImGuiKey_Space); const ImGuiKeyData* key2 = GetKeyData(ImGuiKey_Enter); const ImGuiKeyData* key3 = GetKeyData(ImGuiKey_NavGamepadActivate); const float t1 = ImMax(ImMax(key1->DownDuration, key2->DownDuration), key3->DownDuration); nav_activated_by_inputs = CalcTypematicRepeatAmount(t1 - g.IO.DeltaTime, t1, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0; } if (nav_activated_by_code || nav_activated_by_inputs) { // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button. pressed = true; SetActiveID(id, window); g.ActiveIdSource = g.NavInputSource; if (!(flags & ImGuiButtonFlags_NoNavFocus) && !(g.NavActivateFlags & ImGuiActivateFlags_FromShortcut)) SetFocusID(id, window); if (g.NavActivateFlags & ImGuiActivateFlags_FromShortcut) g.ActiveIdFromShortcut = true; } } // Process while held bool held = false; if (g.ActiveId == id) { if (g.ActiveIdSource == ImGuiInputSource_Mouse) { if (g.ActiveIdIsJustActivated) g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; const int mouse_button = g.ActiveIdMouseButton; if (mouse_button == -1) { // Fallback for the rare situation were g.ActiveId was set programmatically or from another widget (e.g. #6304). ClearActiveID(); } else if (IsMouseDown(mouse_button, test_owner_id)) { held = true; } else { bool release_in = hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease) != 0; bool release_anywhere = (flags & ImGuiButtonFlags_PressedOnClickReleaseAnywhere) != 0; if ((release_in || release_anywhere) && !g.DragDropActive) { // Report as pressed when releasing the mouse (this is the most common path) bool is_double_click_release = (flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseReleased[mouse_button] && g.IO.MouseClickedLastCount[mouse_button] == 2; bool is_repeating_already = (item_flags & ImGuiItemFlags_ButtonRepeat) && g.IO.MouseDownDurationPrev[mouse_button] >= g.IO.KeyRepeatDelay; // Repeat mode trumps bool is_button_avail_or_owned = TestKeyOwner(MouseButtonToKey(mouse_button), test_owner_id); if (!is_double_click_release && !is_repeating_already && is_button_avail_or_owned) pressed = true; } ClearActiveID(); } if (!(flags & ImGuiButtonFlags_NoNavFocus)) g.NavDisableHighlight = true; } else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad) { // When activated using Nav, we hold on the ActiveID until activation button is released if (g.NavActivateDownId == id) held = true; // hovered == true not true as we are already likely hovered on direct activation. else ClearActiveID(); } if (pressed) g.ActiveIdHasBeenPressedBefore = true; } // Activation highlight (this may be a remote activation) if (g.NavHighlightActivatedId == id) hovered = true; if (out_hovered) *out_hovered = hovered; if (out_held) *out_held = held; return pressed; } bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); const ImVec2 label_size = CalcTextSize(label, NULL, true); ImVec2 pos = window->DC.CursorPos; if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag) pos.y += window->DC.CurrLineTextBaseOffset - style.FramePadding.y; ImVec2 size = CalcItemSize(size_arg, label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f); const ImRect bb(pos, pos + size); ItemSize(size, style.FramePadding.y); if (!ItemAdd(bb, id)) return false; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); // Render const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); RenderNavHighlight(bb, id); RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); if (g.LogEnabled) LogSetNextTextDecoration("[", "]"); RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb); // Automatically close popups //if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup)) // CloseCurrentPopup(); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); return pressed; } bool ImGui::Button(const char* label, const ImVec2& size_arg) { return ButtonEx(label, size_arg, ImGuiButtonFlags_None); } // Small buttons fits within text without additional vertical spacing. bool ImGui::SmallButton(const char* label) { ImGuiContext& g = *GImGui; float backup_padding_y = g.Style.FramePadding.y; g.Style.FramePadding.y = 0.0f; bool pressed = ButtonEx(label, ImVec2(0, 0), ImGuiButtonFlags_AlignTextBaseLine); g.Style.FramePadding.y = backup_padding_y; return pressed; } // Tip: use ImGui::PushID()/PopID() to push indices or pointers in the ID stack. // Then you can keep 'str_id' empty or the same for all your buttons (instead of creating a string based on a non-string id) bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg, ImGuiButtonFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; // Cannot use zero-size for InvisibleButton(). Unlike Button() there is not way to fallback using the label size. IM_ASSERT(size_arg.x != 0.0f && size_arg.y != 0.0f); const ImGuiID id = window->GetID(str_id); ImVec2 size = CalcItemSize(size_arg, 0.0f, 0.0f); const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); ItemSize(size); if (!ItemAdd(bb, id)) return false; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); IMGUI_TEST_ENGINE_ITEM_INFO(id, str_id, g.LastItemData.StatusFlags); return pressed; } bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiButtonFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; const ImGuiID id = window->GetID(str_id); const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); const float default_size = GetFrameHeight(); ItemSize(size, (size.y >= default_size) ? g.Style.FramePadding.y : -1.0f); if (!ItemAdd(bb, id)) return false; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); // Render const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); const ImU32 text_col = GetColorU32(ImGuiCol_Text); RenderNavHighlight(bb, id); RenderFrame(bb.Min, bb.Max, bg_col, true, g.Style.FrameRounding); RenderArrow(window->DrawList, bb.Min + ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f), ImMax(0.0f, (size.y - g.FontSize) * 0.5f)), text_col, dir); IMGUI_TEST_ENGINE_ITEM_INFO(id, str_id, g.LastItemData.StatusFlags); return pressed; } bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir) { float sz = GetFrameHeight(); return ArrowButtonEx(str_id, dir, ImVec2(sz, sz), ImGuiButtonFlags_None); } // Button to close a window bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; // Tweak 1: Shrink hit-testing area if button covers an abnormally large proportion of the visible region. That's in order to facilitate moving the window away. (#3825) // This may better be applied as a general hit-rect reduction mechanism for all widgets to ensure the area to move window is always accessible? const ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize)); ImRect bb_interact = bb; const float area_to_visible_ratio = window->OuterRectClipped.GetArea() / bb.GetArea(); if (area_to_visible_ratio < 1.5f) bb_interact.Expand(ImTrunc(bb_interact.GetSize() * -0.25f)); // Tweak 2: We intentionally allow interaction when clipped so that a mechanical Alt,Right,Activate sequence can always close a window. // (this isn't the common behavior of buttons, but it doesn't affect the user because navigation tends to keep items visible in scrolling layer). bool is_clipped = !ItemAdd(bb_interact, id); bool hovered, held; bool pressed = ButtonBehavior(bb_interact, id, &hovered, &held); if (is_clipped) return pressed; // Render // FIXME: Clarify this mess ImU32 col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered); ImVec2 center = bb.GetCenter(); if (hovered) window->DrawList->AddCircleFilled(center, ImMax(2.0f, g.FontSize * 0.5f + 1.0f), col); float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f; ImU32 cross_col = GetColorU32(ImGuiCol_Text); center -= ImVec2(0.5f, 0.5f); window->DrawList->AddLine(center + ImVec2(+cross_extent, +cross_extent), center + ImVec2(-cross_extent, -cross_extent), cross_col, 1.0f); window->DrawList->AddLine(center + ImVec2(+cross_extent, -cross_extent), center + ImVec2(-cross_extent, +cross_extent), cross_col, 1.0f); return pressed; } bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize)); bool is_clipped = !ItemAdd(bb, id); bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_None); if (is_clipped) return pressed; // Render ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); ImU32 text_col = GetColorU32(ImGuiCol_Text); if (hovered || held) window->DrawList->AddCircleFilled(bb.GetCenter() + ImVec2(0.0f, -0.5f), g.FontSize * 0.5f + 1.0f, bg_col); RenderArrow(window->DrawList, bb.Min, text_col, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f); // Switch to moving the window after mouse is moved beyond the initial drag threshold if (IsItemActive() && IsMouseDragging(0)) StartMouseMovingWindow(window); return pressed; } ImGuiID ImGui::GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis) { return window->GetID(axis == ImGuiAxis_X ? "#SCROLLX" : "#SCROLLY"); } // Return scrollbar rectangle, must only be called for corresponding axis if window->ScrollbarX/Y is set. ImRect ImGui::GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis) { const ImRect outer_rect = window->Rect(); const ImRect inner_rect = window->InnerRect; const float border_size = window->WindowBorderSize; const float scrollbar_size = window->ScrollbarSizes[axis ^ 1]; // (ScrollbarSizes.x = width of Y scrollbar; ScrollbarSizes.y = height of X scrollbar) IM_ASSERT(scrollbar_size > 0.0f); if (axis == ImGuiAxis_X) return ImRect(inner_rect.Min.x, ImMax(outer_rect.Min.y, outer_rect.Max.y - border_size - scrollbar_size), inner_rect.Max.x - border_size, outer_rect.Max.y - border_size); else return ImRect(ImMax(outer_rect.Min.x, outer_rect.Max.x - border_size - scrollbar_size), inner_rect.Min.y, outer_rect.Max.x - border_size, inner_rect.Max.y - border_size); } void ImGui::Scrollbar(ImGuiAxis axis) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; const ImGuiID id = GetWindowScrollbarID(window, axis); // Calculate scrollbar bounding box ImRect bb = GetWindowScrollbarRect(window, axis); ImDrawFlags rounding_corners = ImDrawFlags_RoundCornersNone; if (axis == ImGuiAxis_X) { rounding_corners |= ImDrawFlags_RoundCornersBottomLeft; if (!window->ScrollbarY) rounding_corners |= ImDrawFlags_RoundCornersBottomRight; } else { if ((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) rounding_corners |= ImDrawFlags_RoundCornersTopRight; if (!window->ScrollbarX) rounding_corners |= ImDrawFlags_RoundCornersBottomRight; } float size_avail = window->InnerRect.Max[axis] - window->InnerRect.Min[axis]; float size_contents = window->ContentSize[axis] + window->WindowPadding[axis] * 2.0f; ImS64 scroll = (ImS64)window->Scroll[axis]; ScrollbarEx(bb, id, axis, &scroll, (ImS64)size_avail, (ImS64)size_contents, rounding_corners); window->Scroll[axis] = (float)scroll; } // Vertical/Horizontal scrollbar // The entire piece of code below is rather confusing because: // - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab) // - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar // - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal. // Still, the code should probably be made simpler.. bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS64* p_scroll_v, ImS64 size_avail_v, ImS64 size_contents_v, ImDrawFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (window->SkipItems) return false; const float bb_frame_width = bb_frame.GetWidth(); const float bb_frame_height = bb_frame.GetHeight(); if (bb_frame_width <= 0.0f || bb_frame_height <= 0.0f) return false; // When we are too small, start hiding and disabling the grab (this reduce visual noise on very small window and facilitate using the window resize grab) float alpha = 1.0f; if ((axis == ImGuiAxis_Y) && bb_frame_height < g.FontSize + g.Style.FramePadding.y * 2.0f) alpha = ImSaturate((bb_frame_height - g.FontSize) / (g.Style.FramePadding.y * 2.0f)); if (alpha <= 0.0f) return false; const ImGuiStyle& style = g.Style; const bool allow_interaction = (alpha >= 1.0f); ImRect bb = bb_frame; bb.Expand(ImVec2(-ImClamp(IM_TRUNC((bb_frame_width - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp(IM_TRUNC((bb_frame_height - 2.0f) * 0.5f), 0.0f, 3.0f))); // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar) const float scrollbar_size_v = (axis == ImGuiAxis_X) ? bb.GetWidth() : bb.GetHeight(); // Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount) // But we maintain a minimum size in pixel to allow for the user to still aim inside. IM_ASSERT(ImMax(size_contents_v, size_avail_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers. const ImS64 win_size_v = ImMax(ImMax(size_contents_v, size_avail_v), (ImS64)1); const float grab_h_pixels = ImClamp(scrollbar_size_v * ((float)size_avail_v / (float)win_size_v), style.GrabMinSize, scrollbar_size_v); const float grab_h_norm = grab_h_pixels / scrollbar_size_v; // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar(). bool held = false; bool hovered = false; ItemAdd(bb_frame, id, NULL, ImGuiItemFlags_NoNav); ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus); const ImS64 scroll_max = ImMax((ImS64)1, size_contents_v - size_avail_v); float scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max); float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; // Grab position in normalized space if (held && allow_interaction && grab_h_norm < 1.0f) { const float scrollbar_pos_v = bb.Min[axis]; const float mouse_pos_v = g.IO.MousePos[axis]; // Click position in scrollbar normalized space (0.0f->1.0f) const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v); bool seek_absolute = false; if (g.ActiveIdIsJustActivated) { // On initial click calculate the distance between mouse and the center of the grab seek_absolute = (clicked_v_norm < grab_v_norm || clicked_v_norm > grab_v_norm + grab_h_norm); if (seek_absolute) g.ScrollbarClickDeltaToGrabCenter = 0.0f; else g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f; } // Apply scroll (p_scroll_v will generally point on one member of window->Scroll) // It is ok to modify Scroll here because we are being called in Begin() after the calculation of ContentSize and before setting up our starting position const float scroll_v_norm = ImSaturate((clicked_v_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm * 0.5f) / (1.0f - grab_h_norm)); *p_scroll_v = (ImS64)(scroll_v_norm * scroll_max); // Update values for rendering scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max); grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; // Update distance to grab now that we have seeked and saturated if (seek_absolute) g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f; } // Render const ImU32 bg_col = GetColorU32(ImGuiCol_ScrollbarBg); const ImU32 grab_col = GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab, alpha); window->DrawList->AddRectFilled(bb_frame.Min, bb_frame.Max, bg_col, window->WindowRounding, flags); ImRect grab_rect; if (axis == ImGuiAxis_X) grab_rect = ImRect(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y, ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, bb.Max.y); else grab_rect = ImRect(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm), bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels); window->DrawList->AddRectFilled(grab_rect.Min, grab_rect.Max, grab_col, style.ScrollbarRounding); return held; } // - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples // - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above. void ImGui::Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; const float border_size = (border_col.w > 0.0f) ? 1.0f : 0.0f; const ImVec2 padding(border_size, border_size); const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + image_size + padding * 2.0f); ItemSize(bb); if (!ItemAdd(bb, 0)) return; // Render if (border_size > 0.0f) window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(border_col), 0.0f, ImDrawFlags_None, border_size); window->DrawList->AddImage(user_texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col)); } // ImageButton() is flawed as 'id' is always derived from 'texture_id' (see #2464 #1390) // We provide this internal helper to write your own variant while we figure out how to redesign the public ImageButton() API. bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; const ImVec2 padding = g.Style.FramePadding; const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + image_size + padding * 2.0f); ItemSize(bb); if (!ItemAdd(bb, id)) return false; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); // Render const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); RenderNavHighlight(bb, id); RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, g.Style.FrameRounding)); if (bg_col.w > 0.0f) window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, GetColorU32(bg_col)); window->DrawList->AddImage(texture_id, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col)); return pressed; } // Note that ImageButton() adds style.FramePadding*2.0f to provided size. This is in order to facilitate fitting an image in a button. bool ImGui::ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (window->SkipItems) return false; return ImageButtonEx(window->GetID(str_id), user_texture_id, image_size, uv0, uv1, bg_col, tint_col); } #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // Legacy API obsoleted in 1.89. Two differences with new ImageButton() // - new ImageButton() requires an explicit 'const char* str_id' Old ImageButton() used opaque imTextureId (created issue with: multiple buttons with same image, transient texture id values, opaque computation of ID) // - new ImageButton() always use style.FramePadding Old ImageButton() had an override argument. // If you need to change padding with new ImageButton() you can use PushStyleVar(ImGuiStyleVar_FramePadding, value), consistent with other Button functions. bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, int frame_padding, const ImVec4& bg_col, const ImVec4& tint_col) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (window->SkipItems) return false; // Default to using texture ID as ID. User can still push string/integer prefixes. PushID((void*)(intptr_t)user_texture_id); const ImGuiID id = window->GetID("#image"); PopID(); if (frame_padding >= 0) PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2((float)frame_padding, (float)frame_padding)); bool ret = ImageButtonEx(id, user_texture_id, size, uv0, uv1, bg_col, tint_col); if (frame_padding >= 0) PopStyleVar(); return ret; } #endif // #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS bool ImGui::Checkbox(const char* label, bool* v) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); const ImVec2 label_size = CalcTextSize(label, NULL, true); const float square_sz = GetFrameHeight(); const ImVec2 pos = window->DC.CursorPos; const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f)); ItemSize(total_bb, style.FramePadding.y); if (!ItemAdd(total_bb, id)) { IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); return false; } bool hovered, held; bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); if (pressed) { *v = !(*v); MarkItemEdited(id); } const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz)); RenderNavHighlight(total_bb, id); RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); ImU32 check_col = GetColorU32(ImGuiCol_CheckMark); bool mixed_value = (g.LastItemData.InFlags & ImGuiItemFlags_MixedValue) != 0; if (mixed_value) { // Undocumented tristate/mixed/indeterminate checkbox (#2644) // This may seem awkwardly designed because the aim is to make ImGuiItemFlags_MixedValue supported by all widgets (not just checkbox) ImVec2 pad(ImMax(1.0f, IM_TRUNC(square_sz / 3.6f)), ImMax(1.0f, IM_TRUNC(square_sz / 3.6f))); window->DrawList->AddRectFilled(check_bb.Min + pad, check_bb.Max - pad, check_col, style.FrameRounding); } else if (*v) { const float pad = ImMax(1.0f, IM_TRUNC(square_sz / 6.0f)); RenderCheckMark(window->DrawList, check_bb.Min + ImVec2(pad, pad), check_col, square_sz - pad * 2.0f); } ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y); if (g.LogEnabled) LogRenderedText(&label_pos, mixed_value ? "[~]" : *v ? "[x]" : "[ ]"); if (label_size.x > 0.0f) RenderText(label_pos, label); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); return pressed; } template bool ImGui::CheckboxFlagsT(const char* label, T* flags, T flags_value) { bool all_on = (*flags & flags_value) == flags_value; bool any_on = (*flags & flags_value) != 0; bool pressed; if (!all_on && any_on) { ImGuiContext& g = *GImGui; g.NextItemData.ItemFlags |= ImGuiItemFlags_MixedValue; pressed = Checkbox(label, &all_on); } else { pressed = Checkbox(label, &all_on); } if (pressed) { if (all_on) *flags |= flags_value; else *flags &= ~flags_value; } return pressed; } bool ImGui::CheckboxFlags(const char* label, int* flags, int flags_value) { return CheckboxFlagsT(label, flags, flags_value); } bool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value) { return CheckboxFlagsT(label, flags, flags_value); } bool ImGui::CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value) { return CheckboxFlagsT(label, flags, flags_value); } bool ImGui::CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value) { return CheckboxFlagsT(label, flags, flags_value); } bool ImGui::RadioButton(const char* label, bool active) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); const ImVec2 label_size = CalcTextSize(label, NULL, true); const float square_sz = GetFrameHeight(); const ImVec2 pos = window->DC.CursorPos; const ImRect check_bb(pos, pos + ImVec2(square_sz, square_sz)); const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f)); ItemSize(total_bb, style.FramePadding.y); if (!ItemAdd(total_bb, id)) return false; ImVec2 center = check_bb.GetCenter(); center.x = IM_ROUND(center.x); center.y = IM_ROUND(center.y); const float radius = (square_sz - 1.0f) * 0.5f; bool hovered, held; bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); if (pressed) MarkItemEdited(id); RenderNavHighlight(total_bb, id); const int num_segment = window->DrawList->_CalcCircleAutoSegmentCount(radius); window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), num_segment); if (active) { const float pad = ImMax(1.0f, IM_TRUNC(square_sz / 6.0f)); window->DrawList->AddCircleFilled(center, radius - pad, GetColorU32(ImGuiCol_CheckMark)); } if (style.FrameBorderSize > 0.0f) { window->DrawList->AddCircle(center + ImVec2(1, 1), radius, GetColorU32(ImGuiCol_BorderShadow), num_segment, style.FrameBorderSize); window->DrawList->AddCircle(center, radius, GetColorU32(ImGuiCol_Border), num_segment, style.FrameBorderSize); } ImVec2 label_pos = ImVec2(check_bb.Max.x + style.ItemInnerSpacing.x, check_bb.Min.y + style.FramePadding.y); if (g.LogEnabled) LogRenderedText(&label_pos, active ? "(x)" : "( )"); if (label_size.x > 0.0f) RenderText(label_pos, label); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); return pressed; } // FIXME: This would work nicely if it was a public template, e.g. 'template RadioButton(const char* label, T* v, T v_button)', but I'm not sure how we would expose it.. bool ImGui::RadioButton(const char* label, int* v, int v_button) { const bool pressed = RadioButton(label, *v == v_button); if (pressed) *v = v_button; return pressed; } // size_arg (for each axis) < 0.0f: align to end, 0.0f: auto, > 0.0f: specified size void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* overlay) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; ImVec2 pos = window->DC.CursorPos; ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y * 2.0f); ImRect bb(pos, pos + size); ItemSize(size, style.FramePadding.y); if (!ItemAdd(bb, 0)) return; // Render fraction = ImSaturate(fraction); RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); bb.Expand(ImVec2(-style.FrameBorderSize, -style.FrameBorderSize)); const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y); RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), 0.0f, fraction, style.FrameRounding); // Default displaying the fraction as percentage string, but user can override it char overlay_buf[32]; if (!overlay) { ImFormatString(overlay_buf, IM_ARRAYSIZE(overlay_buf), "%.0f%%", fraction * 100 + 0.01f); overlay = overlay_buf; } ImVec2 overlay_size = CalcTextSize(overlay, NULL); if (overlay_size.x > 0.0f) RenderTextClipped(ImVec2(ImClamp(fill_br.x + style.ItemSpacing.x, bb.Min.x, bb.Max.x - overlay_size.x - style.ItemInnerSpacing.x), bb.Min.y), bb.Max, overlay, NULL, &overlay_size, ImVec2(0.0f, 0.5f), &bb); } void ImGui::Bullet() { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const float line_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y * 2), g.FontSize); const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize, line_height)); ItemSize(bb); if (!ItemAdd(bb, 0)) { SameLine(0, style.FramePadding.x * 2); return; } // Render and stay on same line ImU32 text_col = GetColorU32(ImGuiCol_Text); RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize * 0.5f, line_height * 0.5f), text_col); SameLine(0, style.FramePadding.x * 2.0f); } //------------------------------------------------------------------------- // [SECTION] Widgets: Low-level Layout helpers //------------------------------------------------------------------------- // - Spacing() // - Dummy() // - NewLine() // - AlignTextToFramePadding() // - SeparatorEx() [Internal] // - Separator() // - SplitterBehavior() [Internal] // - ShrinkWidths() [Internal] //------------------------------------------------------------------------- void ImGui::Spacing() { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; ItemSize(ImVec2(0, 0)); } void ImGui::Dummy(const ImVec2& size) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); ItemSize(size); ItemAdd(bb, 0); } void ImGui::NewLine() { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; ImGuiContext& g = *GImGui; const ImGuiLayoutType backup_layout_type = window->DC.LayoutType; window->DC.LayoutType = ImGuiLayoutType_Vertical; window->DC.IsSameLine = false; if (window->DC.CurrLineSize.y > 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height. ItemSize(ImVec2(0, 0)); else ItemSize(ImVec2(0.0f, g.FontSize)); window->DC.LayoutType = backup_layout_type; } void ImGui::AlignTextToFramePadding() { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; ImGuiContext& g = *GImGui; window->DC.CurrLineSize.y = ImMax(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y * 2); window->DC.CurrLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, g.Style.FramePadding.y); } // Horizontal/vertical separating line // FIXME: Surprisingly, this seemingly trivial widget is a victim of many different legacy/tricky layout issues. // Note how thickness == 1.0f is handled specifically as not moving CursorPos by 'thickness', but other values are. void ImGui::SeparatorEx(ImGuiSeparatorFlags flags, float thickness) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; ImGuiContext& g = *GImGui; IM_ASSERT(ImIsPowerOfTwo(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical))); // Check that only 1 option is selected IM_ASSERT(thickness > 0.0f); if (flags & ImGuiSeparatorFlags_Vertical) { // Vertical separator, for menu bars (use current line height). float y1 = window->DC.CursorPos.y; float y2 = window->DC.CursorPos.y + window->DC.CurrLineSize.y; const ImRect bb(ImVec2(window->DC.CursorPos.x, y1), ImVec2(window->DC.CursorPos.x + thickness, y2)); ItemSize(ImVec2(thickness, 0.0f)); if (!ItemAdd(bb, 0)) return; // Draw window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Separator)); if (g.LogEnabled) LogText(" |"); } else if (flags & ImGuiSeparatorFlags_Horizontal) { // Horizontal Separator float x1 = window->DC.CursorPos.x; float x2 = window->WorkRect.Max.x; // Preserve legacy behavior inside Columns() // Before Tables API happened, we relied on Separator() to span all columns of a Columns() set. // We currently don't need to provide the same feature for tables because tables naturally have border features. ImGuiOldColumns* columns = (flags & ImGuiSeparatorFlags_SpanAllColumns) ? window->DC.CurrentColumns : NULL; if (columns) { x1 = window->Pos.x + window->DC.Indent.x; // Used to be Pos.x before 2023/10/03 x2 = window->Pos.x + window->Size.x; PushColumnsBackground(); } // We don't provide our width to the layout so that it doesn't get feed back into AutoFit // FIXME: This prevents ->CursorMaxPos based bounding box evaluation from working (e.g. TableEndCell) const float thickness_for_layout = (thickness == 1.0f) ? 0.0f : thickness; // FIXME: See 1.70/1.71 Separator() change: makes legacy 1-px separator not affect layout yet. Should change. const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness)); ItemSize(ImVec2(0.0f, thickness_for_layout)); if (ItemAdd(bb, 0)) { // Draw window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_Separator)); if (g.LogEnabled) LogRenderedText(&bb.Min, "--------------------------------\n"); } if (columns) { PopColumnsBackground(); columns->LineMinY = window->DC.CursorPos.y; } } } void ImGui::Separator() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (window->SkipItems) return; // Those flags should eventually be configurable by the user // FIXME: We cannot g.Style.SeparatorTextBorderSize for thickness as it relates to SeparatorText() which is a decorated separator, not defaulting to 1.0f. ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal; // Only applies to legacy Columns() api as they relied on Separator() a lot. if (window->DC.CurrentColumns) flags |= ImGuiSeparatorFlags_SpanAllColumns; SeparatorEx(flags, 1.0f); } void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_w) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiStyle& style = g.Style; const ImVec2 label_size = CalcTextSize(label, label_end, false); const ImVec2 pos = window->DC.CursorPos; const ImVec2 padding = style.SeparatorTextPadding; const float separator_thickness = style.SeparatorTextBorderSize; const ImVec2 min_size(label_size.x + extra_w + padding.x * 2.0f, ImMax(label_size.y + padding.y * 2.0f, separator_thickness)); const ImRect bb(pos, ImVec2(window->WorkRect.Max.x, pos.y + min_size.y)); const float text_baseline_y = ImTrunc((bb.GetHeight() - label_size.y) * style.SeparatorTextAlign.y + 0.99999f); //ImMax(padding.y, ImFloor((style.SeparatorTextSize - label_size.y) * 0.5f)); ItemSize(min_size, text_baseline_y); if (!ItemAdd(bb, id)) return; const float sep1_x1 = pos.x; const float sep2_x2 = bb.Max.x; const float seps_y = ImTrunc((bb.Min.y + bb.Max.y) * 0.5f + 0.99999f); const float label_avail_w = ImMax(0.0f, sep2_x2 - sep1_x1 - padding.x * 2.0f); const ImVec2 label_pos(pos.x + padding.x + ImMax(0.0f, (label_avail_w - label_size.x - extra_w) * style.SeparatorTextAlign.x), pos.y + text_baseline_y); // FIXME-ALIGN // This allows using SameLine() to position something in the 'extra_w' window->DC.CursorPosPrevLine.x = label_pos.x + label_size.x; const ImU32 separator_col = GetColorU32(ImGuiCol_Separator); if (label_size.x > 0.0f) { const float sep1_x2 = label_pos.x - style.ItemSpacing.x; const float sep2_x1 = label_pos.x + label_size.x + extra_w + style.ItemSpacing.x; if (sep1_x2 > sep1_x1 && separator_thickness > 0.0f) window->DrawList->AddLine(ImVec2(sep1_x1, seps_y), ImVec2(sep1_x2, seps_y), separator_col, separator_thickness); if (sep2_x2 > sep2_x1 && separator_thickness > 0.0f) window->DrawList->AddLine(ImVec2(sep2_x1, seps_y), ImVec2(sep2_x2, seps_y), separator_col, separator_thickness); if (g.LogEnabled) LogSetNextTextDecoration("---", NULL); RenderTextEllipsis(window->DrawList, label_pos, ImVec2(bb.Max.x, bb.Max.y + style.ItemSpacing.y), bb.Max.x, bb.Max.x, label, label_end, &label_size); } else { if (g.LogEnabled) LogText("---"); if (separator_thickness > 0.0f) window->DrawList->AddLine(ImVec2(sep1_x1, seps_y), ImVec2(sep2_x2, seps_y), separator_col, separator_thickness); } } void ImGui::SeparatorText(const char* label) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; // The SeparatorText() vs SeparatorTextEx() distinction is designed to be considerate that we may want: // - allow separator-text to be draggable items (would require a stable ID + a noticeable highlight) // - this high-level entry point to allow formatting? (which in turns may require ID separate from formatted string) // - because of this we probably can't turn 'const char* label' into 'const char* fmt, ...' // Otherwise, we can decide that users wanting to drag this would layout a dedicated drag-item, // and then we can turn this into a format function. SeparatorTextEx(0, label, FindRenderedTextEnd(label), 0.0f); } // Using 'hover_visibility_delay' allows us to hide the highlight and mouse cursor for a short time, which can be convenient to reduce visual noise. bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend, float hover_visibility_delay, ImU32 bg_col) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (!ItemAdd(bb, id, NULL, ImGuiItemFlags_NoNav)) return false; // FIXME: AFAIK the only leftover reason for passing ImGuiButtonFlags_AllowOverlap here is // to allow caller of SplitterBehavior() to call SetItemAllowOverlap() after the item. // Nowadays we would instead want to use SetNextItemAllowOverlap() before the item. ImGuiButtonFlags button_flags = ImGuiButtonFlags_FlattenChildren; #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS button_flags |= ImGuiButtonFlags_AllowOverlap; #endif bool hovered, held; ImRect bb_interact = bb; bb_interact.Expand(axis == ImGuiAxis_Y ? ImVec2(0.0f, hover_extend) : ImVec2(hover_extend, 0.0f)); ButtonBehavior(bb_interact, id, &hovered, &held, button_flags); if (hovered) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredRect; // for IsItemHovered(), because bb_interact is larger than bb if (held || (hovered && g.HoveredIdPreviousFrame == id && g.HoveredIdTimer >= hover_visibility_delay)) SetMouseCursor(axis == ImGuiAxis_Y ? ImGuiMouseCursor_ResizeNS : ImGuiMouseCursor_ResizeEW); ImRect bb_render = bb; if (held) { float mouse_delta = (g.IO.MousePos - g.ActiveIdClickOffset - bb_interact.Min)[axis]; // Minimum pane size float size_1_maximum_delta = ImMax(0.0f, *size1 - min_size1); float size_2_maximum_delta = ImMax(0.0f, *size2 - min_size2); if (mouse_delta < -size_1_maximum_delta) mouse_delta = -size_1_maximum_delta; if (mouse_delta > size_2_maximum_delta) mouse_delta = size_2_maximum_delta; // Apply resize if (mouse_delta != 0.0f) { *size1 = ImMax(*size1 + mouse_delta, min_size1); *size2 = ImMax(*size2 - mouse_delta, min_size2); bb_render.Translate((axis == ImGuiAxis_X) ? ImVec2(mouse_delta, 0.0f) : ImVec2(0.0f, mouse_delta)); MarkItemEdited(id); } } // Render at new position if (bg_col & IM_COL32_A_MASK) window->DrawList->AddRectFilled(bb_render.Min, bb_render.Max, bg_col, 0.0f); const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : (hovered && g.HoveredIdTimer >= hover_visibility_delay) ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); window->DrawList->AddRectFilled(bb_render.Min, bb_render.Max, col, 0.0f); return held; } static int IMGUI_CDECL ShrinkWidthItemComparer(const void* lhs, const void* rhs) { const ImGuiShrinkWidthItem* a = (const ImGuiShrinkWidthItem*)lhs; const ImGuiShrinkWidthItem* b = (const ImGuiShrinkWidthItem*)rhs; if (int d = (int)(b->Width - a->Width)) return d; return (b->Index - a->Index); } // Shrink excess width from a set of item, by removing width from the larger items first. // Set items Width to -1.0f to disable shrinking this item. void ImGui::ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess) { if (count == 1) { if (items[0].Width >= 0.0f) items[0].Width = ImMax(items[0].Width - width_excess, 1.0f); return; } ImQsort(items, (size_t)count, sizeof(ImGuiShrinkWidthItem), ShrinkWidthItemComparer); int count_same_width = 1; while (width_excess > 0.0f && count_same_width < count) { while (count_same_width < count && items[0].Width <= items[count_same_width].Width) count_same_width++; float max_width_to_remove_per_item = (count_same_width < count && items[count_same_width].Width >= 0.0f) ? (items[0].Width - items[count_same_width].Width) : (items[0].Width - 1.0f); if (max_width_to_remove_per_item <= 0.0f) break; float width_to_remove_per_item = ImMin(width_excess / count_same_width, max_width_to_remove_per_item); for (int item_n = 0; item_n < count_same_width; item_n++) items[item_n].Width -= width_to_remove_per_item; width_excess -= width_to_remove_per_item * count_same_width; } // Round width and redistribute remainder // Ensure that e.g. the right-most tab of a shrunk tab-bar always reaches exactly at the same distance from the right-most edge of the tab bar separator. width_excess = 0.0f; for (int n = 0; n < count; n++) { float width_rounded = ImTrunc(items[n].Width); width_excess += items[n].Width - width_rounded; items[n].Width = width_rounded; } while (width_excess > 0.0f) for (int n = 0; n < count && width_excess > 0.0f; n++) { float width_to_add = ImMin(items[n].InitialWidth - items[n].Width, 1.0f); items[n].Width += width_to_add; width_excess -= width_to_add; } } //------------------------------------------------------------------------- // [SECTION] Widgets: ComboBox //------------------------------------------------------------------------- // - CalcMaxPopupHeightFromItemCount() [Internal] // - BeginCombo() // - BeginComboPopup() [Internal] // - EndCombo() // - BeginComboPreview() [Internal] // - EndComboPreview() [Internal] // - Combo() //------------------------------------------------------------------------- static float CalcMaxPopupHeightFromItemCount(int items_count) { ImGuiContext& g = *GImGui; if (items_count <= 0) return FLT_MAX; return (g.FontSize + g.Style.ItemSpacing.y) * items_count - g.Style.ItemSpacing.y + (g.Style.WindowPadding.y * 2); } bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); ImGuiNextWindowDataFlags backup_next_window_data_flags = g.NextWindowData.Flags; g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values if (window->SkipItems) return false; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together if (flags & ImGuiComboFlags_WidthFitPreview) IM_ASSERT((flags & (ImGuiComboFlags_NoPreview | (ImGuiComboFlags)ImGuiComboFlags_CustomPreview)) == 0); const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight(); const ImVec2 label_size = CalcTextSize(label, NULL, true); const float preview_width = ((flags & ImGuiComboFlags_WidthFitPreview) && (preview_value != NULL)) ? CalcTextSize(preview_value, NULL, true).x : 0.0f; const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : ((flags & ImGuiComboFlags_WidthFitPreview) ? (arrow_size + preview_width + style.FramePadding.x * 2.0f) : CalcItemWidth()); const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); const ImRect total_bb(bb.Min, bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); ItemSize(total_bb, style.FramePadding.y); if (!ItemAdd(total_bb, id, &bb)) return false; // Open on click bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held); const ImGuiID popup_id = ImHashStr("##ComboPopup", 0, id); bool popup_open = IsPopupOpen(popup_id, ImGuiPopupFlags_None); if (pressed && !popup_open) { OpenPopupEx(popup_id, ImGuiPopupFlags_None); popup_open = true; } // Render shape const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); const float value_x2 = ImMax(bb.Min.x, bb.Max.x - arrow_size); RenderNavHighlight(bb, id); if (!(flags & ImGuiComboFlags_NoPreview)) window->DrawList->AddRectFilled(bb.Min, ImVec2(value_x2, bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersLeft); if (!(flags & ImGuiComboFlags_NoArrowButton)) { ImU32 bg_col = GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button); ImU32 text_col = GetColorU32(ImGuiCol_Text); window->DrawList->AddRectFilled(ImVec2(value_x2, bb.Min.y), bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersRight); if (value_x2 + arrow_size - style.FramePadding.x <= bb.Max.x) RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f); } RenderFrameBorder(bb.Min, bb.Max, style.FrameRounding); // Custom preview if (flags & ImGuiComboFlags_CustomPreview) { g.ComboPreviewData.PreviewRect = ImRect(bb.Min.x, bb.Min.y, value_x2, bb.Max.y); IM_ASSERT(preview_value == NULL || preview_value[0] == 0); preview_value = NULL; } // Render preview and label if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview)) { if (g.LogEnabled) LogSetNextTextDecoration("{", "}"); RenderTextClipped(bb.Min + style.FramePadding, ImVec2(value_x2, bb.Max.y), preview_value, NULL, NULL); } if (label_size.x > 0) RenderText(ImVec2(bb.Max.x + style.ItemInnerSpacing.x, bb.Min.y + style.FramePadding.y), label); if (!popup_open) return false; g.NextWindowData.Flags = backup_next_window_data_flags; return BeginComboPopup(popup_id, bb, flags); } bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags flags) { ImGuiContext& g = *GImGui; if (!IsPopupOpen(popup_id, ImGuiPopupFlags_None)) { g.NextWindowData.ClearFlags(); return false; } // Set popup size float w = bb.GetWidth(); if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint) { g.NextWindowData.SizeConstraintRect.Min.x = ImMax(g.NextWindowData.SizeConstraintRect.Min.x, w); } else { if ((flags & ImGuiComboFlags_HeightMask_) == 0) flags |= ImGuiComboFlags_HeightRegular; IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiComboFlags_HeightMask_)); // Only one int popup_max_height_in_items = -1; if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8; else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4; else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20; ImVec2 constraint_min(0.0f, 0.0f), constraint_max(FLT_MAX, FLT_MAX); if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0 || g.NextWindowData.SizeVal.x <= 0.0f) // Don't apply constraints if user specified a size constraint_min.x = w; if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0 || g.NextWindowData.SizeVal.y <= 0.0f) constraint_max.y = CalcMaxPopupHeightFromItemCount(popup_max_height_in_items); SetNextWindowSizeConstraints(constraint_min, constraint_max); } // This is essentially a specialized version of BeginPopupEx() char name[16]; ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginComboDepth); // Recycle windows based on depth // Set position given a custom constraint (peak into expected window size so we can position it) // FIXME: This might be easier to express with an hypothetical SetNextWindowPosConstraints() function? // FIXME: This might be moved to Begin() or at least around the same spot where Tooltips and other Popups are calling FindBestWindowPosForPopupEx()? if (ImGuiWindow* popup_window = FindWindowByName(name)) if (popup_window->WasActive) { // Always override 'AutoPosLastDirection' to not leave a chance for a past value to affect us. ImVec2 size_expected = CalcWindowNextAutoFitSize(popup_window); popup_window->AutoPosLastDirection = (flags & ImGuiComboFlags_PopupAlignLeft) ? ImGuiDir_Left : ImGuiDir_Down; // Left = "Below, Toward Left", Down = "Below, Toward Right (default)" ImRect r_outer = GetPopupAllowedExtentRect(popup_window); ImVec2 pos = FindBestWindowPosForPopupEx(bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, r_outer, bb, ImGuiPopupPositionPolicy_ComboBox); SetNextWindowPos(pos); } // We don't use BeginPopupEx() solely because we have a custom name string, which we could make an argument to BeginPopupEx() ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoMove; PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(g.Style.FramePadding.x, g.Style.WindowPadding.y)); // Horizontally align ourselves with the framed text bool ret = Begin(name, NULL, window_flags); PopStyleVar(); if (!ret) { EndPopup(); IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above return false; } g.BeginComboDepth++; return true; } void ImGui::EndCombo() { ImGuiContext& g = *GImGui; EndPopup(); g.BeginComboDepth--; } // Call directly after the BeginCombo/EndCombo block. The preview is designed to only host non-interactive elements // (Experimental, see GitHub issues: #1658, #4168) bool ImGui::BeginComboPreview() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiComboPreviewData* preview_data = &g.ComboPreviewData; if (window->SkipItems || !(g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible)) return false; IM_ASSERT(g.LastItemData.Rect.Min.x == preview_data->PreviewRect.Min.x && g.LastItemData.Rect.Min.y == preview_data->PreviewRect.Min.y); // Didn't call after BeginCombo/EndCombo block or forgot to pass ImGuiComboFlags_CustomPreview flag? if (!window->ClipRect.Overlaps(preview_data->PreviewRect)) // Narrower test (optional) return false; // FIXME: This could be contained in a PushWorkRect() api preview_data->BackupCursorPos = window->DC.CursorPos; preview_data->BackupCursorMaxPos = window->DC.CursorMaxPos; preview_data->BackupCursorPosPrevLine = window->DC.CursorPosPrevLine; preview_data->BackupPrevLineTextBaseOffset = window->DC.PrevLineTextBaseOffset; preview_data->BackupLayout = window->DC.LayoutType; window->DC.CursorPos = preview_data->PreviewRect.Min + g.Style.FramePadding; window->DC.CursorMaxPos = window->DC.CursorPos; window->DC.LayoutType = ImGuiLayoutType_Horizontal; window->DC.IsSameLine = false; PushClipRect(preview_data->PreviewRect.Min, preview_data->PreviewRect.Max, true); return true; } void ImGui::EndComboPreview() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiComboPreviewData* preview_data = &g.ComboPreviewData; // FIXME: Using CursorMaxPos approximation instead of correct AABB which we will store in ImDrawCmd in the future ImDrawList* draw_list = window->DrawList; if (window->DC.CursorMaxPos.x < preview_data->PreviewRect.Max.x && window->DC.CursorMaxPos.y < preview_data->PreviewRect.Max.y) if (draw_list->CmdBuffer.Size > 1) // Unlikely case that the PushClipRect() didn't create a command { draw_list->_CmdHeader.ClipRect = draw_list->CmdBuffer[draw_list->CmdBuffer.Size - 1].ClipRect = draw_list->CmdBuffer[draw_list->CmdBuffer.Size - 2].ClipRect; draw_list->_TryMergeDrawCmds(); } PopClipRect(); window->DC.CursorPos = preview_data->BackupCursorPos; window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, preview_data->BackupCursorMaxPos); window->DC.CursorPosPrevLine = preview_data->BackupCursorPosPrevLine; window->DC.PrevLineTextBaseOffset = preview_data->BackupPrevLineTextBaseOffset; window->DC.LayoutType = preview_data->BackupLayout; window->DC.IsSameLine = false; preview_data->PreviewRect = ImRect(); } // Getter for the old Combo() API: const char*[] static const char* Items_ArrayGetter(void* data, int idx) { const char* const* items = (const char* const*)data; return items[idx]; } // Getter for the old Combo() API: "item1\0item2\0item3\0" static const char* Items_SingleStringGetter(void* data, int idx) { const char* items_separated_by_zeros = (const char*)data; int items_count = 0; const char* p = items_separated_by_zeros; while (*p) { if (idx == items_count) break; p += strlen(p) + 1; items_count++; } return *p ? p : NULL; } // Old API, prefer using BeginCombo() nowadays if you can. bool ImGui::Combo(const char* label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int popup_max_height_in_items) { ImGuiContext& g = *GImGui; // Call the getter to obtain the preview string which is a parameter to BeginCombo() const char* preview_value = NULL; if (*current_item >= 0 && *current_item < items_count) preview_value = getter(user_data, *current_item); // The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here. if (popup_max_height_in_items != -1 && !(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint)) SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items))); if (!BeginCombo(label, preview_value, ImGuiComboFlags_None)) return false; // Display items // FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed) bool value_changed = false; for (int i = 0; i < items_count; i++) { const char* item_text = getter(user_data, i); if (item_text == NULL) item_text = "*Unknown item*"; PushID(i); const bool item_selected = (i == *current_item); if (Selectable(item_text, item_selected) && *current_item != i) { value_changed = true; *current_item = i; } if (item_selected) SetItemDefaultFocus(); PopID(); } EndCombo(); if (value_changed) MarkItemEdited(g.LastItemData.ID); return value_changed; } // Combo box helper allowing to pass an array of strings. bool ImGui::Combo(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items) { const bool value_changed = Combo(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_in_items); return value_changed; } // Combo box helper allowing to pass all items in a single string literal holding multiple zero-terminated items "item1\0item2\0" bool ImGui::Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items) { int items_count = 0; const char* p = items_separated_by_zeros; // FIXME-OPT: Avoid computing this, or at least only when combo is open while (*p) { p += strlen(p) + 1; items_count++; } bool value_changed = Combo(label, current_item, Items_SingleStringGetter, (void*)items_separated_by_zeros, items_count, height_in_items); return value_changed; } #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS struct ImGuiGetNameFromIndexOldToNewCallbackData { void* UserData; bool (*OldCallback)(void*, int, const char**); }; static const char* ImGuiGetNameFromIndexOldToNewCallback(void* user_data, int idx) { ImGuiGetNameFromIndexOldToNewCallbackData* data = (ImGuiGetNameFromIndexOldToNewCallbackData*)user_data; const char* s = NULL; data->OldCallback(data->UserData, idx, &s); return s; } bool ImGui::ListBox(const char* label, int* current_item, bool (*old_getter)(void*, int, const char**), void* user_data, int items_count, int height_in_items) { ImGuiGetNameFromIndexOldToNewCallbackData old_to_new_data = { user_data, old_getter }; return ListBox(label, current_item, ImGuiGetNameFromIndexOldToNewCallback, &old_to_new_data, items_count, height_in_items); } bool ImGui::Combo(const char* label, int* current_item, bool (*old_getter)(void*, int, const char**), void* user_data, int items_count, int popup_max_height_in_items) { ImGuiGetNameFromIndexOldToNewCallbackData old_to_new_data = { user_data, old_getter }; return Combo(label, current_item, ImGuiGetNameFromIndexOldToNewCallback, &old_to_new_data, items_count, popup_max_height_in_items); } #endif //------------------------------------------------------------------------- // [SECTION] Data Type and Data Formatting Helpers [Internal] //------------------------------------------------------------------------- // - DataTypeGetInfo() // - DataTypeFormatString() // - DataTypeApplyOp() // - DataTypeApplyFromText() // - DataTypeCompare() // - DataTypeClamp() // - GetMinimumStepAtDecimalPrecision // - RoundScalarWithFormat<>() //------------------------------------------------------------------------- static const ImGuiDataTypeInfo GDataTypeInfo[] = { { sizeof(char), "S8", "%d", "%d" }, // ImGuiDataType_S8 { sizeof(unsigned char), "U8", "%u", "%u" }, { sizeof(short), "S16", "%d", "%d" }, // ImGuiDataType_S16 { sizeof(unsigned short), "U16", "%u", "%u" }, { sizeof(int), "S32", "%d", "%d" }, // ImGuiDataType_S32 { sizeof(unsigned int), "U32", "%u", "%u" }, #ifdef _MSC_VER { sizeof(ImS64), "S64", "%I64d","%I64d" }, // ImGuiDataType_S64 { sizeof(ImU64), "U64", "%I64u","%I64u" }, #else { sizeof(ImS64), "S64", "%lld", "%lld" }, // ImGuiDataType_S64 { sizeof(ImU64), "U64", "%llu", "%llu" }, #endif { sizeof(float), "float", "%.3f","%f" }, // ImGuiDataType_Float (float are promoted to double in va_arg) { sizeof(double), "double","%f", "%lf" }, // ImGuiDataType_Double }; IM_STATIC_ASSERT(IM_ARRAYSIZE(GDataTypeInfo) == ImGuiDataType_COUNT); const ImGuiDataTypeInfo* ImGui::DataTypeGetInfo(ImGuiDataType data_type) { IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT); return &GDataTypeInfo[data_type]; } int ImGui::DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* p_data, const char* format) { // Signedness doesn't matter when pushing integer arguments if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32) return ImFormatString(buf, buf_size, format, *(const ImU32*)p_data); if (data_type == ImGuiDataType_S64 || data_type == ImGuiDataType_U64) return ImFormatString(buf, buf_size, format, *(const ImU64*)p_data); if (data_type == ImGuiDataType_Float) return ImFormatString(buf, buf_size, format, *(const float*)p_data); if (data_type == ImGuiDataType_Double) return ImFormatString(buf, buf_size, format, *(const double*)p_data); if (data_type == ImGuiDataType_S8) return ImFormatString(buf, buf_size, format, *(const ImS8*)p_data); if (data_type == ImGuiDataType_U8) return ImFormatString(buf, buf_size, format, *(const ImU8*)p_data); if (data_type == ImGuiDataType_S16) return ImFormatString(buf, buf_size, format, *(const ImS16*)p_data); if (data_type == ImGuiDataType_U16) return ImFormatString(buf, buf_size, format, *(const ImU16*)p_data); IM_ASSERT(0); return 0; } void ImGui::DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, const void* arg1, const void* arg2) { IM_ASSERT(op == '+' || op == '-'); switch (data_type) { case ImGuiDataType_S8: if (op == '+') { *(ImS8*)output = ImAddClampOverflow(*(const ImS8*)arg1, *(const ImS8*)arg2, IM_S8_MIN, IM_S8_MAX); } if (op == '-') { *(ImS8*)output = ImSubClampOverflow(*(const ImS8*)arg1, *(const ImS8*)arg2, IM_S8_MIN, IM_S8_MAX); } return; case ImGuiDataType_U8: if (op == '+') { *(ImU8*)output = ImAddClampOverflow(*(const ImU8*)arg1, *(const ImU8*)arg2, IM_U8_MIN, IM_U8_MAX); } if (op == '-') { *(ImU8*)output = ImSubClampOverflow(*(const ImU8*)arg1, *(const ImU8*)arg2, IM_U8_MIN, IM_U8_MAX); } return; case ImGuiDataType_S16: if (op == '+') { *(ImS16*)output = ImAddClampOverflow(*(const ImS16*)arg1, *(const ImS16*)arg2, IM_S16_MIN, IM_S16_MAX); } if (op == '-') { *(ImS16*)output = ImSubClampOverflow(*(const ImS16*)arg1, *(const ImS16*)arg2, IM_S16_MIN, IM_S16_MAX); } return; case ImGuiDataType_U16: if (op == '+') { *(ImU16*)output = ImAddClampOverflow(*(const ImU16*)arg1, *(const ImU16*)arg2, IM_U16_MIN, IM_U16_MAX); } if (op == '-') { *(ImU16*)output = ImSubClampOverflow(*(const ImU16*)arg1, *(const ImU16*)arg2, IM_U16_MIN, IM_U16_MAX); } return; case ImGuiDataType_S32: if (op == '+') { *(ImS32*)output = ImAddClampOverflow(*(const ImS32*)arg1, *(const ImS32*)arg2, IM_S32_MIN, IM_S32_MAX); } if (op == '-') { *(ImS32*)output = ImSubClampOverflow(*(const ImS32*)arg1, *(const ImS32*)arg2, IM_S32_MIN, IM_S32_MAX); } return; case ImGuiDataType_U32: if (op == '+') { *(ImU32*)output = ImAddClampOverflow(*(const ImU32*)arg1, *(const ImU32*)arg2, IM_U32_MIN, IM_U32_MAX); } if (op == '-') { *(ImU32*)output = ImSubClampOverflow(*(const ImU32*)arg1, *(const ImU32*)arg2, IM_U32_MIN, IM_U32_MAX); } return; case ImGuiDataType_S64: if (op == '+') { *(ImS64*)output = ImAddClampOverflow(*(const ImS64*)arg1, *(const ImS64*)arg2, IM_S64_MIN, IM_S64_MAX); } if (op == '-') { *(ImS64*)output = ImSubClampOverflow(*(const ImS64*)arg1, *(const ImS64*)arg2, IM_S64_MIN, IM_S64_MAX); } return; case ImGuiDataType_U64: if (op == '+') { *(ImU64*)output = ImAddClampOverflow(*(const ImU64*)arg1, *(const ImU64*)arg2, IM_U64_MIN, IM_U64_MAX); } if (op == '-') { *(ImU64*)output = ImSubClampOverflow(*(const ImU64*)arg1, *(const ImU64*)arg2, IM_U64_MIN, IM_U64_MAX); } return; case ImGuiDataType_Float: if (op == '+') { *(float*)output = *(const float*)arg1 + *(const float*)arg2; } if (op == '-') { *(float*)output = *(const float*)arg1 - *(const float*)arg2; } return; case ImGuiDataType_Double: if (op == '+') { *(double*)output = *(const double*)arg1 + *(const double*)arg2; } if (op == '-') { *(double*)output = *(const double*)arg1 - *(const double*)arg2; } return; case ImGuiDataType_COUNT: break; } IM_ASSERT(0); } // User can input math operators (e.g. +100) to edit a numerical values. // NB: This is _not_ a full expression evaluator. We should probably add one and replace this dumb mess.. bool ImGui::DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void* p_data, const char* format) { while (ImCharIsBlankA(*buf)) buf++; if (!buf[0]) return false; // Copy the value in an opaque buffer so we can compare at the end of the function if it changed at all. const ImGuiDataTypeInfo* type_info = DataTypeGetInfo(data_type); ImGuiDataTypeTempStorage data_backup; memcpy(&data_backup, p_data, type_info->Size); // Sanitize format // - For float/double we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in, so force them into %f and %lf // - In theory could treat empty format as using default, but this would only cover rare/bizarre case of using InputScalar() + integer + format string without %. char format_sanitized[32]; if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double) format = type_info->ScanFmt; else format = ImParseFormatSanitizeForScanning(format, format_sanitized, IM_ARRAYSIZE(format_sanitized)); // Small types need a 32-bit buffer to receive the result from scanf() int v32 = 0; if (sscanf(buf, format, type_info->Size >= 4 ? p_data : &v32) < 1) return false; if (type_info->Size < 4) { if (data_type == ImGuiDataType_S8) *(ImS8*)p_data = (ImS8)ImClamp(v32, (int)IM_S8_MIN, (int)IM_S8_MAX); else if (data_type == ImGuiDataType_U8) *(ImU8*)p_data = (ImU8)ImClamp(v32, (int)IM_U8_MIN, (int)IM_U8_MAX); else if (data_type == ImGuiDataType_S16) *(ImS16*)p_data = (ImS16)ImClamp(v32, (int)IM_S16_MIN, (int)IM_S16_MAX); else if (data_type == ImGuiDataType_U16) *(ImU16*)p_data = (ImU16)ImClamp(v32, (int)IM_U16_MIN, (int)IM_U16_MAX); else IM_ASSERT(0); } return memcmp(&data_backup, p_data, type_info->Size) != 0; } template static int DataTypeCompareT(const T* lhs, const T* rhs) { if (*lhs < *rhs) return -1; if (*lhs > *rhs) return +1; return 0; } int ImGui::DataTypeCompare(ImGuiDataType data_type, const void* arg_1, const void* arg_2) { switch (data_type) { case ImGuiDataType_S8: return DataTypeCompareT((const ImS8* )arg_1, (const ImS8* )arg_2); case ImGuiDataType_U8: return DataTypeCompareT((const ImU8* )arg_1, (const ImU8* )arg_2); case ImGuiDataType_S16: return DataTypeCompareT((const ImS16* )arg_1, (const ImS16* )arg_2); case ImGuiDataType_U16: return DataTypeCompareT((const ImU16* )arg_1, (const ImU16* )arg_2); case ImGuiDataType_S32: return DataTypeCompareT((const ImS32* )arg_1, (const ImS32* )arg_2); case ImGuiDataType_U32: return DataTypeCompareT((const ImU32* )arg_1, (const ImU32* )arg_2); case ImGuiDataType_S64: return DataTypeCompareT((const ImS64* )arg_1, (const ImS64* )arg_2); case ImGuiDataType_U64: return DataTypeCompareT((const ImU64* )arg_1, (const ImU64* )arg_2); case ImGuiDataType_Float: return DataTypeCompareT((const float* )arg_1, (const float* )arg_2); case ImGuiDataType_Double: return DataTypeCompareT((const double*)arg_1, (const double*)arg_2); case ImGuiDataType_COUNT: break; } IM_ASSERT(0); return 0; } template static bool DataTypeClampT(T* v, const T* v_min, const T* v_max) { // Clamp, both sides are optional, return true if modified if (v_min && *v < *v_min) { *v = *v_min; return true; } if (v_max && *v > *v_max) { *v = *v_max; return true; } return false; } bool ImGui::DataTypeClamp(ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max) { switch (data_type) { case ImGuiDataType_S8: return DataTypeClampT((ImS8* )p_data, (const ImS8* )p_min, (const ImS8* )p_max); case ImGuiDataType_U8: return DataTypeClampT((ImU8* )p_data, (const ImU8* )p_min, (const ImU8* )p_max); case ImGuiDataType_S16: return DataTypeClampT((ImS16* )p_data, (const ImS16* )p_min, (const ImS16* )p_max); case ImGuiDataType_U16: return DataTypeClampT((ImU16* )p_data, (const ImU16* )p_min, (const ImU16* )p_max); case ImGuiDataType_S32: return DataTypeClampT((ImS32* )p_data, (const ImS32* )p_min, (const ImS32* )p_max); case ImGuiDataType_U32: return DataTypeClampT((ImU32* )p_data, (const ImU32* )p_min, (const ImU32* )p_max); case ImGuiDataType_S64: return DataTypeClampT((ImS64* )p_data, (const ImS64* )p_min, (const ImS64* )p_max); case ImGuiDataType_U64: return DataTypeClampT((ImU64* )p_data, (const ImU64* )p_min, (const ImU64* )p_max); case ImGuiDataType_Float: return DataTypeClampT((float* )p_data, (const float* )p_min, (const float* )p_max); case ImGuiDataType_Double: return DataTypeClampT((double*)p_data, (const double*)p_min, (const double*)p_max); case ImGuiDataType_COUNT: break; } IM_ASSERT(0); return false; } static float GetMinimumStepAtDecimalPrecision(int decimal_precision) { static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f }; if (decimal_precision < 0) return FLT_MIN; return (decimal_precision < IM_ARRAYSIZE(min_steps)) ? min_steps[decimal_precision] : ImPow(10.0f, (float)-decimal_precision); } template TYPE ImGui::RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, TYPE v) { IM_UNUSED(data_type); IM_ASSERT(data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double); const char* fmt_start = ImParseFormatFindStart(format); if (fmt_start[0] != '%' || fmt_start[1] == '%') // Don't apply if the value is not visible in the format string return v; // Sanitize format char fmt_sanitized[32]; ImParseFormatSanitizeForPrinting(fmt_start, fmt_sanitized, IM_ARRAYSIZE(fmt_sanitized)); fmt_start = fmt_sanitized; // Format value with our rounding, and read back char v_str[64]; ImFormatString(v_str, IM_ARRAYSIZE(v_str), fmt_start, v); const char* p = v_str; while (*p == ' ') p++; v = (TYPE)ImAtof(p); return v; } //------------------------------------------------------------------------- // [SECTION] Widgets: DragScalar, DragFloat, DragInt, etc. //------------------------------------------------------------------------- // - DragBehaviorT<>() [Internal] // - DragBehavior() [Internal] // - DragScalar() // - DragScalarN() // - DragFloat() // - DragFloat2() // - DragFloat3() // - DragFloat4() // - DragFloatRange2() // - DragInt() // - DragInt2() // - DragInt3() // - DragInt4() // - DragIntRange2() //------------------------------------------------------------------------- // This is called by DragBehavior() when the widget is active (held by mouse or being manipulated with Nav controls) template bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const TYPE v_min, const TYPE v_max, const char* format, ImGuiSliderFlags flags) { ImGuiContext& g = *GImGui; const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X; const bool is_clamped = (v_min < v_max); const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) != 0; const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double); // Default tweak speed if (v_speed == 0.0f && is_clamped && (v_max - v_min < FLT_MAX)) v_speed = (float)((v_max - v_min) * g.DragSpeedDefaultRatio); // Inputs accumulates into g.DragCurrentAccum, which is flushed into the current value as soon as it makes a difference with our precision settings float adjust_delta = 0.0f; if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid() && IsMouseDragPastThreshold(0, g.IO.MouseDragThreshold * DRAG_MOUSE_THRESHOLD_FACTOR)) { adjust_delta = g.IO.MouseDelta[axis]; if (g.IO.KeyAlt) adjust_delta *= 1.0f / 100.0f; if (g.IO.KeyShift) adjust_delta *= 10.0f; } else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad) { const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0; const bool tweak_slow = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakSlow : ImGuiKey_NavKeyboardTweakSlow); const bool tweak_fast = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakFast : ImGuiKey_NavKeyboardTweakFast); const float tweak_factor = tweak_slow ? 1.0f / 1.0f : tweak_fast ? 10.0f : 1.0f; adjust_delta = GetNavTweakPressedAmount(axis) * tweak_factor; v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); } adjust_delta *= v_speed; // For vertical drag we currently assume that Up=higher value (like we do with vertical sliders). This may become a parameter. if (axis == ImGuiAxis_Y) adjust_delta = -adjust_delta; // For logarithmic use our range is effectively 0..1 so scale the delta into that range if (is_logarithmic && (v_max - v_min < FLT_MAX) && ((v_max - v_min) > 0.000001f)) // Epsilon to avoid /0 adjust_delta /= (float)(v_max - v_min); // Clear current value on activation // Avoid altering values and clamping when we are _already_ past the limits and heading in the same direction, so e.g. if range is 0..255, current value is 300 and we are pushing to the right side, keep the 300. bool is_just_activated = g.ActiveIdIsJustActivated; bool is_already_past_limits_and_pushing_outward = is_clamped && ((*v >= v_max && adjust_delta > 0.0f) || (*v <= v_min && adjust_delta < 0.0f)); if (is_just_activated || is_already_past_limits_and_pushing_outward) { g.DragCurrentAccum = 0.0f; g.DragCurrentAccumDirty = false; } else if (adjust_delta != 0.0f) { g.DragCurrentAccum += adjust_delta; g.DragCurrentAccumDirty = true; } if (!g.DragCurrentAccumDirty) return false; TYPE v_cur = *v; FLOATTYPE v_old_ref_for_accum_remainder = (FLOATTYPE)0.0f; float logarithmic_zero_epsilon = 0.0f; // Only valid when is_logarithmic is true const float zero_deadzone_halfsize = 0.0f; // Drag widgets have no deadzone (as it doesn't make sense) if (is_logarithmic) { // When using logarithmic sliders, we need to clamp to avoid hitting zero, but our choice of clamp value greatly affects slider precision. We attempt to use the specified precision to estimate a good lower bound. const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 1; logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision); // Convert to parametric space, apply delta, convert back float v_old_parametric = ScaleRatioFromValueT(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); float v_new_parametric = v_old_parametric + g.DragCurrentAccum; v_cur = ScaleValueFromRatioT(data_type, v_new_parametric, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); v_old_ref_for_accum_remainder = v_old_parametric; } else { v_cur += (SIGNEDTYPE)g.DragCurrentAccum; } // Round to user desired precision based on format string if (is_floating_point && !(flags & ImGuiSliderFlags_NoRoundToFormat)) v_cur = RoundScalarWithFormatT(format, data_type, v_cur); // Preserve remainder after rounding has been applied. This also allow slow tweaking of values. g.DragCurrentAccumDirty = false; if (is_logarithmic) { // Convert to parametric space, apply delta, convert back float v_new_parametric = ScaleRatioFromValueT(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); g.DragCurrentAccum -= (float)(v_new_parametric - v_old_ref_for_accum_remainder); } else { g.DragCurrentAccum -= (float)((SIGNEDTYPE)v_cur - (SIGNEDTYPE)*v); } // Lose zero sign for float/double if (v_cur == (TYPE)-0) v_cur = (TYPE)0; // Clamp values (+ handle overflow/wrap-around for integer types) if (*v != v_cur && is_clamped) { if (v_cur < v_min || (v_cur > *v && adjust_delta < 0.0f && !is_floating_point)) v_cur = v_min; if (v_cur > v_max || (v_cur < *v && adjust_delta > 0.0f && !is_floating_point)) v_cur = v_max; } // Apply result if (*v == v_cur) return false; *v = v_cur; return true; } bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) { // Read imgui.cpp "API BREAKING CHANGES" section for 1.78 if you hit this assert. IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flags! Has the 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead."); ImGuiContext& g = *GImGui; if (g.ActiveId == id) { // Those are the things we can do easily outside the DragBehaviorT<> template, saves code generation. if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0]) ClearActiveID(); else if ((g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad) && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated) ClearActiveID(); } if (g.ActiveId != id) return false; if ((g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly)) return false; switch (data_type) { case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = DragBehaviorT(ImGuiDataType_S32, &v32, v_speed, p_min ? *(const ImS8*) p_min : IM_S8_MIN, p_max ? *(const ImS8*)p_max : IM_S8_MAX, format, flags); if (r) *(ImS8*)p_v = (ImS8)v32; return r; } case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)p_v; bool r = DragBehaviorT(ImGuiDataType_U32, &v32, v_speed, p_min ? *(const ImU8*) p_min : IM_U8_MIN, p_max ? *(const ImU8*)p_max : IM_U8_MAX, format, flags); if (r) *(ImU8*)p_v = (ImU8)v32; return r; } case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)p_v; bool r = DragBehaviorT(ImGuiDataType_S32, &v32, v_speed, p_min ? *(const ImS16*)p_min : IM_S16_MIN, p_max ? *(const ImS16*)p_max : IM_S16_MAX, format, flags); if (r) *(ImS16*)p_v = (ImS16)v32; return r; } case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)p_v; bool r = DragBehaviorT(ImGuiDataType_U32, &v32, v_speed, p_min ? *(const ImU16*)p_min : IM_U16_MIN, p_max ? *(const ImU16*)p_max : IM_U16_MAX, format, flags); if (r) *(ImU16*)p_v = (ImU16)v32; return r; } case ImGuiDataType_S32: return DragBehaviorT(data_type, (ImS32*)p_v, v_speed, p_min ? *(const ImS32* )p_min : IM_S32_MIN, p_max ? *(const ImS32* )p_max : IM_S32_MAX, format, flags); case ImGuiDataType_U32: return DragBehaviorT(data_type, (ImU32*)p_v, v_speed, p_min ? *(const ImU32* )p_min : IM_U32_MIN, p_max ? *(const ImU32* )p_max : IM_U32_MAX, format, flags); case ImGuiDataType_S64: return DragBehaviorT(data_type, (ImS64*)p_v, v_speed, p_min ? *(const ImS64* )p_min : IM_S64_MIN, p_max ? *(const ImS64* )p_max : IM_S64_MAX, format, flags); case ImGuiDataType_U64: return DragBehaviorT(data_type, (ImU64*)p_v, v_speed, p_min ? *(const ImU64* )p_min : IM_U64_MIN, p_max ? *(const ImU64* )p_max : IM_U64_MAX, format, flags); case ImGuiDataType_Float: return DragBehaviorT(data_type, (float*)p_v, v_speed, p_min ? *(const float* )p_min : -FLT_MAX, p_max ? *(const float* )p_max : FLT_MAX, format, flags); case ImGuiDataType_Double: return DragBehaviorT(data_type, (double*)p_v, v_speed, p_min ? *(const double*)p_min : -DBL_MAX, p_max ? *(const double*)p_max : DBL_MAX, format, flags); case ImGuiDataType_COUNT: break; } IM_ASSERT(0); return false; } // Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a Drag widget, p_min and p_max are optional. // Read code of e.g. DragFloat(), DragInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); const float w = CalcItemWidth(); const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0; ItemSize(total_bb, style.FramePadding.y); if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemFlags_Inputable : 0)) return false; // Default format string when passing NULL if (format == NULL) format = DataTypeGetInfo(data_type)->PrintFmt; const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags); bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); if (!temp_input_is_active) { // Tabbing or CTRL-clicking on Drag turns it into an InputText const bool clicked = hovered && IsMouseClicked(0, id); const bool double_clicked = (hovered && g.IO.MouseClickedCount[0] == 2 && TestKeyOwner(ImGuiKey_MouseLeft, id)); const bool make_active = (clicked || double_clicked || g.NavActivateId == id); if (make_active && (clicked || double_clicked)) SetKeyOwner(ImGuiKey_MouseLeft, id); if (make_active && temp_input_allowed) if ((clicked && g.IO.KeyCtrl) || double_clicked || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput))) temp_input_is_active = true; // (Optional) simple click (without moving) turns Drag into an InputText if (g.IO.ConfigDragClickToInputText && temp_input_allowed && !temp_input_is_active) if (g.ActiveId == id && hovered && g.IO.MouseReleased[0] && !IsMouseDragPastThreshold(0, g.IO.MouseDragThreshold * DRAG_MOUSE_THRESHOLD_FACTOR)) { g.NavActivateId = id; g.NavActivateFlags = ImGuiActivateFlags_PreferInput; temp_input_is_active = true; } if (make_active && !temp_input_is_active) { SetActiveID(id, window); SetFocusID(id, window); FocusWindow(window); g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); } } if (temp_input_is_active) { // Only clamp CTRL+Click input when ImGuiSliderFlags_AlwaysClamp is set const bool is_clamp_input = (flags & ImGuiSliderFlags_AlwaysClamp) != 0 && (p_min == NULL || p_max == NULL || DataTypeCompare(data_type, p_min, p_max) < 0); return TempInputScalar(frame_bb, id, label, data_type, p_data, format, is_clamp_input ? p_min : NULL, is_clamp_input ? p_max : NULL); } // Draw frame const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); // Drag behavior const bool value_changed = DragBehavior(id, data_type, p_data, v_speed, p_min, p_max, format, flags); if (value_changed) MarkItemEdited(id); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. char value_buf[64]; const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format); if (g.LogEnabled) LogSetNextTextDecoration("{", "}"); RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f)); if (label_size.x > 0.0f) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | (temp_input_allowed ? ImGuiItemStatusFlags_Inputable : 0)); return value_changed; } bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; bool value_changed = false; BeginGroup(); PushID(label); PushMultiItemsWidths(components, CalcItemWidth()); size_t type_size = GDataTypeInfo[data_type].Size; for (int i = 0; i < components; i++) { PushID(i); if (i > 0) SameLine(0, g.Style.ItemInnerSpacing.x); value_changed |= DragScalar("", data_type, p_data, v_speed, p_min, p_max, format, flags); PopID(); PopItemWidth(); p_data = (void*)((char*)p_data + type_size); } PopID(); const char* label_end = FindRenderedTextEnd(label); if (label != label_end) { SameLine(0, g.Style.ItemInnerSpacing.x); TextEx(label, label_end); } EndGroup(); return value_changed; } bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return DragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, format, flags); } bool ImGui::DragFloat2(const char* label, float v[2], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_Float, v, 2, v_speed, &v_min, &v_max, format, flags); } bool ImGui::DragFloat3(const char* label, float v[3], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_Float, v, 3, v_speed, &v_min, &v_max, format, flags); } bool ImGui::DragFloat4(const char* label, float v[4], float v_speed, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_Float, v, 4, v_speed, &v_min, &v_max, format, flags); } // NB: You likely want to specify the ImGuiSliderFlags_AlwaysClamp when using this. bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_current_max, float v_speed, float v_min, float v_max, const char* format, const char* format_max, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; PushID(label); BeginGroup(); PushMultiItemsWidths(2, CalcItemWidth()); float min_min = (v_min >= v_max) ? -FLT_MAX : v_min; float min_max = (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max); ImGuiSliderFlags min_flags = flags | ((min_min == min_max) ? ImGuiSliderFlags_ReadOnly : 0); bool value_changed = DragScalar("##min", ImGuiDataType_Float, v_current_min, v_speed, &min_min, &min_max, format, min_flags); PopItemWidth(); SameLine(0, g.Style.ItemInnerSpacing.x); float max_min = (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min); float max_max = (v_min >= v_max) ? FLT_MAX : v_max; ImGuiSliderFlags max_flags = flags | ((max_min == max_max) ? ImGuiSliderFlags_ReadOnly : 0); value_changed |= DragScalar("##max", ImGuiDataType_Float, v_current_max, v_speed, &max_min, &max_max, format_max ? format_max : format, max_flags); PopItemWidth(); SameLine(0, g.Style.ItemInnerSpacing.x); TextEx(label, FindRenderedTextEnd(label)); EndGroup(); PopID(); return value_changed; } // NB: v_speed is float to allow adjusting the drag speed with more precision bool ImGui::DragInt(const char* label, int* v, float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return DragScalar(label, ImGuiDataType_S32, v, v_speed, &v_min, &v_max, format, flags); } bool ImGui::DragInt2(const char* label, int v[2], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_S32, v, 2, v_speed, &v_min, &v_max, format, flags); } bool ImGui::DragInt3(const char* label, int v[3], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_S32, v, 3, v_speed, &v_min, &v_max, format, flags); } bool ImGui::DragInt4(const char* label, int v[4], float v_speed, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return DragScalarN(label, ImGuiDataType_S32, v, 4, v_speed, &v_min, &v_max, format, flags); } // NB: You likely want to specify the ImGuiSliderFlags_AlwaysClamp when using this. bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed, int v_min, int v_max, const char* format, const char* format_max, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; PushID(label); BeginGroup(); PushMultiItemsWidths(2, CalcItemWidth()); int min_min = (v_min >= v_max) ? INT_MIN : v_min; int min_max = (v_min >= v_max) ? *v_current_max : ImMin(v_max, *v_current_max); ImGuiSliderFlags min_flags = flags | ((min_min == min_max) ? ImGuiSliderFlags_ReadOnly : 0); bool value_changed = DragInt("##min", v_current_min, v_speed, min_min, min_max, format, min_flags); PopItemWidth(); SameLine(0, g.Style.ItemInnerSpacing.x); int max_min = (v_min >= v_max) ? *v_current_min : ImMax(v_min, *v_current_min); int max_max = (v_min >= v_max) ? INT_MAX : v_max; ImGuiSliderFlags max_flags = flags | ((max_min == max_max) ? ImGuiSliderFlags_ReadOnly : 0); value_changed |= DragInt("##max", v_current_max, v_speed, max_min, max_max, format_max ? format_max : format, max_flags); PopItemWidth(); SameLine(0, g.Style.ItemInnerSpacing.x); TextEx(label, FindRenderedTextEnd(label)); EndGroup(); PopID(); return value_changed; } //------------------------------------------------------------------------- // [SECTION] Widgets: SliderScalar, SliderFloat, SliderInt, etc. //------------------------------------------------------------------------- // - ScaleRatioFromValueT<> [Internal] // - ScaleValueFromRatioT<> [Internal] // - SliderBehaviorT<>() [Internal] // - SliderBehavior() [Internal] // - SliderScalar() // - SliderScalarN() // - SliderFloat() // - SliderFloat2() // - SliderFloat3() // - SliderFloat4() // - SliderAngle() // - SliderInt() // - SliderInt2() // - SliderInt3() // - SliderInt4() // - VSliderScalar() // - VSliderFloat() // - VSliderInt() //------------------------------------------------------------------------- // Convert a value v in the output space of a slider into a parametric position on the slider itself (the logical opposite of ScaleValueFromRatioT) template float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize) { if (v_min == v_max) return 0.0f; IM_UNUSED(data_type); const TYPE v_clamped = (v_min < v_max) ? ImClamp(v, v_min, v_max) : ImClamp(v, v_max, v_min); if (is_logarithmic) { bool flipped = v_max < v_min; if (flipped) // Handle the case where the range is backwards ImSwap(v_min, v_max); // Fudge min/max to avoid getting close to log(0) FLOATTYPE v_min_fudged = (ImAbs((FLOATTYPE)v_min) < logarithmic_zero_epsilon) ? ((v_min < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_min; FLOATTYPE v_max_fudged = (ImAbs((FLOATTYPE)v_max) < logarithmic_zero_epsilon) ? ((v_max < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_max; // Awkward special cases - we need ranges of the form (-100 .. 0) to convert to (-100 .. -epsilon), not (-100 .. epsilon) if ((v_min == 0.0f) && (v_max < 0.0f)) v_min_fudged = -logarithmic_zero_epsilon; else if ((v_max == 0.0f) && (v_min < 0.0f)) v_max_fudged = -logarithmic_zero_epsilon; float result; if (v_clamped <= v_min_fudged) result = 0.0f; // Workaround for values that are in-range but below our fudge else if (v_clamped >= v_max_fudged) result = 1.0f; // Workaround for values that are in-range but above our fudge else if ((v_min * v_max) < 0.0f) // Range crosses zero, so split into two portions { float zero_point_center = (-(float)v_min) / ((float)v_max - (float)v_min); // The zero point in parametric space. There's an argument we should take the logarithmic nature into account when calculating this, but for now this should do (and the most common case of a symmetrical range works fine) float zero_point_snap_L = zero_point_center - zero_deadzone_halfsize; float zero_point_snap_R = zero_point_center + zero_deadzone_halfsize; if (v == 0.0f) result = zero_point_center; // Special case for exactly zero else if (v < 0.0f) result = (1.0f - (float)(ImLog(-(FLOATTYPE)v_clamped / logarithmic_zero_epsilon) / ImLog(-v_min_fudged / logarithmic_zero_epsilon))) * zero_point_snap_L; else result = zero_point_snap_R + ((float)(ImLog((FLOATTYPE)v_clamped / logarithmic_zero_epsilon) / ImLog(v_max_fudged / logarithmic_zero_epsilon)) * (1.0f - zero_point_snap_R)); } else if ((v_min < 0.0f) || (v_max < 0.0f)) // Entirely negative slider result = 1.0f - (float)(ImLog(-(FLOATTYPE)v_clamped / -v_max_fudged) / ImLog(-v_min_fudged / -v_max_fudged)); else result = (float)(ImLog((FLOATTYPE)v_clamped / v_min_fudged) / ImLog(v_max_fudged / v_min_fudged)); return flipped ? (1.0f - result) : result; } else { // Linear slider return (float)((FLOATTYPE)(SIGNEDTYPE)(v_clamped - v_min) / (FLOATTYPE)(SIGNEDTYPE)(v_max - v_min)); } } // Convert a parametric position on a slider into a value v in the output space (the logical opposite of ScaleRatioFromValueT) template TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize) { // We special-case the extents because otherwise our logarithmic fudging can lead to "mathematically correct" // but non-intuitive behaviors like a fully-left slider not actually reaching the minimum value. Also generally simpler. if (t <= 0.0f || v_min == v_max) return v_min; if (t >= 1.0f) return v_max; TYPE result = (TYPE)0; if (is_logarithmic) { // Fudge min/max to avoid getting silly results close to zero FLOATTYPE v_min_fudged = (ImAbs((FLOATTYPE)v_min) < logarithmic_zero_epsilon) ? ((v_min < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_min; FLOATTYPE v_max_fudged = (ImAbs((FLOATTYPE)v_max) < logarithmic_zero_epsilon) ? ((v_max < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_max; const bool flipped = v_max < v_min; // Check if range is "backwards" if (flipped) ImSwap(v_min_fudged, v_max_fudged); // Awkward special case - we need ranges of the form (-100 .. 0) to convert to (-100 .. -epsilon), not (-100 .. epsilon) if ((v_max == 0.0f) && (v_min < 0.0f)) v_max_fudged = -logarithmic_zero_epsilon; float t_with_flip = flipped ? (1.0f - t) : t; // t, but flipped if necessary to account for us flipping the range if ((v_min * v_max) < 0.0f) // Range crosses zero, so we have to do this in two parts { float zero_point_center = (-(float)ImMin(v_min, v_max)) / ImAbs((float)v_max - (float)v_min); // The zero point in parametric space float zero_point_snap_L = zero_point_center - zero_deadzone_halfsize; float zero_point_snap_R = zero_point_center + zero_deadzone_halfsize; if (t_with_flip >= zero_point_snap_L && t_with_flip <= zero_point_snap_R) result = (TYPE)0.0f; // Special case to make getting exactly zero possible (the epsilon prevents it otherwise) else if (t_with_flip < zero_point_center) result = (TYPE)-(logarithmic_zero_epsilon * ImPow(-v_min_fudged / logarithmic_zero_epsilon, (FLOATTYPE)(1.0f - (t_with_flip / zero_point_snap_L)))); else result = (TYPE)(logarithmic_zero_epsilon * ImPow(v_max_fudged / logarithmic_zero_epsilon, (FLOATTYPE)((t_with_flip - zero_point_snap_R) / (1.0f - zero_point_snap_R)))); } else if ((v_min < 0.0f) || (v_max < 0.0f)) // Entirely negative slider result = (TYPE)-(-v_max_fudged * ImPow(-v_min_fudged / -v_max_fudged, (FLOATTYPE)(1.0f - t_with_flip))); else result = (TYPE)(v_min_fudged * ImPow(v_max_fudged / v_min_fudged, (FLOATTYPE)t_with_flip)); } else { // Linear slider const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double); if (is_floating_point) { result = ImLerp(v_min, v_max, t); } else if (t < 1.0) { // - For integer values we want the clicking position to match the grab box so we round above // This code is carefully tuned to work with large values (e.g. high ranges of U64) while preserving this property.. // - Not doing a *1.0 multiply at the end of a range as it tends to be lossy. While absolute aiming at a large s64/u64 // range is going to be imprecise anyway, with this check we at least make the edge values matches expected limits. FLOATTYPE v_new_off_f = (SIGNEDTYPE)(v_max - v_min) * t; result = (TYPE)((SIGNEDTYPE)v_min + (SIGNEDTYPE)(v_new_off_f + (FLOATTYPE)(v_min > v_max ? -0.5 : 0.5))); } } return result; } // FIXME: Try to move more of the code into shared SliderBehavior() template bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, TYPE* v, const TYPE v_min, const TYPE v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb) { ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X; const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) != 0; const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double); const float v_range_f = (float)(v_min < v_max ? v_max - v_min : v_min - v_max); // We don't need high precision for what we do with it. // Calculate bounds const float grab_padding = 2.0f; // FIXME: Should be part of style. const float slider_sz = (bb.Max[axis] - bb.Min[axis]) - grab_padding * 2.0f; float grab_sz = style.GrabMinSize; if (!is_floating_point && v_range_f >= 0.0f) // v_range_f < 0 may happen on integer overflows grab_sz = ImMax(slider_sz / (v_range_f + 1), style.GrabMinSize); // For integer sliders: if possible have the grab size represent 1 unit grab_sz = ImMin(grab_sz, slider_sz); const float slider_usable_sz = slider_sz - grab_sz; const float slider_usable_pos_min = bb.Min[axis] + grab_padding + grab_sz * 0.5f; const float slider_usable_pos_max = bb.Max[axis] - grab_padding - grab_sz * 0.5f; float logarithmic_zero_epsilon = 0.0f; // Only valid when is_logarithmic is true float zero_deadzone_halfsize = 0.0f; // Only valid when is_logarithmic is true if (is_logarithmic) { // When using logarithmic sliders, we need to clamp to avoid hitting zero, but our choice of clamp value greatly affects slider precision. We attempt to use the specified precision to estimate a good lower bound. const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 1; logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision); zero_deadzone_halfsize = (style.LogSliderDeadzone * 0.5f) / ImMax(slider_usable_sz, 1.0f); } // Process interacting with the slider bool value_changed = false; if (g.ActiveId == id) { bool set_new_value = false; float clicked_t = 0.0f; if (g.ActiveIdSource == ImGuiInputSource_Mouse) { if (!g.IO.MouseDown[0]) { ClearActiveID(); } else { const float mouse_abs_pos = g.IO.MousePos[axis]; if (g.ActiveIdIsJustActivated) { float grab_t = ScaleRatioFromValueT(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); if (axis == ImGuiAxis_Y) grab_t = 1.0f - grab_t; const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); const bool clicked_around_grab = (mouse_abs_pos >= grab_pos - grab_sz * 0.5f - 1.0f) && (mouse_abs_pos <= grab_pos + grab_sz * 0.5f + 1.0f); // No harm being extra generous here. g.SliderGrabClickOffset = (clicked_around_grab && is_floating_point) ? mouse_abs_pos - grab_pos : 0.0f; } if (slider_usable_sz > 0.0f) clicked_t = ImSaturate((mouse_abs_pos - g.SliderGrabClickOffset - slider_usable_pos_min) / slider_usable_sz); if (axis == ImGuiAxis_Y) clicked_t = 1.0f - clicked_t; set_new_value = true; } } else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad) { if (g.ActiveIdIsJustActivated) { g.SliderCurrentAccum = 0.0f; // Reset any stored nav delta upon activation g.SliderCurrentAccumDirty = false; } float input_delta = (axis == ImGuiAxis_X) ? GetNavTweakPressedAmount(axis) : -GetNavTweakPressedAmount(axis); if (input_delta != 0.0f) { const bool tweak_slow = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakSlow : ImGuiKey_NavKeyboardTweakSlow); const bool tweak_fast = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakFast : ImGuiKey_NavKeyboardTweakFast); const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0; if (decimal_precision > 0) { input_delta /= 100.0f; // Gamepad/keyboard tweak speeds in % of slider bounds if (tweak_slow) input_delta /= 10.0f; } else { if ((v_range_f >= -100.0f && v_range_f <= 100.0f && v_range_f != 0.0f) || tweak_slow) input_delta = ((input_delta < 0.0f) ? -1.0f : +1.0f) / v_range_f; // Gamepad/keyboard tweak speeds in integer steps else input_delta /= 100.0f; } if (tweak_fast) input_delta *= 10.0f; g.SliderCurrentAccum += input_delta; g.SliderCurrentAccumDirty = true; } float delta = g.SliderCurrentAccum; if (g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated) { ClearActiveID(); } else if (g.SliderCurrentAccumDirty) { clicked_t = ScaleRatioFromValueT(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); if ((clicked_t >= 1.0f && delta > 0.0f) || (clicked_t <= 0.0f && delta < 0.0f)) // This is to avoid applying the saturation when already past the limits { set_new_value = false; g.SliderCurrentAccum = 0.0f; // If pushing up against the limits, don't continue to accumulate } else { set_new_value = true; float old_clicked_t = clicked_t; clicked_t = ImSaturate(clicked_t + delta); // Calculate what our "new" clicked_t will be, and thus how far we actually moved the slider, and subtract this from the accumulator TYPE v_new = ScaleValueFromRatioT(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); if (is_floating_point && !(flags & ImGuiSliderFlags_NoRoundToFormat)) v_new = RoundScalarWithFormatT(format, data_type, v_new); float new_clicked_t = ScaleRatioFromValueT(data_type, v_new, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); if (delta > 0) g.SliderCurrentAccum -= ImMin(new_clicked_t - old_clicked_t, delta); else g.SliderCurrentAccum -= ImMax(new_clicked_t - old_clicked_t, delta); } g.SliderCurrentAccumDirty = false; } } if (set_new_value) if ((g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly)) set_new_value = false; if (set_new_value) { TYPE v_new = ScaleValueFromRatioT(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); // Round to user desired precision based on format string if (is_floating_point && !(flags & ImGuiSliderFlags_NoRoundToFormat)) v_new = RoundScalarWithFormatT(format, data_type, v_new); // Apply result if (*v != v_new) { *v = v_new; value_changed = true; } } } if (slider_sz < 1.0f) { *out_grab_bb = ImRect(bb.Min, bb.Min); } else { // Output grab position so it can be displayed by the caller float grab_t = ScaleRatioFromValueT(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize); if (axis == ImGuiAxis_Y) grab_t = 1.0f - grab_t; const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); if (axis == ImGuiAxis_X) *out_grab_bb = ImRect(grab_pos - grab_sz * 0.5f, bb.Min.y + grab_padding, grab_pos + grab_sz * 0.5f, bb.Max.y - grab_padding); else *out_grab_bb = ImRect(bb.Min.x + grab_padding, grab_pos - grab_sz * 0.5f, bb.Max.x - grab_padding, grab_pos + grab_sz * 0.5f); } return value_changed; } // For 32-bit and larger types, slider bounds are limited to half the natural type range. // So e.g. an integer Slider between INT_MAX-10 and INT_MAX will fail, but an integer Slider between INT_MAX/2-10 and INT_MAX/2 will be ok. // It would be possible to lift that limitation with some work but it doesn't seem to be worth it for sliders. bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, void* p_v, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb) { // Read imgui.cpp "API BREAKING CHANGES" section for 1.78 if you hit this assert. IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flag! Has the 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead."); switch (data_type) { case ImGuiDataType_S8: { ImS32 v32 = (ImS32)*(ImS8*)p_v; bool r = SliderBehaviorT(bb, id, ImGuiDataType_S32, &v32, *(const ImS8*)p_min, *(const ImS8*)p_max, format, flags, out_grab_bb); if (r) *(ImS8*)p_v = (ImS8)v32; return r; } case ImGuiDataType_U8: { ImU32 v32 = (ImU32)*(ImU8*)p_v; bool r = SliderBehaviorT(bb, id, ImGuiDataType_U32, &v32, *(const ImU8*)p_min, *(const ImU8*)p_max, format, flags, out_grab_bb); if (r) *(ImU8*)p_v = (ImU8)v32; return r; } case ImGuiDataType_S16: { ImS32 v32 = (ImS32)*(ImS16*)p_v; bool r = SliderBehaviorT(bb, id, ImGuiDataType_S32, &v32, *(const ImS16*)p_min, *(const ImS16*)p_max, format, flags, out_grab_bb); if (r) *(ImS16*)p_v = (ImS16)v32; return r; } case ImGuiDataType_U16: { ImU32 v32 = (ImU32)*(ImU16*)p_v; bool r = SliderBehaviorT(bb, id, ImGuiDataType_U32, &v32, *(const ImU16*)p_min, *(const ImU16*)p_max, format, flags, out_grab_bb); if (r) *(ImU16*)p_v = (ImU16)v32; return r; } case ImGuiDataType_S32: IM_ASSERT(*(const ImS32*)p_min >= IM_S32_MIN / 2 && *(const ImS32*)p_max <= IM_S32_MAX / 2); return SliderBehaviorT(bb, id, data_type, (ImS32*)p_v, *(const ImS32*)p_min, *(const ImS32*)p_max, format, flags, out_grab_bb); case ImGuiDataType_U32: IM_ASSERT(*(const ImU32*)p_max <= IM_U32_MAX / 2); return SliderBehaviorT(bb, id, data_type, (ImU32*)p_v, *(const ImU32*)p_min, *(const ImU32*)p_max, format, flags, out_grab_bb); case ImGuiDataType_S64: IM_ASSERT(*(const ImS64*)p_min >= IM_S64_MIN / 2 && *(const ImS64*)p_max <= IM_S64_MAX / 2); return SliderBehaviorT(bb, id, data_type, (ImS64*)p_v, *(const ImS64*)p_min, *(const ImS64*)p_max, format, flags, out_grab_bb); case ImGuiDataType_U64: IM_ASSERT(*(const ImU64*)p_max <= IM_U64_MAX / 2); return SliderBehaviorT(bb, id, data_type, (ImU64*)p_v, *(const ImU64*)p_min, *(const ImU64*)p_max, format, flags, out_grab_bb); case ImGuiDataType_Float: IM_ASSERT(*(const float*)p_min >= -FLT_MAX / 2.0f && *(const float*)p_max <= FLT_MAX / 2.0f); return SliderBehaviorT(bb, id, data_type, (float*)p_v, *(const float*)p_min, *(const float*)p_max, format, flags, out_grab_bb); case ImGuiDataType_Double: IM_ASSERT(*(const double*)p_min >= -DBL_MAX / 2.0f && *(const double*)p_max <= DBL_MAX / 2.0f); return SliderBehaviorT(bb, id, data_type, (double*)p_v, *(const double*)p_min, *(const double*)p_max, format, flags, out_grab_bb); case ImGuiDataType_COUNT: break; } IM_ASSERT(0); return false; } // Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a slider, they are all required. // Read code of e.g. SliderFloat(), SliderInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); const float w = CalcItemWidth(); const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0; ItemSize(total_bb, style.FramePadding.y); if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemFlags_Inputable : 0)) return false; // Default format string when passing NULL if (format == NULL) format = DataTypeGetInfo(data_type)->PrintFmt; const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags); bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); if (!temp_input_is_active) { // Tabbing or CTRL-clicking on Slider turns it into an input box const bool clicked = hovered && IsMouseClicked(0, id); const bool make_active = (clicked || g.NavActivateId == id); if (make_active && clicked) SetKeyOwner(ImGuiKey_MouseLeft, id); if (make_active && temp_input_allowed) if ((clicked && g.IO.KeyCtrl) || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput))) temp_input_is_active = true; if (make_active && !temp_input_is_active) { SetActiveID(id, window); SetFocusID(id, window); FocusWindow(window); g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); } } if (temp_input_is_active) { // Only clamp CTRL+Click input when ImGuiSliderFlags_AlwaysClamp is set const bool is_clamp_input = (flags & ImGuiSliderFlags_AlwaysClamp) != 0; return TempInputScalar(frame_bb, id, label, data_type, p_data, format, is_clamp_input ? p_min : NULL, is_clamp_input ? p_max : NULL); } // Draw frame const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding); // Slider behavior ImRect grab_bb; const bool value_changed = SliderBehavior(frame_bb, id, data_type, p_data, p_min, p_max, format, flags, &grab_bb); if (value_changed) MarkItemEdited(id); // Render grab if (grab_bb.Max.x > grab_bb.Min.x) window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. char value_buf[64]; const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format); if (g.LogEnabled) LogSetNextTextDecoration("{", "}"); RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f)); if (label_size.x > 0.0f) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | (temp_input_allowed ? ImGuiItemStatusFlags_Inputable : 0)); return value_changed; } // Add multiple sliders on 1 line for compact edition of multiple components bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; bool value_changed = false; BeginGroup(); PushID(label); PushMultiItemsWidths(components, CalcItemWidth()); size_t type_size = GDataTypeInfo[data_type].Size; for (int i = 0; i < components; i++) { PushID(i); if (i > 0) SameLine(0, g.Style.ItemInnerSpacing.x); value_changed |= SliderScalar("", data_type, v, v_min, v_max, format, flags); PopID(); PopItemWidth(); v = (void*)((char*)v + type_size); } PopID(); const char* label_end = FindRenderedTextEnd(label); if (label != label_end) { SameLine(0, g.Style.ItemInnerSpacing.x); TextEx(label, label_end); } EndGroup(); return value_changed; } bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return SliderScalar(label, ImGuiDataType_Float, v, &v_min, &v_max, format, flags); } bool ImGui::SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_Float, v, 2, &v_min, &v_max, format, flags); } bool ImGui::SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_Float, v, 3, &v_min, &v_max, format, flags); } bool ImGui::SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_Float, v, 4, &v_min, &v_max, format, flags); } bool ImGui::SliderAngle(const char* label, float* v_rad, float v_degrees_min, float v_degrees_max, const char* format, ImGuiSliderFlags flags) { if (format == NULL) format = "%.0f deg"; float v_deg = (*v_rad) * 360.0f / (2 * IM_PI); bool value_changed = SliderFloat(label, &v_deg, v_degrees_min, v_degrees_max, format, flags); *v_rad = v_deg * (2 * IM_PI) / 360.0f; return value_changed; } bool ImGui::SliderInt(const char* label, int* v, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return SliderScalar(label, ImGuiDataType_S32, v, &v_min, &v_max, format, flags); } bool ImGui::SliderInt2(const char* label, int v[2], int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_S32, v, 2, &v_min, &v_max, format, flags); } bool ImGui::SliderInt3(const char* label, int v[3], int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_S32, v, 3, &v_min, &v_max, format, flags); } bool ImGui::SliderInt4(const char* label, int v[4], int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return SliderScalarN(label, ImGuiDataType_S32, v, 4, &v_min, &v_max, format, flags); } bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size); const ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); ItemSize(bb, style.FramePadding.y); if (!ItemAdd(frame_bb, id)) return false; // Default format string when passing NULL if (format == NULL) format = DataTypeGetInfo(data_type)->PrintFmt; const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags); const bool clicked = hovered && IsMouseClicked(0, id); if (clicked || g.NavActivateId == id) { if (clicked) SetKeyOwner(ImGuiKey_MouseLeft, id); SetActiveID(id, window); SetFocusID(id, window); FocusWindow(window); g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); } // Draw frame const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding); // Slider behavior ImRect grab_bb; const bool value_changed = SliderBehavior(frame_bb, id, data_type, p_data, p_min, p_max, format, flags | ImGuiSliderFlags_Vertical, &grab_bb); if (value_changed) MarkItemEdited(id); // Render grab if (grab_bb.Max.y > grab_bb.Min.y) window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding); // Display value using user-provided display format so user can add prefix/suffix/decorations to the value. // For the vertical slider we allow centered text to overlap the frame padding char value_buf[64]; const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_ARRAYSIZE(value_buf), data_type, p_data, format); RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.0f)); if (label_size.x > 0.0f) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); return value_changed; } bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float v_min, float v_max, const char* format, ImGuiSliderFlags flags) { return VSliderScalar(label, size, ImGuiDataType_Float, v, &v_min, &v_max, format, flags); } bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format, ImGuiSliderFlags flags) { return VSliderScalar(label, size, ImGuiDataType_S32, v, &v_min, &v_max, format, flags); } //------------------------------------------------------------------------- // [SECTION] Widgets: InputScalar, InputFloat, InputInt, etc. //------------------------------------------------------------------------- // - ImParseFormatFindStart() [Internal] // - ImParseFormatFindEnd() [Internal] // - ImParseFormatTrimDecorations() [Internal] // - ImParseFormatSanitizeForPrinting() [Internal] // - ImParseFormatSanitizeForScanning() [Internal] // - ImParseFormatPrecision() [Internal] // - TempInputTextScalar() [Internal] // - InputScalar() // - InputScalarN() // - InputFloat() // - InputFloat2() // - InputFloat3() // - InputFloat4() // - InputInt() // - InputInt2() // - InputInt3() // - InputInt4() // - InputDouble() //------------------------------------------------------------------------- // We don't use strchr() because our strings are usually very short and often start with '%' const char* ImParseFormatFindStart(const char* fmt) { while (char c = fmt[0]) { if (c == '%' && fmt[1] != '%') return fmt; else if (c == '%') fmt++; fmt++; } return fmt; } const char* ImParseFormatFindEnd(const char* fmt) { // Printf/scanf types modifiers: I/L/h/j/l/t/w/z. Other uppercase letters qualify as types aka end of the format. if (fmt[0] != '%') return fmt; const unsigned int ignored_uppercase_mask = (1 << ('I'-'A')) | (1 << ('L'-'A')); const unsigned int ignored_lowercase_mask = (1 << ('h'-'a')) | (1 << ('j'-'a')) | (1 << ('l'-'a')) | (1 << ('t'-'a')) | (1 << ('w'-'a')) | (1 << ('z'-'a')); for (char c; (c = *fmt) != 0; fmt++) { if (c >= 'A' && c <= 'Z' && ((1 << (c - 'A')) & ignored_uppercase_mask) == 0) return fmt + 1; if (c >= 'a' && c <= 'z' && ((1 << (c - 'a')) & ignored_lowercase_mask) == 0) return fmt + 1; } return fmt; } // Extract the format out of a format string with leading or trailing decorations // fmt = "blah blah" -> return "" // fmt = "%.3f" -> return fmt // fmt = "hello %.3f" -> return fmt + 6 // fmt = "%.3f hello" -> return buf written with "%.3f" const char* ImParseFormatTrimDecorations(const char* fmt, char* buf, size_t buf_size) { const char* fmt_start = ImParseFormatFindStart(fmt); if (fmt_start[0] != '%') return ""; const char* fmt_end = ImParseFormatFindEnd(fmt_start); if (fmt_end[0] == 0) // If we only have leading decoration, we don't need to copy the data. return fmt_start; ImStrncpy(buf, fmt_start, ImMin((size_t)(fmt_end - fmt_start) + 1, buf_size)); return buf; } // Sanitize format // - Zero terminate so extra characters after format (e.g. "%f123") don't confuse atof/atoi // - stb_sprintf.h supports several new modifiers which format numbers in a way that also makes them incompatible atof/atoi. void ImParseFormatSanitizeForPrinting(const char* fmt_in, char* fmt_out, size_t fmt_out_size) { const char* fmt_end = ImParseFormatFindEnd(fmt_in); IM_UNUSED(fmt_out_size); IM_ASSERT((size_t)(fmt_end - fmt_in + 1) < fmt_out_size); // Format is too long, let us know if this happens to you! while (fmt_in < fmt_end) { char c = *fmt_in++; if (c != '\'' && c != '$' && c != '_') // Custom flags provided by stb_sprintf.h. POSIX 2008 also supports '. *(fmt_out++) = c; } *fmt_out = 0; // Zero-terminate } // - For scanning we need to remove all width and precision fields and flags "%+3.7f" -> "%f". BUT don't strip types like "%I64d" which includes digits. ! "%07I64d" -> "%I64d" const char* ImParseFormatSanitizeForScanning(const char* fmt_in, char* fmt_out, size_t fmt_out_size) { const char* fmt_end = ImParseFormatFindEnd(fmt_in); const char* fmt_out_begin = fmt_out; IM_UNUSED(fmt_out_size); IM_ASSERT((size_t)(fmt_end - fmt_in + 1) < fmt_out_size); // Format is too long, let us know if this happens to you! bool has_type = false; while (fmt_in < fmt_end) { char c = *fmt_in++; if (!has_type && ((c >= '0' && c <= '9') || c == '.' || c == '+' || c == '#')) continue; has_type |= ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); // Stop skipping digits if (c != '\'' && c != '$' && c != '_') // Custom flags provided by stb_sprintf.h. POSIX 2008 also supports '. *(fmt_out++) = c; } *fmt_out = 0; // Zero-terminate return fmt_out_begin; } template static const char* ImAtoi(const char* src, TYPE* output) { int negative = 0; if (*src == '-') { negative = 1; src++; } if (*src == '+') { src++; } TYPE v = 0; while (*src >= '0' && *src <= '9') v = (v * 10) + (*src++ - '0'); *output = negative ? -v : v; return src; } // Parse display precision back from the display format string // FIXME: This is still used by some navigation code path to infer a minimum tweak step, but we should aim to rework widgets so it isn't needed. int ImParseFormatPrecision(const char* fmt, int default_precision) { fmt = ImParseFormatFindStart(fmt); if (fmt[0] != '%') return default_precision; fmt++; while (*fmt >= '0' && *fmt <= '9') fmt++; int precision = INT_MAX; if (*fmt == '.') { fmt = ImAtoi(fmt + 1, &precision); if (precision < 0 || precision > 99) precision = default_precision; } if (*fmt == 'e' || *fmt == 'E') // Maximum precision with scientific notation precision = -1; if ((*fmt == 'g' || *fmt == 'G') && precision == INT_MAX) precision = -1; return (precision == INT_MAX) ? default_precision : precision; } // Create text input in place of another active widget (e.g. used when doing a CTRL+Click on drag/slider widgets) // FIXME: Facilitate using this in variety of other situations. bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags) { // On the first frame, g.TempInputTextId == 0, then on subsequent frames it becomes == id. // We clear ActiveID on the first frame to allow the InputText() taking it back. ImGuiContext& g = *GImGui; const bool init = (g.TempInputId != id); if (init) ClearActiveID(); g.CurrentWindow->DC.CursorPos = bb.Min; bool value_changed = InputTextEx(label, NULL, buf, buf_size, bb.GetSize(), flags | ImGuiInputTextFlags_MergedItem); if (init) { // First frame we started displaying the InputText widget, we expect it to take the active id. IM_ASSERT(g.ActiveId == id); g.TempInputId = g.ActiveId; } return value_changed; } // Note that Drag/Slider functions are only forwarding the min/max values clamping values if the ImGuiSliderFlags_AlwaysClamp flag is set! // This is intended: this way we allow CTRL+Click manual input to set a value out of bounds, for maximum flexibility. // However this may not be ideal for all uses, as some user code may break on out of bound values. bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min, const void* p_clamp_max) { // FIXME: May need to clarify display behavior if format doesn't contain %. // "%d" -> "%d" / "There are %d items" -> "%d" / "items" -> "%d" (fallback). Also see #6405 const ImGuiDataTypeInfo* type_info = DataTypeGetInfo(data_type); char fmt_buf[32]; char data_buf[32]; format = ImParseFormatTrimDecorations(format, fmt_buf, IM_ARRAYSIZE(fmt_buf)); if (format[0] == 0) format = type_info->PrintFmt; DataTypeFormatString(data_buf, IM_ARRAYSIZE(data_buf), data_type, p_data, format); ImStrTrimBlanks(data_buf); ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited; bool value_changed = false; if (TempInputText(bb, id, label, data_buf, IM_ARRAYSIZE(data_buf), flags)) { // Backup old value size_t data_type_size = type_info->Size; ImGuiDataTypeTempStorage data_backup; memcpy(&data_backup, p_data, data_type_size); // Apply new value (or operations) then clamp DataTypeApplyFromText(data_buf, data_type, p_data, format); if (p_clamp_min || p_clamp_max) { if (p_clamp_min && p_clamp_max && DataTypeCompare(data_type, p_clamp_min, p_clamp_max) > 0) ImSwap(p_clamp_min, p_clamp_max); DataTypeClamp(data_type, p_data, p_clamp_min, p_clamp_max); } // Only mark as edited if new value is different value_changed = memcmp(&data_backup, p_data, data_type_size) != 0; if (value_changed) MarkItemEdited(id); } return value_changed; } // Note: p_data, p_step, p_step_fast are _pointers_ to a memory address holding the data. For an Input widget, p_step and p_step_fast are optional. // Read code of e.g. InputFloat(), InputInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly. bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; ImGuiStyle& style = g.Style; if (format == NULL) format = DataTypeGetInfo(data_type)->PrintFmt; char buf[64]; DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format); flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string. bool value_changed = false; if (p_step == NULL) { if (InputText(label, buf, IM_ARRAYSIZE(buf), flags)) value_changed = DataTypeApplyFromText(buf, data_type, p_data, format); } else { const float button_size = GetFrameHeight(); BeginGroup(); // The only purpose of the group here is to allow the caller to query item data e.g. IsItemActive() PushID(label); SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2)); if (InputText("", buf, IM_ARRAYSIZE(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view value_changed = DataTypeApplyFromText(buf, data_type, p_data, format); IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Inputable); // Step buttons const ImVec2 backup_frame_padding = style.FramePadding; style.FramePadding.x = style.FramePadding.y; ImGuiButtonFlags button_flags = ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups; if (flags & ImGuiInputTextFlags_ReadOnly) BeginDisabled(); SameLine(0, style.ItemInnerSpacing.x); if (ButtonEx("-", ImVec2(button_size, button_size), button_flags)) { DataTypeApplyOp(data_type, '-', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step); value_changed = true; } SameLine(0, style.ItemInnerSpacing.x); if (ButtonEx("+", ImVec2(button_size, button_size), button_flags)) { DataTypeApplyOp(data_type, '+', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step); value_changed = true; } if (flags & ImGuiInputTextFlags_ReadOnly) EndDisabled(); const char* label_end = FindRenderedTextEnd(label); if (label != label_end) { SameLine(0, style.ItemInnerSpacing.x); TextEx(label, label_end); } style.FramePadding = backup_frame_padding; PopID(); EndGroup(); } if (value_changed) MarkItemEdited(g.LastItemData.ID); return value_changed; } bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_step, const void* p_step_fast, const char* format, ImGuiInputTextFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; bool value_changed = false; BeginGroup(); PushID(label); PushMultiItemsWidths(components, CalcItemWidth()); size_t type_size = GDataTypeInfo[data_type].Size; for (int i = 0; i < components; i++) { PushID(i); if (i > 0) SameLine(0, g.Style.ItemInnerSpacing.x); value_changed |= InputScalar("", data_type, p_data, p_step, p_step_fast, format, flags); PopID(); PopItemWidth(); p_data = (void*)((char*)p_data + type_size); } PopID(); const char* label_end = FindRenderedTextEnd(label); if (label != label_end) { SameLine(0.0f, g.Style.ItemInnerSpacing.x); TextEx(label, label_end); } EndGroup(); return value_changed; } bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, const char* format, ImGuiInputTextFlags flags) { return InputScalar(label, ImGuiDataType_Float, (void*)v, (void*)(step > 0.0f ? &step : NULL), (void*)(step_fast > 0.0f ? &step_fast : NULL), format, flags); } bool ImGui::InputFloat2(const char* label, float v[2], const char* format, ImGuiInputTextFlags flags) { return InputScalarN(label, ImGuiDataType_Float, v, 2, NULL, NULL, format, flags); } bool ImGui::InputFloat3(const char* label, float v[3], const char* format, ImGuiInputTextFlags flags) { return InputScalarN(label, ImGuiDataType_Float, v, 3, NULL, NULL, format, flags); } bool ImGui::InputFloat4(const char* label, float v[4], const char* format, ImGuiInputTextFlags flags) { return InputScalarN(label, ImGuiDataType_Float, v, 4, NULL, NULL, format, flags); } bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags flags) { // Hexadecimal input provided as a convenience but the flag name is awkward. Typically you'd use InputText() to parse your own data, if you want to handle prefixes. const char* format = (flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d"; return InputScalar(label, ImGuiDataType_S32, (void*)v, (void*)(step > 0 ? &step : NULL), (void*)(step_fast > 0 ? &step_fast : NULL), format, flags); } bool ImGui::InputInt2(const char* label, int v[2], ImGuiInputTextFlags flags) { return InputScalarN(label, ImGuiDataType_S32, v, 2, NULL, NULL, "%d", flags); } bool ImGui::InputInt3(const char* label, int v[3], ImGuiInputTextFlags flags) { return InputScalarN(label, ImGuiDataType_S32, v, 3, NULL, NULL, "%d", flags); } bool ImGui::InputInt4(const char* label, int v[4], ImGuiInputTextFlags flags) { return InputScalarN(label, ImGuiDataType_S32, v, 4, NULL, NULL, "%d", flags); } bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* format, ImGuiInputTextFlags flags) { return InputScalar(label, ImGuiDataType_Double, (void*)v, (void*)(step > 0.0 ? &step : NULL), (void*)(step_fast > 0.0 ? &step_fast : NULL), format, flags); } //------------------------------------------------------------------------- // [SECTION] Widgets: InputText, InputTextMultiline, InputTextWithHint //------------------------------------------------------------------------- // - InputText() // - InputTextWithHint() // - InputTextMultiline() // - InputTextGetCharInfo() [Internal] // - InputTextReindexLines() [Internal] // - InputTextReindexLinesRange() [Internal] // - InputTextEx() [Internal] // - DebugNodeInputTextState() [Internal] //------------------------------------------------------------------------- bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) { IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline() return InputTextEx(label, NULL, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data); } bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) { return InputTextEx(label, NULL, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data); } bool ImGui::InputTextWithHint(const char* label, const char* hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) { IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline() or InputTextEx() manually if you need multi-line + hint. return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data); } static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end) { int line_count = 0; const char* s = text_begin; while (char c = *s++) // We are only matching for \n so we can ignore UTF-8 decoding if (c == '\n') line_count++; s--; if (s[0] != '\n' && s[0] != '\r') line_count++; *out_text_end = s; return line_count; } static ImVec2 InputTextCalcTextSizeW(ImGuiContext* ctx, const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining, ImVec2* out_offset, bool stop_on_new_line) { ImGuiContext& g = *ctx; ImFont* font = g.Font; const float line_height = g.FontSize; const float scale = line_height / font->FontSize; ImVec2 text_size = ImVec2(0, 0); float line_width = 0.0f; const ImWchar* s = text_begin; while (s < text_end) { unsigned int c = (unsigned int)(*s++); if (c == '\n') { text_size.x = ImMax(text_size.x, line_width); text_size.y += line_height; line_width = 0.0f; if (stop_on_new_line) break; continue; } if (c == '\r') continue; const float char_width = font->GetCharAdvance((ImWchar)c) * scale; line_width += char_width; } if (text_size.x < line_width) text_size.x = line_width; if (out_offset) *out_offset = ImVec2(line_width, text_size.y + line_height); // offset allow for the possibility of sitting after a trailing \n if (line_width > 0 || text_size.y == 0.0f) // whereas size.y will ignore the trailing \n text_size.y += line_height; if (remaining) *remaining = s; return text_size; } // Wrapper for stb_textedit.h to edit text (our wrapper is for: statically sized buffer, single-line, wchar characters. InputText converts between UTF-8 and wchar) namespace ImStb { static int STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj) { return obj->CurLenW; } static ImWchar STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { IM_ASSERT(idx <= obj->CurLenW); return obj->TextW[idx]; } static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { ImWchar c = obj->TextW[line_start_idx + char_idx]; if (c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance(c) * (g.FontSize / g.Font->FontSize); } static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x200000 ? 0 : key; } static ImWchar STB_TEXTEDIT_NEWLINE = '\n'; static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx) { const ImWchar* text = obj->TextW.Data; const ImWchar* text_remaining = NULL; const ImVec2 size = InputTextCalcTextSizeW(obj->Ctx, text + line_start_idx, text + obj->CurLenW, &text_remaining, NULL, true); r->x0 = 0.0f; r->x1 = size.x; r->baseline_y_delta = size.y; r->ymin = 0.0f; r->ymax = size.y; r->num_chars = (int)(text_remaining - (text + line_start_idx)); } static bool is_separator(unsigned int c) { return c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|' || c=='\n' || c=='\r' || c=='.' || c=='!'; } static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx) { // When ImGuiInputTextFlags_Password is set, we don't want actions such as CTRL+Arrow to leak the fact that underlying data are blanks or separators. if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0) return 0; bool prev_white = ImCharIsBlankW(obj->TextW[idx - 1]); bool prev_separ = is_separator(obj->TextW[idx - 1]); bool curr_white = ImCharIsBlankW(obj->TextW[idx]); bool curr_separ = is_separator(obj->TextW[idx]); return ((prev_white || prev_separ) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ); } static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx) { if ((obj->Flags & ImGuiInputTextFlags_Password) || idx <= 0) return 0; bool prev_white = ImCharIsBlankW(obj->TextW[idx]); bool prev_separ = is_separator(obj->TextW[idx]); bool curr_white = ImCharIsBlankW(obj->TextW[idx - 1]); bool curr_separ = is_separator(obj->TextW[idx - 1]); return ((prev_white) && !(curr_separ || curr_white)) || (curr_separ && !prev_separ); } static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; } static int STB_TEXTEDIT_MOVEWORDRIGHT_MAC(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; } static int STB_TEXTEDIT_MOVEWORDRIGHT_WIN(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; } static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx) { ImGuiContext& g = *obj->Ctx; if (g.IO.ConfigMacOSXBehaviors) return STB_TEXTEDIT_MOVEWORDRIGHT_MAC(obj, idx); else return STB_TEXTEDIT_MOVEWORDRIGHT_WIN(obj, idx); } #define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h #define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_IMPL static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n) { ImWchar* dst = obj->TextW.Data + pos; // We maintain our buffer length in both UTF-8 and wchar formats obj->Edited = true; obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n); obj->CurLenW -= n; // Offset remaining text (FIXME-OPT: Use memmove) const ImWchar* src = obj->TextW.Data + pos + n; while (ImWchar c = *src++) *dst++ = c; *dst = '\0'; } static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const ImWchar* new_text, int new_text_len) { const bool is_resizable = (obj->Flags & ImGuiInputTextFlags_CallbackResize) != 0; const int text_len = obj->CurLenW; IM_ASSERT(pos <= text_len); const int new_text_len_utf8 = ImTextCountUtf8BytesFromStr(new_text, new_text + new_text_len); if (!is_resizable && (new_text_len_utf8 + obj->CurLenA + 1 > obj->BufCapacityA)) return false; // Grow internal buffer if needed if (new_text_len + text_len + 1 > obj->TextW.Size) { if (!is_resizable) return false; IM_ASSERT(text_len < obj->TextW.Size); obj->TextW.resize(text_len + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1); } ImWchar* text = obj->TextW.Data; if (pos != text_len) memmove(text + pos + new_text_len, text + pos, (size_t)(text_len - pos) * sizeof(ImWchar)); memcpy(text + pos, new_text, (size_t)new_text_len * sizeof(ImWchar)); obj->Edited = true; obj->CurLenW += new_text_len; obj->CurLenA += new_text_len_utf8; obj->TextW[obj->CurLenW] = '\0'; return true; } // We don't use an enum so we can build even with conflicting symbols (if another user of stb_textedit.h leak their STB_TEXTEDIT_K_* symbols) #define STB_TEXTEDIT_K_LEFT 0x200000 // keyboard input to move cursor left #define STB_TEXTEDIT_K_RIGHT 0x200001 // keyboard input to move cursor right #define STB_TEXTEDIT_K_UP 0x200002 // keyboard input to move cursor up #define STB_TEXTEDIT_K_DOWN 0x200003 // keyboard input to move cursor down #define STB_TEXTEDIT_K_LINESTART 0x200004 // keyboard input to move cursor to start of line #define STB_TEXTEDIT_K_LINEEND 0x200005 // keyboard input to move cursor to end of line #define STB_TEXTEDIT_K_TEXTSTART 0x200006 // keyboard input to move cursor to start of text #define STB_TEXTEDIT_K_TEXTEND 0x200007 // keyboard input to move cursor to end of text #define STB_TEXTEDIT_K_DELETE 0x200008 // keyboard input to delete selection or character under cursor #define STB_TEXTEDIT_K_BACKSPACE 0x200009 // keyboard input to delete selection or character left of cursor #define STB_TEXTEDIT_K_UNDO 0x20000A // keyboard input to perform undo #define STB_TEXTEDIT_K_REDO 0x20000B // keyboard input to perform redo #define STB_TEXTEDIT_K_WORDLEFT 0x20000C // keyboard input to move cursor left one word #define STB_TEXTEDIT_K_WORDRIGHT 0x20000D // keyboard input to move cursor right one word #define STB_TEXTEDIT_K_PGUP 0x20000E // keyboard input to move cursor up a page #define STB_TEXTEDIT_K_PGDOWN 0x20000F // keyboard input to move cursor down a page #define STB_TEXTEDIT_K_SHIFT 0x400000 #define IMSTB_TEXTEDIT_IMPLEMENTATION #define IMSTB_TEXTEDIT_memmove memmove #include "imstb_textedit.h" // stb_textedit internally allows for a single undo record to do addition and deletion, but somehow, calling // the stb_textedit_paste() function creates two separate records, so we perform it manually. (FIXME: Report to nothings/stb?) static void stb_textedit_replace(ImGuiInputTextState* str, STB_TexteditState* state, const IMSTB_TEXTEDIT_CHARTYPE* text, int text_len) { stb_text_makeundo_replace(str, state, 0, str->CurLenW, text_len); ImStb::STB_TEXTEDIT_DELETECHARS(str, 0, str->CurLenW); state->cursor = state->select_start = state->select_end = 0; if (text_len <= 0) return; if (ImStb::STB_TEXTEDIT_INSERTCHARS(str, 0, text, text_len)) { state->cursor = state->select_start = state->select_end = text_len; state->has_preferred_x = 0; return; } IM_ASSERT(0); // Failed to insert character, normally shouldn't happen because of how we currently use stb_textedit_replace() } } // namespace ImStb void ImGuiInputTextState::OnKeyPressed(int key) { stb_textedit_key(this, &Stb, key); CursorFollow = true; CursorAnimReset(); } ImGuiInputTextCallbackData::ImGuiInputTextCallbackData() { memset(this, 0, sizeof(*this)); } // Public API to manipulate UTF-8 text // We expose UTF-8 to the user (unlike the STB_TEXTEDIT_* functions which are manipulating wchar) // FIXME: The existence of this rarely exercised code path is a bit of a nuisance. void ImGuiInputTextCallbackData::DeleteChars(int pos, int bytes_count) { IM_ASSERT(pos + bytes_count <= BufTextLen); char* dst = Buf + pos; const char* src = Buf + pos + bytes_count; while (char c = *src++) *dst++ = c; *dst = '\0'; if (CursorPos >= pos + bytes_count) CursorPos -= bytes_count; else if (CursorPos >= pos) CursorPos = pos; SelectionStart = SelectionEnd = CursorPos; BufDirty = true; BufTextLen -= bytes_count; } void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, const char* new_text_end) { // Accept null ranges if (new_text == new_text_end) return; const bool is_resizable = (Flags & ImGuiInputTextFlags_CallbackResize) != 0; const int new_text_len = new_text_end ? (int)(new_text_end - new_text) : (int)strlen(new_text); if (new_text_len + BufTextLen >= BufSize) { if (!is_resizable) return; // Contrary to STB_TEXTEDIT_INSERTCHARS() this is working in the UTF8 buffer, hence the mildly similar code (until we remove the U16 buffer altogether!) ImGuiContext& g = *Ctx; ImGuiInputTextState* edit_state = &g.InputTextState; IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID); IM_ASSERT(Buf == edit_state->TextA.Data); int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1; edit_state->TextA.reserve(new_buf_size + 1); Buf = edit_state->TextA.Data; BufSize = edit_state->BufCapacityA = new_buf_size; } if (BufTextLen != pos) memmove(Buf + pos + new_text_len, Buf + pos, (size_t)(BufTextLen - pos)); memcpy(Buf + pos, new_text, (size_t)new_text_len * sizeof(char)); Buf[BufTextLen + new_text_len] = '\0'; if (CursorPos >= pos) CursorPos += new_text_len; SelectionStart = SelectionEnd = CursorPos; BufDirty = true; BufTextLen += new_text_len; } // Return false to discard a character. static bool InputTextFilterCharacter(ImGuiContext* ctx, unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, ImGuiInputSource input_source) { IM_ASSERT(input_source == ImGuiInputSource_Keyboard || input_source == ImGuiInputSource_Clipboard); unsigned int c = *p_char; // Filter non-printable (NB: isprint is unreliable! see #2467) bool apply_named_filters = true; if (c < 0x20) { bool pass = false; pass |= (c == '\n') && (flags & ImGuiInputTextFlags_Multiline) != 0; // Note that an Enter KEY will emit \r and be ignored (we poll for KEY in InputText() code) pass |= (c == '\t') && (flags & ImGuiInputTextFlags_AllowTabInput) != 0; if (!pass) return false; apply_named_filters = false; // Override named filters below so newline and tabs can still be inserted. } if (input_source != ImGuiInputSource_Clipboard) { // We ignore Ascii representation of delete (emitted from Backspace on OSX, see #2578, #2817) if (c == 127) return false; // Filter private Unicode range. GLFW on OSX seems to send private characters for special keys like arrow keys (FIXME) if (c >= 0xE000 && c <= 0xF8FF) return false; } // Filter Unicode ranges we are not handling in this build if (c > IM_UNICODE_CODEPOINT_MAX) return false; // Generic named filters if (apply_named_filters && (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific))) { // The libc allows overriding locale, with e.g. 'setlocale(LC_NUMERIC, "de_DE.UTF-8");' which affect the output/input of printf/scanf to use e.g. ',' instead of '.'. // The standard mandate that programs starts in the "C" locale where the decimal point is '.'. // We don't really intend to provide widespread support for it, but out of empathy for people stuck with using odd API, we support the bare minimum aka overriding the decimal point. // Change the default decimal_point with: // ImGui::GetIO()->PlatformLocaleDecimalPoint = *localeconv()->decimal_point; // Users of non-default decimal point (in particular ',') may be affected by word-selection logic (is_word_boundary_from_right/is_word_boundary_from_left) functions. ImGuiContext& g = *ctx; const unsigned c_decimal_point = (unsigned int)g.IO.PlatformLocaleDecimalPoint; if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsScientific)) if (c == '.' || c == ',') c = c_decimal_point; // Full-width -> half-width conversion for numeric fields (https://en.wikipedia.org/wiki/Halfwidth_and_Fullwidth_Forms_(Unicode_block) // While this is mostly convenient, this has the side-effect for uninformed users accidentally inputting full-width characters that they may // scratch their head as to why it works in numerical fields vs in generic text fields it would require support in the font. if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsScientific | ImGuiInputTextFlags_CharsHexadecimal)) if (c >= 0xFF01 && c <= 0xFF5E) c = c - 0xFF01 + 0x21; // Allow 0-9 . - + * / if (flags & ImGuiInputTextFlags_CharsDecimal) if (!(c >= '0' && c <= '9') && (c != c_decimal_point) && (c != '-') && (c != '+') && (c != '*') && (c != '/')) return false; // Allow 0-9 . - + * / e E if (flags & ImGuiInputTextFlags_CharsScientific) if (!(c >= '0' && c <= '9') && (c != c_decimal_point) && (c != '-') && (c != '+') && (c != '*') && (c != '/') && (c != 'e') && (c != 'E')) return false; // Allow 0-9 a-F A-F if (flags & ImGuiInputTextFlags_CharsHexadecimal) if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F')) return false; // Turn a-z into A-Z if (flags & ImGuiInputTextFlags_CharsUppercase) if (c >= 'a' && c <= 'z') c += (unsigned int)('A' - 'a'); if (flags & ImGuiInputTextFlags_CharsNoBlank) if (ImCharIsBlankW(c)) return false; *p_char = c; } // Custom callback filter if (flags & ImGuiInputTextFlags_CallbackCharFilter) { ImGuiContext& g = *GImGui; ImGuiInputTextCallbackData callback_data; callback_data.Ctx = &g; callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter; callback_data.EventChar = (ImWchar)c; callback_data.Flags = flags; callback_data.UserData = user_data; if (callback(&callback_data) != 0) return false; *p_char = callback_data.EventChar; if (!callback_data.EventChar) return false; } return true; } // Find the shortest single replacement we can make to get the new text from the old text. // Important: needs to be run before TextW is rewritten with the new characters because calling STB_TEXTEDIT_GETCHAR() at the end. // FIXME: Ideally we should transition toward (1) making InsertChars()/DeleteChars() update undo-stack (2) discourage (and keep reconcile) or obsolete (and remove reconcile) accessing buffer directly. static void InputTextReconcileUndoStateAfterUserCallback(ImGuiInputTextState* state, const char* new_buf_a, int new_length_a) { ImGuiContext& g = *GImGui; const ImWchar* old_buf = state->TextW.Data; const int old_length = state->CurLenW; const int new_length = ImTextCountCharsFromUtf8(new_buf_a, new_buf_a + new_length_a); g.TempBuffer.reserve_discard((new_length + 1) * sizeof(ImWchar)); ImWchar* new_buf = (ImWchar*)(void*)g.TempBuffer.Data; ImTextStrFromUtf8(new_buf, new_length + 1, new_buf_a, new_buf_a + new_length_a); const int shorter_length = ImMin(old_length, new_length); int first_diff; for (first_diff = 0; first_diff < shorter_length; first_diff++) if (old_buf[first_diff] != new_buf[first_diff]) break; if (first_diff == old_length && first_diff == new_length) return; int old_last_diff = old_length - 1; int new_last_diff = new_length - 1; for (; old_last_diff >= first_diff && new_last_diff >= first_diff; old_last_diff--, new_last_diff--) if (old_buf[old_last_diff] != new_buf[new_last_diff]) break; const int insert_len = new_last_diff - first_diff + 1; const int delete_len = old_last_diff - first_diff + 1; if (insert_len > 0 || delete_len > 0) if (IMSTB_TEXTEDIT_CHARTYPE* p = stb_text_createundo(&state->Stb.undostate, first_diff, delete_len, insert_len)) for (int i = 0; i < delete_len; i++) p[i] = ImStb::STB_TEXTEDIT_GETCHAR(state, first_diff + i); } // As InputText() retain textual data and we currently provide a path for user to not retain it (via local variables) // we need some form of hook to reapply data back to user buffer on deactivation frame. (#4714) // It would be more desirable that we discourage users from taking advantage of the "user not retaining data" trick, // but that more likely be attractive when we do have _NoLiveEdit flag available. void ImGui::InputTextDeactivateHook(ImGuiID id) { ImGuiContext& g = *GImGui; ImGuiInputTextState* state = &g.InputTextState; if (id == 0 || state->ID != id) return; g.InputTextDeactivatedState.ID = state->ID; if (state->Flags & ImGuiInputTextFlags_ReadOnly) { g.InputTextDeactivatedState.TextA.resize(0); // In theory this data won't be used, but clear to be neat. } else { IM_ASSERT(state->TextA.Data != 0); g.InputTextDeactivatedState.TextA.resize(state->CurLenA + 1); memcpy(g.InputTextDeactivatedState.TextA.Data, state->TextA.Data, state->CurLenA + 1); } } // Edit a string of text // - buf_size account for the zero-terminator, so a buf_size of 6 can hold "Hello" but not "Hello!". // This is so we can easily call InputText() on static arrays using ARRAYSIZE() and to match // Note that in std::string world, capacity() would omit 1 byte used by the zero-terminator. // - When active, hold on a privately held copy of the text (and apply back to 'buf'). So changing 'buf' while the InputText is active has no effect. // - If you want to use ImGui::InputText() with std::string, see misc/cpp/imgui_stdlib.h // (FIXME: Rather confusing and messy function, among the worse part of our codebase, expecting to rewrite a V2 at some point.. Partly because we are // doing UTF8 > U16 > UTF8 conversions on the go to easily interface with stb_textedit. Ideally should stay in UTF-8 all the time. See https://github.com/nothings/stb/issues/188) bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* callback_user_data) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; IM_ASSERT(buf != NULL && buf_size >= 0); IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackHistory) && (flags & ImGuiInputTextFlags_Multiline))); // Can't use both together (they both use up/down keys) IM_ASSERT(!((flags & ImGuiInputTextFlags_CallbackCompletion) && (flags & ImGuiInputTextFlags_AllowTabInput))); // Can't use both together (they both use tab key) ImGuiContext& g = *GImGui; ImGuiIO& io = g.IO; const ImGuiStyle& style = g.Style; const bool RENDER_SELECTION_WHEN_INACTIVE = false; const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0; if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope (including the scrollbar) BeginGroup(); const ImGuiID id = window->GetID(label); const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? g.FontSize * 8.0f : label_size.y) + style.FramePadding.y * 2.0f); // Arbitrary default of 8 lines high for multi-line const ImVec2 total_size = ImVec2(frame_size.x + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), frame_size.y); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); const ImRect total_bb(frame_bb.Min, frame_bb.Min + total_size); ImGuiWindow* draw_window = window; ImVec2 inner_size = frame_size; ImGuiLastItemData item_data_backup; if (is_multiline) { ImVec2 backup_pos = window->DC.CursorPos; ItemSize(total_bb, style.FramePadding.y); if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable)) { EndGroup(); return false; } item_data_backup = g.LastItemData; window->DC.CursorPos = backup_pos; // Prevent NavActivation from Tabbing when our widget accepts Tab inputs: this allows cycling through widgets without stopping. if (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_FromTabbing) && (flags & ImGuiInputTextFlags_AllowTabInput)) g.NavActivateId = 0; // Prevent NavActivate reactivating in BeginChild() when we are already active. const ImGuiID backup_activate_id = g.NavActivateId; if (g.ActiveId == id) // Prevent reactivation g.NavActivateId = 0; // We reproduce the contents of BeginChildFrame() in order to provide 'label' so our window internal data are easier to read/debug. PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]); PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding); PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize); PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); // Ensure no clip rect so mouse hover can reach FramePadding edges bool child_visible = BeginChildEx(label, id, frame_bb.GetSize(), true, ImGuiWindowFlags_NoMove); g.NavActivateId = backup_activate_id; PopStyleVar(3); PopStyleColor(); if (!child_visible) { EndChild(); EndGroup(); return false; } draw_window = g.CurrentWindow; // Child window draw_window->DC.NavLayersActiveMaskNext |= (1 << draw_window->DC.NavLayerCurrent); // This is to ensure that EndChild() will display a navigation highlight so we can "enter" into it. draw_window->DC.CursorPos += style.FramePadding; inner_size.x -= draw_window->ScrollbarSizes.x; } else { // Support for internal ImGuiInputTextFlags_MergedItem flag, which could be redesigned as an ItemFlags if needed (with test performed in ItemAdd) ItemSize(total_bb, style.FramePadding.y); if (!(flags & ImGuiInputTextFlags_MergedItem)) if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable)) return false; } const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags); if (hovered) g.MouseCursor = ImGuiMouseCursor_TextInput; // We are only allowed to access the state if we are already the active widget. ImGuiInputTextState* state = GetInputTextState(id); if (g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) flags |= ImGuiInputTextFlags_ReadOnly; const bool is_readonly = (flags & ImGuiInputTextFlags_ReadOnly) != 0; const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0; const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0; const bool is_resizable = (flags & ImGuiInputTextFlags_CallbackResize) != 0; if (is_resizable) IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag! const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateId == id) && ((g.NavActivateFlags & ImGuiActivateFlags_PreferInput) || (g.NavInputSource == ImGuiInputSource_Keyboard))); const bool user_clicked = hovered && io.MouseClicked[0]; const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == GetWindowScrollbarID(draw_window, ImGuiAxis_Y); const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == GetWindowScrollbarID(draw_window, ImGuiAxis_Y); bool clear_active_id = false; bool select_all = false; float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX; const bool init_reload_from_user_buf = (state != NULL && state->ReloadUserBuf); const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline); // state != NULL means its our state. const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav); const bool init_state = (init_make_active || user_scroll_active); if ((init_state && g.ActiveId != id) || init_changed_specs || init_reload_from_user_buf) { // Access state even if we don't own it yet. state = &g.InputTextState; state->CursorAnimReset(); state->ReloadUserBuf = false; // Backup state of deactivating item so they'll have a chance to do a write to output buffer on the same frame they report IsItemDeactivatedAfterEdit (#4714) InputTextDeactivateHook(state->ID); // From the moment we focused we are normally ignoring the content of 'buf' (unless we are in read-only mode) const int buf_len = (int)strlen(buf); if (!init_reload_from_user_buf) { // Take a copy of the initial buffer value. state->InitialTextA.resize(buf_len + 1); // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string. memcpy(state->InitialTextA.Data, buf, buf_len + 1); } // Preserve cursor position and undo/redo stack if we come back to same widget // FIXME: Since we reworked this on 2022/06, may want to differentiate recycle_cursor vs recycle_undostate? bool recycle_state = (state->ID == id && !init_changed_specs && !init_reload_from_user_buf); if (recycle_state && (state->CurLenA != buf_len || (state->TextAIsValid && strncmp(state->TextA.Data, buf, buf_len) != 0))) recycle_state = false; // Start edition const char* buf_end = NULL; state->ID = id; state->TextW.resize(buf_size + 1); // wchar count <= UTF-8 count. we use +1 to make sure that .Data is always pointing to at least an empty string. state->TextA.resize(0); state->TextAIsValid = false; // TextA is not valid yet (we will display buf until then) state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, buf_size, buf, NULL, &buf_end); state->CurLenA = (int)(buf_end - buf); // We can't get the result from ImStrncpy() above because it is not UTF-8 aware. Here we'll cut off malformed UTF-8. if (recycle_state) { // Recycle existing cursor/selection/undo stack but clamp position // Note a single mouse click will override the cursor/position immediately by calling stb_textedit_click handler. state->CursorClamp(); } else { state->ScrollX = 0.0f; stb_textedit_initialize_state(&state->Stb, !is_multiline); } if (init_reload_from_user_buf) { state->Stb.select_start = state->ReloadSelectionStart; state->Stb.cursor = state->Stb.select_end = state->ReloadSelectionEnd; state->CursorClamp(); } else if (!is_multiline) { if (flags & ImGuiInputTextFlags_AutoSelectAll) select_all = true; if (input_requested_by_nav && (!recycle_state || !(g.NavActivateFlags & ImGuiActivateFlags_TryToPreserveState))) select_all = true; if (user_clicked && io.KeyCtrl) select_all = true; } if (flags & ImGuiInputTextFlags_AlwaysOverwrite) state->Stb.insert_mode = 1; // stb field name is indeed incorrect (see #2863) } const bool is_osx = io.ConfigMacOSXBehaviors; if (g.ActiveId != id && init_make_active) { IM_ASSERT(state && state->ID == id); SetActiveID(id, window); SetFocusID(id, window); FocusWindow(window); } if (g.ActiveId == id) { // Declare some inputs, the other are registered and polled via Shortcut() routing system. if (user_clicked) SetKeyOwner(ImGuiKey_MouseLeft, id); g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); if (is_multiline || (flags & ImGuiInputTextFlags_CallbackHistory)) g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); SetKeyOwner(ImGuiKey_Enter, id); SetKeyOwner(ImGuiKey_KeypadEnter, id); SetKeyOwner(ImGuiKey_Home, id); SetKeyOwner(ImGuiKey_End, id); if (is_multiline) { SetKeyOwner(ImGuiKey_PageUp, id); SetKeyOwner(ImGuiKey_PageDown, id); } if (is_osx) SetKeyOwner(ImGuiMod_Alt, id); } // We have an edge case if ActiveId was set through another widget (e.g. widget being swapped), clear id immediately (don't wait until the end of the function) if (g.ActiveId == id && state == NULL) ClearActiveID(); // Release focus when we click outside if (g.ActiveId == id && io.MouseClicked[0] && !init_state && !init_make_active) //-V560 clear_active_id = true; // Lock the decision of whether we are going to take the path displaying the cursor or selection bool render_cursor = (g.ActiveId == id) || (state && user_scroll_active); bool render_selection = state && (state->HasSelection() || select_all) && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor); bool value_changed = false; bool validated = false; // When read-only we always use the live data passed to the function // FIXME-OPT: Because our selection/cursor code currently needs the wide text we need to convert it when active, which is not ideal :( if (is_readonly && state != NULL && (render_cursor || render_selection)) { const char* buf_end = NULL; state->TextW.resize(buf_size + 1); state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, state->TextW.Size, buf, NULL, &buf_end); state->CurLenA = (int)(buf_end - buf); state->CursorClamp(); render_selection &= state->HasSelection(); } // Select the buffer to render. const bool buf_display_from_state = (render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state && state->TextAIsValid; const bool is_displaying_hint = (hint != NULL && (buf_display_from_state ? state->TextA.Data : buf)[0] == 0); // Password pushes a temporary font with only a fallback glyph if (is_password && !is_displaying_hint) { const ImFontGlyph* glyph = g.Font->FindGlyph('*'); ImFont* password_font = &g.InputTextPasswordFont; password_font->FontSize = g.Font->FontSize; password_font->Scale = g.Font->Scale; password_font->Ascent = g.Font->Ascent; password_font->Descent = g.Font->Descent; password_font->ContainerAtlas = g.Font->ContainerAtlas; password_font->FallbackGlyph = glyph; password_font->FallbackAdvanceX = glyph->AdvanceX; IM_ASSERT(password_font->Glyphs.empty() && password_font->IndexAdvanceX.empty() && password_font->IndexLookup.empty()); PushFont(password_font); } // Process mouse inputs and character inputs int backup_current_text_length = 0; if (g.ActiveId == id) { IM_ASSERT(state != NULL); backup_current_text_length = state->CurLenA; state->Edited = false; state->BufCapacityA = buf_size; state->Flags = flags; // Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget. // Down the line we should have a cleaner library-wide concept of Selected vs Active. g.ActiveIdAllowOverlap = !io.MouseDown[0]; // Edit in progress const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX; const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y) : (g.FontSize * 0.5f)); if (select_all) { state->SelectAll(); state->SelectedAllMouseLock = true; } else if (hovered && io.MouseClickedCount[0] >= 2 && !io.KeyShift) { stb_textedit_click(state, &state->Stb, mouse_x, mouse_y); const int multiclick_count = (io.MouseClickedCount[0] - 2); if ((multiclick_count % 2) == 0) { // Double-click: Select word // We always use the "Mac" word advance for double-click select vs CTRL+Right which use the platform dependent variant: // FIXME: There are likely many ways to improve this behavior, but there's no "right" behavior (depends on use-case, software, OS) const bool is_bol = (state->Stb.cursor == 0) || ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb.cursor - 1) == '\n'; if (STB_TEXT_HAS_SELECTION(&state->Stb) || !is_bol) state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT); //state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT); if (!STB_TEXT_HAS_SELECTION(&state->Stb)) ImStb::stb_textedit_prep_selection_at_cursor(&state->Stb); state->Stb.cursor = ImStb::STB_TEXTEDIT_MOVEWORDRIGHT_MAC(state, state->Stb.cursor); state->Stb.select_end = state->Stb.cursor; ImStb::stb_textedit_clamp(state, &state->Stb); } else { // Triple-click: Select line const bool is_eol = ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb.cursor) == '\n'; state->OnKeyPressed(STB_TEXTEDIT_K_LINESTART); state->OnKeyPressed(STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT); state->OnKeyPressed(STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT); if (!is_eol && is_multiline) { ImSwap(state->Stb.select_start, state->Stb.select_end); state->Stb.cursor = state->Stb.select_end; } state->CursorFollow = false; } state->CursorAnimReset(); } else if (io.MouseClicked[0] && !state->SelectedAllMouseLock) { if (hovered) { if (io.KeyShift) stb_textedit_drag(state, &state->Stb, mouse_x, mouse_y); else stb_textedit_click(state, &state->Stb, mouse_x, mouse_y); state->CursorAnimReset(); } } else if (io.MouseDown[0] && !state->SelectedAllMouseLock && (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)) { stb_textedit_drag(state, &state->Stb, mouse_x, mouse_y); state->CursorAnimReset(); state->CursorFollow = true; } if (state->SelectedAllMouseLock && !io.MouseDown[0]) state->SelectedAllMouseLock = false; // We expect backends to emit a Tab key but some also emit a Tab character which we ignore (#2467, #1336) // (For Tab and Enter: Win32/SFML/Allegro are sending both keys and chars, GLFW and SDL are only sending keys. For Space they all send all threes) if ((flags & ImGuiInputTextFlags_AllowTabInput) && !is_readonly) { if (Shortcut(ImGuiKey_Tab, id, ImGuiInputFlags_Repeat)) { unsigned int c = '\t'; // Insert TAB if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard)) state->OnKeyPressed((int)c); } // FIXME: Implement Shift+Tab /* if (Shortcut(ImGuiKey_Tab | ImGuiMod_Shift, id, ImGuiInputFlags_Repeat)) { } */ } // Process regular text input (before we check for Return because using some IME will effectively send a Return?) // We ignore CTRL inputs, but need to allow ALT+CTRL as some keyboards (e.g. German) use AltGR (which _is_ Alt+Ctrl) to input certain characters. const bool ignore_char_inputs = (io.KeyCtrl && !io.KeyAlt) || (is_osx && io.KeySuper); if (io.InputQueueCharacters.Size > 0) { if (!ignore_char_inputs && !is_readonly && !input_requested_by_nav) for (int n = 0; n < io.InputQueueCharacters.Size; n++) { // Insert character if they pass filtering unsigned int c = (unsigned int)io.InputQueueCharacters[n]; if (c == '\t') // Skip Tab, see above. continue; if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard)) state->OnKeyPressed((int)c); } // Consume characters io.InputQueueCharacters.resize(0); } } // Process other shortcuts/key-presses bool revert_edit = false; if (g.ActiveId == id && !g.ActiveIdIsJustActivated && !clear_active_id) { IM_ASSERT(state != NULL); const int row_count_per_page = ImMax((int)((inner_size.y - style.FramePadding.y) / g.FontSize), 1); state->Stb.row_count_per_page = row_count_per_page; const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0); const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl const bool is_startend_key_down = is_osx && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End // Using Shortcut() with ImGuiInputFlags_RouteFocused (default policy) to allow routing operations for other code (e.g. calling window trying to use CTRL+A and CTRL+B: formet would be handled by InputText) // Otherwise we could simply assume that we own the keys as we are active. const ImGuiInputFlags f_repeat = ImGuiInputFlags_Repeat; const bool is_cut = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_X, id, f_repeat) || Shortcut(ImGuiMod_Shift | ImGuiKey_Delete, id, f_repeat)) && !is_readonly && !is_password && (!is_multiline || state->HasSelection()); const bool is_copy = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_C, id) || Shortcut(ImGuiMod_Ctrl | ImGuiKey_Insert, id)) && !is_password && (!is_multiline || state->HasSelection()); const bool is_paste = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_V, id, f_repeat) || Shortcut(ImGuiMod_Shift | ImGuiKey_Insert, id, f_repeat)) && !is_readonly; const bool is_undo = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_Z, id, f_repeat)) && !is_readonly && is_undoable; const bool is_redo = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_Y, id, f_repeat) || (is_osx && Shortcut(ImGuiMod_Shortcut | ImGuiMod_Shift | ImGuiKey_Z, id, f_repeat))) && !is_readonly && is_undoable; const bool is_select_all = Shortcut(ImGuiMod_Shortcut | ImGuiKey_A, id); // We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful. const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; const bool is_enter_pressed = IsKeyPressed(ImGuiKey_Enter, true) || IsKeyPressed(ImGuiKey_KeypadEnter, true); const bool is_gamepad_validate = nav_gamepad_active && (IsKeyPressed(ImGuiKey_NavGamepadActivate, false) || IsKeyPressed(ImGuiKey_NavGamepadInput, false)); const bool is_cancel = Shortcut(ImGuiKey_Escape, id, f_repeat) || (nav_gamepad_active && Shortcut(ImGuiKey_NavGamepadCancel, id, f_repeat)); // FIXME: Should use more Shortcut() and reduce IsKeyPressed()+SetKeyOwner(), but requires modifiers combination to be taken account of. if (IsKeyPressed(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); } else if (IsKeyPressed(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); } else if (IsKeyPressed(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); } else if (IsKeyPressed(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); } else if (IsKeyPressed(ImGuiKey_PageUp) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGUP | k_mask); scroll_y -= row_count_per_page * g.FontSize; } else if (IsKeyPressed(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; } else if (IsKeyPressed(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); } else if (IsKeyPressed(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); } else if (IsKeyPressed(ImGuiKey_Delete) && !is_readonly && !is_cut) { if (!state->HasSelection()) { // OSX doesn't seem to have Super+Delete to delete until end-of-line, so we don't emulate that (as opposed to Super+Backspace) if (is_wordmove_key_down) state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT); } state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); } else if (IsKeyPressed(ImGuiKey_Backspace) && !is_readonly) { if (!state->HasSelection()) { if (is_wordmove_key_down) state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT); else if (is_osx && io.KeySuper && !io.KeyAlt && !io.KeyCtrl) state->OnKeyPressed(STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT); } state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); } else if (is_enter_pressed || is_gamepad_validate) { // Determine if we turn Enter into a \n character bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0; if (!is_multiline || is_gamepad_validate || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl)) { validated = true; if (io.ConfigInputTextEnterKeepActive && !is_multiline) state->SelectAll(); // No need to scroll else clear_active_id = true; } else if (!is_readonly) { unsigned int c = '\n'; // Insert new line if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard)) state->OnKeyPressed((int)c); } } else if (is_cancel) { if (flags & ImGuiInputTextFlags_EscapeClearsAll) { if (buf[0] != 0) { revert_edit = true; } else { render_cursor = render_selection = false; clear_active_id = true; } } else { clear_active_id = revert_edit = true; render_cursor = render_selection = false; } } else if (is_undo || is_redo) { state->OnKeyPressed(is_undo ? STB_TEXTEDIT_K_UNDO : STB_TEXTEDIT_K_REDO); state->ClearSelection(); } else if (is_select_all) { state->SelectAll(); state->CursorFollow = true; } else if (is_cut || is_copy) { // Cut, Copy if (io.SetClipboardTextFn) { const int ib = state->HasSelection() ? ImMin(state->Stb.select_start, state->Stb.select_end) : 0; const int ie = state->HasSelection() ? ImMax(state->Stb.select_start, state->Stb.select_end) : state->CurLenW; const int clipboard_data_len = ImTextCountUtf8BytesFromStr(state->TextW.Data + ib, state->TextW.Data + ie) + 1; char* clipboard_data = (char*)IM_ALLOC(clipboard_data_len * sizeof(char)); ImTextStrToUtf8(clipboard_data, clipboard_data_len, state->TextW.Data + ib, state->TextW.Data + ie); SetClipboardText(clipboard_data); MemFree(clipboard_data); } if (is_cut) { if (!state->HasSelection()) state->SelectAll(); state->CursorFollow = true; stb_textedit_cut(state, &state->Stb); } } else if (is_paste) { if (const char* clipboard = GetClipboardText()) { // Filter pasted buffer const int clipboard_len = (int)strlen(clipboard); ImWchar* clipboard_filtered = (ImWchar*)IM_ALLOC((clipboard_len + 1) * sizeof(ImWchar)); int clipboard_filtered_len = 0; for (const char* s = clipboard; *s != 0; ) { unsigned int c; s += ImTextCharFromUtf8(&c, s, NULL); if (!InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data, ImGuiInputSource_Clipboard)) continue; clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c; } clipboard_filtered[clipboard_filtered_len] = 0; if (clipboard_filtered_len > 0) // If everything was filtered, ignore the pasting operation { stb_textedit_paste(state, &state->Stb, clipboard_filtered, clipboard_filtered_len); state->CursorFollow = true; } MemFree(clipboard_filtered); } } // Update render selection flag after events have been handled, so selection highlight can be displayed during the same frame. render_selection |= state->HasSelection() && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor); } // Process callbacks and apply result back to user's buffer. const char* apply_new_text = NULL; int apply_new_text_length = 0; if (g.ActiveId == id) { IM_ASSERT(state != NULL); if (revert_edit && !is_readonly) { if (flags & ImGuiInputTextFlags_EscapeClearsAll) { // Clear input IM_ASSERT(buf[0] != 0); apply_new_text = ""; apply_new_text_length = 0; value_changed = true; IMSTB_TEXTEDIT_CHARTYPE empty_string; stb_textedit_replace(state, &state->Stb, &empty_string, 0); } else if (strcmp(buf, state->InitialTextA.Data) != 0) { // Restore initial value. Only return true if restoring to the initial value changes the current buffer contents. // Push records into the undo stack so we can CTRL+Z the revert operation itself apply_new_text = state->InitialTextA.Data; apply_new_text_length = state->InitialTextA.Size - 1; value_changed = true; ImVector w_text; if (apply_new_text_length > 0) { w_text.resize(ImTextCountCharsFromUtf8(apply_new_text, apply_new_text + apply_new_text_length) + 1); ImTextStrFromUtf8(w_text.Data, w_text.Size, apply_new_text, apply_new_text + apply_new_text_length); } stb_textedit_replace(state, &state->Stb, w_text.Data, (apply_new_text_length > 0) ? (w_text.Size - 1) : 0); } } // Apply ASCII value if (!is_readonly) { state->TextAIsValid = true; state->TextA.resize(state->TextW.Size * 4 + 1); ImTextStrToUtf8(state->TextA.Data, state->TextA.Size, state->TextW.Data, NULL); } // When using 'ImGuiInputTextFlags_EnterReturnsTrue' as a special case we reapply the live buffer back to the input buffer // before clearing ActiveId, even though strictly speaking it wasn't modified on this frame. // If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail. // This also allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage // (please note that if you use this property along ImGuiInputTextFlags_CallbackResize you can end up with your temporary string object // unnecessarily allocating once a frame, either store your string data, either if you don't then don't use ImGuiInputTextFlags_CallbackResize). const bool apply_edit_back_to_user_buffer = !revert_edit || (validated && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0); if (apply_edit_back_to_user_buffer) { // Apply new value immediately - copy modified buffer back // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer // FIXME: We actually always render 'buf' when calling DrawList->AddText, making the comment above incorrect. // FIXME-OPT: CPU waste to do this every time the widget is active, should mark dirty state from the stb_textedit callbacks. // User callback if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_CallbackAlways)) != 0) { IM_ASSERT(callback != NULL); // The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard TABBING at the moment. ImGuiInputTextFlags event_flag = 0; ImGuiKey event_key = ImGuiKey_None; if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && Shortcut(ImGuiKey_Tab, id)) { event_flag = ImGuiInputTextFlags_CallbackCompletion; event_key = ImGuiKey_Tab; } else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressed(ImGuiKey_UpArrow)) { event_flag = ImGuiInputTextFlags_CallbackHistory; event_key = ImGuiKey_UpArrow; } else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressed(ImGuiKey_DownArrow)) { event_flag = ImGuiInputTextFlags_CallbackHistory; event_key = ImGuiKey_DownArrow; } else if ((flags & ImGuiInputTextFlags_CallbackEdit) && state->Edited) { event_flag = ImGuiInputTextFlags_CallbackEdit; } else if (flags & ImGuiInputTextFlags_CallbackAlways) { event_flag = ImGuiInputTextFlags_CallbackAlways; } if (event_flag) { ImGuiInputTextCallbackData callback_data; callback_data.Ctx = &g; callback_data.EventFlag = event_flag; callback_data.Flags = flags; callback_data.UserData = callback_user_data; char* callback_buf = is_readonly ? buf : state->TextA.Data; callback_data.EventKey = event_key; callback_data.Buf = callback_buf; callback_data.BufTextLen = state->CurLenA; callback_data.BufSize = state->BufCapacityA; callback_data.BufDirty = false; // We have to convert from wchar-positions to UTF-8-positions, which can be pretty slow (an incentive to ditch the ImWchar buffer, see https://github.com/nothings/stb/issues/188) ImWchar* text = state->TextW.Data; const int utf8_cursor_pos = callback_data.CursorPos = ImTextCountUtf8BytesFromStr(text, text + state->Stb.cursor); const int utf8_selection_start = callback_data.SelectionStart = ImTextCountUtf8BytesFromStr(text, text + state->Stb.select_start); const int utf8_selection_end = callback_data.SelectionEnd = ImTextCountUtf8BytesFromStr(text, text + state->Stb.select_end); // Call user code callback(&callback_data); // Read back what user may have modified callback_buf = is_readonly ? buf : state->TextA.Data; // Pointer may have been invalidated by a resize callback IM_ASSERT(callback_data.Buf == callback_buf); // Invalid to modify those fields IM_ASSERT(callback_data.BufSize == state->BufCapacityA); IM_ASSERT(callback_data.Flags == flags); const bool buf_dirty = callback_data.BufDirty; if (callback_data.CursorPos != utf8_cursor_pos || buf_dirty) { state->Stb.cursor = ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.CursorPos); state->CursorFollow = true; } if (callback_data.SelectionStart != utf8_selection_start || buf_dirty) { state->Stb.select_start = (callback_data.SelectionStart == callback_data.CursorPos) ? state->Stb.cursor : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionStart); } if (callback_data.SelectionEnd != utf8_selection_end || buf_dirty) { state->Stb.select_end = (callback_data.SelectionEnd == callback_data.SelectionStart) ? state->Stb.select_start : ImTextCountCharsFromUtf8(callback_data.Buf, callback_data.Buf + callback_data.SelectionEnd); } if (buf_dirty) { IM_ASSERT(!is_readonly); IM_ASSERT(callback_data.BufTextLen == (int)strlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text! InputTextReconcileUndoStateAfterUserCallback(state, callback_data.Buf, callback_data.BufTextLen); // FIXME: Move the rest of this block inside function and rename to InputTextReconcileStateAfterUserCallback() ? if (callback_data.BufTextLen > backup_current_text_length && is_resizable) state->TextW.resize(state->TextW.Size + (callback_data.BufTextLen - backup_current_text_length)); // Worse case scenario resize state->CurLenW = ImTextStrFromUtf8(state->TextW.Data, state->TextW.Size, callback_data.Buf, NULL); state->CurLenA = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen() state->CursorAnimReset(); } } } // Will copy result string if modified if (!is_readonly && strcmp(state->TextA.Data, buf) != 0) { apply_new_text = state->TextA.Data; apply_new_text_length = state->CurLenA; value_changed = true; } } } // Handle reapplying final data on deactivation (see InputTextDeactivateHook() for details) if (g.InputTextDeactivatedState.ID == id) { if (g.ActiveId != id && IsItemDeactivatedAfterEdit() && !is_readonly && strcmp(g.InputTextDeactivatedState.TextA.Data, buf) != 0) { apply_new_text = g.InputTextDeactivatedState.TextA.Data; apply_new_text_length = g.InputTextDeactivatedState.TextA.Size - 1; value_changed = true; //IMGUI_DEBUG_LOG("InputText(): apply Deactivated data for 0x%08X: \"%.*s\".\n", id, apply_new_text_length, apply_new_text); } g.InputTextDeactivatedState.ID = 0; } // Copy result to user buffer. This can currently only happen when (g.ActiveId == id) if (apply_new_text != NULL) { // We cannot test for 'backup_current_text_length != apply_new_text_length' here because we have no guarantee that the size // of our owned buffer matches the size of the string object held by the user, and by design we allow InputText() to be used // without any storage on user's side. IM_ASSERT(apply_new_text_length >= 0); if (is_resizable) { ImGuiInputTextCallbackData callback_data; callback_data.Ctx = &g; callback_data.EventFlag = ImGuiInputTextFlags_CallbackResize; callback_data.Flags = flags; callback_data.Buf = buf; callback_data.BufTextLen = apply_new_text_length; callback_data.BufSize = ImMax(buf_size, apply_new_text_length + 1); callback_data.UserData = callback_user_data; callback(&callback_data); buf = callback_data.Buf; buf_size = callback_data.BufSize; apply_new_text_length = ImMin(callback_data.BufTextLen, buf_size - 1); IM_ASSERT(apply_new_text_length <= buf_size); } //IMGUI_DEBUG_PRINT("InputText(\"%s\"): apply_new_text length %d\n", label, apply_new_text_length); // If the underlying buffer resize was denied or not carried to the next frame, apply_new_text_length+1 may be >= buf_size. ImStrncpy(buf, apply_new_text, ImMin(apply_new_text_length + 1, buf_size)); } // Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value) // Otherwise request text input ahead for next frame. if (g.ActiveId == id && clear_active_id) ClearActiveID(); else if (g.ActiveId == id) g.WantTextInputNextFrame = 1; // Render frame if (!is_multiline) { RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); } const ImVec4 clip_rect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + inner_size.x, frame_bb.Min.y + inner_size.y); // Not using frame_bb.Max because we have adjusted size ImVec2 draw_pos = is_multiline ? draw_window->DC.CursorPos : frame_bb.Min + style.FramePadding; ImVec2 text_size(0.0f, 0.0f); // Set upper limit of single-line InputTextEx() at 2 million characters strings. The current pathological worst case is a long line // without any carriage return, which would makes ImFont::RenderText() reserve too many vertices and probably crash. Avoid it altogether. // Note that we only use this limit on single-line InputText(), so a pathologically large line on a InputTextMultiline() would still crash. const int buf_display_max_length = 2 * 1024 * 1024; const char* buf_display = buf_display_from_state ? state->TextA.Data : buf; //-V595 const char* buf_display_end = NULL; // We have specialized paths below for setting the length if (is_displaying_hint) { buf_display = hint; buf_display_end = hint + strlen(hint); } // Render text. We currently only render selection when the widget is active or while scrolling. // FIXME: We could remove the '&& render_cursor' to keep rendering selection when inactive. if (render_cursor || render_selection) { IM_ASSERT(state != NULL); if (!is_displaying_hint) buf_display_end = buf_display + state->CurLenA; // Render text (with cursor and selection) // This is going to be messy. We need to: // - Display the text (this alone can be more easily clipped) // - Handle scrolling, highlight selection, display cursor (those all requires some form of 1d->2d cursor position calculation) // - Measure text height (for scrollbar) // We are attempting to do most of that in **one main pass** to minimize the computation cost (non-negligible for large amount of text) + 2nd pass for selection rendering (we could merge them by an extra refactoring effort) // FIXME: This should occur on buf_display but we'd need to maintain cursor/select_start/select_end for UTF-8. const ImWchar* text_begin = state->TextW.Data; ImVec2 cursor_offset, select_start_offset; { // Find lines numbers straddling 'cursor' (slot 0) and 'select_start' (slot 1) positions. const ImWchar* searches_input_ptr[2] = { NULL, NULL }; int searches_result_line_no[2] = { -1000, -1000 }; int searches_remaining = 0; if (render_cursor) { searches_input_ptr[0] = text_begin + state->Stb.cursor; searches_result_line_no[0] = -1; searches_remaining++; } if (render_selection) { searches_input_ptr[1] = text_begin + ImMin(state->Stb.select_start, state->Stb.select_end); searches_result_line_no[1] = -1; searches_remaining++; } // Iterate all lines to find our line numbers // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter. searches_remaining += is_multiline ? 1 : 0; int line_count = 0; //for (const ImWchar* s = text_begin; (s = (const ImWchar*)wcschr((const wchar_t*)s, (wchar_t)'\n')) != NULL; s++) // FIXME-OPT: Could use this when wchar_t are 16-bit for (const ImWchar* s = text_begin; *s != 0; s++) if (*s == '\n') { line_count++; if (searches_result_line_no[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_no[0] = line_count; if (--searches_remaining <= 0) break; } if (searches_result_line_no[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_no[1] = line_count; if (--searches_remaining <= 0) break; } } line_count++; if (searches_result_line_no[0] == -1) searches_result_line_no[0] = line_count; if (searches_result_line_no[1] == -1) searches_result_line_no[1] = line_count; // Calculate 2d position by finding the beginning of the line and measuring distance cursor_offset.x = InputTextCalcTextSizeW(&g, ImStrbolW(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x; cursor_offset.y = searches_result_line_no[0] * g.FontSize; if (searches_result_line_no[1] >= 0) { select_start_offset.x = InputTextCalcTextSizeW(&g, ImStrbolW(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x; select_start_offset.y = searches_result_line_no[1] * g.FontSize; } // Store text height (note that we haven't calculated text width at all, see GitHub issues #383, #1224) if (is_multiline) text_size = ImVec2(inner_size.x, line_count * g.FontSize); } // Scroll if (render_cursor && state->CursorFollow) { // Horizontal scroll in chunks of quarter width if (!(flags & ImGuiInputTextFlags_NoHorizontalScroll)) { const float scroll_increment_x = inner_size.x * 0.25f; const float visible_width = inner_size.x - style.FramePadding.x; if (cursor_offset.x < state->ScrollX) state->ScrollX = IM_TRUNC(ImMax(0.0f, cursor_offset.x - scroll_increment_x)); else if (cursor_offset.x - visible_width >= state->ScrollX) state->ScrollX = IM_TRUNC(cursor_offset.x - visible_width + scroll_increment_x); } else { state->ScrollX = 0.0f; } // Vertical scroll if (is_multiline) { // Test if cursor is vertically visible if (cursor_offset.y - g.FontSize < scroll_y) scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize); else if (cursor_offset.y - (inner_size.y - style.FramePadding.y * 2.0f) >= scroll_y) scroll_y = cursor_offset.y - inner_size.y + style.FramePadding.y * 2.0f; const float scroll_max_y = ImMax((text_size.y + style.FramePadding.y * 2.0f) - inner_size.y, 0.0f); scroll_y = ImClamp(scroll_y, 0.0f, scroll_max_y); draw_pos.y += (draw_window->Scroll.y - scroll_y); // Manipulate cursor pos immediately avoid a frame of lag draw_window->Scroll.y = scroll_y; } state->CursorFollow = false; } // Draw selection const ImVec2 draw_scroll = ImVec2(state->ScrollX, 0.0f); if (render_selection) { const ImWchar* text_selected_begin = text_begin + ImMin(state->Stb.select_start, state->Stb.select_end); const ImWchar* text_selected_end = text_begin + ImMax(state->Stb.select_start, state->Stb.select_end); ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg, render_cursor ? 1.0f : 0.6f); // FIXME: current code flow mandate that render_cursor is always true here, we are leaving the transparent one for tests. float bg_offy_up = is_multiline ? 0.0f : -1.0f; // FIXME: those offsets should be part of the style? they don't play so well with multi-line selection. float bg_offy_dn = is_multiline ? 0.0f : 2.0f; ImVec2 rect_pos = draw_pos + select_start_offset - draw_scroll; for (const ImWchar* p = text_selected_begin; p < text_selected_end; ) { if (rect_pos.y > clip_rect.w + g.FontSize) break; if (rect_pos.y < clip_rect.y) { //p = (const ImWchar*)wmemchr((const wchar_t*)p, '\n', text_selected_end - p); // FIXME-OPT: Could use this when wchar_t are 16-bit //p = p ? p + 1 : text_selected_end; while (p < text_selected_end) if (*p++ == '\n') break; } else { ImVec2 rect_size = InputTextCalcTextSizeW(&g, p, text_selected_end, &p, NULL, true); if (rect_size.x <= 0.0f) rect_size.x = IM_TRUNC(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos + ImVec2(rect_size.x, bg_offy_dn)); rect.ClipWith(clip_rect); if (rect.Overlaps(clip_rect)) draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color); } rect_pos.x = draw_pos.x - draw_scroll.x; rect_pos.y += g.FontSize; } } // We test for 'buf_display_max_length' as a way to avoid some pathological cases (e.g. single-line 1 MB string) which would make ImDrawList crash. if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length) { ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text); draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect); } // Draw blinking cursor if (render_cursor) { state->CursorAnim += io.DeltaTime; bool cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (state->CursorAnim <= 0.0f) || ImFmod(state->CursorAnim, 1.20f) <= 0.80f; ImVec2 cursor_screen_pos = ImTrunc(draw_pos + cursor_offset - draw_scroll); ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f); if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect)) draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text)); // Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.) if (!is_readonly) { g.PlatformImeData.WantVisible = true; g.PlatformImeData.InputPos = ImVec2(cursor_screen_pos.x - 1.0f, cursor_screen_pos.y - g.FontSize); g.PlatformImeData.InputLineHeight = g.FontSize; } } } else { // Render text only (no selection, no cursor) if (is_multiline) text_size = ImVec2(inner_size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_display_end) * g.FontSize); // We don't need width else if (!is_displaying_hint && g.ActiveId == id) buf_display_end = buf_display + state->CurLenA; else if (!is_displaying_hint) buf_display_end = buf_display + strlen(buf_display); if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length) { ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text); draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect); } } if (is_password && !is_displaying_hint) PopFont(); if (is_multiline) { // For focus requests to work on our multiline we need to ensure our child ItemAdd() call specifies the ImGuiItemFlags_Inputable (ref issue #4761)... Dummy(ImVec2(text_size.x, text_size.y + style.FramePadding.y)); g.NextItemData.ItemFlags |= ImGuiItemFlags_Inputable | ImGuiItemFlags_NoTabStop; EndChild(); item_data_backup.StatusFlags |= (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredWindow); // ...and then we need to undo the group overriding last item data, which gets a bit messy as EndGroup() tries to forward scrollbar being active... // FIXME: This quite messy/tricky, should attempt to get rid of the child window. EndGroup(); if (g.LastItemData.ID == 0) { g.LastItemData.ID = id; g.LastItemData.InFlags = item_data_backup.InFlags; g.LastItemData.StatusFlags = item_data_backup.StatusFlags; } } // Log as text if (g.LogEnabled && (!is_password || is_displaying_hint)) { LogSetNextTextDecoration("{", "}"); LogRenderedText(&draw_pos, buf_display, buf_display_end); } if (label_size.x > 0) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); if (value_changed && !(flags & ImGuiInputTextFlags_NoMarkEdited)) MarkItemEdited(id); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Inputable); if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0) return validated; else return value_changed; } void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state) { #ifndef IMGUI_DISABLE_DEBUG_TOOLS ImGuiContext& g = *GImGui; ImStb::STB_TexteditState* stb_state = &state->Stb; ImStb::StbUndoState* undo_state = &stb_state->undostate; Text("ID: 0x%08X, ActiveID: 0x%08X", state->ID, g.ActiveId); DebugLocateItemOnHover(state->ID); Text("CurLenW: %d, CurLenA: %d, Cursor: %d, Selection: %d..%d", state->CurLenW, state->CurLenA, stb_state->cursor, stb_state->select_start, stb_state->select_end); Text("has_preferred_x: %d (%.2f)", stb_state->has_preferred_x, stb_state->preferred_x); Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state->undo_point, undo_state->redo_point, undo_state->undo_char_point, undo_state->redo_char_point); if (BeginChild("undopoints", ImVec2(0.0f, GetTextLineHeight() * 10), ImGuiChildFlags_Border | ImGuiChildFlags_ResizeY)) // Visualize undo state { PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); for (int n = 0; n < IMSTB_TEXTEDIT_UNDOSTATECOUNT; n++) { ImStb::StbUndoRecord* undo_rec = &undo_state->undo_rec[n]; const char undo_rec_type = (n < undo_state->undo_point) ? 'u' : (n >= undo_state->redo_point) ? 'r' : ' '; if (undo_rec_type == ' ') BeginDisabled(); char buf[64] = ""; if (undo_rec_type != ' ' && undo_rec->char_storage != -1) ImTextStrToUtf8(buf, IM_ARRAYSIZE(buf), undo_state->undo_char + undo_rec->char_storage, undo_state->undo_char + undo_rec->char_storage + undo_rec->insert_length); Text("%c [%02d] where %03d, insert %03d, delete %03d, char_storage %03d \"%s\"", undo_rec_type, n, undo_rec->where, undo_rec->insert_length, undo_rec->delete_length, undo_rec->char_storage, buf); if (undo_rec_type == ' ') EndDisabled(); } PopStyleVar(); } EndChild(); #else IM_UNUSED(state); #endif } //------------------------------------------------------------------------- // [SECTION] Widgets: ColorEdit, ColorPicker, ColorButton, etc. //------------------------------------------------------------------------- // - ColorEdit3() // - ColorEdit4() // - ColorPicker3() // - RenderColorRectWithAlphaCheckerboard() [Internal] // - ColorPicker4() // - ColorButton() // - SetColorEditOptions() // - ColorTooltip() [Internal] // - ColorEditOptionsPopup() [Internal] // - ColorPickerOptionsPopup() [Internal] //------------------------------------------------------------------------- bool ImGui::ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags) { return ColorEdit4(label, col, flags | ImGuiColorEditFlags_NoAlpha); } static void ColorEditRestoreH(const float* col, float* H) { ImGuiContext& g = *GImGui; IM_ASSERT(g.ColorEditCurrentID != 0); if (g.ColorEditSavedID != g.ColorEditCurrentID || g.ColorEditSavedColor != ImGui::ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0))) return; *H = g.ColorEditSavedHue; } // ColorEdit supports RGB and HSV inputs. In case of RGB input resulting color may have undefined hue and/or saturation. // Since widget displays both RGB and HSV values we must preserve hue and saturation to prevent these values resetting. static void ColorEditRestoreHS(const float* col, float* H, float* S, float* V) { ImGuiContext& g = *GImGui; IM_ASSERT(g.ColorEditCurrentID != 0); if (g.ColorEditSavedID != g.ColorEditCurrentID || g.ColorEditSavedColor != ImGui::ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0))) return; // When S == 0, H is undefined. // When H == 1 it wraps around to 0. if (*S == 0.0f || (*H == 0.0f && g.ColorEditSavedHue == 1)) *H = g.ColorEditSavedHue; // When V == 0, S is undefined. if (*V == 0.0f) *S = g.ColorEditSavedSat; } // Edit colors components (each component in 0.0f..1.0f range). // See enum ImGuiColorEditFlags_ for available options. e.g. Only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. // With typical options: Left-click on color square to open color picker. Right-click to open option menu. CTRL-Click over input fields to edit them and TAB to go to next item. bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const float square_sz = GetFrameHeight(); const char* label_display_end = FindRenderedTextEnd(label); float w_full = CalcItemWidth(); g.NextItemData.ClearFlags(); BeginGroup(); PushID(label); const bool set_current_color_edit_id = (g.ColorEditCurrentID == 0); if (set_current_color_edit_id) g.ColorEditCurrentID = window->IDStack.back(); // If we're not showing any slider there's no point in doing any HSV conversions const ImGuiColorEditFlags flags_untouched = flags; if (flags & ImGuiColorEditFlags_NoInputs) flags = (flags & (~ImGuiColorEditFlags_DisplayMask_)) | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_NoOptions; // Context menu: display and modify options (before defaults are applied) if (!(flags & ImGuiColorEditFlags_NoOptions)) ColorEditOptionsPopup(col, flags); // Read stored options if (!(flags & ImGuiColorEditFlags_DisplayMask_)) flags |= (g.ColorEditOptions & ImGuiColorEditFlags_DisplayMask_); if (!(flags & ImGuiColorEditFlags_DataTypeMask_)) flags |= (g.ColorEditOptions & ImGuiColorEditFlags_DataTypeMask_); if (!(flags & ImGuiColorEditFlags_PickerMask_)) flags |= (g.ColorEditOptions & ImGuiColorEditFlags_PickerMask_); if (!(flags & ImGuiColorEditFlags_InputMask_)) flags |= (g.ColorEditOptions & ImGuiColorEditFlags_InputMask_); flags |= (g.ColorEditOptions & ~(ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_)); IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DisplayMask_)); // Check that only 1 is selected IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check that only 1 is selected const bool alpha = (flags & ImGuiColorEditFlags_NoAlpha) == 0; const bool hdr = (flags & ImGuiColorEditFlags_HDR) != 0; const int components = alpha ? 4 : 3; const float w_button = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x); const float w_inputs = ImMax(w_full - w_button, 1.0f); w_full = w_inputs + w_button; // Convert to the formats we need float f[4] = { col[0], col[1], col[2], alpha ? col[3] : 1.0f }; if ((flags & ImGuiColorEditFlags_InputHSV) && (flags & ImGuiColorEditFlags_DisplayRGB)) ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); else if ((flags & ImGuiColorEditFlags_InputRGB) && (flags & ImGuiColorEditFlags_DisplayHSV)) { // Hue is lost when converting from grayscale rgb (saturation=0). Restore it. ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); ColorEditRestoreHS(col, &f[0], &f[1], &f[2]); } int i[4] = { IM_F32_TO_INT8_UNBOUND(f[0]), IM_F32_TO_INT8_UNBOUND(f[1]), IM_F32_TO_INT8_UNBOUND(f[2]), IM_F32_TO_INT8_UNBOUND(f[3]) }; bool value_changed = false; bool value_changed_as_float = false; const ImVec2 pos = window->DC.CursorPos; const float inputs_offset_x = (style.ColorButtonPosition == ImGuiDir_Left) ? w_button : 0.0f; window->DC.CursorPos.x = pos.x + inputs_offset_x; if ((flags & (ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV)) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0) { // RGB/HSV 0..255 Sliders const float w_items = w_inputs - style.ItemInnerSpacing.x * (components - 1); const bool hide_prefix = (IM_TRUNC(w_items / components) <= CalcTextSize((flags & ImGuiColorEditFlags_Float) ? "M:0.000" : "M:000").x); static const char* ids[4] = { "##X", "##Y", "##Z", "##W" }; static const char* fmt_table_int[3][4] = { { "%3d", "%3d", "%3d", "%3d" }, // Short display { "R:%3d", "G:%3d", "B:%3d", "A:%3d" }, // Long display for RGBA { "H:%3d", "S:%3d", "V:%3d", "A:%3d" } // Long display for HSVA }; static const char* fmt_table_float[3][4] = { { "%0.3f", "%0.3f", "%0.3f", "%0.3f" }, // Short display { "R:%0.3f", "G:%0.3f", "B:%0.3f", "A:%0.3f" }, // Long display for RGBA { "H:%0.3f", "S:%0.3f", "V:%0.3f", "A:%0.3f" } // Long display for HSVA }; const int fmt_idx = hide_prefix ? 0 : (flags & ImGuiColorEditFlags_DisplayHSV) ? 2 : 1; float prev_split = 0.0f; for (int n = 0; n < components; n++) { if (n > 0) SameLine(0, style.ItemInnerSpacing.x); float next_split = IM_TRUNC(w_items * (n + 1) / components); SetNextItemWidth(ImMax(next_split - prev_split, 1.0f)); prev_split = next_split; // FIXME: When ImGuiColorEditFlags_HDR flag is passed HS values snap in weird ways when SV values go below 0. if (flags & ImGuiColorEditFlags_Float) { value_changed |= DragFloat(ids[n], &f[n], 1.0f / 255.0f, 0.0f, hdr ? 0.0f : 1.0f, fmt_table_float[fmt_idx][n]); value_changed_as_float |= value_changed; } else { value_changed |= DragInt(ids[n], &i[n], 1.0f, 0, hdr ? 0 : 255, fmt_table_int[fmt_idx][n]); } if (!(flags & ImGuiColorEditFlags_NoOptions)) OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight); } } else if ((flags & ImGuiColorEditFlags_DisplayHex) != 0 && (flags & ImGuiColorEditFlags_NoInputs) == 0) { // RGB Hexadecimal Input char buf[64]; if (alpha) ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", ImClamp(i[0], 0, 255), ImClamp(i[1], 0, 255), ImClamp(i[2], 0, 255), ImClamp(i[3], 0, 255)); else ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", ImClamp(i[0], 0, 255), ImClamp(i[1], 0, 255), ImClamp(i[2], 0, 255)); SetNextItemWidth(w_inputs); if (InputText("##Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_CharsUppercase)) { value_changed = true; char* p = buf; while (*p == '#' || ImCharIsBlankA(*p)) p++; i[0] = i[1] = i[2] = 0; i[3] = 0xFF; // alpha default to 255 is not parsed by scanf (e.g. inputting #FFFFFF omitting alpha) int r; if (alpha) r = sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); // Treat at unsigned (%X is unsigned) else r = sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]); IM_UNUSED(r); // Fixes C6031: Return value ignored: 'sscanf'. } if (!(flags & ImGuiColorEditFlags_NoOptions)) OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight); } ImGuiWindow* picker_active_window = NULL; if (!(flags & ImGuiColorEditFlags_NoSmallPreview)) { const float button_offset_x = ((flags & ImGuiColorEditFlags_NoInputs) || (style.ColorButtonPosition == ImGuiDir_Left)) ? 0.0f : w_inputs + style.ItemInnerSpacing.x; window->DC.CursorPos = ImVec2(pos.x + button_offset_x, pos.y); const ImVec4 col_v4(col[0], col[1], col[2], alpha ? col[3] : 1.0f); if (ColorButton("##ColorButton", col_v4, flags)) { if (!(flags & ImGuiColorEditFlags_NoPicker)) { // Store current color and open a picker g.ColorPickerRef = col_v4; OpenPopup("picker"); SetNextWindowPos(g.LastItemData.Rect.GetBL() + ImVec2(0.0f, style.ItemSpacing.y)); } } if (!(flags & ImGuiColorEditFlags_NoOptions)) OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight); if (BeginPopup("picker")) { if (g.CurrentWindow->BeginCount == 1) { picker_active_window = g.CurrentWindow; if (label != label_display_end) { TextEx(label, label_display_end); Spacing(); } ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar; ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf; SetNextItemWidth(square_sz * 12.0f); // Use 256 + bar sizes? value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x); } EndPopup(); } } if (label != label_display_end && !(flags & ImGuiColorEditFlags_NoLabel)) { // Position not necessarily next to last submitted button (e.g. if style.ColorButtonPosition == ImGuiDir_Left), // but we need to use SameLine() to setup baseline correctly. Might want to refactor SameLine() to simplify this. SameLine(0.0f, style.ItemInnerSpacing.x); window->DC.CursorPos.x = pos.x + ((flags & ImGuiColorEditFlags_NoInputs) ? w_button : w_full + style.ItemInnerSpacing.x); TextEx(label, label_display_end); } // Convert back if (value_changed && picker_active_window == NULL) { if (!value_changed_as_float) for (int n = 0; n < 4; n++) f[n] = i[n] / 255.0f; if ((flags & ImGuiColorEditFlags_DisplayHSV) && (flags & ImGuiColorEditFlags_InputRGB)) { g.ColorEditSavedHue = f[0]; g.ColorEditSavedSat = f[1]; ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); g.ColorEditSavedID = g.ColorEditCurrentID; g.ColorEditSavedColor = ColorConvertFloat4ToU32(ImVec4(f[0], f[1], f[2], 0)); } if ((flags & ImGuiColorEditFlags_DisplayRGB) && (flags & ImGuiColorEditFlags_InputHSV)) ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); col[0] = f[0]; col[1] = f[1]; col[2] = f[2]; if (alpha) col[3] = f[3]; } if (set_current_color_edit_id) g.ColorEditCurrentID = 0; PopID(); EndGroup(); // Drag and Drop Target // NB: The flag test is merely an optional micro-optimization, BeginDragDropTarget() does the same test. if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) && !(g.LastItemData.InFlags & ImGuiItemFlags_ReadOnly) && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropTarget()) { bool accepted_drag_drop = false; if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) { memcpy((float*)col, payload->Data, sizeof(float) * 3); // Preserve alpha if any //-V512 //-V1086 value_changed = accepted_drag_drop = true; } if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F)) { memcpy((float*)col, payload->Data, sizeof(float) * components); value_changed = accepted_drag_drop = true; } // Drag-drop payloads are always RGB if (accepted_drag_drop && (flags & ImGuiColorEditFlags_InputHSV)) ColorConvertRGBtoHSV(col[0], col[1], col[2], col[0], col[1], col[2]); EndDragDropTarget(); } // When picker is being actively used, use its active id so IsItemActive() will function on ColorEdit4(). if (picker_active_window && g.ActiveId != 0 && g.ActiveIdWindow == picker_active_window) g.LastItemData.ID = g.ActiveId; if (value_changed && g.LastItemData.ID != 0) // In case of ID collision, the second EndGroup() won't catch g.ActiveId MarkItemEdited(g.LastItemData.ID); return value_changed; } bool ImGui::ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags) { float col4[4] = { col[0], col[1], col[2], 1.0f }; if (!ColorPicker4(label, col4, flags | ImGuiColorEditFlags_NoAlpha)) return false; col[0] = col4[0]; col[1] = col4[1]; col[2] = col4[2]; return true; } // Helper for ColorPicker4() static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, float bar_w, float alpha) { ImU32 alpha8 = IM_F32_TO_INT8_SAT(alpha); ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x + 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Right, IM_COL32(0,0,0,alpha8)); ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + half_sz.x, pos.y), half_sz, ImGuiDir_Right, IM_COL32(255,255,255,alpha8)); ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x - 1, pos.y), ImVec2(half_sz.x + 2, half_sz.y + 1), ImGuiDir_Left, IM_COL32(0,0,0,alpha8)); ImGui::RenderArrowPointingAt(draw_list, ImVec2(pos.x + bar_w - half_sz.x, pos.y), half_sz, ImGuiDir_Left, IM_COL32(255,255,255,alpha8)); } // Note: ColorPicker4() only accesses 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. // (In C++ the 'float col[4]' notation for a function argument is equivalent to 'float* col', we only specify a size to facilitate understanding of the code.) // FIXME: we adjust the big color square height based on item width, which may cause a flickering feedback loop (if automatic height makes a vertical scrollbar appears, affecting automatic width..) // FIXME: this is trying to be aware of style.Alpha but not fully correct. Also, the color wheel will have overlapping glitches with (style.Alpha < 1.0) bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags, const float* ref_col) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImDrawList* draw_list = window->DrawList; ImGuiStyle& style = g.Style; ImGuiIO& io = g.IO; const float width = CalcItemWidth(); const bool is_readonly = ((g.NextItemData.ItemFlags | g.CurrentItemFlags) & ImGuiItemFlags_ReadOnly) != 0; g.NextItemData.ClearFlags(); PushID(label); const bool set_current_color_edit_id = (g.ColorEditCurrentID == 0); if (set_current_color_edit_id) g.ColorEditCurrentID = window->IDStack.back(); BeginGroup(); if (!(flags & ImGuiColorEditFlags_NoSidePreview)) flags |= ImGuiColorEditFlags_NoSmallPreview; // Context menu: display and store options. if (!(flags & ImGuiColorEditFlags_NoOptions)) ColorPickerOptionsPopup(col, flags); // Read stored options if (!(flags & ImGuiColorEditFlags_PickerMask_)) flags |= ((g.ColorEditOptions & ImGuiColorEditFlags_PickerMask_) ? g.ColorEditOptions : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_PickerMask_; if (!(flags & ImGuiColorEditFlags_InputMask_)) flags |= ((g.ColorEditOptions & ImGuiColorEditFlags_InputMask_) ? g.ColorEditOptions : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_InputMask_; IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_PickerMask_)); // Check that only 1 is selected IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check that only 1 is selected if (!(flags & ImGuiColorEditFlags_NoOptions)) flags |= (g.ColorEditOptions & ImGuiColorEditFlags_AlphaBar); // Setup int components = (flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4; bool alpha_bar = (flags & ImGuiColorEditFlags_AlphaBar) && !(flags & ImGuiColorEditFlags_NoAlpha); ImVec2 picker_pos = window->DC.CursorPos; float square_sz = GetFrameHeight(); float bars_width = square_sz; // Arbitrary smallish width of Hue/Alpha picking bars float sv_picker_size = ImMax(bars_width * 1, width - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x; float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x; float bars_triangles_half_sz = IM_TRUNC(bars_width * 0.20f); float backup_initial_col[4]; memcpy(backup_initial_col, col, components * sizeof(float)); float wheel_thickness = sv_picker_size * 0.08f; float wheel_r_outer = sv_picker_size * 0.50f; float wheel_r_inner = wheel_r_outer - wheel_thickness; ImVec2 wheel_center(picker_pos.x + (sv_picker_size + bars_width)*0.5f, picker_pos.y + sv_picker_size * 0.5f); // Note: the triangle is displayed rotated with triangle_pa pointing to Hue, but most coordinates stays unrotated for logic. float triangle_r = wheel_r_inner - (int)(sv_picker_size * 0.027f); ImVec2 triangle_pa = ImVec2(triangle_r, 0.0f); // Hue point. ImVec2 triangle_pb = ImVec2(triangle_r * -0.5f, triangle_r * -0.866025f); // Black point. ImVec2 triangle_pc = ImVec2(triangle_r * -0.5f, triangle_r * +0.866025f); // White point. float H = col[0], S = col[1], V = col[2]; float R = col[0], G = col[1], B = col[2]; if (flags & ImGuiColorEditFlags_InputRGB) { // Hue is lost when converting from grayscale rgb (saturation=0). Restore it. ColorConvertRGBtoHSV(R, G, B, H, S, V); ColorEditRestoreHS(col, &H, &S, &V); } else if (flags & ImGuiColorEditFlags_InputHSV) { ColorConvertHSVtoRGB(H, S, V, R, G, B); } bool value_changed = false, value_changed_h = false, value_changed_sv = false; PushItemFlag(ImGuiItemFlags_NoNav, true); if (flags & ImGuiColorEditFlags_PickerHueWheel) { // Hue wheel + SV triangle logic InvisibleButton("hsv", ImVec2(sv_picker_size + style.ItemInnerSpacing.x + bars_width, sv_picker_size)); if (IsItemActive() && !is_readonly) { ImVec2 initial_off = g.IO.MouseClickedPos[0] - wheel_center; ImVec2 current_off = g.IO.MousePos - wheel_center; float initial_dist2 = ImLengthSqr(initial_off); if (initial_dist2 >= (wheel_r_inner - 1) * (wheel_r_inner - 1) && initial_dist2 <= (wheel_r_outer + 1) * (wheel_r_outer + 1)) { // Interactive with Hue wheel H = ImAtan2(current_off.y, current_off.x) / IM_PI * 0.5f; if (H < 0.0f) H += 1.0f; value_changed = value_changed_h = true; } float cos_hue_angle = ImCos(-H * 2.0f * IM_PI); float sin_hue_angle = ImSin(-H * 2.0f * IM_PI); if (ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, ImRotate(initial_off, cos_hue_angle, sin_hue_angle))) { // Interacting with SV triangle ImVec2 current_off_unrotated = ImRotate(current_off, cos_hue_angle, sin_hue_angle); if (!ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated)) current_off_unrotated = ImTriangleClosestPoint(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated); float uu, vv, ww; ImTriangleBarycentricCoords(triangle_pa, triangle_pb, triangle_pc, current_off_unrotated, uu, vv, ww); V = ImClamp(1.0f - vv, 0.0001f, 1.0f); S = ImClamp(uu / V, 0.0001f, 1.0f); value_changed = value_changed_sv = true; } } if (!(flags & ImGuiColorEditFlags_NoOptions)) OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight); } else if (flags & ImGuiColorEditFlags_PickerHueBar) { // SV rectangle logic InvisibleButton("sv", ImVec2(sv_picker_size, sv_picker_size)); if (IsItemActive() && !is_readonly) { S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size - 1)); V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1)); ColorEditRestoreH(col, &H); // Greatly reduces hue jitter and reset to 0 when hue == 255 and color is rapidly modified using SV square. value_changed = value_changed_sv = true; } if (!(flags & ImGuiColorEditFlags_NoOptions)) OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight); // Hue bar logic SetCursorScreenPos(ImVec2(bar0_pos_x, picker_pos.y)); InvisibleButton("hue", ImVec2(bars_width, sv_picker_size)); if (IsItemActive() && !is_readonly) { H = ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1)); value_changed = value_changed_h = true; } } // Alpha bar logic if (alpha_bar) { SetCursorScreenPos(ImVec2(bar1_pos_x, picker_pos.y)); InvisibleButton("alpha", ImVec2(bars_width, sv_picker_size)); if (IsItemActive()) { col[3] = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1)); value_changed = true; } } PopItemFlag(); // ImGuiItemFlags_NoNav if (!(flags & ImGuiColorEditFlags_NoSidePreview)) { SameLine(0, style.ItemInnerSpacing.x); BeginGroup(); } if (!(flags & ImGuiColorEditFlags_NoLabel)) { const char* label_display_end = FindRenderedTextEnd(label); if (label != label_display_end) { if ((flags & ImGuiColorEditFlags_NoSidePreview)) SameLine(0, style.ItemInnerSpacing.x); TextEx(label, label_display_end); } } if (!(flags & ImGuiColorEditFlags_NoSidePreview)) { PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true); ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); if ((flags & ImGuiColorEditFlags_NoLabel)) Text("Current"); ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf | ImGuiColorEditFlags_NoTooltip; ColorButton("##current", col_v4, (flags & sub_flags_to_forward), ImVec2(square_sz * 3, square_sz * 2)); if (ref_col != NULL) { Text("Original"); ImVec4 ref_col_v4(ref_col[0], ref_col[1], ref_col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : ref_col[3]); if (ColorButton("##original", ref_col_v4, (flags & sub_flags_to_forward), ImVec2(square_sz * 3, square_sz * 2))) { memcpy(col, ref_col, components * sizeof(float)); value_changed = true; } } PopItemFlag(); EndGroup(); } // Convert back color to RGB if (value_changed_h || value_changed_sv) { if (flags & ImGuiColorEditFlags_InputRGB) { ColorConvertHSVtoRGB(H, S, V, col[0], col[1], col[2]); g.ColorEditSavedHue = H; g.ColorEditSavedSat = S; g.ColorEditSavedID = g.ColorEditCurrentID; g.ColorEditSavedColor = ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0)); } else if (flags & ImGuiColorEditFlags_InputHSV) { col[0] = H; col[1] = S; col[2] = V; } } // R,G,B and H,S,V slider color editor bool value_changed_fix_hue_wrap = false; if ((flags & ImGuiColorEditFlags_NoInputs) == 0) { PushItemWidth((alpha_bar ? bar1_pos_x : bar0_pos_x) + bars_width - picker_pos.x); ImGuiColorEditFlags sub_flags_to_forward = ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoSmallPreview | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf; ImGuiColorEditFlags sub_flags = (flags & sub_flags_to_forward) | ImGuiColorEditFlags_NoPicker; if (flags & ImGuiColorEditFlags_DisplayRGB || (flags & ImGuiColorEditFlags_DisplayMask_) == 0) if (ColorEdit4("##rgb", col, sub_flags | ImGuiColorEditFlags_DisplayRGB)) { // FIXME: Hackily differentiating using the DragInt (ActiveId != 0 && !ActiveIdAllowOverlap) vs. using the InputText or DropTarget. // For the later we don't want to run the hue-wrap canceling code. If you are well versed in HSV picker please provide your input! (See #2050) value_changed_fix_hue_wrap = (g.ActiveId != 0 && !g.ActiveIdAllowOverlap); value_changed = true; } if (flags & ImGuiColorEditFlags_DisplayHSV || (flags & ImGuiColorEditFlags_DisplayMask_) == 0) value_changed |= ColorEdit4("##hsv", col, sub_flags | ImGuiColorEditFlags_DisplayHSV); if (flags & ImGuiColorEditFlags_DisplayHex || (flags & ImGuiColorEditFlags_DisplayMask_) == 0) value_changed |= ColorEdit4("##hex", col, sub_flags | ImGuiColorEditFlags_DisplayHex); PopItemWidth(); } // Try to cancel hue wrap (after ColorEdit4 call), if any if (value_changed_fix_hue_wrap && (flags & ImGuiColorEditFlags_InputRGB)) { float new_H, new_S, new_V; ColorConvertRGBtoHSV(col[0], col[1], col[2], new_H, new_S, new_V); if (new_H <= 0 && H > 0) { if (new_V <= 0 && V != new_V) ColorConvertHSVtoRGB(H, S, new_V <= 0 ? V * 0.5f : new_V, col[0], col[1], col[2]); else if (new_S <= 0) ColorConvertHSVtoRGB(H, new_S <= 0 ? S * 0.5f : new_S, new_V, col[0], col[1], col[2]); } } if (value_changed) { if (flags & ImGuiColorEditFlags_InputRGB) { R = col[0]; G = col[1]; B = col[2]; ColorConvertRGBtoHSV(R, G, B, H, S, V); ColorEditRestoreHS(col, &H, &S, &V); // Fix local Hue as display below will use it immediately. } else if (flags & ImGuiColorEditFlags_InputHSV) { H = col[0]; S = col[1]; V = col[2]; ColorConvertHSVtoRGB(H, S, V, R, G, B); } } const int style_alpha8 = IM_F32_TO_INT8_SAT(style.Alpha); const ImU32 col_black = IM_COL32(0,0,0,style_alpha8); const ImU32 col_white = IM_COL32(255,255,255,style_alpha8); const ImU32 col_midgrey = IM_COL32(128,128,128,style_alpha8); const ImU32 col_hues[6 + 1] = { IM_COL32(255,0,0,style_alpha8), IM_COL32(255,255,0,style_alpha8), IM_COL32(0,255,0,style_alpha8), IM_COL32(0,255,255,style_alpha8), IM_COL32(0,0,255,style_alpha8), IM_COL32(255,0,255,style_alpha8), IM_COL32(255,0,0,style_alpha8) }; ImVec4 hue_color_f(1, 1, 1, style.Alpha); ColorConvertHSVtoRGB(H, 1, 1, hue_color_f.x, hue_color_f.y, hue_color_f.z); ImU32 hue_color32 = ColorConvertFloat4ToU32(hue_color_f); ImU32 user_col32_striped_of_alpha = ColorConvertFloat4ToU32(ImVec4(R, G, B, style.Alpha)); // Important: this is still including the main rendering/style alpha!! ImVec2 sv_cursor_pos; if (flags & ImGuiColorEditFlags_PickerHueWheel) { // Render Hue Wheel const float aeps = 0.5f / wheel_r_outer; // Half a pixel arc length in radians (2pi cancels out). const int segment_per_arc = ImMax(4, (int)wheel_r_outer / 12); for (int n = 0; n < 6; n++) { const float a0 = (n) /6.0f * 2.0f * IM_PI - aeps; const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps; const int vert_start_idx = draw_list->VtxBuffer.Size; draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc); draw_list->PathStroke(col_white, 0, wheel_thickness); const int vert_end_idx = draw_list->VtxBuffer.Size; // Paint colors over existing vertices ImVec2 gradient_p0(wheel_center.x + ImCos(a0) * wheel_r_inner, wheel_center.y + ImSin(a0) * wheel_r_inner); ImVec2 gradient_p1(wheel_center.x + ImCos(a1) * wheel_r_inner, wheel_center.y + ImSin(a1) * wheel_r_inner); ShadeVertsLinearColorGradientKeepAlpha(draw_list, vert_start_idx, vert_end_idx, gradient_p0, gradient_p1, col_hues[n], col_hues[n + 1]); } // Render Cursor + preview on Hue Wheel float cos_hue_angle = ImCos(H * 2.0f * IM_PI); float sin_hue_angle = ImSin(H * 2.0f * IM_PI); ImVec2 hue_cursor_pos(wheel_center.x + cos_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f, wheel_center.y + sin_hue_angle * (wheel_r_inner + wheel_r_outer) * 0.5f); float hue_cursor_rad = value_changed_h ? wheel_thickness * 0.65f : wheel_thickness * 0.55f; int hue_cursor_segments = draw_list->_CalcCircleAutoSegmentCount(hue_cursor_rad); // Lock segment count so the +1 one matches others. draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments); draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad + 1, col_midgrey, hue_cursor_segments); draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments); // Render SV triangle (rotated according to hue) ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle); ImVec2 trb = wheel_center + ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle); ImVec2 trc = wheel_center + ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle); ImVec2 uv_white = GetFontTexUvWhitePixel(); draw_list->PrimReserve(3, 3); draw_list->PrimVtx(tra, uv_white, hue_color32); draw_list->PrimVtx(trb, uv_white, col_black); draw_list->PrimVtx(trc, uv_white, col_white); draw_list->AddTriangle(tra, trb, trc, col_midgrey, 1.5f); sv_cursor_pos = ImLerp(ImLerp(trc, tra, ImSaturate(S)), trb, ImSaturate(1 - V)); } else if (flags & ImGuiColorEditFlags_PickerHueBar) { // Render SV Square draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), col_white, hue_color32, hue_color32, col_white); draw_list->AddRectFilledMultiColor(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0, 0, col_black, col_black); RenderFrameBorder(picker_pos, picker_pos + ImVec2(sv_picker_size, sv_picker_size), 0.0f); sv_cursor_pos.x = ImClamp(IM_ROUND(picker_pos.x + ImSaturate(S) * sv_picker_size), picker_pos.x + 2, picker_pos.x + sv_picker_size - 2); // Sneakily prevent the circle to stick out too much sv_cursor_pos.y = ImClamp(IM_ROUND(picker_pos.y + ImSaturate(1 - V) * sv_picker_size), picker_pos.y + 2, picker_pos.y + sv_picker_size - 2); // Render Hue Bar for (int i = 0; i < 6; ++i) draw_list->AddRectFilledMultiColor(ImVec2(bar0_pos_x, picker_pos.y + i * (sv_picker_size / 6)), ImVec2(bar0_pos_x + bars_width, picker_pos.y + (i + 1) * (sv_picker_size / 6)), col_hues[i], col_hues[i], col_hues[i + 1], col_hues[i + 1]); float bar0_line_y = IM_ROUND(picker_pos.y + H * sv_picker_size); RenderFrameBorder(ImVec2(bar0_pos_x, picker_pos.y), ImVec2(bar0_pos_x + bars_width, picker_pos.y + sv_picker_size), 0.0f); RenderArrowsForVerticalBar(draw_list, ImVec2(bar0_pos_x - 1, bar0_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha); } // Render cursor/preview circle (clamp S/V within 0..1 range because floating points colors may lead HSV values to be out of range) float sv_cursor_rad = value_changed_sv ? wheel_thickness * 0.55f : wheel_thickness * 0.40f; int sv_cursor_segments = draw_list->_CalcCircleAutoSegmentCount(sv_cursor_rad); // Lock segment count so the +1 one matches others. draw_list->AddCircleFilled(sv_cursor_pos, sv_cursor_rad, user_col32_striped_of_alpha, sv_cursor_segments); draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad + 1, col_midgrey, sv_cursor_segments); draw_list->AddCircle(sv_cursor_pos, sv_cursor_rad, col_white, sv_cursor_segments); // Render alpha bar if (alpha_bar) { float alpha = ImSaturate(col[3]); ImRect bar1_bb(bar1_pos_x, picker_pos.y, bar1_pos_x + bars_width, picker_pos.y + sv_picker_size); RenderColorRectWithAlphaCheckerboard(draw_list, bar1_bb.Min, bar1_bb.Max, 0, bar1_bb.GetWidth() / 2.0f, ImVec2(0.0f, 0.0f)); draw_list->AddRectFilledMultiColor(bar1_bb.Min, bar1_bb.Max, user_col32_striped_of_alpha, user_col32_striped_of_alpha, user_col32_striped_of_alpha & ~IM_COL32_A_MASK, user_col32_striped_of_alpha & ~IM_COL32_A_MASK); float bar1_line_y = IM_ROUND(picker_pos.y + (1.0f - alpha) * sv_picker_size); RenderFrameBorder(bar1_bb.Min, bar1_bb.Max, 0.0f); RenderArrowsForVerticalBar(draw_list, ImVec2(bar1_pos_x - 1, bar1_line_y), ImVec2(bars_triangles_half_sz + 1, bars_triangles_half_sz), bars_width + 2.0f, style.Alpha); } EndGroup(); if (value_changed && memcmp(backup_initial_col, col, components * sizeof(float)) == 0) value_changed = false; if (value_changed && g.LastItemData.ID != 0) // In case of ID collision, the second EndGroup() won't catch g.ActiveId MarkItemEdited(g.LastItemData.ID); if (set_current_color_edit_id) g.ColorEditCurrentID = 0; PopID(); return value_changed; } // A little color square. Return true when clicked. // FIXME: May want to display/ignore the alpha component in the color display? Yet show it in the tooltip. // 'desc_id' is not called 'label' because we don't display it next to the button, but only in the tooltip. // Note that 'col' may be encoded in HSV if ImGuiColorEditFlags_InputHSV is set. bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags, const ImVec2& size_arg) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; const ImGuiID id = window->GetID(desc_id); const float default_size = GetFrameHeight(); const ImVec2 size(size_arg.x == 0.0f ? default_size : size_arg.x, size_arg.y == 0.0f ? default_size : size_arg.y); const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); ItemSize(bb, (size.y >= default_size) ? g.Style.FramePadding.y : 0.0f); if (!ItemAdd(bb, id)) return false; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held); if (flags & ImGuiColorEditFlags_NoAlpha) flags &= ~(ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf); ImVec4 col_rgb = col; if (flags & ImGuiColorEditFlags_InputHSV) ColorConvertHSVtoRGB(col_rgb.x, col_rgb.y, col_rgb.z, col_rgb.x, col_rgb.y, col_rgb.z); ImVec4 col_rgb_without_alpha(col_rgb.x, col_rgb.y, col_rgb.z, 1.0f); float grid_step = ImMin(size.x, size.y) / 2.99f; float rounding = ImMin(g.Style.FrameRounding, grid_step * 0.5f); ImRect bb_inner = bb; float off = 0.0f; if ((flags & ImGuiColorEditFlags_NoBorder) == 0) { off = -0.75f; // The border (using Col_FrameBg) tends to look off when color is near-opaque and rounding is enabled. This offset seemed like a good middle ground to reduce those artifacts. bb_inner.Expand(off); } if ((flags & ImGuiColorEditFlags_AlphaPreviewHalf) && col_rgb.w < 1.0f) { float mid_x = IM_ROUND((bb_inner.Min.x + bb_inner.Max.x) * 0.5f); RenderColorRectWithAlphaCheckerboard(window->DrawList, ImVec2(bb_inner.Min.x + grid_step, bb_inner.Min.y), bb_inner.Max, GetColorU32(col_rgb), grid_step, ImVec2(-grid_step + off, off), rounding, ImDrawFlags_RoundCornersRight); window->DrawList->AddRectFilled(bb_inner.Min, ImVec2(mid_x, bb_inner.Max.y), GetColorU32(col_rgb_without_alpha), rounding, ImDrawFlags_RoundCornersLeft); } else { // Because GetColorU32() multiplies by the global style Alpha and we don't want to display a checkerboard if the source code had no alpha ImVec4 col_source = (flags & ImGuiColorEditFlags_AlphaPreview) ? col_rgb : col_rgb_without_alpha; if (col_source.w < 1.0f) RenderColorRectWithAlphaCheckerboard(window->DrawList, bb_inner.Min, bb_inner.Max, GetColorU32(col_source), grid_step, ImVec2(off, off), rounding); else window->DrawList->AddRectFilled(bb_inner.Min, bb_inner.Max, GetColorU32(col_source), rounding); } RenderNavHighlight(bb, id); if ((flags & ImGuiColorEditFlags_NoBorder) == 0) { if (g.Style.FrameBorderSize > 0.0f) RenderFrameBorder(bb.Min, bb.Max, rounding); else window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border } // Drag and Drop Source // NB: The ActiveId test is merely an optional micro-optimization, BeginDragDropSource() does the same test. if (g.ActiveId == id && !(flags & ImGuiColorEditFlags_NoDragDrop) && BeginDragDropSource()) { if (flags & ImGuiColorEditFlags_NoAlpha) SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F, &col_rgb, sizeof(float) * 3, ImGuiCond_Once); else SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, &col_rgb, sizeof(float) * 4, ImGuiCond_Once); ColorButton(desc_id, col, flags); SameLine(); TextEx("Color"); EndDragDropSource(); } // Tooltip if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered && IsItemHovered(ImGuiHoveredFlags_ForTooltip)) ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)); return pressed; } // Initialize/override default color options void ImGui::SetColorEditOptions(ImGuiColorEditFlags flags) { ImGuiContext& g = *GImGui; if ((flags & ImGuiColorEditFlags_DisplayMask_) == 0) flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DisplayMask_; if ((flags & ImGuiColorEditFlags_DataTypeMask_) == 0) flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DataTypeMask_; if ((flags & ImGuiColorEditFlags_PickerMask_) == 0) flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_PickerMask_; if ((flags & ImGuiColorEditFlags_InputMask_) == 0) flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_InputMask_; IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DisplayMask_)); // Check only 1 option is selected IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DataTypeMask_)); // Check only 1 option is selected IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_PickerMask_)); // Check only 1 option is selected IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check only 1 option is selected g.ColorEditOptions = flags; } // Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags) { ImGuiContext& g = *GImGui; if (!BeginTooltipEx(ImGuiTooltipFlags_OverridePrevious, ImGuiWindowFlags_None)) return; const char* text_end = text ? FindRenderedTextEnd(text, NULL) : text; if (text_end > text) { TextEx(text, text_end); Separator(); } ImVec2 sz(g.FontSize * 3 + g.Style.FramePadding.y * 2, g.FontSize * 3 + g.Style.FramePadding.y * 2); ImVec4 cf(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]); ColorButton("##preview", cf, (flags & (ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)) | ImGuiColorEditFlags_NoTooltip, sz); SameLine(); if ((flags & ImGuiColorEditFlags_InputRGB) || !(flags & ImGuiColorEditFlags_InputMask_)) { if (flags & ImGuiColorEditFlags_NoAlpha) Text("#%02X%02X%02X\nR: %d, G: %d, B: %d\n(%.3f, %.3f, %.3f)", cr, cg, cb, cr, cg, cb, col[0], col[1], col[2]); else Text("#%02X%02X%02X%02X\nR:%d, G:%d, B:%d, A:%d\n(%.3f, %.3f, %.3f, %.3f)", cr, cg, cb, ca, cr, cg, cb, ca, col[0], col[1], col[2], col[3]); } else if (flags & ImGuiColorEditFlags_InputHSV) { if (flags & ImGuiColorEditFlags_NoAlpha) Text("H: %.3f, S: %.3f, V: %.3f", col[0], col[1], col[2]); else Text("H: %.3f, S: %.3f, V: %.3f, A: %.3f", col[0], col[1], col[2], col[3]); } EndTooltip(); } void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags) { bool allow_opt_inputs = !(flags & ImGuiColorEditFlags_DisplayMask_); bool allow_opt_datatype = !(flags & ImGuiColorEditFlags_DataTypeMask_); if ((!allow_opt_inputs && !allow_opt_datatype) || !BeginPopup("context")) return; ImGuiContext& g = *GImGui; g.LockMarkEdited++; ImGuiColorEditFlags opts = g.ColorEditOptions; if (allow_opt_inputs) { if (RadioButton("RGB", (opts & ImGuiColorEditFlags_DisplayRGB) != 0)) opts = (opts & ~ImGuiColorEditFlags_DisplayMask_) | ImGuiColorEditFlags_DisplayRGB; if (RadioButton("HSV", (opts & ImGuiColorEditFlags_DisplayHSV) != 0)) opts = (opts & ~ImGuiColorEditFlags_DisplayMask_) | ImGuiColorEditFlags_DisplayHSV; if (RadioButton("Hex", (opts & ImGuiColorEditFlags_DisplayHex) != 0)) opts = (opts & ~ImGuiColorEditFlags_DisplayMask_) | ImGuiColorEditFlags_DisplayHex; } if (allow_opt_datatype) { if (allow_opt_inputs) Separator(); if (RadioButton("0..255", (opts & ImGuiColorEditFlags_Uint8) != 0)) opts = (opts & ~ImGuiColorEditFlags_DataTypeMask_) | ImGuiColorEditFlags_Uint8; if (RadioButton("0.00..1.00", (opts & ImGuiColorEditFlags_Float) != 0)) opts = (opts & ~ImGuiColorEditFlags_DataTypeMask_) | ImGuiColorEditFlags_Float; } if (allow_opt_inputs || allow_opt_datatype) Separator(); if (Button("Copy as..", ImVec2(-1, 0))) OpenPopup("Copy"); if (BeginPopup("Copy")) { int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]); char buf[64]; ImFormatString(buf, IM_ARRAYSIZE(buf), "(%.3ff, %.3ff, %.3ff, %.3ff)", col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); if (Selectable(buf)) SetClipboardText(buf); ImFormatString(buf, IM_ARRAYSIZE(buf), "(%d,%d,%d,%d)", cr, cg, cb, ca); if (Selectable(buf)) SetClipboardText(buf); ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", cr, cg, cb); if (Selectable(buf)) SetClipboardText(buf); if (!(flags & ImGuiColorEditFlags_NoAlpha)) { ImFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X%02X", cr, cg, cb, ca); if (Selectable(buf)) SetClipboardText(buf); } EndPopup(); } g.ColorEditOptions = opts; EndPopup(); g.LockMarkEdited--; } void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags flags) { bool allow_opt_picker = !(flags & ImGuiColorEditFlags_PickerMask_); bool allow_opt_alpha_bar = !(flags & ImGuiColorEditFlags_NoAlpha) && !(flags & ImGuiColorEditFlags_AlphaBar); if ((!allow_opt_picker && !allow_opt_alpha_bar) || !BeginPopup("context")) return; ImGuiContext& g = *GImGui; g.LockMarkEdited++; if (allow_opt_picker) { ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (GetFrameHeight() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function PushItemWidth(picker_size.x); for (int picker_type = 0; picker_type < 2; picker_type++) { // Draw small/thumbnail version of each picker type (over an invisible button for selection) if (picker_type > 0) Separator(); PushID(picker_type); ImGuiColorEditFlags picker_flags = ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoOptions | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_NoSidePreview | (flags & ImGuiColorEditFlags_NoAlpha); if (picker_type == 0) picker_flags |= ImGuiColorEditFlags_PickerHueBar; if (picker_type == 1) picker_flags |= ImGuiColorEditFlags_PickerHueWheel; ImVec2 backup_pos = GetCursorScreenPos(); if (Selectable("##selectable", false, 0, picker_size)) // By default, Selectable() is closing popup g.ColorEditOptions = (g.ColorEditOptions & ~ImGuiColorEditFlags_PickerMask_) | (picker_flags & ImGuiColorEditFlags_PickerMask_); SetCursorScreenPos(backup_pos); ImVec4 previewing_ref_col; memcpy(&previewing_ref_col, ref_col, sizeof(float) * ((picker_flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4)); ColorPicker4("##previewing_picker", &previewing_ref_col.x, picker_flags); PopID(); } PopItemWidth(); } if (allow_opt_alpha_bar) { if (allow_opt_picker) Separator(); CheckboxFlags("Alpha Bar", &g.ColorEditOptions, ImGuiColorEditFlags_AlphaBar); } EndPopup(); g.LockMarkEdited--; } //------------------------------------------------------------------------- // [SECTION] Widgets: TreeNode, CollapsingHeader, etc. //------------------------------------------------------------------------- // - TreeNode() // - TreeNodeV() // - TreeNodeEx() // - TreeNodeExV() // - TreeNodeBehavior() [Internal] // - TreePush() // - TreePop() // - GetTreeNodeToLabelSpacing() // - SetNextItemOpen() // - CollapsingHeader() //------------------------------------------------------------------------- bool ImGui::TreeNode(const char* str_id, const char* fmt, ...) { va_list args; va_start(args, fmt); bool is_open = TreeNodeExV(str_id, 0, fmt, args); va_end(args); return is_open; } bool ImGui::TreeNode(const void* ptr_id, const char* fmt, ...) { va_list args; va_start(args, fmt); bool is_open = TreeNodeExV(ptr_id, 0, fmt, args); va_end(args); return is_open; } bool ImGui::TreeNode(const char* label) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; return TreeNodeBehavior(window->GetID(label), 0, label, NULL); } bool ImGui::TreeNodeV(const char* str_id, const char* fmt, va_list args) { return TreeNodeExV(str_id, 0, fmt, args); } bool ImGui::TreeNodeV(const void* ptr_id, const char* fmt, va_list args) { return TreeNodeExV(ptr_id, 0, fmt, args); } bool ImGui::TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; return TreeNodeBehavior(window->GetID(label), flags, label, NULL); } bool ImGui::TreeNodeEx(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) { va_list args; va_start(args, fmt); bool is_open = TreeNodeExV(str_id, flags, fmt, args); va_end(args); return is_open; } bool ImGui::TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) { va_list args; va_start(args, fmt); bool is_open = TreeNodeExV(ptr_id, flags, fmt, args); va_end(args); return is_open; } bool ImGui::TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; const char* label, *label_end; ImFormatStringToTempBufferV(&label, &label_end, fmt, args); return TreeNodeBehavior(window->GetID(str_id), flags, label, label_end); } bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; const char* label, *label_end; ImFormatStringToTempBufferV(&label, &label_end, fmt, args); return TreeNodeBehavior(window->GetID(ptr_id), flags, label, label_end); } void ImGui::TreeNodeSetOpen(ImGuiID id, bool open) { ImGuiContext& g = *GImGui; ImGuiStorage* storage = g.CurrentWindow->DC.StateStorage; storage->SetInt(id, open ? 1 : 0); } bool ImGui::TreeNodeUpdateNextOpen(ImGuiID id, ImGuiTreeNodeFlags flags) { if (flags & ImGuiTreeNodeFlags_Leaf) return true; // We only write to the tree storage if the user clicks (or explicitly use the SetNextItemOpen function) ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; ImGuiStorage* storage = window->DC.StateStorage; bool is_open; if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasOpen) { if (g.NextItemData.OpenCond & ImGuiCond_Always) { is_open = g.NextItemData.OpenVal; TreeNodeSetOpen(id, is_open); } else { // We treat ImGuiCond_Once and ImGuiCond_FirstUseEver the same because tree node state are not saved persistently. const int stored_value = storage->GetInt(id, -1); if (stored_value == -1) { is_open = g.NextItemData.OpenVal; TreeNodeSetOpen(id, is_open); } else { is_open = stored_value != 0; } } } else { is_open = storage->GetInt(id, (flags & ImGuiTreeNodeFlags_DefaultOpen) ? 1 : 0) != 0; } // When logging is enabled, we automatically expand tree nodes (but *NOT* collapsing headers.. seems like sensible behavior). // NB- If we are above max depth we still allow manually opened nodes to be logged. if (g.LogEnabled && !(flags & ImGuiTreeNodeFlags_NoAutoOpenOnLog) && (window->DC.TreeDepth - g.LogDepthRef) < g.LogDepthToExpand) is_open = true; return is_open; } bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* label, const char* label_end) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0; const ImVec2 padding = (display_frame || (flags & ImGuiTreeNodeFlags_FramePadding)) ? style.FramePadding : ImVec2(style.FramePadding.x, ImMin(window->DC.CurrLineTextBaseOffset, style.FramePadding.y)); if (!label_end) label_end = FindRenderedTextEnd(label); const ImVec2 label_size = CalcTextSize(label, label_end, false); // We vertically grow up to current line height up the typical widget height. const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y * 2), label_size.y + padding.y * 2); const bool span_all_columns = (flags & ImGuiTreeNodeFlags_SpanAllColumns) != 0 && (g.CurrentTable != NULL); ImRect frame_bb; frame_bb.Min.x = span_all_columns ? window->ParentWorkRect.Min.x : (flags & ImGuiTreeNodeFlags_SpanFullWidth) ? window->WorkRect.Min.x : window->DC.CursorPos.x; frame_bb.Min.y = window->DC.CursorPos.y; frame_bb.Max.x = span_all_columns ? window->ParentWorkRect.Max.x : window->WorkRect.Max.x; frame_bb.Max.y = window->DC.CursorPos.y + frame_height; if (display_frame) { // Framed header expand a little outside the default padding, to the edge of InnerClipRect // (FIXME: May remove this at some point and make InnerClipRect align with WindowPadding.x instead of WindowPadding.x*0.5f) frame_bb.Min.x -= IM_TRUNC(window->WindowPadding.x * 0.5f - 1.0f); frame_bb.Max.x += IM_TRUNC(window->WindowPadding.x * 0.5f); } const float text_offset_x = g.FontSize + (display_frame ? padding.x * 3 : padding.x * 2); // Collapsing arrow width + Spacing const float text_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x * 2 : 0.0f); // Include collapsing ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y); ItemSize(ImVec2(text_width, frame_height), padding.y); // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing ImRect interact_bb = frame_bb; if (!display_frame && (flags & (ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_SpanAllColumns)) == 0) interact_bb.Max.x = frame_bb.Min.x + text_width + style.ItemSpacing.x * 2.0f; // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable.. const float backup_clip_rect_min_x = window->ClipRect.Min.x; const float backup_clip_rect_max_x = window->ClipRect.Max.x; if (span_all_columns) { window->ClipRect.Min.x = window->ParentWorkRect.Min.x; window->ClipRect.Max.x = window->ParentWorkRect.Max.x; } // Compute open and multi-select states before ItemAdd() as it clear NextItem data. bool is_open = TreeNodeUpdateNextOpen(id, flags); bool item_add = ItemAdd(interact_bb, id); g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDisplayRect; g.LastItemData.DisplayRect = frame_bb; if (span_all_columns) { window->ClipRect.Min.x = backup_clip_rect_min_x; window->ClipRect.Max.x = backup_clip_rect_max_x; } // If a NavLeft request is happening and ImGuiTreeNodeFlags_NavLeftJumpsBackHere enabled: // Store data for the current depth to allow returning to this node from any child item. // For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop(). // It will become tempting to enable ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default or move it to ImGuiStyle. // Currently only supports 32 level deep and we are fine with (1 << Depth) overflowing into a zero, easy to increase. if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) { g.NavTreeNodeStack.resize(g.NavTreeNodeStack.Size + 1); ImGuiNavTreeNodeData* nav_tree_node_data = &g.NavTreeNodeStack.back(); nav_tree_node_data->ID = id; nav_tree_node_data->InFlags = g.LastItemData.InFlags; nav_tree_node_data->NavRect = g.LastItemData.NavRect; window->DC.TreeJumpToParentOnPopMask |= (1 << window->DC.TreeDepth); } const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0; if (!item_add) { if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) TreePushOverrideID(id); IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0)); return is_open; } if (span_all_columns) { TablePushBackgroundChannel(); g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasClipRect; g.LastItemData.ClipRect = window->ClipRect; } ImGuiButtonFlags button_flags = ImGuiTreeNodeFlags_None; if ((flags & ImGuiTreeNodeFlags_AllowOverlap) || (g.LastItemData.InFlags & ImGuiItemFlags_AllowOverlap)) button_flags |= ImGuiButtonFlags_AllowOverlap; if (!is_leaf) button_flags |= ImGuiButtonFlags_PressedOnDragDropHold; // We allow clicking on the arrow section with keyboard modifiers held, in order to easily // allow browsing a tree while preserving selection with code implementing multi-selection patterns. // When clicking on the rest of the tree node we always disallow keyboard modifiers. const float arrow_hit_x1 = (text_pos.x - text_offset_x) - style.TouchExtraPadding.x; const float arrow_hit_x2 = (text_pos.x - text_offset_x) + (g.FontSize + padding.x * 2.0f) + style.TouchExtraPadding.x; const bool is_mouse_x_over_arrow = (g.IO.MousePos.x >= arrow_hit_x1 && g.IO.MousePos.x < arrow_hit_x2); if (window != g.HoveredWindow || !is_mouse_x_over_arrow) button_flags |= ImGuiButtonFlags_NoKeyModifiers; // Open behaviors can be altered with the _OpenOnArrow and _OnOnDoubleClick flags. // Some alteration have subtle effects (e.g. toggle on MouseUp vs MouseDown events) due to requirements for multi-selection and drag and drop support. // - Single-click on label = Toggle on MouseUp (default, when _OpenOnArrow=0) // - Single-click on arrow = Toggle on MouseDown (when _OpenOnArrow=0) // - Single-click on arrow = Toggle on MouseDown (when _OpenOnArrow=1) // - Double-click on label = Toggle on MouseDoubleClick (when _OpenOnDoubleClick=1) // - Double-click on arrow = Toggle on MouseDoubleClick (when _OpenOnDoubleClick=1 and _OpenOnArrow=0) // It is rather standard that arrow click react on Down rather than Up. // We set ImGuiButtonFlags_PressedOnClickRelease on OpenOnDoubleClick because we want the item to be active on the initial MouseDown in order for drag and drop to work. if (is_mouse_x_over_arrow) button_flags |= ImGuiButtonFlags_PressedOnClick; else if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; else button_flags |= ImGuiButtonFlags_PressedOnClickRelease; bool selected = (flags & ImGuiTreeNodeFlags_Selected) != 0; const bool was_selected = selected; bool hovered, held; bool pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); bool toggled = false; if (!is_leaf) { if (pressed && g.DragDropHoldJustPressedId != id) { if ((flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) == 0 || (g.NavActivateId == id)) toggled = true; if (flags & ImGuiTreeNodeFlags_OpenOnArrow) toggled |= is_mouse_x_over_arrow && !g.NavDisableMouseHover; // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job if ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) && g.IO.MouseClickedCount[0] == 2) toggled = true; } else if (pressed && g.DragDropHoldJustPressedId == id) { IM_ASSERT(button_flags & ImGuiButtonFlags_PressedOnDragDropHold); if (!is_open) // When using Drag and Drop "hold to open" we keep the node highlighted after opening, but never close it again. toggled = true; } if (g.NavId == id && g.NavMoveDir == ImGuiDir_Left && is_open) { toggled = true; NavClearPreferredPosForAxis(ImGuiAxis_X); NavMoveRequestCancel(); } if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right && !is_open) // If there's something upcoming on the line we may want to give it the priority? { toggled = true; NavClearPreferredPosForAxis(ImGuiAxis_X); NavMoveRequestCancel(); } if (toggled) { is_open = !is_open; window->DC.StateStorage->SetInt(id, is_open); g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledOpen; } } // In this branch, TreeNodeBehavior() cannot toggle the selection so this will never trigger. if (selected != was_selected) //-V547 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection; // Render const ImU32 text_col = GetColorU32(ImGuiCol_Text); ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_Compact; if (display_frame) { // Framed type const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding); RenderNavHighlight(frame_bb, id, nav_highlight_flags); if (flags & ImGuiTreeNodeFlags_Bullet) RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col); else if (!is_leaf) RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ((flags & ImGuiTreeNodeFlags_UpsideDownArrow) ? ImGuiDir_Up : ImGuiDir_Down) : ImGuiDir_Right, 1.0f); else // Leaf without bullet, left-adjusted text text_pos.x -= text_offset_x -padding.x; if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton) frame_bb.Max.x -= g.FontSize + style.FramePadding.x; if (g.LogEnabled) LogSetNextTextDecoration("###", "###"); } else { // Unframed typed for tree nodes if (hovered || selected) { const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false); } RenderNavHighlight(frame_bb, id, nav_highlight_flags); if (flags & ImGuiTreeNodeFlags_Bullet) RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col); else if (!is_leaf) RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.15f), text_col, is_open ? ((flags & ImGuiTreeNodeFlags_UpsideDownArrow) ? ImGuiDir_Up : ImGuiDir_Down) : ImGuiDir_Right, 0.70f); if (g.LogEnabled) LogSetNextTextDecoration(">", NULL); } if (span_all_columns) TablePopBackgroundChannel(); // Label if (display_frame) RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size); else RenderText(text_pos, label, label_end, false); if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) TreePushOverrideID(id); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0)); return is_open; } void ImGui::TreePush(const char* str_id) { ImGuiWindow* window = GetCurrentWindow(); Indent(); window->DC.TreeDepth++; PushID(str_id); } void ImGui::TreePush(const void* ptr_id) { ImGuiWindow* window = GetCurrentWindow(); Indent(); window->DC.TreeDepth++; PushID(ptr_id); } void ImGui::TreePushOverrideID(ImGuiID id) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; Indent(); window->DC.TreeDepth++; PushOverrideID(id); } void ImGui::TreePop() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; Unindent(); window->DC.TreeDepth--; ImU32 tree_depth_mask = (1 << window->DC.TreeDepth); // Handle Left arrow to move to parent tree node (when ImGuiTreeNodeFlags_NavLeftJumpsBackHere is enabled) if (window->DC.TreeJumpToParentOnPopMask & tree_depth_mask) // Only set during request { ImGuiNavTreeNodeData* nav_tree_node_data = &g.NavTreeNodeStack.back(); IM_ASSERT(nav_tree_node_data->ID == window->IDStack.back()); if (g.NavIdIsAlive && g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) NavMoveRequestResolveWithPastTreeNode(&g.NavMoveResultLocal, nav_tree_node_data); g.NavTreeNodeStack.pop_back(); } window->DC.TreeJumpToParentOnPopMask &= tree_depth_mask - 1; IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much. PopID(); } // Horizontal distance preceding label when using TreeNode() or Bullet() float ImGui::GetTreeNodeToLabelSpacing() { ImGuiContext& g = *GImGui; return g.FontSize + (g.Style.FramePadding.x * 2.0f); } // Set next TreeNode/CollapsingHeader open state. void ImGui::SetNextItemOpen(bool is_open, ImGuiCond cond) { ImGuiContext& g = *GImGui; if (g.CurrentWindow->SkipItems) return; g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasOpen; g.NextItemData.OpenVal = is_open; g.NextItemData.OpenCond = cond ? cond : ImGuiCond_Always; } // CollapsingHeader returns true when opened but do not indent nor push into the ID stack (because of the ImGuiTreeNodeFlags_NoTreePushOnOpen flag). // This is basically the same as calling TreeNodeEx(label, ImGuiTreeNodeFlags_CollapsingHeader). You can remove the _NoTreePushOnOpen flag if you want behavior closer to normal TreeNode(). bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; return TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_CollapsingHeader, label); } // p_visible == NULL : regular collapsing header // p_visible != NULL && *p_visible == true : show a small close button on the corner of the header, clicking the button will set *p_visible = false // p_visible != NULL && *p_visible == false : do not show the header at all // Do not mistake this with the Open state of the header itself, which you can adjust with SetNextItemOpen() or ImGuiTreeNodeFlags_DefaultOpen. bool ImGui::CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; if (p_visible && !*p_visible) return false; ImGuiID id = window->GetID(label); flags |= ImGuiTreeNodeFlags_CollapsingHeader; if (p_visible) flags |= ImGuiTreeNodeFlags_AllowOverlap | (ImGuiTreeNodeFlags)ImGuiTreeNodeFlags_ClipLabelForTrailingButton; bool is_open = TreeNodeBehavior(id, flags, label); if (p_visible != NULL) { // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. // FIXME: CloseButton can overlap into text, need find a way to clip the text somehow. ImGuiContext& g = *GImGui; ImGuiLastItemData last_item_backup = g.LastItemData; float button_size = g.FontSize; float button_x = ImMax(g.LastItemData.Rect.Min.x, g.LastItemData.Rect.Max.x - g.Style.FramePadding.x - button_size); float button_y = g.LastItemData.Rect.Min.y + g.Style.FramePadding.y; ImGuiID close_button_id = GetIDWithSeed("#CLOSE", NULL, id); if (CloseButton(close_button_id, ImVec2(button_x, button_y))) *p_visible = false; g.LastItemData = last_item_backup; } return is_open; } //------------------------------------------------------------------------- // [SECTION] Widgets: Selectable //------------------------------------------------------------------------- // - Selectable() //------------------------------------------------------------------------- // Tip: pass a non-visible label (e.g. "##hello") then you can use the space to draw other text or image. // But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID or use ##unique_id. // With this scheme, ImGuiSelectableFlags_SpanAllColumns and ImGuiSelectableFlags_AllowOverlap are also frequently used flags. // FIXME: Selectable() with (size.x == 0.0f) and (SelectableTextAlign.x > 0.0f) followed by SameLine() is currently not supported. bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; // Submit label or explicit size to ItemSize(), whereas ItemAdd() will submit a larger/spanning rectangle. ImGuiID id = window->GetID(label); ImVec2 label_size = CalcTextSize(label, NULL, true); ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y); ImVec2 pos = window->DC.CursorPos; pos.y += window->DC.CurrLineTextBaseOffset; ItemSize(size, 0.0f); // Fill horizontal space // We don't support (size < 0.0f) in Selectable() because the ItemSpacing extension would make explicitly right-aligned sizes not visibly match other widgets. const bool span_all_columns = (flags & ImGuiSelectableFlags_SpanAllColumns) != 0; const float min_x = span_all_columns ? window->ParentWorkRect.Min.x : pos.x; const float max_x = span_all_columns ? window->ParentWorkRect.Max.x : window->WorkRect.Max.x; if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_SpanAvailWidth)) size.x = ImMax(label_size.x, max_x - min_x); // Text stays at the submission position, but bounding box may be extended on both sides const ImVec2 text_min = pos; const ImVec2 text_max(min_x + size.x, pos.y + size.y); // Selectables are meant to be tightly packed together with no click-gap, so we extend their box to cover spacing between selectable. ImRect bb(min_x, pos.y, text_max.x, text_max.y); if ((flags & ImGuiSelectableFlags_NoPadWithHalfSpacing) == 0) { const float spacing_x = span_all_columns ? 0.0f : style.ItemSpacing.x; const float spacing_y = style.ItemSpacing.y; const float spacing_L = IM_TRUNC(spacing_x * 0.50f); const float spacing_U = IM_TRUNC(spacing_y * 0.50f); bb.Min.x -= spacing_L; bb.Min.y -= spacing_U; bb.Max.x += (spacing_x - spacing_L); bb.Max.y += (spacing_y - spacing_U); } //if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(0, 255, 0, 255)); } // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable.. const float backup_clip_rect_min_x = window->ClipRect.Min.x; const float backup_clip_rect_max_x = window->ClipRect.Max.x; if (span_all_columns) { window->ClipRect.Min.x = window->ParentWorkRect.Min.x; window->ClipRect.Max.x = window->ParentWorkRect.Max.x; } const bool disabled_item = (flags & ImGuiSelectableFlags_Disabled) != 0; const bool item_add = ItemAdd(bb, id, NULL, disabled_item ? ImGuiItemFlags_Disabled : ImGuiItemFlags_None); if (span_all_columns) { window->ClipRect.Min.x = backup_clip_rect_min_x; window->ClipRect.Max.x = backup_clip_rect_max_x; } if (!item_add) return false; const bool disabled_global = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0; if (disabled_item && !disabled_global) // Only testing this as an optimization BeginDisabled(); // FIXME: We can standardize the behavior of those two, we could also keep the fast path of override ClipRect + full push on render only, // which would be advantageous since most selectable are not selected. if (span_all_columns) { if (g.CurrentTable) TablePushBackgroundChannel(); else if (window->DC.CurrentColumns) PushColumnsBackground(); g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasClipRect; g.LastItemData.ClipRect = window->ClipRect; } // We use NoHoldingActiveID on menus so user can click and _hold_ on a menu then drag to browse child entries ImGuiButtonFlags button_flags = 0; if (flags & ImGuiSelectableFlags_NoHoldingActiveID) { button_flags |= ImGuiButtonFlags_NoHoldingActiveId; } if (flags & ImGuiSelectableFlags_NoSetKeyOwner) { button_flags |= ImGuiButtonFlags_NoSetKeyOwner; } if (flags & ImGuiSelectableFlags_SelectOnClick) { button_flags |= ImGuiButtonFlags_PressedOnClick; } if (flags & ImGuiSelectableFlags_SelectOnRelease) { button_flags |= ImGuiButtonFlags_PressedOnRelease; } if (flags & ImGuiSelectableFlags_AllowDoubleClick) { button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; } if ((flags & ImGuiSelectableFlags_AllowOverlap) || (g.LastItemData.InFlags & ImGuiItemFlags_AllowOverlap)) { button_flags |= ImGuiButtonFlags_AllowOverlap; } const bool was_selected = selected; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); // Auto-select when moved into // - This will be more fully fleshed in the range-select branch // - This is not exposed as it won't nicely work with some user side handling of shift/control // - We cannot do 'if (g.NavJustMovedToId != id) { selected = false; pressed = was_selected; }' for two reasons // - (1) it would require focus scope to be set, need exposing PushFocusScope() or equivalent (e.g. BeginSelection() calling PushFocusScope()) // - (2) usage will fail with clipped items // The multi-select API aim to fix those issues, e.g. may be replaced with a BeginSelection() API. if ((flags & ImGuiSelectableFlags_SelectOnNav) && g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == g.CurrentFocusScopeId) if (g.NavJustMovedToId == id) selected = pressed = true; // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover))) { if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent) { SetNavID(id, window->DC.NavLayerCurrent, g.CurrentFocusScopeId, WindowRectAbsToRel(window, bb)); // (bb == NavRect) g.NavDisableHighlight = true; } } if (pressed) MarkItemEdited(id); // In this branch, Selectable() cannot toggle the selection so this will never trigger. if (selected != was_selected) //-V547 g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection; // Render if (hovered || selected) { const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); RenderFrame(bb.Min, bb.Max, col, false, 0.0f); } if (g.NavId == id) RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_Compact | ImGuiNavHighlightFlags_NoRounding); if (span_all_columns) { if (g.CurrentTable) TablePopBackgroundChannel(); else if (window->DC.CurrentColumns) PopColumnsBackground(); } RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb); // Automatically close popups if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(g.LastItemData.InFlags & ImGuiItemFlags_SelectableDontClosePopup)) CloseCurrentPopup(); if (disabled_item && !disabled_global) EndDisabled(); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); return pressed; //-V1020 } bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags, const ImVec2& size_arg) { if (Selectable(label, *p_selected, flags, size_arg)) { *p_selected = !*p_selected; return true; } return false; } //------------------------------------------------------------------------- // [SECTION] Widgets: Typing-Select support //------------------------------------------------------------------------- // [Experimental] Currently not exposed in public API. // Consume character inputs and return search request, if any. // This would typically only be called on the focused window or location you want to grab inputs for, e.g. // if (ImGui::IsWindowFocused(...)) // if (ImGuiTypingSelectRequest* req = ImGui::GetTypingSelectRequest()) // focus_idx = ImGui::TypingSelectFindMatch(req, my_items.size(), [](void*, int n) { return my_items[n]->Name; }, &my_items, -1); // However the code is written in a way where calling it from multiple locations is safe (e.g. to obtain buffer). ImGuiTypingSelectRequest* ImGui::GetTypingSelectRequest(ImGuiTypingSelectFlags flags) { ImGuiContext& g = *GImGui; ImGuiTypingSelectState* data = &g.TypingSelectState; ImGuiTypingSelectRequest* out_request = &data->Request; // Clear buffer const float TYPING_SELECT_RESET_TIMER = 1.80f; // FIXME: Potentially move to IO config. const int TYPING_SELECT_SINGLE_CHAR_COUNT_FOR_LOCK = 4; // Lock single char matching when repeating same char 4 times if (data->SearchBuffer[0] != 0) { bool clear_buffer = false; clear_buffer |= (g.NavFocusScopeId != data->FocusScope); clear_buffer |= (data->LastRequestTime + TYPING_SELECT_RESET_TIMER < g.Time); clear_buffer |= g.NavAnyRequest; clear_buffer |= g.ActiveId != 0 && g.NavActivateId == 0; // Allow temporary SPACE activation to not interfere clear_buffer |= IsKeyPressed(ImGuiKey_Escape) || IsKeyPressed(ImGuiKey_Enter); clear_buffer |= IsKeyPressed(ImGuiKey_Backspace) && (flags & ImGuiTypingSelectFlags_AllowBackspace) == 0; //if (clear_buffer) { IMGUI_DEBUG_LOG("GetTypingSelectRequest(): Clear SearchBuffer.\n"); } if (clear_buffer) data->Clear(); } // Append to buffer const int buffer_max_len = IM_ARRAYSIZE(data->SearchBuffer) - 1; int buffer_len = (int)strlen(data->SearchBuffer); bool select_request = false; for (ImWchar w : g.IO.InputQueueCharacters) { const int w_len = ImTextCountUtf8BytesFromStr(&w, &w + 1); if (w < 32 || (buffer_len == 0 && ImCharIsBlankW(w)) || (buffer_len + w_len > buffer_max_len)) // Ignore leading blanks continue; char w_buf[5]; ImTextCharToUtf8(w_buf, (unsigned int)w); if (data->SingleCharModeLock && w_len == out_request->SingleCharSize && memcmp(w_buf, data->SearchBuffer, w_len) == 0) { select_request = true; // Same character: don't need to append to buffer. continue; } if (data->SingleCharModeLock) { data->Clear(); // Different character: clear buffer_len = 0; } memcpy(data->SearchBuffer + buffer_len, w_buf, w_len + 1); // Append buffer_len += w_len; select_request = true; } g.IO.InputQueueCharacters.resize(0); // Handle backspace if ((flags & ImGuiTypingSelectFlags_AllowBackspace) && IsKeyPressed(ImGuiKey_Backspace, 0, ImGuiInputFlags_Repeat)) { char* p = (char*)(void*)ImTextFindPreviousUtf8Codepoint(data->SearchBuffer, data->SearchBuffer + buffer_len); *p = 0; buffer_len = (int)(p - data->SearchBuffer); } // Return request if any if (buffer_len == 0) return NULL; if (select_request) { data->FocusScope = g.NavFocusScopeId; data->LastRequestFrame = g.FrameCount; data->LastRequestTime = (float)g.Time; } out_request->Flags = flags; out_request->SearchBufferLen = buffer_len; out_request->SearchBuffer = data->SearchBuffer; out_request->SelectRequest = (data->LastRequestFrame == g.FrameCount); out_request->SingleCharMode = false; out_request->SingleCharSize = 0; // Calculate if buffer contains the same character repeated. // - This can be used to implement a special search mode on first character. // - Performed on UTF-8 codepoint for correctness. // - SingleCharMode is always set for first input character, because it usually leads to a "next". if (flags & ImGuiTypingSelectFlags_AllowSingleCharMode) { const char* buf_begin = out_request->SearchBuffer; const char* buf_end = out_request->SearchBuffer + out_request->SearchBufferLen; const int c0_len = ImTextCountUtf8BytesFromChar(buf_begin, buf_end); const char* p = buf_begin + c0_len; for (; p < buf_end; p += c0_len) if (memcmp(buf_begin, p, (size_t)c0_len) != 0) break; const int single_char_count = (p == buf_end) ? (out_request->SearchBufferLen / c0_len) : 0; out_request->SingleCharMode = (single_char_count > 0 || data->SingleCharModeLock); out_request->SingleCharSize = (ImS8)c0_len; data->SingleCharModeLock |= (single_char_count >= TYPING_SELECT_SINGLE_CHAR_COUNT_FOR_LOCK); // From now on we stop search matching to lock to single char mode. } return out_request; } static int ImStrimatchlen(const char* s1, const char* s1_end, const char* s2) { int match_len = 0; while (s1 < s1_end && ImToUpper(*s1++) == ImToUpper(*s2++)) match_len++; return match_len; } // Default handler for finding a result for typing-select. You may implement your own. // You might want to display a tooltip to visualize the current request SearchBuffer // When SingleCharMode is set: // - it is better to NOT display a tooltip of other on-screen display indicator. // - the index of the currently focused item is required. // if your SetNextItemSelectionData() values are indices, you can obtain it from ImGuiMultiSelectIO::NavIdItem, otherwise from g.NavLastValidSelectionUserData. int ImGui::TypingSelectFindMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx) { if (req == NULL || req->SelectRequest == false) // Support NULL parameter so both calls can be done from same spot. return -1; int idx = -1; if (req->SingleCharMode && (req->Flags & ImGuiTypingSelectFlags_AllowSingleCharMode)) idx = TypingSelectFindNextSingleCharMatch(req, items_count, get_item_name_func, user_data, nav_item_idx); else idx = TypingSelectFindBestLeadingMatch(req, items_count, get_item_name_func, user_data); if (idx != -1) NavRestoreHighlightAfterMove(); return idx; } // Special handling when a single character is repeated: perform search on a single letter and goes to next. int ImGui::TypingSelectFindNextSingleCharMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx) { // FIXME: Assume selection user data is index. Would be extremely practical. //if (nav_item_idx == -1) // nav_item_idx = (int)g.NavLastValidSelectionUserData; int first_match_idx = -1; bool return_next_match = false; for (int idx = 0; idx < items_count; idx++) { const char* item_name = get_item_name_func(user_data, idx); if (ImStrimatchlen(req->SearchBuffer, req->SearchBuffer + req->SingleCharSize, item_name) < req->SingleCharSize) continue; if (return_next_match) // Return next matching item after current item. return idx; if (first_match_idx == -1 && nav_item_idx == -1) // Return first match immediately if we don't have a nav_item_idx value. return idx; if (first_match_idx == -1) // Record first match for wrapping. first_match_idx = idx; if (nav_item_idx == idx) // Record that we encountering nav_item so we can return next match. return_next_match = true; } return first_match_idx; // First result } int ImGui::TypingSelectFindBestLeadingMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data) { int longest_match_idx = -1; int longest_match_len = 0; for (int idx = 0; idx < items_count; idx++) { const char* item_name = get_item_name_func(user_data, idx); const int match_len = ImStrimatchlen(req->SearchBuffer, req->SearchBuffer + req->SearchBufferLen, item_name); if (match_len <= longest_match_len) continue; longest_match_idx = idx; longest_match_len = match_len; if (match_len == req->SearchBufferLen) break; } return longest_match_idx; } void ImGui::DebugNodeTypingSelectState(ImGuiTypingSelectState* data) { #ifndef IMGUI_DISABLE_DEBUG_TOOLS Text("SearchBuffer = \"%s\"", data->SearchBuffer); Text("SingleCharMode = %d, Size = %d, Lock = %d", data->Request.SingleCharMode, data->Request.SingleCharSize, data->SingleCharModeLock); Text("LastRequest = time: %.2f, frame: %d", data->LastRequestTime, data->LastRequestFrame); #else IM_UNUSED(data); #endif } //------------------------------------------------------------------------- // [SECTION] Widgets: Multi-Select support //------------------------------------------------------------------------- void ImGui::SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_data) { // Note that flags will be cleared by ItemAdd(), so it's only useful for Navigation code! // This designed so widgets can also cheaply set this before calling ItemAdd(), so we are not tied to MultiSelect api. ImGuiContext& g = *GImGui; g.NextItemData.ItemFlags |= ImGuiItemFlags_HasSelectionUserData; g.NextItemData.SelectionUserData = selection_user_data; } //------------------------------------------------------------------------- // [SECTION] Widgets: ListBox //------------------------------------------------------------------------- // - BeginListBox() // - EndListBox() // - ListBox() //------------------------------------------------------------------------- // This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label. // Tip: To have a list filling the entire window width, use size.x = -FLT_MIN and pass an non-visible label e.g. "##empty" // Tip: If your vertical size is calculated from an item count (e.g. 10 * item_height) consider adding a fractional part to facilitate seeing scrolling boundaries (e.g. 10.25 * item_height). bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; const ImGuiStyle& style = g.Style; const ImGuiID id = GetID(label); const ImVec2 label_size = CalcTextSize(label, NULL, true); // Size default to hold ~7.25 items. // Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar. ImVec2 size = ImTrunc(CalcItemSize(size_arg, CalcItemWidth(), GetTextLineHeightWithSpacing() * 7.25f + style.FramePadding.y * 2.0f)); ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y)); ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); g.NextItemData.ClearFlags(); if (!IsRectVisible(bb.Min, bb.Max)) { ItemSize(bb.GetSize(), style.FramePadding.y); ItemAdd(bb, 0, &frame_bb); g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values return false; } // FIXME-OPT: We could omit the BeginGroup() if label_size.x == 0.0f but would need to omit the EndGroup() as well. BeginGroup(); if (label_size.x > 0.0f) { ImVec2 label_pos = ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y); RenderText(label_pos, label); window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, label_pos + label_size); } BeginChild(id, frame_bb.GetSize(), ImGuiChildFlags_FrameStyle); return true; } void ImGui::EndListBox() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) && "Mismatched BeginListBox/EndListBox calls. Did you test the return value of BeginListBox?"); IM_UNUSED(window); EndChild(); EndGroup(); // This is only required to be able to do IsItemXXX query on the whole ListBox including label } bool ImGui::ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_items) { const bool value_changed = ListBox(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_items); return value_changed; } // This is merely a helper around BeginListBox(), EndListBox(). // Considering using those directly to submit custom data or store selection differently. bool ImGui::ListBox(const char* label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int height_in_items) { ImGuiContext& g = *GImGui; // Calculate size from "height_in_items" if (height_in_items < 0) height_in_items = ImMin(items_count, 7); float height_in_items_f = height_in_items + 0.25f; ImVec2 size(0.0f, ImTrunc(GetTextLineHeightWithSpacing() * height_in_items_f + g.Style.FramePadding.y * 2.0f)); if (!BeginListBox(label, size)) return false; // Assume all items have even height (= 1 line of text). If you need items of different height, // you can create a custom version of ListBox() in your code without using the clipper. bool value_changed = false; ImGuiListClipper clipper; clipper.Begin(items_count, GetTextLineHeightWithSpacing()); // We know exactly our line height here so we pass it as a minor optimization, but generally you don't need to. while (clipper.Step()) for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { const char* item_text = getter(user_data, i); if (item_text == NULL) item_text = "*Unknown item*"; PushID(i); const bool item_selected = (i == *current_item); if (Selectable(item_text, item_selected)) { *current_item = i; value_changed = true; } if (item_selected) SetItemDefaultFocus(); PopID(); } EndListBox(); if (value_changed) MarkItemEdited(g.LastItemData.ID); return value_changed; } //------------------------------------------------------------------------- // [SECTION] Widgets: PlotLines, PlotHistogram //------------------------------------------------------------------------- // - PlotEx() [Internal] // - PlotLines() // - PlotHistogram() //------------------------------------------------------------------------- // Plot/Graph widgets are not very good. // Consider writing your own, or using a third-party one, see: // - ImPlot https://github.com/epezent/implot // - others https://github.com/ocornut/imgui/wiki/Useful-Extensions //------------------------------------------------------------------------- int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, const ImVec2& size_arg) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return -1; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), label_size.y + style.FramePadding.y * 2.0f); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0)); ItemSize(total_bb, style.FramePadding.y); if (!ItemAdd(total_bb, 0, &frame_bb)) return -1; const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags); // Determine scale from values if not specified if (scale_min == FLT_MAX || scale_max == FLT_MAX) { float v_min = FLT_MAX; float v_max = -FLT_MAX; for (int i = 0; i < values_count; i++) { const float v = values_getter(data, i); if (v != v) // Ignore NaN values continue; v_min = ImMin(v_min, v); v_max = ImMax(v_max, v); } if (scale_min == FLT_MAX) scale_min = v_min; if (scale_max == FLT_MAX) scale_max = v_max; } RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); const int values_count_min = (plot_type == ImGuiPlotType_Lines) ? 2 : 1; int idx_hovered = -1; if (values_count >= values_count_min) { int res_w = ImMin((int)frame_size.x, values_count) + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0); int item_count = values_count + ((plot_type == ImGuiPlotType_Lines) ? -1 : 0); // Tooltip on hover if (hovered && inner_bb.Contains(g.IO.MousePos)) { const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f); const int v_idx = (int)(t * item_count); IM_ASSERT(v_idx >= 0 && v_idx < values_count); const float v0 = values_getter(data, (v_idx + values_offset) % values_count); const float v1 = values_getter(data, (v_idx + 1 + values_offset) % values_count); if (plot_type == ImGuiPlotType_Lines) SetTooltip("%d: %8.4g\n%d: %8.4g", v_idx, v0, v_idx + 1, v1); else if (plot_type == ImGuiPlotType_Histogram) SetTooltip("%d: %8.4g", v_idx, v0); idx_hovered = v_idx; } const float t_step = 1.0f / (float)res_w; const float inv_scale = (scale_min == scale_max) ? 0.0f : (1.0f / (scale_max - scale_min)); float v0 = values_getter(data, (0 + values_offset) % values_count); float t0 = 0.0f; ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) * inv_scale) ); // Point in the normalized space of our target rectangle float histogram_zero_line_t = (scale_min * scale_max < 0.0f) ? (1 + scale_min * inv_scale) : (scale_min < 0.0f ? 0.0f : 1.0f); // Where does the zero line stands const ImU32 col_base = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram); const ImU32 col_hovered = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered); for (int n = 0; n < res_w; n++) { const float t1 = t0 + t_step; const int v1_idx = (int)(t0 * item_count + 0.5f); IM_ASSERT(v1_idx >= 0 && v1_idx < values_count); const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count); const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) * inv_scale) ); // NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU. ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0); ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, histogram_zero_line_t)); if (plot_type == ImGuiPlotType_Lines) { window->DrawList->AddLine(pos0, pos1, idx_hovered == v1_idx ? col_hovered : col_base); } else if (plot_type == ImGuiPlotType_Histogram) { if (pos1.x >= pos0.x + 2.0f) pos1.x -= 1.0f; window->DrawList->AddRectFilled(pos0, pos1, idx_hovered == v1_idx ? col_hovered : col_base); } t0 = t1; tp0 = tp1; } } // Text overlay if (overlay_text) RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, overlay_text, NULL, NULL, ImVec2(0.5f, 0.0f)); if (label_size.x > 0.0f) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label); // Return hovered index or -1 if none are hovered. // This is currently not exposed in the public API because we need a larger redesign of the whole thing, but in the short-term we are making it available in PlotEx(). return idx_hovered; } struct ImGuiPlotArrayGetterData { const float* Values; int Stride; ImGuiPlotArrayGetterData(const float* values, int stride) { Values = values; Stride = stride; } }; static float Plot_ArrayGetter(void* data, int idx) { ImGuiPlotArrayGetterData* plot_data = (ImGuiPlotArrayGetterData*)data; const float v = *(const float*)(const void*)((const unsigned char*)plot_data->Values + (size_t)idx * plot_data->Stride); return v; } void ImGui::PlotLines(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride) { ImGuiPlotArrayGetterData data(values, stride); PlotEx(ImGuiPlotType_Lines, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); } void ImGui::PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size) { PlotEx(ImGuiPlotType_Lines, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); } void ImGui::PlotHistogram(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride) { ImGuiPlotArrayGetterData data(values, stride); PlotEx(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); } void ImGui::PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size) { PlotEx(ImGuiPlotType_Histogram, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size); } //------------------------------------------------------------------------- // [SECTION] Widgets: Value helpers // Those is not very useful, legacy API. //------------------------------------------------------------------------- // - Value() //------------------------------------------------------------------------- void ImGui::Value(const char* prefix, bool b) { Text("%s: %s", prefix, (b ? "true" : "false")); } void ImGui::Value(const char* prefix, int v) { Text("%s: %d", prefix, v); } void ImGui::Value(const char* prefix, unsigned int v) { Text("%s: %d", prefix, v); } void ImGui::Value(const char* prefix, float v, const char* float_format) { if (float_format) { char fmt[64]; ImFormatString(fmt, IM_ARRAYSIZE(fmt), "%%s: %s", float_format); Text(fmt, prefix, v); } else { Text("%s: %.3f", prefix, v); } } //------------------------------------------------------------------------- // [SECTION] MenuItem, BeginMenu, EndMenu, etc. //------------------------------------------------------------------------- // - ImGuiMenuColumns [Internal] // - BeginMenuBar() // - EndMenuBar() // - BeginMainMenuBar() // - EndMainMenuBar() // - BeginMenu() // - EndMenu() // - MenuItemEx() [Internal] // - MenuItem() //------------------------------------------------------------------------- // Helpers for internal use void ImGuiMenuColumns::Update(float spacing, bool window_reappearing) { if (window_reappearing) memset(Widths, 0, sizeof(Widths)); Spacing = (ImU16)spacing; CalcNextTotalWidth(true); memset(Widths, 0, sizeof(Widths)); TotalWidth = NextTotalWidth; NextTotalWidth = 0; } void ImGuiMenuColumns::CalcNextTotalWidth(bool update_offsets) { ImU16 offset = 0; bool want_spacing = false; for (int i = 0; i < IM_ARRAYSIZE(Widths); i++) { ImU16 width = Widths[i]; if (want_spacing && width > 0) offset += Spacing; want_spacing |= (width > 0); if (update_offsets) { if (i == 1) { OffsetLabel = offset; } if (i == 2) { OffsetShortcut = offset; } if (i == 3) { OffsetMark = offset; } } offset += width; } NextTotalWidth = offset; } float ImGuiMenuColumns::DeclColumns(float w_icon, float w_label, float w_shortcut, float w_mark) { Widths[0] = ImMax(Widths[0], (ImU16)w_icon); Widths[1] = ImMax(Widths[1], (ImU16)w_label); Widths[2] = ImMax(Widths[2], (ImU16)w_shortcut); Widths[3] = ImMax(Widths[3], (ImU16)w_mark); CalcNextTotalWidth(false); return (float)ImMax(TotalWidth, NextTotalWidth); } // FIXME: Provided a rectangle perhaps e.g. a BeginMenuBarEx() could be used anywhere.. // Currently the main responsibility of this function being to setup clip-rect + horizontal layout + menu navigation layer. // Ideally we also want this to be responsible for claiming space out of the main window scrolling rectangle, in which case ImGuiWindowFlags_MenuBar will become unnecessary. // Then later the same system could be used for multiple menu-bars, scrollbars, side-bars. bool ImGui::BeginMenuBar() { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; if (!(window->Flags & ImGuiWindowFlags_MenuBar)) return false; IM_ASSERT(!window->DC.MenuBarAppending); BeginGroup(); // Backup position on layer 0 // FIXME: Misleading to use a group for that backup/restore PushID("##menubar"); // We don't clip with current window clipping rectangle as it is already set to the area below. However we clip with window full rect. // We remove 1 worth of rounding to Max.x to that text in long menus and small windows don't tend to display over the lower-right rounded area, which looks particularly glitchy. ImRect bar_rect = window->MenuBarRect(); ImRect clip_rect(IM_ROUND(bar_rect.Min.x + window->WindowBorderSize), IM_ROUND(bar_rect.Min.y + window->WindowBorderSize), IM_ROUND(ImMax(bar_rect.Min.x, bar_rect.Max.x - ImMax(window->WindowRounding, window->WindowBorderSize))), IM_ROUND(bar_rect.Max.y)); clip_rect.ClipWith(window->OuterRectClipped); PushClipRect(clip_rect.Min, clip_rect.Max, false); // We overwrite CursorMaxPos because BeginGroup sets it to CursorPos (essentially the .EmitItem hack in EndMenuBar() would need something analogous here, maybe a BeginGroupEx() with flags). window->DC.CursorPos = window->DC.CursorMaxPos = ImVec2(bar_rect.Min.x + window->DC.MenuBarOffset.x, bar_rect.Min.y + window->DC.MenuBarOffset.y); window->DC.LayoutType = ImGuiLayoutType_Horizontal; window->DC.IsSameLine = false; window->DC.NavLayerCurrent = ImGuiNavLayer_Menu; window->DC.MenuBarAppending = true; AlignTextToFramePadding(); return true; } void ImGui::EndMenuBar() { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; ImGuiContext& g = *GImGui; // Nav: When a move request within one of our child menu failed, capture the request to navigate among our siblings. if (NavMoveRequestButNoResultYet() && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) { // Try to find out if the request is for one of our child menu ImGuiWindow* nav_earliest_child = g.NavWindow; while (nav_earliest_child->ParentWindow && (nav_earliest_child->ParentWindow->Flags & ImGuiWindowFlags_ChildMenu)) nav_earliest_child = nav_earliest_child->ParentWindow; if (nav_earliest_child->ParentWindow == window && nav_earliest_child->DC.ParentLayoutType == ImGuiLayoutType_Horizontal && (g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded) == 0) { // To do so we claim focus back, restore NavId and then process the movement request for yet another frame. // This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth bothering) const ImGuiNavLayer layer = ImGuiNavLayer_Menu; IM_ASSERT(window->DC.NavLayersActiveMaskNext & (1 << layer)); // Sanity check (FIXME: Seems unnecessary) FocusWindow(window); SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]); g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection. g.NavDisableMouseHover = g.NavMousePosDirty = true; NavMoveRequestForward(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags, g.NavMoveScrollFlags); // Repeat } } IM_MSVC_WARNING_SUPPRESS(6011); // Static Analysis false positive "warning C6011: Dereferencing NULL pointer 'window'" IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar); IM_ASSERT(window->DC.MenuBarAppending); PopClipRect(); PopID(); window->DC.MenuBarOffset.x = window->DC.CursorPos.x - window->Pos.x; // Save horizontal position so next append can reuse it. This is kinda equivalent to a per-layer CursorPos. // FIXME: Extremely confusing, cleanup by (a) working on WorkRect stack system (b) not using a Group confusingly here. ImGuiGroupData& group_data = g.GroupStack.back(); group_data.EmitItem = false; ImVec2 restore_cursor_max_pos = group_data.BackupCursorMaxPos; window->DC.IdealMaxPos.x = ImMax(window->DC.IdealMaxPos.x, window->DC.CursorMaxPos.x - window->Scroll.x); // Convert ideal extents for scrolling layer equivalent. EndGroup(); // Restore position on layer 0 // FIXME: Misleading to use a group for that backup/restore window->DC.LayoutType = ImGuiLayoutType_Vertical; window->DC.IsSameLine = false; window->DC.NavLayerCurrent = ImGuiNavLayer_Main; window->DC.MenuBarAppending = false; window->DC.CursorMaxPos = restore_cursor_max_pos; } // Important: calling order matters! // FIXME: Somehow overlapping with docking tech. // FIXME: The "rect-cut" aspect of this could be formalized into a lower-level helper (rect-cut: https://halt.software/dead-simple-layouts) bool ImGui::BeginViewportSideBar(const char* name, ImGuiViewport* viewport_p, ImGuiDir dir, float axis_size, ImGuiWindowFlags window_flags) { IM_ASSERT(dir != ImGuiDir_None); ImGuiWindow* bar_window = FindWindowByName(name); if (bar_window == NULL || bar_window->BeginCount == 0) { // Calculate and set window size/position ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)(viewport_p ? viewport_p : GetMainViewport()); ImRect avail_rect = viewport->GetBuildWorkRect(); ImGuiAxis axis = (dir == ImGuiDir_Up || dir == ImGuiDir_Down) ? ImGuiAxis_Y : ImGuiAxis_X; ImVec2 pos = avail_rect.Min; if (dir == ImGuiDir_Right || dir == ImGuiDir_Down) pos[axis] = avail_rect.Max[axis] - axis_size; ImVec2 size = avail_rect.GetSize(); size[axis] = axis_size; SetNextWindowPos(pos); SetNextWindowSize(size); // Report our size into work area (for next frame) using actual window size if (dir == ImGuiDir_Up || dir == ImGuiDir_Left) viewport->BuildWorkOffsetMin[axis] += axis_size; else if (dir == ImGuiDir_Down || dir == ImGuiDir_Right) viewport->BuildWorkOffsetMax[axis] -= axis_size; } window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove; PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0, 0)); // Lift normal size constraint bool is_open = Begin(name, NULL, window_flags); PopStyleVar(2); return is_open; } bool ImGui::BeginMainMenuBar() { ImGuiContext& g = *GImGui; ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)GetMainViewport(); // For the main menu bar, which cannot be moved, we honor g.Style.DisplaySafeAreaPadding to ensure text can be visible on a TV set. // FIXME: This could be generalized as an opt-in way to clamp window->DC.CursorStartPos to avoid SafeArea? // FIXME: Consider removing support for safe area down the line... it's messy. Nowadays consoles have support for TV calibration in OS settings. g.NextWindowData.MenuBarOffsetMinVal = ImVec2(g.Style.DisplaySafeAreaPadding.x, ImMax(g.Style.DisplaySafeAreaPadding.y - g.Style.FramePadding.y, 0.0f)); ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar; float height = GetFrameHeight(); bool is_open = BeginViewportSideBar("##MainMenuBar", viewport, ImGuiDir_Up, height, window_flags); g.NextWindowData.MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f); if (is_open) BeginMenuBar(); else End(); return is_open; } void ImGui::EndMainMenuBar() { EndMenuBar(); // When the user has left the menu layer (typically: closed menus through activation of an item), we restore focus to the previous window // FIXME: With this strategy we won't be able to restore a NULL focus. ImGuiContext& g = *GImGui; if (g.CurrentWindow == g.NavWindow && g.NavLayer == ImGuiNavLayer_Main && !g.NavAnyRequest) FocusTopMostWindowUnderOne(g.NavWindow, NULL, NULL, ImGuiFocusRequestFlags_UnlessBelowModal | ImGuiFocusRequestFlags_RestoreFocusedChild); End(); } static bool IsRootOfOpenMenuSet() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if ((g.OpenPopupStack.Size <= g.BeginPopupStack.Size) || (window->Flags & ImGuiWindowFlags_ChildMenu)) return false; // Initially we used 'upper_popup->OpenParentId == window->IDStack.back()' to differentiate multiple menu sets from each others // (e.g. inside menu bar vs loose menu items) based on parent ID. // This would however prevent the use of e.g. PushID() user code submitting menus. // Previously this worked between popup and a first child menu because the first child menu always had the _ChildWindow flag, // making hovering on parent popup possible while first child menu was focused - but this was generally a bug with other side effects. // Instead we don't treat Popup specifically (in order to consistently support menu features in them), maybe the first child menu of a Popup // doesn't have the _ChildWindow flag, and we rely on this IsRootOfOpenMenuSet() check to allow hovering between root window/popup and first child menu. // In the end, lack of ID check made it so we could no longer differentiate between separate menu sets. To compensate for that, we at least check parent window nav layer. // This fixes the most common case of menu opening on hover when moving between window content and menu bar. Multiple different menu sets in same nav layer would still // open on hover, but that should be a lesser problem, because if such menus are close in proximity in window content then it won't feel weird and if they are far apart // it likely won't be a problem anyone runs into. const ImGuiPopupData* upper_popup = &g.OpenPopupStack[g.BeginPopupStack.Size]; if (window->DC.NavLayerCurrent != upper_popup->ParentNavLayer) return false; return upper_popup->Window && (upper_popup->Window->Flags & ImGuiWindowFlags_ChildMenu) && ImGui::IsWindowChildOf(upper_popup->Window, window, true); } bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); bool menu_is_open = IsPopupOpen(id, ImGuiPopupFlags_None); // Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu) // The first menu in a hierarchy isn't so hovering doesn't get across (otherwise e.g. resizing borders with ImGuiButtonFlags_FlattenChildren would react), but top-most BeginMenu() will bypass that limitation. ImGuiWindowFlags window_flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus; if (window->Flags & ImGuiWindowFlags_ChildMenu) window_flags |= ImGuiWindowFlags_ChildWindow; // If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin(). // We are relying on a O(N) search - so O(N log N) over the frame - which seems like the most efficient for the expected small amount of BeginMenu() calls per frame. // If somehow this is ever becoming a problem we can switch to use e.g. ImGuiStorage mapping key to last frame used. if (g.MenusIdSubmittedThisFrame.contains(id)) { if (menu_is_open) menu_is_open = BeginPopupEx(id, window_flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) else g.NextWindowData.ClearFlags(); // we behave like Begin() and need to consume those values return menu_is_open; } // Tag menu as used. Next time BeginMenu() with same ID is called it will append to existing menu g.MenusIdSubmittedThisFrame.push_back(id); ImVec2 label_size = CalcTextSize(label, NULL, true); // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent without always being a Child window) // This is only done for items for the menu set and not the full parent window. const bool menuset_is_open = IsRootOfOpenMenuSet(); if (menuset_is_open) PushItemFlag(ImGuiItemFlags_NoWindowHoverableCheck, true); // The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu, // However the final position is going to be different! It is chosen by FindBestWindowPosForPopup(). // e.g. Menus tend to overlap each other horizontally to amplify relative Z-ordering. ImVec2 popup_pos, pos = window->DC.CursorPos; PushID(label); if (!enabled) BeginDisabled(); const ImGuiMenuColumns* offsets = &window->DC.MenuColumns; bool pressed; // We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another. const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) { // Menu inside an horizontal menu bar // Selectable extend their highlight by half ItemSpacing in each direction. // For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin() popup_pos = ImVec2(pos.x - 1.0f - IM_TRUNC(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight()); window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * 0.5f); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); float w = label_size.x; ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); pressed = Selectable("", menu_is_open, selectable_flags, ImVec2(w, label_size.y)); RenderText(text_pos, label); PopStyleVar(); window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). } else { // Menu inside a regular/vertical menu // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f. // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system. popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y); float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f; float checkmark_w = IM_TRUNC(g.FontSize * 1.20f); float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); pressed = Selectable("", menu_is_open, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y)); RenderText(text_pos, label); if (icon_w > 0.0f) RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon); RenderArrow(window->DrawList, pos + ImVec2(offsets->OffsetMark + extra_w + g.FontSize * 0.30f, 0.0f), GetColorU32(ImGuiCol_Text), ImGuiDir_Right); } if (!enabled) EndDisabled(); const bool hovered = (g.HoveredId == id) && enabled && !g.NavDisableMouseHover; if (menuset_is_open) PopItemFlag(); bool want_open = false; bool want_open_nav_init = false; bool want_close = false; if (window->DC.LayoutType == ImGuiLayoutType_Vertical) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) { // Close menu when not hovering it anymore unless we are moving roughly in the direction of the menu // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive. bool moving_toward_child_menu = false; ImGuiPopupData* child_popup = (g.BeginPopupStack.Size < g.OpenPopupStack.Size) ? &g.OpenPopupStack[g.BeginPopupStack.Size] : NULL; // Popup candidate (testing below) ImGuiWindow* child_menu_window = (child_popup && child_popup->Window && child_popup->Window->ParentWindow == window) ? child_popup->Window : NULL; if (g.HoveredWindow == window && child_menu_window != NULL) { const float ref_unit = g.FontSize; // FIXME-DPI const float child_dir = (window->Pos.x < child_menu_window->Pos.x) ? 1.0f : -1.0f; const ImRect next_window_rect = child_menu_window->Rect(); ImVec2 ta = (g.IO.MousePos - g.IO.MouseDelta); ImVec2 tb = (child_dir > 0.0f) ? next_window_rect.GetTL() : next_window_rect.GetTR(); ImVec2 tc = (child_dir > 0.0f) ? next_window_rect.GetBL() : next_window_rect.GetBR(); const float pad_farmost_h = ImClamp(ImFabs(ta.x - tb.x) * 0.30f, ref_unit * 0.5f, ref_unit * 2.5f); // Add a bit of extra slack. ta.x += child_dir * -0.5f; tb.x += child_dir * ref_unit; tc.x += child_dir * ref_unit; tb.y = ta.y + ImMax((tb.y - pad_farmost_h) - ta.y, -ref_unit * 8.0f); // Triangle has maximum height to limit the slope and the bias toward large sub-menus tc.y = ta.y + ImMin((tc.y + pad_farmost_h) - ta.y, +ref_unit * 8.0f); moving_toward_child_menu = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos); //GetForegroundDrawList()->AddTriangleFilled(ta, tb, tc, moving_toward_child_menu ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); // [DEBUG] } // The 'HovereWindow == window' check creates an inconsistency (e.g. moving away from menu slowly tends to hit same window, whereas moving away fast does not) // But we also need to not close the top-menu menu when moving over void. Perhaps we should extend the triangle check to a larger polygon. // (Remember to test this on BeginPopup("A")->BeginMenu("B") sequence which behaves slightly differently as B isn't a Child of A and hovering isn't shared.) if (menu_is_open && !hovered && g.HoveredWindow == window && !moving_toward_child_menu && !g.NavDisableMouseHover && g.ActiveId == 0) want_close = true; // Open // (note: at this point 'hovered' actually includes the NavDisableMouseHover == false test) if (!menu_is_open && pressed) // Click/activate to open want_open = true; else if (!menu_is_open && hovered && !moving_toward_child_menu) // Hover to open want_open = true; else if (!menu_is_open && hovered && g.HoveredIdTimer >= 0.30f && g.MouseStationaryTimer >= 0.30f) // Hover to open (timer fallback) want_open = true; if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open { want_open = want_open_nav_init = true; NavMoveRequestCancel(); NavRestoreHighlightAfterMove(); } } else { // Menu bar if (menu_is_open && pressed && menuset_is_open) // Click an open menu again to close it { want_close = true; want_open = menu_is_open = false; } else if (pressed || (hovered && menuset_is_open && !menu_is_open)) // First click to open, then hover to open others { want_open = true; } else if (g.NavId == id && g.NavMoveDir == ImGuiDir_Down) // Nav-Down to open { want_open = true; NavMoveRequestCancel(); } } if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }' want_close = true; if (want_close && IsPopupOpen(id, ImGuiPopupFlags_None)) ClosePopupToLevel(g.BeginPopupStack.Size, true); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0)); PopID(); if (want_open && !menu_is_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size) { // Don't reopen/recycle same menu level in the same frame if it is a different menu ID, first close the other menu and yield for a frame. OpenPopup(label); } else if (want_open) { menu_is_open = true; OpenPopup(label, ImGuiPopupFlags_NoReopen);// | (want_open_nav_init ? ImGuiPopupFlags_NoReopenAlwaysNavInit : 0)); } if (menu_is_open) { ImGuiLastItemData last_item_in_parent = g.LastItemData; SetNextWindowPos(popup_pos, ImGuiCond_Always); // Note: misleading: the value will serve as reference for FindBestWindowPosForPopup(), not actual pos. PushStyleVar(ImGuiStyleVar_ChildRounding, style.PopupRounding); // First level will use _PopupRounding, subsequent will use _ChildRounding menu_is_open = BeginPopupEx(id, window_flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) PopStyleVar(); if (menu_is_open) { // Implement what ImGuiPopupFlags_NoReopenAlwaysNavInit would do: // Perform an init request in the case the popup was already open (via a previous mouse hover) if (want_open && want_open_nav_init && !g.NavInitRequest) { FocusWindow(g.CurrentWindow, ImGuiFocusRequestFlags_UnlessBelowModal); NavInitWindow(g.CurrentWindow, false); } // Restore LastItemData so IsItemXXXX functions can work after BeginMenu()/EndMenu() // (This fixes using IsItemClicked() and IsItemHovered(), but IsItemHovered() also relies on its support for ImGuiItemFlags_NoWindowHoverableCheck) g.LastItemData = last_item_in_parent; if (g.HoveredWindow == window) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow; } } else { g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values } return menu_is_open; } bool ImGui::BeginMenu(const char* label, bool enabled) { return BeginMenuEx(label, NULL, enabled); } void ImGui::EndMenu() { // Nav: When a left move request our menu failed, close ourselves. ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginMenu()/EndMenu() calls ImGuiWindow* parent_window = window->ParentWindow; // Should always be != NULL is we passed assert. if (window->BeginCount == window->BeginCountPreviousFrame) if (g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet()) if (g.NavWindow && (g.NavWindow->RootWindowForNav == window) && parent_window->DC.LayoutType == ImGuiLayoutType_Vertical) { ClosePopupToLevel(g.BeginPopupStack.Size - 1, true); NavMoveRequestCancel(); } EndPopup(); } bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut, bool selected, bool enabled) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; ImGuiContext& g = *GImGui; ImGuiStyle& style = g.Style; ImVec2 pos = window->DC.CursorPos; ImVec2 label_size = CalcTextSize(label, NULL, true); // See BeginMenuEx() for comments about this. const bool menuset_is_open = IsRootOfOpenMenuSet(); if (menuset_is_open) PushItemFlag(ImGuiItemFlags_NoWindowHoverableCheck, true); // We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73), // but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only. bool pressed; PushID(label); if (!enabled) BeginDisabled(); // We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another. const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SetNavIdOnHover; const ImGuiMenuColumns* offsets = &window->DC.MenuColumns; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) { // Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful // Note that in this situation: we don't render the shortcut, we render a highlight instead of the selected tick mark. float w = label_size.x; window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * 0.5f); ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); pressed = Selectable("", selected, selectable_flags, ImVec2(w, 0.0f)); PopStyleVar(); if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) RenderText(text_pos, label); window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). } else { // Menu item inside a vertical menu // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f. // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system. float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f; float shortcut_w = (shortcut && shortcut[0]) ? CalcTextSize(shortcut, NULL).x : 0.0f; float checkmark_w = IM_TRUNC(g.FontSize * 1.20f); float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y)); if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) { RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label); if (icon_w > 0.0f) RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon); if (shortcut_w > 0.0f) { PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); RenderText(pos + ImVec2(offsets->OffsetShortcut + stretch_w, 0.0f), shortcut, NULL, false); PopStyleColor(); } if (selected) RenderCheckMark(window->DrawList, pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f); } } IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0)); if (!enabled) EndDisabled(); PopID(); if (menuset_is_open) PopItemFlag(); return pressed; } bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, bool enabled) { return MenuItemEx(label, NULL, shortcut, selected, enabled); } bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled) { if (MenuItemEx(label, NULL, shortcut, p_selected ? *p_selected : false, enabled)) { if (p_selected) *p_selected = !*p_selected; return true; } return false; } //------------------------------------------------------------------------- // [SECTION] Widgets: BeginTabBar, EndTabBar, etc. //------------------------------------------------------------------------- // - BeginTabBar() // - BeginTabBarEx() [Internal] // - EndTabBar() // - TabBarLayout() [Internal] // - TabBarCalcTabID() [Internal] // - TabBarCalcMaxTabWidth() [Internal] // - TabBarFindTabById() [Internal] // - TabBarFindTabByOrder() [Internal] // - TabBarGetCurrentTab() [Internal] // - TabBarGetTabName() [Internal] // - TabBarRemoveTab() [Internal] // - TabBarCloseTab() [Internal] // - TabBarScrollClamp() [Internal] // - TabBarScrollToTab() [Internal] // - TabBarQueueFocus() [Internal] // - TabBarQueueReorder() [Internal] // - TabBarProcessReorderFromMousePos() [Internal] // - TabBarProcessReorder() [Internal] // - TabBarScrollingButtons() [Internal] // - TabBarTabListPopupButton() [Internal] //------------------------------------------------------------------------- struct ImGuiTabBarSection { int TabCount; // Number of tabs in this section. float Width; // Sum of width of tabs in this section (after shrinking down) float Spacing; // Horizontal spacing at the end of the section. ImGuiTabBarSection() { memset(this, 0, sizeof(*this)); } }; namespace ImGui { static void TabBarLayout(ImGuiTabBar* tab_bar); static ImU32 TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label, ImGuiWindow* docked_window); static float TabBarCalcMaxTabWidth(); static float TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling); static void TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGuiTabBarSection* sections); static ImGuiTabItem* TabBarScrollingButtons(ImGuiTabBar* tab_bar); static ImGuiTabItem* TabBarTabListPopupButton(ImGuiTabBar* tab_bar); } ImGuiTabBar::ImGuiTabBar() { memset(this, 0, sizeof(*this)); CurrFrameVisible = PrevFrameVisible = -1; LastTabItemIdx = -1; } static inline int TabItemGetSectionIdx(const ImGuiTabItem* tab) { return (tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1; } static int IMGUI_CDECL TabItemComparerBySection(const void* lhs, const void* rhs) { const ImGuiTabItem* a = (const ImGuiTabItem*)lhs; const ImGuiTabItem* b = (const ImGuiTabItem*)rhs; const int a_section = TabItemGetSectionIdx(a); const int b_section = TabItemGetSectionIdx(b); if (a_section != b_section) return a_section - b_section; return (int)(a->IndexDuringLayout - b->IndexDuringLayout); } static int IMGUI_CDECL TabItemComparerByBeginOrder(const void* lhs, const void* rhs) { const ImGuiTabItem* a = (const ImGuiTabItem*)lhs; const ImGuiTabItem* b = (const ImGuiTabItem*)rhs; return (int)(a->BeginOrder - b->BeginOrder); } static ImGuiTabBar* GetTabBarFromTabBarRef(const ImGuiPtrOrIndex& ref) { ImGuiContext& g = *GImGui; return ref.Ptr ? (ImGuiTabBar*)ref.Ptr : g.TabBars.GetByIndex(ref.Index); } static ImGuiPtrOrIndex GetTabBarRefFromTabBar(ImGuiTabBar* tab_bar) { ImGuiContext& g = *GImGui; if (g.TabBars.Contains(tab_bar)) return ImGuiPtrOrIndex(g.TabBars.GetIndex(tab_bar)); return ImGuiPtrOrIndex(tab_bar); } bool ImGui::BeginTabBar(const char* str_id, ImGuiTabBarFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (window->SkipItems) return false; ImGuiID id = window->GetID(str_id); ImGuiTabBar* tab_bar = g.TabBars.GetOrAddByKey(id); ImRect tab_bar_bb = ImRect(window->DC.CursorPos.x, window->DC.CursorPos.y, window->WorkRect.Max.x, window->DC.CursorPos.y + g.FontSize + g.Style.FramePadding.y * 2); tab_bar->ID = id; tab_bar->SeparatorMinX = tab_bar->BarRect.Min.x - IM_TRUNC(window->WindowPadding.x * 0.5f); tab_bar->SeparatorMaxX = tab_bar->BarRect.Max.x + IM_TRUNC(window->WindowPadding.x * 0.5f); return BeginTabBarEx(tab_bar, tab_bar_bb, flags | ImGuiTabBarFlags_IsFocused); } bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImGuiTabBarFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (window->SkipItems) return false; IM_ASSERT(tab_bar->ID != 0); if ((flags & ImGuiTabBarFlags_DockNode) == 0) PushOverrideID(tab_bar->ID); // Add to stack g.CurrentTabBarStack.push_back(GetTabBarRefFromTabBar(tab_bar)); g.CurrentTabBar = tab_bar; // Append with multiple BeginTabBar()/EndTabBar() pairs. tab_bar->BackupCursorPos = window->DC.CursorPos; if (tab_bar->CurrFrameVisible == g.FrameCount) { window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x, tab_bar->BarRect.Max.y + tab_bar->ItemSpacingY); tab_bar->BeginCount++; return true; } // Ensure correct ordering when toggling ImGuiTabBarFlags_Reorderable flag, or when a new tab was added while being not reorderable if ((flags & ImGuiTabBarFlags_Reorderable) != (tab_bar->Flags & ImGuiTabBarFlags_Reorderable) || (tab_bar->TabsAddedNew && !(flags & ImGuiTabBarFlags_Reorderable))) ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByBeginOrder); tab_bar->TabsAddedNew = false; // Flags if ((flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0) flags |= ImGuiTabBarFlags_FittingPolicyDefault_; tab_bar->Flags = flags; tab_bar->BarRect = tab_bar_bb; tab_bar->WantLayout = true; // Layout will be done on the first call to ItemTab() tab_bar->PrevFrameVisible = tab_bar->CurrFrameVisible; tab_bar->CurrFrameVisible = g.FrameCount; tab_bar->PrevTabsContentsHeight = tab_bar->CurrTabsContentsHeight; tab_bar->CurrTabsContentsHeight = 0.0f; tab_bar->ItemSpacingY = g.Style.ItemSpacing.y; tab_bar->FramePadding = g.Style.FramePadding; tab_bar->TabsActiveCount = 0; tab_bar->LastTabItemIdx = -1; tab_bar->BeginCount = 1; // Set cursor pos in a way which only be used in the off-chance the user erroneously submits item before BeginTabItem(): items will overlap window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x, tab_bar->BarRect.Max.y + tab_bar->ItemSpacingY); // Draw separator // (it would be misleading to draw this in EndTabBar() suggesting that it may be drawn over tabs, as tab bar are appendable) const ImU32 col = GetColorU32((flags & ImGuiTabBarFlags_IsFocused) ? ImGuiCol_TabActive : ImGuiCol_TabUnfocusedActive); if (g.Style.TabBarBorderSize > 0.0f) { const float y = tab_bar->BarRect.Max.y; window->DrawList->AddRectFilled(ImVec2(tab_bar->SeparatorMinX, y - g.Style.TabBarBorderSize), ImVec2(tab_bar->SeparatorMaxX, y), col); } return true; } void ImGui::EndTabBar() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (window->SkipItems) return; ImGuiTabBar* tab_bar = g.CurrentTabBar; if (tab_bar == NULL) { IM_ASSERT_USER_ERROR(tab_bar != NULL, "Mismatched BeginTabBar()/EndTabBar()!"); return; } // Fallback in case no TabItem have been submitted if (tab_bar->WantLayout) TabBarLayout(tab_bar); // Restore the last visible height if no tab is visible, this reduce vertical flicker/movement when a tabs gets removed without calling SetTabItemClosed(). const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount); if (tab_bar->VisibleTabWasSubmitted || tab_bar->VisibleTabId == 0 || tab_bar_appearing) { tab_bar->CurrTabsContentsHeight = ImMax(window->DC.CursorPos.y - tab_bar->BarRect.Max.y, tab_bar->CurrTabsContentsHeight); window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->CurrTabsContentsHeight; } else { window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->PrevTabsContentsHeight; } if (tab_bar->BeginCount > 1) window->DC.CursorPos = tab_bar->BackupCursorPos; tab_bar->LastTabItemIdx = -1; if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0) PopID(); g.CurrentTabBarStack.pop_back(); g.CurrentTabBar = g.CurrentTabBarStack.empty() ? NULL : GetTabBarFromTabBarRef(g.CurrentTabBarStack.back()); } // Scrolling happens only in the central section (leading/trailing sections are not scrolling) static float TabBarCalcScrollableWidth(ImGuiTabBar* tab_bar, ImGuiTabBarSection* sections) { return tab_bar->BarRect.GetWidth() - sections[0].Width - sections[2].Width - sections[1].Spacing; } // This is called only once a frame before by the first call to ItemTab() // The reason we're not calling it in BeginTabBar() is to leave a chance to the user to call the SetTabItemClosed() functions. static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) { ImGuiContext& g = *GImGui; tab_bar->WantLayout = false; // Garbage collect by compacting list // Detect if we need to sort out tab list (e.g. in rare case where a tab changed section) int tab_dst_n = 0; bool need_sort_by_section = false; ImGuiTabBarSection sections[3]; // Layout sections: Leading, Central, Trailing for (int tab_src_n = 0; tab_src_n < tab_bar->Tabs.Size; tab_src_n++) { ImGuiTabItem* tab = &tab_bar->Tabs[tab_src_n]; if (tab->LastFrameVisible < tab_bar->PrevFrameVisible || tab->WantClose) { // Remove tab if (tab_bar->VisibleTabId == tab->ID) { tab_bar->VisibleTabId = 0; } if (tab_bar->SelectedTabId == tab->ID) { tab_bar->SelectedTabId = 0; } if (tab_bar->NextSelectedTabId == tab->ID) { tab_bar->NextSelectedTabId = 0; } continue; } if (tab_dst_n != tab_src_n) tab_bar->Tabs[tab_dst_n] = tab_bar->Tabs[tab_src_n]; tab = &tab_bar->Tabs[tab_dst_n]; tab->IndexDuringLayout = (ImS16)tab_dst_n; // We will need sorting if tabs have changed section (e.g. moved from one of Leading/Central/Trailing to another) int curr_tab_section_n = TabItemGetSectionIdx(tab); if (tab_dst_n > 0) { ImGuiTabItem* prev_tab = &tab_bar->Tabs[tab_dst_n - 1]; int prev_tab_section_n = TabItemGetSectionIdx(prev_tab); if (curr_tab_section_n == 0 && prev_tab_section_n != 0) need_sort_by_section = true; if (prev_tab_section_n == 2 && curr_tab_section_n != 2) need_sort_by_section = true; } sections[curr_tab_section_n].TabCount++; tab_dst_n++; } if (tab_bar->Tabs.Size != tab_dst_n) tab_bar->Tabs.resize(tab_dst_n); if (need_sort_by_section) ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerBySection); // Calculate spacing between sections sections[0].Spacing = sections[0].TabCount > 0 && (sections[1].TabCount + sections[2].TabCount) > 0 ? g.Style.ItemInnerSpacing.x : 0.0f; sections[1].Spacing = sections[1].TabCount > 0 && sections[2].TabCount > 0 ? g.Style.ItemInnerSpacing.x : 0.0f; // Setup next selected tab ImGuiID scroll_to_tab_id = 0; if (tab_bar->NextSelectedTabId) { tab_bar->SelectedTabId = tab_bar->NextSelectedTabId; tab_bar->NextSelectedTabId = 0; scroll_to_tab_id = tab_bar->SelectedTabId; } // Process order change request (we could probably process it when requested but it's just saner to do it in a single spot). if (tab_bar->ReorderRequestTabId != 0) { if (TabBarProcessReorder(tab_bar)) if (tab_bar->ReorderRequestTabId == tab_bar->SelectedTabId) scroll_to_tab_id = tab_bar->ReorderRequestTabId; tab_bar->ReorderRequestTabId = 0; } // Tab List Popup (will alter tab_bar->BarRect and therefore the available width!) const bool tab_list_popup_button = (tab_bar->Flags & ImGuiTabBarFlags_TabListPopupButton) != 0; if (tab_list_popup_button) if (ImGuiTabItem* tab_to_select = TabBarTabListPopupButton(tab_bar)) // NB: Will alter BarRect.Min.x! scroll_to_tab_id = tab_bar->SelectedTabId = tab_to_select->ID; // Leading/Trailing tabs will be shrink only if central one aren't visible anymore, so layout the shrink data as: leading, trailing, central // (whereas our tabs are stored as: leading, central, trailing) int shrink_buffer_indexes[3] = { 0, sections[0].TabCount + sections[2].TabCount, sections[0].TabCount }; g.ShrinkWidthBuffer.resize(tab_bar->Tabs.Size); // Compute ideal tabs widths + store them into shrink buffer ImGuiTabItem* most_recently_selected_tab = NULL; int curr_section_n = -1; bool found_selected_tab_id = false; for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++) { ImGuiTabItem* tab = &tab_bar->Tabs[tab_n]; IM_ASSERT(tab->LastFrameVisible >= tab_bar->PrevFrameVisible); if ((most_recently_selected_tab == NULL || most_recently_selected_tab->LastFrameSelected < tab->LastFrameSelected) && !(tab->Flags & ImGuiTabItemFlags_Button)) most_recently_selected_tab = tab; if (tab->ID == tab_bar->SelectedTabId) found_selected_tab_id = true; if (scroll_to_tab_id == 0 && g.NavJustMovedToId == tab->ID) scroll_to_tab_id = tab->ID; // Refresh tab width immediately, otherwise changes of style e.g. style.FramePadding.x would noticeably lag in the tab bar. // Additionally, when using TabBarAddTab() to manipulate tab bar order we occasionally insert new tabs that don't have a width yet, // and we cannot wait for the next BeginTabItem() call. We cannot compute this width within TabBarAddTab() because font size depends on the active window. const char* tab_name = TabBarGetTabName(tab_bar, tab); const bool has_close_button_or_unsaved_marker = (tab->Flags & ImGuiTabItemFlags_NoCloseButton) == 0 || (tab->Flags & ImGuiTabItemFlags_UnsavedDocument); tab->ContentWidth = (tab->RequestedWidth >= 0.0f) ? tab->RequestedWidth : TabItemCalcSize(tab_name, has_close_button_or_unsaved_marker).x; int section_n = TabItemGetSectionIdx(tab); ImGuiTabBarSection* section = §ions[section_n]; section->Width += tab->ContentWidth + (section_n == curr_section_n ? g.Style.ItemInnerSpacing.x : 0.0f); curr_section_n = section_n; // Store data so we can build an array sorted by width if we need to shrink tabs down IM_MSVC_WARNING_SUPPRESS(6385); ImGuiShrinkWidthItem* shrink_width_item = &g.ShrinkWidthBuffer[shrink_buffer_indexes[section_n]++]; shrink_width_item->Index = tab_n; shrink_width_item->Width = shrink_width_item->InitialWidth = tab->ContentWidth; tab->Width = ImMax(tab->ContentWidth, 1.0f); } // Compute total ideal width (used for e.g. auto-resizing a window) tab_bar->WidthAllTabsIdeal = 0.0f; for (int section_n = 0; section_n < 3; section_n++) tab_bar->WidthAllTabsIdeal += sections[section_n].Width + sections[section_n].Spacing; // Horizontal scrolling buttons // (note that TabBarScrollButtons() will alter BarRect.Max.x) if ((tab_bar->WidthAllTabsIdeal > tab_bar->BarRect.GetWidth() && tab_bar->Tabs.Size > 1) && !(tab_bar->Flags & ImGuiTabBarFlags_NoTabListScrollingButtons) && (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll)) if (ImGuiTabItem* scroll_and_select_tab = TabBarScrollingButtons(tab_bar)) { scroll_to_tab_id = scroll_and_select_tab->ID; if ((scroll_and_select_tab->Flags & ImGuiTabItemFlags_Button) == 0) tab_bar->SelectedTabId = scroll_to_tab_id; } // Shrink widths if full tabs don't fit in their allocated space float section_0_w = sections[0].Width + sections[0].Spacing; float section_1_w = sections[1].Width + sections[1].Spacing; float section_2_w = sections[2].Width + sections[2].Spacing; bool central_section_is_visible = (section_0_w + section_2_w) < tab_bar->BarRect.GetWidth(); float width_excess; if (central_section_is_visible) width_excess = ImMax(section_1_w - (tab_bar->BarRect.GetWidth() - section_0_w - section_2_w), 0.0f); // Excess used to shrink central section else width_excess = (section_0_w + section_2_w) - tab_bar->BarRect.GetWidth(); // Excess used to shrink leading/trailing section // With ImGuiTabBarFlags_FittingPolicyScroll policy, we will only shrink leading/trailing if the central section is not visible anymore if (width_excess >= 1.0f && ((tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyResizeDown) || !central_section_is_visible)) { int shrink_data_count = (central_section_is_visible ? sections[1].TabCount : sections[0].TabCount + sections[2].TabCount); int shrink_data_offset = (central_section_is_visible ? sections[0].TabCount + sections[2].TabCount : 0); ShrinkWidths(g.ShrinkWidthBuffer.Data + shrink_data_offset, shrink_data_count, width_excess); // Apply shrunk values into tabs and sections for (int tab_n = shrink_data_offset; tab_n < shrink_data_offset + shrink_data_count; tab_n++) { ImGuiTabItem* tab = &tab_bar->Tabs[g.ShrinkWidthBuffer[tab_n].Index]; float shrinked_width = IM_TRUNC(g.ShrinkWidthBuffer[tab_n].Width); if (shrinked_width < 0.0f) continue; shrinked_width = ImMax(1.0f, shrinked_width); int section_n = TabItemGetSectionIdx(tab); sections[section_n].Width -= (tab->Width - shrinked_width); tab->Width = shrinked_width; } } // Layout all active tabs int section_tab_index = 0; float tab_offset = 0.0f; tab_bar->WidthAllTabs = 0.0f; for (int section_n = 0; section_n < 3; section_n++) { ImGuiTabBarSection* section = §ions[section_n]; if (section_n == 2) tab_offset = ImMin(ImMax(0.0f, tab_bar->BarRect.GetWidth() - section->Width), tab_offset); for (int tab_n = 0; tab_n < section->TabCount; tab_n++) { ImGuiTabItem* tab = &tab_bar->Tabs[section_tab_index + tab_n]; tab->Offset = tab_offset; tab->NameOffset = -1; tab_offset += tab->Width + (tab_n < section->TabCount - 1 ? g.Style.ItemInnerSpacing.x : 0.0f); } tab_bar->WidthAllTabs += ImMax(section->Width + section->Spacing, 0.0f); tab_offset += section->Spacing; section_tab_index += section->TabCount; } // Clear name buffers tab_bar->TabsNames.Buf.resize(0); // If we have lost the selected tab, select the next most recently active one if (found_selected_tab_id == false) tab_bar->SelectedTabId = 0; if (tab_bar->SelectedTabId == 0 && tab_bar->NextSelectedTabId == 0 && most_recently_selected_tab != NULL) scroll_to_tab_id = tab_bar->SelectedTabId = most_recently_selected_tab->ID; // Lock in visible tab tab_bar->VisibleTabId = tab_bar->SelectedTabId; tab_bar->VisibleTabWasSubmitted = false; // Apply request requests if (scroll_to_tab_id != 0) TabBarScrollToTab(tab_bar, scroll_to_tab_id, sections); else if ((tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll) && IsMouseHoveringRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max, true) && IsWindowContentHoverable(g.CurrentWindow)) { const float wheel = g.IO.MouseWheelRequestAxisSwap ? g.IO.MouseWheel : g.IO.MouseWheelH; const ImGuiKey wheel_key = g.IO.MouseWheelRequestAxisSwap ? ImGuiKey_MouseWheelY : ImGuiKey_MouseWheelX; if (TestKeyOwner(wheel_key, tab_bar->ID) && wheel != 0.0f) { const float scroll_step = wheel * TabBarCalcScrollableWidth(tab_bar, sections) / 3.0f; tab_bar->ScrollingTargetDistToVisibility = 0.0f; tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget - scroll_step); } SetKeyOwner(wheel_key, tab_bar->ID); } // Update scrolling tab_bar->ScrollingAnim = TabBarScrollClamp(tab_bar, tab_bar->ScrollingAnim); tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget); if (tab_bar->ScrollingAnim != tab_bar->ScrollingTarget) { // Scrolling speed adjust itself so we can always reach our target in 1/3 seconds. // Teleport if we are aiming far off the visible line tab_bar->ScrollingSpeed = ImMax(tab_bar->ScrollingSpeed, 70.0f * g.FontSize); tab_bar->ScrollingSpeed = ImMax(tab_bar->ScrollingSpeed, ImFabs(tab_bar->ScrollingTarget - tab_bar->ScrollingAnim) / 0.3f); const bool teleport = (tab_bar->PrevFrameVisible + 1 < g.FrameCount) || (tab_bar->ScrollingTargetDistToVisibility > 10.0f * g.FontSize); tab_bar->ScrollingAnim = teleport ? tab_bar->ScrollingTarget : ImLinearSweep(tab_bar->ScrollingAnim, tab_bar->ScrollingTarget, g.IO.DeltaTime * tab_bar->ScrollingSpeed); } else { tab_bar->ScrollingSpeed = 0.0f; } tab_bar->ScrollingRectMinX = tab_bar->BarRect.Min.x + sections[0].Width + sections[0].Spacing; tab_bar->ScrollingRectMaxX = tab_bar->BarRect.Max.x - sections[2].Width - sections[1].Spacing; // Actual layout in host window (we don't do it in BeginTabBar() so as not to waste an extra frame) ImGuiWindow* window = g.CurrentWindow; window->DC.CursorPos = tab_bar->BarRect.Min; ItemSize(ImVec2(tab_bar->WidthAllTabs, tab_bar->BarRect.GetHeight()), tab_bar->FramePadding.y); window->DC.IdealMaxPos.x = ImMax(window->DC.IdealMaxPos.x, tab_bar->BarRect.Min.x + tab_bar->WidthAllTabsIdeal); } // Dockable windows uses Name/ID in the global namespace. Non-dockable items use the ID stack. static ImU32 ImGui::TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label, ImGuiWindow* docked_window) { IM_ASSERT(docked_window == NULL); // master branch only IM_UNUSED(docked_window); if (tab_bar->Flags & ImGuiTabBarFlags_DockNode) { ImGuiID id = ImHashStr(label); KeepAliveID(id); return id; } else { ImGuiWindow* window = GImGui->CurrentWindow; return window->GetID(label); } } static float ImGui::TabBarCalcMaxTabWidth() { ImGuiContext& g = *GImGui; return g.FontSize * 20.0f; } ImGuiTabItem* ImGui::TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id) { if (tab_id != 0) for (int n = 0; n < tab_bar->Tabs.Size; n++) if (tab_bar->Tabs[n].ID == tab_id) return &tab_bar->Tabs[n]; return NULL; } // Order = visible order, not submission order! (which is tab->BeginOrder) ImGuiTabItem* ImGui::TabBarFindTabByOrder(ImGuiTabBar* tab_bar, int order) { if (order < 0 || order >= tab_bar->Tabs.Size) return NULL; return &tab_bar->Tabs[order]; } ImGuiTabItem* ImGui::TabBarGetCurrentTab(ImGuiTabBar* tab_bar) { if (tab_bar->LastTabItemIdx <= 0 || tab_bar->LastTabItemIdx >= tab_bar->Tabs.Size) return NULL; return &tab_bar->Tabs[tab_bar->LastTabItemIdx]; } const char* ImGui::TabBarGetTabName(ImGuiTabBar* tab_bar, ImGuiTabItem* tab) { if (tab->NameOffset == -1) return "N/A"; IM_ASSERT(tab->NameOffset < tab_bar->TabsNames.Buf.Size); return tab_bar->TabsNames.Buf.Data + tab->NameOffset; } // The *TabId fields are already set by the docking system _before_ the actual TabItem was created, so we clear them regardless. void ImGui::TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id) { if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id)) tab_bar->Tabs.erase(tab); if (tab_bar->VisibleTabId == tab_id) { tab_bar->VisibleTabId = 0; } if (tab_bar->SelectedTabId == tab_id) { tab_bar->SelectedTabId = 0; } if (tab_bar->NextSelectedTabId == tab_id) { tab_bar->NextSelectedTabId = 0; } } // Called on manual closure attempt void ImGui::TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab) { if (tab->Flags & ImGuiTabItemFlags_Button) return; // A button appended with TabItemButton(). if ((tab->Flags & (ImGuiTabItemFlags_UnsavedDocument | ImGuiTabItemFlags_NoAssumedClosure)) == 0) { // This will remove a frame of lag for selecting another tab on closure. // However we don't run it in the case where the 'Unsaved' flag is set, so user gets a chance to fully undo the closure tab->WantClose = true; if (tab_bar->VisibleTabId == tab->ID) { tab->LastFrameVisible = -1; tab_bar->SelectedTabId = tab_bar->NextSelectedTabId = 0; } } else { // Actually select before expecting closure attempt (on an UnsavedDocument tab user is expect to e.g. show a popup) if (tab_bar->VisibleTabId != tab->ID) TabBarQueueFocus(tab_bar, tab); } } static float ImGui::TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling) { scrolling = ImMin(scrolling, tab_bar->WidthAllTabs - tab_bar->BarRect.GetWidth()); return ImMax(scrolling, 0.0f); } // Note: we may scroll to tab that are not selected! e.g. using keyboard arrow keys static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGuiTabBarSection* sections) { ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id); if (tab == NULL) return; if (tab->Flags & ImGuiTabItemFlags_SectionMask_) return; ImGuiContext& g = *GImGui; float margin = g.FontSize * 1.0f; // When to scroll to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar) int order = TabBarGetTabOrder(tab_bar, tab); // Scrolling happens only in the central section (leading/trailing sections are not scrolling) float scrollable_width = TabBarCalcScrollableWidth(tab_bar, sections); // We make all tabs positions all relative Sections[0].Width to make code simpler float tab_x1 = tab->Offset - sections[0].Width + (order > sections[0].TabCount - 1 ? -margin : 0.0f); float tab_x2 = tab->Offset - sections[0].Width + tab->Width + (order + 1 < tab_bar->Tabs.Size - sections[2].TabCount ? margin : 1.0f); tab_bar->ScrollingTargetDistToVisibility = 0.0f; if (tab_bar->ScrollingTarget > tab_x1 || (tab_x2 - tab_x1 >= scrollable_width)) { // Scroll to the left tab_bar->ScrollingTargetDistToVisibility = ImMax(tab_bar->ScrollingAnim - tab_x2, 0.0f); tab_bar->ScrollingTarget = tab_x1; } else if (tab_bar->ScrollingTarget < tab_x2 - scrollable_width) { // Scroll to the right tab_bar->ScrollingTargetDistToVisibility = ImMax((tab_x1 - scrollable_width) - tab_bar->ScrollingAnim, 0.0f); tab_bar->ScrollingTarget = tab_x2 - scrollable_width; } } void ImGui::TabBarQueueFocus(ImGuiTabBar* tab_bar, ImGuiTabItem* tab) { tab_bar->NextSelectedTabId = tab->ID; } void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, int offset) { IM_ASSERT(offset != 0); IM_ASSERT(tab_bar->ReorderRequestTabId == 0); tab_bar->ReorderRequestTabId = tab->ID; tab_bar->ReorderRequestOffset = (ImS16)offset; } void ImGui::TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, ImGuiTabItem* src_tab, ImVec2 mouse_pos) { ImGuiContext& g = *GImGui; IM_ASSERT(tab_bar->ReorderRequestTabId == 0); if ((tab_bar->Flags & ImGuiTabBarFlags_Reorderable) == 0) return; const bool is_central_section = (src_tab->Flags & ImGuiTabItemFlags_SectionMask_) == 0; const float bar_offset = tab_bar->BarRect.Min.x - (is_central_section ? tab_bar->ScrollingTarget : 0); // Count number of contiguous tabs we are crossing over const int dir = (bar_offset + src_tab->Offset) > mouse_pos.x ? -1 : +1; const int src_idx = tab_bar->Tabs.index_from_ptr(src_tab); int dst_idx = src_idx; for (int i = src_idx; i >= 0 && i < tab_bar->Tabs.Size; i += dir) { // Reordered tabs must share the same section const ImGuiTabItem* dst_tab = &tab_bar->Tabs[i]; if (dst_tab->Flags & ImGuiTabItemFlags_NoReorder) break; if ((dst_tab->Flags & ImGuiTabItemFlags_SectionMask_) != (src_tab->Flags & ImGuiTabItemFlags_SectionMask_)) break; dst_idx = i; // Include spacing after tab, so when mouse cursor is between tabs we would not continue checking further tabs that are not hovered. const float x1 = bar_offset + dst_tab->Offset - g.Style.ItemInnerSpacing.x; const float x2 = bar_offset + dst_tab->Offset + dst_tab->Width + g.Style.ItemInnerSpacing.x; //GetForegroundDrawList()->AddRect(ImVec2(x1, tab_bar->BarRect.Min.y), ImVec2(x2, tab_bar->BarRect.Max.y), IM_COL32(255, 0, 0, 255)); if ((dir < 0 && mouse_pos.x > x1) || (dir > 0 && mouse_pos.x < x2)) break; } if (dst_idx != src_idx) TabBarQueueReorder(tab_bar, src_tab, dst_idx - src_idx); } bool ImGui::TabBarProcessReorder(ImGuiTabBar* tab_bar) { ImGuiTabItem* tab1 = TabBarFindTabByID(tab_bar, tab_bar->ReorderRequestTabId); if (tab1 == NULL || (tab1->Flags & ImGuiTabItemFlags_NoReorder)) return false; //IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools int tab2_order = TabBarGetTabOrder(tab_bar, tab1) + tab_bar->ReorderRequestOffset; if (tab2_order < 0 || tab2_order >= tab_bar->Tabs.Size) return false; // Reordered tabs must share the same section // (Note: TabBarQueueReorderFromMousePos() also has a similar test but since we allow direct calls to TabBarQueueReorder() we do it here too) ImGuiTabItem* tab2 = &tab_bar->Tabs[tab2_order]; if (tab2->Flags & ImGuiTabItemFlags_NoReorder) return false; if ((tab1->Flags & ImGuiTabItemFlags_SectionMask_) != (tab2->Flags & ImGuiTabItemFlags_SectionMask_)) return false; ImGuiTabItem item_tmp = *tab1; ImGuiTabItem* src_tab = (tab_bar->ReorderRequestOffset > 0) ? tab1 + 1 : tab2; ImGuiTabItem* dst_tab = (tab_bar->ReorderRequestOffset > 0) ? tab1 : tab2 + 1; const int move_count = (tab_bar->ReorderRequestOffset > 0) ? tab_bar->ReorderRequestOffset : -tab_bar->ReorderRequestOffset; memmove(dst_tab, src_tab, move_count * sizeof(ImGuiTabItem)); *tab2 = item_tmp; if (tab_bar->Flags & ImGuiTabBarFlags_SaveSettings) MarkIniSettingsDirty(); return true; } static ImGuiTabItem* ImGui::TabBarScrollingButtons(ImGuiTabBar* tab_bar) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; const ImVec2 arrow_button_size(g.FontSize - 2.0f, g.FontSize + g.Style.FramePadding.y * 2.0f); const float scrolling_buttons_width = arrow_button_size.x * 2.0f; const ImVec2 backup_cursor_pos = window->DC.CursorPos; //window->DrawList->AddRect(ImVec2(tab_bar->BarRect.Max.x - scrolling_buttons_width, tab_bar->BarRect.Min.y), ImVec2(tab_bar->BarRect.Max.x, tab_bar->BarRect.Max.y), IM_COL32(255,0,0,255)); int select_dir = 0; ImVec4 arrow_col = g.Style.Colors[ImGuiCol_Text]; arrow_col.w *= 0.5f; PushStyleColor(ImGuiCol_Text, arrow_col); PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); const float backup_repeat_delay = g.IO.KeyRepeatDelay; const float backup_repeat_rate = g.IO.KeyRepeatRate; g.IO.KeyRepeatDelay = 0.250f; g.IO.KeyRepeatRate = 0.200f; float x = ImMax(tab_bar->BarRect.Min.x, tab_bar->BarRect.Max.x - scrolling_buttons_width); window->DC.CursorPos = ImVec2(x, tab_bar->BarRect.Min.y); if (ArrowButtonEx("##<", ImGuiDir_Left, arrow_button_size, ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_Repeat)) select_dir = -1; window->DC.CursorPos = ImVec2(x + arrow_button_size.x, tab_bar->BarRect.Min.y); if (ArrowButtonEx("##>", ImGuiDir_Right, arrow_button_size, ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_Repeat)) select_dir = +1; PopStyleColor(2); g.IO.KeyRepeatRate = backup_repeat_rate; g.IO.KeyRepeatDelay = backup_repeat_delay; ImGuiTabItem* tab_to_scroll_to = NULL; if (select_dir != 0) if (ImGuiTabItem* tab_item = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId)) { int selected_order = TabBarGetTabOrder(tab_bar, tab_item); int target_order = selected_order + select_dir; // Skip tab item buttons until another tab item is found or end is reached while (tab_to_scroll_to == NULL) { // If we are at the end of the list, still scroll to make our tab visible tab_to_scroll_to = &tab_bar->Tabs[(target_order >= 0 && target_order < tab_bar->Tabs.Size) ? target_order : selected_order]; // Cross through buttons // (even if first/last item is a button, return it so we can update the scroll) if (tab_to_scroll_to->Flags & ImGuiTabItemFlags_Button) { target_order += select_dir; selected_order += select_dir; tab_to_scroll_to = (target_order < 0 || target_order >= tab_bar->Tabs.Size) ? tab_to_scroll_to : NULL; } } } window->DC.CursorPos = backup_cursor_pos; tab_bar->BarRect.Max.x -= scrolling_buttons_width + 1.0f; return tab_to_scroll_to; } static ImGuiTabItem* ImGui::TabBarTabListPopupButton(ImGuiTabBar* tab_bar) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; // We use g.Style.FramePadding.y to match the square ArrowButton size const float tab_list_popup_button_width = g.FontSize + g.Style.FramePadding.y; const ImVec2 backup_cursor_pos = window->DC.CursorPos; window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x - g.Style.FramePadding.y, tab_bar->BarRect.Min.y); tab_bar->BarRect.Min.x += tab_list_popup_button_width; ImVec4 arrow_col = g.Style.Colors[ImGuiCol_Text]; arrow_col.w *= 0.5f; PushStyleColor(ImGuiCol_Text, arrow_col); PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); bool open = BeginCombo("##v", NULL, ImGuiComboFlags_NoPreview | ImGuiComboFlags_HeightLargest); PopStyleColor(2); ImGuiTabItem* tab_to_select = NULL; if (open) { for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++) { ImGuiTabItem* tab = &tab_bar->Tabs[tab_n]; if (tab->Flags & ImGuiTabItemFlags_Button) continue; const char* tab_name = TabBarGetTabName(tab_bar, tab); if (Selectable(tab_name, tab_bar->SelectedTabId == tab->ID)) tab_to_select = tab; } EndCombo(); } window->DC.CursorPos = backup_cursor_pos; return tab_to_select; } //------------------------------------------------------------------------- // [SECTION] Widgets: BeginTabItem, EndTabItem, etc. //------------------------------------------------------------------------- // - BeginTabItem() // - EndTabItem() // - TabItemButton() // - TabItemEx() [Internal] // - SetTabItemClosed() // - TabItemCalcSize() [Internal] // - TabItemBackground() [Internal] // - TabItemLabelAndCloseButton() [Internal] //------------------------------------------------------------------------- bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (window->SkipItems) return false; ImGuiTabBar* tab_bar = g.CurrentTabBar; if (tab_bar == NULL) { IM_ASSERT_USER_ERROR(tab_bar, "Needs to be called between BeginTabBar() and EndTabBar()!"); return false; } IM_ASSERT(!(flags & ImGuiTabItemFlags_Button)); // BeginTabItem() Can't be used with button flags, use TabItemButton() instead! bool ret = TabItemEx(tab_bar, label, p_open, flags, NULL); if (ret && !(flags & ImGuiTabItemFlags_NoPushId)) { ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx]; PushOverrideID(tab->ID); // We already hashed 'label' so push into the ID stack directly instead of doing another hash through PushID(label) } return ret; } void ImGui::EndTabItem() { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (window->SkipItems) return; ImGuiTabBar* tab_bar = g.CurrentTabBar; if (tab_bar == NULL) { IM_ASSERT_USER_ERROR(tab_bar != NULL, "Needs to be called between BeginTabBar() and EndTabBar()!"); return; } IM_ASSERT(tab_bar->LastTabItemIdx >= 0); ImGuiTabItem* tab = &tab_bar->Tabs[tab_bar->LastTabItemIdx]; if (!(tab->Flags & ImGuiTabItemFlags_NoPushId)) PopID(); } bool ImGui::TabItemButton(const char* label, ImGuiTabItemFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; if (window->SkipItems) return false; ImGuiTabBar* tab_bar = g.CurrentTabBar; if (tab_bar == NULL) { IM_ASSERT_USER_ERROR(tab_bar != NULL, "Needs to be called between BeginTabBar() and EndTabBar()!"); return false; } return TabItemEx(tab_bar, label, NULL, flags | ImGuiTabItemFlags_Button | ImGuiTabItemFlags_NoReorder, NULL); } bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags, ImGuiWindow* docked_window) { // Layout whole tab bar if not already done ImGuiContext& g = *GImGui; if (tab_bar->WantLayout) { ImGuiNextItemData backup_next_item_data = g.NextItemData; TabBarLayout(tab_bar); g.NextItemData = backup_next_item_data; } ImGuiWindow* window = g.CurrentWindow; if (window->SkipItems) return false; const ImGuiStyle& style = g.Style; const ImGuiID id = TabBarCalcTabID(tab_bar, label, docked_window); // If the user called us with *p_open == false, we early out and don't render. // We make a call to ItemAdd() so that attempts to use a contextual popup menu with an implicit ID won't use an older ID. IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags); if (p_open && !*p_open) { ItemAdd(ImRect(), id, NULL, ImGuiItemFlags_NoNav); return false; } IM_ASSERT(!p_open || !(flags & ImGuiTabItemFlags_Button)); IM_ASSERT((flags & (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing)) != (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing)); // Can't use both Leading and Trailing // Store into ImGuiTabItemFlags_NoCloseButton, also honor ImGuiTabItemFlags_NoCloseButton passed by user (although not documented) if (flags & ImGuiTabItemFlags_NoCloseButton) p_open = NULL; else if (p_open == NULL) flags |= ImGuiTabItemFlags_NoCloseButton; // Acquire tab data ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, id); bool tab_is_new = false; if (tab == NULL) { tab_bar->Tabs.push_back(ImGuiTabItem()); tab = &tab_bar->Tabs.back(); tab->ID = id; tab_bar->TabsAddedNew = tab_is_new = true; } tab_bar->LastTabItemIdx = (ImS16)tab_bar->Tabs.index_from_ptr(tab); // Calculate tab contents size ImVec2 size = TabItemCalcSize(label, (p_open != NULL) || (flags & ImGuiTabItemFlags_UnsavedDocument)); tab->RequestedWidth = -1.0f; if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasWidth) size.x = tab->RequestedWidth = g.NextItemData.Width; if (tab_is_new) tab->Width = ImMax(1.0f, size.x); tab->ContentWidth = size.x; tab->BeginOrder = tab_bar->TabsActiveCount++; const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount); const bool tab_bar_focused = (tab_bar->Flags & ImGuiTabBarFlags_IsFocused) != 0; const bool tab_appearing = (tab->LastFrameVisible + 1 < g.FrameCount); const bool tab_just_unsaved = (flags & ImGuiTabItemFlags_UnsavedDocument) && !(tab->Flags & ImGuiTabItemFlags_UnsavedDocument); const bool is_tab_button = (flags & ImGuiTabItemFlags_Button) != 0; tab->LastFrameVisible = g.FrameCount; tab->Flags = flags; // Append name _WITH_ the zero-terminator if (docked_window != NULL) { IM_ASSERT(docked_window == NULL); // master branch only } else { tab->NameOffset = (ImS32)tab_bar->TabsNames.size(); tab_bar->TabsNames.append(label, label + strlen(label) + 1); } // Update selected tab if (!is_tab_button) { if (tab_appearing && (tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs) && tab_bar->NextSelectedTabId == 0) if (!tab_bar_appearing || tab_bar->SelectedTabId == 0) TabBarQueueFocus(tab_bar, tab); // New tabs gets activated if ((flags & ImGuiTabItemFlags_SetSelected) && (tab_bar->SelectedTabId != id)) // _SetSelected can only be passed on explicit tab bar TabBarQueueFocus(tab_bar, tab); } // Lock visibility // (Note: tab_contents_visible != tab_selected... because CTRL+TAB operations may preview some tabs without selecting them!) bool tab_contents_visible = (tab_bar->VisibleTabId == id); if (tab_contents_visible) tab_bar->VisibleTabWasSubmitted = true; // On the very first frame of a tab bar we let first tab contents be visible to minimize appearing glitches if (!tab_contents_visible && tab_bar->SelectedTabId == 0 && tab_bar_appearing) if (tab_bar->Tabs.Size == 1 && !(tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs)) tab_contents_visible = true; // Note that tab_is_new is not necessarily the same as tab_appearing! When a tab bar stops being submitted // and then gets submitted again, the tabs will have 'tab_appearing=true' but 'tab_is_new=false'. if (tab_appearing && (!tab_bar_appearing || tab_is_new)) { ItemAdd(ImRect(), id, NULL, ImGuiItemFlags_NoNav); if (is_tab_button) return false; return tab_contents_visible; } if (tab_bar->SelectedTabId == id) tab->LastFrameSelected = g.FrameCount; // Backup current layout position const ImVec2 backup_main_cursor_pos = window->DC.CursorPos; // Layout const bool is_central_section = (tab->Flags & ImGuiTabItemFlags_SectionMask_) == 0; size.x = tab->Width; if (is_central_section) window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2(IM_TRUNC(tab->Offset - tab_bar->ScrollingAnim), 0.0f); else window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2(tab->Offset, 0.0f); ImVec2 pos = window->DC.CursorPos; ImRect bb(pos, pos + size); // We don't have CPU clipping primitives to clip the CloseButton (until it becomes a texture), so need to add an extra draw call (temporary in the case of vertical animation) const bool want_clip_rect = is_central_section && (bb.Min.x < tab_bar->ScrollingRectMinX || bb.Max.x > tab_bar->ScrollingRectMaxX); if (want_clip_rect) PushClipRect(ImVec2(ImMax(bb.Min.x, tab_bar->ScrollingRectMinX), bb.Min.y - 1), ImVec2(tab_bar->ScrollingRectMaxX, bb.Max.y), true); ImVec2 backup_cursor_max_pos = window->DC.CursorMaxPos; ItemSize(bb.GetSize(), style.FramePadding.y); window->DC.CursorMaxPos = backup_cursor_max_pos; if (!ItemAdd(bb, id)) { if (want_clip_rect) PopClipRect(); window->DC.CursorPos = backup_main_cursor_pos; return tab_contents_visible; } // Click to Select a tab // Allow the close button to overlap ImGuiButtonFlags button_flags = ((is_tab_button ? ImGuiButtonFlags_PressedOnClickRelease : ImGuiButtonFlags_PressedOnClick) | ImGuiButtonFlags_AllowOverlap); if (g.DragDropActive) button_flags |= ImGuiButtonFlags_PressedOnDragDropHold; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); if (pressed && !is_tab_button) TabBarQueueFocus(tab_bar, tab); // Drag and drop: re-order tabs if (held && !tab_appearing && IsMouseDragging(0)) { if (!g.DragDropActive && (tab_bar->Flags & ImGuiTabBarFlags_Reorderable)) { // While moving a tab it will jump on the other side of the mouse, so we also test for MouseDelta.x if (g.IO.MouseDelta.x < 0.0f && g.IO.MousePos.x < bb.Min.x) { TabBarQueueReorderFromMousePos(tab_bar, tab, g.IO.MousePos); } else if (g.IO.MouseDelta.x > 0.0f && g.IO.MousePos.x > bb.Max.x) { TabBarQueueReorderFromMousePos(tab_bar, tab, g.IO.MousePos); } } } #if 0 if (hovered && g.HoveredIdNotActiveTimer > TOOLTIP_DELAY && bb.GetWidth() < tab->ContentWidth) { // Enlarge tab display when hovering bb.Max.x = bb.Min.x + IM_TRUNC(ImLerp(bb.GetWidth(), tab->ContentWidth, ImSaturate((g.HoveredIdNotActiveTimer - 0.40f) * 6.0f))); display_draw_list = GetForegroundDrawList(window); TabItemBackground(display_draw_list, bb, flags, GetColorU32(ImGuiCol_TitleBgActive)); } #endif // Render tab shape ImDrawList* display_draw_list = window->DrawList; const ImU32 tab_col = GetColorU32((held || hovered) ? ImGuiCol_TabHovered : tab_contents_visible ? (tab_bar_focused ? ImGuiCol_TabActive : ImGuiCol_TabUnfocusedActive) : (tab_bar_focused ? ImGuiCol_Tab : ImGuiCol_TabUnfocused)); TabItemBackground(display_draw_list, bb, flags, tab_col); RenderNavHighlight(bb, id); // Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget. const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup); if (hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)) && !is_tab_button) TabBarQueueFocus(tab_bar, tab); if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton) flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton; // Render tab label, process close button const ImGuiID close_button_id = p_open ? GetIDWithSeed("#CLOSE", NULL, id) : 0; bool just_closed; bool text_clipped; TabItemLabelAndCloseButton(display_draw_list, bb, tab_just_unsaved ? (flags & ~ImGuiTabItemFlags_UnsavedDocument) : flags, tab_bar->FramePadding, label, id, close_button_id, tab_contents_visible, &just_closed, &text_clipped); if (just_closed && p_open != NULL) { *p_open = false; TabBarCloseTab(tab_bar, tab); } // Restore main window position so user can draw there if (want_clip_rect) PopClipRect(); window->DC.CursorPos = backup_main_cursor_pos; // Tooltip // (Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer-> seems ok) // (We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar, which g.HoveredId ignores) // FIXME: This is a mess. // FIXME: We may want disabled tab to still display the tooltip? if (text_clipped && g.HoveredId == id && !held) if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip)) SetItemTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label); IM_ASSERT(!is_tab_button || !(tab_bar->SelectedTabId == tab->ID && is_tab_button)); // TabItemButton should not be selected if (is_tab_button) return pressed; return tab_contents_visible; } // [Public] This is call is 100% optional but it allows to remove some one-frame glitches when a tab has been unexpectedly removed. // To use it to need to call the function SetTabItemClosed() between BeginTabBar() and EndTabBar(). // Tabs closed by the close button will automatically be flagged to avoid this issue. void ImGui::SetTabItemClosed(const char* label) { ImGuiContext& g = *GImGui; bool is_within_manual_tab_bar = g.CurrentTabBar && !(g.CurrentTabBar->Flags & ImGuiTabBarFlags_DockNode); if (is_within_manual_tab_bar) { ImGuiTabBar* tab_bar = g.CurrentTabBar; ImGuiID tab_id = TabBarCalcTabID(tab_bar, label, NULL); if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id)) tab->WantClose = true; // Will be processed by next call to TabBarLayout() } } ImVec2 ImGui::TabItemCalcSize(const char* label, bool has_close_button_or_unsaved_marker) { ImGuiContext& g = *GImGui; ImVec2 label_size = CalcTextSize(label, NULL, true); ImVec2 size = ImVec2(label_size.x + g.Style.FramePadding.x, label_size.y + g.Style.FramePadding.y * 2.0f); if (has_close_button_or_unsaved_marker) size.x += g.Style.FramePadding.x + (g.Style.ItemInnerSpacing.x + g.FontSize); // We use Y intentionally to fit the close button circle. else size.x += g.Style.FramePadding.x + 1.0f; return ImVec2(ImMin(size.x, TabBarCalcMaxTabWidth()), size.y); } ImVec2 ImGui::TabItemCalcSize(ImGuiWindow*) { IM_ASSERT(0); // This function exists to facilitate merge with 'docking' branch. return ImVec2(0.0f, 0.0f); } void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImU32 col) { // While rendering tabs, we trim 1 pixel off the top of our bounding box so they can fit within a regular frame height while looking "detached" from it. ImGuiContext& g = *GImGui; const float width = bb.GetWidth(); IM_UNUSED(flags); IM_ASSERT(width > 0.0f); const float rounding = ImMax(0.0f, ImMin((flags & ImGuiTabItemFlags_Button) ? g.Style.FrameRounding : g.Style.TabRounding, width * 0.5f - 1.0f)); const float y1 = bb.Min.y + 1.0f; const float y2 = bb.Max.y - g.Style.TabBarBorderSize; draw_list->PathLineTo(ImVec2(bb.Min.x, y2)); draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding, y1 + rounding), rounding, 6, 9); draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding, y1 + rounding), rounding, 9, 12); draw_list->PathLineTo(ImVec2(bb.Max.x, y2)); draw_list->PathFillConvex(col); if (g.Style.TabBorderSize > 0.0f) { draw_list->PathLineTo(ImVec2(bb.Min.x + 0.5f, y2)); draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding + 0.5f, y1 + rounding + 0.5f), rounding, 6, 9); draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding - 0.5f, y1 + rounding + 0.5f), rounding, 9, 12); draw_list->PathLineTo(ImVec2(bb.Max.x - 0.5f, y2)); draw_list->PathStroke(GetColorU32(ImGuiCol_Border), 0, g.Style.TabBorderSize); } } // Render text label (with custom clipping) + Unsaved Document marker + Close Button logic // We tend to lock style.FramePadding for a given tab-bar, hence the 'frame_padding' parameter. void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char* label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped) { ImGuiContext& g = *GImGui; ImVec2 label_size = CalcTextSize(label, NULL, true); if (out_just_closed) *out_just_closed = false; if (out_text_clipped) *out_text_clipped = false; if (bb.GetWidth() <= 1.0f) return; // In Style V2 we'll have full override of all colors per state (e.g. focused, selected) // But right now if you want to alter text color of tabs this is what you need to do. #if 0 const float backup_alpha = g.Style.Alpha; if (!is_contents_visible) g.Style.Alpha *= 0.7f; #endif // Render text label (with clipping + alpha gradient) + unsaved marker ImRect text_pixel_clip_bb(bb.Min.x + frame_padding.x, bb.Min.y + frame_padding.y, bb.Max.x - frame_padding.x, bb.Max.y); ImRect text_ellipsis_clip_bb = text_pixel_clip_bb; // Return clipped state ignoring the close button if (out_text_clipped) { *out_text_clipped = (text_ellipsis_clip_bb.Min.x + label_size.x) > text_pixel_clip_bb.Max.x; //draw_list->AddCircle(text_ellipsis_clip_bb.Min, 3.0f, *out_text_clipped ? IM_COL32(255, 0, 0, 255) : IM_COL32(0, 255, 0, 255)); } const float button_sz = g.FontSize; const ImVec2 button_pos(ImMax(bb.Min.x, bb.Max.x - frame_padding.x - button_sz), bb.Min.y + frame_padding.y); // Close Button & Unsaved Marker // We are relying on a subtle and confusing distinction between 'hovered' and 'g.HoveredId' which happens because we are using ImGuiButtonFlags_AllowOverlapMode + SetItemAllowOverlap() // 'hovered' will be true when hovering the Tab but NOT when hovering the close button // 'g.HoveredId==id' will be true when hovering the Tab including when hovering the close button // 'g.ActiveId==close_button_id' will be true when we are holding on the close button, in which case both hovered booleans are false bool close_button_pressed = false; bool close_button_visible = false; if (close_button_id != 0) if (is_contents_visible || bb.GetWidth() >= ImMax(button_sz, g.Style.TabMinWidthForCloseButton)) if (g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == tab_id || g.ActiveId == close_button_id) close_button_visible = true; bool unsaved_marker_visible = (flags & ImGuiTabItemFlags_UnsavedDocument) != 0 && (button_pos.x + button_sz <= bb.Max.x); if (close_button_visible) { ImGuiLastItemData last_item_backup = g.LastItemData; if (CloseButton(close_button_id, button_pos)) close_button_pressed = true; g.LastItemData = last_item_backup; // Close with middle mouse button if (!(flags & ImGuiTabItemFlags_NoCloseWithMiddleMouseButton) && IsMouseClicked(2)) close_button_pressed = true; } else if (unsaved_marker_visible) { const ImRect bullet_bb(button_pos, button_pos + ImVec2(button_sz, button_sz)); RenderBullet(draw_list, bullet_bb.GetCenter(), GetColorU32(ImGuiCol_Text)); } // This is all rather complicated // (the main idea is that because the close button only appears on hover, we don't want it to alter the ellipsis position) // FIXME: if FramePadding is noticeably large, ellipsis_max_x will be wrong here (e.g. #3497), maybe for consistency that parameter of RenderTextEllipsis() shouldn't exist.. float ellipsis_max_x = close_button_visible ? text_pixel_clip_bb.Max.x : bb.Max.x - 1.0f; if (close_button_visible || unsaved_marker_visible) { text_pixel_clip_bb.Max.x -= close_button_visible ? (button_sz) : (button_sz * 0.80f); text_ellipsis_clip_bb.Max.x -= unsaved_marker_visible ? (button_sz * 0.80f) : 0.0f; ellipsis_max_x = text_pixel_clip_bb.Max.x; } RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, text_pixel_clip_bb.Max.x, ellipsis_max_x, label, NULL, &label_size); #if 0 if (!is_contents_visible) g.Style.Alpha = backup_alpha; #endif if (out_just_closed) *out_just_closed = close_button_pressed; } #endif // #ifndef IMGUI_DISABLE RenderKit-ospray-f2a61c2/apps/common/external/imgui/imstb_rectpack.h000066400000000000000000000475701456566705700257160ustar00rootroot00000000000000// [DEAR IMGUI] // This is a slightly modified version of stb_rect_pack.h 1.01. // Grep for [DEAR IMGUI] to find the changes. // // stb_rect_pack.h - v1.01 - public domain - rectangle packing // Sean Barrett 2014 // // Useful for e.g. packing rectangular textures into an atlas. // Does not do rotation. // // Before #including, // // #define STB_RECT_PACK_IMPLEMENTATION // // in the file that you want to have the implementation. // // Not necessarily the awesomest packing method, but better than // the totally naive one in stb_truetype (which is primarily what // this is meant to replace). // // Has only had a few tests run, may have issues. // // More docs to come. // // No memory allocations; uses qsort() and assert() from stdlib. // Can override those by defining STBRP_SORT and STBRP_ASSERT. // // This library currently uses the Skyline Bottom-Left algorithm. // // Please note: better rectangle packers are welcome! Please // implement them to the same API, but with a different init // function. // // Credits // // Library // Sean Barrett // Minor features // Martins Mozeiko // github:IntellectualKitty // // Bugfixes / warning fixes // Jeremy Jaussaud // Fabian Giesen // // Version history: // // 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section // 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles // 0.99 (2019-02-07) warning fixes // 0.11 (2017-03-03) return packing success/fail result // 0.10 (2016-10-25) remove cast-away-const to avoid warnings // 0.09 (2016-08-27) fix compiler warnings // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) // 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort // 0.05: added STBRP_ASSERT to allow replacing assert // 0.04: fixed minor bug in STBRP_LARGE_RECTS support // 0.01: initial release // // LICENSE // // See end of file for license information. ////////////////////////////////////////////////////////////////////////////// // // INCLUDE SECTION // #ifndef STB_INCLUDE_STB_RECT_PACK_H #define STB_INCLUDE_STB_RECT_PACK_H #define STB_RECT_PACK_VERSION 1 #ifdef STBRP_STATIC #define STBRP_DEF static #else #define STBRP_DEF extern #endif #ifdef __cplusplus extern "C" { #endif typedef struct stbrp_context stbrp_context; typedef struct stbrp_node stbrp_node; typedef struct stbrp_rect stbrp_rect; typedef int stbrp_coord; #define STBRP__MAXVAL 0x7fffffff // Mostly for internal use, but this is the maximum supported coordinate value. STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); // Assign packed locations to rectangles. The rectangles are of type // 'stbrp_rect' defined below, stored in the array 'rects', and there // are 'num_rects' many of them. // // Rectangles which are successfully packed have the 'was_packed' flag // set to a non-zero value and 'x' and 'y' store the minimum location // on each axis (i.e. bottom-left in cartesian coordinates, top-left // if you imagine y increasing downwards). Rectangles which do not fit // have the 'was_packed' flag set to 0. // // You should not try to access the 'rects' array from another thread // while this function is running, as the function temporarily reorders // the array while it executes. // // To pack into another rectangle, you need to call stbrp_init_target // again. To continue packing into the same rectangle, you can call // this function again. Calling this multiple times with multiple rect // arrays will probably produce worse packing results than calling it // a single time with the full rectangle array, but the option is // available. // // The function returns 1 if all of the rectangles were successfully // packed and 0 otherwise. struct stbrp_rect { // reserved for your use: int id; // input: stbrp_coord w, h; // output: stbrp_coord x, y; int was_packed; // non-zero if valid packing }; // 16 bytes, nominally STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); // Initialize a rectangle packer to: // pack a rectangle that is 'width' by 'height' in dimensions // using temporary storage provided by the array 'nodes', which is 'num_nodes' long // // You must call this function every time you start packing into a new target. // // There is no "shutdown" function. The 'nodes' memory must stay valid for // the following stbrp_pack_rects() call (or calls), but can be freed after // the call (or calls) finish. // // Note: to guarantee best results, either: // 1. make sure 'num_nodes' >= 'width' // or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' // // If you don't do either of the above things, widths will be quantized to multiples // of small integers to guarantee the algorithm doesn't run out of temporary storage. // // If you do #2, then the non-quantized algorithm will be used, but the algorithm // may run out of temporary storage and be unable to pack some rectangles. STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem); // Optionally call this function after init but before doing any packing to // change the handling of the out-of-temp-memory scenario, described above. // If you call init again, this will be reset to the default (false). STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic); // Optionally select which packing heuristic the library should use. Different // heuristics will produce better/worse results for different data sets. // If you call init again, this will be reset to the default. enum { STBRP_HEURISTIC_Skyline_default=0, STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, STBRP_HEURISTIC_Skyline_BF_sortHeight }; ////////////////////////////////////////////////////////////////////////////// // // the details of the following structures don't matter to you, but they must // be visible so you can handle the memory allocations for them struct stbrp_node { stbrp_coord x,y; stbrp_node *next; }; struct stbrp_context { int width; int height; int align; int init_mode; int heuristic; int num_nodes; stbrp_node *active_head; stbrp_node *free_head; stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' }; #ifdef __cplusplus } #endif #endif ////////////////////////////////////////////////////////////////////////////// // // IMPLEMENTATION SECTION // #ifdef STB_RECT_PACK_IMPLEMENTATION #ifndef STBRP_SORT #include #define STBRP_SORT qsort #endif #ifndef STBRP_ASSERT #include #define STBRP_ASSERT assert #endif #ifdef _MSC_VER #define STBRP__NOTUSED(v) (void)(v) #define STBRP__CDECL __cdecl #else #define STBRP__NOTUSED(v) (void)sizeof(v) #define STBRP__CDECL #endif enum { STBRP__INIT_skyline = 1 }; STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) { switch (context->init_mode) { case STBRP__INIT_skyline: STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); context->heuristic = heuristic; break; default: STBRP_ASSERT(0); } } STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem) { if (allow_out_of_mem) // if it's ok to run out of memory, then don't bother aligning them; // this gives better packing, but may fail due to OOM (even though // the rectangles easily fit). @TODO a smarter approach would be to only // quantize once we've hit OOM, then we could get rid of this parameter. context->align = 1; else { // if it's not ok to run out of memory, then quantize the widths // so that num_nodes is always enough nodes. // // I.e. num_nodes * align >= width // align >= width / num_nodes // align = ceil(width/num_nodes) context->align = (context->width + context->num_nodes-1) / context->num_nodes; } } STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) { int i; for (i=0; i < num_nodes-1; ++i) nodes[i].next = &nodes[i+1]; nodes[i].next = NULL; context->init_mode = STBRP__INIT_skyline; context->heuristic = STBRP_HEURISTIC_Skyline_default; context->free_head = &nodes[0]; context->active_head = &context->extra[0]; context->width = width; context->height = height; context->num_nodes = num_nodes; stbrp_setup_allow_out_of_mem(context, 0); // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) context->extra[0].x = 0; context->extra[0].y = 0; context->extra[0].next = &context->extra[1]; context->extra[1].x = (stbrp_coord) width; context->extra[1].y = (1<<30); context->extra[1].next = NULL; } // find minimum y position if it starts at x1 static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) { stbrp_node *node = first; int x1 = x0 + width; int min_y, visited_width, waste_area; STBRP__NOTUSED(c); STBRP_ASSERT(first->x <= x0); #if 0 // skip in case we're past the node while (node->next->x <= x0) ++node; #else STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency #endif STBRP_ASSERT(node->x <= x0); min_y = 0; waste_area = 0; visited_width = 0; while (node->x < x1) { if (node->y > min_y) { // raise min_y higher. // we've accounted for all waste up to min_y, // but we'll now add more waste for everything we've visted waste_area += visited_width * (node->y - min_y); min_y = node->y; // the first time through, visited_width might be reduced if (node->x < x0) visited_width += node->next->x - x0; else visited_width += node->next->x - node->x; } else { // add waste area int under_width = node->next->x - node->x; if (under_width + visited_width > width) under_width = width - visited_width; waste_area += under_width * (min_y - node->y); visited_width += under_width; } node = node->next; } *pwaste = waste_area; return min_y; } typedef struct { int x,y; stbrp_node **prev_link; } stbrp__findresult; static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height) { int best_waste = (1<<30), best_x, best_y = (1 << 30); stbrp__findresult fr; stbrp_node **prev, *node, *tail, **best = NULL; // align to multiple of c->align width = (width + c->align - 1); width -= width % c->align; STBRP_ASSERT(width % c->align == 0); // if it can't possibly fit, bail immediately if (width > c->width || height > c->height) { fr.prev_link = NULL; fr.x = fr.y = 0; return fr; } node = c->active_head; prev = &c->active_head; while (node->x + width <= c->width) { int y,waste; y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL // bottom left if (y < best_y) { best_y = y; best = prev; } } else { // best-fit if (y + height <= c->height) { // can only use it if it first vertically if (y < best_y || (y == best_y && waste < best_waste)) { best_y = y; best_waste = waste; best = prev; } } } prev = &node->next; node = node->next; } best_x = (best == NULL) ? 0 : (*best)->x; // if doing best-fit (BF), we also have to try aligning right edge to each node position // // e.g, if fitting // // ____________________ // |____________________| // // into // // | | // | ____________| // |____________| // // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned // // This makes BF take about 2x the time if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) { tail = c->active_head; node = c->active_head; prev = &c->active_head; // find first node that's admissible while (tail->x < width) tail = tail->next; while (tail) { int xpos = tail->x - width; int y,waste; STBRP_ASSERT(xpos >= 0); // find the left position that matches this while (node->next->x <= xpos) { prev = &node->next; node = node->next; } STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); if (y + height <= c->height) { if (y <= best_y) { if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { best_x = xpos; //STBRP_ASSERT(y <= best_y); [DEAR IMGUI] best_y = y; best_waste = waste; best = prev; } } } tail = tail->next; } } fr.prev_link = best; fr.x = best_x; fr.y = best_y; return fr; } static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height) { // find best position according to heuristic stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); stbrp_node *node, *cur; // bail if: // 1. it failed // 2. the best node doesn't fit (we don't always check this) // 3. we're out of memory if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) { res.prev_link = NULL; return res; } // on success, create new node node = context->free_head; node->x = (stbrp_coord) res.x; node->y = (stbrp_coord) (res.y + height); context->free_head = node->next; // insert the new node into the right starting point, and // let 'cur' point to the remaining nodes needing to be // stiched back in cur = *res.prev_link; if (cur->x < res.x) { // preserve the existing one, so start testing with the next one stbrp_node *next = cur->next; cur->next = node; cur = next; } else { *res.prev_link = node; } // from here, traverse cur and free the nodes, until we get to one // that shouldn't be freed while (cur->next && cur->next->x <= res.x + width) { stbrp_node *next = cur->next; // move the current node to the free list cur->next = context->free_head; context->free_head = cur; cur = next; } // stitch the list back in node->next = cur; if (cur->x < res.x + width) cur->x = (stbrp_coord) (res.x + width); #ifdef _DEBUG cur = context->active_head; while (cur->x < context->width) { STBRP_ASSERT(cur->x < cur->next->x); cur = cur->next; } STBRP_ASSERT(cur->next == NULL); { int count=0; cur = context->active_head; while (cur) { cur = cur->next; ++count; } cur = context->free_head; while (cur) { cur = cur->next; ++count; } STBRP_ASSERT(count == context->num_nodes+2); } #endif return res; } static int STBRP__CDECL rect_height_compare(const void *a, const void *b) { const stbrp_rect *p = (const stbrp_rect *) a; const stbrp_rect *q = (const stbrp_rect *) b; if (p->h > q->h) return -1; if (p->h < q->h) return 1; return (p->w > q->w) ? -1 : (p->w < q->w); } static int STBRP__CDECL rect_original_order(const void *a, const void *b) { const stbrp_rect *p = (const stbrp_rect *) a; const stbrp_rect *q = (const stbrp_rect *) b; return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); } STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) { int i, all_rects_packed = 1; // we use the 'was_packed' field internally to allow sorting/unsorting for (i=0; i < num_rects; ++i) { rects[i].was_packed = i; } // sort according to heuristic STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); for (i=0; i < num_rects; ++i) { if (rects[i].w == 0 || rects[i].h == 0) { rects[i].x = rects[i].y = 0; // empty rect needs no space } else { stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); if (fr.prev_link) { rects[i].x = (stbrp_coord) fr.x; rects[i].y = (stbrp_coord) fr.y; } else { rects[i].x = rects[i].y = STBRP__MAXVAL; } } } // unsort STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); // set was_packed flags and all_rects_packed status for (i=0; i < num_rects; ++i) { rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); if (!rects[i].was_packed) all_rects_packed = 0; } // return the all_rects_packed status return all_rects_packed; } #endif /* ------------------------------------------------------------------------------ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ RenderKit-ospray-f2a61c2/apps/common/external/imgui/imstb_textedit.h000066400000000000000000001536471456566705700257570ustar00rootroot00000000000000// [DEAR IMGUI] // This is a slightly modified version of stb_textedit.h 1.14. // Those changes would need to be pushed into nothings/stb: // - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321) // - Fix in stb_textedit_find_charpos to handle last line (see https://github.com/ocornut/imgui/issues/6000 + #6783) // Grep for [DEAR IMGUI] to find the changes. // - Also renamed macros used or defined outside of IMSTB_TEXTEDIT_IMPLEMENTATION block from STB_TEXTEDIT_* to IMSTB_TEXTEDIT_* // stb_textedit.h - v1.14 - public domain - Sean Barrett // Development of this library was sponsored by RAD Game Tools // // This C header file implements the guts of a multi-line text-editing // widget; you implement display, word-wrapping, and low-level string // insertion/deletion, and stb_textedit will map user inputs into // insertions & deletions, plus updates to the cursor position, // selection state, and undo state. // // It is intended for use in games and other systems that need to build // their own custom widgets and which do not have heavy text-editing // requirements (this library is not recommended for use for editing large // texts, as its performance does not scale and it has limited undo). // // Non-trivial behaviors are modelled after Windows text controls. // // // LICENSE // // See end of file for license information. // // // DEPENDENCIES // // Uses the C runtime function 'memmove', which you can override // by defining IMSTB_TEXTEDIT_memmove before the implementation. // Uses no other functions. Performs no runtime allocations. // // // VERSION HISTORY // // 1.14 (2021-07-11) page up/down, various fixes // 1.13 (2019-02-07) fix bug in undo size management // 1.12 (2018-01-29) user can change STB_TEXTEDIT_KEYTYPE, fix redo to avoid crash // 1.11 (2017-03-03) fix HOME on last line, dragging off single-line textfield // 1.10 (2016-10-25) supress warnings about casting away const with -Wcast-qual // 1.9 (2016-08-27) customizable move-by-word // 1.8 (2016-04-02) better keyboard handling when mouse button is down // 1.7 (2015-09-13) change y range handling in case baseline is non-0 // 1.6 (2015-04-15) allow STB_TEXTEDIT_memmove // 1.5 (2014-09-10) add support for secondary keys for OS X // 1.4 (2014-08-17) fix signed/unsigned warnings // 1.3 (2014-06-19) fix mouse clicking to round to nearest char boundary // 1.2 (2014-05-27) fix some RAD types that had crept into the new code // 1.1 (2013-12-15) move-by-word (requires STB_TEXTEDIT_IS_SPACE ) // 1.0 (2012-07-26) improve documentation, initial public release // 0.3 (2012-02-24) bugfixes, single-line mode; insert mode // 0.2 (2011-11-28) fixes to undo/redo // 0.1 (2010-07-08) initial version // // ADDITIONAL CONTRIBUTORS // // Ulf Winklemann: move-by-word in 1.1 // Fabian Giesen: secondary key inputs in 1.5 // Martins Mozeiko: STB_TEXTEDIT_memmove in 1.6 // Louis Schnellbach: page up/down in 1.14 // // Bugfixes: // Scott Graham // Daniel Keller // Omar Cornut // Dan Thompson // // USAGE // // This file behaves differently depending on what symbols you define // before including it. // // // Header-file mode: // // If you do not define STB_TEXTEDIT_IMPLEMENTATION before including this, // it will operate in "header file" mode. In this mode, it declares a // single public symbol, STB_TexteditState, which encapsulates the current // state of a text widget (except for the string, which you will store // separately). // // To compile in this mode, you must define STB_TEXTEDIT_CHARTYPE to a // primitive type that defines a single character (e.g. char, wchar_t, etc). // // To save space or increase undo-ability, you can optionally define the // following things that are used by the undo system: // // STB_TEXTEDIT_POSITIONTYPE small int type encoding a valid cursor position // STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow // STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer // // If you don't define these, they are set to permissive types and // moderate sizes. The undo system does no memory allocations, so // it grows STB_TexteditState by the worst-case storage which is (in bytes): // // [4 + 3 * sizeof(STB_TEXTEDIT_POSITIONTYPE)] * STB_TEXTEDIT_UNDOSTATECOUNT // + sizeof(STB_TEXTEDIT_CHARTYPE) * STB_TEXTEDIT_UNDOCHARCOUNT // // // Implementation mode: // // If you define STB_TEXTEDIT_IMPLEMENTATION before including this, it // will compile the implementation of the text edit widget, depending // on a large number of symbols which must be defined before the include. // // The implementation is defined only as static functions. You will then // need to provide your own APIs in the same file which will access the // static functions. // // The basic concept is that you provide a "string" object which // behaves like an array of characters. stb_textedit uses indices to // refer to positions in the string, implicitly representing positions // in the displayed textedit. This is true for both plain text and // rich text; even with rich text stb_truetype interacts with your // code as if there was an array of all the displayed characters. // // Symbols that must be the same in header-file and implementation mode: // // STB_TEXTEDIT_CHARTYPE the character type // STB_TEXTEDIT_POSITIONTYPE small type that is a valid cursor position // STB_TEXTEDIT_UNDOSTATECOUNT the number of undo states to allow // STB_TEXTEDIT_UNDOCHARCOUNT the number of characters to store in the undo buffer // // Symbols you must define for implementation mode: // // STB_TEXTEDIT_STRING the type of object representing a string being edited, // typically this is a wrapper object with other data you need // // STB_TEXTEDIT_STRINGLEN(obj) the length of the string (ideally O(1)) // STB_TEXTEDIT_LAYOUTROW(&r,obj,n) returns the results of laying out a line of characters // starting from character #n (see discussion below) // STB_TEXTEDIT_GETWIDTH(obj,n,i) returns the pixel delta from the xpos of the i'th character // to the xpos of the i+1'th char for a line of characters // starting at character #n (i.e. accounts for kerning // with previous char) // STB_TEXTEDIT_KEYTOTEXT(k) maps a keyboard input to an insertable character // (return type is int, -1 means not valid to insert) // STB_TEXTEDIT_GETCHAR(obj,i) returns the i'th character of obj, 0-based // STB_TEXTEDIT_NEWLINE the character returned by _GETCHAR() we recognize // as manually wordwrapping for end-of-line positioning // // STB_TEXTEDIT_DELETECHARS(obj,i,n) delete n characters starting at i // STB_TEXTEDIT_INSERTCHARS(obj,i,c*,n) insert n characters at i (pointed to by STB_TEXTEDIT_CHARTYPE*) // // STB_TEXTEDIT_K_SHIFT a power of two that is or'd in to a keyboard input to represent the shift key // // STB_TEXTEDIT_K_LEFT keyboard input to move cursor left // STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right // STB_TEXTEDIT_K_UP keyboard input to move cursor up // STB_TEXTEDIT_K_DOWN keyboard input to move cursor down // STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page // STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page // STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME // STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END // STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME // STB_TEXTEDIT_K_TEXTEND keyboard input to move cursor to end of text // e.g. ctrl-END // STB_TEXTEDIT_K_DELETE keyboard input to delete selection or character under cursor // STB_TEXTEDIT_K_BACKSPACE keyboard input to delete selection or character left of cursor // STB_TEXTEDIT_K_UNDO keyboard input to perform undo // STB_TEXTEDIT_K_REDO keyboard input to perform redo // // Optional: // STB_TEXTEDIT_K_INSERT keyboard input to toggle insert mode // STB_TEXTEDIT_IS_SPACE(ch) true if character is whitespace (e.g. 'isspace'), // required for default WORDLEFT/WORDRIGHT handlers // STB_TEXTEDIT_MOVEWORDLEFT(obj,i) custom handler for WORDLEFT, returns index to move cursor to // STB_TEXTEDIT_MOVEWORDRIGHT(obj,i) custom handler for WORDRIGHT, returns index to move cursor to // STB_TEXTEDIT_K_WORDLEFT keyboard input to move cursor left one word // e.g. ctrl-LEFT // STB_TEXTEDIT_K_WORDRIGHT keyboard input to move cursor right one word // e.g. ctrl-RIGHT // STB_TEXTEDIT_K_LINESTART2 secondary keyboard input to move cursor to start of line // STB_TEXTEDIT_K_LINEEND2 secondary keyboard input to move cursor to end of line // STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text // STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text // // Keyboard input must be encoded as a single integer value; e.g. a character code // and some bitflags that represent shift states. to simplify the interface, SHIFT must // be a bitflag, so we can test the shifted state of cursor movements to allow selection, // i.e. (STB_TEXTEDIT_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow. // // You can encode other things, such as CONTROL or ALT, in additional bits, and // then test for their presence in e.g. STB_TEXTEDIT_K_WORDLEFT. For example, // my Windows implementations add an additional CONTROL bit, and an additional KEYDOWN // bit. Then all of the STB_TEXTEDIT_K_ values bitwise-or in the KEYDOWN bit, // and I pass both WM_KEYDOWN and WM_CHAR events to the "key" function in the // API below. The control keys will only match WM_KEYDOWN events because of the // keydown bit I add, and STB_TEXTEDIT_KEYTOTEXT only tests for the KEYDOWN // bit so it only decodes WM_CHAR events. // // STB_TEXTEDIT_LAYOUTROW returns information about the shape of one displayed // row of characters assuming they start on the i'th character--the width and // the height and the number of characters consumed. This allows this library // to traverse the entire layout incrementally. You need to compute word-wrapping // here. // // Each textfield keeps its own insert mode state, which is not how normal // applications work. To keep an app-wide insert mode, update/copy the // "insert_mode" field of STB_TexteditState before/after calling API functions. // // API // // void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line) // // void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) // void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) // int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) // int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len) // void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key) // // Each of these functions potentially updates the string and updates the // state. // // initialize_state: // set the textedit state to a known good default state when initially // constructing the textedit. // // click: // call this with the mouse x,y on a mouse down; it will update the cursor // and reset the selection start/end to the cursor point. the x,y must // be relative to the text widget, with (0,0) being the top left. // // drag: // call this with the mouse x,y on a mouse drag/up; it will update the // cursor and the selection end point // // cut: // call this to delete the current selection; returns true if there was // one. you should FIRST copy the current selection to the system paste buffer. // (To copy, just copy the current selection out of the string yourself.) // // paste: // call this to paste text at the current cursor point or over the current // selection if there is one. // // key: // call this for keyboard inputs sent to the textfield. you can use it // for "key down" events or for "translated" key events. if you need to // do both (as in Win32), or distinguish Unicode characters from control // inputs, set a high bit to distinguish the two; then you can define the // various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit // set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is // clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to // anything other type you wante before including. // // // When rendering, you can read the cursor position and selection state from // the STB_TexteditState. // // // Notes: // // This is designed to be usable in IMGUI, so it allows for the possibility of // running in an IMGUI that has NOT cached the multi-line layout. For this // reason, it provides an interface that is compatible with computing the // layout incrementally--we try to make sure we make as few passes through // as possible. (For example, to locate the mouse pointer in the text, we // could define functions that return the X and Y positions of characters // and binary search Y and then X, but if we're doing dynamic layout this // will run the layout algorithm many times, so instead we manually search // forward in one pass. Similar logic applies to e.g. up-arrow and // down-arrow movement.) // // If it's run in a widget that *has* cached the layout, then this is less // efficient, but it's not horrible on modern computers. But you wouldn't // want to edit million-line files with it. //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //// //// Header-file mode //// //// #ifndef INCLUDE_IMSTB_TEXTEDIT_H #define INCLUDE_IMSTB_TEXTEDIT_H //////////////////////////////////////////////////////////////////////// // // STB_TexteditState // // Definition of STB_TexteditState which you should store // per-textfield; it includes cursor position, selection state, // and undo state. // #ifndef IMSTB_TEXTEDIT_UNDOSTATECOUNT #define IMSTB_TEXTEDIT_UNDOSTATECOUNT 99 #endif #ifndef IMSTB_TEXTEDIT_UNDOCHARCOUNT #define IMSTB_TEXTEDIT_UNDOCHARCOUNT 999 #endif #ifndef IMSTB_TEXTEDIT_CHARTYPE #define IMSTB_TEXTEDIT_CHARTYPE int #endif #ifndef IMSTB_TEXTEDIT_POSITIONTYPE #define IMSTB_TEXTEDIT_POSITIONTYPE int #endif typedef struct { // private data IMSTB_TEXTEDIT_POSITIONTYPE where; IMSTB_TEXTEDIT_POSITIONTYPE insert_length; IMSTB_TEXTEDIT_POSITIONTYPE delete_length; int char_storage; } StbUndoRecord; typedef struct { // private data StbUndoRecord undo_rec [IMSTB_TEXTEDIT_UNDOSTATECOUNT]; IMSTB_TEXTEDIT_CHARTYPE undo_char[IMSTB_TEXTEDIT_UNDOCHARCOUNT]; short undo_point, redo_point; int undo_char_point, redo_char_point; } StbUndoState; typedef struct { ///////////////////// // // public data // int cursor; // position of the text cursor within the string int select_start; // selection start point int select_end; // selection start and end point in characters; if equal, no selection. // note that start may be less than or greater than end (e.g. when // dragging the mouse, start is where the initial click was, and you // can drag in either direction) unsigned char insert_mode; // each textfield keeps its own insert mode state. to keep an app-wide // insert mode, copy this value in/out of the app state int row_count_per_page; // page size in number of row. // this value MUST be set to >0 for pageup or pagedown in multilines documents. ///////////////////// // // private data // unsigned char cursor_at_end_of_line; // not implemented yet unsigned char initialized; unsigned char has_preferred_x; unsigned char single_line; unsigned char padding1, padding2, padding3; float preferred_x; // this determines where the cursor up/down tries to seek to along x StbUndoState undostate; } STB_TexteditState; //////////////////////////////////////////////////////////////////////// // // StbTexteditRow // // Result of layout query, used by stb_textedit to determine where // the text in each row is. // result of layout query typedef struct { float x0,x1; // starting x location, end x location (allows for align=right, etc) float baseline_y_delta; // position of baseline relative to previous row's baseline float ymin,ymax; // height of row above and below baseline int num_chars; } StbTexteditRow; #endif //INCLUDE_IMSTB_TEXTEDIT_H //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //// //// Implementation mode //// //// // implementation isn't include-guarded, since it might have indirectly // included just the "header" portion #ifdef IMSTB_TEXTEDIT_IMPLEMENTATION #ifndef IMSTB_TEXTEDIT_memmove #include #define IMSTB_TEXTEDIT_memmove memmove #endif ///////////////////////////////////////////////////////////////////////////// // // Mouse input handling // // traverse the layout to locate the nearest character to a display position static int stb_text_locate_coord(IMSTB_TEXTEDIT_STRING *str, float x, float y) { StbTexteditRow r; int n = STB_TEXTEDIT_STRINGLEN(str); float base_y = 0, prev_x; int i=0, k; r.x0 = r.x1 = 0; r.ymin = r.ymax = 0; r.num_chars = 0; // search rows to find one that straddles 'y' while (i < n) { STB_TEXTEDIT_LAYOUTROW(&r, str, i); if (r.num_chars <= 0) return n; if (i==0 && y < base_y + r.ymin) return 0; if (y < base_y + r.ymax) break; i += r.num_chars; base_y += r.baseline_y_delta; } // below all text, return 'after' last character if (i >= n) return n; // check if it's before the beginning of the line if (x < r.x0) return i; // check if it's before the end of the line if (x < r.x1) { // search characters in row for one that straddles 'x' prev_x = r.x0; for (k=0; k < r.num_chars; ++k) { float w = STB_TEXTEDIT_GETWIDTH(str, i, k); if (x < prev_x+w) { if (x < prev_x+w/2) return k+i; else return k+i+1; } prev_x += w; } // shouldn't happen, but if it does, fall through to end-of-line case } // if the last character is a newline, return that. otherwise return 'after' the last character if (STB_TEXTEDIT_GETCHAR(str, i+r.num_chars-1) == STB_TEXTEDIT_NEWLINE) return i+r.num_chars-1; else return i+r.num_chars; } // API click: on mouse down, move the cursor to the clicked location, and reset the selection static void stb_textedit_click(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) { // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse // goes off the top or bottom of the text if( state->single_line ) { StbTexteditRow r; STB_TEXTEDIT_LAYOUTROW(&r, str, 0); y = r.ymin; } state->cursor = stb_text_locate_coord(str, x, y); state->select_start = state->cursor; state->select_end = state->cursor; state->has_preferred_x = 0; } // API drag: on mouse drag, move the cursor and selection endpoint to the clicked location static void stb_textedit_drag(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y) { int p = 0; // In single-line mode, just always make y = 0. This lets the drag keep working if the mouse // goes off the top or bottom of the text if( state->single_line ) { StbTexteditRow r; STB_TEXTEDIT_LAYOUTROW(&r, str, 0); y = r.ymin; } if (state->select_start == state->select_end) state->select_start = state->cursor; p = stb_text_locate_coord(str, x, y); state->cursor = state->select_end = p; } ///////////////////////////////////////////////////////////////////////////// // // Keyboard input handling // // forward declarations static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state); static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state); static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length); static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length); static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length); typedef struct { float x,y; // position of n'th character float height; // height of line int first_char, length; // first char of row, and length int prev_first; // first char of previous row } StbFindState; // find the x/y location of a character, and remember info about the previous row in // case we get a move-up event (for page up, we'll have to rescan) static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING *str, int n, int single_line) { StbTexteditRow r; int prev_start = 0; int z = STB_TEXTEDIT_STRINGLEN(str); int i=0, first; if (n == z && single_line) { // special case if it's at the end (may not be needed?) STB_TEXTEDIT_LAYOUTROW(&r, str, 0); find->y = 0; find->first_char = 0; find->length = z; find->height = r.ymax - r.ymin; find->x = r.x1; return; } // search rows to find the one that straddles character n find->y = 0; for(;;) { STB_TEXTEDIT_LAYOUTROW(&r, str, i); if (n < i + r.num_chars) break; if (i + r.num_chars == z && z > 0 && STB_TEXTEDIT_GETCHAR(str, z - 1) != STB_TEXTEDIT_NEWLINE) // [DEAR IMGUI] special handling for last line break; // [DEAR IMGUI] prev_start = i; i += r.num_chars; find->y += r.baseline_y_delta; if (i == z) // [DEAR IMGUI] { r.num_chars = 0; // [DEAR IMGUI] break; // [DEAR IMGUI] } } find->first_char = first = i; find->length = r.num_chars; find->height = r.ymax - r.ymin; find->prev_first = prev_start; // now scan to find xpos find->x = r.x0; for (i=0; first+i < n; ++i) find->x += STB_TEXTEDIT_GETWIDTH(str, first, i); } #define STB_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end) // make the selection/cursor state valid if client altered the string static void stb_textedit_clamp(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) { int n = STB_TEXTEDIT_STRINGLEN(str); if (STB_TEXT_HAS_SELECTION(state)) { if (state->select_start > n) state->select_start = n; if (state->select_end > n) state->select_end = n; // if clamping forced them to be equal, move the cursor to match if (state->select_start == state->select_end) state->cursor = state->select_start; } if (state->cursor > n) state->cursor = n; } // delete characters while updating undo static void stb_textedit_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int len) { stb_text_makeundo_delete(str, state, where, len); STB_TEXTEDIT_DELETECHARS(str, where, len); state->has_preferred_x = 0; } // delete the section static void stb_textedit_delete_selection(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) { stb_textedit_clamp(str, state); if (STB_TEXT_HAS_SELECTION(state)) { if (state->select_start < state->select_end) { stb_textedit_delete(str, state, state->select_start, state->select_end - state->select_start); state->select_end = state->cursor = state->select_start; } else { stb_textedit_delete(str, state, state->select_end, state->select_start - state->select_end); state->select_start = state->cursor = state->select_end; } state->has_preferred_x = 0; } } // canoncialize the selection so start <= end static void stb_textedit_sortselection(STB_TexteditState *state) { if (state->select_end < state->select_start) { int temp = state->select_end; state->select_end = state->select_start; state->select_start = temp; } } // move cursor to first character of selection static void stb_textedit_move_to_first(STB_TexteditState *state) { if (STB_TEXT_HAS_SELECTION(state)) { stb_textedit_sortselection(state); state->cursor = state->select_start; state->select_end = state->select_start; state->has_preferred_x = 0; } } // move cursor to last character of selection static void stb_textedit_move_to_last(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) { if (STB_TEXT_HAS_SELECTION(state)) { stb_textedit_sortselection(state); stb_textedit_clamp(str, state); state->cursor = state->select_end; state->select_start = state->select_end; state->has_preferred_x = 0; } } #ifdef STB_TEXTEDIT_IS_SPACE static int is_word_boundary( IMSTB_TEXTEDIT_STRING *str, int idx ) { return idx > 0 ? (STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str,idx-1) ) && !STB_TEXTEDIT_IS_SPACE( STB_TEXTEDIT_GETCHAR(str, idx) ) ) : 1; } #ifndef STB_TEXTEDIT_MOVEWORDLEFT static int stb_textedit_move_to_word_previous( IMSTB_TEXTEDIT_STRING *str, int c ) { --c; // always move at least one character while( c >= 0 && !is_word_boundary( str, c ) ) --c; if( c < 0 ) c = 0; return c; } #define STB_TEXTEDIT_MOVEWORDLEFT stb_textedit_move_to_word_previous #endif #ifndef STB_TEXTEDIT_MOVEWORDRIGHT static int stb_textedit_move_to_word_next( IMSTB_TEXTEDIT_STRING *str, int c ) { const int len = STB_TEXTEDIT_STRINGLEN(str); ++c; // always move at least one character while( c < len && !is_word_boundary( str, c ) ) ++c; if( c > len ) c = len; return c; } #define STB_TEXTEDIT_MOVEWORDRIGHT stb_textedit_move_to_word_next #endif #endif // update selection and cursor to match each other static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state) { if (!STB_TEXT_HAS_SELECTION(state)) state->select_start = state->select_end = state->cursor; else state->cursor = state->select_end; } // API cut: delete selection static int stb_textedit_cut(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) { if (STB_TEXT_HAS_SELECTION(state)) { stb_textedit_delete_selection(str,state); // implicitly clamps state->has_preferred_x = 0; return 1; } return 0; } // API paste: replace existing selection with passed-in text static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE *text, int len) { // if there's a selection, the paste should delete it stb_textedit_clamp(str, state); stb_textedit_delete_selection(str,state); // try to insert the characters if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) { stb_text_makeundo_insert(state, state->cursor, len); state->cursor += len; state->has_preferred_x = 0; return 1; } // note: paste failure will leave deleted selection, may be restored with an undo (see https://github.com/nothings/stb/issues/734 for details) return 0; } #ifndef STB_TEXTEDIT_KEYTYPE #define STB_TEXTEDIT_KEYTYPE int #endif // API key: process a keyboard input static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key) { retry: switch (key) { default: { int c = STB_TEXTEDIT_KEYTOTEXT(key); if (c > 0) { IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE) c; // can't add newline in single-line mode if (c == '\n' && state->single_line) break; if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) { stb_text_makeundo_replace(str, state, state->cursor, 1, 1); STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1); if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) { ++state->cursor; state->has_preferred_x = 0; } } else { stb_textedit_delete_selection(str,state); // implicitly clamps if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) { stb_text_makeundo_insert(state, state->cursor, 1); ++state->cursor; state->has_preferred_x = 0; } } } break; } #ifdef STB_TEXTEDIT_K_INSERT case STB_TEXTEDIT_K_INSERT: state->insert_mode = !state->insert_mode; break; #endif case STB_TEXTEDIT_K_UNDO: stb_text_undo(str, state); state->has_preferred_x = 0; break; case STB_TEXTEDIT_K_REDO: stb_text_redo(str, state); state->has_preferred_x = 0; break; case STB_TEXTEDIT_K_LEFT: // if currently there's a selection, move cursor to start of selection if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_first(state); else if (state->cursor > 0) --state->cursor; state->has_preferred_x = 0; break; case STB_TEXTEDIT_K_RIGHT: // if currently there's a selection, move cursor to end of selection if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_last(str, state); else ++state->cursor; stb_textedit_clamp(str, state); state->has_preferred_x = 0; break; case STB_TEXTEDIT_K_LEFT | STB_TEXTEDIT_K_SHIFT: stb_textedit_clamp(str, state); stb_textedit_prep_selection_at_cursor(state); // move selection left if (state->select_end > 0) --state->select_end; state->cursor = state->select_end; state->has_preferred_x = 0; break; #ifdef STB_TEXTEDIT_MOVEWORDLEFT case STB_TEXTEDIT_K_WORDLEFT: if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_first(state); else { state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); stb_textedit_clamp( str, state ); } break; case STB_TEXTEDIT_K_WORDLEFT | STB_TEXTEDIT_K_SHIFT: if( !STB_TEXT_HAS_SELECTION( state ) ) stb_textedit_prep_selection_at_cursor(state); state->cursor = STB_TEXTEDIT_MOVEWORDLEFT(str, state->cursor); state->select_end = state->cursor; stb_textedit_clamp( str, state ); break; #endif #ifdef STB_TEXTEDIT_MOVEWORDRIGHT case STB_TEXTEDIT_K_WORDRIGHT: if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_last(str, state); else { state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); stb_textedit_clamp( str, state ); } break; case STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT: if( !STB_TEXT_HAS_SELECTION( state ) ) stb_textedit_prep_selection_at_cursor(state); state->cursor = STB_TEXTEDIT_MOVEWORDRIGHT(str, state->cursor); state->select_end = state->cursor; stb_textedit_clamp( str, state ); break; #endif case STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT: stb_textedit_prep_selection_at_cursor(state); // move selection right ++state->select_end; stb_textedit_clamp(str, state); state->cursor = state->select_end; state->has_preferred_x = 0; break; case STB_TEXTEDIT_K_DOWN: case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: case STB_TEXTEDIT_K_PGDOWN: case STB_TEXTEDIT_K_PGDOWN | STB_TEXTEDIT_K_SHIFT: { StbFindState find; StbTexteditRow row; int i, j, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGDOWN; int row_count = is_page ? state->row_count_per_page : 1; if (!is_page && state->single_line) { // on windows, up&down in single-line behave like left&right key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT); goto retry; } if (sel) stb_textedit_prep_selection_at_cursor(state); else if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_last(str, state); // compute current position of cursor point stb_textedit_clamp(str, state); stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); for (j = 0; j < row_count; ++j) { float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x; int start = find.first_char + find.length; if (find.length == 0) break; // [DEAR IMGUI] // going down while being on the last line shouldn't bring us to that line end if (STB_TEXTEDIT_GETCHAR(str, find.first_char + find.length - 1) != STB_TEXTEDIT_NEWLINE) break; // now find character position down a row state->cursor = start; STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); x = row.x0; for (i=0; i < row.num_chars; ++i) { float dx = STB_TEXTEDIT_GETWIDTH(str, start, i); #ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE) break; #endif x += dx; if (x > goal_x) break; ++state->cursor; } stb_textedit_clamp(str, state); state->has_preferred_x = 1; state->preferred_x = goal_x; if (sel) state->select_end = state->cursor; // go to next line find.first_char = find.first_char + find.length; find.length = row.num_chars; } break; } case STB_TEXTEDIT_K_UP: case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: case STB_TEXTEDIT_K_PGUP: case STB_TEXTEDIT_K_PGUP | STB_TEXTEDIT_K_SHIFT: { StbFindState find; StbTexteditRow row; int i, j, prev_scan, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0; int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGUP; int row_count = is_page ? state->row_count_per_page : 1; if (!is_page && state->single_line) { // on windows, up&down become left&right key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT); goto retry; } if (sel) stb_textedit_prep_selection_at_cursor(state); else if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_move_to_first(state); // compute current position of cursor point stb_textedit_clamp(str, state); stb_textedit_find_charpos(&find, str, state->cursor, state->single_line); for (j = 0; j < row_count; ++j) { float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x; // can only go up if there's a previous row if (find.prev_first == find.first_char) break; // now find character position up a row state->cursor = find.prev_first; STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor); x = row.x0; for (i=0; i < row.num_chars; ++i) { float dx = STB_TEXTEDIT_GETWIDTH(str, find.prev_first, i); #ifdef IMSTB_TEXTEDIT_GETWIDTH_NEWLINE if (dx == IMSTB_TEXTEDIT_GETWIDTH_NEWLINE) break; #endif x += dx; if (x > goal_x) break; ++state->cursor; } stb_textedit_clamp(str, state); state->has_preferred_x = 1; state->preferred_x = goal_x; if (sel) state->select_end = state->cursor; // go to previous line // (we need to scan previous line the hard way. maybe we could expose this as a new API function?) prev_scan = find.prev_first > 0 ? find.prev_first - 1 : 0; while (prev_scan > 0 && STB_TEXTEDIT_GETCHAR(str, prev_scan - 1) != STB_TEXTEDIT_NEWLINE) --prev_scan; find.first_char = find.prev_first; find.prev_first = prev_scan; } break; } case STB_TEXTEDIT_K_DELETE: case STB_TEXTEDIT_K_DELETE | STB_TEXTEDIT_K_SHIFT: if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_delete_selection(str, state); else { int n = STB_TEXTEDIT_STRINGLEN(str); if (state->cursor < n) stb_textedit_delete(str, state, state->cursor, 1); } state->has_preferred_x = 0; break; case STB_TEXTEDIT_K_BACKSPACE: case STB_TEXTEDIT_K_BACKSPACE | STB_TEXTEDIT_K_SHIFT: if (STB_TEXT_HAS_SELECTION(state)) stb_textedit_delete_selection(str, state); else { stb_textedit_clamp(str, state); if (state->cursor > 0) { stb_textedit_delete(str, state, state->cursor-1, 1); --state->cursor; } } state->has_preferred_x = 0; break; #ifdef STB_TEXTEDIT_K_TEXTSTART2 case STB_TEXTEDIT_K_TEXTSTART2: #endif case STB_TEXTEDIT_K_TEXTSTART: state->cursor = state->select_start = state->select_end = 0; state->has_preferred_x = 0; break; #ifdef STB_TEXTEDIT_K_TEXTEND2 case STB_TEXTEDIT_K_TEXTEND2: #endif case STB_TEXTEDIT_K_TEXTEND: state->cursor = STB_TEXTEDIT_STRINGLEN(str); state->select_start = state->select_end = 0; state->has_preferred_x = 0; break; #ifdef STB_TEXTEDIT_K_TEXTSTART2 case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT: #endif case STB_TEXTEDIT_K_TEXTSTART | STB_TEXTEDIT_K_SHIFT: stb_textedit_prep_selection_at_cursor(state); state->cursor = state->select_end = 0; state->has_preferred_x = 0; break; #ifdef STB_TEXTEDIT_K_TEXTEND2 case STB_TEXTEDIT_K_TEXTEND2 | STB_TEXTEDIT_K_SHIFT: #endif case STB_TEXTEDIT_K_TEXTEND | STB_TEXTEDIT_K_SHIFT: stb_textedit_prep_selection_at_cursor(state); state->cursor = state->select_end = STB_TEXTEDIT_STRINGLEN(str); state->has_preferred_x = 0; break; #ifdef STB_TEXTEDIT_K_LINESTART2 case STB_TEXTEDIT_K_LINESTART2: #endif case STB_TEXTEDIT_K_LINESTART: stb_textedit_clamp(str, state); stb_textedit_move_to_first(state); if (state->single_line) state->cursor = 0; else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE) --state->cursor; state->has_preferred_x = 0; break; #ifdef STB_TEXTEDIT_K_LINEEND2 case STB_TEXTEDIT_K_LINEEND2: #endif case STB_TEXTEDIT_K_LINEEND: { int n = STB_TEXTEDIT_STRINGLEN(str); stb_textedit_clamp(str, state); stb_textedit_move_to_first(state); if (state->single_line) state->cursor = n; else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) ++state->cursor; state->has_preferred_x = 0; break; } #ifdef STB_TEXTEDIT_K_LINESTART2 case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT: #endif case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT: stb_textedit_clamp(str, state); stb_textedit_prep_selection_at_cursor(state); if (state->single_line) state->cursor = 0; else while (state->cursor > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) != STB_TEXTEDIT_NEWLINE) --state->cursor; state->select_end = state->cursor; state->has_preferred_x = 0; break; #ifdef STB_TEXTEDIT_K_LINEEND2 case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT: #endif case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: { int n = STB_TEXTEDIT_STRINGLEN(str); stb_textedit_clamp(str, state); stb_textedit_prep_selection_at_cursor(state); if (state->single_line) state->cursor = n; else while (state->cursor < n && STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) ++state->cursor; state->select_end = state->cursor; state->has_preferred_x = 0; break; } } } ///////////////////////////////////////////////////////////////////////////// // // Undo processing // // @OPTIMIZE: the undo/redo buffer should be circular static void stb_textedit_flush_redo(StbUndoState *state) { state->redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT; state->redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT; } // discard the oldest entry in the undo list static void stb_textedit_discard_undo(StbUndoState *state) { if (state->undo_point > 0) { // if the 0th undo state has characters, clean those up if (state->undo_rec[0].char_storage >= 0) { int n = state->undo_rec[0].insert_length, i; // delete n characters from all other records state->undo_char_point -= n; IMSTB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(IMSTB_TEXTEDIT_CHARTYPE))); for (i=0; i < state->undo_point; ++i) if (state->undo_rec[i].char_storage >= 0) state->undo_rec[i].char_storage -= n; // @OPTIMIZE: get rid of char_storage and infer it } --state->undo_point; IMSTB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0]))); } } // discard the oldest entry in the redo list--it's bad if this // ever happens, but because undo & redo have to store the actual // characters in different cases, the redo character buffer can // fill up even though the undo buffer didn't static void stb_textedit_discard_redo(StbUndoState *state) { int k = IMSTB_TEXTEDIT_UNDOSTATECOUNT-1; if (state->redo_point <= k) { // if the k'th undo state has characters, clean those up if (state->undo_rec[k].char_storage >= 0) { int n = state->undo_rec[k].insert_length, i; // move the remaining redo character data to the end of the buffer state->redo_char_point += n; IMSTB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((IMSTB_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point)*sizeof(IMSTB_TEXTEDIT_CHARTYPE))); // adjust the position of all the other records to account for above memmove for (i=state->redo_point; i < k; ++i) if (state->undo_rec[i].char_storage >= 0) state->undo_rec[i].char_storage += n; } // now move all the redo records towards the end of the buffer; the first one is at 'redo_point' // [DEAR IMGUI] size_t move_size = (size_t)((IMSTB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0])); const char* buf_begin = (char*)state->undo_rec; (void)buf_begin; const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end; IM_ASSERT(((char*)(state->undo_rec + state->redo_point)) >= buf_begin); IM_ASSERT(((char*)(state->undo_rec + state->redo_point + 1) + move_size) <= buf_end); IMSTB_TEXTEDIT_memmove(state->undo_rec + state->redo_point+1, state->undo_rec + state->redo_point, move_size); // now move redo_point to point to the new one ++state->redo_point; } } static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numchars) { // any time we create a new undo record, we discard redo stb_textedit_flush_redo(state); // if we have no free records, we have to make room, by sliding the // existing records down if (state->undo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT) stb_textedit_discard_undo(state); // if the characters to store won't possibly fit in the buffer, we can't undo if (numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT) { state->undo_point = 0; state->undo_char_point = 0; return NULL; } // if we don't have enough free characters in the buffer, we have to make room while (state->undo_char_point + numchars > IMSTB_TEXTEDIT_UNDOCHARCOUNT) stb_textedit_discard_undo(state); return &state->undo_rec[state->undo_point++]; } static IMSTB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, int pos, int insert_len, int delete_len) { StbUndoRecord *r = stb_text_create_undo_record(state, insert_len); if (r == NULL) return NULL; r->where = pos; r->insert_length = (IMSTB_TEXTEDIT_POSITIONTYPE) insert_len; r->delete_length = (IMSTB_TEXTEDIT_POSITIONTYPE) delete_len; if (insert_len == 0) { r->char_storage = -1; return NULL; } else { r->char_storage = state->undo_char_point; state->undo_char_point += insert_len; return &state->undo_char[r->char_storage]; } } static void stb_text_undo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) { StbUndoState *s = &state->undostate; StbUndoRecord u, *r; if (s->undo_point == 0) return; // we need to do two things: apply the undo record, and create a redo record u = s->undo_rec[s->undo_point-1]; r = &s->undo_rec[s->redo_point-1]; r->char_storage = -1; r->insert_length = u.delete_length; r->delete_length = u.insert_length; r->where = u.where; if (u.delete_length) { // if the undo record says to delete characters, then the redo record will // need to re-insert the characters that get deleted, so we need to store // them. // there are three cases: // there's enough room to store the characters // characters stored for *redoing* don't leave room for redo // characters stored for *undoing* don't leave room for redo // if the last is true, we have to bail if (s->undo_char_point + u.delete_length >= IMSTB_TEXTEDIT_UNDOCHARCOUNT) { // the undo records take up too much character space; there's no space to store the redo characters r->insert_length = 0; } else { int i; // there's definitely room to store the characters eventually while (s->undo_char_point + u.delete_length > s->redo_char_point) { // should never happen: if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT) return; // there's currently not enough room, so discard a redo record stb_textedit_discard_redo(s); } r = &s->undo_rec[s->redo_point-1]; r->char_storage = s->redo_char_point - u.delete_length; s->redo_char_point = s->redo_char_point - u.delete_length; // now save the characters for (i=0; i < u.delete_length; ++i) s->undo_char[r->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u.where + i); } // now we can carry out the deletion STB_TEXTEDIT_DELETECHARS(str, u.where, u.delete_length); } // check type of recorded action: if (u.insert_length) { // easy case: was a deletion, so we need to insert n characters STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length); s->undo_char_point -= u.insert_length; } state->cursor = u.where + u.insert_length; s->undo_point--; s->redo_point--; } static void stb_text_redo(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state) { StbUndoState *s = &state->undostate; StbUndoRecord *u, r; if (s->redo_point == IMSTB_TEXTEDIT_UNDOSTATECOUNT) return; // we need to do two things: apply the redo record, and create an undo record u = &s->undo_rec[s->undo_point]; r = s->undo_rec[s->redo_point]; // we KNOW there must be room for the undo record, because the redo record // was derived from an undo record u->delete_length = r.insert_length; u->insert_length = r.delete_length; u->where = r.where; u->char_storage = -1; if (r.delete_length) { // the redo record requires us to delete characters, so the undo record // needs to store the characters if (s->undo_char_point + u->insert_length > s->redo_char_point) { u->insert_length = 0; u->delete_length = 0; } else { int i; u->char_storage = s->undo_char_point; s->undo_char_point = s->undo_char_point + u->insert_length; // now save the characters for (i=0; i < u->insert_length; ++i) s->undo_char[u->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u->where + i); } STB_TEXTEDIT_DELETECHARS(str, r.where, r.delete_length); } if (r.insert_length) { // easy case: need to insert n characters STB_TEXTEDIT_INSERTCHARS(str, r.where, &s->undo_char[r.char_storage], r.insert_length); s->redo_char_point += r.insert_length; } state->cursor = r.where + r.insert_length; s->undo_point++; s->redo_point++; } static void stb_text_makeundo_insert(STB_TexteditState *state, int where, int length) { stb_text_createundo(&state->undostate, where, 0, length); } static void stb_text_makeundo_delete(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int length) { int i; IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, length, 0); if (p) { for (i=0; i < length; ++i) p[i] = STB_TEXTEDIT_GETCHAR(str, where+i); } } static void stb_text_makeundo_replace(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, int where, int old_length, int new_length) { int i; IMSTB_TEXTEDIT_CHARTYPE *p = stb_text_createundo(&state->undostate, where, old_length, new_length); if (p) { for (i=0; i < old_length; ++i) p[i] = STB_TEXTEDIT_GETCHAR(str, where+i); } } // reset the state to default static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_line) { state->undostate.undo_point = 0; state->undostate.undo_char_point = 0; state->undostate.redo_point = IMSTB_TEXTEDIT_UNDOSTATECOUNT; state->undostate.redo_char_point = IMSTB_TEXTEDIT_UNDOCHARCOUNT; state->select_end = state->select_start = 0; state->cursor = 0; state->has_preferred_x = 0; state->preferred_x = 0; state->cursor_at_end_of_line = 0; state->initialized = 1; state->single_line = (unsigned char) is_single_line; state->insert_mode = 0; state->row_count_per_page = 0; } // API initialize static void stb_textedit_initialize_state(STB_TexteditState *state, int is_single_line) { stb_textedit_clear_state(state, is_single_line); } #if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" #endif static int stb_textedit_paste(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, IMSTB_TEXTEDIT_CHARTYPE const *ctext, int len) { return stb_textedit_paste_internal(str, state, (IMSTB_TEXTEDIT_CHARTYPE *) ctext, len); } #if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic pop #endif #endif//IMSTB_TEXTEDIT_IMPLEMENTATION /* ------------------------------------------------------------------------------ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ RenderKit-ospray-f2a61c2/apps/common/external/imgui/imstb_truetype.h000066400000000000000000006054741456566705700260060ustar00rootroot00000000000000// [DEAR IMGUI] // This is a slightly modified version of stb_truetype.h 1.26. // Mostly fixing for compiler and static analyzer warnings. // Grep for [DEAR IMGUI] to find the changes. // stb_truetype.h - v1.26 - public domain // authored from 2009-2021 by Sean Barrett / RAD Game Tools // // ======================================================================= // // NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES // // This library does no range checking of the offsets found in the file, // meaning an attacker can use it to read arbitrary memory. // // ======================================================================= // // This library processes TrueType files: // parse files // extract glyph metrics // extract glyph shapes // render glyphs to one-channel bitmaps with antialiasing (box filter) // render glyphs to one-channel SDF bitmaps (signed-distance field/function) // // Todo: // non-MS cmaps // crashproof on bad data // hinting? (no longer patented) // cleartype-style AA? // optimize: use simple memory allocator for intermediates // optimize: build edge-list directly from curves // optimize: rasterize directly from curves? // // ADDITIONAL CONTRIBUTORS // // Mikko Mononen: compound shape support, more cmap formats // Tor Andersson: kerning, subpixel rendering // Dougall Johnson: OpenType / Type 2 font handling // Daniel Ribeiro Maciel: basic GPOS-based kerning // // Misc other: // Ryan Gordon // Simon Glass // github:IntellectualKitty // Imanol Celaya // Daniel Ribeiro Maciel // // Bug/warning reports/fixes: // "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe // Cass Everitt Martins Mozeiko github:aloucks // stoiko (Haemimont Games) Cap Petschulat github:oyvindjam // Brian Hook Omar Cornut github:vassvik // Walter van Niftrik Ryan Griege // David Gow Peter LaValle // David Given Sergey Popov // Ivan-Assen Ivanov Giumo X. Clanjor // Anthony Pesch Higor Euripedes // Johan Duparc Thomas Fields // Hou Qiming Derek Vinyard // Rob Loach Cort Stratton // Kenney Phillis Jr. Brian Costabile // Ken Voskuil (kaesve) // // VERSION HISTORY // // 1.26 (2021-08-28) fix broken rasterizer // 1.25 (2021-07-11) many fixes // 1.24 (2020-02-05) fix warning // 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) // 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined // 1.21 (2019-02-25) fix warning // 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() // 1.19 (2018-02-11) GPOS kerning, STBTT_fmod // 1.18 (2018-01-29) add missing function // 1.17 (2017-07-23) make more arguments const; doc fix // 1.16 (2017-07-12) SDF support // 1.15 (2017-03-03) make more arguments const // 1.14 (2017-01-16) num-fonts-in-TTC function // 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts // 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual // 1.11 (2016-04-02) fix unused-variable warning // 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef // 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; // variant PackFontRanges to pack and render in separate phases; // fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); // fixed an assert() bug in the new rasterizer // replace assert() with STBTT_assert() in new rasterizer // // Full history can be found at the end of this file. // // LICENSE // // See end of file for license information. // // USAGE // // Include this file in whatever places need to refer to it. In ONE C/C++ // file, write: // #define STB_TRUETYPE_IMPLEMENTATION // before the #include of this file. This expands out the actual // implementation into that C/C++ file. // // To make the implementation private to the file that generates the implementation, // #define STBTT_STATIC // // Simple 3D API (don't ship this, but it's fine for tools and quick start) // stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture // stbtt_GetBakedQuad() -- compute quad to draw for a given char // // Improved 3D API (more shippable): // #include "stb_rect_pack.h" -- optional, but you really want it // stbtt_PackBegin() // stbtt_PackSetOversampling() -- for improved quality on small fonts // stbtt_PackFontRanges() -- pack and renders // stbtt_PackEnd() // stbtt_GetPackedQuad() // // "Load" a font file from a memory buffer (you have to keep the buffer loaded) // stbtt_InitFont() // stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections // stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections // // Render a unicode codepoint to a bitmap // stbtt_GetCodepointBitmap() -- allocates and returns a bitmap // stbtt_MakeCodepointBitmap() -- renders into bitmap you provide // stbtt_GetCodepointBitmapBox() -- how big the bitmap must be // // Character advance/positioning // stbtt_GetCodepointHMetrics() // stbtt_GetFontVMetrics() // stbtt_GetFontVMetricsOS2() // stbtt_GetCodepointKernAdvance() // // Starting with version 1.06, the rasterizer was replaced with a new, // faster and generally-more-precise rasterizer. The new rasterizer more // accurately measures pixel coverage for anti-aliasing, except in the case // where multiple shapes overlap, in which case it overestimates the AA pixel // coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If // this turns out to be a problem, you can re-enable the old rasterizer with // #define STBTT_RASTERIZER_VERSION 1 // which will incur about a 15% speed hit. // // ADDITIONAL DOCUMENTATION // // Immediately after this block comment are a series of sample programs. // // After the sample programs is the "header file" section. This section // includes documentation for each API function. // // Some important concepts to understand to use this library: // // Codepoint // Characters are defined by unicode codepoints, e.g. 65 is // uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is // the hiragana for "ma". // // Glyph // A visual character shape (every codepoint is rendered as // some glyph) // // Glyph index // A font-specific integer ID representing a glyph // // Baseline // Glyph shapes are defined relative to a baseline, which is the // bottom of uppercase characters. Characters extend both above // and below the baseline. // // Current Point // As you draw text to the screen, you keep track of a "current point" // which is the origin of each character. The current point's vertical // position is the baseline. Even "baked fonts" use this model. // // Vertical Font Metrics // The vertical qualities of the font, used to vertically position // and space the characters. See docs for stbtt_GetFontVMetrics. // // Font Size in Pixels or Points // The preferred interface for specifying font sizes in stb_truetype // is to specify how tall the font's vertical extent should be in pixels. // If that sounds good enough, skip the next paragraph. // // Most font APIs instead use "points", which are a common typographic // measurement for describing font size, defined as 72 points per inch. // stb_truetype provides a point API for compatibility. However, true // "per inch" conventions don't make much sense on computer displays // since different monitors have different number of pixels per // inch. For example, Windows traditionally uses a convention that // there are 96 pixels per inch, thus making 'inch' measurements have // nothing to do with inches, and thus effectively defining a point to // be 1.333 pixels. Additionally, the TrueType font data provides // an explicit scale factor to scale a given font's glyphs to points, // but the author has observed that this scale factor is often wrong // for non-commercial fonts, thus making fonts scaled in points // according to the TrueType spec incoherently sized in practice. // // DETAILED USAGE: // // Scale: // Select how high you want the font to be, in points or pixels. // Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute // a scale factor SF that will be used by all other functions. // // Baseline: // You need to select a y-coordinate that is the baseline of where // your text will appear. Call GetFontBoundingBox to get the baseline-relative // bounding box for all characters. SF*-y0 will be the distance in pixels // that the worst-case character could extend above the baseline, so if // you want the top edge of characters to appear at the top of the // screen where y=0, then you would set the baseline to SF*-y0. // // Current point: // Set the current point where the first character will appear. The // first character could extend left of the current point; this is font // dependent. You can either choose a current point that is the leftmost // point and hope, or add some padding, or check the bounding box or // left-side-bearing of the first character to be displayed and set // the current point based on that. // // Displaying a character: // Compute the bounding box of the character. It will contain signed values // relative to . I.e. if it returns x0,y0,x1,y1, // then the character should be displayed in the rectangle from // to = 32 && *text < 128) { stbtt_aligned_quad q; stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);//1=opengl & d3d10+,0=d3d9 glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0); glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0); glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1); glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1); } ++text; } glEnd(); } #endif // // ////////////////////////////////////////////////////////////////////////////// // // Complete program (this compiles): get a single bitmap, print as ASCII art // #if 0 #include #define STB_TRUETYPE_IMPLEMENTATION // force following include to generate implementation #include "stb_truetype.h" char ttf_buffer[1<<25]; int main(int argc, char **argv) { stbtt_fontinfo font; unsigned char *bitmap; int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20); fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb")); stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0)); bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0); for (j=0; j < h; ++j) { for (i=0; i < w; ++i) putchar(" .:ioVM@"[bitmap[j*w+i]>>5]); putchar('\n'); } return 0; } #endif // // Output: // // .ii. // @@@@@@. // V@Mio@@o // :i. V@V // :oM@@M // :@@@MM@M // @@o o@M // :@@. M@M // @@@o@@@@ // :M@@V:@@. // ////////////////////////////////////////////////////////////////////////////// // // Complete program: print "Hello World!" banner, with bugs // #if 0 char buffer[24<<20]; unsigned char screen[20][79]; int main(int arg, char **argv) { stbtt_fontinfo font; int i,j,ascent,baseline,ch=0; float scale, xpos=2; // leave a little padding in case the character extends left char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); stbtt_InitFont(&font, buffer, 0); scale = stbtt_ScaleForPixelHeight(&font, 15); stbtt_GetFontVMetrics(&font, &ascent,0,0); baseline = (int) (ascent*scale); while (text[ch]) { int advance,lsb,x0,y0,x1,y1; float x_shift = xpos - (float) floor(xpos); stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb); stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1); stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]); // note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong // because this API is really for baking character bitmaps into textures. if you want to render // a sequence of characters, you really need to render each bitmap to a temp buffer, then // "alpha blend" that into the working buffer xpos += (advance * scale); if (text[ch+1]) xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]); ++ch; } for (j=0; j < 20; ++j) { for (i=0; i < 78; ++i) putchar(" .:ioVM@"[screen[j][i]>>5]); putchar('\n'); } return 0; } #endif ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// //// //// INTEGRATION WITH YOUR CODEBASE //// //// The following sections allow you to supply alternate definitions //// of C library functions used by stb_truetype, e.g. if you don't //// link with the C runtime library. #ifdef STB_TRUETYPE_IMPLEMENTATION // #define your own (u)stbtt_int8/16/32 before including to override this #ifndef stbtt_uint8 typedef unsigned char stbtt_uint8; typedef signed char stbtt_int8; typedef unsigned short stbtt_uint16; typedef signed short stbtt_int16; typedef unsigned int stbtt_uint32; typedef signed int stbtt_int32; #endif typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h #ifndef STBTT_ifloor #include #define STBTT_ifloor(x) ((int) floor(x)) #define STBTT_iceil(x) ((int) ceil(x)) #endif #ifndef STBTT_sqrt #include #define STBTT_sqrt(x) sqrt(x) #define STBTT_pow(x,y) pow(x,y) #endif #ifndef STBTT_fmod #include #define STBTT_fmod(x,y) fmod(x,y) #endif #ifndef STBTT_cos #include #define STBTT_cos(x) cos(x) #define STBTT_acos(x) acos(x) #endif #ifndef STBTT_fabs #include #define STBTT_fabs(x) fabs(x) #endif // #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h #ifndef STBTT_malloc #include #define STBTT_malloc(x,u) ((void)(u),malloc(x)) #define STBTT_free(x,u) ((void)(u),free(x)) #endif #ifndef STBTT_assert #include #define STBTT_assert(x) assert(x) #endif #ifndef STBTT_strlen #include #define STBTT_strlen(x) strlen(x) #endif #ifndef STBTT_memcpy #include #define STBTT_memcpy memcpy #define STBTT_memset memset #endif #endif /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// //// //// INTERFACE //// //// #ifndef __STB_INCLUDE_STB_TRUETYPE_H__ #define __STB_INCLUDE_STB_TRUETYPE_H__ #ifdef STBTT_STATIC #define STBTT_DEF static #else #define STBTT_DEF extern #endif #ifdef __cplusplus extern "C" { #endif // private structure typedef struct { unsigned char *data; int cursor; int size; } stbtt__buf; ////////////////////////////////////////////////////////////////////////////// // // TEXTURE BAKING API // // If you use this API, you only have to call two functions ever. // typedef struct { unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap float xoff,yoff,xadvance; } stbtt_bakedchar; STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) float pixel_height, // height of font in pixels unsigned char *pixels, int pw, int ph, // bitmap to be filled in int first_char, int num_chars, // characters to bake stbtt_bakedchar *chardata); // you allocate this, it's num_chars long // if return is positive, the first unused row of the bitmap // if return is negative, returns the negative of the number of characters that fit // if return is 0, no characters fit and no rows were used // This uses a very crappy packing. typedef struct { float x0,y0,s0,t0; // top-left float x1,y1,s1,t1; // bottom-right } stbtt_aligned_quad; STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above int char_index, // character to display float *xpos, float *ypos, // pointers to current position in screen pixel space stbtt_aligned_quad *q, // output: quad to draw int opengl_fillrule); // true if opengl fill rule; false if DX9 or earlier // Call GetBakedQuad with char_index = 'character - first_char', and it // creates the quad you need to draw and advances the current position. // // The coordinate system used assumes y increases downwards. // // Characters will extend both above and below the current position; // see discussion of "BASELINE" above. // // It's inefficient; you might want to c&p it and optimize it. STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap); // Query the font vertical metrics without having to create a font first. ////////////////////////////////////////////////////////////////////////////// // // NEW TEXTURE BAKING API // // This provides options for packing multiple fonts into one atlas, not // perfectly but better than nothing. typedef struct { unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap float xoff,yoff,xadvance; float xoff2,yoff2; } stbtt_packedchar; typedef struct stbtt_pack_context stbtt_pack_context; typedef struct stbtt_fontinfo stbtt_fontinfo; #ifndef STB_RECT_PACK_VERSION typedef struct stbrp_rect stbrp_rect; #endif STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); // Initializes a packing context stored in the passed-in stbtt_pack_context. // Future calls using this context will pack characters into the bitmap passed // in here: a 1-channel bitmap that is width * height. stride_in_bytes is // the distance from one row to the next (or 0 to mean they are packed tightly // together). "padding" is the amount of padding to leave between each // character (normally you want '1' for bitmaps you'll use as textures with // bilinear filtering). // // Returns 0 on failure, 1 on success. STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); // Cleans up the packing context and frees all memory. #define STBTT_POINT_SIZE(x) (-(x)) STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); // Creates character bitmaps from the font_index'th font found in fontdata (use // font_index=0 if you don't know what that is). It creates num_chars_in_range // bitmaps for characters with unicode values starting at first_unicode_char_in_range // and increasing. Data for how to render them is stored in chardata_for_range; // pass these to stbtt_GetPackedQuad to get back renderable quads. // // font_size is the full height of the character from ascender to descender, // as computed by stbtt_ScaleForPixelHeight. To use a point size as computed // by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() // and pass that result as 'font_size': // ..., 20 , ... // font max minus min y is 20 pixels tall // ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall typedef struct { float font_size; int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints int num_chars; stbtt_packedchar *chardata_for_range; // output unsigned char h_oversample, v_oversample; // don't set these, they're used internally } stbtt_pack_range; STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); // Creates character bitmaps from multiple ranges of characters stored in // ranges. This will usually create a better-packed bitmap than multiple // calls to stbtt_PackFontRange. Note that you can call this multiple // times within a single PackBegin/PackEnd. STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); // Oversampling a font increases the quality by allowing higher-quality subpixel // positioning, and is especially valuable at smaller text sizes. // // This function sets the amount of oversampling for all following calls to // stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given // pack context. The default (no oversampling) is achieved by h_oversample=1 // and v_oversample=1. The total number of pixels required is // h_oversample*v_oversample larger than the default; for example, 2x2 // oversampling requires 4x the storage of 1x1. For best results, render // oversampled textures with bilinear filtering. Look at the readme in // stb/tests/oversample for information about oversampled fonts // // To use with PackFontRangesGather etc., you must set it before calls // call to PackFontRangesGatherRects. STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip); // If skip != 0, this tells stb_truetype to skip any codepoints for which // there is no corresponding glyph. If skip=0, which is the default, then // codepoints without a glyph recived the font's "missing character" glyph, // typically an empty box by convention. STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above int char_index, // character to display float *xpos, float *ypos, // pointers to current position in screen pixel space stbtt_aligned_quad *q, // output: quad to draw int align_to_integer); STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); // Calling these functions in sequence is roughly equivalent to calling // stbtt_PackFontRanges(). If you more control over the packing of multiple // fonts, or if you want to pack custom data into a font texture, take a look // at the source to of stbtt_PackFontRanges() and create a custom version // using these functions, e.g. call GatherRects multiple times, // building up a single array of rects, then call PackRects once, // then call RenderIntoRects repeatedly. This may result in a // better packing than calling PackFontRanges multiple times // (or it may not). // this is an opaque structure that you shouldn't mess with which holds // all the context needed from PackBegin to PackEnd. struct stbtt_pack_context { void *user_allocator_context; void *pack_info; int width; int height; int stride_in_bytes; int padding; int skip_missing; unsigned int h_oversample, v_oversample; unsigned char *pixels; void *nodes; }; ////////////////////////////////////////////////////////////////////////////// // // FONT LOADING // // STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); // This function will determine the number of fonts in a font file. TrueType // collection (.ttc) files may contain multiple fonts, while TrueType font // (.ttf) files only contain one font. The number of fonts can be used for // indexing with the previous function where the index is between zero and one // less than the total fonts. If an error occurs, -1 is returned. STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); // Each .ttf/.ttc file may have more than one font. Each font has a sequential // index number starting from 0. Call this function to get the font offset for // a given index; it returns -1 if the index is out of range. A regular .ttf // file will only define one font and it always be at offset 0, so it will // return '0' for index 0, and -1 for all other indices. // The following structure is defined publicly so you can declare one on // the stack or as a global or etc, but you should treat it as opaque. struct stbtt_fontinfo { void * userdata; unsigned char * data; // pointer to .ttf file int fontstart; // offset of start of font int numGlyphs; // number of glyphs, needed for range checking int loca,head,glyf,hhea,hmtx,kern,gpos,svg; // table locations as offset from start of .ttf int index_map; // a cmap mapping for our chosen character encoding int indexToLocFormat; // format needed to map from glyph index to glyph stbtt__buf cff; // cff font data stbtt__buf charstrings; // the charstring index stbtt__buf gsubrs; // global charstring subroutines index stbtt__buf subrs; // private charstring subroutines index stbtt__buf fontdicts; // array of font dicts stbtt__buf fdselect; // map from glyph to fontdict }; STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); // Given an offset into the file that defines a font, this function builds // the necessary cached info for the rest of the system. You must allocate // the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't // need to do anything special to free it, because the contents are pure // value data with no additional data structures. Returns 0 on failure. ////////////////////////////////////////////////////////////////////////////// // // CHARACTER TO GLYPH-INDEX CONVERSIOn STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); // If you're going to perform multiple operations on the same character // and you want a speed-up, call this function with the character you're // going to process, then use glyph-based functions instead of the // codepoint-based functions. // Returns 0 if the character codepoint is not defined in the font. ////////////////////////////////////////////////////////////////////////////// // // CHARACTER PROPERTIES // STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); // computes a scale factor to produce a font whose "height" is 'pixels' tall. // Height is measured as the distance from the highest ascender to the lowest // descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics // and computing: // scale = pixels / (ascent - descent) // so if you prefer to measure height by the ascent only, use a similar calculation. STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); // computes a scale factor to produce a font whose EM size is mapped to // 'pixels' tall. This is probably what traditional APIs compute, but // I'm not positive. STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); // ascent is the coordinate above the baseline the font extends; descent // is the coordinate below the baseline the font extends (i.e. it is typically negative) // lineGap is the spacing between one row's descent and the next row's ascent... // so you should advance the vertical position by "*ascent - *descent + *lineGap" // these are expressed in unscaled coordinates, so you must multiply by // the scale factor for a given size STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); // analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 // table (specific to MS/Windows TTF files). // // Returns 1 on success (table present), 0 on failure. STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); // the bounding box around all possible characters STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); // leftSideBearing is the offset from the current horizontal position to the left edge of the character // advanceWidth is the offset from the current horizontal position to the next horizontal position // these are expressed in unscaled coordinates STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); // an additional amount to add to the 'advance' value between ch1 and ch2 STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); // Gets the bounding box of the visible part of the glyph, in unscaled coordinates STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); // as above, but takes one or more glyph indices for greater efficiency typedef struct stbtt_kerningentry { int glyph1; // use stbtt_FindGlyphIndex int glyph2; int advance; } stbtt_kerningentry; STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info); STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length); // Retrieves a complete list of all of the kerning pairs provided by the font // stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. // The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) ////////////////////////////////////////////////////////////////////////////// // // GLYPH SHAPES (you probably don't need these, but they have to go before // the bitmaps for C declaration-order reasons) // #ifndef STBTT_vmove // you can predefine these to use different values (but why?) enum { STBTT_vmove=1, STBTT_vline, STBTT_vcurve, STBTT_vcubic }; #endif #ifndef stbtt_vertex // you can predefine this to use different values // (we share this with other code at RAD) #define stbtt_vertex_type short // can't use stbtt_int16 because that's not visible in the header file typedef struct { stbtt_vertex_type x,y,cx,cy,cx1,cy1; unsigned char type,padding; } stbtt_vertex; #endif STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); // returns non-zero if nothing is drawn for this glyph STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); // returns # of vertices and fills *vertices with the pointer to them // these are expressed in "unscaled" coordinates // // The shape is a series of contours. Each one starts with // a STBTT_moveto, then consists of a series of mixed // STBTT_lineto and STBTT_curveto segments. A lineto // draws a line from previous endpoint to its x,y; a curveto // draws a quadratic bezier from previous endpoint to // its x,y, using cx,cy as the bezier control point. STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); // frees the data allocated above STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl); STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg); STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg); // fills svg with the character's SVG data. // returns data size or 0 if SVG not found. ////////////////////////////////////////////////////////////////////////////// // // BITMAP RENDERING // STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); // frees the bitmap allocated below STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); // allocates a large-enough single-channel 8bpp bitmap and renders the // specified character/glyph at the specified scale into it, with // antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). // *width & *height are filled out with the width & height of the bitmap, // which is stored left-to-right, top-to-bottom. // // xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff); // the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel // shift for the character STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); // the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap // in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap // is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the // width and height and positioning info for it first. STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint); // same as stbtt_MakeCodepointBitmap, but you can specify a subpixel // shift for the character STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint); // same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering // is performed (see stbtt_PackSetOversampling) STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); // get the bbox of the bitmap centered around the glyph origin; so the // bitmap width is ix1-ix0, height is iy1-iy0, and location to place // the bitmap top left is (leftSideBearing*scale,iy0). // (Note that the bitmap uses y-increases-down, but the shape uses // y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); // same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel // shift for the character // the following functions are equivalent to the above functions, but operate // on glyph indices instead of Unicode codepoints (for efficiency) STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); // @TODO: don't expose this structure typedef struct { int w,h,stride; unsigned char *pixels; } stbtt__bitmap; // rasterize a shape with quadratic beziers into a bitmap STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into float flatness_in_pixels, // allowable error of curve in pixels stbtt_vertex *vertices, // array of vertices defining shape int num_verts, // number of vertices in above array float scale_x, float scale_y, // scale applied to input vertices float shift_x, float shift_y, // translation applied to input vertices int x_off, int y_off, // another translation applied to input int invert, // if non-zero, vertically flip shape void *userdata); // context for to STBTT_MALLOC ////////////////////////////////////////////////////////////////////////////// // // Signed Distance Function (or Field) rendering STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); // frees the SDF bitmap allocated below STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); // These functions compute a discretized SDF field for a single character, suitable for storing // in a single-channel texture, sampling with bilinear filtering, and testing against // larger than some threshold to produce scalable fonts. // info -- the font // scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap // glyph/codepoint -- the character to generate the SDF for // padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), // which allows effects like bit outlines // onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) // pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) // if positive, > onedge_value is inside; if negative, < onedge_value is inside // width,height -- output height & width of the SDF bitmap (including padding) // xoff,yoff -- output origin of the character // return value -- a 2D array of bytes 0..255, width*height in size // // pixel_dist_scale & onedge_value are a scale & bias that allows you to make // optimal use of the limited 0..255 for your application, trading off precision // and special effects. SDF values outside the range 0..255 are clamped to 0..255. // // Example: // scale = stbtt_ScaleForPixelHeight(22) // padding = 5 // onedge_value = 180 // pixel_dist_scale = 180/5.0 = 36.0 // // This will create an SDF bitmap in which the character is about 22 pixels // high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled // shape, sample the SDF at each pixel and fill the pixel if the SDF value // is greater than or equal to 180/255. (You'll actually want to antialias, // which is beyond the scope of this example.) Additionally, you can compute // offset outlines (e.g. to stroke the character border inside & outside, // or only outside). For example, to fill outside the character up to 3 SDF // pixels, you would compare against (180-36.0*3)/255 = 72/255. The above // choice of variables maps a range from 5 pixels outside the shape to // 2 pixels inside the shape to 0..255; this is intended primarily for apply // outside effects only (the interior range is needed to allow proper // antialiasing of the font at *smaller* sizes) // // The function computes the SDF analytically at each SDF pixel, not by e.g. // building a higher-res bitmap and approximating it. In theory the quality // should be as high as possible for an SDF of this size & representation, but // unclear if this is true in practice (perhaps building a higher-res bitmap // and computing from that can allow drop-out prevention). // // The algorithm has not been optimized at all, so expect it to be slow // if computing lots of characters or very large sizes. ////////////////////////////////////////////////////////////////////////////// // // Finding the right font... // // You should really just solve this offline, keep your own tables // of what font is what, and don't try to get it out of the .ttf file. // That's because getting it out of the .ttf file is really hard, because // the names in the file can appear in many possible encodings, in many // possible languages, and e.g. if you need a case-insensitive comparison, // the details of that depend on the encoding & language in a complex way // (actually underspecified in truetype, but also gigantic). // // But you can use the provided functions in two possible ways: // stbtt_FindMatchingFont() will use *case-sensitive* comparisons on // unicode-encoded names to try to find the font you want; // you can run this before calling stbtt_InitFont() // // stbtt_GetFontNameString() lets you get any of the various strings // from the file yourself and do your own comparisons on them. // You have to have called stbtt_InitFont() first. STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); // returns the offset (not index) of the font that matches, or -1 if none // if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". // if you use any other flag, use a font name like "Arial"; this checks // the 'macStyle' header field; i don't know if fonts set this consistently #define STBTT_MACSTYLE_DONTCARE 0 #define STBTT_MACSTYLE_BOLD 1 #define STBTT_MACSTYLE_ITALIC 2 #define STBTT_MACSTYLE_UNDERSCORE 4 #define STBTT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); // returns 1/0 whether the first string interpreted as utf8 is identical to // the second string interpreted as big-endian utf16... useful for strings from next func STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); // returns the string (which may be big-endian double byte, e.g. for unicode) // and puts the length in bytes in *length. // // some of the values for the IDs are below; for more see the truetype spec: // http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html // http://www.microsoft.com/typography/otspec/name.htm enum { // platformID STBTT_PLATFORM_ID_UNICODE =0, STBTT_PLATFORM_ID_MAC =1, STBTT_PLATFORM_ID_ISO =2, STBTT_PLATFORM_ID_MICROSOFT =3 }; enum { // encodingID for STBTT_PLATFORM_ID_UNICODE STBTT_UNICODE_EID_UNICODE_1_0 =0, STBTT_UNICODE_EID_UNICODE_1_1 =1, STBTT_UNICODE_EID_ISO_10646 =2, STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, STBTT_UNICODE_EID_UNICODE_2_0_FULL=4 }; enum { // encodingID for STBTT_PLATFORM_ID_MICROSOFT STBTT_MS_EID_SYMBOL =0, STBTT_MS_EID_UNICODE_BMP =1, STBTT_MS_EID_SHIFTJIS =2, STBTT_MS_EID_UNICODE_FULL =10 }; enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7 }; enum { // languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... // problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410, STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411, STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D }; enum { // languageID for STBTT_PLATFORM_ID_MAC STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11, STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23, STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32, STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19 }; #ifdef __cplusplus } #endif #endif // __STB_INCLUDE_STB_TRUETYPE_H__ /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// //// //// IMPLEMENTATION //// //// #ifdef STB_TRUETYPE_IMPLEMENTATION #ifndef STBTT_MAX_OVERSAMPLE #define STBTT_MAX_OVERSAMPLE 8 #endif #if STBTT_MAX_OVERSAMPLE > 255 #error "STBTT_MAX_OVERSAMPLE cannot be > 255" #endif typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; #ifndef STBTT_RASTERIZER_VERSION #define STBTT_RASTERIZER_VERSION 2 #endif #ifdef _MSC_VER #define STBTT__NOTUSED(v) (void)(v) #else #define STBTT__NOTUSED(v) (void)sizeof(v) #endif ////////////////////////////////////////////////////////////////////////// // // stbtt__buf helpers to parse data from file // static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b) { if (b->cursor >= b->size) return 0; return b->data[b->cursor++]; } static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b) { if (b->cursor >= b->size) return 0; return b->data[b->cursor]; } static void stbtt__buf_seek(stbtt__buf *b, int o) { STBTT_assert(!(o > b->size || o < 0)); b->cursor = (o > b->size || o < 0) ? b->size : o; } static void stbtt__buf_skip(stbtt__buf *b, int o) { stbtt__buf_seek(b, b->cursor + o); } static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n) { stbtt_uint32 v = 0; int i; STBTT_assert(n >= 1 && n <= 4); for (i = 0; i < n; i++) v = (v << 8) | stbtt__buf_get8(b); return v; } static stbtt__buf stbtt__new_buf(const void *p, size_t size) { stbtt__buf r; STBTT_assert(size < 0x40000000); r.data = (stbtt_uint8*) p; r.size = (int) size; r.cursor = 0; return r; } #define stbtt__buf_get16(b) stbtt__buf_get((b), 2) #define stbtt__buf_get32(b) stbtt__buf_get((b), 4) static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s) { stbtt__buf r = stbtt__new_buf(NULL, 0); if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r; r.data = b->data + o; r.size = s; return r; } static stbtt__buf stbtt__cff_get_index(stbtt__buf *b) { int count, start, offsize; start = b->cursor; count = stbtt__buf_get16(b); if (count) { offsize = stbtt__buf_get8(b); STBTT_assert(offsize >= 1 && offsize <= 4); stbtt__buf_skip(b, offsize * count); stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1); } return stbtt__buf_range(b, start, b->cursor - start); } static stbtt_uint32 stbtt__cff_int(stbtt__buf *b) { int b0 = stbtt__buf_get8(b); if (b0 >= 32 && b0 <= 246) return b0 - 139; else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108; else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108; else if (b0 == 28) return stbtt__buf_get16(b); else if (b0 == 29) return stbtt__buf_get32(b); STBTT_assert(0); return 0; } static void stbtt__cff_skip_operand(stbtt__buf *b) { int v, b0 = stbtt__buf_peek8(b); STBTT_assert(b0 >= 28); if (b0 == 30) { stbtt__buf_skip(b, 1); while (b->cursor < b->size) { v = stbtt__buf_get8(b); if ((v & 0xF) == 0xF || (v >> 4) == 0xF) break; } } else { stbtt__cff_int(b); } } static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key) { stbtt__buf_seek(b, 0); while (b->cursor < b->size) { int start = b->cursor, end, op; while (stbtt__buf_peek8(b) >= 28) stbtt__cff_skip_operand(b); end = b->cursor; op = stbtt__buf_get8(b); if (op == 12) op = stbtt__buf_get8(b) | 0x100; if (op == key) return stbtt__buf_range(b, start, end-start); } return stbtt__buf_range(b, 0, 0); } static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out) { int i; stbtt__buf operands = stbtt__dict_get(b, key); for (i = 0; i < outcount && operands.cursor < operands.size; i++) out[i] = stbtt__cff_int(&operands); } static int stbtt__cff_index_count(stbtt__buf *b) { stbtt__buf_seek(b, 0); return stbtt__buf_get16(b); } static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) { int count, offsize, start, end; stbtt__buf_seek(&b, 0); count = stbtt__buf_get16(&b); offsize = stbtt__buf_get8(&b); STBTT_assert(i >= 0 && i < count); STBTT_assert(offsize >= 1 && offsize <= 4); stbtt__buf_skip(&b, i*offsize); start = stbtt__buf_get(&b, offsize); end = stbtt__buf_get(&b, offsize); return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start); } ////////////////////////////////////////////////////////////////////////// // // accessors to parse data from file // // on platforms that don't allow misaligned reads, if we want to allow // truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE #define ttBYTE(p) (* (stbtt_uint8 *) (p)) #define ttCHAR(p) (* (stbtt_int8 *) (p)) #define ttFixed(p) ttLONG(p) static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) #define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) static int stbtt__isfont(stbtt_uint8 *font) { // check the version number if (stbtt_tag4(font, '1',0,0,0)) return 1; // TrueType 1 if (stbtt_tag(font, "typ1")) return 1; // TrueType with type 1 font -- we don't support this! if (stbtt_tag(font, "OTTO")) return 1; // OpenType with CFF if (stbtt_tag4(font, 0,1,0,0)) return 1; // OpenType 1.0 if (stbtt_tag(font, "true")) return 1; // Apple specification for TrueType fonts return 0; } // @OPTIMIZE: binary search static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) { stbtt_int32 num_tables = ttUSHORT(data+fontstart+4); stbtt_uint32 tabledir = fontstart + 12; stbtt_int32 i; for (i=0; i < num_tables; ++i) { stbtt_uint32 loc = tabledir + 16*i; if (stbtt_tag(data+loc+0, tag)) return ttULONG(data+loc+8); } return 0; } static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index) { // if it's just a font, there's only one valid index if (stbtt__isfont(font_collection)) return index == 0 ? 0 : -1; // check if it's a TTC if (stbtt_tag(font_collection, "ttcf")) { // version 1? if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { stbtt_int32 n = ttLONG(font_collection+8); if (index >= n) return -1; return ttULONG(font_collection+12+index*4); } } return -1; } static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection) { // if it's just a font, there's only one valid font if (stbtt__isfont(font_collection)) return 1; // check if it's a TTC if (stbtt_tag(font_collection, "ttcf")) { // version 1? if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { return ttLONG(font_collection+8); } } return 0; } static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict) { stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 }; stbtt__buf pdict; stbtt__dict_get_ints(&fontdict, 18, 2, private_loc); if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0); pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]); stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); if (!subrsoff) return stbtt__new_buf(NULL, 0); stbtt__buf_seek(&cff, private_loc[1]+subrsoff); return stbtt__cff_get_index(&cff); } // since most people won't use this, find this table the first time it's needed static int stbtt__get_svg(stbtt_fontinfo *info) { stbtt_uint32 t; if (info->svg < 0) { t = stbtt__find_table(info->data, info->fontstart, "SVG "); if (t) { stbtt_uint32 offset = ttULONG(info->data + t + 2); info->svg = t + offset; } else { info->svg = 0; } } return info->svg; } static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) { stbtt_uint32 cmap, t; stbtt_int32 i,numTables; info->data = data; info->fontstart = fontstart; info->cff = stbtt__new_buf(NULL, 0); cmap = stbtt__find_table(data, fontstart, "cmap"); // required info->loca = stbtt__find_table(data, fontstart, "loca"); // required info->head = stbtt__find_table(data, fontstart, "head"); // required info->glyf = stbtt__find_table(data, fontstart, "glyf"); // required info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required info->kern = stbtt__find_table(data, fontstart, "kern"); // not required info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required if (!cmap || !info->head || !info->hhea || !info->hmtx) return 0; if (info->glyf) { // required for truetype if (!info->loca) return 0; } else { // initialization for CFF / Type2 fonts (OTF) stbtt__buf b, topdict, topdictidx; stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0; stbtt_uint32 cff; cff = stbtt__find_table(data, fontstart, "CFF "); if (!cff) return 0; info->fontdicts = stbtt__new_buf(NULL, 0); info->fdselect = stbtt__new_buf(NULL, 0); // @TODO this should use size from table (not 512MB) info->cff = stbtt__new_buf(data+cff, 512*1024*1024); b = info->cff; // read the header stbtt__buf_skip(&b, 2); stbtt__buf_seek(&b, stbtt__buf_get8(&b)); // hdrsize // @TODO the name INDEX could list multiple fonts, // but we just use the first one. stbtt__cff_get_index(&b); // name INDEX topdictidx = stbtt__cff_get_index(&b); topdict = stbtt__cff_index_get(topdictidx, 0); stbtt__cff_get_index(&b); // string INDEX info->gsubrs = stbtt__cff_get_index(&b); stbtt__dict_get_ints(&topdict, 17, 1, &charstrings); stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype); stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff); stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff); info->subrs = stbtt__get_subrs(b, topdict); // we only support Type 2 charstrings if (cstype != 2) return 0; if (charstrings == 0) return 0; if (fdarrayoff) { // looks like a CID font if (!fdselectoff) return 0; stbtt__buf_seek(&b, fdarrayoff); info->fontdicts = stbtt__cff_get_index(&b); info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff); } stbtt__buf_seek(&b, charstrings); info->charstrings = stbtt__cff_get_index(&b); } t = stbtt__find_table(data, fontstart, "maxp"); if (t) info->numGlyphs = ttUSHORT(data+t+4); else info->numGlyphs = 0xffff; info->svg = -1; // find a cmap encoding table we understand *now* to avoid searching // later. (todo: could make this installable) // the same regardless of glyph. numTables = ttUSHORT(data + cmap + 2); info->index_map = 0; for (i=0; i < numTables; ++i) { stbtt_uint32 encoding_record = cmap + 4 + 8 * i; // find an encoding we understand: switch(ttUSHORT(data+encoding_record)) { case STBTT_PLATFORM_ID_MICROSOFT: switch (ttUSHORT(data+encoding_record+2)) { case STBTT_MS_EID_UNICODE_BMP: case STBTT_MS_EID_UNICODE_FULL: // MS/Unicode info->index_map = cmap + ttULONG(data+encoding_record+4); break; } break; case STBTT_PLATFORM_ID_UNICODE: // Mac/iOS has these // all the encodingIDs are unicode, so we don't bother to check it info->index_map = cmap + ttULONG(data+encoding_record+4); break; } } if (info->index_map == 0) return 0; info->indexToLocFormat = ttUSHORT(data+info->head + 50); return 1; } STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) { stbtt_uint8 *data = info->data; stbtt_uint32 index_map = info->index_map; stbtt_uint16 format = ttUSHORT(data + index_map + 0); if (format == 0) { // apple byte encoding stbtt_int32 bytes = ttUSHORT(data + index_map + 2); if (unicode_codepoint < bytes-6) return ttBYTE(data + index_map + 6 + unicode_codepoint); return 0; } else if (format == 6) { stbtt_uint32 first = ttUSHORT(data + index_map + 6); stbtt_uint32 count = ttUSHORT(data + index_map + 8); if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count) return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2); return 0; } else if (format == 2) { STBTT_assert(0); // @TODO: high-byte mapping for japanese/chinese/korean return 0; } else if (format == 4) { // standard mapping for windows fonts: binary search collection of ranges stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1; stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; // do a binary search of the segments stbtt_uint32 endCount = index_map + 14; stbtt_uint32 search = endCount; if (unicode_codepoint > 0xffff) return 0; // they lie from endCount .. endCount + segCount // but searchRange is the nearest power of two, so... if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2)) search += rangeShift*2; // now decrement to bias correctly to find smallest search -= 2; while (entrySelector) { stbtt_uint16 end; searchRange >>= 1; end = ttUSHORT(data + search + searchRange*2); if (unicode_codepoint > end) search += searchRange*2; --entrySelector; } search += 2; { stbtt_uint16 offset, start, last; stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); last = ttUSHORT(data + endCount + 2*item); if (unicode_codepoint < start || unicode_codepoint > last) return 0; offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); if (offset == 0) return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); } } else if (format == 12 || format == 13) { stbtt_uint32 ngroups = ttULONG(data+index_map+12); stbtt_int32 low,high; low = 0; high = (stbtt_int32)ngroups; // Binary search the right group. while (low < high) { stbtt_int32 mid = low + ((high-low) >> 1); // rounds down, so low <= mid < high stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); if ((stbtt_uint32) unicode_codepoint < start_char) high = mid; else if ((stbtt_uint32) unicode_codepoint > end_char) low = mid+1; else { stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); if (format == 12) return start_glyph + unicode_codepoint-start_char; else // format == 13 return start_glyph; } } return 0; // not found } // @TODO STBTT_assert(0); return 0; } STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) { return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); } static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy) { v->type = type; v->x = (stbtt_int16) x; v->y = (stbtt_int16) y; v->cx = (stbtt_int16) cx; v->cy = (stbtt_int16) cy; } static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) { int g1,g2; STBTT_assert(!info->cff.size); if (glyph_index >= info->numGlyphs) return -1; // glyph index out of range if (info->indexToLocFormat >= 2) return -1; // unknown index->glyph map format if (info->indexToLocFormat == 0) { g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; } else { g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4); g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4); } return g1==g2 ? -1 : g1; // if length is 0, return -1 } static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) { if (info->cff.size) { stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); } else { int g = stbtt__GetGlyfOffset(info, glyph_index); if (g < 0) return 0; if (x0) *x0 = ttSHORT(info->data + g + 2); if (y0) *y0 = ttSHORT(info->data + g + 4); if (x1) *x1 = ttSHORT(info->data + g + 6); if (y1) *y1 = ttSHORT(info->data + g + 8); } return 1; } STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) { return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); } STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) { stbtt_int16 numberOfContours; int g; if (info->cff.size) return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0; g = stbtt__GetGlyfOffset(info, glyph_index); if (g < 0) return 1; numberOfContours = ttSHORT(info->data + g); return numberOfContours == 0; } static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) { if (start_off) { if (was_off) stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy); } else { if (was_off) stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy); else stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0); } return num_vertices; } static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) { stbtt_int16 numberOfContours; stbtt_uint8 *endPtsOfContours; stbtt_uint8 *data = info->data; stbtt_vertex *vertices=0; int num_vertices=0; int g = stbtt__GetGlyfOffset(info, glyph_index); *pvertices = NULL; if (g < 0) return 0; numberOfContours = ttSHORT(data + g); if (numberOfContours > 0) { stbtt_uint8 flags=0,flagcount; stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; stbtt_int32 x,y,cx,cy,sx,sy, scx,scy; stbtt_uint8 *points; endPtsOfContours = (data + g + 10); ins = ttUSHORT(data + g + 10 + numberOfContours * 2); points = data + g + 10 + numberOfContours * 2 + 2 + ins; n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); m = n + 2*numberOfContours; // a loose bound on how many vertices we might need vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); if (vertices == 0) return 0; next_move = 0; flagcount=0; // in first pass, we load uninterpreted data into the allocated array // above, shifted to the end of the array so we won't overwrite it when // we create our final data starting from the front off = m - n; // starting offset for uninterpreted data, regardless of how m ends up being calculated // first load flags for (i=0; i < n; ++i) { if (flagcount == 0) { flags = *points++; if (flags & 8) flagcount = *points++; } else --flagcount; vertices[off+i].type = flags; } // now load x coordinates x=0; for (i=0; i < n; ++i) { flags = vertices[off+i].type; if (flags & 2) { stbtt_int16 dx = *points++; x += (flags & 16) ? dx : -dx; // ??? } else { if (!(flags & 16)) { x = x + (stbtt_int16) (points[0]*256 + points[1]); points += 2; } } vertices[off+i].x = (stbtt_int16) x; } // now load y coordinates y=0; for (i=0; i < n; ++i) { flags = vertices[off+i].type; if (flags & 4) { stbtt_int16 dy = *points++; y += (flags & 32) ? dy : -dy; // ??? } else { if (!(flags & 32)) { y = y + (stbtt_int16) (points[0]*256 + points[1]); points += 2; } } vertices[off+i].y = (stbtt_int16) y; } // now convert them to our format num_vertices=0; sx = sy = cx = cy = scx = scy = 0; for (i=0; i < n; ++i) { flags = vertices[off+i].type; x = (stbtt_int16) vertices[off+i].x; y = (stbtt_int16) vertices[off+i].y; if (next_move == i) { if (i != 0) num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); // now start the new one start_off = !(flags & 1); if (start_off) { // if we start off with an off-curve point, then when we need to find a point on the curve // where we can start, and we need to save some state for when we wraparound. scx = x; scy = y; if (!(vertices[off+i+1].type & 1)) { // next point is also a curve point, so interpolate an on-point curve sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1; sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1; } else { // otherwise just use the next point as our start point sx = (stbtt_int32) vertices[off+i+1].x; sy = (stbtt_int32) vertices[off+i+1].y; ++i; // we're using point i+1 as the starting point, so skip it } } else { sx = x; sy = y; } stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0); was_off = 0; next_move = 1 + ttUSHORT(endPtsOfContours+j*2); ++j; } else { if (!(flags & 1)) { // if it's a curve if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); cx = x; cy = y; was_off = 1; } else { if (was_off) stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy); else stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0); was_off = 0; } } } num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); } else if (numberOfContours < 0) { // Compound shapes. int more = 1; stbtt_uint8 *comp = data + g + 10; num_vertices = 0; vertices = 0; while (more) { stbtt_uint16 flags, gidx; int comp_num_verts = 0, i; stbtt_vertex *comp_verts = 0, *tmp = 0; float mtx[6] = {1,0,0,1,0,0}, m, n; flags = ttSHORT(comp); comp+=2; gidx = ttSHORT(comp); comp+=2; if (flags & 2) { // XY values if (flags & 1) { // shorts mtx[4] = ttSHORT(comp); comp+=2; mtx[5] = ttSHORT(comp); comp+=2; } else { mtx[4] = ttCHAR(comp); comp+=1; mtx[5] = ttCHAR(comp); comp+=1; } } else { // @TODO handle matching point STBTT_assert(0); } if (flags & (1<<3)) { // WE_HAVE_A_SCALE mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; mtx[1] = mtx[2] = 0; } else if (flags & (1<<6)) { // WE_HAVE_AN_X_AND_YSCALE mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; mtx[1] = mtx[2] = 0; mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; } else if (flags & (1<<7)) { // WE_HAVE_A_TWO_BY_TWO mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; mtx[1] = ttSHORT(comp)/16384.0f; comp+=2; mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; } // Find transformation scales. m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); // Get indexed glyph. comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); if (comp_num_verts > 0) { // Transform vertices. for (i = 0; i < comp_num_verts; ++i) { stbtt_vertex* v = &comp_verts[i]; stbtt_vertex_type x,y; x=v->x; y=v->y; v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); x=v->cx; y=v->cy; v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); } // Append vertices. tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata); if (!tmp) { if (vertices) STBTT_free(vertices, info->userdata); if (comp_verts) STBTT_free(comp_verts, info->userdata); return 0; } if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); if (vertices) STBTT_free(vertices, info->userdata); vertices = tmp; STBTT_free(comp_verts, info->userdata); num_vertices += comp_num_verts; } // More components ? more = flags & (1<<5); } } else { // numberOfCounters == 0, do nothing } *pvertices = vertices; return num_vertices; } typedef struct { int bounds; int started; float first_x, first_y; float x, y; stbtt_int32 min_x, max_x, min_y, max_y; stbtt_vertex *pvertices; int num_vertices; } stbtt__csctx; #define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0} static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y) { if (x > c->max_x || !c->started) c->max_x = x; if (y > c->max_y || !c->started) c->max_y = y; if (x < c->min_x || !c->started) c->min_x = x; if (y < c->min_y || !c->started) c->min_y = y; c->started = 1; } static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) { if (c->bounds) { stbtt__track_vertex(c, x, y); if (type == STBTT_vcubic) { stbtt__track_vertex(c, cx, cy); stbtt__track_vertex(c, cx1, cy1); } } else { stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1; c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1; } c->num_vertices++; } static void stbtt__csctx_close_shape(stbtt__csctx *ctx) { if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); } static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) { stbtt__csctx_close_shape(ctx); ctx->first_x = ctx->x = ctx->x + dx; ctx->first_y = ctx->y = ctx->y + dy; stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); } static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy) { ctx->x += dx; ctx->y += dy; stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); } static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) { float cx1 = ctx->x + dx1; float cy1 = ctx->y + dy1; float cx2 = cx1 + dx2; float cy2 = cy1 + dy2; ctx->x = cx2 + dx3; ctx->y = cy2 + dy3; stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); } static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n) { int count = stbtt__cff_index_count(&idx); int bias = 107; if (count >= 33900) bias = 32768; else if (count >= 1240) bias = 1131; n += bias; if (n < 0 || n >= count) return stbtt__new_buf(NULL, 0); return stbtt__cff_index_get(idx, n); } static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index) { stbtt__buf fdselect = info->fdselect; int nranges, start, end, v, fmt, fdselector = -1, i; stbtt__buf_seek(&fdselect, 0); fmt = stbtt__buf_get8(&fdselect); if (fmt == 0) { // untested stbtt__buf_skip(&fdselect, glyph_index); fdselector = stbtt__buf_get8(&fdselect); } else if (fmt == 3) { nranges = stbtt__buf_get16(&fdselect); start = stbtt__buf_get16(&fdselect); for (i = 0; i < nranges; i++) { v = stbtt__buf_get8(&fdselect); end = stbtt__buf_get16(&fdselect); if (glyph_index >= start && glyph_index < end) { fdselector = v; break; } start = end; } } if (fdselector == -1) return stbtt__new_buf(NULL, 0); // [DEAR IMGUI] fixed, see #6007 and nothings/stb#1422 return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); } static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c) { int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0; int has_subrs = 0, clear_stack; float s[48]; stbtt__buf subr_stack[10], subrs = info->subrs, b; float f; #define STBTT__CSERR(s) (0) // this currently ignores the initial width value, which isn't needed if we have hmtx b = stbtt__cff_index_get(info->charstrings, glyph_index); while (b.cursor < b.size) { i = 0; clear_stack = 1; b0 = stbtt__buf_get8(&b); switch (b0) { // @TODO implement hinting case 0x13: // hintmask case 0x14: // cntrmask if (in_header) maskbits += (sp / 2); // implicit "vstem" in_header = 0; stbtt__buf_skip(&b, (maskbits + 7) / 8); break; case 0x01: // hstem case 0x03: // vstem case 0x12: // hstemhm case 0x17: // vstemhm maskbits += (sp / 2); break; case 0x15: // rmoveto in_header = 0; if (sp < 2) return STBTT__CSERR("rmoveto stack"); stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]); break; case 0x04: // vmoveto in_header = 0; if (sp < 1) return STBTT__CSERR("vmoveto stack"); stbtt__csctx_rmove_to(c, 0, s[sp-1]); break; case 0x16: // hmoveto in_header = 0; if (sp < 1) return STBTT__CSERR("hmoveto stack"); stbtt__csctx_rmove_to(c, s[sp-1], 0); break; case 0x05: // rlineto if (sp < 2) return STBTT__CSERR("rlineto stack"); for (; i + 1 < sp; i += 2) stbtt__csctx_rline_to(c, s[i], s[i+1]); break; // hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical // starting from a different place. case 0x07: // vlineto if (sp < 1) return STBTT__CSERR("vlineto stack"); goto vlineto; case 0x06: // hlineto if (sp < 1) return STBTT__CSERR("hlineto stack"); for (;;) { if (i >= sp) break; stbtt__csctx_rline_to(c, s[i], 0); i++; vlineto: if (i >= sp) break; stbtt__csctx_rline_to(c, 0, s[i]); i++; } break; case 0x1F: // hvcurveto if (sp < 4) return STBTT__CSERR("hvcurveto stack"); goto hvcurveto; case 0x1E: // vhcurveto if (sp < 4) return STBTT__CSERR("vhcurveto stack"); for (;;) { if (i + 3 >= sp) break; stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f); i += 4; hvcurveto: if (i + 3 >= sp) break; stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]); i += 4; } break; case 0x08: // rrcurveto if (sp < 6) return STBTT__CSERR("rcurveline stack"); for (; i + 5 < sp; i += 6) stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); break; case 0x18: // rcurveline if (sp < 8) return STBTT__CSERR("rcurveline stack"); for (; i + 5 < sp - 2; i += 6) stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); stbtt__csctx_rline_to(c, s[i], s[i+1]); break; case 0x19: // rlinecurve if (sp < 8) return STBTT__CSERR("rlinecurve stack"); for (; i + 1 < sp - 6; i += 2) stbtt__csctx_rline_to(c, s[i], s[i+1]); if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); break; case 0x1A: // vvcurveto case 0x1B: // hhcurveto if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack"); f = 0.0; if (sp & 1) { f = s[i]; i++; } for (; i + 3 < sp; i += 4) { if (b0 == 0x1B) stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0); else stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]); f = 0.0; } break; case 0x0A: // callsubr if (!has_subrs) { if (info->fdselect.size) subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); has_subrs = 1; } // FALLTHROUGH case 0x1D: // callgsubr if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); v = (int) s[--sp]; if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); subr_stack[subr_stack_height++] = b; b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v); if (b.size == 0) return STBTT__CSERR("subr not found"); b.cursor = 0; clear_stack = 0; break; case 0x0B: // return if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr"); b = subr_stack[--subr_stack_height]; clear_stack = 0; break; case 0x0E: // endchar stbtt__csctx_close_shape(c); return 1; case 0x0C: { // two-byte escape float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6; float dx, dy; int b1 = stbtt__buf_get8(&b); switch (b1) { // @TODO These "flex" implementations ignore the flex-depth and resolution, // and always draw beziers. case 0x22: // hflex if (sp < 7) return STBTT__CSERR("hflex stack"); dx1 = s[0]; dx2 = s[1]; dy2 = s[2]; dx3 = s[3]; dx4 = s[4]; dx5 = s[5]; dx6 = s[6]; stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0); stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0); break; case 0x23: // flex if (sp < 13) return STBTT__CSERR("flex stack"); dx1 = s[0]; dy1 = s[1]; dx2 = s[2]; dy2 = s[3]; dx3 = s[4]; dy3 = s[5]; dx4 = s[6]; dy4 = s[7]; dx5 = s[8]; dy5 = s[9]; dx6 = s[10]; dy6 = s[11]; //fd is s[12] stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); break; case 0x24: // hflex1 if (sp < 9) return STBTT__CSERR("hflex1 stack"); dx1 = s[0]; dy1 = s[1]; dx2 = s[2]; dy2 = s[3]; dx3 = s[4]; dx4 = s[5]; dx5 = s[6]; dy5 = s[7]; dx6 = s[8]; stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5)); break; case 0x25: // flex1 if (sp < 11) return STBTT__CSERR("flex1 stack"); dx1 = s[0]; dy1 = s[1]; dx2 = s[2]; dy2 = s[3]; dx3 = s[4]; dy3 = s[5]; dx4 = s[6]; dy4 = s[7]; dx5 = s[8]; dy5 = s[9]; dx6 = dy6 = s[10]; dx = dx1+dx2+dx3+dx4+dx5; dy = dy1+dy2+dy3+dy4+dy5; if (STBTT_fabs(dx) > STBTT_fabs(dy)) dy6 = -dy; else dx6 = -dx; stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); break; default: return STBTT__CSERR("unimplemented"); } } break; default: if (b0 != 255 && b0 != 28 && b0 < 32) return STBTT__CSERR("reserved operator"); // push immediate if (b0 == 255) { f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; } else { stbtt__buf_skip(&b, -1); f = (float)(stbtt_int16)stbtt__cff_int(&b); } if (sp >= 48) return STBTT__CSERR("push stack overflow"); s[sp++] = f; clear_stack = 0; break; } if (clear_stack) sp = 0; } return STBTT__CSERR("no endchar"); #undef STBTT__CSERR } static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) { // runs the charstring twice, once to count and once to output (to avoid realloc) stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1); stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); if (stbtt__run_charstring(info, glyph_index, &count_ctx)) { *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata); output_ctx.pvertices = *pvertices; if (stbtt__run_charstring(info, glyph_index, &output_ctx)) { STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices); return output_ctx.num_vertices; } } *pvertices = NULL; return 0; } static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) { stbtt__csctx c = STBTT__CSCTX_INIT(1); int r = stbtt__run_charstring(info, glyph_index, &c); if (x0) *x0 = r ? c.min_x : 0; if (y0) *y0 = r ? c.min_y : 0; if (x1) *x1 = r ? c.max_x : 0; if (y1) *y1 = r ? c.max_y : 0; return r ? c.num_vertices : 0; } STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) { if (!info->cff.size) return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices); else return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); } STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) { stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); if (glyph_index < numOfLongHorMetrics) { if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index); if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); } else { if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); } } STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info) { stbtt_uint8 *data = info->data + info->kern; // we only look at the first table. it must be 'horizontal' and format 0. if (!info->kern) return 0; if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 return 0; if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format return 0; return ttUSHORT(data+10); } STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length) { stbtt_uint8 *data = info->data + info->kern; int k, length; // we only look at the first table. it must be 'horizontal' and format 0. if (!info->kern) return 0; if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 return 0; if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format return 0; length = ttUSHORT(data+10); if (table_length < length) length = table_length; for (k = 0; k < length; k++) { table[k].glyph1 = ttUSHORT(data+18+(k*6)); table[k].glyph2 = ttUSHORT(data+20+(k*6)); table[k].advance = ttSHORT(data+22+(k*6)); } return length; } static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) { stbtt_uint8 *data = info->data + info->kern; stbtt_uint32 needle, straw; int l, r, m; // we only look at the first table. it must be 'horizontal' and format 0. if (!info->kern) return 0; if (ttUSHORT(data+2) < 1) // number of tables, need at least 1 return 0; if (ttUSHORT(data+8) != 1) // horizontal flag must be set in format return 0; l = 0; r = ttUSHORT(data+10) - 1; needle = glyph1 << 16 | glyph2; while (l <= r) { m = (l + r) >> 1; straw = ttULONG(data+18+(m*6)); // note: unaligned read if (needle < straw) r = m - 1; else if (needle > straw) l = m + 1; else return ttSHORT(data+22+(m*6)); } return 0; } static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) { stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); switch (coverageFormat) { case 1: { stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); // Binary search. stbtt_int32 l=0, r=glyphCount-1, m; int straw, needle=glyph; while (l <= r) { stbtt_uint8 *glyphArray = coverageTable + 4; stbtt_uint16 glyphID; m = (l + r) >> 1; glyphID = ttUSHORT(glyphArray + 2 * m); straw = glyphID; if (needle < straw) r = m - 1; else if (needle > straw) l = m + 1; else { return m; } } break; } case 2: { stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); stbtt_uint8 *rangeArray = coverageTable + 4; // Binary search. stbtt_int32 l=0, r=rangeCount-1, m; int strawStart, strawEnd, needle=glyph; while (l <= r) { stbtt_uint8 *rangeRecord; m = (l + r) >> 1; rangeRecord = rangeArray + 6 * m; strawStart = ttUSHORT(rangeRecord); strawEnd = ttUSHORT(rangeRecord + 2); if (needle < strawStart) r = m - 1; else if (needle > strawEnd) l = m + 1; else { stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); return startCoverageIndex + glyph - strawStart; } } break; } default: return -1; // unsupported } return -1; } static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) { stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); switch (classDefFormat) { case 1: { stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); stbtt_uint8 *classDef1ValueArray = classDefTable + 6; if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); break; } case 2: { stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); stbtt_uint8 *classRangeRecords = classDefTable + 4; // Binary search. stbtt_int32 l=0, r=classRangeCount-1, m; int strawStart, strawEnd, needle=glyph; while (l <= r) { stbtt_uint8 *classRangeRecord; m = (l + r) >> 1; classRangeRecord = classRangeRecords + 6 * m; strawStart = ttUSHORT(classRangeRecord); strawEnd = ttUSHORT(classRangeRecord + 2); if (needle < strawStart) r = m - 1; else if (needle > strawEnd) l = m + 1; else return (stbtt_int32)ttUSHORT(classRangeRecord + 4); } break; } default: return -1; // Unsupported definition type, return an error. } // "All glyphs not assigned to a class fall into class 0". (OpenType spec) return 0; } // Define to STBTT_assert(x) if you want to break on unimplemented formats. #define STBTT_GPOS_TODO_assert(x) static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) { stbtt_uint16 lookupListOffset; stbtt_uint8 *lookupList; stbtt_uint16 lookupCount; stbtt_uint8 *data; stbtt_int32 i, sti; if (!info->gpos) return 0; data = info->data + info->gpos; if (ttUSHORT(data+0) != 1) return 0; // Major version 1 if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 lookupListOffset = ttUSHORT(data+8); lookupList = data + lookupListOffset; lookupCount = ttUSHORT(lookupList); for (i=0; i= pairSetCount) return 0; needle=glyph2; r=pairValueCount-1; l=0; // Binary search. while (l <= r) { stbtt_uint16 secondGlyph; stbtt_uint8 *pairValue; m = (l + r) >> 1; pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; secondGlyph = ttUSHORT(pairValue); straw = secondGlyph; if (needle < straw) r = m - 1; else if (needle > straw) l = m + 1; else { stbtt_int16 xAdvance = ttSHORT(pairValue + 2); return xAdvance; } } } else return 0; break; } case 2: { stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); if (valueFormat1 == 4 && valueFormat2 == 0) { // Support more formats? stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); stbtt_uint16 class1Count = ttUSHORT(table + 12); stbtt_uint16 class2Count = ttUSHORT(table + 14); stbtt_uint8 *class1Records, *class2Records; stbtt_int16 xAdvance; if (glyph1class < 0 || glyph1class >= class1Count) return 0; // malformed if (glyph2class < 0 || glyph2class >= class2Count) return 0; // malformed class1Records = table + 16; class2Records = class1Records + 2 * (glyph1class * class2Count); xAdvance = ttSHORT(class2Records + 2 * glyph2class); return xAdvance; } else return 0; break; } default: return 0; // Unsupported position format } } } return 0; } STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) { int xAdvance = 0; if (info->gpos) xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); else if (info->kern) xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); return xAdvance; } STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) { if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs return 0; return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); } STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) { stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); } STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) { if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); if (descent) *descent = ttSHORT(info->data+info->hhea + 6); if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); } STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap) { int tab = stbtt__find_table(info->data, info->fontstart, "OS/2"); if (!tab) return 0; if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); return 1; } STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) { *x0 = ttSHORT(info->data + info->head + 36); *y0 = ttSHORT(info->data + info->head + 38); *x1 = ttSHORT(info->data + info->head + 40); *y1 = ttSHORT(info->data + info->head + 42); } STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) { int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); return (float) height / fheight; } STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) { int unitsPerEm = ttUSHORT(info->data + info->head + 18); return pixels / unitsPerEm; } STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) { STBTT_free(v, info->userdata); } STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl) { int i; stbtt_uint8 *data = info->data; stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info); int numEntries = ttUSHORT(svg_doc_list); stbtt_uint8 *svg_docs = svg_doc_list + 2; for(i=0; i= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2))) return svg_doc; } return 0; } STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg) { stbtt_uint8 *data = info->data; stbtt_uint8 *svg_doc; if (info->svg == 0) return 0; svg_doc = stbtt_FindSVGDoc(info, gl); if (svg_doc != NULL) { *svg = (char *) data + info->svg + ttULONG(svg_doc + 4); return ttULONG(svg_doc + 8); } else { return 0; } } STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg) { return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg); } ////////////////////////////////////////////////////////////////////////////// // // antialiasing software rasterizer // STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) { int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { // e.g. space character if (ix0) *ix0 = 0; if (iy0) *iy0 = 0; if (ix1) *ix1 = 0; if (iy1) *iy1 = 0; } else { // move to integral bboxes (treating pixels as little squares, what pixels get touched)? if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x); if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x); if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y); } } STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) { stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); } STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) { stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); } STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) { stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); } ////////////////////////////////////////////////////////////////////////////// // // Rasterizer typedef struct stbtt__hheap_chunk { struct stbtt__hheap_chunk *next; } stbtt__hheap_chunk; typedef struct stbtt__hheap { struct stbtt__hheap_chunk *head; void *first_free; int num_remaining_in_head_chunk; } stbtt__hheap; static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) { if (hh->first_free) { void *p = hh->first_free; hh->first_free = * (void **) p; return p; } else { if (hh->num_remaining_in_head_chunk == 0) { int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); if (c == NULL) return NULL; c->next = hh->head; hh->head = c; hh->num_remaining_in_head_chunk = count; } --hh->num_remaining_in_head_chunk; return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; } } static void stbtt__hheap_free(stbtt__hheap *hh, void *p) { *(void **) p = hh->first_free; hh->first_free = p; } static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) { stbtt__hheap_chunk *c = hh->head; while (c) { stbtt__hheap_chunk *n = c->next; STBTT_free(c, userdata); c = n; } } typedef struct stbtt__edge { float x0,y0, x1,y1; int invert; } stbtt__edge; typedef struct stbtt__active_edge { struct stbtt__active_edge *next; #if STBTT_RASTERIZER_VERSION==1 int x,dx; float ey; int direction; #elif STBTT_RASTERIZER_VERSION==2 float fx,fdx,fdy; float direction; float sy; float ey; #else #error "Unrecognized value of STBTT_RASTERIZER_VERSION" #endif } stbtt__active_edge; #if STBTT_RASTERIZER_VERSION == 1 #define STBTT_FIXSHIFT 10 #define STBTT_FIX (1 << STBTT_FIXSHIFT) #define STBTT_FIXMASK (STBTT_FIX-1) static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) { stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); STBTT_assert(z != NULL); if (!z) return z; // round dx down to avoid overshooting if (dxdy < 0) z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); else z->dx = STBTT_ifloor(STBTT_FIX * dxdy); z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount z->x -= off_x * STBTT_FIX; z->ey = e->y1; z->next = 0; z->direction = e->invert ? 1 : -1; return z; } #elif STBTT_RASTERIZER_VERSION == 2 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) { stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); STBTT_assert(z != NULL); //STBTT_assert(e->y0 <= start_point); if (!z) return z; z->fdx = dxdy; z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; z->fx = e->x0 + dxdy * (start_point - e->y0); z->fx -= off_x; z->direction = e->invert ? 1.0f : -1.0f; z->sy = e->y0; z->ey = e->y1; z->next = 0; return z; } #else #error "Unrecognized value of STBTT_RASTERIZER_VERSION" #endif #if STBTT_RASTERIZER_VERSION == 1 // note: this routine clips fills that extend off the edges... ideally this // wouldn't happen, but it could happen if the truetype glyph bounding boxes // are wrong, or if the user supplies a too-small bitmap static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight) { // non-zero winding fill int x0=0, w=0; while (e) { if (w == 0) { // if we're currently at zero, we need to record the edge start point x0 = e->x; w += e->direction; } else { int x1 = e->x; w += e->direction; // if we went to zero, we need to draw if (w == 0) { int i = x0 >> STBTT_FIXSHIFT; int j = x1 >> STBTT_FIXSHIFT; if (i < len && j >= 0) { if (i == j) { // x0,x1 are the same pixel, so compute combined coverage scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT); } else { if (i >= 0) // add antialiasing for x0 scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); else i = -1; // clip if (j < len) // add antialiasing for x1 scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); else j = len; // clip for (++i; i < j; ++i) // fill pixels between x0 and x1 scanline[i] = scanline[i] + (stbtt_uint8) max_weight; } } } } e = e->next; } } static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) { stbtt__hheap hh = { 0, 0, 0 }; stbtt__active_edge *active = NULL; int y,j=0; int max_weight = (255 / vsubsample); // weight per vertical scanline int s; // vertical subsample index unsigned char scanline_data[512], *scanline; if (result->w > 512) scanline = (unsigned char *) STBTT_malloc(result->w, userdata); else scanline = scanline_data; y = off_y * vsubsample; e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; while (j < result->h) { STBTT_memset(scanline, 0, result->w); for (s=0; s < vsubsample; ++s) { // find center of pixel for this scanline float scan_y = y + 0.5f; stbtt__active_edge **step = &active; // update all active edges; // remove all active edges that terminate before the center of this scanline while (*step) { stbtt__active_edge * z = *step; if (z->ey <= scan_y) { *step = z->next; // delete from list STBTT_assert(z->direction); z->direction = 0; stbtt__hheap_free(&hh, z); } else { z->x += z->dx; // advance to position for current scanline step = &((*step)->next); // advance through list } } // resort the list if needed for(;;) { int changed=0; step = &active; while (*step && (*step)->next) { if ((*step)->x > (*step)->next->x) { stbtt__active_edge *t = *step; stbtt__active_edge *q = t->next; t->next = q->next; q->next = t; *step = q; changed = 1; } step = &(*step)->next; } if (!changed) break; } // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline while (e->y0 <= scan_y) { if (e->y1 > scan_y) { stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); if (z != NULL) { // find insertion point if (active == NULL) active = z; else if (z->x < active->x) { // insert at front z->next = active; active = z; } else { // find thing to insert AFTER stbtt__active_edge *p = active; while (p->next && p->next->x < z->x) p = p->next; // at this point, p->next->x is NOT < z->x z->next = p->next; p->next = z; } } } ++e; } // now process all active edges in XOR fashion if (active) stbtt__fill_active_edges(scanline, result->w, active, max_weight); ++y; } STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); ++j; } stbtt__hheap_cleanup(&hh, userdata); if (scanline != scanline_data) STBTT_free(scanline, userdata); } #elif STBTT_RASTERIZER_VERSION == 2 // the edge passed in here does not cross the vertical line at x or the vertical line at x+1 // (i.e. it has already been clipped to those) static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1) { if (y0 == y1) return; STBTT_assert(y0 < y1); STBTT_assert(e->sy <= e->ey); if (y0 > e->ey) return; if (y1 < e->sy) return; if (y0 < e->sy) { x0 += (x1-x0) * (e->sy - y0) / (y1-y0); y0 = e->sy; } if (y1 > e->ey) { x1 += (x1-x0) * (e->ey - y1) / (y1-y0); y1 = e->ey; } if (x0 == x) STBTT_assert(x1 <= x+1); else if (x0 == x+1) STBTT_assert(x1 >= x); else if (x0 <= x) STBTT_assert(x1 <= x); else if (x0 >= x+1) STBTT_assert(x1 >= x+1); else STBTT_assert(x1 >= x && x1 <= x+1); if (x0 <= x && x1 <= x) scanline[x] += e->direction * (y1-y0); else if (x0 >= x+1 && x1 >= x+1) ; else { STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position } } static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width) { STBTT_assert(top_width >= 0); STBTT_assert(bottom_width >= 0); return (top_width + bottom_width) / 2.0f * height; } static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1) { return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0); } static float stbtt__sized_triangle_area(float height, float width) { return height * width / 2; } static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) { float y_bottom = y_top+1; while (e) { // brute force every pixel // compute intersection points with top & bottom STBTT_assert(e->ey >= y_top); if (e->fdx == 0) { float x0 = e->fx; if (x0 < len) { if (x0 >= 0) { stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); } else { stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); } } } else { float x0 = e->fx; float dx = e->fdx; float xb = x0 + dx; float x_top, x_bottom; float sy0,sy1; float dy = e->fdy; STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); // compute endpoints of line segment clipped to this scanline (if the // line segment starts on this scanline. x0 is the intersection of the // line with y_top, but that may be off the line segment. if (e->sy > y_top) { x_top = x0 + dx * (e->sy - y_top); sy0 = e->sy; } else { x_top = x0; sy0 = y_top; } if (e->ey < y_bottom) { x_bottom = x0 + dx * (e->ey - y_top); sy1 = e->ey; } else { x_bottom = xb; sy1 = y_bottom; } if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) { // from here on, we don't have to range check x values if ((int) x_top == (int) x_bottom) { float height; // simple case, only spans one pixel int x = (int) x_top; height = (sy1 - sy0) * e->direction; STBTT_assert(x >= 0 && x < len); scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f); scanline_fill[x] += height; // everything right of this pixel is filled } else { int x,x1,x2; float y_crossing, y_final, step, sign, area; // covers 2+ pixels if (x_top > x_bottom) { // flip scanline vertically; signed area is the same float t; sy0 = y_bottom - (sy0 - y_top); sy1 = y_bottom - (sy1 - y_top); t = sy0, sy0 = sy1, sy1 = t; t = x_bottom, x_bottom = x_top, x_top = t; dx = -dx; dy = -dy; t = x0, x0 = xb, xb = t; } STBTT_assert(dy >= 0); STBTT_assert(dx >= 0); x1 = (int) x_top; x2 = (int) x_bottom; // compute intersection with y axis at x1+1 y_crossing = y_top + dy * (x1+1 - x0); // compute intersection with y axis at x2 y_final = y_top + dy * (x2 - x0); // x1 x_top x2 x_bottom // y_top +------|-----+------------+------------+--------|---+------------+ // | | | | | | // | | | | | | // sy0 | Txxxxx|............|............|............|............| // y_crossing | *xxxxx.......|............|............|............| // | | xxxxx..|............|............|............| // | | /- xx*xxxx........|............|............| // | | dy < | xxxxxx..|............|............| // y_final | | \- | xx*xxx.........|............| // sy1 | | | | xxxxxB...|............| // | | | | | | // | | | | | | // y_bottom +------------+------------+------------+------------+------------+ // // goal is to measure the area covered by '.' in each pixel // if x2 is right at the right edge of x1, y_crossing can blow up, github #1057 // @TODO: maybe test against sy1 rather than y_bottom? if (y_crossing > y_bottom) y_crossing = y_bottom; sign = e->direction; // area of the rectangle covered from sy0..y_crossing area = sign * (y_crossing-sy0); // area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing) scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top); // check if final y_crossing is blown up; no test case for this if (y_final > y_bottom) { int denom = (x2 - (x1+1)); y_final = y_bottom; if (denom != 0) { // [DEAR IMGUI] Avoid div by zero (https://github.com/nothings/stb/issues/1316) dy = (y_final - y_crossing ) / denom; // if denom=0, y_final = y_crossing, so y_final <= y_bottom } } // in second pixel, area covered by line segment found in first pixel // is always a rectangle 1 wide * the height of that line segment; this // is exactly what the variable 'area' stores. it also gets a contribution // from the line segment within it. the THIRD pixel will get the first // pixel's rectangle contribution, the second pixel's rectangle contribution, // and its own contribution. the 'own contribution' is the same in every pixel except // the leftmost and rightmost, a trapezoid that slides down in each pixel. // the second pixel's contribution to the third pixel will be the // rectangle 1 wide times the height change in the second pixel, which is dy. step = sign * dy * 1; // dy is dy/dx, change in y for every 1 change in x, // which multiplied by 1-pixel-width is how much pixel area changes for each step in x // so the area advances by 'step' every time for (x = x1+1; x < x2; ++x) { scanline[x] += area + step/2; // area of trapezoid is 1*step/2 area += step; } STBTT_assert(STBTT_fabs(area) <= 1.01f); // accumulated error from area += step unless we round step down STBTT_assert(sy1 > y_final-0.01f); // area covered in the last pixel is the rectangle from all the pixels to the left, // plus the trapezoid filled by the line segment in this pixel all the way to the right edge scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f); // the rest of the line is filled based on the total height of the line segment in this pixel scanline_fill[x2] += sign * (sy1-sy0); } } else { // if edge goes outside of box we're drawing, we require // clipping logic. since this does not match the intended use // of this library, we use a different, very slow brute // force implementation // note though that this does happen some of the time because // x_top and x_bottom can be extrapolated at the top & bottom of // the shape and actually lie outside the bounding box int x; for (x=0; x < len; ++x) { // cases: // // there can be up to two intersections with the pixel. any intersection // with left or right edges can be handled by splitting into two (or three) // regions. intersections with top & bottom do not necessitate case-wise logic. // // the old way of doing this found the intersections with the left & right edges, // then used some simple logic to produce up to three segments in sorted order // from top-to-bottom. however, this had a problem: if an x edge was epsilon // across the x border, then the corresponding y position might not be distinct // from the other y segment, and it might ignored as an empty segment. to avoid // that, we need to explicitly produce segments based on x positions. // rename variables to clearly-defined pairs float y0 = y_top; float x1 = (float) (x); float x2 = (float) (x+1); float x3 = xb; float y3 = y_bottom; // x = e->x + e->dx * (y-y_top) // (y-y_top) = (x - e->x) / e->dx // y = (x - e->x) / e->dx + y_top float y1 = (x - x0) / dx + y_top; float y2 = (x+1 - x0) / dx + y_top; if (x0 < x1 && x3 > x2) { // three segments descending down-right stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2); stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); } else if (x3 < x1 && x0 > x2) { // three segments descending down-left stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1); stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); } else { // one segment stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3); } } } } e = e->next; } } // directly AA rasterize edges w/o supersampling static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) { stbtt__hheap hh = { 0, 0, 0 }; stbtt__active_edge *active = NULL; int y,j=0, i; float scanline_data[129], *scanline, *scanline2; STBTT__NOTUSED(vsubsample); if (result->w > 64) scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); else scanline = scanline_data; scanline2 = scanline + result->w; y = off_y; e[n].y0 = (float) (off_y + result->h) + 1; while (j < result->h) { // find center of pixel for this scanline float scan_y_top = y + 0.0f; float scan_y_bottom = y + 1.0f; stbtt__active_edge **step = &active; STBTT_memset(scanline , 0, result->w*sizeof(scanline[0])); STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0])); // update all active edges; // remove all active edges that terminate before the top of this scanline while (*step) { stbtt__active_edge * z = *step; if (z->ey <= scan_y_top) { *step = z->next; // delete from list STBTT_assert(z->direction); z->direction = 0; stbtt__hheap_free(&hh, z); } else { step = &((*step)->next); // advance through list } } // insert all edges that start before the bottom of this scanline while (e->y0 <= scan_y_bottom) { if (e->y0 != e->y1) { stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); if (z != NULL) { if (j == 0 && off_y != 0) { if (z->ey < scan_y_top) { // this can happen due to subpixel positioning and some kind of fp rounding error i think z->ey = scan_y_top; } } STBTT_assert(z->ey >= scan_y_top); // if we get really unlucky a tiny bit of an edge can be out of bounds // insert at front z->next = active; active = z; } } ++e; } // now process all active edges if (active) stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); { float sum = 0; for (i=0; i < result->w; ++i) { float k; int m; sum += scanline2[i]; k = scanline[i] + sum; k = (float) STBTT_fabs(k)*255 + 0.5f; m = (int) k; if (m > 255) m = 255; result->pixels[j*result->stride + i] = (unsigned char) m; } } // advance all the edges step = &active; while (*step) { stbtt__active_edge *z = *step; z->fx += z->fdx; // advance to position for current scanline step = &((*step)->next); // advance through list } ++y; ++j; } stbtt__hheap_cleanup(&hh, userdata); if (scanline != scanline_data) STBTT_free(scanline, userdata); } #else #error "Unrecognized value of STBTT_RASTERIZER_VERSION" #endif #define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0) static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) { int i,j; for (i=1; i < n; ++i) { stbtt__edge t = p[i], *a = &t; j = i; while (j > 0) { stbtt__edge *b = &p[j-1]; int c = STBTT__COMPARE(a,b); if (!c) break; p[j] = p[j-1]; --j; } if (i != j) p[j] = t; } } static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) { /* threshold for transitioning to insertion sort */ while (n > 12) { stbtt__edge t; int c01,c12,c,m,i,j; /* compute median of three */ m = n >> 1; c01 = STBTT__COMPARE(&p[0],&p[m]); c12 = STBTT__COMPARE(&p[m],&p[n-1]); /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ if (c01 != c12) { /* otherwise, we'll need to swap something else to middle */ int z; c = STBTT__COMPARE(&p[0],&p[n-1]); /* 0>mid && midn => n; 0 0 */ /* 0n: 0>n => 0; 0 n */ z = (c == c12) ? 0 : n-1; t = p[z]; p[z] = p[m]; p[m] = t; } /* now p[m] is the median-of-three */ /* swap it to the beginning so it won't move around */ t = p[0]; p[0] = p[m]; p[m] = t; /* partition loop */ i=1; j=n-1; for(;;) { /* handling of equality is crucial here */ /* for sentinels & efficiency with duplicates */ for (;;++i) { if (!STBTT__COMPARE(&p[i], &p[0])) break; } for (;;--j) { if (!STBTT__COMPARE(&p[0], &p[j])) break; } /* make sure we haven't crossed */ if (i >= j) break; t = p[i]; p[i] = p[j]; p[j] = t; ++i; --j; } /* recurse on smaller side, iterate on larger */ if (j < (n-i)) { stbtt__sort_edges_quicksort(p,j); p = p+i; n = n-i; } else { stbtt__sort_edges_quicksort(p+i, n-i); n = j; } } } static void stbtt__sort_edges(stbtt__edge *p, int n) { stbtt__sort_edges_quicksort(p, n); stbtt__sort_edges_ins_sort(p, n); } typedef struct { float x,y; } stbtt__point; static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) { float y_scale_inv = invert ? -scale_y : scale_y; stbtt__edge *e; int n,i,j,k,m; #if STBTT_RASTERIZER_VERSION == 1 int vsubsample = result->h < 8 ? 15 : 5; #elif STBTT_RASTERIZER_VERSION == 2 int vsubsample = 1; #else #error "Unrecognized value of STBTT_RASTERIZER_VERSION" #endif // vsubsample should divide 255 evenly; otherwise we won't reach full opacity // now we have to blow out the windings into explicit edge lists n = 0; for (i=0; i < windings; ++i) n += wcount[i]; e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); // add an extra one as a sentinel if (e == 0) return; n = 0; m=0; for (i=0; i < windings; ++i) { stbtt__point *p = pts + m; m += wcount[i]; j = wcount[i]-1; for (k=0; k < wcount[i]; j=k++) { int a=k,b=j; // skip the edge if horizontal if (p[j].y == p[k].y) continue; // add edge from j to k to the list e[n].invert = 0; if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { e[n].invert = 1; a=j,b=k; } e[n].x0 = p[a].x * scale_x + shift_x; e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; e[n].x1 = p[b].x * scale_x + shift_x; e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; ++n; } } // now sort the edges by their highest point (should snap to integer, and then by x) //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); stbtt__sort_edges(e, n); // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); STBTT_free(e, userdata); } static void stbtt__add_point(stbtt__point *points, int n, float x, float y) { if (!points) return; // during first pass, it's unallocated points[n].x = x; points[n].y = y; } // tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) { // midpoint float mx = (x0 + 2*x1 + x2)/4; float my = (y0 + 2*y1 + y2)/4; // versus directly drawn line float dx = (x0+x2)/2 - mx; float dy = (y0+y2)/2 - my; if (n > 16) // 65536 segments on one curve better be enough! return 1; if (dx*dx+dy*dy > objspace_flatness_squared) { // half-pixel error allowed... need to be smaller if AA stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); } else { stbtt__add_point(points, *num_points,x2,y2); *num_points = *num_points+1; } return 1; } static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n) { // @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough float dx0 = x1-x0; float dy0 = y1-y0; float dx1 = x2-x1; float dy1 = y2-y1; float dx2 = x3-x2; float dy2 = y3-y2; float dx = x3-x0; float dy = y3-y0; float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2)); float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy); float flatness_squared = longlen*longlen-shortlen*shortlen; if (n > 16) // 65536 segments on one curve better be enough! return; if (flatness_squared > objspace_flatness_squared) { float x01 = (x0+x1)/2; float y01 = (y0+y1)/2; float x12 = (x1+x2)/2; float y12 = (y1+y2)/2; float x23 = (x2+x3)/2; float y23 = (y2+y3)/2; float xa = (x01+x12)/2; float ya = (y01+y12)/2; float xb = (x12+x23)/2; float yb = (y12+y23)/2; float mx = (xa+xb)/2; float my = (ya+yb)/2; stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1); stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1); } else { stbtt__add_point(points, *num_points,x3,y3); *num_points = *num_points+1; } } // returns number of contours static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) { stbtt__point *points=0; int num_points=0; float objspace_flatness_squared = objspace_flatness * objspace_flatness; int i,n=0,start=0, pass; // count how many "moves" there are to get the contour count for (i=0; i < num_verts; ++i) if (vertices[i].type == STBTT_vmove) ++n; *num_contours = n; if (n == 0) return 0; *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); if (*contour_lengths == 0) { *num_contours = 0; return 0; } // make two passes through the points so we don't need to realloc for (pass=0; pass < 2; ++pass) { float x=0,y=0; if (pass == 1) { points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); if (points == NULL) goto error; } num_points = 0; n= -1; for (i=0; i < num_verts; ++i) { switch (vertices[i].type) { case STBTT_vmove: // start the next contour if (n >= 0) (*contour_lengths)[n] = num_points - start; ++n; start = num_points; x = vertices[i].x, y = vertices[i].y; stbtt__add_point(points, num_points++, x,y); break; case STBTT_vline: x = vertices[i].x, y = vertices[i].y; stbtt__add_point(points, num_points++, x, y); break; case STBTT_vcurve: stbtt__tesselate_curve(points, &num_points, x,y, vertices[i].cx, vertices[i].cy, vertices[i].x, vertices[i].y, objspace_flatness_squared, 0); x = vertices[i].x, y = vertices[i].y; break; case STBTT_vcubic: stbtt__tesselate_cubic(points, &num_points, x,y, vertices[i].cx, vertices[i].cy, vertices[i].cx1, vertices[i].cy1, vertices[i].x, vertices[i].y, objspace_flatness_squared, 0); x = vertices[i].x, y = vertices[i].y; break; } } (*contour_lengths)[n] = num_points - start; } return points; error: STBTT_free(points, userdata); STBTT_free(*contour_lengths, userdata); *contour_lengths = 0; *num_contours = 0; return NULL; } STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) { float scale = scale_x > scale_y ? scale_y : scale_x; int winding_count = 0; int *winding_lengths = NULL; stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); if (windings) { stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); STBTT_free(winding_lengths, userdata); STBTT_free(windings, userdata); } } STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) { STBTT_free(bitmap, userdata); } STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) { int ix0,iy0,ix1,iy1; stbtt__bitmap gbm; stbtt_vertex *vertices; int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); if (scale_x == 0) scale_x = scale_y; if (scale_y == 0) { if (scale_x == 0) { STBTT_free(vertices, info->userdata); return NULL; } scale_y = scale_x; } stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1); // now we get the size gbm.w = (ix1 - ix0); gbm.h = (iy1 - iy0); gbm.pixels = NULL; // in case we error if (width ) *width = gbm.w; if (height) *height = gbm.h; if (xoff ) *xoff = ix0; if (yoff ) *yoff = iy0; if (gbm.w && gbm.h) { gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); if (gbm.pixels) { gbm.stride = gbm.w; stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); } } STBTT_free(vertices, info->userdata); return gbm.pixels; } STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) { return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); } STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) { int ix0,iy0; stbtt_vertex *vertices; int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); stbtt__bitmap gbm; stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); gbm.pixels = output; gbm.w = out_w; gbm.h = out_h; gbm.stride = out_stride; if (gbm.w && gbm.h) stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); STBTT_free(vertices, info->userdata); } STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) { stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); } STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) { return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); } STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) { stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint)); } STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) { stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); } STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) { return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); } STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) { stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint); } ////////////////////////////////////////////////////////////////////////////// // // bitmap baking // // This is SUPER-CRAPPY packing to keep source code small static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // font location (use offset=0 for plain .ttf) float pixel_height, // height of font in pixels unsigned char *pixels, int pw, int ph, // bitmap to be filled in int first_char, int num_chars, // characters to bake stbtt_bakedchar *chardata) { float scale; int x,y,bottom_y, i; stbtt_fontinfo f; f.userdata = NULL; if (!stbtt_InitFont(&f, data, offset)) return -1; STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels x=y=1; bottom_y = 1; scale = stbtt_ScaleForPixelHeight(&f, pixel_height); for (i=0; i < num_chars; ++i) { int advance, lsb, x0,y0,x1,y1,gw,gh; int g = stbtt_FindGlyphIndex(&f, first_char + i); stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); gw = x1-x0; gh = y1-y0; if (x + gw + 1 >= pw) y = bottom_y, x = 1; // advance to next row if (y + gh + 1 >= ph) // check if it fits vertically AFTER potentially moving to next row return -i; STBTT_assert(x+gw < pw); STBTT_assert(y+gh < ph); stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); chardata[i].x0 = (stbtt_int16) x; chardata[i].y0 = (stbtt_int16) y; chardata[i].x1 = (stbtt_int16) (x + gw); chardata[i].y1 = (stbtt_int16) (y + gh); chardata[i].xadvance = scale * advance; chardata[i].xoff = (float) x0; chardata[i].yoff = (float) y0; x = x + gw + 1; if (y+gh+1 > bottom_y) bottom_y = y+gh+1; } return bottom_y; } STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) { float d3d_bias = opengl_fillrule ? 0 : -0.5f; float ipw = 1.0f / pw, iph = 1.0f / ph; const stbtt_bakedchar *b = chardata + char_index; int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); q->x0 = round_x + d3d_bias; q->y0 = round_y + d3d_bias; q->x1 = round_x + b->x1 - b->x0 + d3d_bias; q->y1 = round_y + b->y1 - b->y0 + d3d_bias; q->s0 = b->x0 * ipw; q->t0 = b->y0 * iph; q->s1 = b->x1 * ipw; q->t1 = b->y1 * iph; *xpos += b->xadvance; } ////////////////////////////////////////////////////////////////////////////// // // rectangle packing replacement routines if you don't have stb_rect_pack.h // #ifndef STB_RECT_PACK_VERSION typedef int stbrp_coord; //////////////////////////////////////////////////////////////////////////////////// // // // // // COMPILER WARNING ?!?!? // // // // // // if you get a compile warning due to these symbols being defined more than // // once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" // // // //////////////////////////////////////////////////////////////////////////////////// typedef struct { int width,height; int x,y,bottom_y; } stbrp_context; typedef struct { unsigned char x; } stbrp_node; struct stbrp_rect { stbrp_coord x,y; int id,w,h,was_packed; }; static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) { con->width = pw; con->height = ph; con->x = 0; con->y = 0; con->bottom_y = 0; STBTT__NOTUSED(nodes); STBTT__NOTUSED(num_nodes); } static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) { int i; for (i=0; i < num_rects; ++i) { if (con->x + rects[i].w > con->width) { con->x = 0; con->y = con->bottom_y; } if (con->y + rects[i].h > con->height) break; rects[i].x = con->x; rects[i].y = con->y; rects[i].was_packed = 1; con->x += rects[i].w; if (con->y + rects[i].h > con->bottom_y) con->bottom_y = con->y + rects[i].h; } for ( ; i < num_rects; ++i) rects[i].was_packed = 0; } #endif ////////////////////////////////////////////////////////////////////////////// // // bitmap baking // // This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If // stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) { stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); int num_nodes = pw - padding; stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); if (context == NULL || nodes == NULL) { if (context != NULL) STBTT_free(context, alloc_context); if (nodes != NULL) STBTT_free(nodes , alloc_context); return 0; } spc->user_allocator_context = alloc_context; spc->width = pw; spc->height = ph; spc->pixels = pixels; spc->pack_info = context; spc->nodes = nodes; spc->padding = padding; spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; spc->h_oversample = 1; spc->v_oversample = 1; spc->skip_missing = 0; stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); if (pixels) STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels return 1; } STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc) { STBTT_free(spc->nodes , spc->user_allocator_context); STBTT_free(spc->pack_info, spc->user_allocator_context); } STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample) { STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); if (h_oversample <= STBTT_MAX_OVERSAMPLE) spc->h_oversample = h_oversample; if (v_oversample <= STBTT_MAX_OVERSAMPLE) spc->v_oversample = v_oversample; } STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip) { spc->skip_missing = skip; } #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) { unsigned char buffer[STBTT_MAX_OVERSAMPLE]; int safe_w = w - kernel_width; int j; STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze for (j=0; j < h; ++j) { int i; unsigned int total; STBTT_memset(buffer, 0, kernel_width); total = 0; // make kernel_width a constant in common cases so compiler can optimize out the divide switch (kernel_width) { case 2: for (i=0; i <= safe_w; ++i) { total += pixels[i] - buffer[i & STBTT__OVER_MASK]; buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; pixels[i] = (unsigned char) (total / 2); } break; case 3: for (i=0; i <= safe_w; ++i) { total += pixels[i] - buffer[i & STBTT__OVER_MASK]; buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; pixels[i] = (unsigned char) (total / 3); } break; case 4: for (i=0; i <= safe_w; ++i) { total += pixels[i] - buffer[i & STBTT__OVER_MASK]; buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; pixels[i] = (unsigned char) (total / 4); } break; case 5: for (i=0; i <= safe_w; ++i) { total += pixels[i] - buffer[i & STBTT__OVER_MASK]; buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; pixels[i] = (unsigned char) (total / 5); } break; default: for (i=0; i <= safe_w; ++i) { total += pixels[i] - buffer[i & STBTT__OVER_MASK]; buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; pixels[i] = (unsigned char) (total / kernel_width); } break; } for (; i < w; ++i) { STBTT_assert(pixels[i] == 0); total -= buffer[i & STBTT__OVER_MASK]; pixels[i] = (unsigned char) (total / kernel_width); } pixels += stride_in_bytes; } } static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) { unsigned char buffer[STBTT_MAX_OVERSAMPLE]; int safe_h = h - kernel_width; int j; STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze for (j=0; j < w; ++j) { int i; unsigned int total; STBTT_memset(buffer, 0, kernel_width); total = 0; // make kernel_width a constant in common cases so compiler can optimize out the divide switch (kernel_width) { case 2: for (i=0; i <= safe_h; ++i) { total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; pixels[i*stride_in_bytes] = (unsigned char) (total / 2); } break; case 3: for (i=0; i <= safe_h; ++i) { total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; pixels[i*stride_in_bytes] = (unsigned char) (total / 3); } break; case 4: for (i=0; i <= safe_h; ++i) { total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; pixels[i*stride_in_bytes] = (unsigned char) (total / 4); } break; case 5: for (i=0; i <= safe_h; ++i) { total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; pixels[i*stride_in_bytes] = (unsigned char) (total / 5); } break; default: for (i=0; i <= safe_h; ++i) { total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); } break; } for (; i < h; ++i) { STBTT_assert(pixels[i*stride_in_bytes] == 0); total -= buffer[i & STBTT__OVER_MASK]; pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); } pixels += 1; } } static float stbtt__oversample_shift(int oversample) { if (!oversample) return 0.0f; // The prefilter is a box filter of width "oversample", // which shifts phase by (oversample - 1)/2 pixels in // oversampled space. We want to shift in the opposite // direction to counter this. return (float)-(oversample - 1) / (2.0f * (float)oversample); } // rects array must be big enough to accommodate all characters in the given ranges STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) { int i,j,k; int missing_glyph_added = 0; k=0; for (i=0; i < num_ranges; ++i) { float fh = ranges[i].font_size; float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); ranges[i].h_oversample = (unsigned char) spc->h_oversample; ranges[i].v_oversample = (unsigned char) spc->v_oversample; for (j=0; j < ranges[i].num_chars; ++j) { int x0,y0,x1,y1; int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; int glyph = stbtt_FindGlyphIndex(info, codepoint); if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) { rects[k].w = rects[k].h = 0; } else { stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, scale * spc->h_oversample, scale * spc->v_oversample, 0,0, &x0,&y0,&x1,&y1); rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); if (glyph == 0) missing_glyph_added = 1; } ++k; } } return k; } STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) { stbtt_MakeGlyphBitmapSubpixel(info, output, out_w - (prefilter_x - 1), out_h - (prefilter_y - 1), out_stride, scale_x, scale_y, shift_x, shift_y, glyph); if (prefilter_x > 1) stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x); if (prefilter_y > 1) stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y); *sub_x = stbtt__oversample_shift(prefilter_x); *sub_y = stbtt__oversample_shift(prefilter_y); } // rects array must be big enough to accommodate all characters in the given ranges STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) { int i,j,k, missing_glyph = -1, return_value = 1; // save current values int old_h_over = spc->h_oversample; int old_v_over = spc->v_oversample; k = 0; for (i=0; i < num_ranges; ++i) { float fh = ranges[i].font_size; float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); float recip_h,recip_v,sub_x,sub_y; spc->h_oversample = ranges[i].h_oversample; spc->v_oversample = ranges[i].v_oversample; recip_h = 1.0f / spc->h_oversample; recip_v = 1.0f / spc->v_oversample; sub_x = stbtt__oversample_shift(spc->h_oversample); sub_y = stbtt__oversample_shift(spc->v_oversample); for (j=0; j < ranges[i].num_chars; ++j) { stbrp_rect *r = &rects[k]; if (r->was_packed && r->w != 0 && r->h != 0) { stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; int advance, lsb, x0,y0,x1,y1; int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; int glyph = stbtt_FindGlyphIndex(info, codepoint); stbrp_coord pad = (stbrp_coord) spc->padding; // pad on left and top r->x += pad; r->y += pad; r->w -= pad; r->h -= pad; stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); stbtt_GetGlyphBitmapBox(info, glyph, scale * spc->h_oversample, scale * spc->v_oversample, &x0,&y0,&x1,&y1); stbtt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes, r->w - spc->h_oversample+1, r->h - spc->v_oversample+1, spc->stride_in_bytes, scale * spc->h_oversample, scale * spc->v_oversample, 0,0, glyph); if (spc->h_oversample > 1) stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, r->w, r->h, spc->stride_in_bytes, spc->h_oversample); if (spc->v_oversample > 1) stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, r->w, r->h, spc->stride_in_bytes, spc->v_oversample); bc->x0 = (stbtt_int16) r->x; bc->y0 = (stbtt_int16) r->y; bc->x1 = (stbtt_int16) (r->x + r->w); bc->y1 = (stbtt_int16) (r->y + r->h); bc->xadvance = scale * advance; bc->xoff = (float) x0 * recip_h + sub_x; bc->yoff = (float) y0 * recip_v + sub_y; bc->xoff2 = (x0 + r->w) * recip_h + sub_x; bc->yoff2 = (y0 + r->h) * recip_v + sub_y; if (glyph == 0) missing_glyph = j; } else if (spc->skip_missing) { return_value = 0; } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) { ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph]; } else { return_value = 0; // if any fail, report failure } ++k; } } // restore original values spc->h_oversample = old_h_over; spc->v_oversample = old_v_over; return return_value; } STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects) { stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); } STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) { stbtt_fontinfo info; int i, j, n, return_value; // [DEAR IMGUI] removed = 1; //stbrp_context *context = (stbrp_context *) spc->pack_info; stbrp_rect *rects; // flag all characters as NOT packed for (i=0; i < num_ranges; ++i) for (j=0; j < ranges[i].num_chars; ++j) ranges[i].chardata_for_range[j].x0 = ranges[i].chardata_for_range[j].y0 = ranges[i].chardata_for_range[j].x1 = ranges[i].chardata_for_range[j].y1 = 0; n = 0; for (i=0; i < num_ranges; ++i) n += ranges[i].num_chars; rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); if (rects == NULL) return 0; info.userdata = spc->user_allocator_context; stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); stbtt_PackFontRangesPackRects(spc, rects, n); return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); STBTT_free(rects, spc->user_allocator_context); return return_value; } STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) { stbtt_pack_range range; range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; range.array_of_unicode_codepoints = NULL; range.num_chars = num_chars_in_range; range.chardata_for_range = chardata_for_range; range.font_size = font_size; return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); } STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap) { int i_ascent, i_descent, i_lineGap; float scale; stbtt_fontinfo info; stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index)); scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size); stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap); *ascent = (float) i_ascent * scale; *descent = (float) i_descent * scale; *lineGap = (float) i_lineGap * scale; } STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) { float ipw = 1.0f / pw, iph = 1.0f / ph; const stbtt_packedchar *b = chardata + char_index; if (align_to_integer) { float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f); q->x0 = x; q->y0 = y; q->x1 = x + b->xoff2 - b->xoff; q->y1 = y + b->yoff2 - b->yoff; } else { q->x0 = *xpos + b->xoff; q->y0 = *ypos + b->yoff; q->x1 = *xpos + b->xoff2; q->y1 = *ypos + b->yoff2; } q->s0 = b->x0 * ipw; q->t0 = b->y0 * iph; q->s1 = b->x1 * ipw; q->t1 = b->y1 * iph; *xpos += b->xadvance; } ////////////////////////////////////////////////////////////////////////////// // // sdf computation // #define STBTT_min(a,b) ((a) < (b) ? (a) : (b)) #define STBTT_max(a,b) ((a) < (b) ? (b) : (a)) static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) { float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; float roperp = orig[1]*ray[0] - orig[0]*ray[1]; float a = q0perp - 2*q1perp + q2perp; float b = q1perp - q0perp; float c = q0perp - roperp; float s0 = 0., s1 = 0.; int num_s = 0; if (a != 0.0) { float discr = b*b - a*c; if (discr > 0.0) { float rcpna = -1 / a; float d = (float) STBTT_sqrt(discr); s0 = (b+d) * rcpna; s1 = (b-d) * rcpna; if (s0 >= 0.0 && s0 <= 1.0) num_s = 1; if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { if (num_s == 0) s0 = s1; ++num_s; } } } else { // 2*b*s + c = 0 // s = -c / (2*b) s0 = c / (-2 * b); if (s0 >= 0.0 && s0 <= 1.0) num_s = 1; } if (num_s == 0) return 0; else { float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; float q0d = q0[0]*rayn_x + q0[1]*rayn_y; float q1d = q1[0]*rayn_x + q1[1]*rayn_y; float q2d = q2[0]*rayn_x + q2[1]*rayn_y; float rod = orig[0]*rayn_x + orig[1]*rayn_y; float q10d = q1d - q0d; float q20d = q2d - q0d; float q0rd = q0d - rod; hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; hits[0][1] = a*s0+b; if (num_s > 1) { hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; hits[1][1] = a*s1+b; return 2; } else { return 1; } } } static int equal(float *a, float *b) { return (a[0] == b[0] && a[1] == b[1]); } static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) { int i; float orig[2], ray[2] = { 1, 0 }; float y_frac; int winding = 0; // make sure y never passes through a vertex of the shape y_frac = (float) STBTT_fmod(y, 1.0f); if (y_frac < 0.01f) y += 0.01f; else if (y_frac > 0.99f) y -= 0.01f; orig[0] = x; orig[1] = y; // test a ray from (-infinity,y) to (x,y) for (i=0; i < nverts; ++i) { if (verts[i].type == STBTT_vline) { int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; if (x_inter < x) winding += (y0 < y1) ? 1 : -1; } } if (verts[i].type == STBTT_vcurve) { int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); int by = STBTT_max(y0,STBTT_max(y1,y2)); if (y > ay && y < by && x > ax) { float q0[2],q1[2],q2[2]; float hits[2][2]; q0[0] = (float)x0; q0[1] = (float)y0; q1[0] = (float)x1; q1[1] = (float)y1; q2[0] = (float)x2; q2[1] = (float)y2; if (equal(q0,q1) || equal(q1,q2)) { x0 = (int)verts[i-1].x; y0 = (int)verts[i-1].y; x1 = (int)verts[i ].x; y1 = (int)verts[i ].y; if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; if (x_inter < x) winding += (y0 < y1) ? 1 : -1; } } else { int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); if (num_hits >= 1) if (hits[0][0] < 0) winding += (hits[0][1] < 0 ? -1 : 1); if (num_hits >= 2) if (hits[1][0] < 0) winding += (hits[1][1] < 0 ? -1 : 1); } } } } return winding; } static float stbtt__cuberoot( float x ) { if (x<0) return -(float) STBTT_pow(-x,1.0f/3.0f); else return (float) STBTT_pow( x,1.0f/3.0f); } // x^3 + a*x^2 + b*x + c = 0 static int stbtt__solve_cubic(float a, float b, float c, float* r) { float s = -a / 3; float p = b - a*a / 3; float q = a * (2*a*a - 9*b) / 27 + c; float p3 = p*p*p; float d = q*q + 4*p3 / 27; if (d >= 0) { float z = (float) STBTT_sqrt(d); float u = (-q + z) / 2; float v = (-q - z) / 2; u = stbtt__cuberoot(u); v = stbtt__cuberoot(v); r[0] = s + u + v; return 1; } else { float u = (float) STBTT_sqrt(-p/3); float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative float m = (float) STBTT_cos(v); float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; r[0] = s + u * 2 * m; r[1] = s - u * (m + n); r[2] = s - u * (m - n); //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); return 3; } } STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) { float scale_x = scale, scale_y = scale; int ix0,iy0,ix1,iy1; int w,h; unsigned char *data; if (scale == 0) return NULL; stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); // if empty, return NULL if (ix0 == ix1 || iy0 == iy1) return NULL; ix0 -= padding; iy0 -= padding; ix1 += padding; iy1 += padding; w = (ix1 - ix0); h = (iy1 - iy0); if (width ) *width = w; if (height) *height = h; if (xoff ) *xoff = ix0; if (yoff ) *yoff = iy0; // invert for y-downwards bitmaps scale_y = -scale_y; { int x,y,i,j; float *precompute; stbtt_vertex *verts; int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); data = (unsigned char *) STBTT_malloc(w * h, info->userdata); precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); for (i=0,j=num_verts-1; i < num_verts; j=i++) { if (verts[i].type == STBTT_vline) { float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist; } else if (verts[i].type == STBTT_vcurve) { float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; float len2 = bx*bx + by*by; if (len2 != 0.0f) precompute[i] = 1.0f / (bx*bx + by*by); else precompute[i] = 0.0f; } else precompute[i] = 0.0f; } for (y=iy0; y < iy1; ++y) { for (x=ix0; x < ix1; ++x) { float val; float min_dist = 999999.0f; float sx = (float) x + 0.5f; float sy = (float) y + 0.5f; float x_gspace = (sx / scale_x); float y_gspace = (sy / scale_y); int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path for (i=0; i < num_verts; ++i) { float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) { float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); if (dist2 < min_dist*min_dist) min_dist = (float) STBTT_sqrt(dist2); // coarse culling against bbox //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; STBTT_assert(i != 0); if (dist < min_dist) { // check position along line // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) float dx = x1-x0, dy = y1-y0; float px = x0-sx, py = y0-sy; // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve float t = -(px*dx + py*dy) / (dx*dx + dy*dy); if (t >= 0.0f && t <= 1.0f) min_dist = dist; } } else if (verts[i].type == STBTT_vcurve) { float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); // coarse culling against bbox to avoid computing cubic unnecessarily if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { int num=0; float ax = x1-x0, ay = y1-y0; float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; float mx = x0 - sx, my = y0 - sy; float res[3] = {0.f,0.f,0.f}; float px,py,t,it,dist2; float a_inv = precompute[i]; if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula float a = 3*(ax*bx + ay*by); float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); float c = mx*ax+my*ay; if (a == 0.0) { // if a is 0, it's linear if (b != 0.0) { res[num++] = -c/b; } } else { float discriminant = b*b - 4*a*c; if (discriminant < 0) num = 0; else { float root = (float) STBTT_sqrt(discriminant); res[0] = (-b - root)/(2*a); res[1] = (-b + root)/(2*a); num = 2; // don't bother distinguishing 1-solution case, as code below will still work } } } else { float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; float d = (mx*ax+my*ay) * a_inv; num = stbtt__solve_cubic(b, c, d, res); } dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); if (dist2 < min_dist*min_dist) min_dist = (float) STBTT_sqrt(dist2); if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { t = res[0], it = 1.0f - t; px = it*it*x0 + 2*t*it*x1 + t*t*x2; py = it*it*y0 + 2*t*it*y1 + t*t*y2; dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); if (dist2 < min_dist * min_dist) min_dist = (float) STBTT_sqrt(dist2); } if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { t = res[1], it = 1.0f - t; px = it*it*x0 + 2*t*it*x1 + t*t*x2; py = it*it*y0 + 2*t*it*y1 + t*t*y2; dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); if (dist2 < min_dist * min_dist) min_dist = (float) STBTT_sqrt(dist2); } if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { t = res[2], it = 1.0f - t; px = it*it*x0 + 2*t*it*x1 + t*t*x2; py = it*it*y0 + 2*t*it*y1 + t*t*y2; dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); if (dist2 < min_dist * min_dist) min_dist = (float) STBTT_sqrt(dist2); } } } } if (winding == 0) min_dist = -min_dist; // if outside the shape, value is negative val = onedge_value + pixel_dist_scale * min_dist; if (val < 0) val = 0; else if (val > 255) val = 255; data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; } } STBTT_free(precompute, info->userdata); STBTT_free(verts, info->userdata); } return data; } STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) { return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); } STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) { STBTT_free(bitmap, userdata); } ////////////////////////////////////////////////////////////////////////////// // // font name matching -- recommended not to use this // // check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) { stbtt_int32 i=0; // convert utf16 to utf8 and compare the results while converting while (len2) { stbtt_uint16 ch = s2[0]*256 + s2[1]; if (ch < 0x80) { if (i >= len1) return -1; if (s1[i++] != ch) return -1; } else if (ch < 0x800) { if (i+1 >= len1) return -1; if (s1[i++] != 0xc0 + (ch >> 6)) return -1; if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; } else if (ch >= 0xd800 && ch < 0xdc00) { stbtt_uint32 c; stbtt_uint16 ch2 = s2[2]*256 + s2[3]; if (i+3 >= len1) return -1; c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; if (s1[i++] != 0xf0 + (c >> 18)) return -1; if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1; s2 += 2; // plus another 2 below len2 -= 2; } else if (ch >= 0xdc00 && ch < 0xe000) { return -1; } else { if (i+2 >= len1) return -1; if (s1[i++] != 0xe0 + (ch >> 12)) return -1; if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1; } s2 += 2; len2 -= 2; } return i; } static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) { return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); } // returns results in whatever encoding you request... but note that 2-byte encodings // will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) { stbtt_int32 i,count,stringOffset; stbtt_uint8 *fc = font->data; stbtt_uint32 offset = font->fontstart; stbtt_uint32 nm = stbtt__find_table(fc, offset, "name"); if (!nm) return NULL; count = ttUSHORT(fc+nm+2); stringOffset = nm + ttUSHORT(fc+nm+4); for (i=0; i < count; ++i) { stbtt_uint32 loc = nm + 6 + 12 * i; if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { *length = ttUSHORT(fc+loc+8); return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); } } return NULL; } static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id) { stbtt_int32 i; stbtt_int32 count = ttUSHORT(fc+nm+2); stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4); for (i=0; i < count; ++i) { stbtt_uint32 loc = nm + 6 + 12 * i; stbtt_int32 id = ttUSHORT(fc+loc+6); if (id == target_id) { // find the encoding stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); // is this a Unicode encoding? if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { stbtt_int32 slen = ttUSHORT(fc+loc+8); stbtt_int32 off = ttUSHORT(fc+loc+10); // check if there's a prefix match stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); if (matchlen >= 0) { // check for target_id+1 immediately following, with same encoding & language if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) { slen = ttUSHORT(fc+loc+12+8); off = ttUSHORT(fc+loc+12+10); if (slen == 0) { if (matchlen == nlen) return 1; } else if (matchlen < nlen && name[matchlen] == ' ') { ++matchlen; if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) return 1; } } else { // if nothing immediately following if (matchlen == nlen) return 1; } } } // @TODO handle other encodings } } return 0; } static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) { stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name); stbtt_uint32 nm,hd; if (!stbtt__isfont(fc+offset)) return 0; // check italics/bold/underline flags in macStyle... if (flags) { hd = stbtt__find_table(fc, offset, "head"); if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0; } nm = stbtt__find_table(fc, offset, "name"); if (!nm) return 0; if (flags) { // if we checked the macStyle flags, then just check the family and ignore the subfamily if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; } else { if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; } return 0; } static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags) { stbtt_int32 i; for (i=0;;++i) { stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); if (off < 0) return off; if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags)) return off; } } #if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" #endif STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, float pixel_height, unsigned char *pixels, int pw, int ph, int first_char, int num_chars, stbtt_bakedchar *chardata) { return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); } STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) { return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); } STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) { return stbtt_GetNumberOfFonts_internal((unsigned char *) data); } STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) { return stbtt_InitFont_internal(info, (unsigned char *) data, offset); } STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) { return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags); } STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) { return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2); } #if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic pop #endif #endif // STB_TRUETYPE_IMPLEMENTATION // FULL VERSION HISTORY // // 1.25 (2021-07-11) many fixes // 1.24 (2020-02-05) fix warning // 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) // 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined // 1.21 (2019-02-25) fix warning // 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() // 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod // 1.18 (2018-01-29) add missing function // 1.17 (2017-07-23) make more arguments const; doc fix // 1.16 (2017-07-12) SDF support // 1.15 (2017-03-03) make more arguments const // 1.14 (2017-01-16) num-fonts-in-TTC function // 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts // 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual // 1.11 (2016-04-02) fix unused-variable warning // 1.10 (2016-04-02) allow user-defined fabs() replacement // fix memory leak if fontsize=0.0 // fix warning from duplicate typedef // 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges // 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges // 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; // allow PackFontRanges to pack and render in separate phases; // fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); // fixed an assert() bug in the new rasterizer // replace assert() with STBTT_assert() in new rasterizer // 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) // also more precise AA rasterizer, except if shapes overlap // remove need for STBTT_sort // 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC // 1.04 (2015-04-15) typo in example // 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes // 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ // 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match // non-oversampled; STBTT_POINT_SIZE for packed case only // 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling // 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) // 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID // 0.8b (2014-07-07) fix a warning // 0.8 (2014-05-25) fix a few more warnings // 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back // 0.6c (2012-07-24) improve documentation // 0.6b (2012-07-20) fix a few more warnings // 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, // stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty // 0.5 (2011-12-09) bugfixes: // subpixel glyph renderer computed wrong bounding box // first vertex of shape can be off-curve (FreeSans) // 0.4b (2011-12-03) fixed an error in the font baking example // 0.4 (2011-12-01) kerning, subpixel rendering (tor) // bugfixes for: // codepoint-to-glyph conversion using table fmt=12 // codepoint-to-glyph conversion using table fmt=4 // stbtt_GetBakedQuad with non-square texture (Zer) // updated Hello World! sample to use kerning and subpixel // fixed some warnings // 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) // userdata, malloc-from-userdata, non-zero fill (stb) // 0.2 (2009-03-11) Fix unsigned/signed char warnings // 0.1 (2009-03-09) First public release // /* ------------------------------------------------------------------------------ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ RenderKit-ospray-f2a61c2/apps/common/external/stb_image/000077500000000000000000000000001456566705700233565ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/common/external/stb_image/CMakeLists.txt000066400000000000000000000003211456566705700261120ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 add_library(stb_image INTERFACE) target_include_directories(stb_image INTERFACE $ ) RenderKit-ospray-f2a61c2/apps/common/external/stb_image/stb_image.h000066400000000000000000010540751456566705700254750ustar00rootroot00000000000000/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb no warranty implied; use at your own risk Do this: #define STB_IMAGE_IMPLEMENTATION before you include this file in *one* C or C++ file to create the implementation. // i.e. it should look like this: #include ... #include ... #include ... #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free QUICK NOTES: Primarily of interest to game developers and other people who can avoid problematic images and only need the trivial interface JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) PNG 1/2/4/8/16-bit-per-channel TGA (not sure what subset, if a subset) BMP non-1bpp, non-RLE PSD (composited view only, no extra channels, 8/16 bit-per-channel) GIF (*comp always reports as 4-channel) HDR (radiance rgbE format) PIC (Softimage PIC) PNM (PPM and PGM binary only) Animated GIF still needs a proper API, but here's one way to do it: http://gist.github.com/urraka/685d9a6340b26b830d49 - decode from memory or through FILE (define STBI_NO_STDIO to remove code) - decode from arbitrary I/O callbacks - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) Full documentation under "DOCUMENTATION" below. LICENSE See end of file for license information. RECENT REVISION HISTORY: 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes 2.26 (2020-07-13) many minor fixes 2.25 (2020-02-02) fix warnings 2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically 2.23 (2019-08-11) fix clang static analysis warning 2.22 (2019-03-04) gif fixes, fix warnings 2.21 (2019-02-25) fix typo in comment 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs 2.19 (2018-02-11) fix warning 2.18 (2018-01-30) fix warnings 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 RGB-format JPEG; remove white matting in PSD; allocate large structures on the stack; correct channel count for PNG & BMP 2.10 (2016-01-22) avoid warning introduced in 2.09 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED See end of file for full revision history. ============================ Contributors ========================= Image formats Extensions, features Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) github:urraka (animated gif) Junggon Kim (PNM comments) Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) socks-the-fox (16-bit PNG) Jeremy Sawicki (handle all ImageNet JPGs) Optimizations & bugfixes Mikhail Morozov (1-bit BMP) Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) Arseny Kapoulkine Simon Breuss (16-bit PNM) John-Mark Allen Carmelo J Fdez-Aguera Bug & warning fixes Marc LeBlanc David Woo Guillaume George Martins Mozeiko Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski Phil Jordan Dave Moore Roy Eltham Hayaki Saito Nathan Reed Won Chun Luke Graham Johan Duparc Nick Verigakis the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh Janez Zemva John Bartholomew Michal Cichon github:romigrou Jonathan Blow Ken Hamada Tero Hanninen github:svdijk Eugene Golushkov Laurent Gomila Cort Stratton github:snagar Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex Cass Everitt Ryamond Barbiero github:grim210 Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo Julian Raschke Gregory Mullen Christian Floisand github:darealshinji Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 Brad Weinberger Matvey Cherevko github:mosra Luca Sas Alexander Veselov Zack Middleton [reserved] Ryan C. Gordon [reserved] [reserved] DO NOT ADD YOUR NAME HERE Jacko Dirks To add your name to the credits, pick a random blank space in the middle and fill it. 80% of merge conflicts on stb PRs are due to people adding their name at the end of the credits. */ #ifndef STBI_INCLUDE_STB_IMAGE_H #define STBI_INCLUDE_STB_IMAGE_H // DOCUMENTATION // // Limitations: // - no 12-bit-per-channel JPEG // - no JPEGs with arithmetic coding // - GIF always returns *comp=4 // // Basic usage (see HDR discussion below for HDR usage): // int x,y,n; // unsigned char *data = stbi_load(filename, &x, &y, &n, 0); // // ... process data if not NULL ... // // ... x = width, y = height, n = # 8-bit components per pixel ... // // ... replace '0' with '1'..'4' to force that many components per pixel // // ... but 'n' will always be the number that it would have been if you said 0 // stbi_image_free(data); // // Standard parameters: // int *x -- outputs image width in pixels // int *y -- outputs image height in pixels // int *channels_in_file -- outputs # of image components in image file // int desired_channels -- if non-zero, # of image components requested in result // // The return value from an image loader is an 'unsigned char *' which points // to the pixel data, or NULL on an allocation failure or if the image is // corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, // with each pixel consisting of N interleaved 8-bit components; the first // pixel pointed to is top-left-most in the image. There is no padding between // image scanlines or between pixels, regardless of format. The number of // components N is 'desired_channels' if desired_channels is non-zero, or // *channels_in_file otherwise. If desired_channels is non-zero, // *channels_in_file has the number of components that _would_ have been // output otherwise. E.g. if you set desired_channels to 4, you will always // get RGBA output, but you can check *channels_in_file to see if it's trivially // opaque because e.g. there were only 3 channels in the source image. // // An output image with N components has the following components interleaved // in this order in each pixel: // // N=#comp components // 1 grey // 2 grey, alpha // 3 red, green, blue // 4 red, green, blue, alpha // // If image loading fails for any reason, the return value will be NULL, // and *x, *y, *channels_in_file will be unchanged. The function // stbi_failure_reason() can be queried for an extremely brief, end-user // unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS // to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly // more user-friendly ones. // // Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. // // To query the width, height and component count of an image without having to // decode the full file, you can use the stbi_info family of functions: // // int x,y,n,ok; // ok = stbi_info(filename, &x, &y, &n); // // returns ok=1 and sets x, y, n if image is a supported format, // // 0 otherwise. // // Note that stb_image pervasively uses ints in its public API for sizes, // including sizes of memory buffers. This is now part of the API and thus // hard to change without causing breakage. As a result, the various image // loaders all have certain limits on image size; these differ somewhat // by format but generally boil down to either just under 2GB or just under // 1GB. When the decoded image would be larger than this, stb_image decoding // will fail. // // Additionally, stb_image will reject image files that have any of their // dimensions set to a larger value than the configurable STBI_MAX_DIMENSIONS, // which defaults to 2**24 = 16777216 pixels. Due to the above memory limit, // the only way to have an image with such dimensions load correctly // is for it to have a rather extreme aspect ratio. Either way, the // assumption here is that such larger images are likely to be malformed // or malicious. If you do need to load an image with individual dimensions // larger than that, and it still fits in the overall size limit, you can // #define STBI_MAX_DIMENSIONS on your own to be something larger. // // =========================================================================== // // UNICODE: // // If compiling for Windows and you wish to use Unicode filenames, compile // with // #define STBI_WINDOWS_UTF8 // and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert // Windows wchar_t filenames to utf8. // // =========================================================================== // // Philosophy // // stb libraries are designed with the following priorities: // // 1. easy to use // 2. easy to maintain // 3. good performance // // Sometimes I let "good performance" creep up in priority over "easy to maintain", // and for best performance I may provide less-easy-to-use APIs that give higher // performance, in addition to the easy-to-use ones. Nevertheless, it's important // to keep in mind that from the standpoint of you, a client of this library, // all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. // // Some secondary priorities arise directly from the first two, some of which // provide more explicit reasons why performance can't be emphasized. // // - Portable ("ease of use") // - Small source code footprint ("easy to maintain") // - No dependencies ("ease of use") // // =========================================================================== // // I/O callbacks // // I/O callbacks allow you to read from arbitrary sources, like packaged // files or some other source. Data read from callbacks are processed // through a small internal buffer (currently 128 bytes) to try to reduce // overhead. // // The three functions you must define are "read" (reads some bytes of data), // "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). // // =========================================================================== // // SIMD support // // The JPEG decoder will try to automatically use SIMD kernels on x86 when // supported by the compiler. For ARM Neon support, you must explicitly // request it. // // (The old do-it-yourself SIMD API is no longer supported in the current // code.) // // On x86, SSE2 will automatically be used when available based on a run-time // test; if not, the generic C versions are used as a fall-back. On ARM targets, // the typical path is to have separate builds for NEON and non-NEON devices // (at least this is true for iOS and Android). Therefore, the NEON support is // toggled by a build flag: define STBI_NEON to get NEON loops. // // If for some reason you do not want to use any of SIMD code, or if // you have issues compiling it, you can disable it entirely by // defining STBI_NO_SIMD. // // =========================================================================== // // HDR image support (disable by defining STBI_NO_HDR) // // stb_image supports loading HDR images in general, and currently the Radiance // .HDR file format specifically. You can still load any file through the existing // interface; if you attempt to load an HDR file, it will be automatically remapped // to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; // both of these constants can be reconfigured through this interface: // // stbi_hdr_to_ldr_gamma(2.2f); // stbi_hdr_to_ldr_scale(1.0f); // // (note, do not use _inverse_ constants; stbi_image will invert them // appropriately). // // Additionally, there is a new, parallel interface for loading files as // (linear) floats to preserve the full dynamic range: // // float *data = stbi_loadf(filename, &x, &y, &n, 0); // // If you load LDR images through this interface, those images will // be promoted to floating point values, run through the inverse of // constants corresponding to the above: // // stbi_ldr_to_hdr_scale(1.0f); // stbi_ldr_to_hdr_gamma(2.2f); // // Finally, given a filename (or an open file or memory block--see header // file for details) containing image data, you can query for the "most // appropriate" interface to use (that is, whether the image is HDR or // not), using: // // stbi_is_hdr(char *filename); // // =========================================================================== // // iPhone PNG support: // // We optionally support converting iPhone-formatted PNGs (which store // premultiplied BGRA) back to RGB, even though they're internally encoded // differently. To enable this conversion, call // stbi_convert_iphone_png_to_rgb(1). // // Call stbi_set_unpremultiply_on_load(1) as well to force a divide per // pixel to remove any premultiplied alpha *only* if the image file explicitly // says there's premultiplied data (currently only happens in iPhone images, // and only if iPhone convert-to-rgb processing is on). // // =========================================================================== // // ADDITIONAL CONFIGURATION // // - You can suppress implementation of any of the decoders to reduce // your code footprint by #defining one or more of the following // symbols before creating the implementation. // // STBI_NO_JPEG // STBI_NO_PNG // STBI_NO_BMP // STBI_NO_PSD // STBI_NO_TGA // STBI_NO_GIF // STBI_NO_HDR // STBI_NO_PIC // STBI_NO_PNM (.ppm and .pgm) // // - You can request *only* certain decoders and suppress all other ones // (this will be more forward-compatible, as addition of new decoders // doesn't require you to disable them explicitly): // // STBI_ONLY_JPEG // STBI_ONLY_PNG // STBI_ONLY_BMP // STBI_ONLY_PSD // STBI_ONLY_TGA // STBI_ONLY_GIF // STBI_ONLY_HDR // STBI_ONLY_PIC // STBI_ONLY_PNM (.ppm and .pgm) // // - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still // want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB // // - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater // than that size (in either width or height) without further processing. // This is to let programs in the wild set an upper bound to prevent // denial-of-service attacks on untrusted data, as one could generate a // valid image of gigantic dimensions and force stb_image to allocate a // huge block of memory and spend disproportionate time decoding it. By // default this is set to (1 << 24), which is 16777216, but that's still // very big. #ifndef STBI_NO_STDIO #include #endif // STBI_NO_STDIO #define STBI_VERSION 1 enum { STBI_default = 0, // only used for desired_channels STBI_grey = 1, STBI_grey_alpha = 2, STBI_rgb = 3, STBI_rgb_alpha = 4 }; #include typedef unsigned char stbi_uc; typedef unsigned short stbi_us; #ifdef __cplusplus extern "C" { #endif #ifndef STBIDEF #ifdef STB_IMAGE_STATIC #define STBIDEF static #else #define STBIDEF extern #endif #endif ////////////////////////////////////////////////////////////////////////////// // // PRIMARY API - works on images of any type // // // load image by filename, open file, or memory buffer // typedef struct { int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative int (*eof) (void *user); // returns nonzero if we are at end of file/data } stbi_io_callbacks; //////////////////////////////////// // // 8-bits-per-channel interface // STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); #ifndef STBI_NO_STDIO STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); // for stbi_load_from_file, file pointer is left pointing immediately after image #endif #ifndef STBI_NO_GIF STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp); #endif #ifdef STBI_WINDOWS_UTF8 STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); #endif //////////////////////////////////// // // 16-bits-per-channel interface // STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); #ifndef STBI_NO_STDIO STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); #endif //////////////////////////////////// // // float-per-channel interface // #ifndef STBI_NO_LINEAR STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); #ifndef STBI_NO_STDIO STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); #endif #endif #ifndef STBI_NO_HDR STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); STBIDEF void stbi_hdr_to_ldr_scale(float scale); #endif // STBI_NO_HDR #ifndef STBI_NO_LINEAR STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); STBIDEF void stbi_ldr_to_hdr_scale(float scale); #endif // STBI_NO_LINEAR // stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); #ifndef STBI_NO_STDIO STBIDEF int stbi_is_hdr (char const *filename); STBIDEF int stbi_is_hdr_from_file(FILE *f); #endif // STBI_NO_STDIO // get a VERY brief reason for failure // on most compilers (and ALL modern mainstream compilers) this is threadsafe STBIDEF const char *stbi_failure_reason (void); // free the loaded image -- this is just free() STBIDEF void stbi_image_free (void *retval_from_stbi_load); // get image dimensions & components without fully decoding STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); #ifndef STBI_NO_STDIO STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); STBIDEF int stbi_is_16_bit (char const *filename); STBIDEF int stbi_is_16_bit_from_file(FILE *f); #endif // for image formats that explicitly notate that they have premultiplied alpha, // we just return the colors as stored in the file. set this flag to force // unpremultiplication. results are undefined if the unpremultiply overflow. STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); // indicate whether we should process iphone images back to canonical format, // or just pass them through "as-is" STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); // flip the image vertically, so the first pixel in the output array is the bottom left STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); // as above, but only applies to images loaded on the thread that calls the function // this function is only available if your compiler supports thread-local variables; // calling it will fail to link if your compiler doesn't STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply); STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert); STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip); // ZLIB client - used by PNG, available for other purposes STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); #ifdef __cplusplus } #endif // // //// end header file ///////////////////////////////////////////////////// #endif // STBI_INCLUDE_STB_IMAGE_H #ifdef STB_IMAGE_IMPLEMENTATION #if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ || defined(STBI_ONLY_ZLIB) #ifndef STBI_ONLY_JPEG #define STBI_NO_JPEG #endif #ifndef STBI_ONLY_PNG #define STBI_NO_PNG #endif #ifndef STBI_ONLY_BMP #define STBI_NO_BMP #endif #ifndef STBI_ONLY_PSD #define STBI_NO_PSD #endif #ifndef STBI_ONLY_TGA #define STBI_NO_TGA #endif #ifndef STBI_ONLY_GIF #define STBI_NO_GIF #endif #ifndef STBI_ONLY_HDR #define STBI_NO_HDR #endif #ifndef STBI_ONLY_PIC #define STBI_NO_PIC #endif #ifndef STBI_ONLY_PNM #define STBI_NO_PNM #endif #endif #if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) #define STBI_NO_ZLIB #endif #include #include // ptrdiff_t on osx #include #include #include #if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) #include // ldexp, pow #endif #ifndef STBI_NO_STDIO #include #endif #ifndef STBI_ASSERT #include #define STBI_ASSERT(x) assert(x) #endif #ifdef __cplusplus #define STBI_EXTERN extern "C" #else #define STBI_EXTERN extern #endif #ifndef _MSC_VER #ifdef __cplusplus #define stbi_inline inline #else #define stbi_inline #endif #else #define stbi_inline __forceinline #endif #ifndef STBI_NO_THREAD_LOCALS #if defined(__cplusplus) && __cplusplus >= 201103L #define STBI_THREAD_LOCAL thread_local #elif defined(__GNUC__) && __GNUC__ < 5 #define STBI_THREAD_LOCAL __thread #elif defined(_MSC_VER) #define STBI_THREAD_LOCAL __declspec(thread) #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) #define STBI_THREAD_LOCAL _Thread_local #endif #ifndef STBI_THREAD_LOCAL #if defined(__GNUC__) #define STBI_THREAD_LOCAL __thread #endif #endif #endif #if defined(_MSC_VER) || defined(__SYMBIAN32__) typedef unsigned short stbi__uint16; typedef signed short stbi__int16; typedef unsigned int stbi__uint32; typedef signed int stbi__int32; #else #include typedef uint16_t stbi__uint16; typedef int16_t stbi__int16; typedef uint32_t stbi__uint32; typedef int32_t stbi__int32; #endif // should produce compiler error if size is wrong typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #ifdef _MSC_VER #define STBI_NOTUSED(v) (void)(v) #else #define STBI_NOTUSED(v) (void)sizeof(v) #endif #ifdef _MSC_VER #define STBI_HAS_LROTL #endif #ifdef STBI_HAS_LROTL #define stbi_lrot(x,y) _lrotl(x,y) #else #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (-(y) & 31))) #endif #if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) // ok #elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) // ok #else #error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." #endif #ifndef STBI_MALLOC #define STBI_MALLOC(sz) malloc(sz) #define STBI_REALLOC(p,newsz) realloc(p,newsz) #define STBI_FREE(p) free(p) #endif #ifndef STBI_REALLOC_SIZED #define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) #endif // x86/x64 detection #if defined(__x86_64__) || defined(_M_X64) #define STBI__X64_TARGET #elif defined(__i386) || defined(_M_IX86) #define STBI__X86_TARGET #endif #if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) // gcc doesn't support sse2 intrinsics unless you compile with -msse2, // which in turn means it gets to use SSE2 everywhere. This is unfortunate, // but previous attempts to provide the SSE2 functions with runtime // detection caused numerous issues. The way architecture extensions are // exposed in GCC/Clang is, sadly, not really suited for one-file libs. // New behavior: if compiled with -msse2, we use SSE2 without any // detection; if not, we don't use it at all. #define STBI_NO_SIMD #endif #if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) // Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET // // 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the // Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. // As a result, enabling SSE2 on 32-bit MinGW is dangerous when not // simultaneously enabling "-mstackrealign". // // See https://github.com/nothings/stb/issues/81 for more information. // // So default to no SSE2 on 32-bit MinGW. If you've read this far and added // -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. #define STBI_NO_SIMD #endif #if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) #define STBI_SSE2 #include #ifdef _MSC_VER #if _MSC_VER >= 1400 // not VC6 #include // __cpuid static int stbi__cpuid3(void) { int info[4]; __cpuid(info,1); return info[3]; } #else static int stbi__cpuid3(void) { int res; __asm { mov eax,1 cpuid mov res,edx } return res; } #endif #define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name #if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) static int stbi__sse2_available(void) { int info3 = stbi__cpuid3(); return ((info3 >> 26) & 1) != 0; } #endif #else // assume GCC-style if not VC++ #define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) #if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) static int stbi__sse2_available(void) { // If we're even attempting to compile this on GCC/Clang, that means // -msse2 is on, which means the compiler is allowed to use SSE2 // instructions at will, and so are we. return 1; } #endif #endif #endif // ARM NEON #if defined(STBI_NO_SIMD) && defined(STBI_NEON) #undef STBI_NEON #endif #ifdef STBI_NEON #include #ifdef _MSC_VER #define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name #else #define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) #endif #endif #ifndef STBI_SIMD_ALIGN #define STBI_SIMD_ALIGN(type, name) type name #endif #ifndef STBI_MAX_DIMENSIONS #define STBI_MAX_DIMENSIONS (1 << 24) #endif /////////////////////////////////////////////// // // stbi__context struct and start_xxx functions // stbi__context structure is our basic context used by all images, so it // contains all the IO context, plus some basic image information typedef struct { stbi__uint32 img_x, img_y; int img_n, img_out_n; stbi_io_callbacks io; void *io_user_data; int read_from_callbacks; int buflen; stbi_uc buffer_start[128]; int callback_already_read; stbi_uc *img_buffer, *img_buffer_end; stbi_uc *img_buffer_original, *img_buffer_original_end; } stbi__context; static void stbi__refill_buffer(stbi__context *s); // initialize a memory-decode context static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) { s->io.read = NULL; s->read_from_callbacks = 0; s->callback_already_read = 0; s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; } // initialize a callback-based context static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) { s->io = *c; s->io_user_data = user; s->buflen = sizeof(s->buffer_start); s->read_from_callbacks = 1; s->callback_already_read = 0; s->img_buffer = s->img_buffer_original = s->buffer_start; stbi__refill_buffer(s); s->img_buffer_original_end = s->img_buffer_end; } #ifndef STBI_NO_STDIO static int stbi__stdio_read(void *user, char *data, int size) { return (int) fread(data,1,size,(FILE*) user); } static void stbi__stdio_skip(void *user, int n) { int ch; fseek((FILE*) user, n, SEEK_CUR); ch = fgetc((FILE*) user); /* have to read a byte to reset feof()'s flag */ if (ch != EOF) { ungetc(ch, (FILE *) user); /* push byte back onto stream if valid. */ } } static int stbi__stdio_eof(void *user) { return feof((FILE*) user) || ferror((FILE *) user); } static stbi_io_callbacks stbi__stdio_callbacks = { stbi__stdio_read, stbi__stdio_skip, stbi__stdio_eof, }; static void stbi__start_file(stbi__context *s, FILE *f) { stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); } //static void stop_file(stbi__context *s) { } #endif // !STBI_NO_STDIO static void stbi__rewind(stbi__context *s) { // conceptually rewind SHOULD rewind to the beginning of the stream, // but we just rewind to the beginning of the initial buffer, because // we only use it after doing 'test', which only ever looks at at most 92 bytes s->img_buffer = s->img_buffer_original; s->img_buffer_end = s->img_buffer_original_end; } enum { STBI_ORDER_RGB, STBI_ORDER_BGR }; typedef struct { int bits_per_channel; int num_channels; int channel_order; } stbi__result_info; #ifndef STBI_NO_JPEG static int stbi__jpeg_test(stbi__context *s); static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_PNG static int stbi__png_test(stbi__context *s); static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); static int stbi__png_is16(stbi__context *s); #endif #ifndef STBI_NO_BMP static int stbi__bmp_test(stbi__context *s); static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_TGA static int stbi__tga_test(stbi__context *s); static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_PSD static int stbi__psd_test(stbi__context *s); static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); static int stbi__psd_is16(stbi__context *s); #endif #ifndef STBI_NO_HDR static int stbi__hdr_test(stbi__context *s); static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_PIC static int stbi__pic_test(stbi__context *s); static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_GIF static int stbi__gif_test(stbi__context *s); static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); #endif #ifndef STBI_NO_PNM static int stbi__pnm_test(stbi__context *s); static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); static int stbi__pnm_is16(stbi__context *s); #endif static #ifdef STBI_THREAD_LOCAL STBI_THREAD_LOCAL #endif const char *stbi__g_failure_reason; STBIDEF const char *stbi_failure_reason(void) { return stbi__g_failure_reason; } #ifndef STBI_NO_FAILURE_STRINGS static int stbi__err(const char *str) { stbi__g_failure_reason = str; return 0; } #endif static void *stbi__malloc(size_t size) { return STBI_MALLOC(size); } // stb_image uses ints pervasively, including for offset calculations. // therefore the largest decoded image size we can support with the // current code, even on 64-bit targets, is INT_MAX. this is not a // significant limitation for the intended use case. // // we do, however, need to make sure our size calculations don't // overflow. hence a few helper functions for size calculations that // multiply integers together, making sure that they're non-negative // and no overflow occurs. // return 1 if the sum is valid, 0 on overflow. // negative terms are considered invalid. static int stbi__addsizes_valid(int a, int b) { if (b < 0) return 0; // now 0 <= b <= INT_MAX, hence also // 0 <= INT_MAX - b <= INTMAX. // And "a + b <= INT_MAX" (which might overflow) is the // same as a <= INT_MAX - b (no overflow) return a <= INT_MAX - b; } // returns 1 if the product is valid, 0 on overflow. // negative factors are considered invalid. static int stbi__mul2sizes_valid(int a, int b) { if (a < 0 || b < 0) return 0; if (b == 0) return 1; // mul-by-0 is always safe // portable way to check for no overflows in a*b return a <= INT_MAX/b; } #if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) // returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow static int stbi__mad2sizes_valid(int a, int b, int add) { return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); } #endif // returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow static int stbi__mad3sizes_valid(int a, int b, int c, int add) { return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && stbi__addsizes_valid(a*b*c, add); } // returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow #if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) { return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); } #endif #if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) // mallocs with size overflow checking static void *stbi__malloc_mad2(int a, int b, int add) { if (!stbi__mad2sizes_valid(a, b, add)) return NULL; return stbi__malloc(a*b + add); } #endif static void *stbi__malloc_mad3(int a, int b, int c, int add) { if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; return stbi__malloc(a*b*c + add); } #if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) { if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; return stbi__malloc(a*b*c*d + add); } #endif // returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow. static int stbi__addints_valid(int a, int b) { if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0. return a <= INT_MAX - b; } // returns 1 if the product of two signed shorts is valid, 0 on overflow. static int stbi__mul2shorts_valid(short a, short b) { if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN return a >= SHRT_MIN / b; } // stbi__err - error // stbi__errpf - error returning pointer to float // stbi__errpuc - error returning pointer to unsigned char #ifdef STBI_NO_FAILURE_STRINGS #define stbi__err(x,y) 0 #elif defined(STBI_FAILURE_USERMSG) #define stbi__err(x,y) stbi__err(y) #else #define stbi__err(x,y) stbi__err(x) #endif #define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) #define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) STBIDEF void stbi_image_free(void *retval_from_stbi_load) { STBI_FREE(retval_from_stbi_load); } #ifndef STBI_NO_LINEAR static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); #endif #ifndef STBI_NO_HDR static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); #endif static int stbi__vertically_flip_on_load_global = 0; STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) { stbi__vertically_flip_on_load_global = flag_true_if_should_flip; } #ifndef STBI_THREAD_LOCAL #define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global #else static STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set; STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip) { stbi__vertically_flip_on_load_local = flag_true_if_should_flip; stbi__vertically_flip_on_load_set = 1; } #define stbi__vertically_flip_on_load (stbi__vertically_flip_on_load_set \ ? stbi__vertically_flip_on_load_local \ : stbi__vertically_flip_on_load_global) #endif // STBI_THREAD_LOCAL static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) { memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order ri->num_channels = 0; // test the formats with a very explicit header first (at least a FOURCC // or distinctive magic number first) #ifndef STBI_NO_PNG if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_BMP if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_GIF if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_PSD if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); #else STBI_NOTUSED(bpc); #endif #ifndef STBI_NO_PIC if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); #endif // then the formats that can end up attempting to load with just 1 or 2 // bytes matching expectations; these are prone to false positives, so // try them later #ifndef STBI_NO_JPEG if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_PNM if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); #endif #ifndef STBI_NO_HDR if (stbi__hdr_test(s)) { float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); } #endif #ifndef STBI_NO_TGA // test tga last because it's a crappy test! if (stbi__tga_test(s)) return stbi__tga_load(s,x,y,comp,req_comp, ri); #endif return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); } static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) { int i; int img_len = w * h * channels; stbi_uc *reduced; reduced = (stbi_uc *) stbi__malloc(img_len); if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); for (i = 0; i < img_len; ++i) reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling STBI_FREE(orig); return reduced; } static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) { int i; int img_len = w * h * channels; stbi__uint16 *enlarged; enlarged = (stbi__uint16 *) stbi__malloc(img_len*2); if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); for (i = 0; i < img_len; ++i) enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff STBI_FREE(orig); return enlarged; } static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) { int row; size_t bytes_per_row = (size_t)w * bytes_per_pixel; stbi_uc temp[2048]; stbi_uc *bytes = (stbi_uc *)image; for (row = 0; row < (h>>1); row++) { stbi_uc *row0 = bytes + row*bytes_per_row; stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; // swap row0 with row1 size_t bytes_left = bytes_per_row; while (bytes_left) { size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); memcpy(temp, row0, bytes_copy); memcpy(row0, row1, bytes_copy); memcpy(row1, temp, bytes_copy); row0 += bytes_copy; row1 += bytes_copy; bytes_left -= bytes_copy; } } } #ifndef STBI_NO_GIF static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) { int slice; int slice_size = w * h * bytes_per_pixel; stbi_uc *bytes = (stbi_uc *)image; for (slice = 0; slice < z; ++slice) { stbi__vertical_flip(bytes, w, h, bytes_per_pixel); bytes += slice_size; } } #endif static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) { stbi__result_info ri; void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); if (result == NULL) return NULL; // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); if (ri.bits_per_channel != 8) { result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); ri.bits_per_channel = 8; } // @TODO: move stbi__convert_format to here if (stbi__vertically_flip_on_load) { int channels = req_comp ? req_comp : *comp; stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); } return (unsigned char *) result; } static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) { stbi__result_info ri; void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); if (result == NULL) return NULL; // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); if (ri.bits_per_channel != 16) { result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); ri.bits_per_channel = 16; } // @TODO: move stbi__convert_format16 to here // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision if (stbi__vertically_flip_on_load) { int channels = req_comp ? req_comp : *comp; stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); } return (stbi__uint16 *) result; } #if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR) static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) { if (stbi__vertically_flip_on_load && result != NULL) { int channels = req_comp ? req_comp : *comp; stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); } } #endif #ifndef STBI_NO_STDIO #if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); #endif #if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) { return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); } #endif static FILE *stbi__fopen(char const *filename, char const *mode) { FILE *f; #if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) wchar_t wMode[64]; wchar_t wFilename[1024]; if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) return 0; if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) return 0; #if defined(_MSC_VER) && _MSC_VER >= 1400 if (0 != _wfopen_s(&f, wFilename, wMode)) f = 0; #else f = _wfopen(wFilename, wMode); #endif #elif defined(_MSC_VER) && _MSC_VER >= 1400 if (0 != fopen_s(&f, filename, mode)) f=0; #else f = fopen(filename, mode); #endif return f; } STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) { FILE *f = stbi__fopen(filename, "rb"); unsigned char *result; if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); result = stbi_load_from_file(f,x,y,comp,req_comp); fclose(f); return result; } STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) { unsigned char *result; stbi__context s; stbi__start_file(&s,f); result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); if (result) { // need to 'unget' all the characters in the IO buffer fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); } return result; } STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) { stbi__uint16 *result; stbi__context s; stbi__start_file(&s,f); result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); if (result) { // need to 'unget' all the characters in the IO buffer fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); } return result; } STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) { FILE *f = stbi__fopen(filename, "rb"); stbi__uint16 *result; if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); result = stbi_load_from_file_16(f,x,y,comp,req_comp); fclose(f); return result; } #endif //!STBI_NO_STDIO STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) { stbi__context s; stbi__start_mem(&s,buffer,len); return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); } STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) { stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); } STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_mem(&s,buffer,len); return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); } STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); } #ifndef STBI_NO_GIF STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) { unsigned char *result; stbi__context s; stbi__start_mem(&s,buffer,len); result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); if (stbi__vertically_flip_on_load) { stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); } return result; } #endif #ifndef STBI_NO_LINEAR static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) { unsigned char *data; #ifndef STBI_NO_HDR if (stbi__hdr_test(s)) { stbi__result_info ri; float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); if (hdr_data) stbi__float_postprocess(hdr_data,x,y,comp,req_comp); return hdr_data; } #endif data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); if (data) return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); } STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_mem(&s,buffer,len); return stbi__loadf_main(&s,x,y,comp,req_comp); } STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); return stbi__loadf_main(&s,x,y,comp,req_comp); } #ifndef STBI_NO_STDIO STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) { float *result; FILE *f = stbi__fopen(filename, "rb"); if (!f) return stbi__errpf("can't fopen", "Unable to open file"); result = stbi_loadf_from_file(f,x,y,comp,req_comp); fclose(f); return result; } STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) { stbi__context s; stbi__start_file(&s,f); return stbi__loadf_main(&s,x,y,comp,req_comp); } #endif // !STBI_NO_STDIO #endif // !STBI_NO_LINEAR // these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is // defined, for API simplicity; if STBI_NO_LINEAR is defined, it always // reports false! STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) { #ifndef STBI_NO_HDR stbi__context s; stbi__start_mem(&s,buffer,len); return stbi__hdr_test(&s); #else STBI_NOTUSED(buffer); STBI_NOTUSED(len); return 0; #endif } #ifndef STBI_NO_STDIO STBIDEF int stbi_is_hdr (char const *filename) { FILE *f = stbi__fopen(filename, "rb"); int result=0; if (f) { result = stbi_is_hdr_from_file(f); fclose(f); } return result; } STBIDEF int stbi_is_hdr_from_file(FILE *f) { #ifndef STBI_NO_HDR long pos = ftell(f); int res; stbi__context s; stbi__start_file(&s,f); res = stbi__hdr_test(&s); fseek(f, pos, SEEK_SET); return res; #else STBI_NOTUSED(f); return 0; #endif } #endif // !STBI_NO_STDIO STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) { #ifndef STBI_NO_HDR stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); return stbi__hdr_test(&s); #else STBI_NOTUSED(clbk); STBI_NOTUSED(user); return 0; #endif } #ifndef STBI_NO_LINEAR static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } #endif static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } ////////////////////////////////////////////////////////////////////////////// // // Common code used by all image loaders // enum { STBI__SCAN_load=0, STBI__SCAN_type, STBI__SCAN_header }; static void stbi__refill_buffer(stbi__context *s) { int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); s->callback_already_read += (int) (s->img_buffer - s->img_buffer_original); if (n == 0) { // at end of file, treat same as if from memory, but need to handle case // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file s->read_from_callbacks = 0; s->img_buffer = s->buffer_start; s->img_buffer_end = s->buffer_start+1; *s->img_buffer = 0; } else { s->img_buffer = s->buffer_start; s->img_buffer_end = s->buffer_start + n; } } stbi_inline static stbi_uc stbi__get8(stbi__context *s) { if (s->img_buffer < s->img_buffer_end) return *s->img_buffer++; if (s->read_from_callbacks) { stbi__refill_buffer(s); return *s->img_buffer++; } return 0; } #if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) // nothing #else stbi_inline static int stbi__at_eof(stbi__context *s) { if (s->io.read) { if (!(s->io.eof)(s->io_user_data)) return 0; // if feof() is true, check if buffer = end // special case: we've only got the special 0 character at the end if (s->read_from_callbacks == 0) return 1; } return s->img_buffer >= s->img_buffer_end; } #endif #if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) // nothing #else static void stbi__skip(stbi__context *s, int n) { if (n == 0) return; // already there! if (n < 0) { s->img_buffer = s->img_buffer_end; return; } if (s->io.read) { int blen = (int) (s->img_buffer_end - s->img_buffer); if (blen < n) { s->img_buffer = s->img_buffer_end; (s->io.skip)(s->io_user_data, n - blen); return; } } s->img_buffer += n; } #endif #if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM) // nothing #else static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) { if (s->io.read) { int blen = (int) (s->img_buffer_end - s->img_buffer); if (blen < n) { int res, count; memcpy(buffer, s->img_buffer, blen); count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); res = (count == (n-blen)); s->img_buffer = s->img_buffer_end; return res; } } if (s->img_buffer+n <= s->img_buffer_end) { memcpy(buffer, s->img_buffer, n); s->img_buffer += n; return 1; } else return 0; } #endif #if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) // nothing #else static int stbi__get16be(stbi__context *s) { int z = stbi__get8(s); return (z << 8) + stbi__get8(s); } #endif #if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) // nothing #else static stbi__uint32 stbi__get32be(stbi__context *s) { stbi__uint32 z = stbi__get16be(s); return (z << 16) + stbi__get16be(s); } #endif #if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) // nothing #else static int stbi__get16le(stbi__context *s) { int z = stbi__get8(s); return z + (stbi__get8(s) << 8); } #endif #ifndef STBI_NO_BMP static stbi__uint32 stbi__get32le(stbi__context *s) { stbi__uint32 z = stbi__get16le(s); z += (stbi__uint32)stbi__get16le(s) << 16; return z; } #endif #define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings #if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) // nothing #else ////////////////////////////////////////////////////////////////////////////// // // generic converter from built-in img_n to req_comp // individual types do this automatically as much as possible (e.g. jpeg // does all cases internally since it needs to colorspace convert anyway, // and it never has alpha, so very few cases ). png can automatically // interleave an alpha=255 channel, but falls back to this for other cases // // assume data buffer is malloced, so malloc a new one and free that one // only failure mode is malloc failing static stbi_uc stbi__compute_y(int r, int g, int b) { return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); } #endif #if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) // nothing #else static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) { int i,j; unsigned char *good; if (req_comp == img_n) return data; STBI_ASSERT(req_comp >= 1 && req_comp <= 4); good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); if (good == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } for (j=0; j < (int) y; ++j) { unsigned char *src = data + j * x * img_n ; unsigned char *dest = good + j * x * req_comp; #define STBI__COMBO(a,b) ((a)*8+(b)) #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) // convert source image with img_n components to one with req_comp components; // avoid switch per pixel, so use switch per scanline and massive macros switch (STBI__COMBO(img_n, req_comp)) { STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=255; } break; STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=255; } break; STBI__CASE(2,1) { dest[0]=src[0]; } break; STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=255; } break; STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = 255; } break; STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break; STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion"); } #undef STBI__CASE } STBI_FREE(data); return good; } #endif #if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) // nothing #else static stbi__uint16 stbi__compute_y_16(int r, int g, int b) { return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); } #endif #if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) // nothing #else static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) { int i,j; stbi__uint16 *good; if (req_comp == img_n) return data; STBI_ASSERT(req_comp >= 1 && req_comp <= 4); good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); if (good == NULL) { STBI_FREE(data); return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); } for (j=0; j < (int) y; ++j) { stbi__uint16 *src = data + j * x * img_n ; stbi__uint16 *dest = good + j * x * req_comp; #define STBI__COMBO(a,b) ((a)*8+(b)) #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) // convert source image with img_n components to one with req_comp components; // avoid switch per pixel, so use switch per scanline and massive macros switch (STBI__COMBO(img_n, req_comp)) { STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=0xffff; } break; STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=0xffff; } break; STBI__CASE(2,1) { dest[0]=src[0]; } break; STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=0xffff; } break; STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = 0xffff; } break; STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break; STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion"); } #undef STBI__CASE } STBI_FREE(data); return good; } #endif #ifndef STBI_NO_LINEAR static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) { int i,k,n; float *output; if (!data) return NULL; output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } // compute number of non-alpha components if (comp & 1) n = comp; else n = comp-1; for (i=0; i < x*y; ++i) { for (k=0; k < n; ++k) { output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); } } if (n < comp) { for (i=0; i < x*y; ++i) { output[i*comp + n] = data[i*comp + n]/255.0f; } } STBI_FREE(data); return output; } #endif #ifndef STBI_NO_HDR #define stbi__float2int(x) ((int) (x)) static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) { int i,k,n; stbi_uc *output; if (!data) return NULL; output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } // compute number of non-alpha components if (comp & 1) n = comp; else n = comp-1; for (i=0; i < x*y; ++i) { for (k=0; k < n; ++k) { float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; if (z < 0) z = 0; if (z > 255) z = 255; output[i*comp + k] = (stbi_uc) stbi__float2int(z); } if (k < comp) { float z = data[i*comp+k] * 255 + 0.5f; if (z < 0) z = 0; if (z > 255) z = 255; output[i*comp + k] = (stbi_uc) stbi__float2int(z); } } STBI_FREE(data); return output; } #endif ////////////////////////////////////////////////////////////////////////////// // // "baseline" JPEG/JFIF decoder // // simple implementation // - doesn't support delayed output of y-dimension // - simple interface (only one output format: 8-bit interleaved RGB) // - doesn't try to recover corrupt jpegs // - doesn't allow partial loading, loading multiple at once // - still fast on x86 (copying globals into locals doesn't help x86) // - allocates lots of intermediate memory (full size of all components) // - non-interleaved case requires this anyway // - allows good upsampling (see next) // high-quality // - upsampled channels are bilinearly interpolated, even across blocks // - quality integer IDCT derived from IJG's 'slow' // performance // - fast huffman; reasonable integer IDCT // - some SIMD kernels for common paths on targets with SSE2/NEON // - uses a lot of intermediate memory, could cache poorly #ifndef STBI_NO_JPEG // huffman decoding acceleration #define FAST_BITS 9 // larger handles more cases; smaller stomps less cache typedef struct { stbi_uc fast[1 << FAST_BITS]; // weirdly, repacking this into AoS is a 10% speed loss, instead of a win stbi__uint16 code[256]; stbi_uc values[256]; stbi_uc size[257]; unsigned int maxcode[18]; int delta[17]; // old 'firstsymbol' - old 'firstcode' } stbi__huffman; typedef struct { stbi__context *s; stbi__huffman huff_dc[4]; stbi__huffman huff_ac[4]; stbi__uint16 dequant[4][64]; stbi__int16 fast_ac[4][1 << FAST_BITS]; // sizes for components, interleaved MCUs int img_h_max, img_v_max; int img_mcu_x, img_mcu_y; int img_mcu_w, img_mcu_h; // definition of jpeg image component struct { int id; int h,v; int tq; int hd,ha; int dc_pred; int x,y,w2,h2; stbi_uc *data; void *raw_data, *raw_coeff; stbi_uc *linebuf; short *coeff; // progressive only int coeff_w, coeff_h; // number of 8x8 coefficient blocks } img_comp[4]; stbi__uint32 code_buffer; // jpeg entropy-coded buffer int code_bits; // number of valid bits unsigned char marker; // marker seen while filling entropy buffer int nomore; // flag if we saw a marker so must stop int progressive; int spec_start; int spec_end; int succ_high; int succ_low; int eob_run; int jfif; int app14_color_transform; // Adobe APP14 tag int rgb; int scan_n, order[4]; int restart_interval, todo; // kernels void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); } stbi__jpeg; static int stbi__build_huffman(stbi__huffman *h, int *count) { int i,j,k=0; unsigned int code; // build size list for each symbol (from JPEG spec) for (i=0; i < 16; ++i) { for (j=0; j < count[i]; ++j) { h->size[k++] = (stbi_uc) (i+1); if(k >= 257) return stbi__err("bad size list","Corrupt JPEG"); } } h->size[k] = 0; // compute actual symbols (from jpeg spec) code = 0; k = 0; for(j=1; j <= 16; ++j) { // compute delta to add to code to compute symbol id h->delta[j] = k - code; if (h->size[k] == j) { while (h->size[k] == j) h->code[k++] = (stbi__uint16) (code++); if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); } // compute largest code + 1 for this size, preshifted as needed later h->maxcode[j] = code << (16-j); code <<= 1; } h->maxcode[j] = 0xffffffff; // build non-spec acceleration table; 255 is flag for not-accelerated memset(h->fast, 255, 1 << FAST_BITS); for (i=0; i < k; ++i) { int s = h->size[i]; if (s <= FAST_BITS) { int c = h->code[i] << (FAST_BITS-s); int m = 1 << (FAST_BITS-s); for (j=0; j < m; ++j) { h->fast[c+j] = (stbi_uc) i; } } } return 1; } // build a table that decodes both magnitude and value of small ACs in // one go. static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) { int i; for (i=0; i < (1 << FAST_BITS); ++i) { stbi_uc fast = h->fast[i]; fast_ac[i] = 0; if (fast < 255) { int rs = h->values[fast]; int run = (rs >> 4) & 15; int magbits = rs & 15; int len = h->size[fast]; if (magbits && len + magbits <= FAST_BITS) { // magnitude code followed by receive_extend code int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); int m = 1 << (magbits - 1); if (k < m) k += (~0U << magbits) + 1; // if the result is small enough, we can fit it in fast_ac table if (k >= -128 && k <= 127) fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); } } } } static void stbi__grow_buffer_unsafe(stbi__jpeg *j) { do { unsigned int b = j->nomore ? 0 : stbi__get8(j->s); if (b == 0xff) { int c = stbi__get8(j->s); while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes if (c != 0) { j->marker = (unsigned char) c; j->nomore = 1; return; } } j->code_buffer |= b << (24 - j->code_bits); j->code_bits += 8; } while (j->code_bits <= 24); } // (1 << n) - 1 static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; // decode a jpeg huffman value from the bitstream stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) { unsigned int temp; int c,k; if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); // look at the top FAST_BITS and determine what symbol ID it is, // if the code is <= FAST_BITS c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); k = h->fast[c]; if (k < 255) { int s = h->size[k]; if (s > j->code_bits) return -1; j->code_buffer <<= s; j->code_bits -= s; return h->values[k]; } // naive test is to shift the code_buffer down so k bits are // valid, then test against maxcode. To speed this up, we've // preshifted maxcode left so that it has (16-k) 0s at the // end; in other words, regardless of the number of bits, it // wants to be compared against something shifted to have 16; // that way we don't need to shift inside the loop. temp = j->code_buffer >> 16; for (k=FAST_BITS+1 ; ; ++k) if (temp < h->maxcode[k]) break; if (k == 17) { // error! code not found j->code_bits -= 16; return -1; } if (k > j->code_bits) return -1; // convert the huffman code to the symbol id c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; if(c < 0 || c >= 256) // symbol id out of bounds! return -1; STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); // convert the id to a symbol j->code_bits -= k; j->code_buffer <<= k; return h->values[c]; } // bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative) k = stbi_lrot(j->code_buffer, n); j->code_buffer = k & ~stbi__bmask[n]; k &= stbi__bmask[n]; j->code_bits -= n; return k + (stbi__jbias[n] & (sgn - 1)); } // get some unsigned bits stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) { unsigned int k; if (j->code_bits < n) stbi__grow_buffer_unsafe(j); if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing k = stbi_lrot(j->code_buffer, n); j->code_buffer = k & ~stbi__bmask[n]; k &= stbi__bmask[n]; j->code_bits -= n; return k; } stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) { unsigned int k; if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing k = j->code_buffer; j->code_buffer <<= 1; --j->code_bits; return k & 0x80000000; } // given a value that's at position X in the zigzag stream, // where does it appear in the 8x8 matrix coded as row-major? static const stbi_uc stbi__jpeg_dezigzag[64+15] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63, // let corrupt input sample past end 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 }; // decode one 64-entry block-- static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) { int diff,dc,k; int t; if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); t = stbi__jpeg_huff_decode(j, hdc); if (t < 0 || t > 15) return stbi__err("bad huffman code","Corrupt JPEG"); // 0 all the ac values now so we can do it 32-bits at a time memset(data,0,64*sizeof(data[0])); diff = t ? stbi__extend_receive(j, t) : 0; if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG"); dc = j->img_comp[b].dc_pred + diff; j->img_comp[b].dc_pred = dc; if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); data[0] = (short) (dc * dequant[0]); // decode AC components, see JPEG spec k = 1; do { unsigned int zig; int c,r,s; if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); r = fac[c]; if (r) { // fast-AC path k += (r >> 4) & 15; // run s = r & 15; // combined length if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); j->code_buffer <<= s; j->code_bits -= s; // decode into unzigzag'd location zig = stbi__jpeg_dezigzag[k++]; data[zig] = (short) ((r >> 8) * dequant[zig]); } else { int rs = stbi__jpeg_huff_decode(j, hac); if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); s = rs & 15; r = rs >> 4; if (s == 0) { if (rs != 0xf0) break; // end block k += 16; } else { k += r; // decode into unzigzag'd location zig = stbi__jpeg_dezigzag[k++]; data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); } } } while (k < 64); return 1; } static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) { int diff,dc; int t; if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); if (j->succ_high == 0) { // first scan for DC coefficient, must be first memset(data,0,64*sizeof(data[0])); // 0 all the ac values now t = stbi__jpeg_huff_decode(j, hdc); if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); diff = t ? stbi__extend_receive(j, t) : 0; if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG"); dc = j->img_comp[b].dc_pred + diff; j->img_comp[b].dc_pred = dc; if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); data[0] = (short) (dc * (1 << j->succ_low)); } else { // refinement scan for DC coefficient if (stbi__jpeg_get_bit(j)) data[0] += (short) (1 << j->succ_low); } return 1; } // @OPTIMIZE: store non-zigzagged during the decode passes, // and only de-zigzag when dequantizing static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) { int k; if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); if (j->succ_high == 0) { int shift = j->succ_low; if (j->eob_run) { --j->eob_run; return 1; } k = j->spec_start; do { unsigned int zig; int c,r,s; if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); r = fac[c]; if (r) { // fast-AC path k += (r >> 4) & 15; // run s = r & 15; // combined length if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); j->code_buffer <<= s; j->code_bits -= s; zig = stbi__jpeg_dezigzag[k++]; data[zig] = (short) ((r >> 8) * (1 << shift)); } else { int rs = stbi__jpeg_huff_decode(j, hac); if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); s = rs & 15; r = rs >> 4; if (s == 0) { if (r < 15) { j->eob_run = (1 << r); if (r) j->eob_run += stbi__jpeg_get_bits(j, r); --j->eob_run; break; } k += 16; } else { k += r; zig = stbi__jpeg_dezigzag[k++]; data[zig] = (short) (stbi__extend_receive(j,s) * (1 << shift)); } } } while (k <= j->spec_end); } else { // refinement scan for these AC coefficients short bit = (short) (1 << j->succ_low); if (j->eob_run) { --j->eob_run; for (k = j->spec_start; k <= j->spec_end; ++k) { short *p = &data[stbi__jpeg_dezigzag[k]]; if (*p != 0) if (stbi__jpeg_get_bit(j)) if ((*p & bit)==0) { if (*p > 0) *p += bit; else *p -= bit; } } } else { k = j->spec_start; do { int r,s; int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); s = rs & 15; r = rs >> 4; if (s == 0) { if (r < 15) { j->eob_run = (1 << r) - 1; if (r) j->eob_run += stbi__jpeg_get_bits(j, r); r = 64; // force end of block } else { // r=15 s=0 should write 16 0s, so we just do // a run of 15 0s and then write s (which is 0), // so we don't have to do anything special here } } else { if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); // sign bit if (stbi__jpeg_get_bit(j)) s = bit; else s = -bit; } // advance by r while (k <= j->spec_end) { short *p = &data[stbi__jpeg_dezigzag[k++]]; if (*p != 0) { if (stbi__jpeg_get_bit(j)) if ((*p & bit)==0) { if (*p > 0) *p += bit; else *p -= bit; } } else { if (r == 0) { *p = (short) s; break; } --r; } } } while (k <= j->spec_end); } } return 1; } // take a -128..127 value and stbi__clamp it and convert to 0..255 stbi_inline static stbi_uc stbi__clamp(int x) { // trick to use a single test to catch both cases if ((unsigned int) x > 255) { if (x < 0) return 0; if (x > 255) return 255; } return (stbi_uc) x; } #define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) #define stbi__fsh(x) ((x) * 4096) // derived from jidctint -- DCT_ISLOW #define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ p2 = s2; \ p3 = s6; \ p1 = (p2+p3) * stbi__f2f(0.5411961f); \ t2 = p1 + p3*stbi__f2f(-1.847759065f); \ t3 = p1 + p2*stbi__f2f( 0.765366865f); \ p2 = s0; \ p3 = s4; \ t0 = stbi__fsh(p2+p3); \ t1 = stbi__fsh(p2-p3); \ x0 = t0+t3; \ x3 = t0-t3; \ x1 = t1+t2; \ x2 = t1-t2; \ t0 = s7; \ t1 = s5; \ t2 = s3; \ t3 = s1; \ p3 = t0+t2; \ p4 = t1+t3; \ p1 = t0+t3; \ p2 = t1+t2; \ p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ t0 = t0*stbi__f2f( 0.298631336f); \ t1 = t1*stbi__f2f( 2.053119869f); \ t2 = t2*stbi__f2f( 3.072711026f); \ t3 = t3*stbi__f2f( 1.501321110f); \ p1 = p5 + p1*stbi__f2f(-0.899976223f); \ p2 = p5 + p2*stbi__f2f(-2.562915447f); \ p3 = p3*stbi__f2f(-1.961570560f); \ p4 = p4*stbi__f2f(-0.390180644f); \ t3 += p1+p4; \ t2 += p2+p3; \ t1 += p2+p4; \ t0 += p1+p3; static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) { int i,val[64],*v=val; stbi_uc *o; short *d = data; // columns for (i=0; i < 8; ++i,++d, ++v) { // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 && d[40]==0 && d[48]==0 && d[56]==0) { // no shortcut 0 seconds // (1|2|3|4|5|6|7)==0 0 seconds // all separate -0.047 seconds // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds int dcterm = d[0]*4; v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; } else { STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) // constants scaled things up by 1<<12; let's bring them back // down, but keep 2 extra bits of precision x0 += 512; x1 += 512; x2 += 512; x3 += 512; v[ 0] = (x0+t3) >> 10; v[56] = (x0-t3) >> 10; v[ 8] = (x1+t2) >> 10; v[48] = (x1-t2) >> 10; v[16] = (x2+t1) >> 10; v[40] = (x2-t1) >> 10; v[24] = (x3+t0) >> 10; v[32] = (x3-t0) >> 10; } } for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { // no fast case since the first 1D IDCT spread components out STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) // constants scaled things up by 1<<12, plus we had 1<<2 from first // loop, plus horizontal and vertical each scale by sqrt(8) so together // we've got an extra 1<<3, so 1<<17 total we need to remove. // so we want to round that, which means adding 0.5 * 1<<17, // aka 65536. Also, we'll end up with -128 to 127 that we want // to encode as 0..255 by adding 128, so we'll add that before the shift x0 += 65536 + (128<<17); x1 += 65536 + (128<<17); x2 += 65536 + (128<<17); x3 += 65536 + (128<<17); // tried computing the shifts into temps, or'ing the temps to see // if any were out of range, but that was slower o[0] = stbi__clamp((x0+t3) >> 17); o[7] = stbi__clamp((x0-t3) >> 17); o[1] = stbi__clamp((x1+t2) >> 17); o[6] = stbi__clamp((x1-t2) >> 17); o[2] = stbi__clamp((x2+t1) >> 17); o[5] = stbi__clamp((x2-t1) >> 17); o[3] = stbi__clamp((x3+t0) >> 17); o[4] = stbi__clamp((x3-t0) >> 17); } } #ifdef STBI_SSE2 // sse2 integer IDCT. not the fastest possible implementation but it // produces bit-identical results to the generic C version so it's // fully "transparent". static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) { // This is constructed to match our regular (generic) integer IDCT exactly. __m128i row0, row1, row2, row3, row4, row5, row6, row7; __m128i tmp; // dot product constant: even elems=x, odd elems=y #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) // out(1) = c1[even]*x + c1[odd]*y #define dct_rot(out0,out1, x,y,c0,c1) \ __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) // out = in << 12 (in 16-bit, out 32-bit) #define dct_widen(out, in) \ __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) // wide add #define dct_wadd(out, a, b) \ __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ __m128i out##_h = _mm_add_epi32(a##_h, b##_h) // wide sub #define dct_wsub(out, a, b) \ __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) // butterfly a/b, add bias, then shift by "s" and pack #define dct_bfly32o(out0, out1, a,b,bias,s) \ { \ __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ dct_wadd(sum, abiased, b); \ dct_wsub(dif, abiased, b); \ out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ } // 8-bit interleave step (for transposes) #define dct_interleave8(a, b) \ tmp = a; \ a = _mm_unpacklo_epi8(a, b); \ b = _mm_unpackhi_epi8(tmp, b) // 16-bit interleave step (for transposes) #define dct_interleave16(a, b) \ tmp = a; \ a = _mm_unpacklo_epi16(a, b); \ b = _mm_unpackhi_epi16(tmp, b) #define dct_pass(bias,shift) \ { \ /* even part */ \ dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ __m128i sum04 = _mm_add_epi16(row0, row4); \ __m128i dif04 = _mm_sub_epi16(row0, row4); \ dct_widen(t0e, sum04); \ dct_widen(t1e, dif04); \ dct_wadd(x0, t0e, t3e); \ dct_wsub(x3, t0e, t3e); \ dct_wadd(x1, t1e, t2e); \ dct_wsub(x2, t1e, t2e); \ /* odd part */ \ dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ __m128i sum17 = _mm_add_epi16(row1, row7); \ __m128i sum35 = _mm_add_epi16(row3, row5); \ dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ dct_wadd(x4, y0o, y4o); \ dct_wadd(x5, y1o, y5o); \ dct_wadd(x6, y2o, y5o); \ dct_wadd(x7, y3o, y4o); \ dct_bfly32o(row0,row7, x0,x7,bias,shift); \ dct_bfly32o(row1,row6, x1,x6,bias,shift); \ dct_bfly32o(row2,row5, x2,x5,bias,shift); \ dct_bfly32o(row3,row4, x3,x4,bias,shift); \ } __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); // rounding biases in column/row passes, see stbi__idct_block for explanation. __m128i bias_0 = _mm_set1_epi32(512); __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); // load row0 = _mm_load_si128((const __m128i *) (data + 0*8)); row1 = _mm_load_si128((const __m128i *) (data + 1*8)); row2 = _mm_load_si128((const __m128i *) (data + 2*8)); row3 = _mm_load_si128((const __m128i *) (data + 3*8)); row4 = _mm_load_si128((const __m128i *) (data + 4*8)); row5 = _mm_load_si128((const __m128i *) (data + 5*8)); row6 = _mm_load_si128((const __m128i *) (data + 6*8)); row7 = _mm_load_si128((const __m128i *) (data + 7*8)); // column pass dct_pass(bias_0, 10); { // 16bit 8x8 transpose pass 1 dct_interleave16(row0, row4); dct_interleave16(row1, row5); dct_interleave16(row2, row6); dct_interleave16(row3, row7); // transpose pass 2 dct_interleave16(row0, row2); dct_interleave16(row1, row3); dct_interleave16(row4, row6); dct_interleave16(row5, row7); // transpose pass 3 dct_interleave16(row0, row1); dct_interleave16(row2, row3); dct_interleave16(row4, row5); dct_interleave16(row6, row7); } // row pass dct_pass(bias_1, 17); { // pack __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 __m128i p1 = _mm_packus_epi16(row2, row3); __m128i p2 = _mm_packus_epi16(row4, row5); __m128i p3 = _mm_packus_epi16(row6, row7); // 8bit 8x8 transpose pass 1 dct_interleave8(p0, p2); // a0e0a1e1... dct_interleave8(p1, p3); // c0g0c1g1... // transpose pass 2 dct_interleave8(p0, p1); // a0c0e0g0... dct_interleave8(p2, p3); // b0d0f0h0... // transpose pass 3 dct_interleave8(p0, p2); // a0b0c0d0... dct_interleave8(p1, p3); // a4b4c4d4... // store _mm_storel_epi64((__m128i *) out, p0); out += out_stride; _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; _mm_storel_epi64((__m128i *) out, p2); out += out_stride; _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; _mm_storel_epi64((__m128i *) out, p1); out += out_stride; _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; _mm_storel_epi64((__m128i *) out, p3); out += out_stride; _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); } #undef dct_const #undef dct_rot #undef dct_widen #undef dct_wadd #undef dct_wsub #undef dct_bfly32o #undef dct_interleave8 #undef dct_interleave16 #undef dct_pass } #endif // STBI_SSE2 #ifdef STBI_NEON // NEON integer IDCT. should produce bit-identical // results to the generic C version. static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) { int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); #define dct_long_mul(out, inq, coeff) \ int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) #define dct_long_mac(out, acc, inq, coeff) \ int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) #define dct_widen(out, inq) \ int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) // wide add #define dct_wadd(out, a, b) \ int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ int32x4_t out##_h = vaddq_s32(a##_h, b##_h) // wide sub #define dct_wsub(out, a, b) \ int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ int32x4_t out##_h = vsubq_s32(a##_h, b##_h) // butterfly a/b, then shift using "shiftop" by "s" and pack #define dct_bfly32o(out0,out1, a,b,shiftop,s) \ { \ dct_wadd(sum, a, b); \ dct_wsub(dif, a, b); \ out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ } #define dct_pass(shiftop, shift) \ { \ /* even part */ \ int16x8_t sum26 = vaddq_s16(row2, row6); \ dct_long_mul(p1e, sum26, rot0_0); \ dct_long_mac(t2e, p1e, row6, rot0_1); \ dct_long_mac(t3e, p1e, row2, rot0_2); \ int16x8_t sum04 = vaddq_s16(row0, row4); \ int16x8_t dif04 = vsubq_s16(row0, row4); \ dct_widen(t0e, sum04); \ dct_widen(t1e, dif04); \ dct_wadd(x0, t0e, t3e); \ dct_wsub(x3, t0e, t3e); \ dct_wadd(x1, t1e, t2e); \ dct_wsub(x2, t1e, t2e); \ /* odd part */ \ int16x8_t sum15 = vaddq_s16(row1, row5); \ int16x8_t sum17 = vaddq_s16(row1, row7); \ int16x8_t sum35 = vaddq_s16(row3, row5); \ int16x8_t sum37 = vaddq_s16(row3, row7); \ int16x8_t sumodd = vaddq_s16(sum17, sum35); \ dct_long_mul(p5o, sumodd, rot1_0); \ dct_long_mac(p1o, p5o, sum17, rot1_1); \ dct_long_mac(p2o, p5o, sum35, rot1_2); \ dct_long_mul(p3o, sum37, rot2_0); \ dct_long_mul(p4o, sum15, rot2_1); \ dct_wadd(sump13o, p1o, p3o); \ dct_wadd(sump24o, p2o, p4o); \ dct_wadd(sump23o, p2o, p3o); \ dct_wadd(sump14o, p1o, p4o); \ dct_long_mac(x4, sump13o, row7, rot3_0); \ dct_long_mac(x5, sump24o, row5, rot3_1); \ dct_long_mac(x6, sump23o, row3, rot3_2); \ dct_long_mac(x7, sump14o, row1, rot3_3); \ dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ } // load row0 = vld1q_s16(data + 0*8); row1 = vld1q_s16(data + 1*8); row2 = vld1q_s16(data + 2*8); row3 = vld1q_s16(data + 3*8); row4 = vld1q_s16(data + 4*8); row5 = vld1q_s16(data + 5*8); row6 = vld1q_s16(data + 6*8); row7 = vld1q_s16(data + 7*8); // add DC bias row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); // column pass dct_pass(vrshrn_n_s32, 10); // 16bit 8x8 transpose { // these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. // whether compilers actually get this is another story, sadly. #define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } #define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } #define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } // pass 1 dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 dct_trn16(row2, row3); dct_trn16(row4, row5); dct_trn16(row6, row7); // pass 2 dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 dct_trn32(row1, row3); dct_trn32(row4, row6); dct_trn32(row5, row7); // pass 3 dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 dct_trn64(row1, row5); dct_trn64(row2, row6); dct_trn64(row3, row7); #undef dct_trn16 #undef dct_trn32 #undef dct_trn64 } // row pass // vrshrn_n_s32 only supports shifts up to 16, we need // 17. so do a non-rounding shift of 16 first then follow // up with a rounding shift by 1. dct_pass(vshrn_n_s32, 16); { // pack and round uint8x8_t p0 = vqrshrun_n_s16(row0, 1); uint8x8_t p1 = vqrshrun_n_s16(row1, 1); uint8x8_t p2 = vqrshrun_n_s16(row2, 1); uint8x8_t p3 = vqrshrun_n_s16(row3, 1); uint8x8_t p4 = vqrshrun_n_s16(row4, 1); uint8x8_t p5 = vqrshrun_n_s16(row5, 1); uint8x8_t p6 = vqrshrun_n_s16(row6, 1); uint8x8_t p7 = vqrshrun_n_s16(row7, 1); // again, these can translate into one instruction, but often don't. #define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } #define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } #define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } // sadly can't use interleaved stores here since we only write // 8 bytes to each scan line! // 8x8 8-bit transpose pass 1 dct_trn8_8(p0, p1); dct_trn8_8(p2, p3); dct_trn8_8(p4, p5); dct_trn8_8(p6, p7); // pass 2 dct_trn8_16(p0, p2); dct_trn8_16(p1, p3); dct_trn8_16(p4, p6); dct_trn8_16(p5, p7); // pass 3 dct_trn8_32(p0, p4); dct_trn8_32(p1, p5); dct_trn8_32(p2, p6); dct_trn8_32(p3, p7); // store vst1_u8(out, p0); out += out_stride; vst1_u8(out, p1); out += out_stride; vst1_u8(out, p2); out += out_stride; vst1_u8(out, p3); out += out_stride; vst1_u8(out, p4); out += out_stride; vst1_u8(out, p5); out += out_stride; vst1_u8(out, p6); out += out_stride; vst1_u8(out, p7); #undef dct_trn8_8 #undef dct_trn8_16 #undef dct_trn8_32 } #undef dct_long_mul #undef dct_long_mac #undef dct_widen #undef dct_wadd #undef dct_wsub #undef dct_bfly32o #undef dct_pass } #endif // STBI_NEON #define STBI__MARKER_none 0xff // if there's a pending marker from the entropy stream, return that // otherwise, fetch from the stream and get a marker. if there's no // marker, return 0xff, which is never a valid marker value static stbi_uc stbi__get_marker(stbi__jpeg *j) { stbi_uc x; if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } x = stbi__get8(j->s); if (x != 0xff) return STBI__MARKER_none; while (x == 0xff) x = stbi__get8(j->s); // consume repeated 0xff fill bytes return x; } // in each scan, we'll have scan_n components, and the order // of the components is specified by order[] #define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) // after a restart interval, stbi__jpeg_reset the entropy decoder and // the dc prediction static void stbi__jpeg_reset(stbi__jpeg *j) { j->code_bits = 0; j->code_buffer = 0; j->nomore = 0; j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; j->marker = STBI__MARKER_none; j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; j->eob_run = 0; // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, // since we don't even allow 1<<30 pixels } static int stbi__parse_entropy_coded_data(stbi__jpeg *z) { stbi__jpeg_reset(z); if (!z->progressive) { if (z->scan_n == 1) { int i,j; STBI_SIMD_ALIGN(short, data[64]); int n = z->order[0]; // non-interleaved data, we just need to process one block at a time, // in trivial scanline order // number of blocks to do just depends on how many actual "pixels" this // component has, independent of interleaved MCU blocking and such int w = (z->img_comp[n].x+7) >> 3; int h = (z->img_comp[n].y+7) >> 3; for (j=0; j < h; ++j) { for (i=0; i < w; ++i) { int ha = z->img_comp[n].ha; if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); // every data block is an MCU, so countdown the restart interval if (--z->todo <= 0) { if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); // if it's NOT a restart, then just bail, so we get corrupt data // rather than no data if (!STBI__RESTART(z->marker)) return 1; stbi__jpeg_reset(z); } } } return 1; } else { // interleaved int i,j,k,x,y; STBI_SIMD_ALIGN(short, data[64]); for (j=0; j < z->img_mcu_y; ++j) { for (i=0; i < z->img_mcu_x; ++i) { // scan an interleaved mcu... process scan_n components in order for (k=0; k < z->scan_n; ++k) { int n = z->order[k]; // scan out an mcu's worth of this component; that's just determined // by the basic H and V specified for the component for (y=0; y < z->img_comp[n].v; ++y) { for (x=0; x < z->img_comp[n].h; ++x) { int x2 = (i*z->img_comp[n].h + x)*8; int y2 = (j*z->img_comp[n].v + y)*8; int ha = z->img_comp[n].ha; if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); } } } // after all interleaved components, that's an interleaved MCU, // so now count down the restart interval if (--z->todo <= 0) { if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); if (!STBI__RESTART(z->marker)) return 1; stbi__jpeg_reset(z); } } } return 1; } } else { if (z->scan_n == 1) { int i,j; int n = z->order[0]; // non-interleaved data, we just need to process one block at a time, // in trivial scanline order // number of blocks to do just depends on how many actual "pixels" this // component has, independent of interleaved MCU blocking and such int w = (z->img_comp[n].x+7) >> 3; int h = (z->img_comp[n].y+7) >> 3; for (j=0; j < h; ++j) { for (i=0; i < w; ++i) { short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); if (z->spec_start == 0) { if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) return 0; } else { int ha = z->img_comp[n].ha; if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) return 0; } // every data block is an MCU, so countdown the restart interval if (--z->todo <= 0) { if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); if (!STBI__RESTART(z->marker)) return 1; stbi__jpeg_reset(z); } } } return 1; } else { // interleaved int i,j,k,x,y; for (j=0; j < z->img_mcu_y; ++j) { for (i=0; i < z->img_mcu_x; ++i) { // scan an interleaved mcu... process scan_n components in order for (k=0; k < z->scan_n; ++k) { int n = z->order[k]; // scan out an mcu's worth of this component; that's just determined // by the basic H and V specified for the component for (y=0; y < z->img_comp[n].v; ++y) { for (x=0; x < z->img_comp[n].h; ++x) { int x2 = (i*z->img_comp[n].h + x); int y2 = (j*z->img_comp[n].v + y); short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) return 0; } } } // after all interleaved components, that's an interleaved MCU, // so now count down the restart interval if (--z->todo <= 0) { if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); if (!STBI__RESTART(z->marker)) return 1; stbi__jpeg_reset(z); } } } return 1; } } } static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) { int i; for (i=0; i < 64; ++i) data[i] *= dequant[i]; } static void stbi__jpeg_finish(stbi__jpeg *z) { if (z->progressive) { // dequantize and idct the data int i,j,n; for (n=0; n < z->s->img_n; ++n) { int w = (z->img_comp[n].x+7) >> 3; int h = (z->img_comp[n].y+7) >> 3; for (j=0; j < h; ++j) { for (i=0; i < w; ++i) { short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); } } } } } static int stbi__process_marker(stbi__jpeg *z, int m) { int L; switch (m) { case STBI__MARKER_none: // no marker found return stbi__err("expected marker","Corrupt JPEG"); case 0xDD: // DRI - specify restart interval if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); z->restart_interval = stbi__get16be(z->s); return 1; case 0xDB: // DQT - define quantization table L = stbi__get16be(z->s)-2; while (L > 0) { int q = stbi__get8(z->s); int p = q >> 4, sixteen = (p != 0); int t = q & 15,i; if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); for (i=0; i < 64; ++i) z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); L -= (sixteen ? 129 : 65); } return L==0; case 0xC4: // DHT - define huffman table L = stbi__get16be(z->s)-2; while (L > 0) { stbi_uc *v; int sizes[16],i,n=0; int q = stbi__get8(z->s); int tc = q >> 4; int th = q & 15; if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); for (i=0; i < 16; ++i) { sizes[i] = stbi__get8(z->s); n += sizes[i]; } if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values! L -= 17; if (tc == 0) { if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; v = z->huff_dc[th].values; } else { if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; v = z->huff_ac[th].values; } for (i=0; i < n; ++i) v[i] = stbi__get8(z->s); if (tc != 0) stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); L -= n; } return L==0; } // check for comment block or APP blocks if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { L = stbi__get16be(z->s); if (L < 2) { if (m == 0xFE) return stbi__err("bad COM len","Corrupt JPEG"); else return stbi__err("bad APP len","Corrupt JPEG"); } L -= 2; if (m == 0xE0 && L >= 5) { // JFIF APP0 segment static const unsigned char tag[5] = {'J','F','I','F','\0'}; int ok = 1; int i; for (i=0; i < 5; ++i) if (stbi__get8(z->s) != tag[i]) ok = 0; L -= 5; if (ok) z->jfif = 1; } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; int ok = 1; int i; for (i=0; i < 6; ++i) if (stbi__get8(z->s) != tag[i]) ok = 0; L -= 6; if (ok) { stbi__get8(z->s); // version stbi__get16be(z->s); // flags0 stbi__get16be(z->s); // flags1 z->app14_color_transform = stbi__get8(z->s); // color transform L -= 6; } } stbi__skip(z->s, L); return 1; } return stbi__err("unknown marker","Corrupt JPEG"); } // after we see SOS static int stbi__process_scan_header(stbi__jpeg *z) { int i; int Ls = stbi__get16be(z->s); z->scan_n = stbi__get8(z->s); if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); for (i=0; i < z->scan_n; ++i) { int id = stbi__get8(z->s), which; int q = stbi__get8(z->s); for (which = 0; which < z->s->img_n; ++which) if (z->img_comp[which].id == id) break; if (which == z->s->img_n) return 0; // no match z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); z->order[i] = which; } { int aa; z->spec_start = stbi__get8(z->s); z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 aa = stbi__get8(z->s); z->succ_high = (aa >> 4); z->succ_low = (aa & 15); if (z->progressive) { if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) return stbi__err("bad SOS", "Corrupt JPEG"); } else { if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); z->spec_end = 63; } } return 1; } static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) { int i; for (i=0; i < ncomp; ++i) { if (z->img_comp[i].raw_data) { STBI_FREE(z->img_comp[i].raw_data); z->img_comp[i].raw_data = NULL; z->img_comp[i].data = NULL; } if (z->img_comp[i].raw_coeff) { STBI_FREE(z->img_comp[i].raw_coeff); z->img_comp[i].raw_coeff = 0; z->img_comp[i].coeff = 0; } if (z->img_comp[i].linebuf) { STBI_FREE(z->img_comp[i].linebuf); z->img_comp[i].linebuf = NULL; } } return why; } static int stbi__process_frame_header(stbi__jpeg *z, int scan) { stbi__context *s = z->s; int Lf,p,i,q, h_max=1,v_max=1,c; Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); c = stbi__get8(s); if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); s->img_n = c; for (i=0; i < c; ++i) { z->img_comp[i].data = NULL; z->img_comp[i].linebuf = NULL; } if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); z->rgb = 0; for (i=0; i < s->img_n; ++i) { static const unsigned char rgb[3] = { 'R', 'G', 'B' }; z->img_comp[i].id = stbi__get8(s); if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) ++z->rgb; q = stbi__get8(s); z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); } if (scan != STBI__SCAN_load) return 1; if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); for (i=0; i < s->img_n; ++i) { if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; } // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios // and I've never seen a non-corrupted JPEG file actually use them for (i=0; i < s->img_n; ++i) { if (h_max % z->img_comp[i].h != 0) return stbi__err("bad H","Corrupt JPEG"); if (v_max % z->img_comp[i].v != 0) return stbi__err("bad V","Corrupt JPEG"); } // compute interleaved mcu info z->img_h_max = h_max; z->img_v_max = v_max; z->img_mcu_w = h_max * 8; z->img_mcu_h = v_max * 8; // these sizes can't be more than 17 bits z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; for (i=0; i < s->img_n; ++i) { // number of effective pixels (e.g. for non-interleaved MCU) z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; // to simplify generation, we'll allocate enough memory to decode // the bogus oversized data from using interleaved MCUs and their // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't // discard the extra data until colorspace conversion // // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) // so these muls can't overflow with 32-bit ints (which we require) z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; z->img_comp[i].coeff = 0; z->img_comp[i].raw_coeff = 0; z->img_comp[i].linebuf = NULL; z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); if (z->img_comp[i].raw_data == NULL) return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); // align blocks for idct using mmx/sse z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); if (z->progressive) { // w2, h2 are multiples of 8 (see above) z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); if (z->img_comp[i].raw_coeff == NULL) return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); } } return 1; } // use comparisons since in some cases we handle more than one case (e.g. SOF) #define stbi__DNL(x) ((x) == 0xdc) #define stbi__SOI(x) ((x) == 0xd8) #define stbi__EOI(x) ((x) == 0xd9) #define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) #define stbi__SOS(x) ((x) == 0xda) #define stbi__SOF_progressive(x) ((x) == 0xc2) static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) { int m; z->jfif = 0; z->app14_color_transform = -1; // valid values are 0,1,2 z->marker = STBI__MARKER_none; // initialize cached marker to empty m = stbi__get_marker(z); if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); if (scan == STBI__SCAN_type) return 1; m = stbi__get_marker(z); while (!stbi__SOF(m)) { if (!stbi__process_marker(z,m)) return 0; m = stbi__get_marker(z); while (m == STBI__MARKER_none) { // some files have extra padding after their blocks, so ok, we'll scan if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); m = stbi__get_marker(z); } } z->progressive = stbi__SOF_progressive(m); if (!stbi__process_frame_header(z, scan)) return 0; return 1; } static int stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) { // some JPEGs have junk at end, skip over it but if we find what looks // like a valid marker, resume there while (!stbi__at_eof(j->s)) { int x = stbi__get8(j->s); while (x == 255) { // might be a marker if (stbi__at_eof(j->s)) return STBI__MARKER_none; x = stbi__get8(j->s); if (x != 0x00 && x != 0xff) { // not a stuffed zero or lead-in to another marker, looks // like an actual marker, return it return x; } // stuffed zero has x=0 now which ends the loop, meaning we go // back to regular scan loop. // repeated 0xff keeps trying to read the next byte of the marker. } } return STBI__MARKER_none; } // decode image to YCbCr format static int stbi__decode_jpeg_image(stbi__jpeg *j) { int m; for (m = 0; m < 4; m++) { j->img_comp[m].raw_data = NULL; j->img_comp[m].raw_coeff = NULL; } j->restart_interval = 0; if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; m = stbi__get_marker(j); while (!stbi__EOI(m)) { if (stbi__SOS(m)) { if (!stbi__process_scan_header(j)) return 0; if (!stbi__parse_entropy_coded_data(j)) return 0; if (j->marker == STBI__MARKER_none ) { j->marker = stbi__skip_jpeg_junk_at_end(j); // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 } m = stbi__get_marker(j); if (STBI__RESTART(m)) m = stbi__get_marker(j); } else if (stbi__DNL(m)) { int Ld = stbi__get16be(j->s); stbi__uint32 NL = stbi__get16be(j->s); if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); m = stbi__get_marker(j); } else { if (!stbi__process_marker(j, m)) return 1; m = stbi__get_marker(j); } } if (j->progressive) stbi__jpeg_finish(j); return 1; } // static jfif-centered resampling (across block boundaries) typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, int w, int hs); #define stbi__div4(x) ((stbi_uc) ((x) >> 2)) static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) { STBI_NOTUSED(out); STBI_NOTUSED(in_far); STBI_NOTUSED(w); STBI_NOTUSED(hs); return in_near; } static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) { // need to generate two samples vertically for every one in input int i; STBI_NOTUSED(hs); for (i=0; i < w; ++i) out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); return out; } static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) { // need to generate two samples horizontally for every one in input int i; stbi_uc *input = in_near; if (w == 1) { // if only one sample, can't do any interpolation out[0] = out[1] = input[0]; return out; } out[0] = input[0]; out[1] = stbi__div4(input[0]*3 + input[1] + 2); for (i=1; i < w-1; ++i) { int n = 3*input[i]+2; out[i*2+0] = stbi__div4(n+input[i-1]); out[i*2+1] = stbi__div4(n+input[i+1]); } out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); out[i*2+1] = input[w-1]; STBI_NOTUSED(in_far); STBI_NOTUSED(hs); return out; } #define stbi__div16(x) ((stbi_uc) ((x) >> 4)) static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) { // need to generate 2x2 samples for every one in input int i,t0,t1; if (w == 1) { out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); return out; } t1 = 3*in_near[0] + in_far[0]; out[0] = stbi__div4(t1+2); for (i=1; i < w; ++i) { t0 = t1; t1 = 3*in_near[i]+in_far[i]; out[i*2-1] = stbi__div16(3*t0 + t1 + 8); out[i*2 ] = stbi__div16(3*t1 + t0 + 8); } out[w*2-1] = stbi__div4(t1+2); STBI_NOTUSED(hs); return out; } #if defined(STBI_SSE2) || defined(STBI_NEON) static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) { // need to generate 2x2 samples for every one in input int i=0,t0,t1; if (w == 1) { out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); return out; } t1 = 3*in_near[0] + in_far[0]; // process groups of 8 pixels for as long as we can. // note we can't handle the last pixel in a row in this loop // because we need to handle the filter boundary conditions. for (; i < ((w-1) & ~7); i += 8) { #if defined(STBI_SSE2) // load and perform the vertical filtering pass // this uses 3*x + y = 4*x + (y - x) __m128i zero = _mm_setzero_si128(); __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); __m128i farw = _mm_unpacklo_epi8(farb, zero); __m128i nearw = _mm_unpacklo_epi8(nearb, zero); __m128i diff = _mm_sub_epi16(farw, nearw); __m128i nears = _mm_slli_epi16(nearw, 2); __m128i curr = _mm_add_epi16(nears, diff); // current row // horizontal filter works the same based on shifted vers of current // row. "prev" is current row shifted right by 1 pixel; we need to // insert the previous pixel value (from t1). // "next" is current row shifted left by 1 pixel, with first pixel // of next block of 8 pixels added in. __m128i prv0 = _mm_slli_si128(curr, 2); __m128i nxt0 = _mm_srli_si128(curr, 2); __m128i prev = _mm_insert_epi16(prv0, t1, 0); __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); // horizontal filter, polyphase implementation since it's convenient: // even pixels = 3*cur + prev = cur*4 + (prev - cur) // odd pixels = 3*cur + next = cur*4 + (next - cur) // note the shared term. __m128i bias = _mm_set1_epi16(8); __m128i curs = _mm_slli_epi16(curr, 2); __m128i prvd = _mm_sub_epi16(prev, curr); __m128i nxtd = _mm_sub_epi16(next, curr); __m128i curb = _mm_add_epi16(curs, bias); __m128i even = _mm_add_epi16(prvd, curb); __m128i odd = _mm_add_epi16(nxtd, curb); // interleave even and odd pixels, then undo scaling. __m128i int0 = _mm_unpacklo_epi16(even, odd); __m128i int1 = _mm_unpackhi_epi16(even, odd); __m128i de0 = _mm_srli_epi16(int0, 4); __m128i de1 = _mm_srli_epi16(int1, 4); // pack and write output __m128i outv = _mm_packus_epi16(de0, de1); _mm_storeu_si128((__m128i *) (out + i*2), outv); #elif defined(STBI_NEON) // load and perform the vertical filtering pass // this uses 3*x + y = 4*x + (y - x) uint8x8_t farb = vld1_u8(in_far + i); uint8x8_t nearb = vld1_u8(in_near + i); int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); int16x8_t curr = vaddq_s16(nears, diff); // current row // horizontal filter works the same based on shifted vers of current // row. "prev" is current row shifted right by 1 pixel; we need to // insert the previous pixel value (from t1). // "next" is current row shifted left by 1 pixel, with first pixel // of next block of 8 pixels added in. int16x8_t prv0 = vextq_s16(curr, curr, 7); int16x8_t nxt0 = vextq_s16(curr, curr, 1); int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); // horizontal filter, polyphase implementation since it's convenient: // even pixels = 3*cur + prev = cur*4 + (prev - cur) // odd pixels = 3*cur + next = cur*4 + (next - cur) // note the shared term. int16x8_t curs = vshlq_n_s16(curr, 2); int16x8_t prvd = vsubq_s16(prev, curr); int16x8_t nxtd = vsubq_s16(next, curr); int16x8_t even = vaddq_s16(curs, prvd); int16x8_t odd = vaddq_s16(curs, nxtd); // undo scaling and round, then store with even/odd phases interleaved uint8x8x2_t o; o.val[0] = vqrshrun_n_s16(even, 4); o.val[1] = vqrshrun_n_s16(odd, 4); vst2_u8(out + i*2, o); #endif // "previous" value for next iter t1 = 3*in_near[i+7] + in_far[i+7]; } t0 = t1; t1 = 3*in_near[i] + in_far[i]; out[i*2] = stbi__div16(3*t1 + t0 + 8); for (++i; i < w; ++i) { t0 = t1; t1 = 3*in_near[i]+in_far[i]; out[i*2-1] = stbi__div16(3*t0 + t1 + 8); out[i*2 ] = stbi__div16(3*t1 + t0 + 8); } out[w*2-1] = stbi__div4(t1+2); STBI_NOTUSED(hs); return out; } #endif static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) { // resample with nearest-neighbor int i,j; STBI_NOTUSED(in_far); for (i=0; i < w; ++i) for (j=0; j < hs; ++j) out[i*hs+j] = in_near[i]; return out; } // this is a reduced-precision calculation of YCbCr-to-RGB introduced // to make sure the code produces the same results in both SIMD and scalar #define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) { int i; for (i=0; i < count; ++i) { int y_fixed = (y[i] << 20) + (1<<19); // rounding int r,g,b; int cr = pcr[i] - 128; int cb = pcb[i] - 128; r = y_fixed + cr* stbi__float2fixed(1.40200f); g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); b = y_fixed + cb* stbi__float2fixed(1.77200f); r >>= 20; g >>= 20; b >>= 20; if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } out[0] = (stbi_uc)r; out[1] = (stbi_uc)g; out[2] = (stbi_uc)b; out[3] = 255; out += step; } } #if defined(STBI_SSE2) || defined(STBI_NEON) static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) { int i = 0; #ifdef STBI_SSE2 // step == 3 is pretty ugly on the final interleave, and i'm not convinced // it's useful in practice (you wouldn't use it for textures, for example). // so just accelerate step == 4 case. if (step == 4) { // this is a fairly straightforward implementation and not super-optimized. __m128i signflip = _mm_set1_epi8(-0x80); __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); __m128i xw = _mm_set1_epi16(255); // alpha channel for (; i+7 < count; i += 8) { // load __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 // unpack to short (and left-shift cr, cb by 8) __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); // color transform __m128i yws = _mm_srli_epi16(yw, 4); __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); __m128i rws = _mm_add_epi16(cr0, yws); __m128i gwt = _mm_add_epi16(cb0, yws); __m128i bws = _mm_add_epi16(yws, cb1); __m128i gws = _mm_add_epi16(gwt, cr1); // descale __m128i rw = _mm_srai_epi16(rws, 4); __m128i bw = _mm_srai_epi16(bws, 4); __m128i gw = _mm_srai_epi16(gws, 4); // back to byte, set up for transpose __m128i brb = _mm_packus_epi16(rw, bw); __m128i gxb = _mm_packus_epi16(gw, xw); // transpose to interleave channels __m128i t0 = _mm_unpacklo_epi8(brb, gxb); __m128i t1 = _mm_unpackhi_epi8(brb, gxb); __m128i o0 = _mm_unpacklo_epi16(t0, t1); __m128i o1 = _mm_unpackhi_epi16(t0, t1); // store _mm_storeu_si128((__m128i *) (out + 0), o0); _mm_storeu_si128((__m128i *) (out + 16), o1); out += 32; } } #endif #ifdef STBI_NEON // in this version, step=3 support would be easy to add. but is there demand? if (step == 4) { // this is a fairly straightforward implementation and not super-optimized. uint8x8_t signflip = vdup_n_u8(0x80); int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); for (; i+7 < count; i += 8) { // load uint8x8_t y_bytes = vld1_u8(y + i); uint8x8_t cr_bytes = vld1_u8(pcr + i); uint8x8_t cb_bytes = vld1_u8(pcb + i); int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); // expand to s16 int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); int16x8_t crw = vshll_n_s8(cr_biased, 7); int16x8_t cbw = vshll_n_s8(cb_biased, 7); // color transform int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); int16x8_t rws = vaddq_s16(yws, cr0); int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); int16x8_t bws = vaddq_s16(yws, cb1); // undo scaling, round, convert to byte uint8x8x4_t o; o.val[0] = vqrshrun_n_s16(rws, 4); o.val[1] = vqrshrun_n_s16(gws, 4); o.val[2] = vqrshrun_n_s16(bws, 4); o.val[3] = vdup_n_u8(255); // store, interleaving r/g/b/a vst4_u8(out, o); out += 8*4; } } #endif for (; i < count; ++i) { int y_fixed = (y[i] << 20) + (1<<19); // rounding int r,g,b; int cr = pcr[i] - 128; int cb = pcb[i] - 128; r = y_fixed + cr* stbi__float2fixed(1.40200f); g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); b = y_fixed + cb* stbi__float2fixed(1.77200f); r >>= 20; g >>= 20; b >>= 20; if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } out[0] = (stbi_uc)r; out[1] = (stbi_uc)g; out[2] = (stbi_uc)b; out[3] = 255; out += step; } } #endif // set up the kernels static void stbi__setup_jpeg(stbi__jpeg *j) { j->idct_block_kernel = stbi__idct_block; j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; #ifdef STBI_SSE2 if (stbi__sse2_available()) { j->idct_block_kernel = stbi__idct_simd; j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; } #endif #ifdef STBI_NEON j->idct_block_kernel = stbi__idct_simd; j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; #endif } // clean up the temporary component buffers static void stbi__cleanup_jpeg(stbi__jpeg *j) { stbi__free_jpeg_components(j, j->s->img_n, 0); } typedef struct { resample_row_func resample; stbi_uc *line0,*line1; int hs,vs; // expansion factor in each axis int w_lores; // horizontal pixels pre-expansion int ystep; // how far through vertical expansion we are int ypos; // which pre-expansion row we're on } stbi__resample; // fast 0..255 * 0..255 => 0..255 rounded multiplication static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) { unsigned int t = x*y + 128; return (stbi_uc) ((t + (t >>8)) >> 8); } static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) { int n, decode_n, is_rgb; z->s->img_n = 0; // make stbi__cleanup_jpeg safe // validate req_comp if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); // load a jpeg image from whichever source, but leave in YCbCr format if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } // determine actual number of components to generate n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); if (z->s->img_n == 3 && n < 3 && !is_rgb) decode_n = 1; else decode_n = z->s->img_n; // nothing to do if no components requested; check this now to avoid // accessing uninitialized coutput[0] later if (decode_n <= 0) { stbi__cleanup_jpeg(z); return NULL; } // resample and color-convert { int k; unsigned int i,j; stbi_uc *output; stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL }; stbi__resample res_comp[4]; for (k=0; k < decode_n; ++k) { stbi__resample *r = &res_comp[k]; // allocate line buffer big enough for upsampling off the edges // with upsample factor of 4 z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } r->hs = z->img_h_max / z->img_comp[k].h; r->vs = z->img_v_max / z->img_comp[k].v; r->ystep = r->vs >> 1; r->w_lores = (z->s->img_x + r->hs-1) / r->hs; r->ypos = 0; r->line0 = r->line1 = z->img_comp[k].data; if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; else r->resample = stbi__resample_row_generic; } // can't error after this so, this is safe output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } // now go ahead and resample for (j=0; j < z->s->img_y; ++j) { stbi_uc *out = output + n * z->s->img_x * j; for (k=0; k < decode_n; ++k) { stbi__resample *r = &res_comp[k]; int y_bot = r->ystep >= (r->vs >> 1); coutput[k] = r->resample(z->img_comp[k].linebuf, y_bot ? r->line1 : r->line0, y_bot ? r->line0 : r->line1, r->w_lores, r->hs); if (++r->ystep >= r->vs) { r->ystep = 0; r->line0 = r->line1; if (++r->ypos < z->img_comp[k].y) r->line1 += z->img_comp[k].w2; } } if (n >= 3) { stbi_uc *y = coutput[0]; if (z->s->img_n == 3) { if (is_rgb) { for (i=0; i < z->s->img_x; ++i) { out[0] = y[i]; out[1] = coutput[1][i]; out[2] = coutput[2][i]; out[3] = 255; out += n; } } else { z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); } } else if (z->s->img_n == 4) { if (z->app14_color_transform == 0) { // CMYK for (i=0; i < z->s->img_x; ++i) { stbi_uc m = coutput[3][i]; out[0] = stbi__blinn_8x8(coutput[0][i], m); out[1] = stbi__blinn_8x8(coutput[1][i], m); out[2] = stbi__blinn_8x8(coutput[2][i], m); out[3] = 255; out += n; } } else if (z->app14_color_transform == 2) { // YCCK z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); for (i=0; i < z->s->img_x; ++i) { stbi_uc m = coutput[3][i]; out[0] = stbi__blinn_8x8(255 - out[0], m); out[1] = stbi__blinn_8x8(255 - out[1], m); out[2] = stbi__blinn_8x8(255 - out[2], m); out += n; } } else { // YCbCr + alpha? Ignore the fourth channel for now z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); } } else for (i=0; i < z->s->img_x; ++i) { out[0] = out[1] = out[2] = y[i]; out[3] = 255; // not used if n==3 out += n; } } else { if (is_rgb) { if (n == 1) for (i=0; i < z->s->img_x; ++i) *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); else { for (i=0; i < z->s->img_x; ++i, out += 2) { out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); out[1] = 255; } } } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { for (i=0; i < z->s->img_x; ++i) { stbi_uc m = coutput[3][i]; stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); out[0] = stbi__compute_y(r, g, b); out[1] = 255; out += n; } } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { for (i=0; i < z->s->img_x; ++i) { out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); out[1] = 255; out += n; } } else { stbi_uc *y = coutput[0]; if (n == 1) for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; else for (i=0; i < z->s->img_x; ++i) { *out++ = y[i]; *out++ = 255; } } } } stbi__cleanup_jpeg(z); *out_x = z->s->img_x; *out_y = z->s->img_y; if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output return output; } } static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { unsigned char* result; stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); if (!j) return stbi__errpuc("outofmem", "Out of memory"); memset(j, 0, sizeof(stbi__jpeg)); STBI_NOTUSED(ri); j->s = s; stbi__setup_jpeg(j); result = load_jpeg_image(j, x,y,comp,req_comp); STBI_FREE(j); return result; } static int stbi__jpeg_test(stbi__context *s) { int r; stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); if (!j) return stbi__err("outofmem", "Out of memory"); memset(j, 0, sizeof(stbi__jpeg)); j->s = s; stbi__setup_jpeg(j); r = stbi__decode_jpeg_header(j, STBI__SCAN_type); stbi__rewind(s); STBI_FREE(j); return r; } static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) { if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { stbi__rewind( j->s ); return 0; } if (x) *x = j->s->img_x; if (y) *y = j->s->img_y; if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; return 1; } static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) { int result; stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); if (!j) return stbi__err("outofmem", "Out of memory"); memset(j, 0, sizeof(stbi__jpeg)); j->s = s; result = stbi__jpeg_info_raw(j, x, y, comp); STBI_FREE(j); return result; } #endif // public domain zlib decode v0.2 Sean Barrett 2006-11-18 // simple implementation // - all input must be provided in an upfront buffer // - all output is written to a single output buffer (can malloc/realloc) // performance // - fast huffman #ifndef STBI_NO_ZLIB // fast-way is faster to check than jpeg huffman, but slow way is slower #define STBI__ZFAST_BITS 9 // accelerate all cases in default tables #define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) #define STBI__ZNSYMS 288 // number of symbols in literal/length alphabet // zlib-style huffman encoding // (jpegs packs from left, zlib from right, so can't share code) typedef struct { stbi__uint16 fast[1 << STBI__ZFAST_BITS]; stbi__uint16 firstcode[16]; int maxcode[17]; stbi__uint16 firstsymbol[16]; stbi_uc size[STBI__ZNSYMS]; stbi__uint16 value[STBI__ZNSYMS]; } stbi__zhuffman; stbi_inline static int stbi__bitreverse16(int n) { n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); return n; } stbi_inline static int stbi__bit_reverse(int v, int bits) { STBI_ASSERT(bits <= 16); // to bit reverse n bits, reverse 16 and shift // e.g. 11 bits, bit reverse and shift away 5 return stbi__bitreverse16(v) >> (16-bits); } static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) { int i,k=0; int code, next_code[16], sizes[17]; // DEFLATE spec for generating codes memset(sizes, 0, sizeof(sizes)); memset(z->fast, 0, sizeof(z->fast)); for (i=0; i < num; ++i) ++sizes[sizelist[i]]; sizes[0] = 0; for (i=1; i < 16; ++i) if (sizes[i] > (1 << i)) return stbi__err("bad sizes", "Corrupt PNG"); code = 0; for (i=1; i < 16; ++i) { next_code[i] = code; z->firstcode[i] = (stbi__uint16) code; z->firstsymbol[i] = (stbi__uint16) k; code = (code + sizes[i]); if (sizes[i]) if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); z->maxcode[i] = code << (16-i); // preshift for inner loop code <<= 1; k += sizes[i]; } z->maxcode[16] = 0x10000; // sentinel for (i=0; i < num; ++i) { int s = sizelist[i]; if (s) { int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); z->size [c] = (stbi_uc ) s; z->value[c] = (stbi__uint16) i; if (s <= STBI__ZFAST_BITS) { int j = stbi__bit_reverse(next_code[s],s); while (j < (1 << STBI__ZFAST_BITS)) { z->fast[j] = fastv; j += (1 << s); } } ++next_code[s]; } } return 1; } // zlib-from-memory implementation for PNG reading // because PNG allows splitting the zlib stream arbitrarily, // and it's annoying structurally to have PNG call ZLIB call PNG, // we require PNG read all the IDATs and combine them into a single // memory buffer typedef struct { stbi_uc *zbuffer, *zbuffer_end; int num_bits; stbi__uint32 code_buffer; char *zout; char *zout_start; char *zout_end; int z_expandable; stbi__zhuffman z_length, z_distance; } stbi__zbuf; stbi_inline static int stbi__zeof(stbi__zbuf *z) { return (z->zbuffer >= z->zbuffer_end); } stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) { return stbi__zeof(z) ? 0 : *z->zbuffer++; } static void stbi__fill_bits(stbi__zbuf *z) { do { if (z->code_buffer >= (1U << z->num_bits)) { z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */ return; } z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; z->num_bits += 8; } while (z->num_bits <= 24); } stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) { unsigned int k; if (z->num_bits < n) stbi__fill_bits(z); k = z->code_buffer & ((1 << n) - 1); z->code_buffer >>= n; z->num_bits -= n; return k; } static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) { int b,s,k; // not resolved by fast table, so compute it the slow way // use jpeg approach, which requires MSbits at top k = stbi__bit_reverse(a->code_buffer, 16); for (s=STBI__ZFAST_BITS+1; ; ++s) if (k < z->maxcode[s]) break; if (s >= 16) return -1; // invalid code! // code size is s, so: b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; if (b >= STBI__ZNSYMS) return -1; // some data was corrupt somewhere! if (z->size[b] != s) return -1; // was originally an assert, but report failure instead. a->code_buffer >>= s; a->num_bits -= s; return z->value[b]; } stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) { int b,s; if (a->num_bits < 16) { if (stbi__zeof(a)) { return -1; /* report error for unexpected end of data. */ } stbi__fill_bits(a); } b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; if (b) { s = b >> 9; a->code_buffer >>= s; a->num_bits -= s; return b & 511; } return stbi__zhuffman_decode_slowpath(a, z); } static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes { char *q; unsigned int cur, limit, old_limit; z->zout = zout; if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); cur = (unsigned int) (z->zout - z->zout_start); limit = old_limit = (unsigned) (z->zout_end - z->zout_start); if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory"); while (cur + n > limit) { if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory"); limit *= 2; } q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); STBI_NOTUSED(old_limit); if (q == NULL) return stbi__err("outofmem", "Out of memory"); z->zout_start = q; z->zout = q + cur; z->zout_end = q + limit; return 1; } static const int stbi__zlength_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 }; static const int stbi__zlength_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; static const int stbi__zdist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; static int stbi__parse_huffman_block(stbi__zbuf *a) { char *zout = a->zout; for(;;) { int z = stbi__zhuffman_decode(a, &a->z_length); if (z < 256) { if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes if (zout >= a->zout_end) { if (!stbi__zexpand(a, zout, 1)) return 0; zout = a->zout; } *zout++ = (char) z; } else { stbi_uc *p; int len,dist; if (z == 256) { a->zout = zout; return 1; } if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data z -= 257; len = stbi__zlength_base[z]; if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); z = stbi__zhuffman_decode(a, &a->z_distance); if (z < 0 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data dist = stbi__zdist_base[z]; if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); if (zout + len > a->zout_end) { if (!stbi__zexpand(a, zout, len)) return 0; zout = a->zout; } p = (stbi_uc *) (zout - dist); if (dist == 1) { // run of one byte; common in images. stbi_uc v = *p; if (len) { do *zout++ = v; while (--len); } } else { if (len) { do *zout++ = *p++; while (--len); } } } } } static int stbi__compute_huffman_codes(stbi__zbuf *a) { static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; stbi__zhuffman z_codelength; stbi_uc lencodes[286+32+137];//padding for maximum single op stbi_uc codelength_sizes[19]; int i,n; int hlit = stbi__zreceive(a,5) + 257; int hdist = stbi__zreceive(a,5) + 1; int hclen = stbi__zreceive(a,4) + 4; int ntot = hlit + hdist; memset(codelength_sizes, 0, sizeof(codelength_sizes)); for (i=0; i < hclen; ++i) { int s = stbi__zreceive(a,3); codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; } if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; n = 0; while (n < ntot) { int c = stbi__zhuffman_decode(a, &z_codelength); if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); if (c < 16) lencodes[n++] = (stbi_uc) c; else { stbi_uc fill = 0; if (c == 16) { c = stbi__zreceive(a,2)+3; if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); fill = lencodes[n-1]; } else if (c == 17) { c = stbi__zreceive(a,3)+3; } else if (c == 18) { c = stbi__zreceive(a,7)+11; } else { return stbi__err("bad codelengths", "Corrupt PNG"); } if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); memset(lencodes+n, fill, c); n += c; } } if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; return 1; } static int stbi__parse_uncompressed_block(stbi__zbuf *a) { stbi_uc header[4]; int len,nlen,k; if (a->num_bits & 7) stbi__zreceive(a, a->num_bits & 7); // discard // drain the bit-packed data into header k = 0; while (a->num_bits > 0) { header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check a->code_buffer >>= 8; a->num_bits -= 8; } if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG"); // now fill header the normal way while (k < 4) header[k++] = stbi__zget8(a); len = header[1] * 256 + header[0]; nlen = header[3] * 256 + header[2]; if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); if (a->zout + len > a->zout_end) if (!stbi__zexpand(a, a->zout, len)) return 0; memcpy(a->zout, a->zbuffer, len); a->zbuffer += len; a->zout += len; return 1; } static int stbi__parse_zlib_header(stbi__zbuf *a) { int cmf = stbi__zget8(a); int cm = cmf & 15; /* int cinfo = cmf >> 4; */ int flg = stbi__zget8(a); if (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png // window = 1 << (8 + cinfo)... but who cares, we fully buffer output return 1; } static const stbi_uc stbi__zdefault_length[STBI__ZNSYMS] = { 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 }; static const stbi_uc stbi__zdefault_distance[32] = { 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 }; /* Init algorithm: { int i; // use <= to match clearly with spec for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; } */ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) { int final, type; if (parse_header) if (!stbi__parse_zlib_header(a)) return 0; a->num_bits = 0; a->code_buffer = 0; do { final = stbi__zreceive(a,1); type = stbi__zreceive(a,2); if (type == 0) { if (!stbi__parse_uncompressed_block(a)) return 0; } else if (type == 3) { return 0; } else { if (type == 1) { // use fixed code lengths if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , STBI__ZNSYMS)) return 0; if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; } else { if (!stbi__compute_huffman_codes(a)) return 0; } if (!stbi__parse_huffman_block(a)) return 0; } } while (!final); return 1; } static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) { a->zout_start = obuf; a->zout = obuf; a->zout_end = obuf + olen; a->z_expandable = exp; return stbi__parse_zlib(a, parse_header); } STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) { stbi__zbuf a; char *p = (char *) stbi__malloc(initial_size); if (p == NULL) return NULL; a.zbuffer = (stbi_uc *) buffer; a.zbuffer_end = (stbi_uc *) buffer + len; if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { if (outlen) *outlen = (int) (a.zout - a.zout_start); return a.zout_start; } else { STBI_FREE(a.zout_start); return NULL; } } STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) { return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); } STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) { stbi__zbuf a; char *p = (char *) stbi__malloc(initial_size); if (p == NULL) return NULL; a.zbuffer = (stbi_uc *) buffer; a.zbuffer_end = (stbi_uc *) buffer + len; if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { if (outlen) *outlen = (int) (a.zout - a.zout_start); return a.zout_start; } else { STBI_FREE(a.zout_start); return NULL; } } STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) { stbi__zbuf a; a.zbuffer = (stbi_uc *) ibuffer; a.zbuffer_end = (stbi_uc *) ibuffer + ilen; if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) return (int) (a.zout - a.zout_start); else return -1; } STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) { stbi__zbuf a; char *p = (char *) stbi__malloc(16384); if (p == NULL) return NULL; a.zbuffer = (stbi_uc *) buffer; a.zbuffer_end = (stbi_uc *) buffer+len; if (stbi__do_zlib(&a, p, 16384, 1, 0)) { if (outlen) *outlen = (int) (a.zout - a.zout_start); return a.zout_start; } else { STBI_FREE(a.zout_start); return NULL; } } STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) { stbi__zbuf a; a.zbuffer = (stbi_uc *) ibuffer; a.zbuffer_end = (stbi_uc *) ibuffer + ilen; if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) return (int) (a.zout - a.zout_start); else return -1; } #endif // public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 // simple implementation // - only 8-bit samples // - no CRC checking // - allocates lots of intermediate memory // - avoids problem of streaming data between subsystems // - avoids explicit window management // performance // - uses stb_zlib, a PD zlib implementation with fast huffman decoding #ifndef STBI_NO_PNG typedef struct { stbi__uint32 length; stbi__uint32 type; } stbi__pngchunk; static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) { stbi__pngchunk c; c.length = stbi__get32be(s); c.type = stbi__get32be(s); return c; } static int stbi__check_png_header(stbi__context *s) { static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; int i; for (i=0; i < 8; ++i) if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); return 1; } typedef struct { stbi__context *s; stbi_uc *idata, *expanded, *out; int depth; } stbi__png; enum { STBI__F_none=0, STBI__F_sub=1, STBI__F_up=2, STBI__F_avg=3, STBI__F_paeth=4, // synthetic filters used for first scanline to avoid needing a dummy row of 0s STBI__F_avg_first, STBI__F_paeth_first }; static stbi_uc first_row_filter[5] = { STBI__F_none, STBI__F_sub, STBI__F_none, STBI__F_avg_first, STBI__F_paeth_first }; static int stbi__paeth(int a, int b, int c) { int p = a + b - c; int pa = abs(p-a); int pb = abs(p-b); int pc = abs(p-c); if (pa <= pb && pa <= pc) return a; if (pb <= pc) return b; return c; } static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; // create the png data from post-deflated data static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) { int bytes = (depth == 16? 2 : 1); stbi__context *s = a->s; stbi__uint32 i,j,stride = x*out_n*bytes; stbi__uint32 img_len, img_width_bytes; int k; int img_n = s->img_n; // copy it into a local for later int output_bytes = out_n*bytes; int filter_bytes = img_n*bytes; int width = x; STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into if (!a->out) return stbi__err("outofmem", "Out of memory"); if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); img_width_bytes = (((img_n * x * depth) + 7) >> 3); img_len = (img_width_bytes + 1) * y; // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), // so just check for raw_len < img_len always. if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); for (j=0; j < y; ++j) { stbi_uc *cur = a->out + stride*j; stbi_uc *prior; int filter = *raw++; if (filter > 4) return stbi__err("invalid filter","Corrupt PNG"); if (depth < 8) { if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG"); cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place filter_bytes = 1; width = img_width_bytes; } prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above // if first row, use special filter that doesn't sample previous row if (j == 0) filter = first_row_filter[filter]; // handle first byte explicitly for (k=0; k < filter_bytes; ++k) { switch (filter) { case STBI__F_none : cur[k] = raw[k]; break; case STBI__F_sub : cur[k] = raw[k]; break; case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; case STBI__F_avg_first : cur[k] = raw[k]; break; case STBI__F_paeth_first: cur[k] = raw[k]; break; } } if (depth == 8) { if (img_n != out_n) cur[img_n] = 255; // first pixel raw += img_n; cur += out_n; prior += out_n; } else if (depth == 16) { if (img_n != out_n) { cur[filter_bytes] = 255; // first pixel top byte cur[filter_bytes+1] = 255; // first pixel bottom byte } raw += filter_bytes; cur += output_bytes; prior += output_bytes; } else { raw += 1; cur += 1; prior += 1; } // this is a little gross, so that we don't switch per-pixel or per-component if (depth < 8 || img_n == out_n) { int nk = (width - 1)*filter_bytes; #define STBI__CASE(f) \ case f: \ for (k=0; k < nk; ++k) switch (filter) { // "none" filter turns into a memcpy here; make that explicit. case STBI__F_none: memcpy(cur, raw, nk); break; STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break; STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break; STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break; STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break; } #undef STBI__CASE raw += nk; } else { STBI_ASSERT(img_n+1 == out_n); #define STBI__CASE(f) \ case f: \ for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ for (k=0; k < filter_bytes; ++k) switch (filter) { STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break; STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break; STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break; STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break; STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break; STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break; } #undef STBI__CASE // the loop above sets the high byte of the pixels' alpha, but for // 16 bit png files we also need the low byte set. we'll do that here. if (depth == 16) { cur = a->out + stride*j; // start at the beginning of the row again for (i=0; i < x; ++i,cur+=output_bytes) { cur[filter_bytes+1] = 255; } } } } // we make a separate pass to expand bits to pixels; for performance, // this could run two scanlines behind the above code, so it won't // intefere with filtering but will still be in the cache. if (depth < 8) { for (j=0; j < y; ++j) { stbi_uc *cur = a->out + stride*j; stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range // note that the final byte might overshoot and write more data than desired. // we can allocate enough data that this never writes out of memory, but it // could also overwrite the next scanline. can it overwrite non-empty data // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. // so we need to explicitly clamp the final ones if (depth == 4) { for (k=x*img_n; k >= 2; k-=2, ++in) { *cur++ = scale * ((*in >> 4) ); *cur++ = scale * ((*in ) & 0x0f); } if (k > 0) *cur++ = scale * ((*in >> 4) ); } else if (depth == 2) { for (k=x*img_n; k >= 4; k-=4, ++in) { *cur++ = scale * ((*in >> 6) ); *cur++ = scale * ((*in >> 4) & 0x03); *cur++ = scale * ((*in >> 2) & 0x03); *cur++ = scale * ((*in ) & 0x03); } if (k > 0) *cur++ = scale * ((*in >> 6) ); if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); } else if (depth == 1) { for (k=x*img_n; k >= 8; k-=8, ++in) { *cur++ = scale * ((*in >> 7) ); *cur++ = scale * ((*in >> 6) & 0x01); *cur++ = scale * ((*in >> 5) & 0x01); *cur++ = scale * ((*in >> 4) & 0x01); *cur++ = scale * ((*in >> 3) & 0x01); *cur++ = scale * ((*in >> 2) & 0x01); *cur++ = scale * ((*in >> 1) & 0x01); *cur++ = scale * ((*in ) & 0x01); } if (k > 0) *cur++ = scale * ((*in >> 7) ); if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); } if (img_n != out_n) { int q; // insert alpha = 255 cur = a->out + stride*j; if (img_n == 1) { for (q=x-1; q >= 0; --q) { cur[q*2+1] = 255; cur[q*2+0] = cur[q]; } } else { STBI_ASSERT(img_n == 3); for (q=x-1; q >= 0; --q) { cur[q*4+3] = 255; cur[q*4+2] = cur[q*3+2]; cur[q*4+1] = cur[q*3+1]; cur[q*4+0] = cur[q*3+0]; } } } } } else if (depth == 16) { // force the image data from big-endian to platform-native. // this is done in a separate pass due to the decoding relying // on the data being untouched, but could probably be done // per-line during decode if care is taken. stbi_uc *cur = a->out; stbi__uint16 *cur16 = (stbi__uint16*)cur; for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { *cur16 = (cur[0] << 8) | cur[1]; } } return 1; } static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) { int bytes = (depth == 16 ? 2 : 1); int out_bytes = out_n * bytes; stbi_uc *final; int p; if (!interlaced) return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); // de-interlacing final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); if (!final) return stbi__err("outofmem", "Out of memory"); for (p=0; p < 7; ++p) { int xorig[] = { 0,4,0,2,0,1,0 }; int yorig[] = { 0,0,4,0,2,0,1 }; int xspc[] = { 8,8,4,4,2,2,1 }; int yspc[] = { 8,8,8,4,4,2,2 }; int i,j,x,y; // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; if (x && y) { stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { STBI_FREE(final); return 0; } for (j=0; j < y; ++j) { for (i=0; i < x; ++i) { int out_y = j*yspc[p]+yorig[p]; int out_x = i*xspc[p]+xorig[p]; memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, a->out + (j*x+i)*out_bytes, out_bytes); } } STBI_FREE(a->out); image_data += img_len; image_data_len -= img_len; } } a->out = final; return 1; } static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) { stbi__context *s = z->s; stbi__uint32 i, pixel_count = s->img_x * s->img_y; stbi_uc *p = z->out; // compute color-based transparency, assuming we've // already got 255 as the alpha value in the output STBI_ASSERT(out_n == 2 || out_n == 4); if (out_n == 2) { for (i=0; i < pixel_count; ++i) { p[1] = (p[0] == tc[0] ? 0 : 255); p += 2; } } else { for (i=0; i < pixel_count; ++i) { if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) p[3] = 0; p += 4; } } return 1; } static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) { stbi__context *s = z->s; stbi__uint32 i, pixel_count = s->img_x * s->img_y; stbi__uint16 *p = (stbi__uint16*) z->out; // compute color-based transparency, assuming we've // already got 65535 as the alpha value in the output STBI_ASSERT(out_n == 2 || out_n == 4); if (out_n == 2) { for (i = 0; i < pixel_count; ++i) { p[1] = (p[0] == tc[0] ? 0 : 65535); p += 2; } } else { for (i = 0; i < pixel_count; ++i) { if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) p[3] = 0; p += 4; } } return 1; } static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) { stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; stbi_uc *p, *temp_out, *orig = a->out; p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); if (p == NULL) return stbi__err("outofmem", "Out of memory"); // between here and free(out) below, exitting would leak temp_out = p; if (pal_img_n == 3) { for (i=0; i < pixel_count; ++i) { int n = orig[i]*4; p[0] = palette[n ]; p[1] = palette[n+1]; p[2] = palette[n+2]; p += 3; } } else { for (i=0; i < pixel_count; ++i) { int n = orig[i]*4; p[0] = palette[n ]; p[1] = palette[n+1]; p[2] = palette[n+2]; p[3] = palette[n+3]; p += 4; } } STBI_FREE(a->out); a->out = temp_out; STBI_NOTUSED(len); return 1; } static int stbi__unpremultiply_on_load_global = 0; static int stbi__de_iphone_flag_global = 0; STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) { stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply; } STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) { stbi__de_iphone_flag_global = flag_true_if_should_convert; } #ifndef STBI_THREAD_LOCAL #define stbi__unpremultiply_on_load stbi__unpremultiply_on_load_global #define stbi__de_iphone_flag stbi__de_iphone_flag_global #else static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set; static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set; STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) { stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply; stbi__unpremultiply_on_load_set = 1; } STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert) { stbi__de_iphone_flag_local = flag_true_if_should_convert; stbi__de_iphone_flag_set = 1; } #define stbi__unpremultiply_on_load (stbi__unpremultiply_on_load_set \ ? stbi__unpremultiply_on_load_local \ : stbi__unpremultiply_on_load_global) #define stbi__de_iphone_flag (stbi__de_iphone_flag_set \ ? stbi__de_iphone_flag_local \ : stbi__de_iphone_flag_global) #endif // STBI_THREAD_LOCAL static void stbi__de_iphone(stbi__png *z) { stbi__context *s = z->s; stbi__uint32 i, pixel_count = s->img_x * s->img_y; stbi_uc *p = z->out; if (s->img_out_n == 3) { // convert bgr to rgb for (i=0; i < pixel_count; ++i) { stbi_uc t = p[0]; p[0] = p[2]; p[2] = t; p += 3; } } else { STBI_ASSERT(s->img_out_n == 4); if (stbi__unpremultiply_on_load) { // convert bgr to rgb and unpremultiply for (i=0; i < pixel_count; ++i) { stbi_uc a = p[3]; stbi_uc t = p[0]; if (a) { stbi_uc half = a / 2; p[0] = (p[2] * 255 + half) / a; p[1] = (p[1] * 255 + half) / a; p[2] = ( t * 255 + half) / a; } else { p[0] = p[2]; p[2] = t; } p += 4; } } else { // convert bgr to rgb for (i=0; i < pixel_count; ++i) { stbi_uc t = p[0]; p[0] = p[2]; p[2] = t; p += 4; } } } } #define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) { stbi_uc palette[1024], pal_img_n=0; stbi_uc has_trans=0, tc[3]={0}; stbi__uint16 tc16[3]; stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; int first=1,k,interlace=0, color=0, is_iphone=0; stbi__context *s = z->s; z->expanded = NULL; z->idata = NULL; z->out = NULL; if (!stbi__check_png_header(s)) return 0; if (scan == STBI__SCAN_type) return 1; for (;;) { stbi__pngchunk c = stbi__get_chunk_header(s); switch (c.type) { case STBI__PNG_TYPE('C','g','B','I'): is_iphone = 1; stbi__skip(s, c.length); break; case STBI__PNG_TYPE('I','H','D','R'): { int comp,filter; if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); first = 0; if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); s->img_x = stbi__get32be(s); s->img_y = stbi__get32be(s); if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); if (!pal_img_n) { s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); } else { // if paletted, then pal_n is our final components, and // img_n is # components to decompress/filter. s->img_n = 1; if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); } // even with SCAN_header, have to scan to see if we have a tRNS break; } case STBI__PNG_TYPE('P','L','T','E'): { if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); pal_len = c.length / 3; if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); for (i=0; i < pal_len; ++i) { palette[i*4+0] = stbi__get8(s); palette[i*4+1] = stbi__get8(s); palette[i*4+2] = stbi__get8(s); palette[i*4+3] = 255; } break; } case STBI__PNG_TYPE('t','R','N','S'): { if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); if (pal_img_n) { if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); pal_img_n = 4; for (i=0; i < c.length; ++i) palette[i*4+3] = stbi__get8(s); } else { if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); has_trans = 1; // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now. if (scan == STBI__SCAN_header) { ++s->img_n; return 1; } if (z->depth == 16) { for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is } else { for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger } } break; } case STBI__PNG_TYPE('I','D','A','T'): { if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); if (scan == STBI__SCAN_header) { // header scan definitely stops at first IDAT if (pal_img_n) s->img_n = pal_img_n; return 1; } if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes"); if ((int)(ioff + c.length) < (int)ioff) return 0; if (ioff + c.length > idata_limit) { stbi__uint32 idata_limit_old = idata_limit; stbi_uc *p; if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; while (ioff + c.length > idata_limit) idata_limit *= 2; STBI_NOTUSED(idata_limit_old); p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); z->idata = p; } if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); ioff += c.length; break; } case STBI__PNG_TYPE('I','E','N','D'): { stbi__uint32 raw_len, bpl; if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if (scan != STBI__SCAN_load) return 1; if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); // initial guess for decoded data size to avoid unnecessary reallocs bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); if (z->expanded == NULL) return 0; // zlib should set error STBI_FREE(z->idata); z->idata = NULL; if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) s->img_out_n = s->img_n+1; else s->img_out_n = s->img_n; if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; if (has_trans) { if (z->depth == 16) { if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; } else { if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; } } if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) stbi__de_iphone(z); if (pal_img_n) { // pal_img_n == 3 or 4 s->img_n = pal_img_n; // record the actual colors we had s->img_out_n = pal_img_n; if (req_comp >= 3) s->img_out_n = req_comp; if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) return 0; } else if (has_trans) { // non-paletted image with tRNS -> source image has (constant) alpha ++s->img_n; } STBI_FREE(z->expanded); z->expanded = NULL; // end of PNG chunk, read and skip CRC stbi__get32be(s); return 1; } default: // if critical, fail if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if ((c.type & (1 << 29)) == 0) { #ifndef STBI_NO_FAILURE_STRINGS // not threadsafe static char invalid_chunk[] = "XXXX PNG chunk not known"; invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); #endif return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); } stbi__skip(s, c.length); break; } // end of PNG chunk, read and skip CRC stbi__get32be(s); } } static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) { void *result=NULL; if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { if (p->depth <= 8) ri->bits_per_channel = 8; else if (p->depth == 16) ri->bits_per_channel = 16; else return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color depth"); result = p->out; p->out = NULL; if (req_comp && req_comp != p->s->img_out_n) { if (ri->bits_per_channel == 8) result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); else result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); p->s->img_out_n = req_comp; if (result == NULL) return result; } *x = p->s->img_x; *y = p->s->img_y; if (n) *n = p->s->img_n; } STBI_FREE(p->out); p->out = NULL; STBI_FREE(p->expanded); p->expanded = NULL; STBI_FREE(p->idata); p->idata = NULL; return result; } static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { stbi__png p; p.s = s; return stbi__do_png(&p, x,y,comp,req_comp, ri); } static int stbi__png_test(stbi__context *s) { int r; r = stbi__check_png_header(s); stbi__rewind(s); return r; } static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) { if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { stbi__rewind( p->s ); return 0; } if (x) *x = p->s->img_x; if (y) *y = p->s->img_y; if (comp) *comp = p->s->img_n; return 1; } static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) { stbi__png p; p.s = s; return stbi__png_info_raw(&p, x, y, comp); } static int stbi__png_is16(stbi__context *s) { stbi__png p; p.s = s; if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) return 0; if (p.depth != 16) { stbi__rewind(p.s); return 0; } return 1; } #endif // Microsoft/Windows BMP image #ifndef STBI_NO_BMP static int stbi__bmp_test_raw(stbi__context *s) { int r; int sz; if (stbi__get8(s) != 'B') return 0; if (stbi__get8(s) != 'M') return 0; stbi__get32le(s); // discard filesize stbi__get16le(s); // discard reserved stbi__get16le(s); // discard reserved stbi__get32le(s); // discard data offset sz = stbi__get32le(s); r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); return r; } static int stbi__bmp_test(stbi__context *s) { int r = stbi__bmp_test_raw(s); stbi__rewind(s); return r; } // returns 0..31 for the highest set bit static int stbi__high_bit(unsigned int z) { int n=0; if (z == 0) return -1; if (z >= 0x10000) { n += 16; z >>= 16; } if (z >= 0x00100) { n += 8; z >>= 8; } if (z >= 0x00010) { n += 4; z >>= 4; } if (z >= 0x00004) { n += 2; z >>= 2; } if (z >= 0x00002) { n += 1;/* >>= 1;*/ } return n; } static int stbi__bitcount(unsigned int a) { a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits a = (a + (a >> 8)); // max 16 per 8 bits a = (a + (a >> 16)); // max 32 per 8 bits return a & 0xff; } // extract an arbitrarily-aligned N-bit value (N=bits) // from v, and then make it 8-bits long and fractionally // extend it to full full range. static int stbi__shiftsigned(unsigned int v, int shift, int bits) { static unsigned int mul_table[9] = { 0, 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, }; static unsigned int shift_table[9] = { 0, 0,0,1,0,2,4,6,0, }; if (shift < 0) v <<= -shift; else v >>= shift; STBI_ASSERT(v < 256); v >>= (8-bits); STBI_ASSERT(bits >= 0 && bits <= 8); return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; } typedef struct { int bpp, offset, hsz; unsigned int mr,mg,mb,ma, all_a; int extra_read; } stbi__bmp_data; static int stbi__bmp_set_mask_defaults(stbi__bmp_data *info, int compress) { // BI_BITFIELDS specifies masks explicitly, don't override if (compress == 3) return 1; if (compress == 0) { if (info->bpp == 16) { info->mr = 31u << 10; info->mg = 31u << 5; info->mb = 31u << 0; } else if (info->bpp == 32) { info->mr = 0xffu << 16; info->mg = 0xffu << 8; info->mb = 0xffu << 0; info->ma = 0xffu << 24; info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 } else { // otherwise, use defaults, which is all-0 info->mr = info->mg = info->mb = info->ma = 0; } return 1; } return 0; // error } static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) { int hsz; if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); stbi__get32le(s); // discard filesize stbi__get16le(s); // discard reserved stbi__get16le(s); // discard reserved info->offset = stbi__get32le(s); info->hsz = hsz = stbi__get32le(s); info->mr = info->mg = info->mb = info->ma = 0; info->extra_read = 14; if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP"); if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); if (hsz == 12) { s->img_x = stbi__get16le(s); s->img_y = stbi__get16le(s); } else { s->img_x = stbi__get32le(s); s->img_y = stbi__get32le(s); } if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); info->bpp = stbi__get16le(s); if (hsz != 12) { int compress = stbi__get32le(s); if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); if (compress >= 4) return stbi__errpuc("BMP JPEG/PNG", "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes if (compress == 3 && info->bpp != 16 && info->bpp != 32) return stbi__errpuc("bad BMP", "bad BMP"); // bitfields requires 16 or 32 bits/pixel stbi__get32le(s); // discard sizeof stbi__get32le(s); // discard hres stbi__get32le(s); // discard vres stbi__get32le(s); // discard colorsused stbi__get32le(s); // discard max important if (hsz == 40 || hsz == 56) { if (hsz == 56) { stbi__get32le(s); stbi__get32le(s); stbi__get32le(s); stbi__get32le(s); } if (info->bpp == 16 || info->bpp == 32) { if (compress == 0) { stbi__bmp_set_mask_defaults(info, compress); } else if (compress == 3) { info->mr = stbi__get32le(s); info->mg = stbi__get32le(s); info->mb = stbi__get32le(s); info->extra_read += 12; // not documented, but generated by photoshop and handled by mspaint if (info->mr == info->mg && info->mg == info->mb) { // ?!?!? return stbi__errpuc("bad BMP", "bad BMP"); } } else return stbi__errpuc("bad BMP", "bad BMP"); } } else { // V4/V5 header int i; if (hsz != 108 && hsz != 124) return stbi__errpuc("bad BMP", "bad BMP"); info->mr = stbi__get32le(s); info->mg = stbi__get32le(s); info->mb = stbi__get32le(s); info->ma = stbi__get32le(s); if (compress != 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs stbi__bmp_set_mask_defaults(info, compress); stbi__get32le(s); // discard color space for (i=0; i < 12; ++i) stbi__get32le(s); // discard color space parameters if (hsz == 124) { stbi__get32le(s); // discard rendering intent stbi__get32le(s); // discard offset of profile data stbi__get32le(s); // discard size of profile data stbi__get32le(s); // discard reserved } } } return (void *) 1; } static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { stbi_uc *out; unsigned int mr=0,mg=0,mb=0,ma=0, all_a; stbi_uc pal[256][4]; int psize=0,i,j,width; int flip_vertically, pad, target; stbi__bmp_data info; STBI_NOTUSED(ri); info.all_a = 255; if (stbi__bmp_parse_header(s, &info) == NULL) return NULL; // error code already set flip_vertically = ((int) s->img_y) > 0; s->img_y = abs((int) s->img_y); if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); mr = info.mr; mg = info.mg; mb = info.mb; ma = info.ma; all_a = info.all_a; if (info.hsz == 12) { if (info.bpp < 24) psize = (info.offset - info.extra_read - 24) / 3; } else { if (info.bpp < 16) psize = (info.offset - info.extra_read - info.hsz) >> 2; } if (psize == 0) { // accept some number of extra bytes after the header, but if the offset points either to before // the header ends or implies a large amount of extra data, reject the file as malformed int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original); int header_limit = 1024; // max we actually read is below 256 bytes currently. int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size. if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) { return stbi__errpuc("bad header", "Corrupt BMP"); } // we established that bytes_read_so_far is positive and sensible. // the first half of this test rejects offsets that are either too small positives, or // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn // ensures the number computed in the second half of the test can't overflow. if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) { return stbi__errpuc("bad offset", "Corrupt BMP"); } else { stbi__skip(s, info.offset - bytes_read_so_far); } } if (info.bpp == 24 && ma == 0xff000000) s->img_n = 3; else s->img_n = ma ? 4 : 3; if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 target = req_comp; else target = s->img_n; // if they want monochrome, we'll post-convert // sanity-check size if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) return stbi__errpuc("too large", "Corrupt BMP"); out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); if (!out) return stbi__errpuc("outofmem", "Out of memory"); if (info.bpp < 16) { int z=0; if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } for (i=0; i < psize; ++i) { pal[i][2] = stbi__get8(s); pal[i][1] = stbi__get8(s); pal[i][0] = stbi__get8(s); if (info.hsz != 12) stbi__get8(s); pal[i][3] = 255; } stbi__skip(s, info.offset - info.extra_read - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); if (info.bpp == 1) width = (s->img_x + 7) >> 3; else if (info.bpp == 4) width = (s->img_x + 1) >> 1; else if (info.bpp == 8) width = s->img_x; else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } pad = (-width)&3; if (info.bpp == 1) { for (j=0; j < (int) s->img_y; ++j) { int bit_offset = 7, v = stbi__get8(s); for (i=0; i < (int) s->img_x; ++i) { int color = (v>>bit_offset)&0x1; out[z++] = pal[color][0]; out[z++] = pal[color][1]; out[z++] = pal[color][2]; if (target == 4) out[z++] = 255; if (i+1 == (int) s->img_x) break; if((--bit_offset) < 0) { bit_offset = 7; v = stbi__get8(s); } } stbi__skip(s, pad); } } else { for (j=0; j < (int) s->img_y; ++j) { for (i=0; i < (int) s->img_x; i += 2) { int v=stbi__get8(s),v2=0; if (info.bpp == 4) { v2 = v & 15; v >>= 4; } out[z++] = pal[v][0]; out[z++] = pal[v][1]; out[z++] = pal[v][2]; if (target == 4) out[z++] = 255; if (i+1 == (int) s->img_x) break; v = (info.bpp == 8) ? stbi__get8(s) : v2; out[z++] = pal[v][0]; out[z++] = pal[v][1]; out[z++] = pal[v][2]; if (target == 4) out[z++] = 255; } stbi__skip(s, pad); } } } else { int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; int z = 0; int easy=0; stbi__skip(s, info.offset - info.extra_read - info.hsz); if (info.bpp == 24) width = 3 * s->img_x; else if (info.bpp == 16) width = 2*s->img_x; else /* bpp = 32 and pad = 0 */ width=0; pad = (-width) & 3; if (info.bpp == 24) { easy = 1; } else if (info.bpp == 32) { if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) easy = 2; } if (!easy) { if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } // right shift amt to put high bit in position #7 rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } } for (j=0; j < (int) s->img_y; ++j) { if (easy) { for (i=0; i < (int) s->img_x; ++i) { unsigned char a; out[z+2] = stbi__get8(s); out[z+1] = stbi__get8(s); out[z+0] = stbi__get8(s); z += 3; a = (easy == 2 ? stbi__get8(s) : 255); all_a |= a; if (target == 4) out[z++] = a; } } else { int bpp = info.bpp; for (i=0; i < (int) s->img_x; ++i) { stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); unsigned int a; out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); all_a |= a; if (target == 4) out[z++] = STBI__BYTECAST(a); } } stbi__skip(s, pad); } } // if alpha channel is all 0s, replace with all 255s if (target == 4 && all_a == 0) for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) out[i] = 255; if (flip_vertically) { stbi_uc t; for (j=0; j < (int) s->img_y>>1; ++j) { stbi_uc *p1 = out + j *s->img_x*target; stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; for (i=0; i < (int) s->img_x*target; ++i) { t = p1[i]; p1[i] = p2[i]; p2[i] = t; } } } if (req_comp && req_comp != target) { out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); if (out == NULL) return out; // stbi__convert_format frees input on failure } *x = s->img_x; *y = s->img_y; if (comp) *comp = s->img_n; return out; } #endif // Targa Truevision - TGA // by Jonathan Dummer #ifndef STBI_NO_TGA // returns STBI_rgb or whatever, 0 on error static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) { // only RGB or RGBA (incl. 16bit) or grey allowed if (is_rgb16) *is_rgb16 = 0; switch(bits_per_pixel) { case 8: return STBI_grey; case 16: if(is_grey) return STBI_grey_alpha; // fallthrough case 15: if(is_rgb16) *is_rgb16 = 1; return STBI_rgb; case 24: // fallthrough case 32: return bits_per_pixel/8; default: return 0; } } static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) { int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; int sz, tga_colormap_type; stbi__get8(s); // discard Offset tga_colormap_type = stbi__get8(s); // colormap type if( tga_colormap_type > 1 ) { stbi__rewind(s); return 0; // only RGB or indexed allowed } tga_image_type = stbi__get8(s); // image type if ( tga_colormap_type == 1 ) { // colormapped (paletted) image if (tga_image_type != 1 && tga_image_type != 9) { stbi__rewind(s); return 0; } stbi__skip(s,4); // skip index of first colormap entry and number of entries sz = stbi__get8(s); // check bits per palette color entry if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { stbi__rewind(s); return 0; } stbi__skip(s,4); // skip image x and y origin tga_colormap_bpp = sz; } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { stbi__rewind(s); return 0; // only RGB or grey allowed, +/- RLE } stbi__skip(s,9); // skip colormap specification and image x/y origin tga_colormap_bpp = 0; } tga_w = stbi__get16le(s); if( tga_w < 1 ) { stbi__rewind(s); return 0; // test width } tga_h = stbi__get16le(s); if( tga_h < 1 ) { stbi__rewind(s); return 0; // test height } tga_bits_per_pixel = stbi__get8(s); // bits per pixel stbi__get8(s); // ignore alpha bits if (tga_colormap_bpp != 0) { if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { // when using a colormap, tga_bits_per_pixel is the size of the indexes // I don't think anything but 8 or 16bit indexes makes sense stbi__rewind(s); return 0; } tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); } else { tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); } if(!tga_comp) { stbi__rewind(s); return 0; } if (x) *x = tga_w; if (y) *y = tga_h; if (comp) *comp = tga_comp; return 1; // seems to have passed everything } static int stbi__tga_test(stbi__context *s) { int res = 0; int sz, tga_color_type; stbi__get8(s); // discard Offset tga_color_type = stbi__get8(s); // color type if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed sz = stbi__get8(s); // image type if ( tga_color_type == 1 ) { // colormapped (paletted) image if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 stbi__skip(s,4); // skip index of first colormap entry and number of entries sz = stbi__get8(s); // check bits per palette color entry if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; stbi__skip(s,4); // skip image x and y origin } else { // "normal" image w/o colormap if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE stbi__skip(s,9); // skip colormap specification and image x/y origin } if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height sz = stbi__get8(s); // bits per pixel if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; res = 1; // if we got this far, everything's good and we can return 1 instead of 0 errorEnd: stbi__rewind(s); return res; } // read 16bit value and convert to 24bit RGB static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) { stbi__uint16 px = (stbi__uint16)stbi__get16le(s); stbi__uint16 fiveBitMask = 31; // we have 3 channels with 5bits each int r = (px >> 10) & fiveBitMask; int g = (px >> 5) & fiveBitMask; int b = px & fiveBitMask; // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later out[0] = (stbi_uc)((r * 255)/31); out[1] = (stbi_uc)((g * 255)/31); out[2] = (stbi_uc)((b * 255)/31); // some people claim that the most significant bit might be used for alpha // (possibly if an alpha-bit is set in the "image descriptor byte") // but that only made 16bit test images completely translucent.. // so let's treat all 15 and 16bit TGAs as RGB with no alpha. } static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { // read in the TGA header stuff int tga_offset = stbi__get8(s); int tga_indexed = stbi__get8(s); int tga_image_type = stbi__get8(s); int tga_is_RLE = 0; int tga_palette_start = stbi__get16le(s); int tga_palette_len = stbi__get16le(s); int tga_palette_bits = stbi__get8(s); int tga_x_origin = stbi__get16le(s); int tga_y_origin = stbi__get16le(s); int tga_width = stbi__get16le(s); int tga_height = stbi__get16le(s); int tga_bits_per_pixel = stbi__get8(s); int tga_comp, tga_rgb16=0; int tga_inverted = stbi__get8(s); // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) // image data unsigned char *tga_data; unsigned char *tga_palette = NULL; int i, j; unsigned char raw_data[4] = {0}; int RLE_count = 0; int RLE_repeating = 0; int read_next_pixel = 1; STBI_NOTUSED(ri); STBI_NOTUSED(tga_x_origin); // @TODO STBI_NOTUSED(tga_y_origin); // @TODO if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); // do a tiny bit of precessing if ( tga_image_type >= 8 ) { tga_image_type -= 8; tga_is_RLE = 1; } tga_inverted = 1 - ((tga_inverted >> 5) & 1); // If I'm paletted, then I'll use the number of bits from the palette if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); // tga info *x = tga_width; *y = tga_height; if (comp) *comp = tga_comp; if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) return stbi__errpuc("too large", "Corrupt TGA"); tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); // skip to the data's starting position (offset usually = 0) stbi__skip(s, tga_offset ); if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { for (i=0; i < tga_height; ++i) { int row = tga_inverted ? tga_height -i - 1 : i; stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; stbi__getn(s, tga_row, tga_width * tga_comp); } } else { // do I need to load a palette? if ( tga_indexed) { if (tga_palette_len == 0) { /* you have to have at least one entry! */ STBI_FREE(tga_data); return stbi__errpuc("bad palette", "Corrupt TGA"); } // any data to skip? (offset usually = 0) stbi__skip(s, tga_palette_start ); // load the palette tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); if (!tga_palette) { STBI_FREE(tga_data); return stbi__errpuc("outofmem", "Out of memory"); } if (tga_rgb16) { stbi_uc *pal_entry = tga_palette; STBI_ASSERT(tga_comp == STBI_rgb); for (i=0; i < tga_palette_len; ++i) { stbi__tga_read_rgb16(s, pal_entry); pal_entry += tga_comp; } } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { STBI_FREE(tga_data); STBI_FREE(tga_palette); return stbi__errpuc("bad palette", "Corrupt TGA"); } } // load the data for (i=0; i < tga_width * tga_height; ++i) { // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? if ( tga_is_RLE ) { if ( RLE_count == 0 ) { // yep, get the next byte as a RLE command int RLE_cmd = stbi__get8(s); RLE_count = 1 + (RLE_cmd & 127); RLE_repeating = RLE_cmd >> 7; read_next_pixel = 1; } else if ( !RLE_repeating ) { read_next_pixel = 1; } } else { read_next_pixel = 1; } // OK, if I need to read a pixel, do it now if ( read_next_pixel ) { // load however much data we did have if ( tga_indexed ) { // read in index, then perform the lookup int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); if ( pal_idx >= tga_palette_len ) { // invalid index pal_idx = 0; } pal_idx *= tga_comp; for (j = 0; j < tga_comp; ++j) { raw_data[j] = tga_palette[pal_idx+j]; } } else if(tga_rgb16) { STBI_ASSERT(tga_comp == STBI_rgb); stbi__tga_read_rgb16(s, raw_data); } else { // read in the data raw for (j = 0; j < tga_comp; ++j) { raw_data[j] = stbi__get8(s); } } // clear the reading flag for the next pixel read_next_pixel = 0; } // end of reading a pixel // copy data for (j = 0; j < tga_comp; ++j) tga_data[i*tga_comp+j] = raw_data[j]; // in case we're in RLE mode, keep counting down --RLE_count; } // do I need to invert the image? if ( tga_inverted ) { for (j = 0; j*2 < tga_height; ++j) { int index1 = j * tga_width * tga_comp; int index2 = (tga_height - 1 - j) * tga_width * tga_comp; for (i = tga_width * tga_comp; i > 0; --i) { unsigned char temp = tga_data[index1]; tga_data[index1] = tga_data[index2]; tga_data[index2] = temp; ++index1; ++index2; } } } // clear my palette, if I had one if ( tga_palette != NULL ) { STBI_FREE( tga_palette ); } } // swap RGB - if the source data was RGB16, it already is in the right order if (tga_comp >= 3 && !tga_rgb16) { unsigned char* tga_pixel = tga_data; for (i=0; i < tga_width * tga_height; ++i) { unsigned char temp = tga_pixel[0]; tga_pixel[0] = tga_pixel[2]; tga_pixel[2] = temp; tga_pixel += tga_comp; } } // convert to target component count if (req_comp && req_comp != tga_comp) tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); // the things I do to get rid of an error message, and yet keep // Microsoft's C compilers happy... [8^( tga_palette_start = tga_palette_len = tga_palette_bits = tga_x_origin = tga_y_origin = 0; STBI_NOTUSED(tga_palette_start); // OK, done return tga_data; } #endif // ************************************************************************************************* // Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB #ifndef STBI_NO_PSD static int stbi__psd_test(stbi__context *s) { int r = (stbi__get32be(s) == 0x38425053); stbi__rewind(s); return r; } static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) { int count, nleft, len; count = 0; while ((nleft = pixelCount - count) > 0) { len = stbi__get8(s); if (len == 128) { // No-op. } else if (len < 128) { // Copy next len+1 bytes literally. len++; if (len > nleft) return 0; // corrupt data count += len; while (len) { *p = stbi__get8(s); p += 4; len--; } } else if (len > 128) { stbi_uc val; // Next -len+1 bytes in the dest are replicated from next source byte. // (Interpret len as a negative 8-bit int.) len = 257 - len; if (len > nleft) return 0; // corrupt data val = stbi__get8(s); count += len; while (len) { *p = val; p += 4; len--; } } } return 1; } static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) { int pixelCount; int channelCount, compression; int channel, i; int bitdepth; int w,h; stbi_uc *out; STBI_NOTUSED(ri); // Check identifier if (stbi__get32be(s) != 0x38425053) // "8BPS" return stbi__errpuc("not PSD", "Corrupt PSD image"); // Check file type version. if (stbi__get16be(s) != 1) return stbi__errpuc("wrong version", "Unsupported version of PSD image"); // Skip 6 reserved bytes. stbi__skip(s, 6 ); // Read the number of channels (R, G, B, A, etc). channelCount = stbi__get16be(s); if (channelCount < 0 || channelCount > 16) return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); // Read the rows and columns of the image. h = stbi__get32be(s); w = stbi__get32be(s); if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); // Make sure the depth is 8 bits. bitdepth = stbi__get16be(s); if (bitdepth != 8 && bitdepth != 16) return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); // Make sure the color mode is RGB. // Valid options are: // 0: Bitmap // 1: Grayscale // 2: Indexed color // 3: RGB color // 4: CMYK color // 7: Multichannel // 8: Duotone // 9: Lab color if (stbi__get16be(s) != 3) return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) stbi__skip(s,stbi__get32be(s) ); // Skip the image resources. (resolution, pen tool paths, etc) stbi__skip(s, stbi__get32be(s) ); // Skip the reserved data. stbi__skip(s, stbi__get32be(s) ); // Find out if the data is compressed. // Known values: // 0: no compression // 1: RLE compressed compression = stbi__get16be(s); if (compression > 1) return stbi__errpuc("bad compression", "PSD has an unknown compression format"); // Check size if (!stbi__mad3sizes_valid(4, w, h, 0)) return stbi__errpuc("too large", "Corrupt PSD"); // Create the destination image. if (!compression && bitdepth == 16 && bpc == 16) { out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0); ri->bits_per_channel = 16; } else out = (stbi_uc *) stbi__malloc(4 * w*h); if (!out) return stbi__errpuc("outofmem", "Out of memory"); pixelCount = w*h; // Initialize the data to zero. //memset( out, 0, pixelCount * 4 ); // Finally, the image data. if (compression) { // RLE as used by .PSD and .TIFF // Loop until you get the number of unpacked bytes you are expecting: // Read the next source byte into n. // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. // Else if n is 128, noop. // Endloop // The RLE-compressed data is preceded by a 2-byte data count for each row in the data, // which we're going to just skip. stbi__skip(s, h * channelCount * 2 ); // Read the RLE data by channel. for (channel = 0; channel < 4; channel++) { stbi_uc *p; p = out+channel; if (channel >= channelCount) { // Fill this channel with default data. for (i = 0; i < pixelCount; i++, p += 4) *p = (channel == 3 ? 255 : 0); } else { // Read the RLE data. if (!stbi__psd_decode_rle(s, p, pixelCount)) { STBI_FREE(out); return stbi__errpuc("corrupt", "bad RLE data"); } } } } else { // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. // Read the data by channel. for (channel = 0; channel < 4; channel++) { if (channel >= channelCount) { // Fill this channel with default data. if (bitdepth == 16 && bpc == 16) { stbi__uint16 *q = ((stbi__uint16 *) out) + channel; stbi__uint16 val = channel == 3 ? 65535 : 0; for (i = 0; i < pixelCount; i++, q += 4) *q = val; } else { stbi_uc *p = out+channel; stbi_uc val = channel == 3 ? 255 : 0; for (i = 0; i < pixelCount; i++, p += 4) *p = val; } } else { if (ri->bits_per_channel == 16) { // output bpc stbi__uint16 *q = ((stbi__uint16 *) out) + channel; for (i = 0; i < pixelCount; i++, q += 4) *q = (stbi__uint16) stbi__get16be(s); } else { stbi_uc *p = out+channel; if (bitdepth == 16) { // input bpc for (i = 0; i < pixelCount; i++, p += 4) *p = (stbi_uc) (stbi__get16be(s) >> 8); } else { for (i = 0; i < pixelCount; i++, p += 4) *p = stbi__get8(s); } } } } } // remove weird white matte from PSD if (channelCount >= 4) { if (ri->bits_per_channel == 16) { for (i=0; i < w*h; ++i) { stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; if (pixel[3] != 0 && pixel[3] != 65535) { float a = pixel[3] / 65535.0f; float ra = 1.0f / a; float inv_a = 65535.0f * (1 - ra); pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); } } } else { for (i=0; i < w*h; ++i) { unsigned char *pixel = out + 4*i; if (pixel[3] != 0 && pixel[3] != 255) { float a = pixel[3] / 255.0f; float ra = 1.0f / a; float inv_a = 255.0f * (1 - ra); pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); } } } } // convert to desired output format if (req_comp && req_comp != 4) { if (ri->bits_per_channel == 16) out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); else out = stbi__convert_format(out, 4, req_comp, w, h); if (out == NULL) return out; // stbi__convert_format frees input on failure } if (comp) *comp = 4; *y = h; *x = w; return out; } #endif // ************************************************************************************************* // Softimage PIC loader // by Tom Seddon // // See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format // See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ #ifndef STBI_NO_PIC static int stbi__pic_is4(stbi__context *s,const char *str) { int i; for (i=0; i<4; ++i) if (stbi__get8(s) != (stbi_uc)str[i]) return 0; return 1; } static int stbi__pic_test_core(stbi__context *s) { int i; if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) return 0; for(i=0;i<84;++i) stbi__get8(s); if (!stbi__pic_is4(s,"PICT")) return 0; return 1; } typedef struct { stbi_uc size,type,channel; } stbi__pic_packet; static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) { int mask=0x80, i; for (i=0; i<4; ++i, mask>>=1) { if (channel & mask) { if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); dest[i]=stbi__get8(s); } } return dest; } static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) { int mask=0x80,i; for (i=0;i<4; ++i, mask>>=1) if (channel&mask) dest[i]=src[i]; } static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) { int act_comp=0,num_packets=0,y,chained; stbi__pic_packet packets[10]; // this will (should...) cater for even some bizarre stuff like having data // for the same channel in multiple packets. do { stbi__pic_packet *packet; if (num_packets==sizeof(packets)/sizeof(packets[0])) return stbi__errpuc("bad format","too many packets"); packet = &packets[num_packets++]; chained = stbi__get8(s); packet->size = stbi__get8(s); packet->type = stbi__get8(s); packet->channel = stbi__get8(s); act_comp |= packet->channel; if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); } while (chained); *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? for(y=0; ytype) { default: return stbi__errpuc("bad format","packet has bad compression type"); case 0: {//uncompressed int x; for(x=0;xchannel,dest)) return 0; break; } case 1://Pure RLE { int left=width, i; while (left>0) { stbi_uc count,value[4]; count=stbi__get8(s); if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); if (count > left) count = (stbi_uc) left; if (!stbi__readval(s,packet->channel,value)) return 0; for(i=0; ichannel,dest,value); left -= count; } } break; case 2: {//Mixed RLE int left=width; while (left>0) { int count = stbi__get8(s), i; if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); if (count >= 128) { // Repeated stbi_uc value[4]; if (count==128) count = stbi__get16be(s); else count -= 127; if (count > left) return stbi__errpuc("bad file","scanline overrun"); if (!stbi__readval(s,packet->channel,value)) return 0; for(i=0;ichannel,dest,value); } else { // Raw ++count; if (count>left) return stbi__errpuc("bad file","scanline overrun"); for(i=0;ichannel,dest)) return 0; } left-=count; } break; } } } } return result; } static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) { stbi_uc *result; int i, x,y, internal_comp; STBI_NOTUSED(ri); if (!comp) comp = &internal_comp; for (i=0; i<92; ++i) stbi__get8(s); x = stbi__get16be(s); y = stbi__get16be(s); if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); stbi__get32be(s); //skip `ratio' stbi__get16be(s); //skip `fields' stbi__get16be(s); //skip `pad' // intermediate buffer is RGBA result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); if (!result) return stbi__errpuc("outofmem", "Out of memory"); memset(result, 0xff, x*y*4); if (!stbi__pic_load_core(s,x,y,comp, result)) { STBI_FREE(result); result=0; } *px = x; *py = y; if (req_comp == 0) req_comp = *comp; result=stbi__convert_format(result,4,req_comp,x,y); return result; } static int stbi__pic_test(stbi__context *s) { int r = stbi__pic_test_core(s); stbi__rewind(s); return r; } #endif // ************************************************************************************************* // GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb #ifndef STBI_NO_GIF typedef struct { stbi__int16 prefix; stbi_uc first; stbi_uc suffix; } stbi__gif_lzw; typedef struct { int w,h; stbi_uc *out; // output buffer (always 4 components) stbi_uc *background; // The current "background" as far as a gif is concerned stbi_uc *history; int flags, bgindex, ratio, transparent, eflags; stbi_uc pal[256][4]; stbi_uc lpal[256][4]; stbi__gif_lzw codes[8192]; stbi_uc *color_table; int parse, step; int lflags; int start_x, start_y; int max_x, max_y; int cur_x, cur_y; int line_size; int delay; } stbi__gif; static int stbi__gif_test_raw(stbi__context *s) { int sz; if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; sz = stbi__get8(s); if (sz != '9' && sz != '7') return 0; if (stbi__get8(s) != 'a') return 0; return 1; } static int stbi__gif_test(stbi__context *s) { int r = stbi__gif_test_raw(s); stbi__rewind(s); return r; } static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) { int i; for (i=0; i < num_entries; ++i) { pal[i][2] = stbi__get8(s); pal[i][1] = stbi__get8(s); pal[i][0] = stbi__get8(s); pal[i][3] = transp == i ? 0 : 255; } } static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) { stbi_uc version; if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return stbi__err("not GIF", "Corrupt GIF"); version = stbi__get8(s); if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); stbi__g_failure_reason = ""; g->w = stbi__get16le(s); g->h = stbi__get16le(s); g->flags = stbi__get8(s); g->bgindex = stbi__get8(s); g->ratio = stbi__get8(s); g->transparent = -1; if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments if (is_info) return 1; if (g->flags & 0x80) stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); return 1; } static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) { stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); if (!g) return stbi__err("outofmem", "Out of memory"); if (!stbi__gif_header(s, g, comp, 1)) { STBI_FREE(g); stbi__rewind( s ); return 0; } if (x) *x = g->w; if (y) *y = g->h; STBI_FREE(g); return 1; } static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) { stbi_uc *p, *c; int idx; // recurse to decode the prefixes, since the linked-list is backwards, // and working backwards through an interleaved image would be nasty if (g->codes[code].prefix >= 0) stbi__out_gif_code(g, g->codes[code].prefix); if (g->cur_y >= g->max_y) return; idx = g->cur_x + g->cur_y; p = &g->out[idx]; g->history[idx / 4] = 1; c = &g->color_table[g->codes[code].suffix * 4]; if (c[3] > 128) { // don't render transparent pixels; p[0] = c[2]; p[1] = c[1]; p[2] = c[0]; p[3] = c[3]; } g->cur_x += 4; if (g->cur_x >= g->max_x) { g->cur_x = g->start_x; g->cur_y += g->step; while (g->cur_y >= g->max_y && g->parse > 0) { g->step = (1 << g->parse) * g->line_size; g->cur_y = g->start_y + (g->step >> 1); --g->parse; } } } static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) { stbi_uc lzw_cs; stbi__int32 len, init_code; stbi__uint32 first; stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; stbi__gif_lzw *p; lzw_cs = stbi__get8(s); if (lzw_cs > 12) return NULL; clear = 1 << lzw_cs; first = 1; codesize = lzw_cs + 1; codemask = (1 << codesize) - 1; bits = 0; valid_bits = 0; for (init_code = 0; init_code < clear; init_code++) { g->codes[init_code].prefix = -1; g->codes[init_code].first = (stbi_uc) init_code; g->codes[init_code].suffix = (stbi_uc) init_code; } // support no starting clear code avail = clear+2; oldcode = -1; len = 0; for(;;) { if (valid_bits < codesize) { if (len == 0) { len = stbi__get8(s); // start new block if (len == 0) return g->out; } --len; bits |= (stbi__int32) stbi__get8(s) << valid_bits; valid_bits += 8; } else { stbi__int32 code = bits & codemask; bits >>= codesize; valid_bits -= codesize; // @OPTIMIZE: is there some way we can accelerate the non-clear path? if (code == clear) { // clear code codesize = lzw_cs + 1; codemask = (1 << codesize) - 1; avail = clear + 2; oldcode = -1; first = 0; } else if (code == clear + 1) { // end of stream code stbi__skip(s, len); while ((len = stbi__get8(s)) > 0) stbi__skip(s,len); return g->out; } else if (code <= avail) { if (first) { return stbi__errpuc("no clear code", "Corrupt GIF"); } if (oldcode >= 0) { p = &g->codes[avail++]; if (avail > 8192) { return stbi__errpuc("too many codes", "Corrupt GIF"); } p->prefix = (stbi__int16) oldcode; p->first = g->codes[oldcode].first; p->suffix = (code == avail) ? p->first : g->codes[code].first; } else if (code == avail) return stbi__errpuc("illegal code in raster", "Corrupt GIF"); stbi__out_gif_code(g, (stbi__uint16) code); if ((avail & codemask) == 0 && avail <= 0x0FFF) { codesize++; codemask = (1 << codesize) - 1; } oldcode = code; } else { return stbi__errpuc("illegal code in raster", "Corrupt GIF"); } } } } // this function is designed to support animated gifs, although stb_image doesn't support it // two back is the image from two frames ago, used for a very specific disposal format static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) { int dispose; int first_frame; int pi; int pcount; STBI_NOTUSED(req_comp); // on first frame, any non-written pixels get the background colour (non-transparent) first_frame = 0; if (g->out == 0) { if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header if (!stbi__mad3sizes_valid(4, g->w, g->h, 0)) return stbi__errpuc("too large", "GIF image is too large"); pcount = g->w * g->h; g->out = (stbi_uc *) stbi__malloc(4 * pcount); g->background = (stbi_uc *) stbi__malloc(4 * pcount); g->history = (stbi_uc *) stbi__malloc(pcount); if (!g->out || !g->background || !g->history) return stbi__errpuc("outofmem", "Out of memory"); // image is treated as "transparent" at the start - ie, nothing overwrites the current background; // background colour is only used for pixels that are not rendered first frame, after that "background" // color refers to the color that was there the previous frame. memset(g->out, 0x00, 4 * pcount); memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent) memset(g->history, 0x00, pcount); // pixels that were affected previous frame first_frame = 1; } else { // second frame - how do we dispose of the previous one? dispose = (g->eflags & 0x1C) >> 2; pcount = g->w * g->h; if ((dispose == 3) && (two_back == 0)) { dispose = 2; // if I don't have an image to revert back to, default to the old background } if (dispose == 3) { // use previous graphic for (pi = 0; pi < pcount; ++pi) { if (g->history[pi]) { memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); } } } else if (dispose == 2) { // restore what was changed last frame to background before that frame; for (pi = 0; pi < pcount; ++pi) { if (g->history[pi]) { memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); } } } else { // This is a non-disposal case eithe way, so just // leave the pixels as is, and they will become the new background // 1: do not dispose // 0: not specified. } // background is what out is after the undoing of the previou frame; memcpy( g->background, g->out, 4 * g->w * g->h ); } // clear my history; memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame for (;;) { int tag = stbi__get8(s); switch (tag) { case 0x2C: /* Image Descriptor */ { stbi__int32 x, y, w, h; stbi_uc *o; x = stbi__get16le(s); y = stbi__get16le(s); w = stbi__get16le(s); h = stbi__get16le(s); if (((x + w) > (g->w)) || ((y + h) > (g->h))) return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); g->line_size = g->w * 4; g->start_x = x * 4; g->start_y = y * g->line_size; g->max_x = g->start_x + w * 4; g->max_y = g->start_y + h * g->line_size; g->cur_x = g->start_x; g->cur_y = g->start_y; // if the width of the specified rectangle is 0, that means // we may not see *any* pixels or the image is malformed; // to make sure this is caught, move the current y down to // max_y (which is what out_gif_code checks). if (w == 0) g->cur_y = g->max_y; g->lflags = stbi__get8(s); if (g->lflags & 0x40) { g->step = 8 * g->line_size; // first interlaced spacing g->parse = 3; } else { g->step = g->line_size; g->parse = 0; } if (g->lflags & 0x80) { stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); g->color_table = (stbi_uc *) g->lpal; } else if (g->flags & 0x80) { g->color_table = (stbi_uc *) g->pal; } else return stbi__errpuc("missing color table", "Corrupt GIF"); o = stbi__process_gif_raster(s, g); if (!o) return NULL; // if this was the first frame, pcount = g->w * g->h; if (first_frame && (g->bgindex > 0)) { // if first frame, any pixel not drawn to gets the background color for (pi = 0; pi < pcount; ++pi) { if (g->history[pi] == 0) { g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); } } } return o; } case 0x21: // Comment Extension. { int len; int ext = stbi__get8(s); if (ext == 0xF9) { // Graphic Control Extension. len = stbi__get8(s); if (len == 4) { g->eflags = stbi__get8(s); g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. // unset old transparent if (g->transparent >= 0) { g->pal[g->transparent][3] = 255; } if (g->eflags & 0x01) { g->transparent = stbi__get8(s); if (g->transparent >= 0) { g->pal[g->transparent][3] = 0; } } else { // don't need transparent stbi__skip(s, 1); g->transparent = -1; } } else { stbi__skip(s, len); break; } } while ((len = stbi__get8(s)) != 0) { stbi__skip(s, len); } break; } case 0x3B: // gif stream termination code return (stbi_uc *) s; // using '1' causes warning on some compilers default: return stbi__errpuc("unknown code", "Corrupt GIF"); } } } static void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays) { STBI_FREE(g->out); STBI_FREE(g->history); STBI_FREE(g->background); if (out) STBI_FREE(out); if (delays && *delays) STBI_FREE(*delays); return stbi__errpuc("outofmem", "Out of memory"); } static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) { if (stbi__gif_test(s)) { int layers = 0; stbi_uc *u = 0; stbi_uc *out = 0; stbi_uc *two_back = 0; stbi__gif g; int stride; int out_size = 0; int delays_size = 0; STBI_NOTUSED(out_size); STBI_NOTUSED(delays_size); memset(&g, 0, sizeof(g)); if (delays) { *delays = 0; } do { u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); if (u == (stbi_uc *) s) u = 0; // end of animated gif marker if (u) { *x = g.w; *y = g.h; ++layers; stride = g.w * g.h * 4; if (out) { void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride ); if (!tmp) return stbi__load_gif_main_outofmem(&g, out, delays); else { out = (stbi_uc*) tmp; out_size = layers * stride; } if (delays) { int *new_delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers ); if (!new_delays) return stbi__load_gif_main_outofmem(&g, out, delays); *delays = new_delays; delays_size = layers * sizeof(int); } } else { out = (stbi_uc*)stbi__malloc( layers * stride ); if (!out) return stbi__load_gif_main_outofmem(&g, out, delays); out_size = layers * stride; if (delays) { *delays = (int*) stbi__malloc( layers * sizeof(int) ); if (!*delays) return stbi__load_gif_main_outofmem(&g, out, delays); delays_size = layers * sizeof(int); } } memcpy( out + ((layers - 1) * stride), u, stride ); if (layers >= 2) { two_back = out - 2 * stride; } if (delays) { (*delays)[layers - 1U] = g.delay; } } } while (u != 0); // free temp buffer; STBI_FREE(g.out); STBI_FREE(g.history); STBI_FREE(g.background); // do the final conversion after loading everything; if (req_comp && req_comp != 4) out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); *z = layers; return out; } else { return stbi__errpuc("not GIF", "Image was not as a gif type."); } } static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { stbi_uc *u = 0; stbi__gif g; memset(&g, 0, sizeof(g)); STBI_NOTUSED(ri); u = stbi__gif_load_next(s, &g, comp, req_comp, 0); if (u == (stbi_uc *) s) u = 0; // end of animated gif marker if (u) { *x = g.w; *y = g.h; // moved conversion to after successful load so that the same // can be done for multiple frames. if (req_comp && req_comp != 4) u = stbi__convert_format(u, 4, req_comp, g.w, g.h); } else if (g.out) { // if there was an error and we allocated an image buffer, free it! STBI_FREE(g.out); } // free buffers needed for multiple frame loading; STBI_FREE(g.history); STBI_FREE(g.background); return u; } static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) { return stbi__gif_info_raw(s,x,y,comp); } #endif // ************************************************************************************************* // Radiance RGBE HDR loader // originally by Nicolas Schulz #ifndef STBI_NO_HDR static int stbi__hdr_test_core(stbi__context *s, const char *signature) { int i; for (i=0; signature[i]; ++i) if (stbi__get8(s) != signature[i]) return 0; stbi__rewind(s); return 1; } static int stbi__hdr_test(stbi__context* s) { int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); stbi__rewind(s); if(!r) { r = stbi__hdr_test_core(s, "#?RGBE\n"); stbi__rewind(s); } return r; } #define STBI__HDR_BUFLEN 1024 static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) { int len=0; char c = '\0'; c = (char) stbi__get8(z); while (!stbi__at_eof(z) && c != '\n') { buffer[len++] = c; if (len == STBI__HDR_BUFLEN-1) { // flush to end of line while (!stbi__at_eof(z) && stbi__get8(z) != '\n') ; break; } c = (char) stbi__get8(z); } buffer[len] = 0; return buffer; } static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) { if ( input[3] != 0 ) { float f1; // Exponent f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); if (req_comp <= 2) output[0] = (input[0] + input[1] + input[2]) * f1 / 3; else { output[0] = input[0] * f1; output[1] = input[1] * f1; output[2] = input[2] * f1; } if (req_comp == 2) output[1] = 1; if (req_comp == 4) output[3] = 1; } else { switch (req_comp) { case 4: output[3] = 1; /* fallthrough */ case 3: output[0] = output[1] = output[2] = 0; break; case 2: output[1] = 1; /* fallthrough */ case 1: output[0] = 0; break; } } } static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { char buffer[STBI__HDR_BUFLEN]; char *token; int valid = 0; int width, height; stbi_uc *scanline; float *hdr_data; int len; unsigned char count, value; int i, j, k, c1,c2, z; const char *headerToken; STBI_NOTUSED(ri); // Check identifier headerToken = stbi__hdr_gettoken(s,buffer); if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) return stbi__errpf("not HDR", "Corrupt HDR image"); // Parse header for(;;) { token = stbi__hdr_gettoken(s,buffer); if (token[0] == 0) break; if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; } if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); // Parse width and height // can't use sscanf() if we're not using stdio! token = stbi__hdr_gettoken(s,buffer); if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); token += 3; height = (int) strtol(token, &token, 10); while (*token == ' ') ++token; if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); token += 3; width = (int) strtol(token, NULL, 10); if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); *x = width; *y = height; if (comp) *comp = 3; if (req_comp == 0) req_comp = 3; if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) return stbi__errpf("too large", "HDR image is too large"); // Read data hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); if (!hdr_data) return stbi__errpf("outofmem", "Out of memory"); // Load image data // image data is stored as some number of sca if ( width < 8 || width >= 32768) { // Read flat data for (j=0; j < height; ++j) { for (i=0; i < width; ++i) { stbi_uc rgbe[4]; main_decode_loop: stbi__getn(s, rgbe, 4); stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); } } } else { // Read RLE-encoded data scanline = NULL; for (j = 0; j < height; ++j) { c1 = stbi__get8(s); c2 = stbi__get8(s); len = stbi__get8(s); if (c1 != 2 || c2 != 2 || (len & 0x80)) { // not run-length encoded, so we have to actually use THIS data as a decoded // pixel (note this can't be a valid pixel--one of RGB must be >= 128) stbi_uc rgbe[4]; rgbe[0] = (stbi_uc) c1; rgbe[1] = (stbi_uc) c2; rgbe[2] = (stbi_uc) len; rgbe[3] = (stbi_uc) stbi__get8(s); stbi__hdr_convert(hdr_data, rgbe, req_comp); i = 1; j = 0; STBI_FREE(scanline); goto main_decode_loop; // yes, this makes no sense } len <<= 8; len |= stbi__get8(s); if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } if (scanline == NULL) { scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); if (!scanline) { STBI_FREE(hdr_data); return stbi__errpf("outofmem", "Out of memory"); } } for (k = 0; k < 4; ++k) { int nleft; i = 0; while ((nleft = width - i) > 0) { count = stbi__get8(s); if (count > 128) { // Run value = stbi__get8(s); count -= 128; if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } for (z = 0; z < count; ++z) scanline[i++ * 4 + k] = value; } else { // Dump if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } for (z = 0; z < count; ++z) scanline[i++ * 4 + k] = stbi__get8(s); } } } for (i=0; i < width; ++i) stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); } if (scanline) STBI_FREE(scanline); } return hdr_data; } static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) { char buffer[STBI__HDR_BUFLEN]; char *token; int valid = 0; int dummy; if (!x) x = &dummy; if (!y) y = &dummy; if (!comp) comp = &dummy; if (stbi__hdr_test(s) == 0) { stbi__rewind( s ); return 0; } for(;;) { token = stbi__hdr_gettoken(s,buffer); if (token[0] == 0) break; if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; } if (!valid) { stbi__rewind( s ); return 0; } token = stbi__hdr_gettoken(s,buffer); if (strncmp(token, "-Y ", 3)) { stbi__rewind( s ); return 0; } token += 3; *y = (int) strtol(token, &token, 10); while (*token == ' ') ++token; if (strncmp(token, "+X ", 3)) { stbi__rewind( s ); return 0; } token += 3; *x = (int) strtol(token, NULL, 10); *comp = 3; return 1; } #endif // STBI_NO_HDR #ifndef STBI_NO_BMP static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) { void *p; stbi__bmp_data info; info.all_a = 255; p = stbi__bmp_parse_header(s, &info); if (p == NULL) { stbi__rewind( s ); return 0; } if (x) *x = s->img_x; if (y) *y = s->img_y; if (comp) { if (info.bpp == 24 && info.ma == 0xff000000) *comp = 3; else *comp = info.ma ? 4 : 3; } return 1; } #endif #ifndef STBI_NO_PSD static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) { int channelCount, dummy, depth; if (!x) x = &dummy; if (!y) y = &dummy; if (!comp) comp = &dummy; if (stbi__get32be(s) != 0x38425053) { stbi__rewind( s ); return 0; } if (stbi__get16be(s) != 1) { stbi__rewind( s ); return 0; } stbi__skip(s, 6); channelCount = stbi__get16be(s); if (channelCount < 0 || channelCount > 16) { stbi__rewind( s ); return 0; } *y = stbi__get32be(s); *x = stbi__get32be(s); depth = stbi__get16be(s); if (depth != 8 && depth != 16) { stbi__rewind( s ); return 0; } if (stbi__get16be(s) != 3) { stbi__rewind( s ); return 0; } *comp = 4; return 1; } static int stbi__psd_is16(stbi__context *s) { int channelCount, depth; if (stbi__get32be(s) != 0x38425053) { stbi__rewind( s ); return 0; } if (stbi__get16be(s) != 1) { stbi__rewind( s ); return 0; } stbi__skip(s, 6); channelCount = stbi__get16be(s); if (channelCount < 0 || channelCount > 16) { stbi__rewind( s ); return 0; } STBI_NOTUSED(stbi__get32be(s)); STBI_NOTUSED(stbi__get32be(s)); depth = stbi__get16be(s); if (depth != 16) { stbi__rewind( s ); return 0; } return 1; } #endif #ifndef STBI_NO_PIC static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) { int act_comp=0,num_packets=0,chained,dummy; stbi__pic_packet packets[10]; if (!x) x = &dummy; if (!y) y = &dummy; if (!comp) comp = &dummy; if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { stbi__rewind(s); return 0; } stbi__skip(s, 88); *x = stbi__get16be(s); *y = stbi__get16be(s); if (stbi__at_eof(s)) { stbi__rewind( s); return 0; } if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { stbi__rewind( s ); return 0; } stbi__skip(s, 8); do { stbi__pic_packet *packet; if (num_packets==sizeof(packets)/sizeof(packets[0])) return 0; packet = &packets[num_packets++]; chained = stbi__get8(s); packet->size = stbi__get8(s); packet->type = stbi__get8(s); packet->channel = stbi__get8(s); act_comp |= packet->channel; if (stbi__at_eof(s)) { stbi__rewind( s ); return 0; } if (packet->size != 8) { stbi__rewind( s ); return 0; } } while (chained); *comp = (act_comp & 0x10 ? 4 : 3); return 1; } #endif // ************************************************************************************************* // Portable Gray Map and Portable Pixel Map loader // by Ken Miller // // PGM: http://netpbm.sourceforge.net/doc/pgm.html // PPM: http://netpbm.sourceforge.net/doc/ppm.html // // Known limitations: // Does not support comments in the header section // Does not support ASCII image data (formats P2 and P3) #ifndef STBI_NO_PNM static int stbi__pnm_test(stbi__context *s) { char p, t; p = (char) stbi__get8(s); t = (char) stbi__get8(s); if (p != 'P' || (t != '5' && t != '6')) { stbi__rewind( s ); return 0; } return 1; } static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) { stbi_uc *out; STBI_NOTUSED(ri); ri->bits_per_channel = stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n); if (ri->bits_per_channel == 0) return 0; if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); *x = s->img_x; *y = s->img_y; if (comp) *comp = s->img_n; if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0)) return stbi__errpuc("too large", "PNM too large"); out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0); if (!out) return stbi__errpuc("outofmem", "Out of memory"); if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) { STBI_FREE(out); return stbi__errpuc("bad PNM", "PNM file truncated"); } if (req_comp && req_comp != s->img_n) { if (ri->bits_per_channel == 16) { out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y); } else { out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); } if (out == NULL) return out; // stbi__convert_format frees input on failure } return out; } static int stbi__pnm_isspace(char c) { return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; } static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) { for (;;) { while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) *c = (char) stbi__get8(s); if (stbi__at_eof(s) || *c != '#') break; while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) *c = (char) stbi__get8(s); } } static int stbi__pnm_isdigit(char c) { return c >= '0' && c <= '9'; } static int stbi__pnm_getinteger(stbi__context *s, char *c) { int value = 0; while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { value = value*10 + (*c - '0'); *c = (char) stbi__get8(s); if((value > 214748364) || (value == 214748364 && *c > '7')) return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int"); } return value; } static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) { int maxv, dummy; char c, p, t; if (!x) x = &dummy; if (!y) y = &dummy; if (!comp) comp = &dummy; stbi__rewind(s); // Get identifier p = (char) stbi__get8(s); t = (char) stbi__get8(s); if (p != 'P' || (t != '5' && t != '6')) { stbi__rewind(s); return 0; } *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm c = (char) stbi__get8(s); stbi__pnm_skip_whitespace(s, &c); *x = stbi__pnm_getinteger(s, &c); // read width if(*x == 0) return stbi__err("invalid width", "PPM image header had zero or overflowing width"); stbi__pnm_skip_whitespace(s, &c); *y = stbi__pnm_getinteger(s, &c); // read height if (*y == 0) return stbi__err("invalid width", "PPM image header had zero or overflowing width"); stbi__pnm_skip_whitespace(s, &c); maxv = stbi__pnm_getinteger(s, &c); // read max value if (maxv > 65535) return stbi__err("max value > 65535", "PPM image supports only 8-bit and 16-bit images"); else if (maxv > 255) return 16; else return 8; } static int stbi__pnm_is16(stbi__context *s) { if (stbi__pnm_info(s, NULL, NULL, NULL) == 16) return 1; return 0; } #endif static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) { #ifndef STBI_NO_JPEG if (stbi__jpeg_info(s, x, y, comp)) return 1; #endif #ifndef STBI_NO_PNG if (stbi__png_info(s, x, y, comp)) return 1; #endif #ifndef STBI_NO_GIF if (stbi__gif_info(s, x, y, comp)) return 1; #endif #ifndef STBI_NO_BMP if (stbi__bmp_info(s, x, y, comp)) return 1; #endif #ifndef STBI_NO_PSD if (stbi__psd_info(s, x, y, comp)) return 1; #endif #ifndef STBI_NO_PIC if (stbi__pic_info(s, x, y, comp)) return 1; #endif #ifndef STBI_NO_PNM if (stbi__pnm_info(s, x, y, comp)) return 1; #endif #ifndef STBI_NO_HDR if (stbi__hdr_info(s, x, y, comp)) return 1; #endif // test tga last because it's a crappy test! #ifndef STBI_NO_TGA if (stbi__tga_info(s, x, y, comp)) return 1; #endif return stbi__err("unknown image type", "Image not of any known type, or corrupt"); } static int stbi__is_16_main(stbi__context *s) { #ifndef STBI_NO_PNG if (stbi__png_is16(s)) return 1; #endif #ifndef STBI_NO_PSD if (stbi__psd_is16(s)) return 1; #endif #ifndef STBI_NO_PNM if (stbi__pnm_is16(s)) return 1; #endif return 0; } #ifndef STBI_NO_STDIO STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) { FILE *f = stbi__fopen(filename, "rb"); int result; if (!f) return stbi__err("can't fopen", "Unable to open file"); result = stbi_info_from_file(f, x, y, comp); fclose(f); return result; } STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) { int r; stbi__context s; long pos = ftell(f); stbi__start_file(&s, f); r = stbi__info_main(&s,x,y,comp); fseek(f,pos,SEEK_SET); return r; } STBIDEF int stbi_is_16_bit(char const *filename) { FILE *f = stbi__fopen(filename, "rb"); int result; if (!f) return stbi__err("can't fopen", "Unable to open file"); result = stbi_is_16_bit_from_file(f); fclose(f); return result; } STBIDEF int stbi_is_16_bit_from_file(FILE *f) { int r; stbi__context s; long pos = ftell(f); stbi__start_file(&s, f); r = stbi__is_16_main(&s); fseek(f,pos,SEEK_SET); return r; } #endif // !STBI_NO_STDIO STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) { stbi__context s; stbi__start_mem(&s,buffer,len); return stbi__info_main(&s,x,y,comp); } STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) { stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); return stbi__info_main(&s,x,y,comp); } STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) { stbi__context s; stbi__start_mem(&s,buffer,len); return stbi__is_16_main(&s); } STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) { stbi__context s; stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); return stbi__is_16_main(&s); } #endif // STB_IMAGE_IMPLEMENTATION /* revision history: 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs 2.19 (2018-02-11) fix warning 2.18 (2018-01-30) fix warnings 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug 1-bit BMP *_is_16_bit api avoid warnings 2.16 (2017-07-23) all functions have 16-bit variants; STBI_NO_STDIO works again; compilation fixes; fix rounding in unpremultiply; optimize vertical flip; disable raw_len validation; documentation fixes 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; warning fixes; disable run-time SSE detection on gcc; uniform handling of optional "return" values; thread-safe initialization of zlib tables 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes 2.11 (2016-04-02) allocate large structures on the stack remove white matting for transparent PSD fix reported channel count for PNG & BMP re-enable SSE2 in non-gcc 64-bit support RGB-formatted JPEG read 16-bit PNGs (only as 8-bit) 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED 2.09 (2016-01-16) allow comments in PNM files 16-bit-per-pixel TGA (not bit-per-component) info() for TGA could break due to .hdr handling info() for BMP to shares code instead of sloppy parse can use STBI_REALLOC_SIZED if allocator doesn't support realloc code cleanup 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA 2.07 (2015-09-13) fix compiler warnings partial animated GIF support limited 16-bpc PSD support #ifdef unused functions bug with < 92 byte PIC,PNM,HDR,TGA 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit 2.03 (2015-04-12) extra corruption checking (mmozeiko) stbi_set_flip_vertically_on_load (nguillemot) fix NEON support; fix mingw support 2.02 (2015-01-19) fix incorrect assert, fix warning 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) progressive JPEG (stb) PGM/PPM support (Ken Miller) STBI_MALLOC,STBI_REALLOC,STBI_FREE GIF bugfix -- seemingly never worked STBI_NO_*, STBI_ONLY_* 1.48 (2014-12-14) fix incorrectly-named assert() 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) optimize PNG (ryg) fix bug in interlaced PNG with user-specified channel count (stb) 1.46 (2014-08-26) fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG 1.45 (2014-08-16) fix MSVC-ARM internal compiler error by wrapping malloc 1.44 (2014-08-07) various warning fixes from Ronny Chevalier 1.43 (2014-07-15) fix MSVC-only compiler problem in code changed in 1.42 1.42 (2014-07-09) don't define _CRT_SECURE_NO_WARNINGS (affects user code) fixes to stbi__cleanup_jpeg path added STBI_ASSERT to avoid requiring assert.h 1.41 (2014-06-25) fix search&replace from 1.36 that messed up comments/error messages 1.40 (2014-06-22) fix gcc struct-initialization warning 1.39 (2014-06-15) fix to TGA optimization when req_comp != number of components in TGA; fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) add support for BMP version 5 (more ignored fields) 1.38 (2014-06-06) suppress MSVC warnings on integer casts truncating values fix accidental rename of 'skip' field of I/O 1.37 (2014-06-04) remove duplicate typedef 1.36 (2014-06-03) convert to header file single-file library if de-iphone isn't set, load iphone images color-swapped instead of returning NULL 1.35 (2014-05-27) various warnings fix broken STBI_SIMD path fix bug where stbi_load_from_file no longer left file pointer in correct place fix broken non-easy path for 32-bit BMP (possibly never used) TGA optimization by Arseny Kapoulkine 1.34 (unknown) use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case 1.33 (2011-07-14) make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements 1.32 (2011-07-13) support for "info" function for all supported filetypes (SpartanJ) 1.31 (2011-06-20) a few more leak fixes, bug in PNG handling (SpartanJ) 1.30 (2011-06-11) added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) removed deprecated format-specific test/load functions removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) fix inefficiency in decoding 32-bit BMP (David Woo) 1.29 (2010-08-16) various warning fixes from Aurelien Pocheville 1.28 (2010-08-01) fix bug in GIF palette transparency (SpartanJ) 1.27 (2010-08-01) cast-to-stbi_uc to fix warnings 1.26 (2010-07-24) fix bug in file buffering for PNG reported by SpartanJ 1.25 (2010-07-17) refix trans_data warning (Won Chun) 1.24 (2010-07-12) perf improvements reading from files on platforms with lock-heavy fgetc() minor perf improvements for jpeg deprecated type-specific functions so we'll get feedback if they're needed attempt to fix trans_data warning (Won Chun) 1.23 fixed bug in iPhone support 1.22 (2010-07-10) removed image *writing* support stbi_info support from Jetro Lauha GIF support from Jean-Marc Lienher iPhone PNG-extensions from James Brown warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) 1.21 fix use of 'stbi_uc' in header (reported by jon blow) 1.20 added support for Softimage PIC, by Tom Seddon 1.19 bug in interlaced PNG corruption check (found by ryg) 1.18 (2008-08-02) fix a threading bug (local mutable static) 1.17 support interlaced PNG 1.16 major bugfix - stbi__convert_format converted one too many pixels 1.15 initialize some fields for thread safety 1.14 fix threadsafe conversion bug header-file-only version (#define STBI_HEADER_FILE_ONLY before including) 1.13 threadsafe 1.12 const qualifiers in the API 1.11 Support installable IDCT, colorspace conversion routines 1.10 Fixes for 64-bit (don't use "unsigned long") optimized upsampling by Fabian "ryg" Giesen 1.09 Fix format-conversion for PSD code (bad global variables!) 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz 1.07 attempt to fix C++ warning/errors again 1.06 attempt to fix C++ warning/errors again 1.05 fix TGA loading to return correct *comp and use good luminance calc 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR 1.02 support for (subset of) HDR files, float interface for preferred access to them 1.01 fix bug: possible bug in handling right-side up bmps... not sure fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all 1.00 interface to zlib that skips zlib header 0.99 correct handling of alpha in palette 0.98 TGA loader by lonesock; dynamically add loaders (untested) 0.97 jpeg errors on too large a file; also catch another malloc failure 0.96 fix detection of invalid v value - particleman@mollyrocket forum 0.95 during header scan, seek to markers in case of padding 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same 0.93 handle jpegtran output; verbose errors 0.92 read 4,8,16,24,32-bit BMP files of several formats 0.91 output 24-bit Windows 3.0 BMP files 0.90 fix a few more warnings; bump version number to approach 1.0 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd 0.60 fix compiling as c++ 0.59 fix warnings: merge Dave Moore's -Wall fixes 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available 0.56 fix bug: zlib uncompressed mode len vs. nlen 0.55 fix bug: restart_interval not initialized to 0 0.54 allow NULL for 'int *comp' 0.53 fix bug in png 3->4; speedup png decoding 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments 0.51 obey req_comp requests, 1-component jpegs return as 1-component, on 'test' only check type, not whether we support this variant 0.50 (2006-11-19) first released version */ /* ------------------------------------------------------------------------------ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ RenderKit-ospray-f2a61c2/apps/common/external/stb_image/stb_image_write.h000066400000000000000000002130651456566705700267020ustar00rootroot00000000000000/* stb_image_write - v1.16 - public domain - http://nothings.org/stb writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 no warranty implied; use at your own risk Before #including, #define STB_IMAGE_WRITE_IMPLEMENTATION in the file that you want to have the implementation. Will probably not work correctly with strict-aliasing optimizations. ABOUT: This header file is a library for writing images to C stdio or a callback. The PNG output is not optimal; it is 20-50% larger than the file written by a decent optimizing implementation; though providing a custom zlib compress function (see STBIW_ZLIB_COMPRESS) can mitigate that. This library is designed for source code compactness and simplicity, not optimal image file size or run-time performance. BUILDING: You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace malloc,realloc,free. You can #define STBIW_MEMMOVE() to replace memmove() You can #define STBIW_ZLIB_COMPRESS to use a custom zlib-style compress function for PNG compression (instead of the builtin one), it must have the following signature: unsigned char * my_compress(unsigned char *data, int data_len, int *out_len, int quality); The returned data will be freed with STBIW_FREE() (free() by default), so it must be heap allocated with STBIW_MALLOC() (malloc() by default), UNICODE: If compiling for Windows and you wish to use Unicode filenames, compile with #define STBIW_WINDOWS_UTF8 and pass utf8-encoded filenames. Call stbiw_convert_wchar_to_utf8 to convert Windows wchar_t filenames to utf8. USAGE: There are five functions, one for each image file format: int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); int stbi_write_jpg(char const *filename, int w, int h, int comp, const void *data, int quality); int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); void stbi_flip_vertically_on_write(int flag); // flag is non-zero to flip data vertically There are also five equivalent functions that use an arbitrary write function. You are expected to open/close your file-equivalent before and after calling these: int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); where the callback is: void stbi_write_func(void *context, void *data, int size); You can configure it with these global variables: int stbi_write_tga_with_rle; // defaults to true; set to 0 to disable RLE int stbi_write_png_compression_level; // defaults to 8; set to higher for more compression int stbi_write_force_png_filter; // defaults to -1; set to 0..5 to force a filter mode You can define STBI_WRITE_NO_STDIO to disable the file variant of these functions, so the library will not use stdio.h at all. However, this will also disable HDR writing, because it requires stdio for formatted output. Each function returns 0 on failure and non-0 on success. The functions create an image file defined by the parameters. The image is a rectangle of pixels stored from left-to-right, top-to-bottom. Each pixel contains 'comp' channels of data stored interleaved with 8-bits per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. The *data pointer points to the first byte of the top-left-most pixel. For PNG, "stride_in_bytes" is the distance in bytes from the first byte of a row of pixels to the first byte of the next row of pixels. PNG creates output files with the same number of components as the input. The BMP format expands Y to RGB in the file format and does not output alpha. PNG supports writing rectangles of data even when the bytes storing rows of data are not consecutive in memory (e.g. sub-rectangles of a larger image), by supplying the stride between the beginning of adjacent rows. The other formats do not. (Thus you cannot write a native-format BMP through the BMP writer, both because it is in BGR order and because it may have padding at the end of the line.) PNG allows you to set the deflate compression level by setting the global variable 'stbi_write_png_compression_level' (it defaults to 8). HDR expects linear float data. Since the format is always 32-bit rgb(e) data, alpha (if provided) is discarded, and for monochrome data it is replicated across all three channels. TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed data, set the global variable 'stbi_write_tga_with_rle' to 0. JPEG does ignore alpha channels in input data; quality is between 1 and 100. Higher quality looks better but results in a bigger image. JPEG baseline (no JPEG progressive). CREDITS: Sean Barrett - PNG/BMP/TGA Baldur Karlsson - HDR Jean-Sebastien Guay - TGA monochrome Tim Kelsey - misc enhancements Alan Hickman - TGA RLE Emmanuel Julien - initial file IO callback implementation Jon Olick - original jo_jpeg.cpp code Daniel Gibson - integrate JPEG, allow external zlib Aarni Koskela - allow choosing PNG filter bugfixes: github:Chribba Guillaume Chereau github:jry2 github:romigrou Sergio Gonzalez Jonas Karlsson Filip Wasil Thatcher Ulrich github:poppolopoppo Patrick Boettcher github:xeekworx Cap Petschulat Simon Rodriguez Ivan Tikhonov github:ignotion Adam Schackart Andrew Kensler LICENSE See end of file for license information. */ #ifndef INCLUDE_STB_IMAGE_WRITE_H #define INCLUDE_STB_IMAGE_WRITE_H #include // if STB_IMAGE_WRITE_STATIC causes problems, try defining STBIWDEF to 'inline' or 'static inline' #ifndef STBIWDEF #ifdef STB_IMAGE_WRITE_STATIC #define STBIWDEF static #else #ifdef __cplusplus #define STBIWDEF extern "C" #else #define STBIWDEF extern #endif #endif #endif #ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations STBIWDEF int stbi_write_tga_with_rle; STBIWDEF int stbi_write_png_compression_level; STBIWDEF int stbi_write_force_png_filter; #endif #ifndef STBI_WRITE_NO_STDIO STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality); #ifdef STBIW_WINDOWS_UTF8 STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); #endif #endif typedef void stbi_write_func(void *context, void *data, int size); STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean); #endif//INCLUDE_STB_IMAGE_WRITE_H #ifdef STB_IMAGE_WRITE_IMPLEMENTATION #ifdef _WIN32 #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #endif #ifndef _CRT_NONSTDC_NO_DEPRECATE #define _CRT_NONSTDC_NO_DEPRECATE #endif #endif #ifndef STBI_WRITE_NO_STDIO #include #endif // STBI_WRITE_NO_STDIO #include #include #include #include #if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) // ok #elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) // ok #else #error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." #endif #ifndef STBIW_MALLOC #define STBIW_MALLOC(sz) malloc(sz) #define STBIW_REALLOC(p,newsz) realloc(p,newsz) #define STBIW_FREE(p) free(p) #endif #ifndef STBIW_REALLOC_SIZED #define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) #endif #ifndef STBIW_MEMMOVE #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) #endif #ifndef STBIW_ASSERT #include #define STBIW_ASSERT(x) assert(x) #endif #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) #ifdef STB_IMAGE_WRITE_STATIC static int stbi_write_png_compression_level = 8; static int stbi_write_tga_with_rle = 1; static int stbi_write_force_png_filter = -1; #else int stbi_write_png_compression_level = 8; int stbi_write_tga_with_rle = 1; int stbi_write_force_png_filter = -1; #endif static int stbi__flip_vertically_on_write = 0; STBIWDEF void stbi_flip_vertically_on_write(int flag) { stbi__flip_vertically_on_write = flag; } typedef struct { stbi_write_func *func; void *context; unsigned char buffer[64]; int buf_used; } stbi__write_context; // initialize a callback-based context static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) { s->func = c; s->context = context; } #ifndef STBI_WRITE_NO_STDIO static void stbi__stdio_write(void *context, void *data, int size) { fwrite(data,1,size,(FILE*) context); } #if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8) #ifdef __cplusplus #define STBIW_EXTERN extern "C" #else #define STBIW_EXTERN extern #endif STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); STBIW_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) { return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); } #endif static FILE *stbiw__fopen(char const *filename, char const *mode) { FILE *f; #if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8) wchar_t wMode[64]; wchar_t wFilename[1024]; if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) return 0; if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) return 0; #if defined(_MSC_VER) && _MSC_VER >= 1400 if (0 != _wfopen_s(&f, wFilename, wMode)) f = 0; #else f = _wfopen(wFilename, wMode); #endif #elif defined(_MSC_VER) && _MSC_VER >= 1400 if (0 != fopen_s(&f, filename, mode)) f=0; #else f = fopen(filename, mode); #endif return f; } static int stbi__start_write_file(stbi__write_context *s, const char *filename) { FILE *f = stbiw__fopen(filename, "wb"); stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); return f != NULL; } static void stbi__end_write_file(stbi__write_context *s) { fclose((FILE *)s->context); } #endif // !STBI_WRITE_NO_STDIO typedef unsigned int stbiw_uint32; typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) { while (*fmt) { switch (*fmt++) { case ' ': break; case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); s->func(s->context,&x,1); break; } case '2': { int x = va_arg(v,int); unsigned char b[2]; b[0] = STBIW_UCHAR(x); b[1] = STBIW_UCHAR(x>>8); s->func(s->context,b,2); break; } case '4': { stbiw_uint32 x = va_arg(v,int); unsigned char b[4]; b[0]=STBIW_UCHAR(x); b[1]=STBIW_UCHAR(x>>8); b[2]=STBIW_UCHAR(x>>16); b[3]=STBIW_UCHAR(x>>24); s->func(s->context,b,4); break; } default: STBIW_ASSERT(0); return; } } } static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) { va_list v; va_start(v, fmt); stbiw__writefv(s, fmt, v); va_end(v); } static void stbiw__write_flush(stbi__write_context *s) { if (s->buf_used) { s->func(s->context, &s->buffer, s->buf_used); s->buf_used = 0; } } static void stbiw__putc(stbi__write_context *s, unsigned char c) { s->func(s->context, &c, 1); } static void stbiw__write1(stbi__write_context *s, unsigned char a) { if ((size_t)s->buf_used + 1 > sizeof(s->buffer)) stbiw__write_flush(s); s->buffer[s->buf_used++] = a; } static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) { int n; if ((size_t)s->buf_used + 3 > sizeof(s->buffer)) stbiw__write_flush(s); n = s->buf_used; s->buf_used = n+3; s->buffer[n+0] = a; s->buffer[n+1] = b; s->buffer[n+2] = c; } static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) { unsigned char bg[3] = { 255, 0, 255}, px[3]; int k; if (write_alpha < 0) stbiw__write1(s, d[comp - 1]); switch (comp) { case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case case 1: if (expand_mono) stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp else stbiw__write1(s, d[0]); // monochrome TGA break; case 4: if (!write_alpha) { // composite against pink background for (k = 0; k < 3; ++k) px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); break; } /* FALLTHROUGH */ case 3: stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); break; } if (write_alpha > 0) stbiw__write1(s, d[comp - 1]); } static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) { stbiw_uint32 zero = 0; int i,j, j_end; if (y <= 0) return; if (stbi__flip_vertically_on_write) vdir *= -1; if (vdir < 0) { j_end = -1; j = y-1; } else { j_end = y; j = 0; } for (; j != j_end; j += vdir) { for (i=0; i < x; ++i) { unsigned char *d = (unsigned char *) data + (j*x+i)*comp; stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); } stbiw__write_flush(s); s->func(s->context, &zero, scanline_pad); } } static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) { if (y < 0 || x < 0) { return 0; } else { va_list v; va_start(v, fmt); stbiw__writefv(s, fmt, v); va_end(v); stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); return 1; } } static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) { if (comp != 4) { // write RGB bitmap int pad = (-x*3) & 3; return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, "11 4 22 4" "4 44 22 444444", 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header } else { // RGBA bitmaps need a v4 header // use BI_BITFIELDS mode with 32bpp and alpha mask // (straight BI_RGB with alpha mask doesn't work in most readers) return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *)data,1,0, "11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444", 'B', 'M', 14+108+x*y*4, 0, 0, 14+108, // file header 108, x,y, 1,32, 3,0,0,0,0,0, 0xff0000,0xff00,0xff,0xff000000u, 0, 0,0,0, 0,0,0, 0,0,0, 0,0,0); // bitmap V4 header } } STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) { stbi__write_context s = { 0 }; stbi__start_write_callbacks(&s, func, context); return stbi_write_bmp_core(&s, x, y, comp, data); } #ifndef STBI_WRITE_NO_STDIO STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) { stbi__write_context s = { 0 }; if (stbi__start_write_file(&s,filename)) { int r = stbi_write_bmp_core(&s, x, y, comp, data); stbi__end_write_file(&s); return r; } else return 0; } #endif //!STBI_WRITE_NO_STDIO static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) { int has_alpha = (comp == 2 || comp == 4); int colorbytes = has_alpha ? comp-1 : comp; int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 if (y < 0 || x < 0) return 0; if (!stbi_write_tga_with_rle) { return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); } else { int i,j,k; int jend, jdir; stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); if (stbi__flip_vertically_on_write) { j = 0; jend = y; jdir = 1; } else { j = y-1; jend = -1; jdir = -1; } for (; j != jend; j += jdir) { unsigned char *row = (unsigned char *) data + j * x * comp; int len; for (i = 0; i < x; i += len) { unsigned char *begin = row + i * comp; int diff = 1; len = 1; if (i < x - 1) { ++len; diff = memcmp(begin, row + (i + 1) * comp, comp); if (diff) { const unsigned char *prev = begin; for (k = i + 2; k < x && len < 128; ++k) { if (memcmp(prev, row + k * comp, comp)) { prev += comp; ++len; } else { --len; break; } } } else { for (k = i + 2; k < x && len < 128; ++k) { if (!memcmp(begin, row + k * comp, comp)) { ++len; } else { break; } } } } if (diff) { unsigned char header = STBIW_UCHAR(len - 1); stbiw__write1(s, header); for (k = 0; k < len; ++k) { stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); } } else { unsigned char header = STBIW_UCHAR(len - 129); stbiw__write1(s, header); stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); } } } stbiw__write_flush(s); } return 1; } STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) { stbi__write_context s = { 0 }; stbi__start_write_callbacks(&s, func, context); return stbi_write_tga_core(&s, x, y, comp, (void *) data); } #ifndef STBI_WRITE_NO_STDIO STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) { stbi__write_context s = { 0 }; if (stbi__start_write_file(&s,filename)) { int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); stbi__end_write_file(&s); return r; } else return 0; } #endif // ************************************************************************************************* // Radiance RGBE HDR writer // by Baldur Karlsson #define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) #ifndef STBI_WRITE_NO_STDIO static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) { int exponent; float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); if (maxcomp < 1e-32f) { rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; } else { float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; rgbe[0] = (unsigned char)(linear[0] * normalize); rgbe[1] = (unsigned char)(linear[1] * normalize); rgbe[2] = (unsigned char)(linear[2] * normalize); rgbe[3] = (unsigned char)(exponent + 128); } } static void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) { unsigned char lengthbyte = STBIW_UCHAR(length+128); STBIW_ASSERT(length+128 <= 255); s->func(s->context, &lengthbyte, 1); s->func(s->context, &databyte, 1); } static void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) { unsigned char lengthbyte = STBIW_UCHAR(length); STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code s->func(s->context, &lengthbyte, 1); s->func(s->context, data, length); } static void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) { unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; unsigned char rgbe[4]; float linear[3]; int x; scanlineheader[2] = (width&0xff00)>>8; scanlineheader[3] = (width&0x00ff); /* skip RLE for images too small or large */ if (width < 8 || width >= 32768) { for (x=0; x < width; x++) { switch (ncomp) { case 4: /* fallthrough */ case 3: linear[2] = scanline[x*ncomp + 2]; linear[1] = scanline[x*ncomp + 1]; linear[0] = scanline[x*ncomp + 0]; break; default: linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; break; } stbiw__linear_to_rgbe(rgbe, linear); s->func(s->context, rgbe, 4); } } else { int c,r; /* encode into scratch buffer */ for (x=0; x < width; x++) { switch(ncomp) { case 4: /* fallthrough */ case 3: linear[2] = scanline[x*ncomp + 2]; linear[1] = scanline[x*ncomp + 1]; linear[0] = scanline[x*ncomp + 0]; break; default: linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; break; } stbiw__linear_to_rgbe(rgbe, linear); scratch[x + width*0] = rgbe[0]; scratch[x + width*1] = rgbe[1]; scratch[x + width*2] = rgbe[2]; scratch[x + width*3] = rgbe[3]; } s->func(s->context, scanlineheader, 4); /* RLE each component separately */ for (c=0; c < 4; c++) { unsigned char *comp = &scratch[width*c]; x = 0; while (x < width) { // find first run r = x; while (r+2 < width) { if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) break; ++r; } if (r+2 >= width) r = width; // dump up to first run while (x < r) { int len = r-x; if (len > 128) len = 128; stbiw__write_dump_data(s, len, &comp[x]); x += len; } // if there's a run, output it if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd // find next byte after run while (r < width && comp[r] == comp[x]) ++r; // output run up to r while (x < r) { int len = r-x; if (len > 127) len = 127; stbiw__write_run_data(s, len, comp[x]); x += len; } } } } } } static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) { if (y <= 0 || x <= 0 || data == NULL) return 0; else { // Each component is stored separately. Allocate scratch space for full output scanline. unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); int i, len; char buffer[128]; char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; s->func(s->context, header, sizeof(header)-1); #ifdef __STDC_LIB_EXT1__ len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); #else len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); #endif s->func(s->context, buffer, len); for(i=0; i < y; i++) stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i)); STBIW_FREE(scratch); return 1; } } STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) { stbi__write_context s = { 0 }; stbi__start_write_callbacks(&s, func, context); return stbi_write_hdr_core(&s, x, y, comp, (float *) data); } STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) { stbi__write_context s = { 0 }; if (stbi__start_write_file(&s,filename)) { int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); stbi__end_write_file(&s); return r; } else return 0; } #endif // STBI_WRITE_NO_STDIO ////////////////////////////////////////////////////////////////////////////// // // PNG writer // #ifndef STBIW_ZLIB_COMPRESS // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() #define stbiw__sbraw(a) ((int *) (void *) (a) - 2) #define stbiw__sbm(a) stbiw__sbraw(a)[0] #define stbiw__sbn(a) stbiw__sbraw(a)[1] #define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) #define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) #define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) #define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) { int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); STBIW_ASSERT(p); if (p) { if (!*arr) ((int *) p)[1] = 0; *arr = (void *) ((int *) p + 2); stbiw__sbm(*arr) = m; } return *arr; } static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) { while (*bitcount >= 8) { stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); *bitbuffer >>= 8; *bitcount -= 8; } return data; } static int stbiw__zlib_bitrev(int code, int codebits) { int res=0; while (codebits--) { res = (res << 1) | (code & 1); code >>= 1; } return res; } static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) { int i; for (i=0; i < limit && i < 258; ++i) if (a[i] != b[i]) break; return i; } static unsigned int stbiw__zhash(unsigned char *data) { stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); hash ^= hash << 3; hash += hash >> 5; hash ^= hash << 4; hash += hash >> 17; hash ^= hash << 25; hash += hash >> 6; return hash; } #define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) #define stbiw__zlib_add(code,codebits) \ (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) #define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) // default huffman tables #define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) #define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) #define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) #define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) #define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) #define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) #define stbiw__ZHASH 16384 #endif // STBIW_ZLIB_COMPRESS STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) { #ifdef STBIW_ZLIB_COMPRESS // user provided a zlib compress implementation, use that return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality); #else // use builtin static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; unsigned int bitbuf=0; int i,j, bitcount=0; unsigned char *out = NULL; unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(unsigned char**)); if (hash_table == NULL) return NULL; if (quality < 5) quality = 5; stbiw__sbpush(out, 0x78); // DEFLATE 32K window stbiw__sbpush(out, 0x5e); // FLEVEL = 1 stbiw__zlib_add(1,1); // BFINAL = 1 stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman for (i=0; i < stbiw__ZHASH; ++i) hash_table[i] = NULL; i=0; while (i < data_len-3) { // hash next 3 bytes of data to be compressed int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; unsigned char *bestloc = 0; unsigned char **hlist = hash_table[h]; int n = stbiw__sbcount(hlist); for (j=0; j < n; ++j) { if (hlist[j]-data > i-32768) { // if entry lies within window int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); if (d >= best) { best=d; bestloc=hlist[j]; } } } // when hash table entry is too long, delete half the entries if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); stbiw__sbn(hash_table[h]) = quality; } stbiw__sbpush(hash_table[h],data+i); if (bestloc) { // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); hlist = hash_table[h]; n = stbiw__sbcount(hlist); for (j=0; j < n; ++j) { if (hlist[j]-data > i-32767) { int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); if (e > best) { // if next match is better, bail on current match bestloc = NULL; break; } } } } if (bestloc) { int d = (int) (data+i - bestloc); // distance back STBIW_ASSERT(d <= 32767 && best <= 258); for (j=0; best > lengthc[j+1]-1; ++j); stbiw__zlib_huff(j+257); if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); for (j=0; d > distc[j+1]-1; ++j); stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); i += best; } else { stbiw__zlib_huffb(data[i]); ++i; } } // write out final bytes for (;i < data_len; ++i) stbiw__zlib_huffb(data[i]); stbiw__zlib_huff(256); // end of block // pad with 0 bits to byte boundary while (bitcount) stbiw__zlib_add(0,1); for (i=0; i < stbiw__ZHASH; ++i) (void) stbiw__sbfree(hash_table[i]); STBIW_FREE(hash_table); // store uncompressed instead if compression was worse if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) { stbiw__sbn(out) = 2; // truncate to DEFLATE 32K window and FLEVEL = 1 for (j = 0; j < data_len;) { int blocklen = data_len - j; if (blocklen > 32767) blocklen = 32767; stbiw__sbpush(out, data_len - j == blocklen); // BFINAL = ?, BTYPE = 0 -- no compression stbiw__sbpush(out, STBIW_UCHAR(blocklen)); // LEN stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8)); stbiw__sbpush(out, STBIW_UCHAR(~blocklen)); // NLEN stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8)); memcpy(out+stbiw__sbn(out), data+j, blocklen); stbiw__sbn(out) += blocklen; j += blocklen; } } { // compute adler32 on input unsigned int s1=1, s2=0; int blocklen = (int) (data_len % 5552); j=0; while (j < data_len) { for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; } s1 %= 65521; s2 %= 65521; j += blocklen; blocklen = 5552; } stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); stbiw__sbpush(out, STBIW_UCHAR(s2)); stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); stbiw__sbpush(out, STBIW_UCHAR(s1)); } *out_len = stbiw__sbn(out); // make returned pointer freeable STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); return (unsigned char *) stbiw__sbraw(out); #endif // STBIW_ZLIB_COMPRESS } static unsigned int stbiw__crc32(unsigned char *buffer, int len) { #ifdef STBIW_CRC32 return STBIW_CRC32(buffer, len); #else static unsigned int crc_table[256] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D }; unsigned int crc = ~0u; int i; for (i=0; i < len; ++i) crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; return ~crc; #endif } #define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) static void stbiw__wpcrc(unsigned char **data, int len) { unsigned int crc = stbiw__crc32(*data - len - 4, len+4); stbiw__wp32(*data, crc); } static unsigned char stbiw__paeth(int a, int b, int c) { int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); if (pb <= pc) return STBIW_UCHAR(b); return STBIW_UCHAR(c); } // @OPTIMIZE: provide an option that always forces left-predict or paeth predict static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int width, int height, int y, int n, int filter_type, signed char *line_buffer) { static int mapping[] = { 0,1,2,3,4 }; static int firstmap[] = { 0,1,0,5,6 }; int *mymap = (y != 0) ? mapping : firstmap; int i; int type = mymap[filter_type]; unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y); int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes; if (type==0) { memcpy(line_buffer, z, width*n); return; } // first loop isn't optimized since it's just one pixel for (i = 0; i < n; ++i) { switch (type) { case 1: line_buffer[i] = z[i]; break; case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break; case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1); break; case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0)); break; case 5: line_buffer[i] = z[i]; break; case 6: line_buffer[i] = z[i]; break; } } switch (type) { case 1: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n]; break; case 2: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride]; break; case 3: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break; case 4: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]); break; case 5: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1); break; case 6: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; } } STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) { int force_filter = stbi_write_force_png_filter; int ctype[5] = { -1, 0, 4, 2, 6 }; unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; unsigned char *out,*o, *filt, *zlib; signed char *line_buffer; int j,zlen; if (stride_bytes == 0) stride_bytes = x * n; if (force_filter >= 5) { force_filter = -1; } filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } for (j=0; j < y; ++j) { int filter_type; if (force_filter > -1) { filter_type = force_filter; stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer); } else { // Estimate the best filter by running through all of them: int best_filter = 0, best_filter_val = 0x7fffffff, est, i; for (filter_type = 0; filter_type < 5; filter_type++) { stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer); // Estimate the entropy of the line using this filter; the less, the better. est = 0; for (i = 0; i < x*n; ++i) { est += abs((signed char) line_buffer[i]); } if (est < best_filter_val) { best_filter_val = est; best_filter = filter_type; } } if (filter_type != best_filter) { // If the last iteration already got us the best filter, don't redo it stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer); filter_type = best_filter; } } // when we get here, filter_type contains the filter type, and line_buffer contains the data filt[j*(x*n+1)] = (unsigned char) filter_type; STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); } STBIW_FREE(line_buffer); zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_compression_level); STBIW_FREE(filt); if (!zlib) return 0; // each tag requires 12 bytes of overhead out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); if (!out) return 0; *out_len = 8 + 12+13 + 12+zlen + 12; o=out; STBIW_MEMMOVE(o,sig,8); o+= 8; stbiw__wp32(o, 13); // header length stbiw__wptag(o, "IHDR"); stbiw__wp32(o, x); stbiw__wp32(o, y); *o++ = 8; *o++ = STBIW_UCHAR(ctype[n]); *o++ = 0; *o++ = 0; *o++ = 0; stbiw__wpcrc(&o,13); stbiw__wp32(o, zlen); stbiw__wptag(o, "IDAT"); STBIW_MEMMOVE(o, zlib, zlen); o += zlen; STBIW_FREE(zlib); stbiw__wpcrc(&o, zlen); stbiw__wp32(o,0); stbiw__wptag(o, "IEND"); stbiw__wpcrc(&o,0); STBIW_ASSERT(o == out + *out_len); return out; } #ifndef STBI_WRITE_NO_STDIO STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) { FILE *f; int len; unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); if (png == NULL) return 0; f = stbiw__fopen(filename, "wb"); if (!f) { STBIW_FREE(png); return 0; } fwrite(png, 1, len, f); fclose(f); STBIW_FREE(png); return 1; } #endif STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) { int len; unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); if (png == NULL) return 0; func(context, png, len); STBIW_FREE(png); return 1; } /* *************************************************************************** * * JPEG writer * * This is based on Jon Olick's jo_jpeg.cpp: * public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html */ static const unsigned char stbiw__jpg_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18, 24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 }; static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) { int bitBuf = *bitBufP, bitCnt = *bitCntP; bitCnt += bs[1]; bitBuf |= bs[0] << (24 - bitCnt); while(bitCnt >= 8) { unsigned char c = (bitBuf >> 16) & 255; stbiw__putc(s, c); if(c == 255) { stbiw__putc(s, 0); } bitBuf <<= 8; bitCnt -= 8; } *bitBufP = bitBuf; *bitCntP = bitCnt; } static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) { float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p; float z1, z2, z3, z4, z5, z11, z13; float tmp0 = d0 + d7; float tmp7 = d0 - d7; float tmp1 = d1 + d6; float tmp6 = d1 - d6; float tmp2 = d2 + d5; float tmp5 = d2 - d5; float tmp3 = d3 + d4; float tmp4 = d3 - d4; // Even part float tmp10 = tmp0 + tmp3; // phase 2 float tmp13 = tmp0 - tmp3; float tmp11 = tmp1 + tmp2; float tmp12 = tmp1 - tmp2; d0 = tmp10 + tmp11; // phase 3 d4 = tmp10 - tmp11; z1 = (tmp12 + tmp13) * 0.707106781f; // c4 d2 = tmp13 + z1; // phase 5 d6 = tmp13 - z1; // Odd part tmp10 = tmp4 + tmp5; // phase 2 tmp11 = tmp5 + tmp6; tmp12 = tmp6 + tmp7; // The rotator is modified from fig 4-8 to avoid extra negations. z5 = (tmp10 - tmp12) * 0.382683433f; // c6 z2 = tmp10 * 0.541196100f + z5; // c2-c6 z4 = tmp12 * 1.306562965f + z5; // c2+c6 z3 = tmp11 * 0.707106781f; // c4 z11 = tmp7 + z3; // phase 5 z13 = tmp7 - z3; *d5p = z13 + z2; // phase 6 *d3p = z13 - z2; *d1p = z11 + z4; *d7p = z11 - z4; *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6; } static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) { int tmp1 = val < 0 ? -val : val; val = val < 0 ? val-1 : val; bits[1] = 1; while(tmp1 >>= 1) { ++bits[1]; } bits[0] = val & ((1<0)&&(DU[end0pos]==0); --end0pos) { } // end0pos = first element in reverse order !=0 if(end0pos == 0) { stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); return DU[0]; } for(i = 1; i <= end0pos; ++i) { int startpos = i; int nrzeroes; unsigned short bits[2]; for (; DU[i]==0 && i<=end0pos; ++i) { } nrzeroes = i-startpos; if ( nrzeroes >= 16 ) { int lng = nrzeroes>>4; int nrmarker; for (nrmarker=1; nrmarker <= lng; ++nrmarker) stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes); nrzeroes &= 15; } stbiw__jpg_calcBits(DU[i], bits); stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]); stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits); } if(end0pos != 63) { stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); } return DU[0]; } static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) { // Constants that don't pollute global namespace static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0}; static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d}; static const unsigned char std_ac_luminance_values[] = { 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08, 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28, 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59, 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6, 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2, 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa }; static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0}; static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77}; static const unsigned char std_ac_chrominance_values[] = { 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91, 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26, 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58, 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4, 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda, 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa }; // Huffman tables static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}}; static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}}; static const unsigned short YAC_HT[256][2] = { {10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0}, {2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} }; static const unsigned short UVAC_HT[256][2] = { {0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, {16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0}, {1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} }; static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22, 37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99}; static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99, 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99}; static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f, 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f }; int row, col, i, k, subsample; float fdtbl_Y[64], fdtbl_UV[64]; unsigned char YTable[64], UVTable[64]; if(!data || !width || !height || comp > 4 || comp < 1) { return 0; } quality = quality ? quality : 90; subsample = quality <= 90 ? 1 : 0; quality = quality < 1 ? 1 : quality > 100 ? 100 : quality; quality = quality < 50 ? 5000 / quality : 200 - quality * 2; for(i = 0; i < 64; ++i) { int uvti, yti = (YQT[i]*quality+50)/100; YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti); uvti = (UVQT[i]*quality+50)/100; UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti); } for(row = 0, k = 0; row < 8; ++row) { for(col = 0; col < 8; ++col, ++k) { fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); } } // Write Headers { static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 }; static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 }; const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width), 3,1,(unsigned char)(subsample?0x22:0x11),0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 }; s->func(s->context, (void*)head0, sizeof(head0)); s->func(s->context, (void*)YTable, sizeof(YTable)); stbiw__putc(s, 1); s->func(s->context, UVTable, sizeof(UVTable)); s->func(s->context, (void*)head1, sizeof(head1)); s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1); s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values)); stbiw__putc(s, 0x10); // HTYACinfo s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1); s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values)); stbiw__putc(s, 1); // HTUDCinfo s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1); s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values)); stbiw__putc(s, 0x11); // HTUACinfo s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1); s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values)); s->func(s->context, (void*)head2, sizeof(head2)); } // Encode 8x8 macroblocks { static const unsigned short fillBits[] = {0x7F, 7}; int DCY=0, DCU=0, DCV=0; int bitBuf=0, bitCnt=0; // comp == 2 is grey+alpha (alpha is ignored) int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0; const unsigned char *dataR = (const unsigned char *)data; const unsigned char *dataG = dataR + ofsG; const unsigned char *dataB = dataR + ofsB; int x, y, pos; if(subsample) { for(y = 0; y < height; y += 16) { for(x = 0; x < width; x += 16) { float Y[256], U[256], V[256]; for(row = y, pos = 0; row < y+16; ++row) { // row >= height => use last input row int clamped_row = (row < height) ? row : height - 1; int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp; for(col = x; col < x+16; ++col, ++pos) { // if col >= width => use pixel from last input column int p = base_p + ((col < width) ? col : (width-1))*comp; float r = dataR[p], g = dataG[p], b = dataB[p]; Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128; U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b; V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b; } } DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+0, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+8, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); // subsample U,V { float subU[64], subV[64]; int yy, xx; for(yy = 0, pos = 0; yy < 8; ++yy) { for(xx = 0; xx < 8; ++xx, ++pos) { int j = yy*32+xx*2; subU[pos] = (U[j+0] + U[j+1] + U[j+16] + U[j+17]) * 0.25f; subV[pos] = (V[j+0] + V[j+1] + V[j+16] + V[j+17]) * 0.25f; } } DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); } } } } else { for(y = 0; y < height; y += 8) { for(x = 0; x < width; x += 8) { float Y[64], U[64], V[64]; for(row = y, pos = 0; row < y+8; ++row) { // row >= height => use last input row int clamped_row = (row < height) ? row : height - 1; int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp; for(col = x; col < x+8; ++col, ++pos) { // if col >= width => use pixel from last input column int p = base_p + ((col < width) ? col : (width-1))*comp; float r = dataR[p], g = dataG[p], b = dataB[p]; Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128; U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b; V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b; } } DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y, DCY, YDC_HT, YAC_HT); DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); } } } // Do the bit alignment of the EOI marker stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits); } // EOI stbiw__putc(s, 0xFF); stbiw__putc(s, 0xD9); return 1; } STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality) { stbi__write_context s = { 0 }; stbi__start_write_callbacks(&s, func, context); return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality); } #ifndef STBI_WRITE_NO_STDIO STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality) { stbi__write_context s = { 0 }; if (stbi__start_write_file(&s,filename)) { int r = stbi_write_jpg_core(&s, x, y, comp, data, quality); stbi__end_write_file(&s); return r; } else return 0; } #endif #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history 1.16 (2021-07-11) make Deflate code emit uncompressed blocks when it would otherwise expand support writing BMPs with alpha channel 1.15 (2020-07-13) unknown 1.14 (2020-02-02) updated JPEG writer to downsample chroma channels 1.13 1.12 1.11 (2019-08-11) 1.10 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs 1.09 (2018-02-11) fix typo in zlib quality API, improve STB_I_W_STATIC in C++ 1.08 (2018-01-29) add stbi__flip_vertically_on_write, external zlib, zlib quality, choose PNG filter 1.07 (2017-07-24) doc fix 1.06 (2017-07-23) writing JPEG (using Jon Olick's code) 1.05 ??? 1.04 (2017-03-03) monochrome BMP expansion 1.03 ??? 1.02 (2016-04-02) avoid allocating large structures on the stack 1.01 (2016-01-16) STBIW_REALLOC_SIZED: support allocators with no realloc support avoid race-condition in crc initialization minor compile issues 1.00 (2015-09-14) installable file IO function 0.99 (2015-09-13) warning fixes; TGA rle support 0.98 (2015-04-08) added STBIW_MALLOC, STBIW_ASSERT etc 0.97 (2015-01-18) fixed HDR asserts, rewrote HDR rle logic 0.96 (2015-01-17) add HDR output fix monochrome BMP 0.95 (2014-08-17) add monochrome TGA output 0.94 (2014-05-31) rename private functions to avoid conflicts with stb_image.h 0.93 (2014-05-27) warning fixes 0.92 (2010-08-01) casts to unsigned char to fix warnings 0.91 (2010-07-17) first public release 0.90 first internal release */ /* ------------------------------------------------------------------------------ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ RenderKit-ospray-f2a61c2/apps/common/ospray_testing/000077500000000000000000000000001456566705700226545ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/common/ospray_testing/CMakeLists.txt000066400000000000000000000037011456566705700254150ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 include(GenerateExportHeader) add_library(ospray_testing SHARED ${OSPRAY_RESOURCE} ospray_testing.cpp builders/Builder.cpp builders/Boxes.cpp builders/ClippingGeometries.cpp builders/CornellBox.cpp builders/Curves.cpp builders/Empty.cpp builders/GravitySpheresVolume.cpp builders/Instancing.cpp builders/Interpolation.cpp builders/Noise.cpp builders/ParticleVolume.cpp builders/PerlinNoiseVolumes.cpp builders/Planes.cpp builders/RandomSpheres.cpp builders/Streamlines.cpp builders/SubdivisionCube.cpp builders/Transparency.cpp builders/UnstructuredVolumeGen.cpp builders/UnstructuredVolumeSimple.cpp builders/VdbVolume.cpp # regression test scenes builders/test_pt_alloy_roughness.cpp builders/test_pt_carpaint.cpp builders/test_pt_glass.cpp builders/test_pt_luminous.cpp builders/test_pt_material_tex.cpp builders/test_pt_metal_roughness.cpp builders/test_pt_metallic_flakes.cpp builders/test_pt_mix_tex.cpp builders/test_pt_obj.cpp builders/test_pt_plastic.cpp builders/test_pt_principled.cpp builders/test_pt_principled_tex.cpp builders/test_pt_thinglass.cpp builders/test_pt_velvet.cpp ) generate_export_header(ospray_testing) target_link_libraries(ospray_testing PUBLIC ospray_sdk PRIVATE raw_to_amr ) target_include_directories(ospray_testing PUBLIC $ $ $ ) ## Install library/headers ## ospray_install_library(ospray_testing apps) install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ospray COMPONENT devel FILES_MATCHING PATTERN *.h PATTERN *.inl ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ospray_testing_export.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ospray/ospray_testing COMPONENT devel ) RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/000077500000000000000000000000001456566705700244655ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/Boxes.cpp000066400000000000000000000046211456566705700262540ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "ospray_testing.h" #include "rkcommon/utility/multidim_index_sequence.h" using namespace rkcommon::math; namespace ospray { namespace testing { struct Boxes : public detail::Builder { Boxes(bool lights = false) : useLights(lights) {} ~Boxes() override = default; void commit() override; cpp::Group buildGroup() const override; cpp::World buildWorld() const override; private: vec3i dimensions{4}; bool useLights{false}; }; // Inlined definitions //////////////////////////////////////////////////// void Boxes::commit() { Builder::commit(); dimensions = getParam("dimensions", vec3i(4)); addPlane = false; } cpp::Group Boxes::buildGroup() const { cpp::Geometry boxGeometry("box"); index_sequence_3D numBoxes(dimensions); std::vector boxes; std::vector color; auto dim = reduce_max(dimensions); for (auto i : numBoxes) { auto i_f = static_cast(i); auto lower = i_f * 5.f; auto upper = lower + (0.75f * 5.f); boxes.emplace_back(lower, upper); auto box_color = (0.8f * i_f / dim) + 0.2f; color.emplace_back(box_color.x, box_color.y, box_color.z, 1.f); } boxGeometry.setParam("box", cpp::CopiedData(boxes)); boxGeometry.commit(); cpp::GeometricModel model(boxGeometry); model.setParam("color", cpp::CopiedData(color)); cpp::Material material("obj"); material.setParam("ks", vec3f(0.3f)); material.setParam("ns", 10.f); material.commit(); model.setParam("material", material); model.commit(); cpp::Group group; group.setParam("geometry", cpp::CopiedData(model)); group.commit(); return group; } cpp::World Boxes::buildWorld() const { auto world = Builder::buildWorld(); if (!useLights) return world; cpp::Light light("distant"); light.setParam("color", vec3f(0.78f, 0.551f, 0.483f)); light.setParam("intensity", 3.14f); light.setParam("direction", vec3f(-0.8f, -0.6f, 0.3f)); light.commit(); cpp::Light ambient("ambient"); ambient.setParam("intensity", 0.35f); ambient.setParam("visible", false); ambient.commit(); std::vector lights{light, ambient}; world.setParam("light", cpp::CopiedData(lights)); return world; } OSP_REGISTER_TESTING_BUILDER(Boxes, boxes); OSP_REGISTER_TESTING_BUILDER(Boxes(true), boxes_lit); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/Builder.cpp000066400000000000000000000146251456566705700265670ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" namespace ospray { namespace testing { namespace detail { std::unique_ptr Builder::factory; void Builder::commit() { rendererType = getParam("rendererType", "scivis"); tfColorMap = getParam("tf.colorMap", "jet"); tfOpacityMap = getParam("tf.opacityMap", "linear"); randomSeed = getParam("randomSeed", 0); } cpp::World Builder::buildWorld() const { return buildWorld({}); } cpp::World Builder::buildWorld( const std::vector &instances) const { cpp::World world; auto group = buildGroup(); cpp::Instance instance(group); instance.commit(); std::vector inst = instances; inst.push_back(instance); if (addPlane) inst.push_back(makeGroundPlane(group.getBounds())); world.setParam("instance", cpp::CopiedData(inst)); cpp::Light light("ambient"); light.setParam("visible", false); light.commit(); world.setParam("light", cpp::CopiedData(light)); return world; } cpp::TransferFunction Builder::makeTransferFunction( const range1f &valueRange) const { cpp::TransferFunction transferFunction("piecewiseLinear"); std::vector colors; std::vector opacities; if (tfColorMap == "jet") { colors.emplace_back(0, 0, 0.562493); colors.emplace_back(0, 0, 1); colors.emplace_back(0, 1, 1); colors.emplace_back(0.500008, 1, 0.500008); colors.emplace_back(1, 1, 0); colors.emplace_back(1, 0, 0); colors.emplace_back(0.500008, 0, 0); } else if (tfColorMap == "rgb") { colors.emplace_back(0, 0, 1); colors.emplace_back(0, 1, 0); colors.emplace_back(1, 0, 0); } else { colors.emplace_back(0.f, 0.f, 0.f); colors.emplace_back(1.f, 1.f, 1.f); } if (tfOpacityMap == "linear") { opacities.emplace_back(0.f); opacities.emplace_back(1.f); } else if (tfOpacityMap == "linearInv") { opacities.emplace_back(1.f); opacities.emplace_back(0.f); } else if (tfOpacityMap == "opaque") { opacities.emplace_back(1.f); } transferFunction.setParam("color", cpp::CopiedData(colors)); transferFunction.setParam("opacity", cpp::CopiedData(opacities)); transferFunction.setParam("value", valueRange); transferFunction.commit(); return transferFunction; } cpp::Instance Builder::makeGroundPlane(const box3f &bounds, const vec4f &planeColor, const vec4f &stripeColor) const { auto planeExtent = 0.8f * length(bounds.center() - bounds.lower); cpp::Geometry planeGeometry("mesh"); std::vector v_position; std::vector v_normal; std::vector v_color; std::vector indices; unsigned int startingIndex = 0; const vec3f up = vec3f{0.f, 1.f, 0.f}; v_position.emplace_back(-planeExtent, -1.f, -planeExtent); v_position.emplace_back(planeExtent, -1.f, -planeExtent); v_position.emplace_back(planeExtent, -1.f, planeExtent); v_position.emplace_back(-planeExtent, -1.f, planeExtent); v_normal.push_back(up); v_normal.push_back(up); v_normal.push_back(up); v_normal.push_back(up); v_color.push_back(planeColor); v_color.push_back(planeColor); v_color.push_back(planeColor); v_color.push_back(planeColor); indices.emplace_back( startingIndex, startingIndex + 1, startingIndex + 2, startingIndex + 3); // stripes on ground plane const float stripeWidth = 0.025f; const float paddedExtent = planeExtent + stripeWidth; const size_t numStripes = 10; for (size_t i = 0; i < numStripes; i++) { // the center coordinate of the stripe, either in the x or z // direction const float coord = -planeExtent + float(i) / float(numStripes - 1) * 2.f * planeExtent; // offset the stripes by an epsilon above the ground plane const float yLevel = -1.f + 1e-3f; // x-direction stripes startingIndex = v_position.size(); v_position.emplace_back(-paddedExtent, yLevel, coord - stripeWidth); v_position.emplace_back(paddedExtent, yLevel, coord - stripeWidth); v_position.emplace_back(paddedExtent, yLevel, coord + stripeWidth); v_position.emplace_back(-paddedExtent, yLevel, coord + stripeWidth); v_normal.push_back(up); v_normal.push_back(up); v_normal.push_back(up); v_normal.push_back(up); v_color.push_back(stripeColor); v_color.push_back(stripeColor); v_color.push_back(stripeColor); v_color.push_back(stripeColor); indices.emplace_back( startingIndex, startingIndex + 1, startingIndex + 2, startingIndex + 3); // z-direction stripes startingIndex = v_position.size(); // offset another epsilon to avoid z-figthing for primID AOV const float yLevel2 = yLevel + 1e-4f; v_position.emplace_back(coord - stripeWidth, yLevel2, -paddedExtent); v_position.emplace_back(coord + stripeWidth, yLevel2, -paddedExtent); v_position.emplace_back(coord + stripeWidth, yLevel2, paddedExtent); v_position.emplace_back(coord - stripeWidth, yLevel2, paddedExtent); v_normal.push_back(up); v_normal.push_back(up); v_normal.push_back(up); v_normal.push_back(up); v_color.push_back(stripeColor); v_color.push_back(stripeColor); v_color.push_back(stripeColor); v_color.push_back(stripeColor); indices.emplace_back( startingIndex, startingIndex + 1, startingIndex + 2, startingIndex + 3); } planeGeometry.setParam("vertex.position", cpp::CopiedData(v_position)); planeGeometry.setParam("vertex.normal", cpp::CopiedData(v_normal)); planeGeometry.setParam("vertex.color", cpp::CopiedData(v_color)); planeGeometry.setParam("index", cpp::CopiedData(indices)); planeGeometry.commit(); cpp::GeometricModel plane(planeGeometry); cpp::Material material("obj"); material.commit(); plane.setParam("material", material); plane.commit(); cpp::Group planeGroup; planeGroup.setParam("geometry", cpp::CopiedData(plane)); planeGroup.commit(); cpp::Instance planeInst(planeGroup); planeInst.commit(); return planeInst; } void Builder::registerBuilder(const std::string &name, BuilderFcn fcn) { if (factory.get() == nullptr) factory = make_unique(); (*factory)[name] = fcn; } Builder *Builder::createBuilder(const std::string &name) { if (factory.get() == nullptr) return nullptr; else { auto &fcn = (*factory)[name]; return fcn(); } } } // namespace detail } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/Builder.h000066400000000000000000000044761456566705700262370ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray #include "ospray/ospray_cpp.h" #include "ospray/ospray_cpp/ext/rkcommon.h" // rkcommon #include "rkcommon/memory/IntrusivePtr.h" #include "rkcommon/utility/ParameterizedObject.h" // std #include #include #include "ospray_testing_export.h" namespace ospray { namespace testing { namespace detail { using namespace rkcommon; using namespace rkcommon::math; struct Builder : public memory::RefCountedObject, public utility::ParameterizedObject { using BuilderFcn = std::function; ~Builder() override = default; virtual void commit(); virtual cpp::Group buildGroup() const = 0; virtual cpp::World buildWorld() const; virtual cpp::World buildWorld( const std::vector &instances) const; static void registerBuilder(const std::string &name, BuilderFcn fcn); static Builder *createBuilder(const std::string &name); protected: cpp::TransferFunction makeTransferFunction(const range1f &valueRange) const; cpp::Instance makeGroundPlane(const box3f &bounds, const vec4f &planeColor = vec4f{0.9f, 0.9f, 0.9f, 0.75f}, const vec4f &stripeColor = vec4f{1.0f, 0.1f, 0.1f, 1.f}) const; // Data // std::string rendererType{"scivis"}; std::string tfColorMap{"jet"}; std::string tfOpacityMap{"linear"}; bool addPlane{true}; unsigned int randomSeed{0}; private: using BuilderFactory = std::map; static std::unique_ptr factory; }; } // namespace detail } // namespace testing } // namespace ospray #define OSP_REGISTER_TESTING_BUILDER(InternalClassName, Name) \ static bool init_builder_##Name() \ { \ using Builder = ospray::testing::detail::Builder; \ Builder::registerBuilder( \ TOSTRING(Name), [] { return new InternalClassName; }); \ return true; \ } \ static bool val_##Name##_initialized = init_builder_##Name(); RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/ClippingGeometries.cpp000066400000000000000000000177331456566705700307750ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "ospray_testing.h" #include "rkcommon/utility/multidim_index_sequence.h" using namespace rkcommon::math; namespace ospray { namespace testing { struct ClippingGeometries : public detail::Builder { ClippingGeometries( const std::string &geometryType, const std::string &geometrySubType = ""); ~ClippingGeometries() override = default; void commit() override; cpp::Group buildGroup() const override; cpp::World buildWorld() const override; private: vec3i dimensions{19}; std::string geomType; std::string geomSubType; }; // Inlined definitions //////////////////////////////////////////////////// ClippingGeometries::ClippingGeometries( const std::string &geometryType, const std::string &geometrySubType) : geomType(geometryType), geomSubType(geometrySubType) {} void ClippingGeometries::commit() { Builder::commit(); dimensions = getParam("dimensions", dimensions); geomType = getParam("geometryType", geomType); geomSubType = getParam("geometrySubType", geomSubType); addPlane = false; } cpp::Group ClippingGeometries::buildGroup() const { cpp::Geometry spheresGeometry("sphere"); index_sequence_3D numSpheres(dimensions); std::vector positions; auto dim = reduce_max(dimensions) - 1; float size = 2.f; for (auto i : numSpheres) { vec3f i_f = static_cast(i); vec3f p = size * (i_f / dim - .5f); positions.emplace_back(p); } spheresGeometry.setParam("sphere.position", cpp::CopiedData(positions)); spheresGeometry.setParam("radius", size / dim / 2.f); spheresGeometry.commit(); cpp::GeometricModel model(spheresGeometry); cpp::Material material("obj"); material.setParam("kd", vec3f(.1f, .4f, .8f)); material.commit(); model.setParam("material", material); model.commit(); cpp::Group group; group.setParam("geometry", cpp::CopiedData(model)); group.commit(); return group; } cpp::World ClippingGeometries::buildWorld() const { // Create selected geometry vec3f cPos; cpp::Geometry geometry(geomType); if (geomType == "curve") { static std::vector vertices = {{-1.f, +0.f, -1.f, 0.2f}, {+0.f, -1.f, +0.f, 0.2f}, {+1.f, +0.f, +1.f, 0.2f}, {-1.f, +0.f, +1.f, 0.2f}, {+0.f, +1.f, +0.f, 0.3f}, {+1.f, +0.f, -1.f, 0.2f}, {-1.f, +0.f, -1.f, 0.2f}, {+0.f, -1.f, +0.f, 0.2f}, {+1.f, +0.f, +1.f, 0.2f}}; if (geomSubType == "bspline") { geometry.setParam("vertex.position_radius", cpp::CopiedData(vertices)); geometry.setParam("basis", OSP_BSPLINE); cPos = vec3f(-.1f, 0.f, -.1f); } else if (geomSubType == "linear") { geometry.setParam("vertex.position", cpp::CopiedData((vec3f *)vertices.data(), vertices.size(), sizeof(vec4f))); geometry.setParam("radius", 0.2f); geometry.setParam("basis", OSP_LINEAR); cPos = vec3f(-.2f, 0.f, -.2f); } std::vector indices = {0, 1, 2, 3, 4, 5}; geometry.setParam("index", cpp::CopiedData(indices)); geometry.setParam("type", OSP_ROUND); geometry.commit(); } else if (geomType == "subdivision") { const float size = .9f; std::vector vertices = {{-size, -size, -size}, {+size, -size, -size}, {+size, -size, +size}, {-size, -size, +size}, {-size, +size, -size}, {+size, +size, -size}, {+size, +size, +size}, {-size, +size, +size}}; geometry.setParam("vertex.position", cpp::CopiedData(vertices)); std::vector faces = {4, 4, 4, 4, 4, 4}; geometry.setParam("face", cpp::CopiedData(faces)); std::vector indices = { 0, 4, 5, 1, 1, 5, 6, 2, 2, 6, 7, 3, 0, 3, 7, 4, 4, 7, 6, 5, 0, 1, 2, 3, }; geometry.setParam("index", cpp::CopiedData(indices)); std::vector vertexCreaseIndices = {0, 1, 2, 3, 4, 5, 6, 7}; geometry.setParam("vertexCrease.index", cpp::CopiedData(vertexCreaseIndices)); std::vector vertexCreaseWeights = { 2.f, 2.f, 2.f, 2.f, 2.f, 2.f, 2.f, 2.f}; geometry.setParam("vertexCrease.weight", cpp::CopiedData(vertexCreaseWeights)); std::vector edgeCreaseIndices = {{0, 1}, {1, 2}, {2, 3}, {3, 0}, {4, 5}, {5, 6}, {6, 7}, {7, 4}, {0, 4}, {1, 5}, {2, 6}, {3, 7}}; geometry.setParam("edgeCrease.index", cpp::CopiedData(edgeCreaseIndices)); std::vector edgeCreaseWeights = { 2.f, 2.f, 2.f, 2.f, 2.f, 2.f, 2.f, 2.f, 2.f, 2.f, 2.f, 2.f}; geometry.setParam("edgeCrease.weight", cpp::CopiedData(edgeCreaseWeights)); geometry.setParam("level", 10.f); geometry.commit(); cPos = vec3f(-.3f, .3f, -.3f); } else if (geomType == "mesh") { const vec3f pos = vec3f(0.f); const vec3f size = vec3f(1.1f); std::vector vertices = {{pos.x, pos.y - size.y, pos.z}, {pos.x - size.x, pos.y, pos.z - size.z}, {pos.x + size.x, pos.y, pos.z - size.z}, {pos.x + size.x, pos.y, pos.z + size.z}, {pos.x - size.x, pos.y, pos.z + size.z}, {pos.x, pos.y + size.y, pos.z}}; geometry.setParam("vertex.position", cpp::CopiedData(vertices)); std::vector indices = {{0, 1, 2}, {0, 2, 3}, {0, 3, 4}, {0, 4, 1}, {5, 2, 1}, {5, 3, 2}, {5, 4, 3}, {5, 1, 4}}; geometry.setParam("index", cpp::CopiedData(indices)); geometry.commit(); cPos = vec3f(-.3f, 0.f, -.3f); } else if (geomType == "plane") { std::vector coefficients = {vec4f(1.0f, 1.0f, 1.0f, 0.0f)}; geometry.setParam("plane.coefficients", cpp::CopiedData(coefficients)); geometry.commit(); cPos = vec3f(-.3f, .2f, -.3f); } else if (geomType == "box") { std::vector boxes = { box3f(vec3f(-.9f, -.9f, -.9f), vec3f(.9f, .9f, .9f))}; geometry.setParam("box", cpp::CopiedData(boxes)); geometry.commit(); cPos = vec3f(-.3f, .3f, -.3f); } else if (geomType == "sphere") { std::vector position = {vec3f(0.f, 0.f, 0.f)}; geometry.setParam("sphere.position", cpp::CopiedData(position)); geometry.setParam("radius", 1.f); geometry.commit(); cPos = vec3f(-.3f, .2f, -.3f); } else return Builder::buildWorld(); std::vector inst; // Create clipping instance with model that has inverted normals { cpp::GeometricModel model(geometry); model.setParam("invertNormals", true); model.commit(); cpp::Group group; group.setParam("clippingGeometry", cpp::CopiedData(model)); group.commit(); cpp::Instance instance(group); instance.commit(); inst.push_back(instance); } // Create second clipping instance but keep original normals { cpp::GeometricModel model(geometry); model.setParam("invertNormals", false); model.commit(); cpp::Group group; group.setParam("clippingGeometry", cpp::CopiedData(model)); group.commit(); cpp::Instance instance(group); instance.setParam("transform", affine3f::translate(cPos)); instance.commit(); inst.push_back(instance); } return Builder::buildWorld(inst); } OSP_REGISTER_TESTING_BUILDER(ClippingGeometries("sphere"), clip_with_spheres); OSP_REGISTER_TESTING_BUILDER(ClippingGeometries("box"), clip_with_boxes); OSP_REGISTER_TESTING_BUILDER(ClippingGeometries("plane"), clip_with_planes); OSP_REGISTER_TESTING_BUILDER(ClippingGeometries("mesh"), clip_with_meshes); OSP_REGISTER_TESTING_BUILDER( ClippingGeometries("subdivision"), clip_with_subdivisions); OSP_REGISTER_TESTING_BUILDER( ClippingGeometries("curve", "linear"), clip_with_linear_curves); OSP_REGISTER_TESTING_BUILDER( ClippingGeometries("curve", "bspline"), clip_with_bspline_curves); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/CornellBox.cpp000066400000000000000000000155021456566705700272430ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "ospray_testing.h" // stl #include using namespace rkcommon::math; namespace ospray { namespace testing { struct CornellBox : public detail::Builder { CornellBox() = default; ~CornellBox() override = default; void commit() override; cpp::Group buildGroup() const override; cpp::World buildWorld() const override; }; // quad mesh data static std::vector vertices = { // Floor {1.00f, -1.00f, -1.00f}, {-1.00f, -1.00f, -1.00f}, {-1.00f, -1.00f, 1.00f}, {1.00f, -1.00f, 1.00f}, // Ceiling {1.00f, 1.00f, -1.00f}, {1.00f, 1.00f, 1.00f}, {-1.00f, 1.00f, 1.00f}, {-1.00f, 1.00f, -1.00f}, // Backwall {1.00f, -1.00f, 1.00f}, {-1.00f, -1.00f, 1.00f}, {-1.00f, 1.00f, 1.00f}, {1.00f, 1.00f, 1.00f}, // RightWall {-1.00f, -1.00f, 1.00f}, {-1.00f, -1.00f, -1.00f}, {-1.00f, 1.00f, -1.00f}, {-1.00f, 1.00f, 1.00f}, // LeftWall {1.00f, -1.00f, -1.00f}, {1.00f, -1.00f, 1.00f}, {1.00f, 1.00f, 1.00f}, {1.00f, 1.00f, -1.00f}, // ShortBox Top Face {-0.53f, -0.40f, -0.75f}, {-0.70f, -0.40f, -0.17f}, {-0.13f, -0.40f, -0.00f}, {0.05f, -0.40f, -0.57f}, // ShortBox Left Face {0.05f, -1.00f, -0.57f}, {0.05f, -0.40f, -0.57f}, {-0.13f, -0.40f, -0.00f}, {-0.13f, -1.00f, -0.00f}, // ShortBox Front Face {-0.53f, -1.00f, -0.75f}, {-0.53f, -0.40f, -0.75f}, {0.05f, -0.40f, -0.57f}, {0.05f, -1.00f, -0.57f}, // ShortBox Right Face {-0.70f, -1.00f, -0.17f}, {-0.70f, -0.40f, -0.17f}, {-0.53f, -0.40f, -0.75f}, {-0.53f, -1.00f, -0.75f}, // ShortBox Back Face {-0.13f, -1.00f, -0.00f}, {-0.13f, -0.40f, -0.00f}, {-0.70f, -0.40f, -0.17f}, {-0.70f, -1.00f, -0.17f}, // ShortBox Bottom Face {-0.53f, -1.00f, -0.75f}, {-0.70f, -1.00f, -0.17f}, {-0.13f, -1.00f, -0.00f}, {0.05f, -1.00f, -0.57f}, // TallBox Top Face {0.53f, 0.20f, -0.09f}, {-0.04f, 0.20f, 0.09f}, {0.14f, 0.20f, 0.67f}, {0.71f, 0.20f, 0.49f}, // TallBox Left Face {0.53f, -1.00f, -0.09f}, {0.53f, 0.20f, -0.09f}, {0.71f, 0.20f, 0.49f}, {0.71f, -1.00f, 0.49f}, // TallBox Front Face {0.71f, -1.00f, 0.49f}, {0.71f, 0.20f, 0.49f}, {0.14f, 0.20f, 0.67f}, {0.14f, -1.00f, 0.67f}, // TallBox Right Face {0.14f, -1.00f, 0.67f}, {0.14f, 0.20f, 0.67f}, {-0.04f, 0.20f, 0.09f}, {-0.04f, -1.00f, 0.09f}, // TallBox Back Face {-0.04f, -1.00f, 0.09f}, {-0.04f, 0.20f, 0.09f}, {0.53f, 0.20f, -0.09f}, {0.53f, -1.00f, -0.09f}, // TallBox Bottom Face {0.53f, -1.00f, -0.09f}, {-0.04f, -1.00f, 0.09f}, {0.14f, -1.00f, 0.67f}, {0.71f, -1.00f, 0.49f}}; static std::vector colors = { // Floor {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, // Ceiling {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, // Backwall {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, // RightWall {0.140f, 0.450f, 0.091f, 1.0f}, {0.140f, 0.450f, 0.091f, 1.0f}, {0.140f, 0.450f, 0.091f, 1.0f}, {0.140f, 0.450f, 0.091f, 1.0f}, // LeftWall {0.630f, 0.065f, 0.05f, 1.0f}, {0.630f, 0.065f, 0.05f, 1.0f}, {0.630f, 0.065f, 0.05f, 1.0f}, {0.630f, 0.065f, 0.05f, 1.0f}, // ShortBox Top Face {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, // ShortBox Left Face {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, // ShortBox Front Face {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, // ShortBox Right Face {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, // ShortBox Back Face {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, // ShortBox Bottom Face {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, // TallBox Top Face {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, // TallBox Left Face {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, // TallBox Front Face {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, // TallBox Right Face {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, // TallBox Back Face {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, // TallBox Bottom Face {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}, {0.725f, 0.710f, 0.68f, 1.0f}}; // Inlined definitions //////////////////////////////////////////////////// void CornellBox::commit() { Builder::commit(); addPlane = false; } cpp::Group CornellBox::buildGroup() const { cpp::Geometry quadMesh("mesh"); quadMesh.setParam("vertex.position", cpp::CopiedData(vertices)); quadMesh.setParam("vertex.color", cpp::CopiedData(colors)); quadMesh.setParam("quadSoup", true); quadMesh.commit(); cpp::GeometricModel model(quadMesh); cpp::Material quadMeshMaterial("obj"); quadMeshMaterial.commit(); model.setParam("material", quadMeshMaterial); // Put the mesh and material into a model model.commit(); cpp::Group group; group.setParam("geometry", cpp::CopiedData(model)); group.commit(); return group; } cpp::World CornellBox::buildWorld() const { auto world = Builder::buildWorld(); cpp::Light light("quad"); light.setParam("color", vec3f(0.78f, 0.551f, 0.183f)); light.setParam("intensity", 47.f); light.setParam("position", vec3f(-0.23f, 0.98f, -0.16f)); light.setParam("edge1", vec3f(0.47f, 0.0f, 0.0f)); light.setParam("edge2", vec3f(0.0f, 0.0f, 0.38f)); light.commit(); world.setParam("light", cpp::CopiedData(light)); return world; } OSP_REGISTER_TESTING_BUILDER(CornellBox, cornell_box); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/Curves.cpp000066400000000000000000000062311456566705700264420ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include #include "Builder.h" #include "ospray_testing.h" #include "rkcommon/utility/random.h" // stl #include using namespace rkcommon::math; namespace ospray { namespace testing { struct Curves : public detail::Builder { Curves() = default; ~Curves() override = default; void commit() override; cpp::Group buildGroup() const override; std::string curveVariant; }; static std::vector points = {{-1.0f, 0.0f, -2.f, 0.2f}, {0.0f, -1.0f, 0.0f, 0.2f}, {1.0f, 0.0f, 2.f, 0.2f}, {-1.0f, 0.0f, 2.f, 0.2f}, {0.0f, 1.0f, 0.0f, 0.6f}, {1.0f, 0.0f, -2.f, 0.2f}, {-1.0f, 0.0f, -2.f, 0.2f}, {0.0f, -1.0f, 0.0f, 0.2f}, {1.0f, 0.0f, 2.f, 0.2f}}; static std::vector indices = {0, 1, 2, 3, 4, 5}; void Curves::commit() { Builder::commit(); curveVariant = getParam("curveVariant", "bspline"); } cpp::Group Curves::buildGroup() const { std::vector geometricModels; std::mt19937 gen(randomSeed); utility::uniform_real_distribution colorDistribution(0.1f, 1.0f); std::vector s_colors(points.size()); cpp::Geometry geom("curve"); // defaults, "linear" geom.setParam("type", OSP_ROUND); geom.setParam("basis", OSP_LINEAR); geom.setParam("vertex.position_radius", cpp::CopiedData(points)); if (curveVariant == "hermite") { geom.setParam("basis", OSP_HERMITE); std::vector tangents; for (auto iter = points.begin(); iter != points.end() - 1; ++iter) { const vec4f pointTangent = *(iter + 1) - *iter; tangents.push_back(pointTangent); } geom.setParam("vertex.tangent", cpp::CopiedData(tangents)); } else if (curveVariant == "catmull-rom") { geom.setParam("basis", OSP_CATMULL_ROM); } else if (curveVariant == "cones") { geom.setParam("type", OSP_DISJOINT); } else if (curveVariant == "linear_deprecated") { geom.removeParam("vertex.position_radius"); geom.setParam("radius", 0.1f); geom.setParam("vertex.position", cpp::CopiedData((vec3f *)points.data(), points.size(), sizeof(vec4f))); } else if (curveVariant == "bspline") { geom.setParam("basis", OSP_BSPLINE); } for (auto &c : s_colors) { c.x = colorDistribution(gen); c.y = colorDistribution(gen); c.z = colorDistribution(gen); c.w = colorDistribution(gen); } geom.setParam("vertex.color", cpp::CopiedData(s_colors)); geom.setParam("index", cpp::CopiedData(indices)); geom.commit(); cpp::GeometricModel model(geom); if (rendererType == "pathtracer") { // create glass material and assign to geometry cpp::Material glassMaterial("thinGlass"); glassMaterial.setParam("attenuationDistance", 1.f); glassMaterial.commit(); model.setParam("material", glassMaterial); } else { cpp::Material glassMaterial("obj"); glassMaterial.commit(); model.setParam("material", glassMaterial); } model.commit(); cpp::Group group; group.setParam("geometry", cpp::CopiedData(model)); group.commit(); return group; } OSP_REGISTER_TESTING_BUILDER(Curves, curves); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/Empty.cpp000066400000000000000000000020401456566705700262630ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "ospray_testing.h" using namespace rkcommon::math; namespace ospray { namespace testing { struct Empty : public detail::Builder { Empty(bool plane = false) { addPlane = plane; } ~Empty() override = default; void commit() override; cpp::Group buildGroup() const override; cpp::World buildWorld() const override; }; // Inlined definitions //////////////////////////////////////////////////// void Empty::commit() { Builder::commit(); } cpp::Group Empty::buildGroup() const { cpp::Group group; group.commit(); return group; } cpp::World Empty::buildWorld() const { cpp::World world; if (addPlane) { std::vector inst; inst.push_back(makeGroundPlane(box3f(zero, one))); world.setParam("instance", cpp::CopiedData(inst)); } return world; } OSP_REGISTER_TESTING_BUILDER(Empty, empty); OSP_REGISTER_TESTING_BUILDER(Empty(true), nolight); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/GravitySpheresVolume.cpp000066400000000000000000000207761456566705700313540ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "ospray_testing.h" #include "rkcommon/tasking/parallel_for.h" #include "rkcommon/utility/random.h" // stl #include #include // raw_to_amr #include "rawToAMR.h" using namespace rkcommon; using namespace rkcommon::math; namespace ospray { namespace testing { using VoxelArray = std::vector; struct GravitySpheres : public detail::Builder { GravitySpheres(bool addVolume = true, bool asAMR = false, bool addIsosurface = false, bool clip = false, bool multipleIsosurfaces = false); ~GravitySpheres() override = default; void commit() override; cpp::Group buildGroup() const override; cpp::World buildWorld() const override; private: VoxelArray generateVoxels() const; cpp::Volume createStructuredVolume(const VoxelArray &voxels) const; cpp::Volume createAMRVolume(const VoxelArray &voxels) const; // Data // vec3i volumeDimensions{128}; int numPoints{10}; bool withVolume{true}; bool createAsAMR{false}; bool withIsosurface{false}; float isovalue{2.5f}; bool withClipping{false}; bool multipleIsosurfaces{false}; }; // Inlined definitions //////////////////////////////////////////////////// GravitySpheres::GravitySpheres(bool addVolume, bool asAMR, bool addIsosurface, bool clip, bool multipleIsosurfaces) : withVolume(addVolume), createAsAMR(asAMR), withIsosurface(addIsosurface), withClipping(clip), multipleIsosurfaces(multipleIsosurfaces) {} void GravitySpheres::commit() { Builder::commit(); volumeDimensions = getParam("volumeDimensions", vec3i(128)); numPoints = getParam("numPoints", 10); withVolume = getParam("withVolume", withVolume); createAsAMR = getParam("asAMR", createAsAMR); withIsosurface = getParam("withIsosurface", withIsosurface); isovalue = getParam("isovalue", 2.5f); withClipping = getParam("withClipping", withClipping); addPlane = false; } cpp::Group GravitySpheres::buildGroup() const { auto voxels = generateVoxels(); auto voxelRange = range1f(0.f, 10.f); cpp::Volume volume = createAsAMR ? createAMRVolume(voxels) : createStructuredVolume(voxels); cpp::VolumetricModel model(volume); model.setParam("transferFunction", makeTransferFunction(voxelRange)); model.commit(); cpp::Group group; if (withVolume) group.setParam("volume", cpp::CopiedData(model)); if (withIsosurface) { cpp::Geometry isoGeom("isosurface"); std::vector isovalues = {isovalue}; if (multipleIsosurfaces) { isovalues.push_back(isovalue + 1.f); } isoGeom.setParam("isovalue", cpp::CopiedData(isovalues)); isoGeom.setParam("volume", volume); isoGeom.commit(); cpp::GeometricModel isoModel(isoGeom); cpp::Material mat("obj"); mat.setParam("kd", vec3f(1.f)); mat.setParam("d", 0.5f); mat.setParam("ks", vec3f(0.2f)); mat.commit(); if (multipleIsosurfaces) { std::vector colors = { vec4f(0.2f, 0.2f, 0.8f, 1.f), vec4f(0.8f, 0.2f, 0.2f, 1.f)}; isoModel.setParam("color", cpp::CopiedData(colors)); } isoModel.setParam("material", mat); isoModel.commit(); group.setParam("geometry", cpp::CopiedData(isoModel)); } group.commit(); return group; } cpp::World GravitySpheres::buildWorld() const { // Skip clipping if not enabled std::vector instances; if (withClipping) { // Create clipping plane std::vector geometricModels; { cpp::Geometry planeGeometry("plane"); std::vector coefficients = {vec4f(1.f, -1.f, 1.f, 0.f)}; planeGeometry.setParam( "plane.coefficients", cpp::CopiedData(coefficients)); planeGeometry.commit(); cpp::GeometricModel model(planeGeometry); model.commit(); geometricModels.emplace_back(model); } // Create clipping sphere { cpp::Geometry sphereGeometry("sphere"); std::vector position = {vec3f(.2f, -.2f, .2f)}; sphereGeometry.setParam("sphere.position", cpp::CopiedData(position)); sphereGeometry.setParam("radius", .5f); sphereGeometry.commit(); cpp::GeometricModel model(sphereGeometry); model.commit(); geometricModels.emplace_back(model); } cpp::Group group; group.setParam("clippingGeometry", cpp::CopiedData(geometricModels)); group.commit(); cpp::Instance inst(group); inst.commit(); instances.push_back(inst); } return Builder::buildWorld(instances); } std::vector GravitySpheres::generateVoxels() const { struct Point { vec3f center; float weight; }; // create random number distributions for point center and weight std::mt19937 gen(randomSeed); utility::uniform_real_distribution centerDistribution(-1.f, 1.f); utility::uniform_real_distribution weightDistribution(0.1f, 0.3f); // populate the points std::vector points(numPoints); for (auto &p : points) { p.center.x = centerDistribution(gen); p.center.y = centerDistribution(gen); p.center.z = centerDistribution(gen); p.weight = weightDistribution(gen); } // get world coordinate in [-1.f, 1.f] from logical coordinates in [0, // volumeDimension) auto logicalToWorldCoordinates = [&](int i, int j, int k) { return vec3f(-1.f + float(i) / float(volumeDimensions.x - 1) * 2.f, -1.f + float(j) / float(volumeDimensions.y - 1) * 2.f, -1.f + float(k) / float(volumeDimensions.z - 1) * 2.f); }; // generate voxels std::vector voxels(volumeDimensions.long_product()); tasking::parallel_for(volumeDimensions.z, [&](int k) { for (int j = 0; j < volumeDimensions.y; j++) { for (int i = 0; i < volumeDimensions.x; i++) { // index in array size_t index = size_t(k) * volumeDimensions.z * volumeDimensions.y + size_t(j) * volumeDimensions.x + size_t(i); // compute volume value float value = 0.f; for (auto &p : points) { vec3f pointCoordinate = logicalToWorldCoordinates(i, j, k); const float distance = length(pointCoordinate - p.center); // contribution proportional to weighted inverse-square distance // (i.e. gravity) value += p.weight / (distance * distance); } voxels[index] = value; } } }); return voxels; } cpp::Volume GravitySpheres::createStructuredVolume( const VoxelArray &voxels) const { cpp::Volume volume("structuredRegular"); volume.setParam("gridOrigin", vec3f(-1.f)); volume.setParam("gridSpacing", vec3f(2.f / reduce_max(volumeDimensions))); volume.setParam("data", cpp::CopiedData(voxels.data(), volumeDimensions)); volume.commit(); return volume; } cpp::Volume GravitySpheres::createAMRVolume(const VoxelArray &voxels) const { const int numLevels = 2; const int blockSize = 16; const int refinementLevel = 4; const float threshold = 1.0; std::vector blockBounds; std::vector refinementLevels; std::vector cellWidths; std::vector> blockDataVectors; std::vector blockData; // convert the structured volume to AMR ospray::amr::makeAMR(voxels, volumeDimensions, numLevels, blockSize, refinementLevel, threshold, blockBounds, refinementLevels, cellWidths, blockDataVectors); for (const std::vector &bd : blockDataVectors) blockData.emplace_back(bd.data(), OSP_FLOAT, bd.size()); // create an AMR volume and assign attributes cpp::Volume volume("amr"); int toplevelVolDim = reduce_max(volumeDimensions) / std::pow(refinementLevel, numLevels - 1); volume.setParam("gridOrigin", vec3f(-1.f)); volume.setParam("gridSpacing", vec3f(2.f / toplevelVolDim)); volume.setParam("block.data", cpp::CopiedData(blockData)); volume.setParam("block.bounds", cpp::CopiedData(blockBounds)); volume.setParam("block.level", cpp::CopiedData(refinementLevels)); volume.setParam("cellWidth", cpp::CopiedData(cellWidths)); volume.commit(); return volume; } OSP_REGISTER_TESTING_BUILDER(GravitySpheres, gravity_spheres_volume); OSP_REGISTER_TESTING_BUILDER( GravitySpheres(true, true, false), gravity_spheres_amr); OSP_REGISTER_TESTING_BUILDER(GravitySpheres(false, false, true, false, true), gravity_spheres_isosurface); OSP_REGISTER_TESTING_BUILDER( GravitySpheres(true, false, false, true), clip_gravity_spheres_volume); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/Instancing.cpp000066400000000000000000000150571456566705700272760ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "ospray_testing.h" #include "rkcommon/utility/multidim_index_sequence.h" #include "rkcommon/utility/random.h" // stl #include using namespace rkcommon::math; namespace ospray { namespace testing { struct Instancing : public detail::Builder { Instancing() = default; ~Instancing() override = default; void commit() override; cpp::Group buildGroup() const override { return cpp::Group(); } cpp::Group buildGroupA() const; cpp::Group buildGroupB() const; cpp::Group buildGroupC() const; cpp::World buildWorld() const override; private: vec2ui numInstances{10, 10}; bool useIDs{false}; }; // Inlined definitions //////////////////////////////////////////////////// // Helper functions // namespace { cpp::Geometry makeBoxGeometry(const box3f &box) { cpp::Geometry ospGeometry("box"); ospGeometry.setParam("box", cpp::CopiedData(box)); ospGeometry.commit(); return ospGeometry; } cpp::GeometricModel makeGeometricModel( cpp::Geometry geo, const vec3f &kd, bool useIDs) { cpp::GeometricModel geometricModel(geo); cpp::Material objMaterial("obj"); objMaterial.setParam("kd", kd); objMaterial.commit(); geometricModel.setParam("material", objMaterial); if (useIDs) geometricModel.setParam("id", 44u); geometricModel.commit(); return geometricModel; } cpp::Volume makeVolume(const vec3f ¢er) { cpp::Volume volume("structuredRegular"); { const vec3i volumeCells{10, 10, 10}; const vec3f spacing{.25f}; volume.setParam("gridOrigin", center - volumeCells * spacing / 2.f); volume.setParam("gridSpacing", spacing); std::vector voxels(volumeCells.long_product()); index_sequence_3D numCell(volumeCells); for (const vec3i i : numCell) voxels[numCell.flatten(i)] = length(volumeCells - i / 2.f); volume.setParam("data", cpp::CopiedData(voxels.data(), volumeCells)); volume.commit(); } return volume; } cpp::VolumetricModel makeVolumetricModel(cpp::Volume volume, bool useIDs) { cpp::VolumetricModel vModel(volume); { // Create transfer function cpp::TransferFunction transferFunction("piecewiseLinear"); { std::vector colors = {{.1f, .4f, .8f}}; std::vector opacities = {1.f}; transferFunction.setParam("color", cpp::CopiedData(colors)); transferFunction.setParam("opacity", cpp::CopiedData(opacities)); transferFunction.setParam("value", range1f(0.f, 10.f)); transferFunction.commit(); } vModel.setParam("transferFunction", transferFunction); vModel.setParam("densityScale", .5f); vModel.setParam("gradientShadingScale", 1.f); if (useIDs) vModel.setParam("id", 3u); vModel.commit(); } return vModel; } } // namespace // Instancing definitions // void Instancing::commit() { Builder::commit(); numInstances = getParam("numInstances", numInstances); useIDs = getParam("useIDs", useIDs); } cpp::Group Instancing::buildGroupA() const { cpp::Group group; cpp::Geometry box = makeBoxGeometry(box3f(vec3f(-1.f), vec3f(1.f))); cpp::GeometricModel geometricModel = makeGeometricModel(box, vec3f(.1f, .4f, .8f), useIDs); group.setParam("geometry", cpp::CopiedData(geometricModel)); cpp::Light light("quad"); light.setParam("position", vec3f(0.f, 6.f, 0.f)); light.setParam("edge1", vec3f(0.f, 0.f, -1.f)); light.setParam("edge2", vec3f(1.f, 0.f, 0.f)); light.setParam("intensity", 2.0f); light.setParam("color", vec3f(2.6f, 2.5f, 2.3f)); light.commit(); group.setParam("light", cpp::CopiedData(light)); group.commit(); return group; } cpp::Group Instancing::buildGroupB() const { cpp::Group group; std::vector models; cpp::Geometry box = makeBoxGeometry(box3f(vec3f(-1.f), vec3f(0.f, 1.f, 1.f))); models.emplace_back(makeGeometricModel(box, vec3f(.1f, .4f, .8f), useIDs)); box = makeBoxGeometry(box3f(vec3f(0.f, -1.f, -1.f), vec3f(1.f))); models.emplace_back(makeGeometricModel(box, vec3f(.1f, .4f, .8f), useIDs)); group.setParam("geometry", cpp::CopiedData(models)); cpp::Light light("spot"); light.setParam("position", vec3f(0.f, 6.f, 0.f)); light.setParam("direction", vec3f(0.f, -1.f, 0.f)); light.setParam("openingAngle", 180.f); light.setParam("penumbraAngle", 0.f); light.setParam("radius", 0.3f); light.setParam("intensity", 2.0f); float lid1d[] = {0.f, 2.4f, 0.2f, 0.1f, 0.03f, 0.01f, 0.01f}; light.setParam("intensityDistribution", cpp::CopiedData(lid1d, 7)); light.setParam("color", vec3f(2.6f, 2.5f, 2.3f)); light.commit(); group.setParam("light", cpp::CopiedData(light)); group.commit(); return group; } cpp::Group Instancing::buildGroupC() const { cpp::Group group; // Create volumetric model group.setParam("volume", cpp::CopiedData(makeVolumetricModel(makeVolume(vec3f(0.f)), useIDs))); cpp::Light light("sphere"); light.setParam("position", vec3f(0.f, 2.f, 0.f)); light.setParam("radius", .25f); light.setParam("intensity", 2.0f); light.setParam("color", vec3f(2.6f, 2.5f, 2.3f)); light.commit(); group.setParam("light", cpp::CopiedData(light)); group.commit(); return group; } cpp::World Instancing::buildWorld() const { // Create all groups std::vector groups; groups.push_back(buildGroupA()); groups.push_back(buildGroupB()); groups.push_back(buildGroupC()); // Create instances std::vector instances; { const float spacing = 2.5f; const vec2f totalSize = spacing * (numInstances - 1); box3f sceneBounds; index_sequence_2D indexInstances(numInstances); for (const vec2ui i : indexInstances) { const float h = .3f * (sin(.7f * i.x) + sin(.7f * i.y)); const vec3f position = spacing * vec3f(i.x, h, i.y) - 0.5f * vec3f(totalSize.x, 0.0f, totalSize.y); const float d = length(vec2f(position.x, position.z)); const int gId = int(.18f * d) % groups.size(); cpp::Instance instance(groups[gId]); if (useIDs) instance.setParam("id", i.y + 1); const affine3f xfm = affine3f::translate(position) * affine3f::rotate(vec3f(0.f, 1.f, 0.f), .03f * (15.f - d)); instance.setParam("transform", affine3f::rotate(vec3f(-1.f, 0.f, 0.f), .3f * float(pi)) * xfm); instance.commit(); instances.push_back(instance); } } // Create world cpp::World world; world.setParam("instance", cpp::CopiedData(instances)); // Done return world; } OSP_REGISTER_TESTING_BUILDER(Instancing, instancing); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/Interpolation.cpp000066400000000000000000000120351456566705700300210ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "ospray_testing.h" // stl #include using namespace rkcommon::math; namespace ospray { namespace testing { struct Interpolation : public detail::Builder { Interpolation( bool subd = false, unsigned int attrib = 0, unsigned int interp = 0) : useSubd(subd), attribute(attrib), interpolation(interp) {} ~Interpolation() override = default; void commit() override; cpp::Group buildGroup() const override; cpp::World buildWorld() const override; // TODO: support triangles bool useSubd{false}; // otherwise Mesh unsigned int attribute; // color, texcoord, normal unsigned int interpolation; // face varying, vertex varying, uniform, constant }; // quad mesh data static std::vector vertices = { // Left {0.f, 0.f, 0.f}, {1.f, 0.f, 0.f}, {1.f, 1.f, 0.f}, {0.f, 1.f, 0.f}, // Right {2.f, 0.f, 0.f}, {2.f, 1.f, 0.f}}; static std::vector quad_indices = { {0, 1, 2, 3}, // Left {1, 4, 5, 2} // Right }; static std::vector subd_indices = {0, 1, 2, 3, 1, 4, 5, 2}; static std::vector texcoords = {{0.0f, 0.0f}, {0.1f, 0.0f}, {0.2f, 0.0f}, {0.3f, 0.0f}, {0.4f, 0.0f}, {0.5f, 0.0f}, {0.6f, 0.0f}, {0.7f, 0.0f}}; static std::vector colors = {{1.f, 0.f, 0.f, 1.f}, {0.f, 1.f, 0.f, 1.f}, {0.f, 0.f, 1.f, 1.f}, {1.f, 1.f, 0.f, 1.f}, {1.f, 0.f, 1.f, 1.f}, {1.f, 0.f, 1.f, 1.f}}; static std::vector colors_fv = {{1.f, 0.f, 0.f, 1.f}, {0.f, 1.f, 0.f, 1.f}, {0.f, 0.f, 1.f, 1.f}, {1.f, 1.f, 0.f, 1.f}, {1.f, 0.f, 1.f, 1.f}, {1.f, 0.f, 1.f, 1.f}, {1.f, 0.f, 1.f, 1.f}, {1.f, 0.f, 1.f, 1.f}}; static std::vector normals = {{1.f, 0.f, 0.f}, {0.f, 1.f, 0.f}, {0.f, 0.f, 1.f}, {1.f, 1.f, 0.f}, {1.f, 0.f, 1.f}, {1.f, 0.f, 1.f}, {1.f, 0.f, 1.f}, {1.f, 0.f, 1.f}}; // number of vertex indices per face static std::vector faces = {4, 4}; // Inlined definitions //////////////////////////////////////////////////// void Interpolation::commit() { Builder::commit(); useSubd = getParam("useSubd", useSubd); attribute = getParam("attribute", attribute); interpolation = getParam("interpolation", interpolation); addPlane = false; } cpp::Group Interpolation::buildGroup() const { cpp::Geometry mesh; std::vector colors_mod = colors; if (interpolation == 0) colors_mod = colors_fv; else if (interpolation == 2) colors_mod.resize(2); else if (interpolation == 3) colors_mod.resize(1); cpp::Texture tex("texture2d"); tex.setParam("format", OSP_TEXTURE_RGBA32F); tex.setParam( "data", cpp::CopiedData(colors_mod.data(), vec2ul(colors_mod.size(), 1))); tex.commit(); cpp::Material mat("obj"); if (attribute == 1) // texture mat.setParam("map_kd", tex); mat.commit(); if (useSubd) { mesh = cpp::Geometry("subdivision"); mesh.setParam("vertex.position", cpp::CopiedData(vertices)); mesh.setParam("face", cpp::CopiedData(faces)); mesh.setParam("level", 1.0f); // global level mesh.setParam("index", cpp::CopiedData(subd_indices)); mesh.setParam("mode", OSP_SUBDIVISION_PIN_CORNERS); } else { mesh = cpp::Geometry("mesh"); mesh.setParam("vertex.position", cpp::CopiedData(vertices)); mesh.setParam("index", cpp::CopiedData(quad_indices)); } if (interpolation == 0) { if (attribute == 1) mesh.setParam("texcoord", cpp::CopiedData(texcoords)); else if (attribute == 2) mesh.setParam("normal", cpp::CopiedData(normals)); else mesh.setParam("color", cpp::CopiedData(colors_mod)); } else if (interpolation == 1) { if (attribute == 1) mesh.setParam("vertex.texcoord", cpp::CopiedData(texcoords)); else if (attribute == 2) mesh.setParam("vertex.normal", cpp::CopiedData(normals)); else mesh.setParam("vertex.color", cpp::CopiedData(colors_mod)); } mesh.commit(); cpp::GeometricModel model(mesh); model.setParam("material", mat); if ((attribute == 0) && interpolation == 2) model.setParam("color", cpp::CopiedData(colors_mod)); else if ((attribute == 0) && interpolation == 3) model.setParam("color", colors_mod[0]); model.commit(); cpp::Group group; group.setParam("geometry", cpp::CopiedData(model)); group.commit(); return group; } cpp::World Interpolation::buildWorld() const { auto world = Builder::buildWorld(); cpp::Light light("distant"); light.setParam("color", vec3f(0.78f, 0.551f, 0.183f)); light.setParam("intensity", 3.14f); light.setParam("direction", vec3f(-0.8f, -0.6f, 0.3f)); light.commit(); cpp::Light ambient("ambient"); ambient.setParam("intensity", 0.35f); ambient.setParam("visible", false); ambient.commit(); std::vector lights{light, ambient}; world.setParam("light", cpp::CopiedData(lights)); return world; } OSP_REGISTER_TESTING_BUILDER(Interpolation, interpolation); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/Noise.cpp000066400000000000000000000062621456566705700262540ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Noise.h" namespace ospray { namespace testing { // Heavily based on Perlin's Java reference implementation of the improved // perlin noise paper from Siggraph 2002 from here // https://mrl.nyu.edu/~perlin/noise/ PerlinNoise::PerlinNoiseData::PerlinNoiseData() { const int permutation[256] = {151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180}; for (int i = 0; i < 256; i++) p[256 + i] = p[i] = permutation[i]; } PerlinNoise::PerlinNoiseData PerlinNoise::p; } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/Noise.h000066400000000000000000000061751456566705700257240ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ospray_testing.h" using namespace rkcommon::math; namespace ospray { namespace testing { /* * Our basic noise primitive. * Heavily based on Perlin's Java reference implementation of * the improved perlin noise paper from Siggraph 2002 from here * https://mrl.nyu.edu/~perlin/noise/ */ class PerlinNoise { struct PerlinNoiseData { PerlinNoiseData(); inline int operator[](size_t idx) const { return p[idx]; } int p[512]; }; static PerlinNoiseData p; static inline float smooth(float t) { return t * t * t * (t * (t * 6.f - 15.f) + 10.f); } static inline float grad(int hash, float x, float y, float z) { const int h = hash & 15; const float u = h < 8 ? x : y; const float v = h < 4 ? y : h == 12 || h == 14 ? x : z; return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); } public: static float noise(vec3f q, float frequency = 8.f) { float x = q.x * frequency; float y = q.y * frequency; float z = q.z * frequency; const int X = (int)floor(x) & 255; const int Y = (int)floor(y) & 255; const int Z = (int)floor(z) & 255; x -= floor(x); y -= floor(y); z -= floor(z); const float u = smooth(x); const float v = smooth(y); const float w = smooth(z); const int A = p[X] + Y; const int B = p[X + 1] + Y; const int AA = p[A] + Z; const int BA = p[B] + Z; const int BB = p[B + 1] + Z; const int AB = p[A + 1] + Z; return lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z), grad(p[BA], x - 1, y, z)), lerp(u, grad(p[AB], x, y - 1, z), grad(p[BB], x - 1, y - 1, z))), lerp(v, lerp(u, grad(p[AA + 1], x, y, z - 1), grad(p[BA + 1], x - 1, y, z - 1)), lerp(u, grad(p[AB + 1], x, y - 1, z - 1), grad(p[BB + 1], x - 1, y - 1, z - 1)))); } }; // ----------------------------------------------------------------------------- // Hypertexture helpers. // ----------------------------------------------------------------------------- /* * Turbulence - noise at various scales. */ inline float turbulence(const vec3f &p, float base_freqency, int octaves) { float value = 0.f; float scale = 1.f; for (int o = 0; o < octaves; ++o) { value += PerlinNoise::noise(scale * p, base_freqency) / scale; scale *= 2.f; } return value; }; /* * A torus indicator function. */ inline bool torus(vec3f X, float R, float r) { const float tmp = sqrtf(X.x * X.x + X.z * X.z) - R; return tmp * tmp + X.y * X.y - r * r < 0.f; } /* * Turbulent torus indicator function. * We use the turbulence() function to distort space. */ inline bool turbulentTorus(vec3f p, float R, float r) { const vec3f X = 2.f * p - vec3f(1.f); return torus((1.4f + 0.4 * turbulence(p, 12.f, 12)) * X, R, r); } /* * Turbulent sphere indicator function. */ inline bool turbulentSphere(vec3f p, float r) { vec3f X = 2.f * p - vec3f(1.f); return length((1.4f + 0.4 * turbulence(p, 12.f, 12)) * X) < r; } } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/ParticleVolume.cpp000066400000000000000000000163301456566705700301270ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "ospray_testing.h" // stl #include #include // file IO #include #include #include #include // rkcommon #include "rkcommon/math/range.h" #include "rkcommon/math/vec.h" #include "rkcommon/tasking/parallel_for.h" #include "rkcommon/utility/random.h" using namespace rkcommon; using namespace rkcommon::math; namespace ospray { namespace testing { using VoxelArray = std::vector; struct ParticleVolume : public detail::Builder { ParticleVolume(int numParticles, bool withVolume, bool withIsosurface, bool withClipping, bool multipleIsosurfaces, bool provideWeights, float clampMaxCumulativeValue, float radiusSupportFactor); ~ParticleVolume() override = default; void commit() override; cpp::Group buildGroup() const override; cpp::World buildWorld() const override; private: // Data // int numParticles{1000}; bool withVolume{true}; bool withIsosurface{false}; bool withClipping{false}; bool multipleIsosurfaces{false}; bool provideWeights{true}; float clampMaxCumulativeValue{0.f}; float radiusSupportFactor{4.f}; float isovalue{0.5f}; range1f valueRange{0, 1.5f}; box3f bounds{{0, 0, 0}, {10, 10, 10}}; }; // Inlined definitions //////////////////////////////////////////////////// ParticleVolume::ParticleVolume(int numParticles, bool withVolume, bool withIsosurface, bool withClipping, bool multipleIsosurfaces, bool provideWeights, float clampMaxCumulativeValue, float radiusSupportFactor) : numParticles(numParticles), withVolume(withVolume), withIsosurface(withIsosurface), withClipping(withClipping), multipleIsosurfaces(multipleIsosurfaces), provideWeights(provideWeights), clampMaxCumulativeValue(clampMaxCumulativeValue), radiusSupportFactor(radiusSupportFactor) {} void ParticleVolume::commit() { Builder::commit(); numParticles = getParam("numParticles", numParticles); withVolume = getParam("withVolume", withVolume); withIsosurface = getParam("withIsosurface", withIsosurface); isovalue = getParam("isovalue", 0.5f); withClipping = getParam("withClipping", withClipping); multipleIsosurfaces = getParam("multipleIsosurfaces", multipleIsosurfaces); clampMaxCumulativeValue = getParam("clampMaxCumulativeValue", clampMaxCumulativeValue); radiusSupportFactor = getParam("radiusSuportFactor", radiusSupportFactor); addPlane = false; } cpp::Group ParticleVolume::buildGroup() const { // AMK: Very similar to ProceduralParticleVolume.h in OpenVKL. Any way to // combine? std::vector particles(numParticles); std::vector radius(numParticles); std::vector weights(numParticles); int32_t randomSeed = 0; // create random number distributions for point center and weight std::mt19937 gen(randomSeed); range1f weightRange(0.5f, 1.5f); const float radiusScale = 1.f / powf(numParticles, 1.f / 3.f); utility::uniform_real_distribution centerDistribution_x( bounds.lower.x, bounds.upper.x); utility::uniform_real_distribution centerDistribution_y( bounds.lower.y, bounds.upper.y); utility::uniform_real_distribution centerDistribution_z( bounds.lower.z, bounds.upper.z); utility::uniform_real_distribution radiusDistribution( radiusScale, 2.f * radiusScale); utility::uniform_real_distribution weightDistribution( weightRange.lower, weightRange.upper); // populate the points for (int i = 0; i < numParticles; i++) { auto &p = particles[i]; p.x = centerDistribution_x(gen); p.y = centerDistribution_y(gen); p.z = centerDistribution_z(gen); radius[i] = radiusDistribution(gen); weights[i] = provideWeights ? weightDistribution(gen) : 1.f; } cpp::Volume volume("particle"); volume.setParam("particle.position", cpp::CopiedData(particles)); volume.setParam("particle.radius", cpp::CopiedData(radius)); volume.setParam("particle.weight", cpp::CopiedData(weights)); volume.setParam("clampMaxCumulativeValue", clampMaxCumulativeValue); volume.setParam("radiusSupportFactor", radiusSupportFactor); volume.commit(); cpp::VolumetricModel model(volume); // AMK: VKL will set the correct valueRange, but we don't have a good way to // get that to OSPRay yet. Use the weightRange instead. model.setParam("transferFunction", makeTransferFunction(range1f(0.f, weightRange.upper))); model.commit(); cpp::Group group; if (withVolume) group.setParam("volume", cpp::CopiedData(model)); if (withIsosurface) { cpp::Geometry isoGeom("isosurface"); std::vector isovalues = {isovalue}; if (multipleIsosurfaces) { isovalues.push_back(isovalue + .25f); } isoGeom.setParam("isovalue", cpp::CopiedData(isovalues)); isoGeom.setParam("volume", volume); isoGeom.commit(); cpp::GeometricModel isoModel(isoGeom); cpp::Material mat("obj"); mat.setParam("kd", vec3f(1.f)); mat.setParam("d", 0.5f); mat.setParam("ks", vec3f(0.2f)); mat.commit(); if (multipleIsosurfaces) { std::vector colors = { vec4f(0.2f, 0.2f, 0.8f, 1.f), vec4f(0.8f, 0.2f, 0.2f, 1.f)}; isoModel.setParam("color", cpp::CopiedData(colors)); } isoModel.setParam("material", mat); isoModel.commit(); group.setParam("geometry", cpp::CopiedData(isoModel)); } group.commit(); return group; } cpp::World ParticleVolume::buildWorld() const { // Skip clipping if not enabled std::vector instances; if (withClipping) { // Create clipping plane std::vector geometricModels; { cpp::Geometry planeGeometry("plane"); std::vector coefficients = {vec4f(1.f, -1.f, 1.f, 0.f)}; planeGeometry.setParam( "plane.coefficients", cpp::CopiedData(coefficients)); planeGeometry.commit(); cpp::GeometricModel model(planeGeometry); model.commit(); geometricModels.emplace_back(model); } // Create clipping sphere { cpp::Geometry sphereGeometry("sphere"); std::vector position = {vec3f(.2f, -.2f, .2f)}; sphereGeometry.setParam("sphere.position", cpp::CopiedData(position)); sphereGeometry.setParam("radius", .5f); sphereGeometry.commit(); cpp::GeometricModel model(sphereGeometry); model.commit(); geometricModels.emplace_back(model); } cpp::Group group; group.setParam("clippingGeometry", cpp::CopiedData(geometricModels)); group.commit(); cpp::Instance inst(group); inst.commit(); instances.push_back(inst); } auto world = Builder::buildWorld(instances); return world; } OSP_REGISTER_TESTING_BUILDER( ParticleVolume(1000, true, false, false, false, true, 0.f, 4.f), particle_volume); OSP_REGISTER_TESTING_BUILDER( ParticleVolume(1000, false, true, false, false, true, 0.f, 4.f), particle_volume_isosurface); OSP_REGISTER_TESTING_BUILDER( ParticleVolume(1000, true, false, true, false, true, 0.f, 4.f), clip_particle_volume); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/PerlinNoiseVolumes.cpp000066400000000000000000000231371456566705700310010ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "Noise.h" #include "ospray_testing.h" #include "rkcommon/tasking/parallel_for.h" #include "rkcommon/utility/multidim_index_sequence.h" #include "rkcommon/utility/random.h" // stl #include #include using namespace rkcommon::math; namespace ospray { namespace testing { struct PerlinNoiseVolumes : public detail::Builder { PerlinNoiseVolumes(bool clip = false, bool gradientShading = false); PerlinNoiseVolumes(const vec3ui &numVolumes, const vec3ul &volumeDimensions, float densityScale); ~PerlinNoiseVolumes() override = default; void commit() override; cpp::Group buildGroup() const override; cpp::World buildWorld() const override; private: vec3ui numVolumes{1, 1, 1}; vec3ul volumeDimensions{128}; bool addSphereVolume{true}; bool addTorusVolume{true}; bool addBoxes{false}; bool addAreaLight{true}; bool addAmbientLight{true}; float densityScale{10.f}; float anisotropy{0.f}; float gradientShadingScale{0.f}; bool withClipping{false}; }; // Inlined definitions //////////////////////////////////////////////////// // Helper functions // cpp::Geometry makeBoxGeometry(const box3f &box) { cpp::Geometry ospGeometry("box"); ospGeometry.setParam("box", cpp::CopiedData(box)); ospGeometry.commit(); return ospGeometry; } cpp::VolumetricModel createProceduralVolumetricModel( std::function D, const std::vector &colors, const std::vector &opacities, const vec3ul &dims, float densityScale, float anisotropy, float gradientShadingScale) { const float spacing = 3.f / (reduce_max(dims) - 1); cpp::Volume volume("structuredRegular"); // generate volume data auto numVoxels = dims.product(); std::vector voxels(numVoxels, 0); tasking::parallel_for(dims.z, [&](uint64_t z) { for (uint64_t y = 0; y < dims.y; ++y) { for (uint64_t x = 0; x < dims.x; ++x) { vec3f p = vec3f(x + 0.5f, y + 0.5f, z + 0.5f) / dims; if (D(p)) voxels[dims.x * dims.y * z + dims.x * y + x] = 0.5f + 0.5f * PerlinNoise::noise(p, 12); } } }); // calculate voxel range range1f voxelRange; std::for_each(voxels.begin(), voxels.end(), [&](float &v) { if (!std::isnan(v)) voxelRange.extend(v); }); volume.setParam("data", cpp::CopiedData(voxels.data(), dims)); volume.setParam("gridOrigin", vec3f(-1.5f, -1.5f, -1.5f)); volume.setParam("gridSpacing", vec3f(spacing)); volume.commit(); cpp::TransferFunction tfn("piecewiseLinear"); tfn.setParam("value", voxelRange); tfn.setParam("color", cpp::CopiedData(colors)); tfn.setParam("opacity", cpp::CopiedData(opacities)); tfn.commit(); cpp::VolumetricModel volumeModel(volume); volumeModel.setParam("densityScale", densityScale); volumeModel.setParam("anisotropy", anisotropy); volumeModel.setParam("transferFunction", tfn); volumeModel.setParam("gradientShadingScale", gradientShadingScale); volumeModel.commit(); return volumeModel; } cpp::GeometricModel createGeometricModel(cpp::Geometry geo, const vec3f &kd) { cpp::GeometricModel geometricModel(geo); cpp::Material objMaterial("obj"); objMaterial.setParam("kd", kd); objMaterial.commit(); geometricModel.setParam("material", objMaterial); return geometricModel; } // PerlineNoiseVolumes definitions // PerlinNoiseVolumes::PerlinNoiseVolumes(bool clip, bool gradientShading) : gradientShadingScale(gradientShading), withClipping(clip) {} PerlinNoiseVolumes::PerlinNoiseVolumes(const vec3ui &numVolumes, const vec3ul &volumeDimensions, float densityScale) : numVolumes(numVolumes), volumeDimensions(volumeDimensions), addAreaLight(false), densityScale(densityScale) {} void PerlinNoiseVolumes::commit() { Builder::commit(); // Should be at least 2 volumeDimensions = getParam("volumeDimensions", volumeDimensions); addSphereVolume = getParam("addSphereVolume", addSphereVolume); addTorusVolume = getParam("addTorusVolume", addTorusVolume); addBoxes = getParam("addBoxes", addBoxes); addAreaLight = getParam("addAreaLight", addAreaLight); addAmbientLight = getParam("addAmbientLight", addAmbientLight); densityScale = getParam("densityScale", densityScale); anisotropy = getParam("anisotropy", anisotropy); gradientShadingScale = getParam("gradientShadingScale", gradientShadingScale); withClipping = getParam("withClipping", withClipping); } cpp::Group PerlinNoiseVolumes::buildGroup() const { cpp::Group group; std::vector volumetricModels; if (addSphereVolume) { volumetricModels.emplace_back(createProceduralVolumetricModel( [](const vec3f &p) { return turbulentSphere(p, 1.f); }, {vec3f(0.f, 0.0f, 0.f), vec3f(1.f, 0.f, 0.f), vec3f(0.f, 1.f, 1.f), vec3f(1.f, 1.f, 1.f)}, {0.f, 0.33f, 0.66f, 1.f}, volumeDimensions, densityScale, anisotropy, gradientShadingScale)); } if (addTorusVolume) { volumetricModels.emplace_back(createProceduralVolumetricModel( [](const vec3f &p) { return turbulentTorus(p, 1.f, 0.375f); }, {vec3f(0.0, 0.0, 0.0), vec3f(1.0, 0.65, 0.0), vec3f(0.12, 0.6, 1.0), vec3f(1.0, 1.0, 1.0)}, {0.f, 0.33f, 0.66f, 1.f}, volumeDimensions, densityScale, anisotropy, gradientShadingScale)); } for (auto &volumetricModel : volumetricModels) volumetricModel.commit(); std::vector geometricModels; if (addBoxes) { auto box1 = makeBoxGeometry( box3f(vec3f(-1.5f, -1.f, -0.75f), vec3f(-0.5f, 0.f, 0.25f))); auto box2 = makeBoxGeometry(box3f(vec3f(0.0f, -1.5f, 0.f), vec3f(2.f, 1.5f, 2.f))); geometricModels.emplace_back( createGeometricModel(box1, vec3f(0.2f, 0.2f, 0.2f))); geometricModels.emplace_back( createGeometricModel(box2, vec3f(0.2f, 0.2f, 0.2f))); } for (auto &geometricModel : geometricModels) geometricModel.commit(); if (!volumetricModels.empty()) group.setParam("volume", cpp::CopiedData(volumetricModels)); if (!geometricModels.empty()) group.setParam("geometry", cpp::CopiedData(geometricModels)); group.commit(); return group; } cpp::World PerlinNoiseVolumes::buildWorld() const { // Skip clipping if not enabled std::vector instances; if (withClipping) { // Create clipping sphere cpp::Geometry sphereGeometry("sphere"); std::vector position = {vec3f(-.5f, .2f, -.5f)}; sphereGeometry.setParam("sphere.position", cpp::CopiedData(position)); sphereGeometry.setParam("radius", 1.2f); sphereGeometry.commit(); cpp::GeometricModel model(sphereGeometry); model.commit(); cpp::Group group; group.setParam("clippingGeometry", cpp::CopiedData(model)); group.commit(); cpp::Instance inst(group); inst.commit(); instances.push_back(inst); } // Create a group with volumes auto group = buildGroup(); const box3f groupBounds = group.getBounds(); // Create instances std::mt19937 gen(randomSeed); utility::uniform_real_distribution dstrX( groupBounds.lower.x, groupBounds.upper.x); utility::uniform_real_distribution dstrY( groupBounds.lower.y, groupBounds.upper.y); utility::uniform_real_distribution dstrZ( groupBounds.lower.z, groupBounds.upper.z); const vec3f totalSize = groupBounds.size() * (numVolumes - 1); box3f sceneBounds; index_sequence_3D indexVolumes(numVolumes); for (const vec3ui i : indexVolumes) { vec3f rndT = vec3f(0.0f); if (i != vec3ui(0)) { rndT.x = dstrX(gen); rndT.y = dstrY(gen); rndT.z = dstrZ(gen); } const vec3f position = groupBounds.size() * vec3f(i.x, i.y, i.z) - 0.5f * vec3f(totalSize.x, 0.0f, totalSize.z) + rndT; cpp::Instance instance(group); instance.setParam("transform", affine3f::translate(position)); instance.commit(); instances.push_back(instance); sceneBounds.extend(groupBounds + position); } if (addPlane) instances.push_back(makeGroundPlane(sceneBounds)); cpp::World world; world.setParam("instance", cpp::CopiedData(instances)); std::vector lightHandles; cpp::Light quadLight("quad"); quadLight.setParam("position", vec3f(-4.0f, 3.0f, 1.0f)); quadLight.setParam("edge1", vec3f(0.f, 0.0f, -1.0f)); quadLight.setParam("edge2", vec3f(1.0f, 0.5, 0.0f)); quadLight.setParam("intensity", 50.0f); quadLight.setParam("color", vec3f(2.6f, 2.5f, 2.3f)); quadLight.commit(); cpp::Light ambientLight("ambient"); ambientLight.setParam("intensity", 0.4f); ambientLight.setParam("color", vec3f(1.f)); ambientLight.setParam("visible", false); ambientLight.commit(); if (addAreaLight) lightHandles.push_back(quadLight); if (addAmbientLight) lightHandles.push_back(ambientLight); if (lightHandles.empty()) world.removeParam("light"); else world.setParam("light", cpp::CopiedData(lightHandles)); return world; } OSP_REGISTER_TESTING_BUILDER(PerlinNoiseVolumes, perlin_noise_volumes); OSP_REGISTER_TESTING_BUILDER( PerlinNoiseVolumes({7, 7, 13}, {8}, .4f), perlin_noise_many_volumes); OSP_REGISTER_TESTING_BUILDER( PerlinNoiseVolumes(true), clip_perlin_noise_volumes); OSP_REGISTER_TESTING_BUILDER( PerlinNoiseVolumes(false, true), perlin_noise_volumes_gradient); OSP_REGISTER_TESTING_BUILDER( PerlinNoiseVolumes(true, true), clip_perlin_noise_volumes_gradient); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/Planes.cpp000066400000000000000000000032341456566705700264150ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "ospray_testing.h" using namespace rkcommon::math; namespace ospray { namespace testing { struct Planes : public detail::Builder { Planes() = default; ~Planes() override = default; void commit() override; cpp::Group buildGroup() const override; }; // Inlined definitions //////////////////////////////////////////////////// void Planes::commit() { Builder::commit(); addPlane = false; } cpp::Group Planes::buildGroup() const { // Create plane geometry cpp::Geometry planeGeometry("plane"); std::vector coeffs; std::vector bounds; const box3f b = box3f(vec3f(-2.f, -2.f, -1.f), vec3f(2.f, 2.f, 1.f)); const uint32_t count = 28; for (uint32_t i = 0; i < count; i++) { affine3f rotate = affine3f::rotate( vec3f(.3f, 0.f, 1.f), (i / float(count)) * 2.0f * M_PI); vec3f p = xfmNormal(rotate, vec3f(1.f, 0.f, 0.f)); coeffs.push_back(vec4f(p.x, p.y, p.z, 0.f)); bounds.push_back(b); } planeGeometry.setParam("plane.coefficients", cpp::CopiedData(coeffs)); planeGeometry.setParam("plane.bounds", cpp::CopiedData(bounds)); planeGeometry.commit(); // Create geometric model cpp::GeometricModel model(planeGeometry); cpp::Material material("obj"); material.setParam("kd", vec3f(.1f, .4f, .8f)); material.commit(); model.setParam("material", material); model.commit(); // Create group cpp::Group group; group.setParam("geometry", cpp::CopiedData(model)); group.commit(); // Done return group; } OSP_REGISTER_TESTING_BUILDER(Planes, planes); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/RandomSpheres.cpp000066400000000000000000000057151456566705700277530ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "ospray_testing.h" #include "rkcommon/utility/random.h" // stl #include using namespace rkcommon::math; namespace ospray { namespace testing { struct Spheres : public detail::Builder { Spheres(OSPSphereType type); ~Spheres() override = default; void commit() override; cpp::Group buildGroup() const override; private: // Data // OSPSphereType sphereType; int numSpheres{100}; }; // Inlined definitions //////////////////////////////////////////////////// Spheres::Spheres(OSPSphereType type) : sphereType(type) {} void Spheres::commit() { Builder::commit(); numSpheres = getParam("numSpheres", 100); } cpp::Group Spheres::buildGroup() const { std::vector s_center(numSpheres); std::vector s_radius(numSpheres); std::vector s_colors(numSpheres); // create random number distributions for sphere center, radius, and color std::mt19937 gen(randomSeed); utility::uniform_real_distribution centerDistribution(-1.f, 1.f); utility::uniform_real_distribution radiusDistribution(0.05f, 0.15f); utility::uniform_real_distribution colorDistribution(0.5f, 1.f); // populate the spheres for (auto ¢er : s_center) { center.x = centerDistribution(gen); center.y = centerDistribution(gen); center.z = centerDistribution(gen); } for (auto &radius : s_radius) radius = radiusDistribution(gen); for (auto &c : s_colors) { c.x = colorDistribution(gen); c.y = colorDistribution(gen); c.z = colorDistribution(gen); c.w = colorDistribution(gen); } // create the sphere geometry, and assign attributes cpp::Geometry spheresGeometry("sphere"); spheresGeometry.setParam("type", sphereType); spheresGeometry.setParam("sphere.position", cpp::CopiedData(s_center)); if (sphereType == OSP_ORIENTED_DISC) { spheresGeometry.setParam("sphere.normal", cpp::CopiedData(s_center)); } spheresGeometry.setParam("sphere.radius", cpp::CopiedData(s_radius)); spheresGeometry.commit(); cpp::GeometricModel model(spheresGeometry); model.setParam("color", cpp::CopiedData(s_colors)); if (rendererType == "pathtracer") { // create glass material and assign to geometry cpp::Material glassMaterial("thinGlass"); glassMaterial.setParam("attenuationDistance", 0.2f); glassMaterial.commit(); model.setParam("material", glassMaterial); } else { cpp::Material glassMaterial("obj"); glassMaterial.commit(); model.setParam("material", glassMaterial); } model.commit(); cpp::Group group; group.setParam("geometry", cpp::CopiedData(model)); group.commit(); return group; } OSP_REGISTER_TESTING_BUILDER(Spheres(OSP_SPHERE), random_spheres); OSP_REGISTER_TESTING_BUILDER(Spheres(OSP_DISC), random_discs); OSP_REGISTER_TESTING_BUILDER(Spheres(OSP_ORIENTED_DISC), random_oriented_discs); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/Streamlines.cpp000066400000000000000000000077021456566705700274650ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "ospray_testing.h" #include "rkcommon/utility/random.h" // stl #include using namespace rkcommon::math; namespace ospray { namespace testing { struct Streamlines : public detail::Builder { Streamlines() = default; ~Streamlines() override = default; void commit() override; cpp::Group buildGroup() const override; }; // Inlined definitions //////////////////////////////////////////////////// void Streamlines::commit() { Builder::commit(); addPlane = false; } cpp::Group Streamlines::buildGroup() const { cpp::Geometry slGeom("curve"); std::vector points; std::vector indices; std::vector colors; std::mt19937 rng(randomSeed); utility::uniform_real_distribution radDist(0.5f, 1.5f); utility::uniform_real_distribution stepDist(0.001f, 0.1f); utility::uniform_real_distribution sDist(0, 360); utility::uniform_real_distribution dDist(360, 720); utility::uniform_real_distribution freqDist(0.5f, 1.5f); // create multiple lines int numLines = 100; for (int l = 0; l < numLines; l++) { int dStart = sDist(rng); int dEnd = dDist(rng); float radius = radDist(rng); float h = 0; float hStep = stepDist(rng); float f = freqDist(rng); float r = (720 - dEnd) / 360.f; vec4f c(r, 1 - r, 1 - r / 2, 1.f); // spiral up with changing radius of curvature for (int d = dStart; d < dStart + dEnd; d += 10, h += hStep) { vec3f p, q; float startRadius, endRadius; p.x = radius * std::sin(d * M_PI / 180.f); p.y = h - 2; p.z = radius * std::cos(d * M_PI / 180.f); startRadius = 0.015f * std::sin(f * d * M_PI / 180) + 0.02f; q.x = (radius - 0.05f) * std::sin((d + 10) * M_PI / 180.f); q.y = h + hStep - 2; q.z = (radius - 0.05f) * std::cos((d + 10) * M_PI / 180.f); endRadius = 0.015f * std::sin(f * (d + 10) * M_PI / 180) + 0.02f; if (d == dStart) { const vec3f rim = lerp(1.f + endRadius / length(q - p), q, p); const vec3f cap = lerp(1.f + startRadius / length(rim - p), p, rim); points.push_back(vec4f(cap, 0.f)); points.push_back(vec4f(rim, 0.f)); points.push_back(vec4f(p, startRadius)); points.push_back(vec4f(q, endRadius)); indices.push_back(points.size() - 4); colors.push_back(c); colors.push_back(c); } else if (d + 10 < dStart + dEnd && d + 20 > dStart + dEnd) { const vec3f rim = lerp(1.f + startRadius / length(p - q), p, q); const vec3f cap = lerp(1.f + endRadius / length(rim - q), q, rim); points.push_back(vec4f(p, startRadius)); points.push_back(vec4f(q, endRadius)); points.push_back(vec4f(rim, 0.f)); points.push_back(vec4f(cap, 0.f)); indices.push_back(points.size() - 7); indices.push_back(points.size() - 6); indices.push_back(points.size() - 5); indices.push_back(points.size() - 4); colors.push_back(c); colors.push_back(c); } else if ((d != dStart && d != dStart + 10) && d + 20 < dStart + dEnd) { points.push_back(vec4f(p, startRadius)); indices.push_back(points.size() - 4); } colors.push_back(c); radius -= 0.05f; } } slGeom.setParam("vertex.position_radius", cpp::CopiedData(points)); slGeom.setParam("index", cpp::CopiedData(indices)); slGeom.setParam("vertex.color", cpp::CopiedData(colors)); slGeom.setParam("type", OSP_ROUND); slGeom.setParam("basis", OSP_CATMULL_ROM); slGeom.commit(); cpp::GeometricModel model(slGeom); cpp::Material slMat("obj"); slMat.commit(); model.setParam("material", slMat); model.commit(); cpp::Group group; group.setParam("geometry", cpp::CopiedData(model)); group.commit(); return group; } OSP_REGISTER_TESTING_BUILDER(Streamlines, streamlines); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/SubdivisionCube.cpp000066400000000000000000000062731456566705700302760ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "ospray_testing.h" using namespace rkcommon::math; namespace ospray { namespace testing { struct SubdivisionCube : public detail::Builder { SubdivisionCube() = default; ~SubdivisionCube() override = default; cpp::Group buildGroup() const override; }; // Inlined definitions //////////////////////////////////////////////////// cpp::Group SubdivisionCube::buildGroup() const { // vertices of a cube std::vector vertices = {{-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {-1.0f, 1.0f, -1.0f}, {1.0f, 1.0f, -1.0f}, {1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, /*WA: pad for Embree*/ {0.0f}}; // color per vertex std::vector colors = {{0.0f, 0.0f, 0.0f, 1.f}, {1.0f, 0.0f, 0.0f, 1.f}, {1.0f, 0.0f, 1.0f, 1.f}, {0.0f, 0.0f, 1.0f, 1.f}, {0.0f, 1.0f, 0.0f, 1.f}, {1.0f, 1.0f, 0.0f, 1.f}, {1.0f, 1.0f, 1.0f, 1.f}, {0.0f, 1.0f, 1.0f, 1.f}}; // number of vertex indices per face std::vector faces = {4, 4, 4, 4, 4, 4}; // vertex indices for all faces std::vector indices = { 0, 4, 5, 1, 1, 5, 6, 2, 2, 6, 7, 3, 0, 3, 7, 4, 4, 7, 6, 5, 0, 1, 2, 3, }; // vertex crease indices and weights std::vector vertexCreaseIndices = {0, 1, 2, 3, 4, 5, 6, 7}; std::vector vertexCreaseWeights = { 2.f, 2.f, 2.f, 2.f, 2.f, 2.f, 2.f, 2.f}; // edge crease indices and weights std::vector edgeCreaseIndices = {{0, 1}, {1, 2}, {2, 3}, {3, 0}, {4, 5}, {5, 6}, {6, 7}, {7, 4}, {0, 4}, {1, 5}, {2, 6}, {3, 7}}; std::vector edgeCreaseWeights = { 2.f, 2.f, 2.f, 2.f, 2.f, 2.f, 2.f, 2.f, 2.f, 2.f, 2.f, 2.f}; // global level of tessellation float level = 5.f; // create the OSPRay geometry and set all parameters cpp::Geometry geometry("subdivision"); geometry.setParam("vertex.position", cpp::CopiedData(vertices)); geometry.setParam("vertex.color", cpp::CopiedData(colors)); geometry.setParam("face", cpp::CopiedData(faces)); geometry.setParam("index", cpp::CopiedData(indices)); geometry.setParam("vertexCrease.index", cpp::CopiedData(vertexCreaseIndices)); geometry.setParam("vertexCrease.weight", cpp::CopiedData(vertexCreaseWeights)); geometry.setParam("edgeCrease.index", cpp::CopiedData(edgeCreaseIndices)); geometry.setParam("edgeCrease.weight", cpp::CopiedData(edgeCreaseWeights)); geometry.setParam("level", level); geometry.setParam("mode", OSP_SUBDIVISION_PIN_CORNERS); geometry.commit(); cpp::GeometricModel model(geometry); cpp::Material material("obj"); material.commit(); model.setParam("material", material); model.commit(); cpp::Group group; group.setParam("geometry", cpp::CopiedData(model)); group.commit(); return group; } OSP_REGISTER_TESTING_BUILDER(SubdivisionCube, subdivision_cube); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/Transparency.cpp000066400000000000000000000112271456566705700276450ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "ospray_testing.h" #include "rkcommon/utility/multidim_index_sequence.h" using namespace rkcommon::math; namespace ospray { namespace testing { struct Transparency : public detail::Builder { Transparency() = default; ~Transparency() override = default; void commit() override; cpp::Group buildGroup() const override; cpp::World buildWorld() const override; }; // Inlined definitions //////////////////////////////////////////////////// void Transparency::commit() { Builder::commit(); addPlane = true; } cpp::Group Transparency::buildGroup() const { // Create plane geometry cpp::Geometry planeGeometry("plane"); { std::vector coeffs = {{0.f, 0.f, 1.f, 0.f}, {0.f, 0.f, 1.f, 0.f}, {0.f, 0.f, 1.f, 0.f}, {0.f, 0.f, 1.f, 0.f}, {0.f, 0.f, 1.f, -.4f}, {0.f, 0.f, 1.f, -.45f}, {0.f, 0.f, 1.f, -.5f}}; std::vector bounds = {{{-2.f, 1.8f, -2.f}, {2.f, 2.f, 2.f}}, {{-2.f, 1.6f, -2.f}, {2.f, 1.8f, 2.f}}, {{-2.f, 1.4f, -2.f}, {2.f, 1.6f, 2.f}}, {{-2.f, 0.2f, -2.f}, {2.f, 1.4f, 2.f}}, {{-1.7f, 1.f, -1.f}, {-.3f, 2.f, 1.f}}, {{-.7f, 1.f, -1.f}, {.7f, 2.f, 1.f}}, {{.3f, 1.f, -1.f}, {1.7f, 2.f, 1.f}}}; planeGeometry.setParam("plane.coefficients", cpp::CopiedData(coeffs)); planeGeometry.setParam("plane.bounds", cpp::CopiedData(bounds)); planeGeometry.commit(); } // Create geometric model cpp::GeometricModel gModel(planeGeometry); { std::vector colors = {{.8f, 0.f, 0.f}, {0.f, .8f, 0.f}, {0.f, 0.f, .8f}, {.8f, .8f, .8f}, {.5f, 0.f, 0.f}, {0.f, .5f, 0.f}, {0.f, 0.f, .5f}}; std::vector transmissions = {{0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}, {0.f, 0.f, 0.f}, {.8f, 0.f, 0.f}, {0.f, .8f, 0.f}, {0.f, 0.f, .8f}}; std::vector materials; for (uint32_t i = 0; i < std::min(colors.size(), transmissions.size()); i++) { materials.emplace_back(cpp::Material("obj")); materials[i].setParam("kd", colors[i]); materials[i].setParam("tf", transmissions[i]); materials[i].commit(); } gModel.setParam("material", cpp::CopiedData(materials)); gModel.commit(); } // Create volume object with values being shortest distance to surface for // gradient shading working correctly cpp::Volume volume("structuredRegular"); { volume.setParam("gridOrigin", vec3f(-2.f, -.7f, -.1f)); volume.setParam("gridSpacing", vec3f(.1f)); const vec3i volumeCells{41, 10, 5}; std::vector voxels(volumeCells.long_product()); index_sequence_3D numCell(volumeCells); for (vec3i i : numCell) { voxels[numCell.flatten(i)] = (float)std::min( {i.x < (volumeCells.x / 2) ? i.x : volumeCells.x - i.x - 1, i.y < (volumeCells.y / 2) ? i.y : volumeCells.y - i.y - 1, i.z < (volumeCells.z / 2) ? i.z : volumeCells.z - i.z - 1}); } volume.setParam("data", cpp::CopiedData(voxels.data(), volumeCells)); volume.commit(); } // Create volume model cpp::VolumetricModel vModel(volume); { // Create transfer function cpp::TransferFunction transferFunction("piecewiseLinear"); { std::vector colors = {{1.f, 1.f, 1.f}}; std::vector opacities = {1.f}; transferFunction.setParam("color", cpp::CopiedData(colors)); transferFunction.setParam("opacity", cpp::CopiedData(opacities)); transferFunction.setParam("value", range1f(0.f, 10.f)); transferFunction.commit(); } vModel.setParam("transferFunction", transferFunction); vModel.setParam("densityScale", 10.f); vModel.setParam("gradientShadingScale", 1.f); vModel.commit(); } // Create group cpp::Group group; group.setParam("geometry", cpp::CopiedData(gModel)); group.setParam("volume", cpp::CopiedData(vModel)); group.commit(); // Done return group; } cpp::World Transparency::buildWorld() const { auto world = Builder::buildWorld(); cpp::Light light("distant"); light.setParam("color", vec3f(0.78f, 0.551f, 0.483f)); light.setParam("intensity", 3.14f); light.setParam("direction", vec3f(0.f, -0.75f, 0.25f)); light.commit(); cpp::Light ambient("ambient"); ambient.setParam("intensity", 0.5f); ambient.setParam("visible", false); ambient.commit(); std::vector lights{light, ambient}; world.setParam("light", cpp::CopiedData(lights)); return world; } OSP_REGISTER_TESTING_BUILDER(Transparency, transparency); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/UnstructuredVolumeGen.cpp000066400000000000000000000241441456566705700315270ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "ospray_testing.h" #include "rkcommon/utility/multidim_index_sequence.h" using namespace rkcommon::math; namespace { // List degenerate tetrahedrons std::vector> tetraNotAllowed = {{0, 1, 2, 3}, {4, 5, 6, 7}, {0, 3, 4, 7}, {1, 2, 5, 6}, {0, 1, 4, 5}, {2, 3, 6, 7}}; // Allowed pyramid indices order std::vector> pyramidAllowed = {{0, 1, 2, 3, 4}, {0, 1, 2, 3, 5}, {0, 1, 2, 3, 6}, {0, 1, 2, 3, 7}, {4, 5, 6, 7, 0}, {4, 5, 6, 7, 1}, {4, 5, 6, 7, 2}, {4, 5, 6, 7, 3}, {0, 4, 7, 3, 1}, {0, 4, 7, 3, 2}, {0, 4, 7, 3, 5}, {0, 4, 7, 3, 6}, {1, 5, 6, 2, 0}, {1, 5, 6, 2, 3}, {1, 5, 6, 2, 4}, {1, 5, 6, 2, 7}, {0, 1, 5, 4, 2}, {0, 1, 5, 4, 3}, {0, 1, 5, 4, 6}, {0, 1, 5, 4, 7}, {2, 6, 7, 3, 0}, {2, 6, 7, 3, 1}, {2, 6, 7, 3, 4}, {2, 6, 7, 3, 5}}; // Allowed wedge indices order std::vector> wedgeAllowed = {{0, 1, 2, 4, 5, 6}, {1, 2, 3, 5, 6, 7}, {0, 2, 3, 4, 6, 7}, {0, 1, 3, 4, 5, 7}, {0, 4, 3, 1, 5, 2}, {0, 4, 7, 1, 5, 6}, {4, 7, 3, 5, 6, 2}, {0, 7, 3, 1, 6, 2}, {0, 1, 5, 3, 2, 6}, {1, 5, 4, 2, 6, 7}, {5, 4, 0, 6, 7, 3}, {0, 1, 4, 3, 2, 7}}; // Allowed wedge+pyramid indices order std::vector> wedgePyramidAllowed = { {0, 1, 2, 4, 5, 6, 0, 2, 6, 4, 3}, {0, 1, 2, 4, 5, 6, 0, 2, 6, 4, 7}, {1, 2, 3, 5, 6, 7, 1, 5, 7, 3, 0}, {1, 2, 3, 5, 6, 7, 1, 5, 7, 3, 4}, {0, 2, 3, 4, 6, 7, 0, 2, 6, 4, 1}, {0, 2, 3, 4, 6, 7, 0, 2, 6, 4, 5}, {0, 1, 3, 4, 5, 7, 1, 5, 7, 3, 2}, {0, 1, 3, 4, 5, 7, 1, 5, 7, 3, 6}}; // Indices order of all allowed primitives, indexed with 8-vertices mask std::array, 256> primsAllowed; // Not allowed primitives indexed with 8-vertices mask std::array primsNotAllowed; void initializeFromArray(const std::vector> &array) { for (auto &order : array) { uint32_t mask = 0; for (uint32_t i : order) mask |= (1 << i); std::vector &ids = primsAllowed[mask]; ids.insert(ids.begin(), order.begin(), order.end()); } } void initializePrims() { // Initialize degenerate tetrahedrons for (auto &order : tetraNotAllowed) { uint32_t mask = 0; for (uint32_t i : order) mask |= (1 << i); primsNotAllowed[mask] = true; } // Initialize allowed primitives with its indices orders initializeFromArray(pyramidAllowed); initializeFromArray(wedgeAllowed); initializeFromArray(wedgePyramidAllowed); } float sphere(const vec3f &p, const vec3f ¢er, float radius) { vec3f t = p - center; return sqrt(t.x * t.x + t.y * t.y + t.z * t.z) - radius; } float ground(const vec3f &p, const vec3f ¢er) { vec3f t = p - center; return t.y + .1f * sin(10.f * t.x) + .1f * sin(10.f * t.z); } float sdf(const vec3f &p) { return std::min({ground(p, vec3f(0.f, -.7f, 0.f)), sphere(p, vec3f(0.f, .2f, 0.f), .6f), sphere(p, vec3f(.7f, 0.f, .7f), .3f), sphere(p, vec3f(-.6f, -.3f, -.6f), .25f)}); } } // namespace namespace ospray { namespace testing { struct UnstructuredVolumeGen : public detail::Builder { UnstructuredVolumeGen(bool transform = false, bool isosurface = false) : transform(transform), isosurface(isosurface) {} ~UnstructuredVolumeGen() override = default; void commit() override; cpp::Group buildGroup() const override; cpp::World buildWorld() const override; private: bool showCells{false}; float densityScale{1.f}; bool transform{false}; bool isosurface{false}; }; // Inlined definitions //////////////////////////////////////////////////// void UnstructuredVolumeGen::commit() { Builder::commit(); showCells = getParam("showCells", false); densityScale = getParam("densityScale", showCells ? 100.f : 3.f); tfOpacityMap = getParam( "tf.opacityMap", showCells ? "opaque" : "linearInv"); addPlane = false; } cpp::Group UnstructuredVolumeGen::buildGroup() const { // Prepare 3D grid vec3i dimensions = vec3i(30, 30, 30); index_sequence_3D numVertices(dimensions); std::vector positions; std::vector values; float size = 2.f; positions.resize(numVertices.total_indices()); values.resize(numVertices.total_indices()); for (auto i : numVertices) { vec3f i_f = static_cast(i); vec3f p = size * (i_f / (dimensions - 1) - .5f); uint32_t id = numVertices.flatten(i); values[id] = sdf(p); if (transform) p.z *= 0.25f; positions[id] = p; } // Initialize primitive arrays initializePrims(); // Iterate through all cubic cells in the created grid // and build appropriate unstructured cells index_sequence_3D numHex(dimensions - 1); std::vector indices; std::vector cells; std::vector cellTypes; std::vector cellValues; for (auto i : numHex) { std::vector ids = { (uint32_t)numVertices.flatten(i + vec3i(1, 0, 0)), (uint32_t)numVertices.flatten(i + vec3i(0, 0, 0)), (uint32_t)numVertices.flatten(i + vec3i(0, 0, 1)), (uint32_t)numVertices.flatten(i + vec3i(1, 0, 1)), (uint32_t)numVertices.flatten(i + vec3i(1, 1, 0)), (uint32_t)numVertices.flatten(i + vec3i(0, 1, 0)), (uint32_t)numVertices.flatten(i + vec3i(0, 1, 1)), (uint32_t)numVertices.flatten(i + vec3i(1, 1, 1))}; // Calculate mask for cubic cell consisting of 8 vertices, uint32_t mask = 0; uint32_t count = 0; for (uint32_t i = 0; i < 8; i++) { uint32_t bit = 1 << i; if (values[ids[i]] < 0.f) { mask |= bit; count++; } } // Depending on number of bits set switch (count) { // Build tetrahedron case 4: { if (primsNotAllowed[mask]) break; cells.push_back(indices.size()); cellTypes.push_back(OSP_TETRAHEDRON); cellValues.push_back(0.8f); for (uint32_t i = 0; i < 8; i++) if ((mask >> i) & 1) indices.push_back(ids[i]); } break; // Build pyramid case 5: { std::vector &pa = primsAllowed[mask]; if (pa.empty()) break; cells.push_back(indices.size()); cellTypes.push_back(OSP_PYRAMID); for (uint32_t i : pa) indices.push_back(ids[i]); cellValues.push_back(0.6f); } break; // Build wedge case 6: { std::vector &pa = primsAllowed[mask]; if (pa.empty()) break; cells.push_back(indices.size()); cellTypes.push_back(OSP_WEDGE); for (uint32_t i : pa) indices.push_back(ids[i]); cellValues.push_back(0.4f); } break; // Build wedge and pyramid case 7: { std::vector &pa = primsAllowed[mask]; if (pa.empty()) break; cells.push_back(indices.size()); cells.push_back(indices.size() + 6); cellTypes.push_back(OSP_WEDGE); cellTypes.push_back(OSP_PYRAMID); for (uint32_t i : pa) indices.push_back(ids[i]); cellValues.push_back(0.4f); cellValues.push_back(0.6f); } break; // Build hexahedron case 8: { cells.push_back(indices.size()); cellTypes.push_back(OSP_HEXAHEDRON); indices.insert(indices.end(), ids.begin(), ids.end()); cellValues.push_back(0.2f); } break; } } // Create and configure volume object cpp::Volume volume("unstructured"); volume.setParam("vertex.position", cpp::CopiedData(positions)); if (showCells) volume.setParam("cell.data", cpp::CopiedData(cellValues)); else volume.setParam("vertex.data", cpp::CopiedData(values)); volume.setParam("index", cpp::CopiedData(indices)); volume.setParam("cell.index", cpp::CopiedData(cells)); volume.setParam("cell.type", cpp::CopiedData(cellTypes)); volume.setParam("hexIterative", true); volume.commit(); cpp::Group group; if (isosurface) { cpp::Geometry isoGeom("isosurface"); std::vector isovalues = {-0.2f}; isoGeom.setParam("isovalue", cpp::CopiedData(isovalues)); isoGeom.setParam("volume", volume); isoGeom.commit(); cpp::GeometricModel isoModel(isoGeom); cpp::Material mat("obj"); mat.setParam("kd", vec3f(0.8f)); mat.setParam("ks", vec3f(0.2f)); mat.commit(); isoModel.setParam("material", mat); isoModel.commit(); group.setParam("geometry", cpp::CopiedData(isoModel)); } else { cpp::VolumetricModel model(volume); model.setParam("transferFunction", makeTransferFunction( showCells ? range1f{0.f, 1.f} : range1f{-.4f, -.05f})); model.setParam("densityScale", densityScale); model.commit(); group.setParam("volume", cpp::CopiedData(model)); } group.commit(); return group; } cpp::World UnstructuredVolumeGen::buildWorld() const { if (!transform) return Builder::buildWorld(); auto group = buildGroup(); cpp::Instance instance(group); AffineSpace3f xform(LinearSpace3f::rotate(vec3f(2.2f, 1.0f, -0.35f), 0.4f) * LinearSpace3f::scale(vec3f(1.0f, 1.0f, 4.0f)), vec3f(0.1f, -0.3, 2.f)); instance.setParam("transform", xform); instance.commit(); std::vector inst; inst.push_back(instance); cpp::Light light("distant"); light.setParam("direction", vec3f(-0.8f, -0.6f, 0.3f)); light.setParam("color", vec3f(0.78f, 0.551f, 0.483f)); light.setParam("intensity", 3.14f); light.setParam("angularDiameter", 1.f); light.commit(); cpp::Light ambient("ambient"); ambient.setParam("intensity", 0.35f); ambient.setParam("visible", false); ambient.commit(); std::vector lights{light, ambient}; cpp::World world; world.setParam("instance", cpp::CopiedData(inst)); world.setParam("light", cpp::CopiedData(lights)); return world; } OSP_REGISTER_TESTING_BUILDER(UnstructuredVolumeGen, unstructured_volume); OSP_REGISTER_TESTING_BUILDER( UnstructuredVolumeGen(true), unstructured_volume_transformed); OSP_REGISTER_TESTING_BUILDER( UnstructuredVolumeGen(true, true), unstructured_volume_isosurface); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/UnstructuredVolumeSimple.cpp000066400000000000000000000113671456566705700322520ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "ospray_testing.h" using namespace rkcommon::math; namespace ospray { namespace testing { struct UnstructuredVolumeSimple : public detail::Builder { UnstructuredVolumeSimple() = default; ~UnstructuredVolumeSimple() override = default; void commit() override; cpp::Group buildGroup() const override; private: bool sharedVertices{true}; bool valuesPerCell{false}; }; // Inlined definitions //////////////////////////////////////////////////// void UnstructuredVolumeSimple::commit() { Builder::commit(); sharedVertices = getParam("sharedVertices", true); valuesPerCell = getParam("cellCenteredValues", false); } cpp::Group UnstructuredVolumeSimple::buildGroup() const { // define hexahedron parameters const float hSize = .4f; const float hX = -.5f, hY = -.5f, hZ = 0.f; // define wedge parameters const float wSize = .4f; const float wX = .5f, wY = -.5f, wZ = 0.f; // define tetrahedron parameters const float tSize = .4f; const float tX = .5f, tY = .5f, tZ = 0.f; // define pyramid parameters const float pSize = .4f; const float pX = -.5f, pY = .5f, pZ = 0.f; // define vertex positions std::vector vertices = {// hexahedron {-hSize + hX, -hSize + hY, hSize + hZ}, // bottom quad {hSize + hX, -hSize + hY, hSize + hZ}, {hSize + hX, -hSize + hY, -hSize + hZ}, {-hSize + hX, -hSize + hY, -hSize + hZ}, {-hSize + hX, hSize + hY, hSize + hZ}, // top quad {hSize + hX, hSize + hY, hSize + hZ}, {hSize + hX, hSize + hY, -hSize + hZ}, {-hSize + hX, hSize + hY, -hSize + hZ}, // wedge {-wSize + wX, -wSize + wY, wSize + wZ}, // botom triangle {wSize + wX, -wSize + wY, 0.f + wZ}, {-wSize + wX, -wSize + wY, -wSize + wZ}, {-wSize + wX, wSize + wY, wSize + wZ}, // top triangle {wSize + wX, wSize + wY, 0.f + wZ}, {-wSize + wX, wSize + wY, -wSize + wZ}, // tetrahedron {-tSize + tX, -tSize + tY, tSize + tZ}, {tSize + tX, -tSize + tY, 0.f + tZ}, {-tSize + tX, -tSize + tY, -tSize + tZ}, {-tSize + tX, tSize + tY, 0.f + tZ}, // pyramid {-pSize + pX, -pSize + pY, pSize + pZ}, {pSize + pX, -pSize + pY, pSize + pZ}, {pSize + pX, -pSize + pY, -pSize + pZ}, {-pSize + pX, -pSize + pY, -pSize + pZ}, {pSize + pX, pSize + pY, 0.f + pZ}}; // define per-vertex values std::vector vertexValues = {// hexahedron 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f, 0.f, // wedge 0.f, 0.f, 0.f, 1.f, 0.f, 1.f, // tetrahedron 1.f, 0.f, 1.f, 0.f, // pyramid 0.f, 1.f, 1.f, 0.f, 0.f}; // define vertex indices for both shared and separate case std::vector indicesSharedVert = {// hexahedron 0, 1, 2, 3, 4, 5, 6, 7, // wedge 1, 9, 2, 5, 12, 6, // tetrahedron 5, 12, 6, 17, // pyramid 4, 5, 6, 7, 17}; std::vector indicesSeparateVert = {// hexahedron 0, 1, 2, 3, 4, 5, 6, 7, // wedge 8, 9, 10, 11, 12, 13, // tetrahedron 14, 15, 16, 17, // pyramid 18, 19, 20, 21, 22}; std::vector &indices = sharedVertices ? indicesSharedVert : indicesSeparateVert; // define cell offsets in indices array std::vector cells = {0, 8, 14, 18}; // define cell types std::vector cellTypes = { OSP_HEXAHEDRON, OSP_WEDGE, OSP_TETRAHEDRON, OSP_PYRAMID}; // define per-cell values std::vector cellValues = {0.1f, .3f, .7f, 1.f}; cpp::Volume volume("unstructured"); // set data objects for volume object volume.setParam("vertex.position", cpp::CopiedData(vertices)); if (valuesPerCell) volume.setParam("cell.data", cpp::CopiedData(cellValues)); else volume.setParam("vertex.data", cpp::CopiedData(vertexValues)); volume.setParam("index", cpp::CopiedData(indices)); volume.setParam("cell.index", cpp::CopiedData(cells)); volume.setParam("cell.type", cpp::CopiedData(cellTypes)); volume.commit(); cpp::VolumetricModel model(volume); model.setParam("transferFunction", makeTransferFunction({0.f, 1.f})); model.commit(); cpp::Group group; group.setParam("volume", cpp::CopiedData(model)); group.commit(); return group; } OSP_REGISTER_TESTING_BUILDER(UnstructuredVolumeSimple, unstructured_volume_simple); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/VdbVolume.cpp000066400000000000000000000115061456566705700270770ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "Noise.h" #include "ospray_testing.h" #include "rkcommon/math/AffineSpace.h" #include "rkcommon/tasking/parallel_for.h" using namespace rkcommon::math; namespace ospray { namespace testing { struct VdbVolume : public detail::Builder { VdbVolume(bool packed = false) : packed(packed) {} ~VdbVolume() override = default; void commit() override; cpp::Group buildGroup() const override; cpp::World buildWorld() const override; private: float densityScale{1.f}; float anisotropy{0.f}; bool packed{false}; static constexpr uint32_t domainRes = 128; }; // Inlined definitions //////////////////////////////////////////////////// void VdbVolume::commit() { Builder::commit(); densityScale = getParam("densityScale", 20.f); anisotropy = getParam("anisotropy", 0.f); } cpp::Group VdbVolume::buildGroup() const { cpp::Volume volume("vdb"); std::vector origin; std::vector data; std::vector dataPacked; constexpr uint32_t leafRes = 8; constexpr uint32_t N = domainRes / leafRes; constexpr size_t numLeaves = N * static_cast(N) * N; origin.reserve(numLeaves); if (!packed) data.reserve(numLeaves); std::vector leaf(leafRes * (size_t)leafRes * leafRes, 0.f); for (uint32_t z = 0; z < N; ++z) for (uint32_t y = 0; y < N; ++y) for (uint32_t x = 0; x < N; ++x) { std::vector leafValueRange(leafRes); tasking::parallel_for(leafRes, [&](uint32_t vz) { for (uint32_t vy = 0; vy < leafRes; ++vy) for (uint32_t vx = 0; vx < leafRes; ++vx) { float v = 0.f; const vec3f p((x * leafRes + vx + 0.5f) / (float)domainRes, (y * leafRes + vy + 0.5f) / (float)domainRes, (z * leafRes + vz + 0.5f) / (float)domainRes); if (turbulentTorus(p, 0.75f, 0.375f)) v = 0.5f + 0.5f * PerlinNoise::noise(p, 12); const size_t idx = vx * (size_t)leafRes * leafRes + vy * (size_t)leafRes + vz; leafValueRange[vz].extend(v); leaf.at(idx) = v; } }); // reduction for (auto &vr : leafValueRange) leafValueRange[0].extend(vr); if (leafValueRange[0].lower != 0.f || leafValueRange[0].upper != 0.f) { origin.push_back(vec3i(x * leafRes, y * leafRes, z * leafRes)); if (packed) std::copy(leaf.begin(), leaf.end(), std::back_inserter(dataPacked)); else data.emplace_back(cpp::CopiedData( leaf.data(), vec3ul(leafRes, leafRes, leafRes))); } } if (origin.empty()) throw std::runtime_error("vdb volume is empty."); volume.setParam("filter", OSP_VOLUME_FILTER_LINEAR); volume.setParam("gradientFilter", OSP_VOLUME_FILTER_LINEAR); volume.setParam( "node.level", cpp::CopiedData(std::vector(origin.size(), 3))); volume.setParam("node.origin", cpp::CopiedData(origin)); if (packed) { volume.setParam("nodesPackedDense", cpp::CopiedData(dataPacked)); volume.setParam("node.format", cpp::CopiedData(std::vector( origin.size(), OSP_VOLUME_FORMAT_DENSE_ZYX))); } else volume.setParam("node.data", cpp::CopiedData(data)); volume.commit(); cpp::VolumetricModel model(volume); model.setParam("transferFunction", makeTransferFunction({0.f, 1.f})); model.setParam("densityScale", densityScale); model.setParam("anisotropy", anisotropy); model.commit(); cpp::Group group; group.setParam("volume", cpp::CopiedData(model)); group.commit(); return group; } cpp::World VdbVolume::buildWorld() const { auto group = buildGroup(); cpp::Instance instance(group); rkcommon::math::AffineSpace3f xform( rkcommon::math::LinearSpace3f::scale(8.f / domainRes), vec3f(-4.f, 0, -4.f)); instance.setParam("transform", xform); instance.commit(); std::vector inst; inst.push_back(instance); if (addPlane) inst.push_back(makeGroundPlane(instance.getBounds())); cpp::Light quadLight("quad"); quadLight.setParam("position", vec3f(-4.f, 8.0f, 4.f)); quadLight.setParam("edge1", vec3f(0.f, 0.0f, -8.0f)); quadLight.setParam("edge2", vec3f(2.f, 1.0f, 0.0f)); quadLight.setParam("intensity", 5.0f); quadLight.setParam("color", vec3f(2.8f, 2.2f, 1.9f)); quadLight.commit(); std::vector lightHandles; lightHandles.push_back(quadLight); cpp::World world; world.setParam("instance", cpp::CopiedData(inst)); world.setParam("light", cpp::CopiedData(lightHandles)); return world; } OSP_REGISTER_TESTING_BUILDER(VdbVolume, vdb_volume); OSP_REGISTER_TESTING_BUILDER(VdbVolume(true), vdb_volume_packed); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/test_pt_alloy_roughness.cpp000066400000000000000000000036301456566705700321520ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_pt_material.h" namespace ospray { namespace testing { struct PtAlloyRoughness : public PtMaterial { PtAlloyRoughness() = default; ~PtAlloyRoughness() override = default; std::vector buildMaterials() const override; }; static cpp::Material makeAlloyMaterial( vec3f color, vec3f edgeColor, float roughness) { cpp::Material mat("alloy"); mat.setParam("color", color); mat.setParam("edgeColor", edgeColor); mat.setParam("roughness", roughness); mat.commit(); return mat; } // Inlined definitions //////////////////////////////////////////////////// std::vector PtAlloyRoughness::buildMaterials() const { std::vector materials; constexpr int dimSize = 5; index_sequence_2D numSpheres(dimSize); // Silver for (int i = 0; i < dimSize; ++i) { materials.push_back(makeAlloyMaterial(vec3f(.66f, .66f, .67f), vec3f(1.f, 1.f, 1.f), float(i) / (dimSize - 1))); } // Aluminium for (int i = 0; i < dimSize; ++i) { materials.push_back(makeAlloyMaterial(vec3f(.52f, .52f, .5f), vec3f(1.f, 1.f, 1.f), float(i) / (dimSize - 1))); } // Gold for (int i = 0; i < dimSize; ++i) { materials.push_back(makeAlloyMaterial(vec3f(.83f, .68f, .21f), vec3f(1.f, 1.f, 1.f), float(i) / (dimSize - 1))); } // Chromium for (int i = 0; i < dimSize; ++i) { materials.push_back(makeAlloyMaterial(vec3f(.65f, .66f, .67f), vec3f(1.f, 1.f, 1.f), float(i) / (dimSize - 1))); } // Copper for (int i = 0; i < dimSize; ++i) { materials.push_back(makeAlloyMaterial(vec3f(.72f, .45f, .2f), vec3f(1.f, 1.f, 1.f), float(i) / (dimSize - 1))); } return materials; } OSP_REGISTER_TESTING_BUILDER(PtAlloyRoughness, test_pt_alloy_roughness); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/test_pt_carpaint.cpp000066400000000000000000000040551456566705700305400ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_pt_material.h" namespace ospray { namespace testing { struct PtCarPaint : public PtMaterial { PtCarPaint() = default; ~PtCarPaint() override = default; std::vector buildMaterials() const override; }; static cpp::Material makeCarPaintMaterial( std::initializer_list> params) { cpp::Material mat("carPaint"); mat.setParam("baseColor", vec3f(0.0177f, 0.189f, 0.590f)); mat.setParam("flakeColor", vec3f(0.277f, 0.717f, 0.990f)); mat.setParam("flipflopColor", vec3f(0.252f, 0.0385f, 0.550f)); for (auto ¶m : params) mat.setParam(param.first, param.second); mat.commit(); return mat; } // Inlined definitions //////////////////////////////////////////////////// std::vector PtCarPaint::buildMaterials() const { std::vector materials; constexpr int dimSize = 5; index_sequence_2D numSpheres(dimSize); // flakeDensity for (int i = 0; i < dimSize; i++) materials.push_back(makeCarPaintMaterial( {{"flakeDensity", float(i) / (dimSize - 1)}, {"flakeScale", 1000.f}})); // flipflopFalloff for (int i = 0; i < dimSize; i++) materials.push_back(makeCarPaintMaterial({{"flakeDensity", 1.f}, {"flakeScale", 1000.f}, {"flipflopFalloff", 1.f - float(i) / (dimSize - 1)}})); // flakeScale for (int i = 0; i < dimSize; i++) materials.push_back(makeCarPaintMaterial({{"flakeDensity", 1.f}, {"flakeScale", lerp(float(i) / (dimSize - 1), 1000.f, 100.f)}})); // flakeRoughness for (int i = 0; i < dimSize; i++) materials.push_back(makeCarPaintMaterial({{"flakeDensity", 1.f}, {"flakeScale", 1000.f}, {"flakeRoughness", float(i) / (dimSize - 1)}})); // coat for (int i = 0; i < dimSize; i++) materials.push_back( makeCarPaintMaterial({{"coat", float(i) / (dimSize - 1)}})); return materials; } OSP_REGISTER_TESTING_BUILDER(PtCarPaint, test_pt_carpaint); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/test_pt_glass.cpp000066400000000000000000000022731456566705700300500ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_pt_material.h" namespace ospray { namespace testing { struct PtGlass : public PtMaterial { PtGlass() = default; ~PtGlass() override = default; std::vector buildMaterials() const override; }; static cpp::Material makeGlassMaterial( float eta, vec3f color, float attenuationDistance) { cpp::Material mat("glass"); mat.setParam("eta", eta); mat.setParam("attenuationColor", color); mat.setParam("attenuationDistance", attenuationDistance); mat.commit(); return mat; } // Inlined definitions //////////////////////////////////////////////////// std::vector PtGlass::buildMaterials() const { std::vector materials; constexpr int dimSize = 5; index_sequence_2D numSpheres(dimSize); for (auto i : numSpheres) { auto i_f = static_cast(i); materials.push_back(makeGlassMaterial(lerp(i_f.x / (dimSize - 1), 1.f, 2.f), vec3f(.1f, .5f, 1.f), lerp(1.f - i_f.y / (dimSize - 1), 0.5f, 5.f))); } return materials; } OSP_REGISTER_TESTING_BUILDER(PtGlass, test_pt_glass); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/test_pt_luminous.cpp000066400000000000000000000021051456566705700306040ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_pt_material.h" using namespace rkcommon::math; namespace ospray { namespace testing { struct PtLuminous : public PtMaterial { PtLuminous() = default; ~PtLuminous() override = default; std::vector buildMaterials() const override; }; // Inlined definitions //////////////////////////////////////////////////// std::vector PtLuminous::buildMaterials() const { std::vector materials; constexpr int dimSize = 5; index_sequence_2D numSpheres(dimSize); for (auto i : numSpheres) { auto i_f = static_cast(i); materials.push_back(cpp::Material("luminous")); materials.back().setParam("color", vec3f(0.7f, 0.7f, 1.f)); materials.back().setParam("intensity", i_f.x / (dimSize - 1)); materials.back().setParam("transparency", 1.f - i_f.y / (dimSize - 1)); materials.back().commit(); } return materials; } OSP_REGISTER_TESTING_BUILDER(PtLuminous, test_pt_luminous); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/test_pt_material.h000066400000000000000000000054711456566705700302050ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "ospray_testing.h" #include "rkcommon/utility/multidim_index_sequence.h" using namespace rkcommon::math; namespace ospray { namespace testing { struct PtMaterial : public detail::Builder { PtMaterial() = default; ~PtMaterial() override = default; cpp::Group buildGroup() const override; cpp::World buildWorld() const override; virtual std::vector buildMaterials() const = 0; }; // Inlined definitions //////////////////////////////////////////////////// inline cpp::Group PtMaterial::buildGroup() const { cpp::Geometry sphereGeometry("sphere"); std::vector materials = buildMaterials(); const int dimCount = sqrtf(materials.size()); const int dimSize = dimCount - 1; index_sequence_2D numSpheres(dimCount); std::vector spheres; std::vector index; for (auto i : numSpheres) { auto i_f = static_cast(i); spheres.emplace_back(dimSize / 2.f - i_f.x, dimSize / 2.f - i_f.y, .6f); index.push_back(numSpheres.flatten(i)); } sphereGeometry.setParam("sphere.position", cpp::CopiedData(spheres)); sphereGeometry.setParam("radius", 0.4f); sphereGeometry.commit(); cpp::GeometricModel model(sphereGeometry); model.setParam("material", cpp::CopiedData(materials)); model.setParam("index", cpp::CopiedData(index)); model.commit(); cpp::Group group; group.setParam("geometry", cpp::CopiedData(model)); group.commit(); return group; } inline cpp::World PtMaterial::buildWorld() const { cpp::World world; cpp::Group group = buildGroup(); cpp::Instance groupInstance(group); groupInstance.commit(); box3f bbox = group.getBounds(); bbox.lower -= .4f; bbox.upper += .4f; cpp::Instance planeInstance = makeGroundPlane( bbox, vec4f(.9f, .9f, .9f, 1.f), vec4f(.2f, .2f, .2f, 1.f)); planeInstance.setParam( "xfm", affine3f::rotate(vec3f(-1.f, 0.f, 0.f), half_pi)); planeInstance.commit(); std::vector instances; instances.push_back(groupInstance); instances.push_back(planeInstance); world.setParam("instance", cpp::CopiedData(instances)); // Lights { std::vector lightHandles; cpp::Light sphereLight("sphere"); sphereLight.setParam("intensity", 500.f); sphereLight.setParam("position", vec3f(-15.f, 15.f, -20.f)); sphereLight.setParam("radius", 5.f); sphereLight.commit(); cpp::Light ambientLight("ambient"); ambientLight.setParam("intensity", 0.4f); ambientLight.setParam("color", vec3f(1.f)); ambientLight.commit(); lightHandles.push_back(sphereLight); lightHandles.push_back(ambientLight); world.setParam("light", cpp::CopiedData(lightHandles)); } return world; } } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/test_pt_material_tex.cpp000066400000000000000000000106261456566705700314160ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_pt_tex.h" namespace ospray { namespace testing { struct PtMaterialTex : public PtTex { PtMaterialTex() = default; ~PtMaterialTex() override = default; std::vector buildMaterials( const cpp::Texture &texR, const cpp::Texture &texRGBA) const override; }; // Inlined definitions //////////////////////////////////////////////////// std::vector PtMaterialTex::buildMaterials( const cpp::Texture &texR, const cpp::Texture &texRGBA) const { std::vector materials; // carPaint { // roughness materials.push_back(cpp::Material("carPaint")); materials.back().setParam("baseColor", vec3f(0.0177f, 0.189f, 0.590f)); setTexture(materials.back(), "roughness", texR); // flakeColor materials.push_back(cpp::Material("carPaint")); materials.back().setParam("baseColor", vec3f(0.0177f, 0.189f, 0.590f)); materials.back().setParam("flakeScale", 2000.f); materials.back().setParam("flakeDensity", 1.f); setTexture(materials.back(), "flakeColor", texRGBA); // flakeDensity materials.push_back(cpp::Material("carPaint")); materials.back().setParam("baseColor", vec3f(0.0177f, 0.189f, 0.590f)); materials.back().setParam("flakeColor", vec3f(0.277f, 0.717f, 0.990f)); materials.back().setParam("flakeScale", 2000.f); setTexture(materials.back(), "flakeDensity", texR); // flakeRoughness materials.push_back(cpp::Material("carPaint")); materials.back().setParam("baseColor", vec3f(0.0177f, 0.189f, 0.590f)); materials.back().setParam("flakeDensity", 1.f); materials.back().setParam("flakeColor", vec3f(0.277f, 0.717f, 0.990f)); materials.back().setParam("flakeScale", 2000.f); setTexture(materials.back(), "flakeRoughness", texR); // flipflopFalloff materials.push_back(cpp::Material("carPaint")); materials.back().setParam("baseColor", vec3f(0.0177f, 0.189f, 0.590f)); materials.back().setParam("flakeDensity", 1.f); materials.back().setParam("flakeColor", vec3f(0.277f, 0.717f, 0.990f)); materials.back().setParam("flakeScale", 1000.f); materials.back().setParam("flipflopColor", vec3f(0.252f, 0.0385f, 0.550f)); setTexture(materials.back(), "flipflopFalloff", texR); // coat materials.push_back(cpp::Material("carPaint")); materials.back().setParam("baseColor", vec3f(0.0177f, 0.189f, 0.590f)); setTexture(materials.back(), "coat", texR); // coatColor materials.push_back(cpp::Material("carPaint")); materials.back().setParam("baseColor", vec3f(0.0177f, 0.189f, 0.590f)); setTexture(materials.back(), "coatColor", texRGBA); // coatRoughness materials.push_back(cpp::Material("carPaint")); materials.back().setParam("baseColor", vec3f(0.0177f, 0.189f, 0.590f)); setTexture(materials.back(), "coatRoughness", texR); } // obj { // d materials.push_back(cpp::Material("obj")); setTexture(materials.back(), "d", texR); // Kd materials.push_back(cpp::Material("obj")); setTexture(materials.back(), "kd", texRGBA); // Ks materials.push_back(cpp::Material("obj")); setTexture(materials.back(), "ks", texRGBA); // Ns materials.push_back(cpp::Material("obj")); materials.back().setParam("ks", vec3f(1.f)); setTexture(materials.back(), "ns", texR); } // other { // metal roughness materials.push_back(cpp::Material("metal")); materials.back().setParam("eta", vec3f(0.051, 0.043, 0.041)); materials.back().setParam("k", vec3f(5.3f, 3.6f, 2.3f)); setTexture(materials.back(), "roughness", texR); // luminous emissive materials.push_back(cpp::Material("luminous")); setTexture(materials.back(), "color", texRGBA, vec3f(1.f, 0.8f, 0.7f)); // alloy roughness materials.push_back(cpp::Material("alloy")); materials.back().setParam("color", vec3f(.72f, .45f, .2f)); materials.back().setParam("edgeColor", vec3f(1.f, 1.f, 1.f)); setTexture(materials.back(), "roughness", texR); // thinglass attenuationColor materials.push_back(cpp::Material("thinGlass")); setTexture(materials.back(), "attenuationColor", texRGBA); } return materials; } OSP_REGISTER_TESTING_BUILDER(PtMaterialTex, test_pt_material_tex); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/test_pt_metal_roughness.cpp000066400000000000000000000036171456566705700321410ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_pt_material.h" namespace ospray { namespace testing { struct PtMetalRoughness : public PtMaterial { PtMetalRoughness() = default; ~PtMetalRoughness() override = default; std::vector buildMaterials() const override; }; static cpp::Material makeMetalMaterial(vec3f eta, vec3f k, float roughness) { cpp::Material mat("metal"); mat.setParam("eta", eta); mat.setParam("k", k); mat.setParam("roughness", roughness); mat.commit(); return mat; } // Inlined definitions //////////////////////////////////////////////////// std::vector PtMetalRoughness::buildMaterials() const { std::vector materials; constexpr int dimSize = 5; index_sequence_2D numSpheres(dimSize); // Silver for (int i = 0; i < dimSize; ++i) { materials.push_back(makeMetalMaterial(vec3f(0.051f, 0.043f, 0.041f), vec3f(5.3f, 3.6f, 2.3f), float(i) / (dimSize - 1))); } // Aluminium for (int i = 0; i < dimSize; ++i) { materials.push_back(makeMetalMaterial(vec3f(1.5f, 0.98f, 0.6f), vec3f(7.6f, 6.6f, 5.4f), float(i) / (dimSize - 1))); } // Gold for (int i = 0; i < dimSize; ++i) { materials.push_back(makeMetalMaterial(vec3f(0.07f, 0.37f, 1.5f), vec3f(3.7f, 2.3f, 1.7f), float(i) / (dimSize - 1))); } // Chromium for (int i = 0; i < dimSize; ++i) { materials.push_back(makeMetalMaterial(vec3f(3.2f, 3.1f, 2.3f), vec3f(3.3f, 3.3f, 3.1f), float(i) / (dimSize - 1))); } // Copper for (int i = 0; i < dimSize; ++i) { materials.push_back(makeMetalMaterial(vec3f(0.1f, 0.8f, 1.1f), vec3f(3.5f, 2.5f, 2.4f), float(i) / (dimSize - 1))); } return materials; } OSP_REGISTER_TESTING_BUILDER(PtMetalRoughness, test_pt_metal_roughness); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/test_pt_metallic_flakes.cpp000066400000000000000000000023571456566705700320610ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_pt_material.h" namespace ospray { namespace testing { struct PtMetallicFlakes : public PtMaterial { PtMetallicFlakes() = default; ~PtMetallicFlakes() override = default; std::vector buildMaterials() const override; }; static cpp::Material makeMetallicFlakesMaterial( float flakeAmount, float flakeSpread) { cpp::Material mat("metallicPaint"); mat.setParam("baseColor", vec3f(1.f, 0.f, 0.f)); mat.setParam("flakeAmount", flakeAmount); mat.setParam("flakeSpread", flakeSpread); mat.commit(); return mat; } // Inlined definitions //////////////////////////////////////////////////// std::vector PtMetallicFlakes::buildMaterials() const { std::vector materials; constexpr int dimSize = 5; index_sequence_2D numSpheres(dimSize); for (auto i : numSpheres) { auto i_f = static_cast(i); materials.push_back( makeMetallicFlakesMaterial(lerp(i_f.x / (dimSize - 1), 1.f, 0.f), lerp(i_f.y / (dimSize - 1), 0.f, 1.f))); } return materials; } OSP_REGISTER_TESTING_BUILDER(PtMetallicFlakes, test_pt_metallic_flakes); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/test_pt_mix_tex.cpp000066400000000000000000000046261456566705700304200ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_pt_tex.h" namespace ospray { namespace testing { struct PtMixTex : public PtTex { PtMixTex() = default; ~PtMixTex() override = default; std::vector buildMaterials( const cpp::Texture &texR, const cpp::Texture &texRGBA) const override; }; // Inlined definitions //////////////////////////////////////////////////// std::vector PtMixTex::buildMaterials( const cpp::Texture &texR, const cpp::Texture &) const { std::vector materials; // obj & thinGlass { cpp::Material obj("obj"); obj.commit(); cpp::Material thinGlass("thinGlass"); thinGlass.commit(); cpp::Material mix("mix"); mix.setParam("material1", obj); mix.setParam("material2", thinGlass); materials.push_back(mix); setTexture(materials.back(), "factor", texR); } // plastic & metal { cpp::Material plastic("plastic"); plastic.setParam("pigmentColor", vec3f(.8f, 0.f, 0.f)); plastic.commit(); cpp::Material metal("metal"); metal.commit(); cpp::Material mix("mix"); mix.setParam("material1", plastic); mix.setParam("material2", metal); materials.push_back(mix); setTexture(materials.back(), "factor", texR); } // velvet & metallicPaint { cpp::Material velvet("velvet"); cpp::Material metallicPaint("metallicPaint"); cpp::Material mix("mix"); velvet.commit(); metallicPaint.commit(); mix.setParam("material1", velvet); mix.setParam("material2", metallicPaint); materials.push_back(mix); setTexture(materials.back(), "factor", texR); } // carPaint & principled { cpp::Material carPaint("carPaint"); carPaint.setParam("baseColor", vec3f(.5f)); carPaint.setParam("flakeColor", vec3f(.8f)); carPaint.setParam("flakeDensity", 1.f); carPaint.setParam("flakeScale", 1000.f); carPaint.commit(); cpp::Material principled("principled"); principled.setParam("baseColor", vec3f(0.0177f, 0.189f, 0.590f)); principled.commit(); cpp::Material mix("mix"); mix.setParam("material1", carPaint); mix.setParam("material2", principled); materials.push_back(mix); setTexture(materials.back(), "factor", texR); } return materials; } OSP_REGISTER_TESTING_BUILDER(PtMixTex, test_pt_mix_tex); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/test_pt_obj.cpp000066400000000000000000000037151456566705700275130ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_pt_material.h" namespace ospray { namespace testing { struct PtObj : public PtMaterial { PtObj() = default; ~PtObj() override = default; std::vector buildMaterials() const override; }; static cpp::Material makeObjMaterial( float d, vec3f Kd, vec3f Ks, float Ns, vec3f Tf) { cpp::Material mat("obj"); mat.setParam("d", d); mat.setParam("kd", Kd); mat.setParam("ks", Ks); mat.setParam("ns", Ns); mat.setParam("tf", Tf); mat.commit(); return mat; } // Inlined definitions //////////////////////////////////////////////////// std::vector PtObj::buildMaterials() const { std::vector materials; constexpr int dimSize = 5; index_sequence_2D numSpheres(dimSize); // d for (int i = 0; i < dimSize; i++) materials.push_back(makeObjMaterial(1.f - float(i) / (dimSize - 1), vec3f(.8f, 0.f, 0.f), vec3f(0.f), 10.f, vec3f(0.f))); // Kd for (int i = 0; i < dimSize; i++) materials.push_back(makeObjMaterial(1.f, vec3f(1.f - float(i) / (dimSize - 1), 0.f, 0.f), vec3f(0.f), 10.f, vec3f(0.f))); // Ks for (int i = 0; i < dimSize; i++) materials.push_back(makeObjMaterial(1.f, vec3f(.8f, 0.f, 0.f), vec3f(float(i) / (dimSize - 1)), 1000.f, vec3f(0.f))); // Ns for (int i = 0; i < dimSize; i++) materials.push_back(makeObjMaterial(1.f, vec3f(.8f, 0.f, 0.f), vec3f(1.f), lerp(float(i) / (dimSize - 1), 10.f, 1000.f), vec3f(0.f))); // Tf for (int i = 0; i < dimSize; i++) materials.push_back(makeObjMaterial(1.f, vec3f(.2f, 0.f, 0.f), vec3f(.2f, 0.f, 0.f), 1000.f, (float(i) / (dimSize - 1)) * vec3f(1.f, .5f, .5f))); return materials; } OSP_REGISTER_TESTING_BUILDER(PtObj, test_pt_obj); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/test_pt_plastic.cpp000066400000000000000000000022241456566705700303720ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_pt_material.h" namespace ospray { namespace testing { struct PtPlastic : public PtMaterial { PtPlastic() = default; ~PtPlastic() override = default; std::vector buildMaterials() const override; }; static cpp::Material makePlasticMaterial( vec3f color, float eta, float roughness) { cpp::Material mat("plastic"); mat.setParam("pigmentColor", color); mat.setParam("eta", eta); mat.setParam("roughness", roughness); mat.commit(); return mat; } // Inlined definitions //////////////////////////////////////////////////// std::vector PtPlastic::buildMaterials() const { std::vector materials; constexpr int dimSize = 5; index_sequence_2D numSpheres(dimSize); for (auto i : numSpheres) { auto i_f = static_cast(i); materials.push_back(makePlasticMaterial(vec3f(.8f, 0.f, 0.f), lerp(i_f.y / (dimSize - 1), 1.f, 2.f), i_f.x / (dimSize - 1))); } return materials; } OSP_REGISTER_TESTING_BUILDER(PtPlastic, test_pt_plastic); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/test_pt_principled.cpp000066400000000000000000000165441456566705700310760ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_pt_material.h" namespace ospray { namespace testing { struct PtPrincipledMetal : public PtMaterial { PtPrincipledMetal() = default; ~PtPrincipledMetal() override = default; std::vector buildMaterials() const override; }; struct PtPrincipledPlastic : public PtMaterial { PtPrincipledPlastic() = default; ~PtPrincipledPlastic() override = default; std::vector buildMaterials() const override; }; struct PtPrincipledGlass : public PtMaterial { PtPrincipledGlass() = default; ~PtPrincipledGlass() override = default; std::vector buildMaterials() const override; }; static cpp::Material makePrincipledMetalMaterial(vec3f baseColor, float metallic, float roughness, float anisotropy, float coat, float coatRoughness) { cpp::Material mat("principled"); mat.setParam("baseColor", baseColor); mat.setParam("metallic", metallic); mat.setParam("roughness", roughness); mat.setParam("anisotropy", anisotropy); mat.setParam("coat", coat); mat.setParam("coatRoughness", coatRoughness); mat.commit(); return mat; } static cpp::Material makePrincipledPlasticMaterial(vec3f baseColor, float ior, float specular, float sheen, float sheenTint, float sheenRoughness, float opacity) { cpp::Material mat("principled"); mat.setParam("baseColor", baseColor); mat.setParam("ior", ior); mat.setParam("specular", specular); mat.setParam("sheen", sheen); mat.setParam("sheenTint", sheenTint); mat.setParam("sheenRoughness", sheenRoughness); mat.setParam("opacity", opacity); mat.commit(); return mat; } static cpp::Material makePrincipledGlassMaterial(vec3f baseColor, float transmission, float roughness, float ior, float transmissionDepth, bool thin, float thickness, float backlight) { cpp::Material mat("principled"); mat.setParam("baseColor", baseColor); mat.setParam("transmissionColor", baseColor); mat.setParam("transmission", transmission); mat.setParam("roughness", roughness); mat.setParam("ior", ior); mat.setParam("transmissionDepth", transmissionDepth); mat.setParam("thin", thin); mat.setParam("thickness", thickness); mat.setParam("backlight", backlight); mat.commit(); return mat; } // Inlined definitions //////////////////////////////////////////////////// std::vector PtPrincipledMetal::buildMaterials() const { std::vector materials; constexpr int dimSize = 5; index_sequence_2D numSpheres(dimSize); // metallic for (int i = 0; i < dimSize; i++) { materials.push_back( makePrincipledMetalMaterial(vec3f(0.0261f, 0.195f, 0.870f), float(i) / (dimSize - 1), 0.f, 0.f, 0.f, 0.f)); } // roughness for (int i = 0; i < dimSize; i++) { materials.push_back( makePrincipledMetalMaterial(vec3f(0.0261f, 0.195f, 0.870f), 1.f, float(i) / (dimSize - 1), 0.f, 0.f, 0.f)); } // anisotropy for (int i = 0; i < dimSize; i++) { materials.push_back( makePrincipledMetalMaterial(vec3f(0.0261f, 0.195f, 0.870f), 1.f, .5f, float(i) / (dimSize - 1), 0.f, 0.f)); } // coat for (int i = 0; i < dimSize; i++) { materials.push_back( makePrincipledMetalMaterial(vec3f(0.860f, 0.0258f, 0.0536f), 1.f, .5f, 0.f, float(i) / (dimSize - 1), 0.f)); } // coatRoughness for (int i = 0; i < dimSize; i++) { materials.push_back( makePrincipledMetalMaterial(vec3f(0.860f, 0.0258f, 0.0536f), 1.f, .5f, 0.f, 1.f, float(i) / (dimSize - 1))); } return materials; } std::vector PtPrincipledPlastic::buildMaterials() const { std::vector materials; constexpr int dimSize = 5; index_sequence_2D numSpheres(dimSize); // specular for (int i = 0; i < dimSize; i++) { materials.push_back(makePrincipledPlasticMaterial(vec3f(0.770, 0.00, 0.00), 1.45f, float(i) / (dimSize - 1), 0.f, 0.f, 0.f, 1.f)); } // sheen for (int i = 0; i < dimSize; i++) { materials.push_back( makePrincipledPlasticMaterial(vec3f(0.950f, 0.494f, 0.0380f), 1.f, 0.f, float(i) / (dimSize - 1), 0.f, .5f, 1.f)); } // sheenTint for (int i = 0; i < dimSize; i++) { materials.push_back( makePrincipledPlasticMaterial(vec3f(0.950f, 0.494f, 0.0380f), 1.f, 0.f, 1.f, float(i) / (dimSize - 1), .5f, 1.f)); } // sheenRoughness for (int i = 0; i < dimSize; i++) { materials.push_back( makePrincipledPlasticMaterial(vec3f(0.950f, 0.494f, 0.0380f), 1.f, 0.f, 1.f, 0.f, float(i) / (dimSize - 1), 1.f)); } // opacity for (int i = 0; i < dimSize; i++) { materials.push_back( makePrincipledPlasticMaterial(vec3f(0.930f, 0.884f, 0.0186f), 1.45f, 1.f, 0.f, 0.f, 0.f, 1.f - float(i) / (dimSize - 1))); } return materials; } std::vector PtPrincipledGlass::buildMaterials() const { std::vector materials; constexpr int dimSize = 5; index_sequence_2D numSpheres(dimSize); // transmission for (int i = 0; i < dimSize; i++) { materials.push_back( makePrincipledGlassMaterial(vec3f(0.0400f, 0.680f, 1.00f), float(i) / (dimSize - 1), 0.f, 1.1f, 1.f, false, 1.f, 0.f)); } // roughness for (int i = 0; i < dimSize; i++) { materials.push_back( makePrincipledGlassMaterial(vec3f(0.0400f, 0.680f, 1.00f), 1.f, float(i) / (dimSize - 1), 1.5f, 1.f, false, 1.f, 0.f)); } // ior for (int i = 0; i < dimSize; i++) { materials.push_back( makePrincipledGlassMaterial(vec3f(0.0400f, 0.680f, 1.00f), 1.f, 0.f, lerp(float(i) / (dimSize - 1), 1.f, 2.f), 1.f, false, 1.f, 0.f)); } // transmissionDepth for (int i = 0; i < dimSize; i++) { materials.push_back( makePrincipledGlassMaterial(vec3f(0.0400f, 0.680f, 1.00f), 1.f, 0.f, 1.5f, lerp(float(i) / (dimSize - 1), 2.f, 0.f), false, 1.f, 0.f)); } // backlight for (int i = 0; i < dimSize; i++) { materials.push_back( makePrincipledGlassMaterial(vec3f(0.0400f, 0.200f, 1.00f), .3f, 0.f, 1.5f, 1.f, true, 1.f, lerp(float(i) / (dimSize - 1), 0.f, 2.f))); } return materials; } OSP_REGISTER_TESTING_BUILDER(PtPrincipledMetal, test_pt_principled_metal); OSP_REGISTER_TESTING_BUILDER(PtPrincipledPlastic, test_pt_principled_plastic); OSP_REGISTER_TESTING_BUILDER(PtPrincipledGlass, test_pt_principled_glass); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/test_pt_principled_tex.cpp000066400000000000000000000132751456566705700317540ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_pt_tex.h" namespace ospray { namespace testing { struct PtPrincipledTex : public PtTex { PtPrincipledTex() = default; ~PtPrincipledTex() override = default; std::vector buildMaterials( const cpp::Texture &texR, const cpp::Texture &texRGBA) const override; }; // Inlined definitions //////////////////////////////////////////////////// std::vector PtPrincipledTex::buildMaterials( const cpp::Texture &texR, const cpp::Texture &texRGBA) const { std::vector materials; // principled metal { // metallic materials.push_back(cpp::Material("principled")); materials.back().setParam("baseColor", vec3f(0.0261f, 0.195f, 0.870f)); setTexture(materials.back(), "metallic", texR); // roughness materials.push_back(cpp::Material("principled")); materials.back().setParam("baseColor", vec3f(0.0261f, 0.195f, 0.870f)); materials.back().setParam("metallic", 1.f); setTexture(materials.back(), "roughness", texR); // anisotropy materials.push_back(cpp::Material("principled")); materials.back().setParam("baseColor", vec3f(0.0261f, 0.195f, 0.870f)); materials.back().setParam("metallic", 1.f); materials.back().setParam("roughness", .5f); setTexture(materials.back(), "anisotropy", texR); // coat materials.push_back(cpp::Material("principled")); materials.back().setParam("baseColor", vec3f(0.860f, 0.0258f, 0.0536f)); materials.back().setParam("metallic", 1.f); materials.back().setParam("roughness", .5f); setTexture(materials.back(), "coat", texR); // coatRoughness materials.push_back(cpp::Material("principled")); materials.back().setParam("baseColor", vec3f(0.860f, 0.0258f, 0.0536f)); materials.back().setParam("metallic", 1.f); materials.back().setParam("roughness", .5f); materials.back().setParam("coat", 1.f); setTexture(materials.back(), "coatRoughness", texR); } // principled plastic { // roughness materials.push_back(cpp::Material("principled")); materials.back().setParam("baseColor", vec3f(0.770f, 0.00f, 0.00f)); setTexture(materials.back(), "roughness", texR); // specular materials.push_back(cpp::Material("principled")); materials.back().setParam("baseColor", vec3f(0.770f, 0.00f, 0.00f)); materials.back().setParam("ior", 1.45f); setTexture(materials.back(), "specular", texR); // sheen materials.push_back(cpp::Material("principled")); materials.back().setParam("baseColor", vec3f(0.950f, 0.494f, 0.0380f)); materials.back().setParam("sheenRoughness", .5f); setTexture(materials.back(), "sheen", texR); // sheenTint materials.push_back(cpp::Material("principled")); materials.back().setParam("baseColor", vec3f(0.950f, 0.494f, 0.0380f)); materials.back().setParam("sheen", 1.f); materials.back().setParam("sheenRoughness", .5f); setTexture(materials.back(), "sheenTint", texR); // sheenRoughness materials.push_back(cpp::Material("principled")); materials.back().setParam("baseColor", vec3f(0.950f, 0.494f, 0.0380f)); materials.back().setParam("sheen", 1.f); setTexture(materials.back(), "sheenRoughness", texR); } // principled glass { // transmission materials.push_back(cpp::Material("principled")); materials.back().setParam("baseColor", vec3f(0.0400f, 0.680f, 1.00f)); materials.back().setParam( "transmissionColor", vec3f(0.0400f, 0.680f, 1.00f)); materials.back().setParam("ior", 1.1f); setTexture(materials.back(), "transmission", texR); // roughness materials.push_back(cpp::Material("principled")); materials.back().setParam("baseColor", vec3f(0.0400f, 0.680f, 1.00f)); materials.back().setParam( "transmissionColor", vec3f(0.0400f, 0.680f, 1.00f)); materials.back().setParam("transmission", 1.f); materials.back().setParam("ior", 1.5f); setTexture(materials.back(), "roughness", texR); // thickness materials.push_back(cpp::Material("principled")); materials.back().setParam("baseColor", vec3f(0.0400f, 0.680f, 1.00f)); materials.back().setParam( "transmissionColor", vec3f(0.0400f, 0.680f, 1.00f)); materials.back().setParam("transmission", 1.f); materials.back().setParam("ior", 1.5f); materials.back().setParam("thin", true); setTexture(materials.back(), "thickness", texR); // thin roughness materials.push_back(cpp::Material("principled")); materials.back().setParam("baseColor", vec3f(0.0400f, 0.680f, 1.00f)); materials.back().setParam( "transmissionColor", vec3f(0.0400f, 0.680f, 1.00f)); materials.back().setParam("transmission", 1.f); materials.back().setParam("ior", 1.5f); materials.back().setParam("thin", true); setTexture(materials.back(), "roughness", texR); // thin backlight materials.push_back(cpp::Material("principled")); materials.back().setParam("baseColor", vec3f(0.0400f, 0.680f, 1.00f)); materials.back().setParam( "transmissionColor", vec3f(0.0400f, 0.680f, 1.00f)); materials.back().setParam("transmission", .3f); materials.back().setParam("ior", 1.5f); materials.back().setParam("thin", true); setTexture(materials.back(), "backlight", texR, 2.f); } materials.push_back(cpp::Material("principled")); materials.back().setParam("baseColor", vec3f(1.f, 0.8f, 0.7f)); setTexture(materials.back(), "emissiveColor", texRGBA); return materials; } OSP_REGISTER_TESTING_BUILDER(PtPrincipledTex, test_pt_principled_tex); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/test_pt_tex.h000066400000000000000000000200541456566705700272010ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Builder.h" #include "ospray_testing.h" #include "rkcommon/utility/multidim_index_sequence.h" using namespace rkcommon::math; namespace ospray { namespace testing { struct PtTex : public detail::Builder { PtTex() = default; ~PtTex() override = default; cpp::Group buildGroup() const override; cpp::World buildWorld() const override; virtual std::vector buildMaterials( const cpp::Texture &texR, const cpp::Texture &texRGBA) const = 0; }; // Inlined definitions //////////////////////////////////////////////////// static cpp::Texture makeCheckerboardTextureR8() { // Prepare pixel data constexpr uint32_t width = 16; constexpr uint32_t height = 16; std::array dbyte; index_sequence_2D idx(vec2i(width, height)); for (auto i : idx) dbyte[idx.flatten(i)] = ((i.x & 2) ^ (i.y & 2)) * 255; // Create texture object cpp::Texture tex("texture2d"); tex.setParam("format", OSP_TEXTURE_R8); tex.setParam("filter", OSP_TEXTURE_FILTER_NEAREST); tex.setParam("data", cpp::CopiedData(dbyte.data(), vec2ul(width, height))); tex.commit(); // Ready return tex; } static cpp::Texture makeCheckerboardTextureRGBA8() { // Prepare pixel data constexpr uint32_t width = 16; constexpr uint32_t height = 16; std::array dbyte; index_sequence_2D idx(vec2i(width, height)); for (auto i : idx) { uint8_t v = ((i.x & 2) ^ (i.y & 2)) * 255; dbyte[idx.flatten(i)] = vec4uc(v, v, v, 255); } // Create texture object cpp::Texture tex("texture2d"); tex.setParam("format", OSP_TEXTURE_RGBA8); tex.setParam("filter", OSP_TEXTURE_FILTER_NEAREST); tex.setParam("data", cpp::CopiedData(dbyte.data(), vec2ul(width, height))); tex.commit(); // Ready return tex; } static std::vector makeSphereVertices( uint32_t latitudeCount, uint32_t longitudeCount, float radius) { // Calculate latitude and longitude angular steps (in radians) std::vector vPos; const float latAngleStep = float(pi) / float(latitudeCount); const float longAngleStep = (2.0f * float(pi)) / float(longitudeCount); // Iterate through latitude segments for (uint32_t latitudeId = 0; latitudeId <= latitudeCount; latitudeId++) { // Calculate longitude radius at current latitude float longRadius = radius * sin(latAngleStep * latitudeId); // Determine segment level float y = radius * cos(latAngleStep * latitudeId); // Iterate through longitude segments for (uint32_t longitudeId = 0; longitudeId <= longitudeCount; longitudeId++) { // Calculate vertex position float x = longRadius * cos(longAngleStep * longitudeId); float z = longRadius * sin(longAngleStep * longitudeId); vPos.push_back(vec3f(x, y, z)); } } // Ready return vPos; } static std::vector makeSphereTexCoords(uint32_t latitudeCount, uint32_t longitudeCount, float tileLat, float tileLong) { // Iterate through latitude segments std::vector vTexCoord; for (uint32_t latitudeId = 0; latitudeId <= latitudeCount; latitudeId++) { // Iterate through longitude segments for (uint32_t longitudeId = 0; longitudeId <= longitudeCount; longitudeId++) { // Calculate texture coordinates vTexCoord.push_back(vec2f(tileLong * longitudeId / float(longitudeCount), tileLat * (latitudeId - 1) / float(latitudeCount))); } } // Ready return vTexCoord; } static std::vector makeSphereIndices( uint32_t latitudeCount, uint32_t longitudeCount, bool outside) { // Iterate through latitude segments std::vector indices; for (uint32_t latitudeId = 0; latitudeId < latitudeCount; latitudeId++) { // Calculate indices of segment left-most vertices uint32_t firstVertex1 = latitudeId * (longitudeCount + 1); uint32_t firstVertex2 = (latitudeId + 1) * (longitudeCount + 1); // Iterate through longitude segments for (uint32_t longitudeId = 0; longitudeId < longitudeCount; longitudeId++) { // Setup first triangle indices uint32_t i2 = firstVertex2 + longitudeId + 1; uint32_t i3 = firstVertex2 + longitudeId; indices.push_back(vec3ui(firstVertex1 + longitudeId, (outside) ? i2 : i3, (outside) ? i3 : i2)); // Setup second triangle indices i2 = firstVertex1 + longitudeId + 1; i3 = firstVertex2 + longitudeId + 1; indices.push_back(vec3ui(firstVertex1 + longitudeId, (outside) ? i2 : i3, (outside) ? i3 : i2)); } } // Ready return indices; } static cpp::Geometry makeSphereMesh( uint32_t latitudeCount, uint32_t longitudeCount) { cpp::Geometry sphereMesh("mesh"); // Prepare mesh buffers std::vector vertices = makeSphereVertices(latitudeCount, longitudeCount, 1.f); std::vector texCoords = makeSphereTexCoords(latitudeCount, longitudeCount, 1.f, 2.f); std::vector indices = makeSphereIndices(latitudeCount, longitudeCount, false); // Set mesh parameters sphereMesh.setParam("vertex.position", cpp::CopiedData(vertices)); sphereMesh.setParam("vertex.normal", cpp::CopiedData(vertices)); sphereMesh.setParam("vertex.texcoord", cpp::CopiedData(texCoords)); sphereMesh.setParam("index", cpp::CopiedData(indices)); sphereMesh.commit(); // Ready return sphereMesh; } template void setTexture(cpp::Material &mat, const std::string &name, const cpp::Texture &tex, const T mul = T(1.f)) { mat.setParam(name, mul); mat.setParam("map_" + name, tex); mat.commit(); } inline cpp::Group PtTex::buildGroup() const { // Do nothing, needs per-instance materials feature to have single group return cpp::Group(); } inline cpp::World PtTex::buildWorld() const { cpp::World world; std::vector instances; cpp::Texture texR = makeCheckerboardTextureR8(); cpp::Texture texRGBA = makeCheckerboardTextureRGBA8(); std::vector materials = buildMaterials(texR, texRGBA); const int dimCount = sqrtf(materials.size()); const int dimSize = dimCount - 1; cpp::Geometry sphereGeometry = makeSphereMesh(25, 50); // Note: this is a temporary implementation, per-instance materials feature // should be used here box3f bbox(empty); index_sequence_2D numSpheres(dimCount); for (auto i : numSpheres) { // Construct GeometricModel for each instance cpp::GeometricModel model(sphereGeometry); model.setParam( "material", cpp::CopiedData(materials[numSpheres.flatten(i)])); model.commit(); // Construct Group for each instance cpp::Group group; group.setParam("geometry", cpp::CopiedData(model)); group.commit(); // Construct instance cpp::Instance instance(group); auto i_f = static_cast(i); instance.setParam("xfm", affine3f::translate( vec3f(dimSize / 2.f - i_f.x, dimSize / 2.f - i_f.y, .6f)) * affine3f::scale(.4f)); instance.commit(); instances.push_back(instance); bbox.extend(instance.getBounds()); } bbox.lower -= .4f; bbox.upper += .4f; cpp::Instance planeInstance = makeGroundPlane( bbox, vec4f(.9f, .9f, .9f, 1.f), vec4f(.2f, .2f, .2f, 1.f)); planeInstance.setParam( "xfm", affine3f::rotate(vec3f(-1.f, 0.f, 0.f), half_pi)); planeInstance.commit(); instances.push_back(planeInstance); world.setParam("instance", cpp::CopiedData(instances)); // Lights { std::vector lightHandles; cpp::Light sphereLight("sphere"); sphereLight.setParam("intensity", 500.f); sphereLight.setParam("position", vec3f(-15.f, 15.f, -20.f)); sphereLight.setParam("radius", 5.f); sphereLight.commit(); cpp::Light ambientLight("ambient"); ambientLight.setParam("intensity", 0.4f); ambientLight.setParam("color", vec3f(1.f)); ambientLight.commit(); lightHandles.push_back(sphereLight); lightHandles.push_back(ambientLight); world.setParam("light", cpp::CopiedData(lightHandles)); } return world; } } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/test_pt_thinglass.cpp000066400000000000000000000023601456566705700307300ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_pt_material.h" namespace ospray { namespace testing { struct PtThinGlass : public PtMaterial { PtThinGlass() = default; ~PtThinGlass() override = default; std::vector buildMaterials() const override; }; static cpp::Material makeThinGlassMaterial( float eta, vec3f color, float attenuationDistance) { cpp::Material mat("thinGlass"); mat.setParam("eta", eta); mat.setParam("attenuationColor", color); mat.setParam("attenuationDistance", attenuationDistance); mat.commit(); return mat; } // Inlined definitions //////////////////////////////////////////////////// std::vector PtThinGlass::buildMaterials() const { std::vector materials; constexpr int dimSize = 5; index_sequence_2D numSpheres(dimSize); for (auto i : numSpheres) { auto i_f = static_cast(i); materials.push_back( makeThinGlassMaterial(lerp(i_f.x / (dimSize - 1), 1.f, 2.f), vec3f(.1f, .5f, 1.f), lerp(1.f - i_f.y / (dimSize - 1), 0.5f, 5.f))); } return materials; } OSP_REGISTER_TESTING_BUILDER(PtThinGlass, test_pt_thinglass); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/builders/test_pt_velvet.cpp000066400000000000000000000022111456566705700302340ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_pt_material.h" namespace ospray { namespace testing { struct PtVelvet : public PtMaterial { PtVelvet() = default; ~PtVelvet() override = default; std::vector buildMaterials() const override; }; static cpp::Material makeVelvetMaterial( float backScattering, float horizonScatteringFallOff) { cpp::Material mat("velvet"); mat.setParam("backScattering", backScattering); mat.setParam("horizonScatteringFallOff", horizonScatteringFallOff); mat.commit(); return mat; } // Inlined definitions //////////////////////////////////////////////////// std::vector PtVelvet::buildMaterials() const { std::vector materials; constexpr int dimSize = 5; index_sequence_2D numSpheres(dimSize); for (auto i : numSpheres) { auto i_f = static_cast(i); materials.push_back(makeVelvetMaterial( i_f.x / (dimSize - 1), lerp(i_f.y / (dimSize - 1), 0.f, 20.f))); } return materials; } OSP_REGISTER_TESTING_BUILDER(PtVelvet, test_pt_velvet); } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/detail/000077500000000000000000000000001456566705700241165ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/common/ospray_testing/detail/ospray_testing.inl000066400000000000000000000005631456566705700277000ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../builders/Builder.h" namespace ospray { namespace testing { template inline void setParam( SceneBuilderHandle _b, const std::string &type, const T &val) { auto *b = (detail::Builder *)_b; b->setParam(type, val); } } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/ospray_testing.cpp000066400000000000000000000016351456566705700264370ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray_testing #include "ospray_testing.h" // stl #include using namespace rkcommon; using namespace rkcommon::math; namespace ospray { namespace testing { SceneBuilderHandle newBuilder(const std::string &type) { auto *b = detail::Builder::createBuilder(type); if (b == nullptr) throw std::runtime_error("Unable to find '" + type + "' builder"); return (SceneBuilderHandle)b; } cpp::Group buildGroup(SceneBuilderHandle _b) { auto *b = (detail::Builder *)_b; return b->buildGroup(); } cpp::World buildWorld(SceneBuilderHandle _b) { auto *b = (detail::Builder *)_b; return b->buildWorld(); } void commit(SceneBuilderHandle _b) { auto *b = (detail::Builder *)_b; b->commit(); } void release(SceneBuilderHandle _b) { auto *b = (detail::Builder *)_b; b->refDec(); } } // namespace testing } // namespace ospray RenderKit-ospray-f2a61c2/apps/common/ospray_testing/ospray_testing.h000066400000000000000000000015231456566705700261000ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ospray/ospray_cpp.h" #include "ospray/ospray_cpp/ext/rkcommon.h" #include "ospray_testing_export.h" namespace ospray { namespace testing { using namespace rkcommon; using namespace rkcommon::math; using SceneBuilderHandle = void *; OSPRAY_TESTING_EXPORT SceneBuilderHandle newBuilder(const std::string &type); template void setParam(SceneBuilderHandle b, const std::string &type, const T &val); OSPRAY_TESTING_EXPORT cpp::Group buildGroup(SceneBuilderHandle b); OSPRAY_TESTING_EXPORT cpp::World buildWorld(SceneBuilderHandle b); OSPRAY_TESTING_EXPORT void commit(SceneBuilderHandle b); OSPRAY_TESTING_EXPORT void release(SceneBuilderHandle b); } // namespace testing } // namespace ospray #include "detail/ospray_testing.inl" RenderKit-ospray-f2a61c2/apps/common/raw_to_amr/000077500000000000000000000000001456566705700217345ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/common/raw_to_amr/CMakeLists.txt000066400000000000000000000003771456566705700245030ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 add_library(raw_to_amr STATIC rawToAMR.cpp) target_link_libraries(raw_to_amr PUBLIC rkcommon::rkcommon) target_include_directories(raw_to_amr INTERFACE ${CMAKE_CURRENT_LIST_DIR}) RenderKit-ospray-f2a61c2/apps/common/raw_to_amr/rawToAMR.cpp000066400000000000000000000144271456566705700241040ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wundefined-func-template" #include "rawToAMR.h" #include #include #include namespace ospray { namespace amr { void makeAMR(const std::vector &in, const vec3i inGridDims, const int numLevels, const int blockSize, const int refinementLevel, const float threshold, std::vector &blockBounds, std::vector &refinementLevels, std::vector &cellWidths, std::vector> &brickData) { int minWidth = blockSize; for (int i = 1; i < numLevels; i++) minWidth *= refinementLevel; if (minWidth >= refinementLevel * reduce_max(inGridDims)) { throw std::runtime_error( "too many levels, or too fine a refinement factor." "do not have a single brick at the root..."); } vec3i finestLevelSize = vec3i(minWidth); while (finestLevelSize.x < inGridDims.x) finestLevelSize.x += minWidth; while (finestLevelSize.y < inGridDims.y) finestLevelSize.y += minWidth; while (finestLevelSize.z < inGridDims.z) finestLevelSize.z += minWidth; // create container for current level so we don't use in std::vector ¤tLevel = const_cast &>(in); size_t numWritten = 0; size_t numRemoved = 0; std::mutex fileMutex; // create and write the bricks vec3i levelSize = finestLevelSize; for (int level = numLevels - 1; level >= 0; --level) { const vec3i nextLevelSize = levelSize / refinementLevel; // create container for next level down std::vector nextLevel = std::vector(nextLevelSize.product(), 0); const vec3i numBricks = levelSize / blockSize; rkcommon::tasking::parallel_for(numBricks.product(), [&](int brickIdx) { // dt == cellWidth in osp_amr_brick_info float dt = 1.f / powf(refinementLevel, level); // get 3D brick index from flat brickIdx const vec3i brickID(brickIdx % numBricks.x, (brickIdx / numBricks.x) % numBricks.y, brickIdx / (numBricks.x * numBricks.y)); // set upper and lower bounds of brick based on 3D index and // brick size in input data space box3i box; box.lower = brickID * blockSize; box.upper = box.lower + (blockSize - 1); // current brick data std::vector data(blockSize * blockSize * blockSize); size_t out = 0; range1f brickRange; // traverse the data by brick index for (int iz = box.lower.z; iz <= box.upper.z; iz++) { for (int iy = box.lower.y; iy <= box.upper.y; iy++) { for (int ix = box.lower.x; ix <= box.upper.x; ix++) { const size_t thisLevelCoord = ix + levelSize.y * (iy + iz * levelSize.z); const size_t nextLevelCoord = ix / refinementLevel + nextLevelSize.y * (iy / refinementLevel + iz / refinementLevel * nextLevelSize.z); // get the actual data at current coordinates const float v = currentLevel[thisLevelCoord]; // insert the data into the current brick data[out++] = v; nextLevel[nextLevelCoord] += v / (refinementLevel * refinementLevel * refinementLevel); // extend the value range of this brick (min/max) as needed brickRange.extend(v); } } } std::lock_guard lock(fileMutex); if ((level > 0) && ((brickRange.upper - brickRange.lower) <= threshold)) { numRemoved++; } else { blockBounds.push_back(box); refinementLevels.push_back(level); cellWidths.resize(std::max(cellWidths.size(), (size_t)level + 1)); cellWidths[level] = dt; brickData.push_back(data); numWritten++; } }); // end parallel for currentLevel = nextLevel; levelSize = nextLevelSize; numWritten = 0; numRemoved = 0; } // end for loop on levels } void outputAMR(const FileName outFileBase, const std::vector &blockBounds, const std::vector &refinementLevels, const std::vector &cellWidths, const std::vector> &brickData, const int blockSize) { // ALOK: .info is brick metadata FILE *infoOut = fopen(outFileBase.addExt(".info").c_str(), "wb"); if (!infoOut) { throw std::runtime_error("could not open info output file!"); } // ALOK: .data is actual data FILE *dataOut = fopen(outFileBase.addExt(".data").c_str(), "wb"); if (!dataOut) { throw std::runtime_error("could not open data output file!"); } std::ofstream osp(outFileBase + std::string(".osp")); osp << "" << std::endl; osp << "" << std::endl; osp << " " << rkcommon::FileName(outFileBase).base() << "" << std::endl; osp << " " << blockSize << "" << std::endl; osp << " 0 100000" << std::endl; osp << "" << std::endl; size_t numBlockBounds = blockBounds.size(), numRefinementLevels = refinementLevels.size(), numCellWidths = cellWidths.size(); fwrite(&numBlockBounds, sizeof(size_t), 1, infoOut); fwrite(blockBounds.data(), sizeof(box3i), blockBounds.size(), infoOut); fwrite(&numRefinementLevels, sizeof(size_t), 1, infoOut); fwrite( refinementLevels.data(), sizeof(int), refinementLevels.size(), infoOut); fwrite(&numCellWidths, sizeof(size_t), 1, infoOut); fwrite(cellWidths.data(), sizeof(float), cellWidths.size(), infoOut); for (auto &data : brickData) { fwrite(data.data(), sizeof(float), data.size(), dataOut); } fclose(infoOut); fclose(dataOut); } template std::vector loadRAW(const std::string &fileName, const vec3i &dims) { const size_t num = dims.product(); std::vector volume(num); FILE *file = fopen(fileName.c_str(), "rb"); if (!file) throw std::runtime_error( "ospray::amr::loadRaw(): could not open '" + fileName + "'"); size_t numRead = fread(volume.data(), sizeof(T), num, file); if (num != numRead) throw std::runtime_error( "ospray::amr::loadRaw(): read incomplete data ..."); fclose(file); return volume; } } // namespace amr } // namespace ospray #pragma clang diagnostic pop RenderKit-ospray-f2a61c2/apps/common/raw_to_amr/rawToAMR.h000066400000000000000000000045441456566705700235500ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "rkcommon/math/box.h" #include "rkcommon/os/FileName.h" #include "rkcommon/tasking/parallel_for.h" #include #include #ifdef _WIN32 #include #else #include #endif #include #include #include #include #include namespace ospray { namespace amr { using namespace rkcommon; using namespace rkcommon::math; void makeAMR(const std::vector &in, const vec3i inGridDims, const int numLevels, const int blockSize, const int refinementLevel, const float threshold, std::vector &blockBounds, std::vector &refinementLevels, std::vector &cellWidths, std::vector> &brickData); void outputAMR(const FileName outFileBase, const std::vector &blockBounds, const std::vector &refinementLevels, const std::vector &cellWidths, const std::vector> &brickData, const int blockSize); template std::vector loadRAW(const std::string &fileName, const vec3i &dims); template std::vector mmapRAW(const std::string &fileName, const vec3i &dims) { #ifdef _WIN32 throw std::runtime_error("Memory mapping not supported in Windows"); #else FILE *file = fopen(fileName.c_str(), "rb"); if (!file) throw std::runtime_error("Could not open file."); fseek(file, 0, SEEK_END); size_t actualFileSize = ftell(file); fclose(file); size_t fileSize = size_t(dims.x) * size_t(dims.y) * size_t(dims.z) * sizeof(T); if (actualFileSize != fileSize) { std::stringstream ss; ss << "Got file size " << prettyNumber(actualFileSize); ss << ", but expected " << prettyNumber(fileSize); ss << ". Common cause is wrong data type!"; throw std::runtime_error(ss.str()); } int fd = ::open(fileName.c_str(), O_RDONLY); if (fd == -1) throw std::runtime_error("Could not open file."); void *mem = mmap(nullptr, fileSize, PROT_READ, MAP_SHARED // |MAP_HUGETLB , fd, 0); ::close(fd); if (mem == MAP_FAILED) throw std::runtime_error("Could not mmap file."); std::vector volume; volume.assign((T *)mem, (T *)mem + dims.product()); return volume; #endif } } // namespace amr } // namespace ospray RenderKit-ospray-f2a61c2/apps/ospBenchmark/000077500000000000000000000000001456566705700207265ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/ospBenchmark/BaseFixture.cpp000066400000000000000000000036171456566705700236620ustar00rootroot00000000000000// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "BaseFixture.h" #include "rkcommon/utility/SaveImage.h" #include std::string BaseFixture::dumpFinalImageDir; BaseFixture::BaseFixture( const std::string &n, const std::string &s, const std::string &r) : name(n + "/" + r), scene(s), rendererType(r) { ::benchmark::Fixture::SetName(name.c_str()); } void BaseFixture::Init() { framebuffer = cpp::FrameBuffer(imgSize.x, imgSize.y, OSP_FB_SRGBA, OSP_FB_COLOR | OSP_FB_ACCUM | OSP_FB_DEPTH); framebuffer.resetAccumulation(); auto builder = testing::newBuilder(scene); testing::setParam(builder, "rendererType", rendererType); SetBuilderParameters(builder); testing::commit(builder); world = testing::buildWorld(builder); testing::release(builder); world.commit(); auto worldBounds = world.getBounds(); ArcballCamera arcballCamera(worldBounds, imgSize); camera = cpp::Camera("perspective"); camera.setParam("aspect", imgSize.x / (float)imgSize.y); camera.setParam("position", arcballCamera.eyePos()); camera.setParam("direction", arcballCamera.lookDir()); camera.setParam("up", arcballCamera.upDir()); camera.commit(); renderer = cpp::Renderer(rendererType); SetRendererParameters(renderer); renderer.commit(); } void BaseFixture::Shutdown() { framebuffer = nullptr; renderer = nullptr; camera = nullptr; world = nullptr; } void BaseFixture::TearDown(::benchmark::State &) { if (!dumpFinalImageDir.empty() && !name.empty()) { std::string of = name; std::replace(of.begin(), of.end(), '/', '_'); framebuffer.resetAccumulation(); framebuffer.renderFrame(renderer, camera, world); auto *fb = (uint32_t *)framebuffer.map(OSP_FB_COLOR); utility::writePPM( dumpFinalImageDir + "/" + of + ".ppm", imgSize.x, imgSize.y, fb); framebuffer.unmap(fb); } Shutdown(); }RenderKit-ospray-f2a61c2/apps/ospBenchmark/BaseFixture.h000066400000000000000000000103441456566705700233220ustar00rootroot00000000000000// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ArcballCamera.h" // ospray_testing #include "ospray_testing.h" // google benchmark #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wsuggest-override" #include "benchmark/benchmark.h" #pragma clang diagnostic pop using namespace ospray; using namespace rkcommon; using namespace rkcommon::math; class BaseFixture : public ::benchmark::Fixture { public: BaseFixture(const std::string &n, const std::string &s, const std::string &r); void Init(); void Shutdown(); void SetUp(::benchmark::State &) override { Init(); } void TearDown(::benchmark::State &) override; virtual void SetBuilderParameters(testing::SceneBuilderHandle) {} virtual void SetRendererParameters(cpp::Renderer) {} static std::string dumpFinalImageDir; std::string name; protected: vec2i imgSize{1024, 768}; std::string scene; std::string rendererType; cpp::FrameBuffer framebuffer{nullptr}; cpp::Renderer renderer{nullptr}; cpp::Camera camera{nullptr}; cpp::World world{nullptr}; }; // Use line number to generate unique identifier // Must not use the same FixtureName across different compilation units (.cpp // files) or conflicts may appear #define CAT2(a, b) a##b #define CAT(a, b) CAT2(a, b) #define UNIQUE_NAME(name) CAT(name, __LINE__) #define OSPRAY_DEFINE_BENCHMARK(FixtureName, ...) \ class UNIQUE_NAME(FixtureName) : public FixtureName \ { \ public: \ UNIQUE_NAME(FixtureName)() : FixtureName("", __VA_ARGS__) {} \ \ protected: \ void BenchmarkCase(::benchmark::State &st) override \ { \ for (auto _ : st) { \ framebuffer.renderFrame(renderer, camera, world); \ } \ st.SetItemsProcessed(st.iterations()); \ } \ }; \ BENCHMARK_PRIVATE_REGISTER_F(UNIQUE_NAME(FixtureName)) \ ->Unit(benchmark::kMillisecond) \ ->UseRealTime(); #define UNIQUE_SETUP_NAME(name) CAT(CAT(name, Setup), __LINE__) #define OSPRAY_DEFINE_SETUP_BENCHMARK(FixtureName, ...) \ class UNIQUE_SETUP_NAME(FixtureName) : public FixtureName \ { \ public: \ UNIQUE_SETUP_NAME(FixtureName)() : FixtureName("setup/", __VA_ARGS__) {} \ \ protected: \ void BenchmarkCase(::benchmark::State &st) override \ { \ for (auto _ : st) { \ Shutdown(); \ Init(); \ } \ st.SetItemsProcessed(st.iterations()); \ } \ }; \ BENCHMARK_PRIVATE_REGISTER_F(UNIQUE_SETUP_NAME(FixtureName)) \ ->Unit(benchmark::kMillisecond) \ ->UseRealTime(); RenderKit-ospray-f2a61c2/apps/ospBenchmark/CMakeLists.txt000066400000000000000000000012401456566705700234630ustar00rootroot00000000000000## Copyright 2018 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 if (NOT OSPRAY_ENABLE_APPS_BENCHMARK) return() endif() find_package(benchmark REQUIRED) add_executable(ospBenchmark ${OSPRAY_RESOURCE} ospBenchmark.cpp BaseFixture.cpp benchmarks/Simple.cpp benchmarks/BoxesAo.cpp benchmarks/CornellBoxSpp.cpp benchmarks/GravitySpheresVolume.cpp benchmarks/PerlinNoiseVolumes.cpp benchmarks/ClippingGeometries.cpp ) target_link_libraries(ospBenchmark PRIVATE arcball_camera benchmark::benchmark ospray_testing ) ospray_sign_target(ospBenchmark) install(TARGETS ospBenchmark DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT apps ) RenderKit-ospray-f2a61c2/apps/ospBenchmark/benchmarks/000077500000000000000000000000001456566705700230435ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/ospBenchmark/benchmarks/BoxesAo.cpp000066400000000000000000000016511456566705700251120ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../BaseFixture.h" class Boxes : public BaseFixture { public: Boxes( const std::string &n, const std::string &s, const std::string &r, int ao) : BaseFixture(n + s + "/ao_" + std::to_string(ao), s, r), aoSamples(ao) {} void SetRendererParameters(cpp::Renderer r) override { r.setParam("aoSamples", aoSamples); } private: int aoSamples; }; OSPRAY_DEFINE_BENCHMARK(Boxes, "boxes", "ao", 0); OSPRAY_DEFINE_BENCHMARK(Boxes, "boxes", "ao", 1); OSPRAY_DEFINE_BENCHMARK(Boxes, "boxes", "ao", 16); OSPRAY_DEFINE_BENCHMARK(Boxes, "boxes", "ao", 256); OSPRAY_DEFINE_BENCHMARK(Boxes, "boxes", "scivis", 0); OSPRAY_DEFINE_BENCHMARK(Boxes, "boxes", "scivis", 1); OSPRAY_DEFINE_BENCHMARK(Boxes, "boxes", "scivis", 16); OSPRAY_DEFINE_BENCHMARK(Boxes, "boxes", "scivis", 256); OSPRAY_DEFINE_SETUP_BENCHMARK(Boxes, "boxes", "ao", 256); RenderKit-ospray-f2a61c2/apps/ospBenchmark/benchmarks/ClippingGeometries.cpp000066400000000000000000000035011456566705700273370ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../BaseFixture.h" class ClippingGeometries : public BaseFixture { public: ClippingGeometries(const std::string &n, const std::string &s, const std::string &g, const std::string &r) : BaseFixture(n + "clip_geometries/with_" + g, s, r), geometry(g) {} private: std::string geometry; }; OSPRAY_DEFINE_BENCHMARK( ClippingGeometries, "clip_with_spheres", "spheres", "ao"); OSPRAY_DEFINE_BENCHMARK(ClippingGeometries, "clip_with_boxes", "boxes", "ao"); OSPRAY_DEFINE_BENCHMARK(ClippingGeometries, "clip_with_planes", "planes", "ao"); OSPRAY_DEFINE_BENCHMARK(ClippingGeometries, "clip_with_meshes", "meshes", "ao"); OSPRAY_DEFINE_BENCHMARK( ClippingGeometries, "clip_with_spheres", "spheres", "scivis"); OSPRAY_DEFINE_BENCHMARK( ClippingGeometries, "clip_with_boxes", "boxes", "scivis"); OSPRAY_DEFINE_BENCHMARK( ClippingGeometries, "clip_with_planes", "planes", "scivis"); OSPRAY_DEFINE_BENCHMARK( ClippingGeometries, "clip_with_meshes", "meshes", "scivis"); OSPRAY_DEFINE_BENCHMARK( ClippingGeometries, "clip_with_spheres", "spheres", "pathtracer"); OSPRAY_DEFINE_BENCHMARK( ClippingGeometries, "clip_with_boxes", "boxes", "pathtracer"); OSPRAY_DEFINE_BENCHMARK( ClippingGeometries, "clip_with_planes", "planes", "pathtracer"); OSPRAY_DEFINE_BENCHMARK( ClippingGeometries, "clip_with_meshes", "meshes", "pathtracer"); OSPRAY_DEFINE_SETUP_BENCHMARK( ClippingGeometries, "clip_with_spheres", "spheres", "scivis"); OSPRAY_DEFINE_SETUP_BENCHMARK( ClippingGeometries, "clip_with_boxes", "boxes", "scivis"); OSPRAY_DEFINE_SETUP_BENCHMARK( ClippingGeometries, "clip_with_planes", "planes", "scivis"); OSPRAY_DEFINE_SETUP_BENCHMARK( ClippingGeometries, "clip_with_meshes", "meshes", "scivis"); RenderKit-ospray-f2a61c2/apps/ospBenchmark/benchmarks/CornellBoxSpp.cpp000066400000000000000000000022121456566705700262760ustar00rootroot00000000000000// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../BaseFixture.h" class CornellBox : public BaseFixture { public: CornellBox( const std::string &n, const std::string &s, int spp, const std::string &r) : BaseFixture(n + s + "/spp_" + std::to_string(spp), s, r), pixelSamples(spp) {} void SetRendererParameters(cpp::Renderer r) override { r.setParam("pixelSamples", pixelSamples); } private: int pixelSamples; }; OSPRAY_DEFINE_BENCHMARK(CornellBox, "cornell_box", 1, "ao"); OSPRAY_DEFINE_BENCHMARK(CornellBox, "cornell_box", 16, "ao"); OSPRAY_DEFINE_BENCHMARK(CornellBox, "cornell_box", 256, "ao"); OSPRAY_DEFINE_BENCHMARK(CornellBox, "cornell_box", 1, "scivis"); OSPRAY_DEFINE_BENCHMARK(CornellBox, "cornell_box", 16, "scivis"); OSPRAY_DEFINE_BENCHMARK(CornellBox, "cornell_box", 256, "scivis"); OSPRAY_DEFINE_BENCHMARK(CornellBox, "cornell_box", 1, "pathtracer"); OSPRAY_DEFINE_BENCHMARK(CornellBox, "cornell_box", 16, "pathtracer"); OSPRAY_DEFINE_BENCHMARK(CornellBox, "cornell_box", 256, "pathtracer"); OSPRAY_DEFINE_SETUP_BENCHMARK(CornellBox, "cornell_box", 256, "pathtracer"); RenderKit-ospray-f2a61c2/apps/ospBenchmark/benchmarks/GravitySpheresVolume.cpp000066400000000000000000000025151456566705700277210ustar00rootroot00000000000000// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../BaseFixture.h" class GravitySpheres : public BaseFixture { public: GravitySpheres( const std::string &n, const std::string &s, int d, const std::string &r) : BaseFixture(n + s + "/dim_" + std::to_string(d), s, r), dim(d) {} void SetBuilderParameters(testing::SceneBuilderHandle scene) override { testing::setParam(scene, "volumeDimensions", vec3i(dim)); } private: int dim; }; OSPRAY_DEFINE_BENCHMARK(GravitySpheres, "gravity_spheres_volume", 32, "ao"); OSPRAY_DEFINE_BENCHMARK(GravitySpheres, "gravity_spheres_volume", 128, "ao"); OSPRAY_DEFINE_BENCHMARK(GravitySpheres, "gravity_spheres_volume", 512, "ao"); OSPRAY_DEFINE_BENCHMARK(GravitySpheres, "gravity_spheres_volume", 32, "scivis"); OSPRAY_DEFINE_BENCHMARK( GravitySpheres, "gravity_spheres_volume", 128, "scivis"); OSPRAY_DEFINE_BENCHMARK( GravitySpheres, "gravity_spheres_volume", 512, "scivis"); OSPRAY_DEFINE_BENCHMARK( GravitySpheres, "gravity_spheres_volume", 32, "pathtracer"); OSPRAY_DEFINE_BENCHMARK( GravitySpheres, "gravity_spheres_volume", 128, "pathtracer"); OSPRAY_DEFINE_BENCHMARK( GravitySpheres, "gravity_spheres_volume", 512, "pathtracer"); OSPRAY_DEFINE_SETUP_BENCHMARK( GravitySpheres, "gravity_spheres_volume", 128, "pathtracer"); RenderKit-ospray-f2a61c2/apps/ospBenchmark/benchmarks/PerlinNoiseVolumes.cpp000066400000000000000000000022301456566705700273460ustar00rootroot00000000000000// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../BaseFixture.h" class PerlinNoiseVolumes : public BaseFixture { public: PerlinNoiseVolumes( const std::string &n, const std::string &s, bool at, const std::string &r) : BaseFixture(n + s + (at ? "/both_volumes" : "/sphere_only"), s, r), addTorus(at) {} void SetBuilderParameters(testing::SceneBuilderHandle scene) override { testing::setParam(scene, "addTorusVolume", addTorus); } private: bool addTorus; }; OSPRAY_DEFINE_BENCHMARK( PerlinNoiseVolumes, "perlin_noise_volumes", false, "ao"); OSPRAY_DEFINE_BENCHMARK(PerlinNoiseVolumes, "perlin_noise_volumes", true, "ao"); OSPRAY_DEFINE_BENCHMARK( PerlinNoiseVolumes, "perlin_noise_volumes", false, "scivis"); OSPRAY_DEFINE_BENCHMARK( PerlinNoiseVolumes, "perlin_noise_volumes", true, "scivis"); OSPRAY_DEFINE_BENCHMARK( PerlinNoiseVolumes, "perlin_noise_volumes", false, "pathtracer"); OSPRAY_DEFINE_BENCHMARK( PerlinNoiseVolumes, "perlin_noise_volumes", true, "pathtracer"); OSPRAY_DEFINE_SETUP_BENCHMARK( PerlinNoiseVolumes, "perlin_noise_volumes", true, "pathtracer"); RenderKit-ospray-f2a61c2/apps/ospBenchmark/benchmarks/Simple.cpp000066400000000000000000000070231456566705700250020ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../BaseFixture.h" class Simple : public BaseFixture { public: Simple(const std::string &n, const std::string &s, const std::string &r) : BaseFixture(n + s, s, r) {} }; OSPRAY_DEFINE_BENCHMARK(Simple, "boxes", "pathtracer"); OSPRAY_DEFINE_BENCHMARK(Simple, "random_spheres", "ao"); OSPRAY_DEFINE_BENCHMARK(Simple, "random_spheres", "scivis"); OSPRAY_DEFINE_BENCHMARK(Simple, "random_spheres", "pathtracer"); OSPRAY_DEFINE_SETUP_BENCHMARK(Simple, "random_spheres", "pathtracer"); OSPRAY_DEFINE_BENCHMARK(Simple, "streamlines", "ao"); OSPRAY_DEFINE_BENCHMARK(Simple, "streamlines", "scivis"); OSPRAY_DEFINE_BENCHMARK(Simple, "streamlines", "pathtracer"); OSPRAY_DEFINE_SETUP_BENCHMARK(Simple, "streamlines", "pathtracer"); OSPRAY_DEFINE_BENCHMARK(Simple, "planes", "ao"); OSPRAY_DEFINE_BENCHMARK(Simple, "planes", "scivis"); OSPRAY_DEFINE_BENCHMARK(Simple, "planes", "pathtracer"); OSPRAY_DEFINE_SETUP_BENCHMARK(Simple, "planes", "pathtracer"); OSPRAY_DEFINE_BENCHMARK(Simple, "clip_gravity_spheres_volume", "ao"); OSPRAY_DEFINE_BENCHMARK(Simple, "clip_gravity_spheres_volume", "scivis"); OSPRAY_DEFINE_BENCHMARK(Simple, "clip_gravity_spheres_volume", "pathtracer"); OSPRAY_DEFINE_SETUP_BENCHMARK( Simple, "clip_gravity_spheres_volume", "scivis"); OSPRAY_DEFINE_BENCHMARK(Simple, "clip_perlin_noise_volumes", "ao"); OSPRAY_DEFINE_BENCHMARK(Simple, "clip_perlin_noise_volumes", "scivis"); OSPRAY_DEFINE_BENCHMARK(Simple, "clip_perlin_noise_volumes", "pathtracer"); OSPRAY_DEFINE_SETUP_BENCHMARK( Simple, "clip_perlin_noise_volumes", "scivis"); OSPRAY_DEFINE_BENCHMARK(Simple, "clip_particle_volume", "ao"); OSPRAY_DEFINE_BENCHMARK(Simple, "clip_particle_volume", "scivis"); OSPRAY_DEFINE_BENCHMARK(Simple, "clip_particle_volume", "pathtracer"); OSPRAY_DEFINE_SETUP_BENCHMARK(Simple, "clip_particle_volume", "scivis"); OSPRAY_DEFINE_BENCHMARK(Simple, "particle_volume", "ao"); OSPRAY_DEFINE_BENCHMARK(Simple, "particle_volume", "scivis"); OSPRAY_DEFINE_BENCHMARK(Simple, "particle_volume", "pathtracer"); OSPRAY_DEFINE_SETUP_BENCHMARK(Simple, "particle_volume", "pathtracer"); OSPRAY_DEFINE_BENCHMARK(Simple, "particle_volume_isosurface", "ao"); OSPRAY_DEFINE_BENCHMARK(Simple, "particle_volume_isosurface", "scivis"); OSPRAY_DEFINE_BENCHMARK(Simple, "particle_volume_isosurface", "pathtracer"); OSPRAY_DEFINE_SETUP_BENCHMARK( Simple, "particle_volume_isosurface", "pathtracer"); OSPRAY_DEFINE_BENCHMARK(Simple, "vdb_volume", "ao"); OSPRAY_DEFINE_BENCHMARK(Simple, "vdb_volume", "scivis"); OSPRAY_DEFINE_BENCHMARK(Simple, "vdb_volume", "pathtracer"); OSPRAY_DEFINE_SETUP_BENCHMARK(Simple, "vdb_volume", "pathtracer"); OSPRAY_DEFINE_BENCHMARK(Simple, "unstructured_volume", "ao"); OSPRAY_DEFINE_BENCHMARK(Simple, "unstructured_volume", "scivis"); OSPRAY_DEFINE_BENCHMARK(Simple, "unstructured_volume", "pathtracer"); OSPRAY_DEFINE_SETUP_BENCHMARK(Simple, "unstructured_volume", "pathtracer"); OSPRAY_DEFINE_BENCHMARK(Simple, "unstructured_volume_isosurface", "ao"); OSPRAY_DEFINE_BENCHMARK(Simple, "unstructured_volume_isosurface", "scivis"); OSPRAY_DEFINE_BENCHMARK(Simple, "unstructured_volume_isosurface", "pathtracer"); OSPRAY_DEFINE_SETUP_BENCHMARK( Simple, "unstructured_volume_isosurface", "scivis"); OSPRAY_DEFINE_BENCHMARK(Simple, "gravity_spheres_amr", "ao"); OSPRAY_DEFINE_BENCHMARK(Simple, "gravity_spheres_amr", "scivis"); OSPRAY_DEFINE_BENCHMARK(Simple, "gravity_spheres_amr", "pathtracer"); OSPRAY_DEFINE_SETUP_BENCHMARK(Simple, "gravity_spheres_amr", "pathtracer"); RenderKit-ospray-f2a61c2/apps/ospBenchmark/ospBenchmark.cpp000066400000000000000000000101321456566705700240430ustar00rootroot00000000000000// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "BaseFixture.h" #include "rkcommon/utility/getEnvVar.h" #ifdef _WIN32 #ifndef NOMINMAX #define NOMINMAX #endif #include #include #endif #include #include namespace { std::vector cmdArg; } // end namespace // Test init/shutdown cycle time ////////////////////////////////////////////// static void ospInit_ospShutdown(benchmark::State &state) { ospShutdown(); for (auto _ : state) { // Those temp variable are needed because the call to ospInit changes the // number and order of arguments std::vector cmdArgCpy(cmdArg); int argc = cmdArgCpy.size(); ospInit(&argc, cmdArgCpy.data()); ospShutdown(); } state.SetItemsProcessed(state.iterations()); std::vector cmdArgCpy(cmdArg); int argc = cmdArgCpy.size(); ospInit(&argc, cmdArgCpy.data()); } BENCHMARK(ospInit_ospShutdown)->Unit(benchmark::kMillisecond); /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // based on BENCHMARK_MAIN() macro from benchmark.h int main(int argc, char **argv) { #ifdef _WIN32 bool waitForKey = false; CONSOLE_SCREEN_BUFFER_INFO csbi; if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) { // detect standalone console: cursor at (0,0)? waitForKey = csbi.dwCursorPosition.X == 0 && csbi.dwCursorPosition.Y == 0; } #endif // As there is no other way of customizing help output // we have to detect `--help` by ourselves for (int i = 1; i < argc; i++) { if (std::string(argv[i]) == "--help") { std::cout << "The ospBenchmark is a performance measurement tool that " "allows to assess the Intel OSPRay library performance on a target " "hardware. It consists of many workloads that can be listed with " "[--benchmark_list_tests=true] parameter and then selected for run " "with [--benchmark_filter=] parameter. All test assets like " "meshes or textures are generated procedurally during workload " "initialization phase. If a test renders a frame it is stored " "to an offscreen frame buffer." << std::endl << std::endl; std::cout << "After tests completion a results table is printed. Each " "table row corresponds to a single test or a single test " "repetition. Number of repetitions can be controlled with " "[--benchmark_repetitions=] parameter. Each " "repetition completely recreates frame buffer, world, renderer " "and camera. The table has the following columns:" << std::endl; std::cout << " 'Benchmark' - the name of a test" << std::endl; std::cout << " 'Time' - single iteration wall clock time" << std::endl; std::cout << " 'CPU' - single iteration CPU time spend by the main thread" << std::endl; std::cout << " 'Iterations' - number of rendered frames, determined adaptively " "to test for specified minimum time" << std::endl; std::cout << " 'UserCounters' - frames per second value" << std::endl << std::endl; std::cout << "The list of all supported parameters:" << std::endl; } } // save original cmdline args for multiple init/shutdown cycles for (int i = 0; i < argc; i++) cmdArg.push_back(argv[i]); ospInit(&argc, (const char **)argv); std::atexit(ospShutdown); auto DIR = utility::getEnvVar("OSPRAY_BENCHMARK_IMG_DIR"); BaseFixture::dumpFinalImageDir = DIR.value_or(""); ::benchmark::Initialize(&argc, argv); if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1; ::benchmark::RunSpecifiedBenchmarks(); #ifdef _WIN32 if (waitForKey) { printf("\n\tpress any key to exit"); _getch(); } #endif return 0; } RenderKit-ospray-f2a61c2/apps/ospExamples/000077500000000000000000000000001456566705700206125ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/ospExamples/CMakeLists.txt000066400000000000000000000007121456566705700233520ustar00rootroot00000000000000## Copyright 2018 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 if (NOT OSPRAY_ENABLE_APPS_EXAMPLES) return() endif() add_executable(ospExamples ${OSPRAY_RESOURCE} GLFWOSPRayWindow.cpp ospExample.cpp ) target_link_libraries(ospExamples PRIVATE arcball_camera ospray_testing ospray_imgui ${OPENGL_LIBRARIES} ) ospray_sign_target(ospExamples) install(TARGETS ospExamples DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT apps ) RenderKit-ospray-f2a61c2/apps/ospExamples/GLFWOSPRayWindow.cpp000066400000000000000000000714571456566705700243210ustar00rootroot00000000000000// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "GLFWOSPRayWindow.h" // ospray_testing #include "ospray_testing.h" #include "rkcommon/utility/random.h" // imgui #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" // std #include #include #include #include #include // on Windows often only GL 1.1 headers are present #ifndef GL_CLAMP_TO_BORDER #define GL_CLAMP_TO_BORDER 0x812D #endif #ifndef GL_FRAMEBUFFER_SRGB #define GL_FRAMEBUFFER_SRGB 0x8DB9 #endif #ifndef GL_RGBA32F #define GL_RGBA32F 0x8814 #endif #ifndef GL_RGB32F #define GL_RGB32F 0x8815 #endif static bool g_quitNextFrame = false; static const std::vector g_scenes = {"boxes_lit", "boxes", "cornell_box", "curves", "gravity_spheres_volume", "gravity_spheres_amr", "gravity_spheres_isosurface", "perlin_noise_volumes", "random_spheres", "random_discs", "random_oriented_discs", "streamlines", "subdivision_cube", "unstructured_volume", "unstructured_volume_isosurface", "planes", "clip_with_spheres", "clip_with_planes", "clip_gravity_spheres_volume", "clip_perlin_noise_volumes", "clip_particle_volume", "particle_volume", "particle_volume_isosurface", "vdb_volume", "vdb_volume_packed", "instancing", "test_pt_alloy_roughness", "test_pt_carpaint", "test_pt_glass", "test_pt_thinglass", "test_pt_luminous", "test_pt_material_tex", "test_pt_metal_roughness", "test_pt_metallic_flakes", "test_pt_mix_tex", "test_pt_obj", "test_pt_plastic", "test_pt_principled_metal", "test_pt_principled_plastic", "test_pt_principled_glass", "test_pt_principled_tex", "test_pt_velvet"}; static const std::vector g_curveVariant = { "bspline", "hermite", "catmull-rom", "linear", "cones"}; static const std::vector g_renderers = { "scivis", "pathtracer", "ao", "debug"}; static const std::vector g_debugRendererTypes = {"eyeLight", "primID", "geomID", "instID", "Ng", "Ns", "backfacing_Ng", "backfacing_Ns", "dPds", "dPdt", "volume"}; static const std::vector g_pixelFilterTypes = { "point", "box", "gaussian", "mitchell", "blackmanHarris"}; static const std::vector g_AOVs = { "color", "depth", "albedo", "primID", "objID", "instID"}; const char *vec_string_getter(void *vec_, int index) { auto v = (std::vector *)vec_; return v->at(index).c_str(); } // GLFWOSPRayWindow definitions /////////////////////////////////////////////// void error_callback(int error, const char *desc) { std::cerr << "GLFW error " << error << ": " << desc << std::endl; } GLFWOSPRayWindow *GLFWOSPRayWindow::activeWindow = nullptr; GLFWOSPRayWindow::GLFWOSPRayWindow(const vec2i &windowSize, bool denoiser) : denoiserAvailable(denoiser) { if (activeWindow != nullptr) { throw std::runtime_error("Cannot create more than one GLFWOSPRayWindow!"); } activeWindow = this; glfwSetErrorCallback(error_callback); if (!glfwInit()) { throw std::runtime_error("Failed to initialize GLFW!"); } glfwWindowHint(GLFW_SRGB_CAPABLE, GLFW_TRUE); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); #ifdef __APPLE_ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); const char *glslVersion = "#version 150"; #else glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); const char *glslVersion = "#version 130"; #endif glfwWindow = glfwCreateWindow( windowSize.x, windowSize.y, "OSPRay Examples", nullptr, nullptr); if (!glfwWindow) { glfwTerminate(); throw std::runtime_error("Failed to create GLFW window!"); } glfwMakeContextCurrent(glfwWindow); // Setup Dear ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO &io = ImGui::GetIO(); io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; ImGui_ImplGlfw_InitForOpenGL(glfwWindow, false); // set GLFW callbacks glfwSetFramebufferSizeCallback( glfwWindow, [](GLFWwindow *, int newWidth, int newHeight) { activeWindow->reshape(vec2i{newWidth, newHeight}); }); glfwSetCursorPosCallback(glfwWindow, [](GLFWwindow *, double x, double y) { ImGuiIO &io = ImGui::GetIO(); if (!activeWindow->showUi || !io.WantCaptureMouse) { activeWindow->motion(vec2f{float(x), float(y)}); } }); glfwSetKeyCallback( glfwWindow, [](GLFWwindow *, int key, int, int action, int) { if (action == GLFW_PRESS) { switch (key) { case GLFW_KEY_G: activeWindow->showUi = !(activeWindow->showUi); break; case GLFW_KEY_Q: g_quitNextFrame = true; break; } } }); glfwSetMouseButtonCallback( glfwWindow, [](GLFWwindow *, int button, int action, int /*mods*/) { auto &w = *activeWindow; if (button == GLFW_MOUSE_BUTTON_MIDDLE && action == GLFW_PRESS) { auto mouse = activeWindow->previousMouse; auto windowSize = activeWindow->windowSize; const vec2f pos(mouse.x / static_cast(windowSize.x), 1.f - mouse.y / static_cast(windowSize.y)); auto res = w.framebuffer.pick(*w.renderer, w.camera, w.world, pos.x, pos.y); if (res.hasHit) { std::cout << "Picked geometry [inst: " << res.instance << ", model: " << res.model << ", prim: " << res.primID << "]" << std::endl; } } }); // will chain our callbacks above ImGui_ImplGlfw_InstallCallbacks(glfwWindow); ImGui_ImplOpenGL3_Init(glslVersion); // set initial OpenGL state glEnable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); // create OpenGL frame buffer texture glGenTextures(1, &framebufferTexture); glBindTexture(GL_TEXTURE_2D, framebufferTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // OSPRay setup // // set up backplate texture std::vector backplate; backplate.push_back(vec4f(0.8f, 0.2f, 0.2f, 1.0f)); backplate.push_back(vec4f(0.2f, 0.8f, 0.2f, 1.0f)); backplate.push_back(vec4f(0.2f, 0.2f, 0.8f, 1.0f)); backplate.push_back(vec4f(0.4f, 0.2f, 0.4f, 1.0f)); backplateTex.setParam( "data", cpp::CopiedData(backplate.data(), vec2ul(2, 2))); backplateTex.setParam("format", OSP_TEXTURE_RGBA32F); addObjectToCommit(backplateTex.handle()); refreshScene(true); // trigger window reshape events with current window size glfwGetFramebufferSize(glfwWindow, &this->windowSize.x, &this->windowSize.y); reshape(this->windowSize); commitOutstandingHandles(); } GLFWOSPRayWindow::~GLFWOSPRayWindow() { ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); glfwDestroyWindow(glfwWindow); glfwTerminate(); } GLFWOSPRayWindow *GLFWOSPRayWindow::getActiveWindow() { return activeWindow; } void GLFWOSPRayWindow::mainLoop() { // continue until the user closes the window startNewOSPRayFrame(); while (!glfwWindowShouldClose(glfwWindow) && !g_quitNextFrame) { glfwPollEvents(); ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); if (displayCallback) displayCallback(this); display(); if (showUi) buildUI(); glDisable(GL_FRAMEBUFFER_SRGB); // Disable SRGB conversion for UI ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); glfwSwapBuffers(glfwWindow); } waitOnOSPRayFrame(); } void GLFWOSPRayWindow::reshape(const vec2i &newWindowSize) { windowSize = newWindowSize; // create new frame buffer auto buffers = OSP_FB_COLOR | OSP_FB_DEPTH | OSP_FB_ACCUM | OSP_FB_VARIANCE | OSP_FB_ALBEDO | OSP_FB_NORMAL | OSP_FB_ID_PRIMITIVE | OSP_FB_ID_OBJECT | OSP_FB_ID_INSTANCE; framebuffer = cpp::FrameBuffer(windowSize.x, windowSize.y, OSP_FB_RGBA32F, buffers); refreshFrameOperations(); // reset OpenGL viewport and orthographic projection glViewport(0, 0, windowSize.x, windowSize.y); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, windowSize.x, 0.0, windowSize.y, -1.0, 1.0); // update camera arcballCamera->updateWindowSize(windowSize); camera.setParam("aspect", windowSize.x / float(windowSize.y)); camera.commit(); } void GLFWOSPRayWindow::updateCamera() { camera.setParam("aspect", windowSize.x / float(windowSize.y)); camera.setParam("stereoMode", cameraStereoMode); const auto xfm = arcballCamera->transform(); if (rendererType == OSPRayRendererType::PATHTRACER && cameraMotionBlur) { camera.removeParam("transform"); std::vector xfms; xfms.push_back(lastXfm); xfms.push_back(xfm); camera.setParam("motion.transform", cpp::CopiedData(xfms)); camera.setParam("shutter", range1f(1.0f - cameraMotionBlur, 1.0f)); camera.setParam("shutterType", cameraShutterType); camera.setParam("rollingShutterDuration", cameraRollingShutter); renderCameraMotionBlur = true; } else { camera.removeParam("motion.transform"); camera.setParam("transform", xfm); camera.setParam("shutter", range1f(0.5f)); } } void GLFWOSPRayWindow::motion(const vec2f &position) { const vec2f mouse(position.x, position.y); if (previousMouse != vec2f(-1)) { const bool leftDown = glfwGetMouseButton(glfwWindow, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS; const bool rightDown = glfwGetMouseButton(glfwWindow, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS; const bool middleDown = glfwGetMouseButton(glfwWindow, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS; const vec2f prev = previousMouse; bool cameraChanged = leftDown || rightDown || middleDown; if (leftDown) { const vec2f mouseFrom(clamp(prev.x * 2.f / windowSize.x - 1.f, -1.f, 1.f), clamp(prev.y * 2.f / windowSize.y - 1.f, -1.f, 1.f)); const vec2f mouseTo(clamp(mouse.x * 2.f / windowSize.x - 1.f, -1.f, 1.f), clamp(mouse.y * 2.f / windowSize.y - 1.f, -1.f, 1.f)); arcballCamera->rotate(mouseFrom, mouseTo); } else if (rightDown) { arcballCamera->zoom(mouse.y - prev.y); } else if (middleDown) { arcballCamera->pan(vec2f(mouse.x - prev.x, prev.y - mouse.y)); } if (cameraChanged) { if (cancelFrameOnInteraction) { currentFrame.cancel(); waitOnOSPRayFrame(); } updateCamera(); addObjectToCommit(camera.handle()); } } previousMouse = mouse; } void GLFWOSPRayWindow::display() { static float totalRenderTime = 0.f; static auto displayStart = std::chrono::steady_clock::now(); static bool firstFrame = true; if (firstFrame || currentFrame.isReady()) { // display frame rate in window title const auto displayEnd = std::chrono::steady_clock::now(); const auto displayMilliseconds = std::chrono::duration_cast( displayEnd - displayStart); const auto renderTime = currentFrame.duration(); totalRenderTime += renderTime; // update fps every 10 frames or every second framesCounter++; if (framesCounter > 9 || totalRenderTime > 1.f || displayMilliseconds > std::chrono::seconds(1)) { displayFPS = 1000.f * float(framesCounter) / displayMilliseconds.count(); latestFPS = float(framesCounter) / totalRenderTime; displayStart = displayEnd; totalRenderTime = 0.f; framesCounter = 0; updateTitleBar(); } waitOnOSPRayFrame(); auto fbChannel = OSP_FB_COLOR; if (showDepth) fbChannel = OSP_FB_DEPTH; if (showAlbedo) fbChannel = OSP_FB_ALBEDO; if (showPrimID) fbChannel = OSP_FB_ID_PRIMITIVE; if (showGeomID) fbChannel = OSP_FB_ID_OBJECT; if (showInstID) fbChannel = OSP_FB_ID_INSTANCE; auto *fb = framebuffer.map(fbChannel); // Copy and normalize depth layer if showDepth is on float *depthFb = static_cast(fb); std::vector depthCopy; if (showDepth) { depthCopy.assign(depthFb, depthFb + (windowSize.x * windowSize.y)); depthFb = depthCopy.data(); float minDepth = rkcommon::math::inf; float maxDepth = rkcommon::math::neg_inf; for (int i = 0; i < windowSize.x * windowSize.y; i++) { if (std::isinf(depthFb[i])) continue; minDepth = std::min(minDepth, depthFb[i]); maxDepth = std::max(maxDepth, depthFb[i]); } const float rcpDepthRange = 1.f / (maxDepth - minDepth); for (int i = 0; i < windowSize.x * windowSize.y; i++) { depthFb[i] = (depthFb[i] - minDepth) * rcpDepthRange; } } unsigned int *ids = static_cast(fb); std::vector idFbArray(windowSize.x * windowSize.y); float *idFb = reinterpret_cast(idFbArray.data()); if (showPrimID || showGeomID || showInstID) { for (int i = 0; i < windowSize.x * windowSize.y; i++) { const unsigned int id = ids[i]; idFbArray[i] = id == -1u ? vec3f(0.f) : rkcommon::utility::makeRandomColor(id); } } glBindTexture(GL_TEXTURE_2D, framebufferTexture); glTexImage2D(GL_TEXTURE_2D, 0, showDepth ? GL_DEPTH_COMPONENT : ((showAlbedo || showPrimID || showGeomID || showInstID) ? GL_RGB32F : GL_RGBA32F), windowSize.x, windowSize.y, 0, showDepth ? GL_DEPTH_COMPONENT : ((showAlbedo || showPrimID || showGeomID || showInstID) ? GL_RGB : GL_RGBA), GL_FLOAT, showDepth ? depthFb : ((showPrimID || showGeomID || showInstID) ? idFb : fb)); framebuffer.unmap(fb); commitOutstandingHandles(); startNewOSPRayFrame(); firstFrame = false; } glEnable(GL_FRAMEBUFFER_SRGB); // Turn on sRGB conversion for OSPRay frame glClear(GL_COLOR_BUFFER_BIT); // render textured quad with OSPRay frame buffer contents glBegin(GL_QUADS); glTexCoord2f(0.f, 0.f); glVertex2f(0.f, 0.f); glTexCoord2f(0.f, 1.f); glVertex2f(0.f, windowSize.y); glTexCoord2f(1.f, 1.f); glVertex2f(windowSize.x, windowSize.y); glTexCoord2f(1.f, 0.f); glVertex2f(windowSize.x, 0.f); glEnd(); } void GLFWOSPRayWindow::startNewOSPRayFrame() { if (updateFrameOpsNextFrame) { refreshFrameOperations(); updateFrameOpsNextFrame = false; } lastXfm = arcballCamera->transform(); currentFrame = framebuffer.renderFrame(*renderer, camera, world); if (renderCameraMotionBlur) { camera.removeParam("motion.transform"); camera.setParam("transform", lastXfm); addObjectToCommit(camera.handle()); renderCameraMotionBlur = false; } } void GLFWOSPRayWindow::waitOnOSPRayFrame() { currentFrame.wait(); } void GLFWOSPRayWindow::addObjectToCommit(OSPObject obj) { objectsToCommit.push_back(obj); } void GLFWOSPRayWindow::updateTitleBar() { std::stringstream windowTitle; windowTitle << "OSPRay: " << std::setprecision(4) << " render: " << latestFPS << " fps, app: " << displayFPS << " fps"; if (latestFPS > 0.f && latestFPS < 2.f) { float progress = currentFrame.progress(); windowTitle << " | "; int barWidth = 20; std::string progBar; progBar.resize(barWidth + 2); auto start = progBar.begin() + 1; auto end = start + progress * barWidth; std::fill(start, end, '='); std::fill(end, progBar.end(), '_'); *end = '>'; progBar.front() = '['; progBar.back() = ']'; windowTitle << progBar; } glfwSetWindowTitle(glfwWindow, windowTitle.str().c_str()); } void GLFWOSPRayWindow::buildUI() { ImGuiWindowFlags flags = ImGuiWindowFlags_AlwaysAutoResize; ImGui::Begin("press 'g' to hide/show UI", nullptr, flags); static int whichScene = 0; if (ImGui::Combo("scene##whichScene", &whichScene, vec_string_getter, (void *)&g_scenes, g_scenes.size())) { scene = g_scenes[whichScene]; refreshScene(true); } if (scene == "curves") { static int whichCurveVariant = 0; if (ImGui::Combo("curveVariant##whichCurveVariant", &whichCurveVariant, vec_string_getter, (void *)&g_curveVariant, g_curveVariant.size())) { curveVariant = g_curveVariant[whichCurveVariant]; refreshScene(true); } } if (scene == "unstructured_volume") { if (ImGui::Checkbox("show cells", &showUnstructuredCells)) refreshScene(true); } static int whichRenderer = 0; static int whichDebuggerType = 0; if (ImGui::Combo("renderer##whichRenderer", &whichRenderer, vec_string_getter, (void *)&g_renderers, g_renderers.size())) { rendererTypeStr = g_renderers[whichRenderer]; if (rendererType == OSPRayRendererType::DEBUGGER) whichDebuggerType = 0; // reset UI if switching away from debug renderer if (rendererTypeStr == "scivis") rendererType = OSPRayRendererType::SCIVIS; else if (rendererTypeStr == "pathtracer") rendererType = OSPRayRendererType::PATHTRACER; else if (rendererTypeStr == "ao") rendererType = OSPRayRendererType::AO; else if (rendererTypeStr == "debug") rendererType = OSPRayRendererType::DEBUGGER; else rendererType = OSPRayRendererType::OTHER; refreshScene(); } if (rendererType == OSPRayRendererType::DEBUGGER) { if (ImGui::Combo("debug type##whichDebugType", &whichDebuggerType, vec_string_getter, (void *)&g_debugRendererTypes, g_debugRendererTypes.size())) { renderer->setParam("method", g_debugRendererTypes[whichDebuggerType]); addObjectToCommit(renderer->handle()); } } ImGui::Checkbox("cancel frame on interaction", &cancelFrameOnInteraction); static int whichAOV = 0; if (ImGui::Combo("AOV Display##whichAOV", &whichAOV, vec_string_getter, (void *)&g_AOVs, g_AOVs.size())) { const auto &aovStr = g_AOVs[whichAOV]; showDepth = showAlbedo = showPrimID = showGeomID = showInstID = false; if (aovStr == "depth") showDepth = true; if (aovStr == "albedo") showAlbedo = true; if (aovStr == "primID") showPrimID = true; if (aovStr == "objID") showGeomID = true; if (aovStr == "instID") showInstID = true; } ImGui::Separator(); if (denoiserAvailable) { if (ImGui::Checkbox("denoiser", &denoiserEnabled)) updateFrameOpsNextFrame = true; } ImGui::Separator(); // the gaussian pixel filter is the default, // which is at position 2 in the list static int whichPixelFilter = 2; if (ImGui::Combo("pixelfilter##whichPixelFilter", &whichPixelFilter, vec_string_getter, (void *)&g_pixelFilterTypes, g_pixelFilterTypes.size())) { pixelFilterTypeStr = g_pixelFilterTypes[whichPixelFilter]; OSPPixelFilterType pixelFilterType = OSPPixelFilterType::OSP_PIXELFILTER_GAUSS; if (pixelFilterTypeStr == "point") pixelFilterType = OSPPixelFilterType::OSP_PIXELFILTER_POINT; else if (pixelFilterTypeStr == "box") pixelFilterType = OSPPixelFilterType::OSP_PIXELFILTER_BOX; else if (pixelFilterTypeStr == "gaussian") pixelFilterType = OSPPixelFilterType::OSP_PIXELFILTER_GAUSS; else if (pixelFilterTypeStr == "mitchell") pixelFilterType = OSPPixelFilterType::OSP_PIXELFILTER_MITCHELL; else if (pixelFilterTypeStr == "blackmanHarris") pixelFilterType = OSPPixelFilterType::OSP_PIXELFILTER_BLACKMAN_HARRIS; rendererPT.setParam("pixelFilter", pixelFilterType); rendererSV.setParam("pixelFilter", pixelFilterType); rendererAO.setParam("pixelFilter", pixelFilterType); rendererDBG.setParam("pixelFilter", pixelFilterType); addObjectToCommit(renderer->handle()); } ImGui::Separator(); static int spp = 1; if (ImGui::SliderInt("pixelSamples", &spp, 1, 64)) { rendererPT.setParam("pixelSamples", spp); rendererSV.setParam("pixelSamples", spp); rendererAO.setParam("pixelSamples", spp); rendererDBG.setParam("pixelSamples", spp); addObjectToCommit(renderer->handle()); } static float varianceThreshold = 0.0f; if (ImGui::SliderFloat("varianceThreshold", &varianceThreshold, 0.f, .5f)) { renderer->setParam("varianceThreshold", varianceThreshold); addObjectToCommit(renderer->handle()); } static vec3f bgColorSRGB{0.0f}; // imGUI's widget implicitly uses sRGB if (ImGui::ColorEdit3("backgroundColor", bgColorSRGB)) { bgColor = vec3f(std::pow(bgColorSRGB.x, 2.2f), std::pow(bgColorSRGB.y, 2.2f), std::pow(bgColorSRGB.z, 2.2f)); // approximate rendererPT.setParam("backgroundColor", bgColor); rendererSV.setParam("backgroundColor", bgColor); rendererAO.setParam("backgroundColor", bgColor); rendererDBG.setParam("backgroundColor", bgColor); addObjectToCommit(renderer->handle()); } static bool useTestTex = false; if (ImGui::Checkbox("backplate texture", &useTestTex)) { if (useTestTex) { rendererPT.setParam("map_backplate", backplateTex); rendererSV.setParam("map_backplate", backplateTex); rendererAO.setParam("map_backplate", backplateTex); rendererDBG.setParam("map_backplate", backplateTex); } else { rendererPT.removeParam("map_backplate"); rendererSV.removeParam("map_backplate"); rendererAO.removeParam("map_backplate"); rendererDBG.removeParam("map_backplate"); } addObjectToCommit(renderer->handle()); } if (ImGui::Checkbox("renderSunSky", &renderSunSky)) { if (renderSunSky) { sunSky.setParam("direction", sunDirection); world.setParam("light", cpp::CopiedData(sunSky)); addObjectToCommit(sunSky.handle()); } else { cpp::Light light("ambient"); light.setParam("visible", false); light.commit(); world.setParam("light", cpp::CopiedData(light)); } addObjectToCommit(world.handle()); } if (renderSunSky) { if (ImGui::DragFloat3("sunDirection", sunDirection, 0.01f, -1.f, 1.f)) { sunSky.setParam("direction", sunDirection); addObjectToCommit(sunSky.handle()); addObjectToCommit(world.handle()); } if (ImGui::DragFloat("turbidity", &turbidity, 0.1f, 1.f, 10.f)) { sunSky.setParam("turbidity", turbidity); addObjectToCommit(sunSky.handle()); addObjectToCommit(world.handle()); } if (ImGui::DragFloat( "horizonExtension", &horizonExtension, 0.01f, 0.f, 1.f)) { sunSky.setParam("horizonExtension", horizonExtension); addObjectToCommit(sunSky.handle()); addObjectToCommit(world.handle()); } } if (rendererType == OSPRayRendererType::PATHTRACER) { static int lightSamples = -1; if (ImGui::SliderInt("lightSamples", &lightSamples, -1, 32)) { renderer->setParam("lightSamples", lightSamples); addObjectToCommit(renderer->handle()); } static int maxDepth = 20; if (ImGui::SliderInt("maxPathLength", &maxDepth, 1, 64)) { renderer->setParam("maxPathLength", maxDepth); addObjectToCommit(renderer->handle()); } static int rouletteDepth = 1; if (ImGui::SliderInt("roulettePathLength", &rouletteDepth, 1, 64)) { renderer->setParam("roulettePathLength", rouletteDepth); addObjectToCommit(renderer->handle()); } static float minContribution = 0.001f; if (ImGui::SliderFloat("minContribution", &minContribution, 0.f, 1.f)) { renderer->setParam("minContribution", minContribution); addObjectToCommit(renderer->handle()); } static float maxContribution = 10000.f; if (ImGui::SliderFloat("maxContribution", &maxContribution, 0.f, 10000.f)) { renderer->setParam("maxContribution", maxContribution); addObjectToCommit(renderer->handle()); } if (ImGui::SliderFloat("camera motion blur", &cameraMotionBlur, 0.f, 1.f)) { updateCamera(); addObjectToCommit(camera.handle()); } if (cameraMotionBlur > 0.0f) { static const char *cameraShutterTypes[] = {"global", "rolling right", "rolling left", "rolling down", "rolling up"}; if (ImGui::BeginCombo("shutterType##cameraShutterType", cameraShutterTypes[cameraShutterType])) { for (uint32_t n = 0; n < 5; n++) { bool is_selected = (cameraShutterType == n); if (ImGui::Selectable(cameraShutterTypes[n], is_selected)) cameraShutterType = (OSPShutterType)n; if (is_selected) ImGui::SetItemDefaultFocus(); } ImGui::EndCombo(); } updateCamera(); addObjectToCommit(camera.handle()); } if (cameraShutterType != OSP_SHUTTER_GLOBAL && ImGui::SliderFloat( "rollingShutterDuration", &cameraRollingShutter, 0.f, 1.0f)) { updateCamera(); addObjectToCommit(camera.handle()); } } else if (rendererType == OSPRayRendererType::SCIVIS) { static bool shadowsEnabled = false; if (ImGui::Checkbox("shadows", &shadowsEnabled)) { renderer->setParam("shadows", shadowsEnabled); addObjectToCommit(renderer->handle()); } static bool visibleLights = false; if (ImGui::Checkbox("visibleLights", &visibleLights)) { renderer->setParam("visibleLights", visibleLights); addObjectToCommit(renderer->handle()); } static int aoSamples = 0; if (ImGui::SliderInt("aoSamples", &aoSamples, 0, 64)) { renderer->setParam("aoSamples", aoSamples); addObjectToCommit(renderer->handle()); } static float samplingRate = 1.f; if (ImGui::SliderFloat("volumeSamplingRate", &samplingRate, 0.001f, 2.f)) { renderer->setParam("volumeSamplingRate", samplingRate); addObjectToCommit(renderer->handle()); } } else if (rendererType == OSPRayRendererType::AO) { static int aoSamples = 1; if (ImGui::SliderInt("aoSamples", &aoSamples, 0, 64)) { renderer->setParam("aoSamples", aoSamples); addObjectToCommit(renderer->handle()); } static float aoIntensity = 1.f; if (ImGui::SliderFloat("aoIntensity", &aoIntensity, 0.f, 1.f)) { renderer->setParam("aoIntensity", aoIntensity); addObjectToCommit(renderer->handle()); } static float samplingRate = 1.f; if (ImGui::SliderFloat("volumeSamplingRate", &samplingRate, 0.001f, 2.f)) { renderer->setParam("volumeSamplingRate", samplingRate); addObjectToCommit(renderer->handle()); } } static const char *cameraStereoModes[] = { "none", "left", "right", "side-by-side", "top/bottom"}; if (ImGui::BeginCombo("camera stereoMode##cameraStereoMode", cameraStereoModes[cameraStereoMode])) { for (uint32_t n = 0; n < 5; n++) { bool is_selected = (cameraStereoMode == n); if (ImGui::Selectable(cameraStereoModes[n], is_selected)) cameraStereoMode = (OSPStereoMode)n; if (is_selected) ImGui::SetItemDefaultFocus(); } ImGui::EndCombo(); updateCamera(); addObjectToCommit(camera.handle()); } if (uiCallback) { ImGui::Separator(); uiCallback(); } ImGui::End(); } void GLFWOSPRayWindow::commitOutstandingHandles() { auto handles = objectsToCommit.consume(); if (!handles.empty()) { for (auto &h : handles) ospCommit(h); framebuffer.resetAccumulation(); } } void GLFWOSPRayWindow::refreshScene(bool resetCamera) { auto builder = testing::newBuilder(scene); testing::setParam(builder, "rendererType", rendererTypeStr); if (scene == "curves") { testing::setParam(builder, "curveVariant", curveVariant); } else if (scene == "unstructured_volume") { testing::setParam(builder, "showCells", showUnstructuredCells); } testing::commit(builder); world = testing::buildWorld(builder); testing::release(builder); switch (rendererType) { case OSPRayRendererType::PATHTRACER: { renderer = &rendererPT; if (renderSunSky) world.setParam("light", cpp::CopiedData(sunSky)); break; } case OSPRayRendererType::SCIVIS: renderer = &rendererSV; break; case OSPRayRendererType::AO: renderer = &rendererAO; break; case OSPRayRendererType::DEBUGGER: renderer = &rendererDBG; break; default: throw std::runtime_error("invalid renderer chosen!"); } // retains a set background color on renderer change renderer->setParam("backgroundColor", bgColor); addObjectToCommit(renderer->handle()); world.commit(); if (resetCamera) { // create the arcball camera model arcballCamera.reset( new ArcballCamera(world.getBounds(), windowSize)); lastXfm = arcballCamera->transform(); // init camera camera.setParam("position", vec3f(0.0f, 0.0f, 1.0f)); updateCamera(); camera.commit(); } } void GLFWOSPRayWindow::refreshFrameOperations() { if (denoiserEnabled) { cpp::ImageOperation d("denoiser"); framebuffer.setParam("imageOperation", cpp::CopiedData(d)); } else { framebuffer.removeParam("imageOperation"); } framebuffer.commit(); } RenderKit-ospray-f2a61c2/apps/ospExamples/GLFWOSPRayWindow.h000066400000000000000000000064341456566705700237570ustar00rootroot00000000000000// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ArcballCamera.h" // glfw #include "GLFW/glfw3.h" // ospray #include "ospray/ospray_cpp.h" #include "rkcommon/containers/TransactionalBuffer.h" // std #include using namespace rkcommon::math; using namespace ospray; enum class OSPRayRendererType { SCIVIS, PATHTRACER, AO, DEBUGGER, OTHER }; class GLFWOSPRayWindow { public: GLFWOSPRayWindow(const vec2i &windowSize, bool denoiser = false); ~GLFWOSPRayWindow(); static GLFWOSPRayWindow *getActiveWindow(); void mainLoop(); protected: void addObjectToCommit(OSPObject obj); void updateCamera(); void reshape(const vec2i &newWindowSize); void motion(const vec2f &position); void display(); void startNewOSPRayFrame(); void waitOnOSPRayFrame(); void updateTitleBar(); void buildUI(); void commitOutstandingHandles(); void refreshScene(bool resetCamera = false); void refreshFrameOperations(); static GLFWOSPRayWindow *activeWindow; vec2i windowSize; vec2f previousMouse{-1.f}; bool denoiserAvailable{false}; bool updateFrameOpsNextFrame{false}; bool denoiserEnabled{false}; bool showAlbedo{false}; bool showDepth{false}; bool showPrimID{false}; bool showGeomID{false}; bool showInstID{false}; bool renderSunSky{false}; bool cancelFrameOnInteraction{false}; bool showUnstructuredCells{false}; // GLFW window instance GLFWwindow *glfwWindow = nullptr; // Arcball camera instance std::unique_ptr arcballCamera; affine3f lastXfm{one}; OSPStereoMode cameraStereoMode{OSP_STEREO_NONE}; float cameraMotionBlur{0.0f}; float cameraRollingShutter{0.0f}; OSPShutterType cameraShutterType{OSP_SHUTTER_GLOBAL}; // only one frame during movement is rendered with MB, // during accumulation the camera is static and thus no MB bool renderCameraMotionBlur{false}; // OSPRay objects managed by this class cpp::Renderer rendererPT{"pathtracer"}; cpp::Renderer rendererSV{"scivis"}; cpp::Renderer rendererAO{"ao"}; cpp::Renderer rendererDBG{"debug"}; cpp::Renderer *renderer{nullptr}; cpp::Camera camera{"perspective"}; cpp::World world; cpp::Light sunSky{"sunSky"}; cpp::FrameBuffer framebuffer; cpp::Future currentFrame; cpp::Texture backplateTex{"texture2d"}; vec3f bgColor{0.f}; vec3f sunDirection{-0.25f, -1.0f, 0.0f}; float turbidity{3.f}; float horizonExtension{0.1f}; std::string scene{"boxes_lit"}; std::string curveVariant{"bspline"}; OSPRayRendererType rendererType{OSPRayRendererType::SCIVIS}; std::string rendererTypeStr{"scivis"}; std::string pixelFilterTypeStr{"gaussian"}; // List of OSPRay handles to commit before the next frame rkcommon::containers::TransactionalBuffer objectsToCommit; // OpenGL framebuffer texture GLuint framebufferTexture = 0; // optional registered display callback, called before every display() std::function displayCallback; // toggles display of ImGui UI, if an ImGui callback is provided bool showUi = true; // optional registered ImGui callback, called during every frame to build UI std::function uiCallback; // FPS measurement of last frame uint32_t framesCounter{0}; float latestFPS{0.f}; float displayFPS{0.f}; }; RenderKit-ospray-f2a61c2/apps/ospExamples/example_common.h000066400000000000000000000030241456566705700237650ustar00rootroot00000000000000// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray #include "ospray/ospray.h" // std #include #include inline void initializeOSPRay( int argc, const char **argv, bool errorsFatal = true) { // initialize OSPRay; OSPRay parses (and removes) its commandline parameters, // e.g. "--osp:debug" OSPError initError = ospInit(&argc, argv); if (initError != OSP_NO_ERROR) throw std::runtime_error("OSPRay not initialized correctly!"); OSPDevice device = ospGetCurrentDevice(); if (!device) throw std::runtime_error("OSPRay device could not be fetched!"); // set an error callback to catch any OSPRay errors and exit the application if (errorsFatal) { ospDeviceSetErrorCallback( device, [](void *, OSPError error, const char *errorDetails) { std::cerr << "OSPRay error: " << errorDetails << std::endl; exit(error); }, nullptr); } else { ospDeviceSetErrorCallback( device, [](void *, OSPError, const char *errorDetails) { std::cerr << "OSPRay error: " << errorDetails << std::endl; }, nullptr); } ospDeviceSetStatusCallback( device, [](void *, const char *msg) { std::cout << msg; }, nullptr); bool warnAsErrors = true; auto logLevel = OSP_LOG_WARNING; ospDeviceSetParam(device, "warnAsError", OSP_BOOL, &warnAsErrors); ospDeviceSetParam(device, "logLevel", OSP_UINT, &logLevel); ospDeviceCommit(device); ospDeviceRelease(device); } RenderKit-ospray-f2a61c2/apps/ospExamples/ospExample.cpp000066400000000000000000000010041456566705700234260ustar00rootroot00000000000000// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "GLFWOSPRayWindow.h" #include "example_common.h" using namespace ospray; using rkcommon::make_unique; int main(int argc, const char *argv[]) { initializeOSPRay(argc, argv, false); bool denoiser = ospLoadModule("denoiser") == OSP_NO_ERROR; auto glfwOSPRayWindow = make_unique(vec2i(1024, 768), denoiser); glfwOSPRayWindow->mainLoop(); glfwOSPRayWindow.reset(); ospShutdown(); return 0; } RenderKit-ospray-f2a61c2/apps/ospTestSuite/000077500000000000000000000000001456566705700207655ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/ospTestSuite/CMakeLists.txt000066400000000000000000000034701456566705700235310ustar00rootroot00000000000000## Copyright 2017 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 if (NOT OSPRAY_ENABLE_APPS_TESTING) return() endif() # Note: CMake provides FindGTest which defines target GTest::GTest find_package(GTest REQUIRED CONFIG) ospray_disable_compiler_warnings() add_library(ospray_gtest_utils environment.cpp test_tools.cpp test_fixture.cpp ) target_link_libraries(ospray_gtest_utils PUBLIC arcball_camera ospray_testing GTest::gtest stb_image ) target_include_directories(ospray_gtest_utils PUBLIC $ ) if (OSPRAY_ENABLE_VOLUMES) # We need to know if volumes are enabled at compile time so that # we can enable/disable the VKL-dependent tests for enum values target_compile_definitions(ospray_gtest_utils PUBLIC -DOSPRAY_ENABLE_VOLUMES ) endif() add_executable(ospTestSuite ${OSPRAY_RESOURCE} environment.cpp # potentially compile with SYCL, overriding non-SYCL ospray_gtest_utils test_geometry.cpp test_volumetric.cpp test_appearance.cpp test_assigned_data.cpp test_sharedusm_data.cpp test_light.cpp test_enums.cpp $<$:test_glm_compat.cpp> test_camera.cpp test_motionblur.cpp test_framebuffer.cpp test_interpolation.cpp test_imageop.cpp ospTestSuite.cpp ) target_link_libraries(ospTestSuite PRIVATE ospray_testing ospray_gtest_utils embree $<$:openvkl::openvkl> $<$:${GLM_TARGET}> ) if (OSPRAY_MODULE_GPU) ospray_add_sycl_target(ospTestSuite) endif() if (OSPRAY_MODULE_DENOISER) # Enable OIDN tests target_compile_definitions(ospTestSuite PUBLIC -DOSPRAY_MODULE_DENOISER ) endif() ospray_sign_target(ospTestSuite) install(TARGETS ospTestSuite DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT apps ) RenderKit-ospray-f2a61c2/apps/ospTestSuite/environment.cpp000066400000000000000000000055631456566705700240460ustar00rootroot00000000000000// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "environment.h" #ifdef SYCL_LANGUAGE_VERSION #include "sycl/sycl.hpp" #endif OSPRayEnvironment::OSPRayEnvironment(int argc, char **argv) { ParseArgs(argc, argv); } void OSPRayEnvironment::ParseArgs(int argc, char **argv) { std::vector testArgs; for (int idx = 0; idx < argc; ++idx) { testArgs.push_back(argv[idx]); } for (size_t idx = 0; idx < testArgs.size(); ++idx) { if (testArgs.at(idx) == "--help") { std::cout << "--help : display this help msg\n" << "--dump-img : dump the rendered image to file\n" << "--imgsize-x=XX : change the length of an image\n" << "--imgsize-y=XX : change the height of an image\n" << "--renderer-type=XX : change the renderer used for tests\n" << "--baseline-dir=XX : Change the directory used for baseline " "images during tests\n" << "--own-SYCL : turn on SYCL data sharing.\n"; std::exit(EXIT_SUCCESS); } else if (testArgs.at(idx) == "--dump-img") { dumpImg = true; } else if (testArgs.at(idx).find("--renderer-type=") == 0) { rendererType = GetStrArgValue(&testArgs.at(idx)); } else if (testArgs.at(idx).find("--imgsize-x=") == 0) { imgSize.x = GetNumArgValue(&testArgs.at(idx)); } else if (testArgs.at(idx).find("--imgsize-y=") == 0) { imgSize.y = GetNumArgValue(&testArgs.at(idx)); } else if (testArgs.at(idx).find("--baseline-dir=") == 0) { baselineDir = GetStrArgValue(&testArgs.at(idx)); } else if (testArgs.at(idx).find("--failed-dir=") == 0) { failedDir = GetStrArgValue(&testArgs.at(idx)); } else if (testArgs.at(idx).find("--own-SYCL") == 0) { #ifdef SYCL_LANGUAGE_VERSION ownSYCL = true; #else std::cerr << "WARNING: Compiled without SYCL support, " "SYCL data sharing not supported." << std::endl; #endif } } } int OSPRayEnvironment::GetNumArgValue(std::string *arg) const { int ret = 0; size_t valueStartPos = arg->find_first_of('='); if (valueStartPos != std::string::npos) { ret = std::stoi(arg->substr(valueStartPos + 1)); if (ret <= 0) { std::cout << "Incorrect value specified for argument %s " << *arg << std::endl << std::flush; } } return ret; } std::string OSPRayEnvironment::GetStrArgValue(std::string *arg) const { std::string ret; size_t valueStartPos = arg->find_first_of('='); if (valueStartPos != std::string::npos) { ret = arg->substr(valueStartPos + 1); } return ret; } #ifdef SYCL_LANGUAGE_VERSION OSPRayEnvironment::~OSPRayEnvironment() { delete appsSyclQueue; } sycl::queue *OSPRayEnvironment::GetAppsSyclQueue() { if (ownSYCL && !appsSyclQueue) appsSyclQueue = new sycl::queue; return appsSyclQueue; } #endif RenderKit-ospray-f2a61c2/apps/ospTestSuite/environment.h000066400000000000000000000025351456566705700235070ustar00rootroot00000000000000// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include #include "ospray/ospray_cpp.h" #include "ospray/ospray_cpp/ext/rkcommon.h" using namespace ospray; using namespace rkcommon::math; namespace sycl { inline namespace _V1 { class queue; } } // namespace sycl class OSPRayEnvironment : public ::testing::Environment { public: OSPRayEnvironment(int argc, char **argv); ~OSPRayEnvironment() #ifndef SYCL_LANGUAGE_VERSION = default #endif ; bool GetDumpImg() const { return dumpImg; } std::string GetRendererType() const { return rendererType; } vec2i GetImgSize() const { return imgSize; } std::string GetBaselineDir() const { return baselineDir; } std::string GetFailedDir() const { return failedDir; } #ifdef SYCL_LANGUAGE_VERSION sycl::queue *GetAppsSyclQueue(); #endif void ParseArgs(int argc, char **argv); std::string GetStrArgValue(std::string *arg) const; int GetNumArgValue(std::string *arg) const; private: bool dumpImg{false}; std::string rendererType{"scivis"}; std::string baselineDir{"regression_test_baseline"}; std::string failedDir{false}; vec2i imgSize{1024, 768}; bool ownSYCL{false}; #ifdef SYCL_LANGUAGE_VERSION sycl::queue *appsSyclQueue{nullptr}; #endif }; RenderKit-ospray-f2a61c2/apps/ospTestSuite/ospTestSuite.cpp000066400000000000000000000034411456566705700241460ustar00rootroot00000000000000// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_fixture.h" #ifdef SYCL_LANGUAGE_VERSION #include "sycl/sycl.hpp" #endif OSPRayEnvironment *ospEnv; int main(int argc, char **argv) { { // Check to make sure these functions work without a currently set device std::cout << "Verify device API usage prior to ospInit()..." << std::endl; auto d = ospGetCurrentDevice(); ospDeviceRetain(d); ospDeviceRelease(d); std::cout << "...done!" << std::endl; } ospInit(&argc, (const char **)argv); ::testing::InitGoogleTest(&argc, argv); ospEnv = new OSPRayEnvironment(argc, argv); AddGlobalTestEnvironment(ospEnv); { cpp::Device device = cpp::Device::current(); #ifdef SYCL_LANGUAGE_VERSION sycl::queue *appsSyclQueue = ospEnv->GetAppsSyclQueue(); if (appsSyclQueue) { static auto appsSyclContext = appsSyclQueue->get_context(); static auto appsSyclDevice = appsSyclQueue->get_device(); device.setParam("syclContext", OSP_VOID_PTR, (void *)&appsSyclContext); device.setParam("syclDevice", OSP_VOID_PTR, (void *)&appsSyclDevice); } #endif device.setErrorCallback( [](void *, OSPError error, const char *errorDetails) { std::cerr << "OSPRay error: " << errorDetails << std::endl; std::exit(EXIT_FAILURE); }); device.setStatusCallback([](void *, const char *msg) { std::cout << msg; }); // First commit with INFO log Level to output device info string device.setParam("warnAsError", true); device.setParam("logLevel", OSP_LOG_INFO); device.commit(); // Then use WARNING log level for tests execution device.setParam("logLevel", OSP_LOG_WARNING); device.commit(); } auto result = RUN_ALL_TESTS(); ospShutdown(); return result; } RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_appearance.cpp000066400000000000000000000370721456566705700246400ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_appearance.h" #include "ArcballCamera.h" #include "rkcommon/utility/multidim_index_sequence.h" namespace OSPRayTestScenes { Texture2D::Texture2D() { rendererType = "pathtracer"; samplesPerPixel = 64; } void Texture2D::SetUp() { Base::SetUp(); camera.setParam("position", vec3f(4.f, 3.f, 0.f)); // flip image to have origin in upper left corner, plus mirror camera.setParam("imageStart", vec2f(1.f, 1.f)); camera.setParam("imageEnd", vec2f(0.f, 0.f)); auto params = GetParam(); OSPTextureFilter filter = std::get<0>(params); // create (4*2) x 4 grid constexpr int cols = 8; constexpr int rows = 4; std::vector vertex; std::vector texcoord; std::vector index; rkcommon::index_sequence_2D iidx(vec2i(cols, rows)); // Generate each quad, each needs its own vertex coordinates w/ unique // texcoords when we're testing w/ texture coordinates on for (auto i : iidx) { const int idx_start = vertex.size(); vertex.push_back(vec3f(i.x, i.y * 1.5f, 5.3f)); vertex.push_back(vec3f(i.x + 1.f, i.y * 1.5f, 5.3f)); vertex.push_back(vec3f(i.x + 1.f, (i.y + 1.f) * 1.5f, 5.3f)); vertex.push_back(vec3f(i.x, (i.y + 1.f) * 1.5f, 5.3f)); texcoord.push_back(vec2f(0.f, 0.f)); texcoord.push_back(vec2f(1.f, 0.f)); texcoord.push_back(vec2f(1.f, 1.f)); texcoord.push_back(vec2f(0.f, 1.f)); index.push_back( vec4ui(idx_start, idx_start + 1, idx_start + 2, idx_start + 3)); } cpp::Geometry mesh("mesh"); mesh.setParam("vertex.position", cpp::CopiedData(vertex)); if (std::get<2>(params)) { mesh.setParam("vertex.texcoord", cpp::CopiedData(texcoord)); } mesh.setParam("index", cpp::CopiedData(index)); mesh.commit(); // create textures: columns=#channels, rows=type=[byte, byte, float, short] std::array format = {OSP_TEXTURE_R8, OSP_TEXTURE_RA8, OSP_TEXTURE_RGB8, OSP_TEXTURE_RGBA8, OSP_TEXTURE_L8, OSP_TEXTURE_LA8, OSP_TEXTURE_SRGB, OSP_TEXTURE_SRGBA, OSP_TEXTURE_R32F, OSP_TEXTURE_R32F, OSP_TEXTURE_RGB32F, OSP_TEXTURE_RGBA32F, OSP_TEXTURE_R16, OSP_TEXTURE_RA16, OSP_TEXTURE_RGB16, OSP_TEXTURE_RGBA16}; std::array eltype = {OSP_UCHAR, OSP_VEC2UC, OSP_VEC3UC, OSP_VEC4UC, OSP_UCHAR, OSP_VEC2UC, OSP_VEC3UC, OSP_VEC4UC, OSP_FLOAT, OSP_FLOAT, OSP_VEC3F, OSP_VEC4F, OSP_USHORT, OSP_VEC2US, OSP_VEC3US, OSP_VEC4US}; std::array dbyte; std::array dshort; std::array dfloat; rkcommon::index_sequence_2D didx(vec2i(3, 5)); for (auto idx : didx) { auto i = didx.flatten(idx); // the center texel should be 127 / 32767 / 0.5, to test normal maps dbyte[i] = vec4uc(idx.x * 85 + 42, idx.y * 50 + 27, 155, i * 17 + 8); dshort[i] = vec4us( idx.x * 22768 + 9999, idx.y * 13000 + 6767, 33000, i * 4400 + 2200); dfloat[i] = vec4f(idx.x * 0.3125f + 0.1875f, idx.y * 0.21875f + 0.0625f, 0.8f, i * 0.06f + 0.15f); } std::array addr = { dbyte.data(), dbyte.data(), dfloat.data(), dshort.data()}; std::array stride = {4, 4, 16, 8}; cpp::GeometricModel model(mesh); std::array material; for (auto idx : iidx) { auto i = iidx.flatten(idx); auto fmt = format[i / 2]; auto eltp = eltype[i / 2]; cpp::Texture tex("texture2d"); tex.setParam("format", fmt); tex.setParam("filter", filter); auto tmp = ospNewSharedData(addr[idx.y], eltp, 3, stride[idx.y], 5); auto data = ospNewData(eltp, 3, 5); ospCopyData(tmp, data); ospRelease(tmp); tex.setParam("data", data); tex.commit(); ospRelease(data); cpp::Material mat("obj"); mat.setParam("kd", vec3f(0.8)); mat.setParam(i & 1 ? "map_bump" : "map_kd", tex); mat.commit(); material[i] = mat; } model.setParam("material", cpp::CopiedData(material)); AddModel(model); { // set up backplate texture std::array bpdata; bool toggle = false; for (auto &el : bpdata) { el = toggle ? vec3uc(5, 10, 5) : vec3uc(10, 5, 10); toggle = !toggle; } cpp::CopiedData texData(bpdata.data(), vec2ul(125, 94)); cpp::Texture backplateTex("texture2d"); backplateTex.setParam("format", OSP_TEXTURE_RGB8); backplateTex.setParam("filter", OSP_TEXTURE_FILTER_NEAREST); backplateTex.setParam("data", texData); backplateTex.commit(); renderer.setParam("map_backplate", backplateTex); } cpp::Light light1("distant"); cpp::Light light2("distant"); // two light sets if (std::get<1>(params)) { // default light light1.setParam("intensity", 3.f); // highlighting normal direction light2.setParam("direction", vec3f(0.7f, 0.2f, 0.f)); light2.setParam("color", vec3f(0.f, 0.f, 0.5f)); } else { // perpendicular bright lights, testing center normal light1.setParam("direction", vec3f(0.5f, -1.f, 0.f)); light1.setParam("color", vec3f(999.f, 0.f, 0.0f)); light2.setParam("direction", vec3f(-0.5f, 1.f, 0.f)); light2.setParam("color", vec3f(0.f, 999.f, 0.0f)); } AddLight(light1); AddLight(light2); } static cpp::Texture createTexture2D(uint32_t width = 32, uint32_t height = 32, vec2ui wrapMode = vec2ui(OSP_TEXTURE_WRAP_REPEAT), OSPTextureFilter filter = OSP_TEXTURE_FILTER_LINEAR) { // Prepare texel data std::vector dbyte(width * height); rkcommon::index_sequence_2D idx(vec2i(width, height)); for (auto i : idx) dbyte[idx.flatten(i)] = vec3uc(i.x * (256 / width), i.y * (256 / height), i.x * (256 / width)); // Create texture object cpp::Texture tex("texture2d"); tex.setParam("format", OSP_TEXTURE_RGB8); tex.setParam("filter", filter); tex.setParam("wrapMode", wrapMode); tex.setParam("data", cpp::CopiedData(dbyte.data(), vec2ul(width, height))); tex.commit(); return tex; } static cpp::Geometry createQuads( const int cols, const int rows, const float gap, const bool withTC = false) { cpp::Geometry quads("mesh"); { // Create quads data std::vector position(4 * cols * rows); rkcommon::index_sequence_2D idx(vec2i(cols, rows)); for (auto i : idx) { auto l = static_cast(i) * gap; auto u = l + (.75f * gap); position[4 * idx.flatten(i) + 0] = vec3f(l.x, l.y, 0.f); position[4 * idx.flatten(i) + 1] = vec3f(l.x, u.y, 0.f); position[4 * idx.flatten(i) + 2] = vec3f(u.x, u.y, 0.f); position[4 * idx.flatten(i) + 3] = vec3f(u.x, l.y, 0.f); } // Set quads parameters quads.setParam( "vertex.position", cpp::CopiedData(position.data(), 4 * cols * rows)); if (withTC) { std::vector texcoord(4 * cols * rows); for (auto i : idx) { texcoord[4 * idx.flatten(i) + 0] = vec2f(-1.f, -1.f); texcoord[4 * idx.flatten(i) + 1] = vec2f(-1.f, 3.f); texcoord[4 * idx.flatten(i) + 2] = vec2f(3.f, 3.f); texcoord[4 * idx.flatten(i) + 3] = vec2f(3.f, -1.f); } quads.setParam( "vertex.texcoord", cpp::CopiedData(texcoord.data(), 4 * cols * rows)); } quads.setParam("quadSoup", true); quads.commit(); } return quads; } Texture2DTransform::Texture2DTransform() { rendererType = GetParam(); } void Texture2DTransform::SetUp() { Base::SetUp(); camera.setParam("position", vec3f(4.f, 4.f, -10.f)); camera.setParam("direction", vec3f(0.f, 0.f, 1.f)); camera.setParam("up", vec3f(0.f, 1.f, 0.f)); // Create quad geometry constexpr int cols = 2; constexpr int rows = 2; cpp::Geometry quads = createQuads(cols, rows, 5.f); // Create materials std::array materials; cpp::Texture tex = createTexture2D(); for (int i = 0; i < cols * rows; i++) { cpp::Material mat("obj"); mat.setParam("map_kd", tex); mat.commit(); materials[i] = mat; } // Set scale materials[1].setParam("map_kd.scale", vec2f(.5f)); materials[1].commit(); // Set rotation materials[2].setParam("map_kd.rotation", 45.f); materials[2].commit(); // Set translation materials[3].setParam("map_kd.translation", vec2f(.5f)); materials[3].commit(); // Create geometric model cpp::GeometricModel model(quads); model.setParam("material", cpp::CopiedData(materials)); AddModel(model); cpp::Light ambient("ambient"); ambient.setParam("intensity", 0.5f); AddLight(ambient); } Texture2DWrapMode::Texture2DWrapMode() { rendererType = "scivis"; filter = GetParam(); } void Texture2DWrapMode::SetUp() { Base::SetUp(); camera.setParam("position", vec3f(4.f, 4.f, -8.f)); camera.setParam("direction", vec3f(0.f, 0.f, 1.f)); camera.setParam("up", vec3f(0.f, 1.f, 0.f)); // Create quad geometry constexpr int cols = 3; constexpr int rows = 3; cpp::Geometry quads = createQuads(cols, rows, 3.f, true); // Create materials std::array materials; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { cpp::Texture tex = createTexture2D(4, 4, vec2ui(j, i), filter); cpp::Material mat("obj"); mat.setParam("map_kd", tex); mat.commit(); materials[(i * cols) + j] = mat; } } // Create geometric model cpp::GeometricModel model(quads); model.setParam("material", cpp::CopiedData(materials)); AddModel(model); cpp::Light ambient("ambient"); ambient.setParam("intensity", 0.5f); AddLight(ambient); } RendererMaterialList::RendererMaterialList() { rendererType = GetParam(); } void RendererMaterialList::SetUp() { Base::SetUp(); // Setup geometry // cpp::Geometry sphereGeometry("sphere"); constexpr int dimSize = 3; rkcommon::index_sequence_2D numSpheres(dimSize); std::vector spheres; std::vector index; std::vector materials; auto makeObjMaterial = [](vec3f Kd, vec3f Ks) -> cpp::Material { cpp::Material mat("obj"); mat.setParam("kd", Kd); mat.setParam("ks", Ks); mat.commit(); return mat; }; for (auto i : numSpheres) { auto i_f = static_cast(i); spheres.emplace_back(i_f.x, i_f.y, 0.f); auto l = i_f / (dimSize - 1); materials.push_back( makeObjMaterial(lerp(l.x, vec3f(0.1f), vec3f(0.f, 0.f, 1.f)), lerp(l.y, vec3f(0.f), vec3f(1.f)))); index.push_back(static_cast(numSpheres.flatten(i))); } sphereGeometry.setParam("sphere.position", cpp::CopiedData(spheres)); sphereGeometry.setParam("radius", 0.4f); sphereGeometry.commit(); cpp::GeometricModel model(sphereGeometry); model.setParam("material", cpp::CopiedData(index)); AddModel(model); // Setup renderer material list // renderer.setParam("material", cpp::CopiedData(materials)); // Create the world to get bounds for camera setup // if (!instances.empty()) world.setParam("instance", cpp::CopiedData(instances)); instances.clear(); world.commit(); auto worldBounds = world.getBounds(); ArcballCamera arcballCamera(worldBounds, imgSize); camera.setParam("position", arcballCamera.eyePos()); camera.setParam("direction", arcballCamera.lookDir()); camera.setParam("up", arcballCamera.upDir()); // Setup lights // cpp::Light ambient("ambient"); ambient.setParam("intensity", 0.5f); AddLight(ambient); } PTBackgroundRefraction::PTBackgroundRefraction() { rendererType = "pathtracer"; samplesPerPixel = 64; } void PTBackgroundRefraction::SetUp() { bool backgroundRefraction = GetParam(); Base::SetUp(); // Setup geometry // cpp::Geometry boxGeometry("box"); rkcommon::index_sequence_3D numBoxes(vec3i(2, 2, 1)); std::vector boxes; for (auto i : numBoxes) { auto f3 = static_cast(i); auto lower = f3 * vec3f(1.5f, 1.5f, 0.0f) + vec3f(-1.25f, -1.25f, 2.5f); auto upper = lower + vec3f(1.f, 1.f, 0.27f); boxes.emplace_back(lower, upper); } boxGeometry.setParam("box", cpp::CopiedData(boxes)); boxGeometry.commit(); cpp::GeometricModel model(boxGeometry); std::vector materials; materials.emplace_back(cpp::Material("thinGlass")); materials.emplace_back(cpp::Material("glass")); materials.emplace_back(cpp::Material("glass")); materials.back().setParam("eta", 1.2f); materials.emplace_back(cpp::Material("obj")); materials.back().setParam("d", 0.2f); materials.back().setParam("kd", vec3f(0.7f, 0.5f, 0.1f)); for (auto &m : materials) m.commit(); model.setParam("material", cpp::CopiedData(materials)); AddModel(model); renderer.setParam("backgroundRefraction", backgroundRefraction); { // set up backplate texture std::vector bpdata; bpdata.push_back(vec4uc(199, 60, 10, 255)); bpdata.push_back(vec4uc(60, 199, 40, 255)); bpdata.push_back(vec4uc(80, 40, 199, 255)); bpdata.push_back(vec4uc(99, 10, 99, 255)); cpp::CopiedData texData(bpdata.data(), vec2ul(2, 2)); cpp::Texture backplateTex("texture2d"); backplateTex.setParam("format", OSP_TEXTURE_RGBA8); backplateTex.setParam("data", texData); backplateTex.commit(); renderer.setParam("map_backplate", backplateTex); } cpp::Light light("sunSky"); light.setParam("turbidity", 8.0f); light.setParam("intensity", 0.005f); AddLight(light); cpp::Light mirrorlight("sunSky"); mirrorlight.setParam("up", vec3f(0.0f, -1.0f, 0.0f)); AddLight(mirrorlight); } // Test Instantiations ////////////////////////////////////////////////////// INSTANTIATE_TEST_SUITE_P(Transparency, FromOsprayTesting, ::testing::Combine(::testing::Values("transparency"), ::testing::Values("scivis", "pathtracer", "ao"), ::testing::Values(16))); TEST_P(RendererMaterialList, material_list) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(MaterialLists, RendererMaterialList, ::testing::Values("scivis", "pathtracer")); INSTANTIATE_TEST_SUITE_P(TestScenesPtMaterials, FromOsprayTesting, ::testing::Combine(::testing::Values("test_pt_alloy_roughness", "test_pt_carpaint", "test_pt_glass", "test_pt_thinglass", "test_pt_luminous", "test_pt_material_tex", "test_pt_metal_roughness", "test_pt_metallic_flakes", "test_pt_mix_tex", "test_pt_obj", "test_pt_plastic", "test_pt_principled_metal", "test_pt_principled_plastic", "test_pt_principled_glass", "test_pt_principled_tex", "test_pt_velvet"), ::testing::Values("pathtracer"), ::testing::Values(64))); TEST_P(Texture2D, filter) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Appearance, Texture2D, ::testing::Combine(::testing::Values(OSP_TEXTURE_FILTER_LINEAR, OSP_TEXTURE_FILTER_NEAREST), ::testing::Bool(), ::testing::Bool())); TEST_P(Texture2DTransform, simple) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P( Appearance, Texture2DTransform, ::testing::Values("scivis")); TEST_P(Texture2DWrapMode, wrap) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Appearance, Texture2DWrapMode, ::testing::Values(OSP_TEXTURE_FILTER_NEAREST, OSP_TEXTURE_FILTER_LINEAR)); TEST_P(PTBackgroundRefraction, backgroundRefraction) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Appearance, PTBackgroundRefraction, ::testing::Bool()); } // namespace OSPRayTestScenes RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_appearance.h000066400000000000000000000022501456566705700242730ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_fixture.h" namespace OSPRayTestScenes { // Test all texture image formats (and filter modes) class Texture2D : public Base, public ::testing::TestWithParam> { public: Texture2D(); void SetUp() override; }; class Texture2DTransform : public Base, public ::testing::TestWithParam { public: Texture2DTransform(); void SetUp() override; }; class Texture2DWrapMode : public Base, public ::testing::TestWithParam { OSPTextureFilter filter; public: Texture2DWrapMode(); void SetUp() override; }; class RendererMaterialList : public Base, public ::testing::TestWithParam { public: RendererMaterialList(); void SetUp() override; }; class PTBackgroundRefraction : public Base, public ::testing::TestWithParam { public: PTBackgroundRefraction(); void SetUp() override; }; } // namespace OSPRayTestScenes RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_assigned_data.cpp000066400000000000000000000106331456566705700253210ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include #include #include "test_fixture.h" #ifdef SYCL_LANGUAGE_VERSION #include "sycl/sycl.hpp" #endif extern OSPRayEnvironment *ospEnv; namespace OSPRayTestScenes { struct TestAssignedCopyDelCounts { ~TestAssignedCopyDelCounts(); static int delcounts; }; int TestAssignedCopyDelCounts::delcounts{0}; static void exiting() { ASSERT_EQ(TestAssignedCopyDelCounts::delcounts, 2) << "Mem leak: The buffers should have been freed by now."; } TestAssignedCopyDelCounts::~TestAssignedCopyDelCounts() { exiting(); } class TestAssignedCopy : public Base, public ::testing::Test, virtual public TestAssignedCopyDelCounts { public: void SetUp() override; }; #define VALIDATION_MESSAGE \ std::cout << __FUNCTION__ \ << " delcounts = " << TestAssignedCopyDelCounts::delcounts \ << std::endl static void customMallocDeleter(const void *dels, const void *buff) { free((void *)buff); (*(int *)dels)++; VALIDATION_MESSAGE; } #ifdef SYCL_LANGUAGE_VERSION static void customSYCLDeleter(const void *syclQueue, const void *buff) { sycl::free((void *)buff, *(sycl::queue *)syclQueue); TestAssignedCopyDelCounts::delcounts++; VALIDATION_MESSAGE; } #endif static void customNewDeleter(const void *dels, const void *buff) { delete[] (float *)buff; (*(int *)dels)++; VALIDATION_MESSAGE; } void TestAssignedCopy::SetUp() { Base::SetUp(); camera.setParam("position", vec3f(0.f, 0.f, 4.f)); camera.setParam("direction", vec3f(0.f, 0.f, -1.f)); camera.setParam("up", vec3f(0.f, 1.f, 0.f)); cpp::Geometry spheres("sphere"); const int numspheres = 1000; std::vector centersB; // per default use malloc float *radiiB = (float *)malloc(numspheres * sizeof(float)); OSPDeleterCallback radiiDeleter = customMallocDeleter; void *radiiUserData = &TestAssignedCopyDelCounts::delcounts; #ifdef SYCL_LANGUAGE_VERSION auto *appsSyclQueue = ospEnv->GetAppsSyclQueue(); if (appsSyclQueue) { // but on GPU use sycl::malloc free(radiiB); radiiB = sycl::malloc_shared(numspheres, *appsSyclQueue); radiiDeleter = customSYCLDeleter; radiiUserData = appsSyclQueue; } #endif vec2f *tcoordsB = new vec2f[numspheres]; unsigned int randomSeed{0}; std::mt19937 gen(randomSeed); std::uniform_real_distribution centerDistribution(-1.f, 1.f); std::uniform_real_distribution radiusDistribution(0.05f, 0.15f); for (int i = 0; i < numspheres; i++) { radiiB[i] = radiusDistribution(gen); const float x = centerDistribution(gen); const float y = centerDistribution(gen); const float z = centerDistribution(gen); centersB.emplace_back(x, y, z); tcoordsB[i] = vec2f((float)i / (float)numspheres, 0.f); } OSPData radii = ospNewAssignedData1D( radiiB, OSP_FLOAT, numspheres, radiiDeleter, radiiUserData); OSPData tcoords = ospNewAssignedData1D(tcoordsB, OSP_VEC2F, numspheres, customNewDeleter, &TestAssignedCopyDelCounts::delcounts); spheres.setParam("sphere.position", cpp::MovedData(centersB)); EXPECT_TRUE(centersB.empty()) << "Buffer was not moved."; spheres.setParam("sphere.radius", radii); spheres.setParam("sphere.texcoord", tcoords); spheres.commit(); ASSERT_EQ(delcounts, 0) << "Buffers were freed before the app released them."; ospRelease(radii); ospRelease(tcoords); cpp::GeometricModel model(spheres); cpp::Material sphereMaterial("obj"); sphereMaterial.commit(); model.setParam("material", sphereMaterial); AddModel(model); cpp::Light distant("distant"); distant.setParam("intensity", 3.0f); distant.setParam("direction", vec3f(0.3f, -4.0f, 0.8f)); distant.setParam("color", vec3f(1.0f, 0.5f, 0.5f)); distant.setParam("angularDiameter", 1.0f); AddLight(distant); cpp::Light ambient = ospNewLight("ambient"); ambient.setParam("intensity", 0.1f); AddLight(ambient); if (delcounts > 0) std::cout << "Buffers were already freed " "(internal copy? missing internal Ref<>?)." << std::endl; } // Test Instantiations ////////////////////////////////////////////////////// TEST_F(TestAssignedCopy, deleterCallbacks) { PerformRenderTest(); } } // namespace OSPRayTestScenes RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_camera.cpp000066400000000000000000000065041456566705700237650ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ospray_testing.h" #include "test_fixture.h" namespace OSPRayTestScenes { // Test all stereo modes of perspective and panoramic class Stereo : public Base, public ::testing::TestWithParam< std::tuple> { public: Stereo(); void SetUp() override; protected: std::string cameraType; vec3f pos{0.0f, 0.0f, -0.5f}; OSPStereoMode stereoMode; }; class PixelFilter : public Base, public ::testing::TestWithParam< std::tuple> { public: PixelFilter(); void SetUp() override; protected: OSPPixelFilterType pixelFilter; }; // Implementations ///////////////////////////////////////////////////////////// Stereo::Stereo() { rendererType = "scivis"; samplesPerPixel = 4; auto params = GetParam(); cameraType = std::get<0>(params); stereoMode = std::get<1>(params); } void Stereo::SetUp() { Base::SetUp(); auto builder = ospray::testing::newBuilder("cornell_box"); ospray::testing::setParam(builder, "rendererType", rendererType); ospray::testing::commit(builder); world = ospray::testing::buildWorld(builder); ospray::testing::release(builder); camera = cpp::Camera(cameraType); if (cameraType == "perspective") { pos.z = -2.f; camera.setParam("aspect", imgSize.x / (float)imgSize.y); } camera.setParam("position", pos); camera.setParam("stereoMode", stereoMode); camera.setParam("transform", affine3f(one)); } PixelFilter::PixelFilter() { auto params = GetParam(); rendererType = std::get<0>(params); pixelFilter = std::get<1>(params); } void PixelFilter::SetUp() { Base::SetUp(); const float aspect = imgSize.x / (float)imgSize.y; const float diag = sqrt(aspect * aspect + 1.f); for (float r = 0.1f; r < diag;) { const float w = lerp(sqrt(r / diag), 0.1f, 0.002f); cpp::Light light("spot"); light.setParam("innerRadius", r); light.setParam("radius", r + 0.5f * w); light.setParam("intensityQuantity", OSP_INTENSITY_QUANTITY_RADIANCE); AddLight(light); r += w; } camera = cpp::Camera("orthographic"); camera.setParam("aspect", aspect); camera.setParam("position", vec3f(0.5f * aspect, -0.5f, 1.f)); camera.setParam("direction", vec3f(0.f, 0.f, -1.f)); renderer.setParam("pixelFilter", pixelFilter); renderer.setParam("backgroundColor", vec4f(0.f, 0.f, 0.f, 1.0f)); if (rendererType == "scivis") renderer.setParam("visibleLights", true); } // Test Instantiations ///////////////////////////////////////////////////////// TEST_P(Stereo, stereo) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Camera, Stereo, ::testing::Combine(::testing::Values("perspective", "panoramic"), ::testing::Values(OSP_STEREO_LEFT, OSP_STEREO_RIGHT, OSP_STEREO_SIDE_BY_SIDE, OSP_STEREO_TOP_BOTTOM))); TEST_P(PixelFilter, test) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Camera, PixelFilter, ::testing::Combine(::testing::Values("scivis", "pathtracer"), ::testing::Values(OSP_PIXELFILTER_POINT, OSP_PIXELFILTER_BOX, OSP_PIXELFILTER_GAUSS, OSP_PIXELFILTER_MITCHELL, OSP_PIXELFILTER_BLACKMAN_HARRIS))); } // namespace OSPRayTestScenes RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_camera.h000066400000000000000000000000001456566705700234130ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_enums.cpp000066400000000000000000000125541456566705700236660ustar00rootroot00000000000000// Copyright 2019 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include #ifdef SYCL_LANGUAGE_VERSION #include "sycl/sycl.hpp" #endif #include "embree4/rtcore.h" #include "ospray/OSPEnums.h" #ifdef OSPRAY_ENABLE_VOLUMES #include "openvkl/openvkl.h" TEST(Enums, VKLLogLevel) { ASSERT_LE(sizeof(OSPLogLevel), sizeof(VKLLogLevel)); ASSERT_EQ(OSP_LOG_DEBUG, VKL_LOG_DEBUG); ASSERT_EQ(OSP_LOG_INFO, VKL_LOG_INFO); ASSERT_EQ(OSP_LOG_WARNING, VKL_LOG_WARNING); ASSERT_EQ(OSP_LOG_ERROR, VKL_LOG_ERROR); ASSERT_EQ(OSP_LOG_NONE, VKL_LOG_NONE); } TEST(Enums, VKLDataType) { ASSERT_LE(sizeof(OSPDataType), sizeof(VKLDataType)); ASSERT_EQ(OSP_BOOL, VKL_BOOL); ASSERT_EQ(OSP_CHAR, VKL_CHAR); ASSERT_EQ(OSP_VEC2C, VKL_VEC2C); ASSERT_EQ(OSP_VEC3C, VKL_VEC3C); ASSERT_EQ(OSP_VEC4C, VKL_VEC4C); ASSERT_EQ(OSP_UCHAR, VKL_UCHAR); ASSERT_EQ(OSP_VEC2UC, VKL_VEC2UC); ASSERT_EQ(OSP_VEC3UC, VKL_VEC3UC); ASSERT_EQ(OSP_VEC4UC, VKL_VEC4UC); ASSERT_EQ(OSP_SHORT, VKL_SHORT); ASSERT_EQ(OSP_VEC2S, VKL_VEC2S); ASSERT_EQ(OSP_VEC3S, VKL_VEC3S); ASSERT_EQ(OSP_VEC4S, VKL_VEC4S); ASSERT_EQ(OSP_USHORT, VKL_USHORT); ASSERT_EQ(OSP_VEC2US, VKL_VEC2US); ASSERT_EQ(OSP_VEC3US, VKL_VEC3US); ASSERT_EQ(OSP_VEC4US, VKL_VEC4US); ASSERT_EQ(OSP_INT, VKL_INT); ASSERT_EQ(OSP_VEC2I, VKL_VEC2I); ASSERT_EQ(OSP_VEC3I, VKL_VEC3I); ASSERT_EQ(OSP_VEC4I, VKL_VEC4I); ASSERT_EQ(OSP_UINT, VKL_UINT); ASSERT_EQ(OSP_VEC2UI, VKL_VEC2UI); ASSERT_EQ(OSP_VEC3UI, VKL_VEC3UI); ASSERT_EQ(OSP_VEC4UI, VKL_VEC4UI); ASSERT_EQ(OSP_LONG, VKL_LONG); ASSERT_EQ(OSP_VEC2L, VKL_VEC2L); ASSERT_EQ(OSP_VEC3L, VKL_VEC3L); ASSERT_EQ(OSP_VEC4L, VKL_VEC4L); ASSERT_EQ(OSP_ULONG, VKL_ULONG); ASSERT_EQ(OSP_VEC2UL, VKL_VEC2UL); ASSERT_EQ(OSP_VEC3UL, VKL_VEC3UL); ASSERT_EQ(OSP_VEC4UL, VKL_VEC4UL); ASSERT_EQ(OSP_HALF, VKL_HALF); ASSERT_EQ(OSP_VEC2H, VKL_VEC2H); ASSERT_EQ(OSP_VEC3H, VKL_VEC3H); ASSERT_EQ(OSP_VEC4H, VKL_VEC4H); ASSERT_EQ(OSP_FLOAT, VKL_FLOAT); ASSERT_EQ(OSP_VEC2F, VKL_VEC2F); ASSERT_EQ(OSP_VEC3F, VKL_VEC3F); ASSERT_EQ(OSP_VEC4F, VKL_VEC4F); ASSERT_EQ(OSP_DOUBLE, VKL_DOUBLE); ASSERT_EQ(OSP_VEC2D, VKL_VEC2D); ASSERT_EQ(OSP_VEC3D, VKL_VEC3D); ASSERT_EQ(OSP_VEC4D, VKL_VEC4D); ASSERT_EQ(OSP_BOX1I, VKL_BOX1I); ASSERT_EQ(OSP_BOX2I, VKL_BOX2I); ASSERT_EQ(OSP_BOX3I, VKL_BOX3I); ASSERT_EQ(OSP_BOX4I, VKL_BOX4I); ASSERT_EQ(OSP_BOX1F, VKL_BOX1F); ASSERT_EQ(OSP_BOX2F, VKL_BOX2F); ASSERT_EQ(OSP_BOX3F, VKL_BOX3F); ASSERT_EQ(OSP_BOX4F, VKL_BOX4F); ASSERT_EQ(OSP_DATA, VKL_DATA); ASSERT_EQ(OSP_LINEAR2F, VKL_LINEAR2F); ASSERT_EQ(OSP_LINEAR3F, VKL_LINEAR3F); ASSERT_EQ(OSP_AFFINE2F, VKL_AFFINE2F); ASSERT_EQ(OSP_AFFINE3F, VKL_AFFINE3F); ASSERT_EQ(OSP_RAW, VKL_RAW); ASSERT_EQ(OSP_BYTE, VKL_BYTE); ASSERT_EQ(OSP_VOID_PTR, VKL_VOID_PTR); ASSERT_EQ(OSP_STRING, VKL_STRING); ASSERT_EQ(OSP_OBJECT, VKL_OBJECT); // those are different object types: // ASSERT_EQ(OSP_VOLUME, VKL_VOLUME); } TEST(Enums, VKLUnstructuredCellType) { ASSERT_LE(sizeof(OSPUnstructuredCellType), sizeof(VKLUnstructuredCellType)); ASSERT_EQ(OSP_TETRAHEDRON, VKL_TETRAHEDRON); ASSERT_EQ(OSP_HEXAHEDRON, VKL_HEXAHEDRON); ASSERT_EQ(OSP_WEDGE, VKL_WEDGE); ASSERT_EQ(OSP_PYRAMID, VKL_PYRAMID); } TEST(Enums, VKLAMRMethod) { ASSERT_LE(sizeof(OSPAMRMethod), sizeof(VKLAMRMethod)); ASSERT_EQ(OSP_AMR_CURRENT, VKL_AMR_CURRENT); ASSERT_EQ(OSP_AMR_FINEST, VKL_AMR_FINEST); ASSERT_EQ(OSP_AMR_OCTANT, VKL_AMR_OCTANT); } TEST(Enums, VKLFilter) { ASSERT_LE(sizeof(OSPVolumeFilter), sizeof(VKLFilter)); ASSERT_EQ(OSP_VOLUME_FILTER_NEAREST, VKL_FILTER_NEAREST); ASSERT_EQ(OSP_VOLUME_FILTER_LINEAR, VKL_FILTER_LINEAR); ASSERT_EQ(OSP_VOLUME_FILTER_CUBIC, VKL_FILTER_CUBIC); } TEST(Enums, VKLFormat) { ASSERT_LE(sizeof(OSPVolumeFormat), sizeof(VKLFormat)); ASSERT_EQ(OSP_VOLUME_FORMAT_TILE, VKL_FORMAT_TILE); ASSERT_EQ(OSP_VOLUME_FORMAT_DENSE_ZYX, VKL_FORMAT_DENSE_ZYX); } TEST(Enums, VKLError) { ASSERT_LE(sizeof(OSPError), sizeof(VKLError)); ASSERT_EQ(OSP_NO_ERROR, VKL_NO_ERROR); ASSERT_EQ(OSP_UNKNOWN_ERROR, VKL_UNKNOWN_ERROR); ASSERT_EQ(OSP_INVALID_ARGUMENT, VKL_INVALID_ARGUMENT); ASSERT_EQ(OSP_INVALID_OPERATION, VKL_INVALID_OPERATION); ASSERT_EQ(OSP_OUT_OF_MEMORY, VKL_OUT_OF_MEMORY); ASSERT_EQ(OSP_UNSUPPORTED_CPU, VKL_UNSUPPORTED_CPU); } #endif TEST(Enums, RTCSubdivisionMode) { ASSERT_LE(sizeof(OSPSubdivisionMode), sizeof(RTCSubdivisionMode)); ASSERT_EQ(OSP_SUBDIVISION_NO_BOUNDARY, RTC_SUBDIVISION_MODE_NO_BOUNDARY); ASSERT_EQ( OSP_SUBDIVISION_SMOOTH_BOUNDARY, RTC_SUBDIVISION_MODE_SMOOTH_BOUNDARY); ASSERT_EQ(OSP_SUBDIVISION_PIN_CORNERS, RTC_SUBDIVISION_MODE_PIN_CORNERS); ASSERT_EQ(OSP_SUBDIVISION_PIN_BOUNDARY, RTC_SUBDIVISION_MODE_PIN_BOUNDARY); ASSERT_EQ(OSP_SUBDIVISION_PIN_ALL, RTC_SUBDIVISION_MODE_PIN_ALL); } TEST(Enums, RTCError) { ASSERT_LE(sizeof(OSPError), sizeof(RTCError)); ASSERT_EQ(OSP_NO_ERROR, RTC_ERROR_NONE); ASSERT_EQ(OSP_UNKNOWN_ERROR, RTC_ERROR_UNKNOWN); ASSERT_EQ(OSP_INVALID_ARGUMENT, RTC_ERROR_INVALID_ARGUMENT); ASSERT_EQ(OSP_INVALID_OPERATION, RTC_ERROR_INVALID_OPERATION); ASSERT_EQ(OSP_OUT_OF_MEMORY, RTC_ERROR_OUT_OF_MEMORY); ASSERT_EQ(OSP_UNSUPPORTED_CPU, RTC_ERROR_UNSUPPORTED_CPU); } TEST(Enums, RTCGeometryType) { ASSERT_EQ(OSP_SPHERE, RTC_GEOMETRY_TYPE_SPHERE_POINT); ASSERT_EQ(OSP_DISC, RTC_GEOMETRY_TYPE_DISC_POINT); ASSERT_EQ(OSP_ORIENTED_DISC, RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT); } RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_fixture.cpp000066400000000000000000000122461456566705700242230ustar00rootroot00000000000000// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_fixture.h" #include "ArcballCamera.h" #include "ospray_testing.h" extern OSPRayEnvironment *ospEnv; namespace OSPRayTestScenes { Base::Base() { const ::testing::TestCase *const testCase = ::testing::UnitTest::GetInstance()->current_test_case(); const ::testing::TestInfo *const testInfo = ::testing::UnitTest::GetInstance()->current_test_info(); { std::string testCaseName = testCase->name(); std::string testInfoName = testInfo->name(); size_t pos = testCaseName.find('/'); if (pos == std::string::npos) { testName = testCaseName + "_" + testInfoName; } else { std::string instantiationName = testCaseName.substr(0, pos); std::string className = testCaseName.substr(pos + 1); testName = className + "_" + instantiationName + "_" + testInfoName; } for (char &byte : testName) if (byte == '/') byte = '_'; } imgSize = ospEnv->GetImgSize(); rendererType = "scivis"; frames = 1; samplesPerPixel = 16; } void Base::SetUp() { framebuffer = cpp::FrameBuffer(imgSize.x, imgSize.y, frameBufferFormat, OSP_FB_COLOR | OSP_FB_ACCUM | OSP_FB_DEPTH); imageTool.reset(new OSPImageTools(imgSize, GetTestName(), frameBufferFormat)); CreateEmptyScene(); } void Base::AddLight(cpp::Light light) { light.commit(); lightsList.push_back(light); } void Base::AddModel(cpp::GeometricModel model, affine3f xfm) { model.commit(); cpp::Group group; group.setParam("geometry", cpp::CopiedData(model)); group.commit(); cpp::Instance instance(group); instance.setParam("transform", xfm); AddInstance(instance); } void Base::AddModel(cpp::VolumetricModel model, affine3f xfm) { model.commit(); cpp::Group group; group.setParam("volume", cpp::CopiedData(model)); group.commit(); cpp::Instance instance(group); instance.setParam("transform", xfm); AddInstance(instance); } void Base::AddInstance(cpp::Instance instance) { instance.commit(); instances.push_back(instance); } void Base::PerformRenderTest() { SetLights(); if (!instances.empty()) world.setParam("instance", cpp::CopiedData(instances)); camera.commit(); world.commit(); renderer.commit(); framebuffer.resetAccumulation(); RenderFrame(); void *framebuffer_data = framebuffer.map(OSP_FB_COLOR); if (ospEnv->GetDumpImg()) { EXPECT_EQ(imageTool->saveTestImage(framebuffer_data), OsprayStatus::Ok); } else { EXPECT_EQ( imageTool->compareImgWithBaseline(framebuffer_data), OsprayStatus::Ok); } framebuffer.unmap(framebuffer_data); } void Base::CreateEmptyScene() { camera = cpp::Camera("perspective"); camera.setParam("aspect", imgSize.x / (float)imgSize.y); camera.setParam("position", vec3f(0.f)); camera.setParam("direction", vec3f(0.f, 0.f, 1.f)); camera.setParam("up", vec3f(0.f, 1.f, 0.f)); renderer = cpp::Renderer(rendererType); if (rendererType == "ao") renderer.setParam("aoSamples", 0); if (rendererType == "scivis") { renderer.setParam("shadows", true); renderer.setParam("aoSamples", 16); } renderer.setParam("backgroundColor", vec3f(1.0f)); renderer.setParam("pixelSamples", samplesPerPixel); world = cpp::World(); } void Base::SetLights() { if (!lightsList.empty()) world.setParam("light", cpp::CopiedData(lightsList)); } void Base::RenderFrame() { for (int frame = 0; frame < frames; ++frame) cpp::Future future = framebuffer.renderFrame(renderer, camera, world); } FromOsprayTesting::FromOsprayTesting() { auto params = GetParam(); sceneName = std::get<0>(params); rendererType = std::get<1>(params); samplesPerPixel = std::get<2>(params); } void FromOsprayTesting::SetUp() { Base::SetUp(); auto builder = ospray::testing::newBuilder(sceneName); ospray::testing::setParam(builder, "rendererType", rendererType); ospray::testing::commit(builder); world = ospray::testing::buildWorld(builder); ospray::testing::release(builder); world.commit(); auto worldBounds = world.getBounds(); ArcballCamera arcballCamera(worldBounds, imgSize); camera.setParam("position", arcballCamera.eyePos()); camera.setParam("direction", arcballCamera.lookDir()); camera.setParam("up", arcballCamera.upDir()); } void FromOsprayTestingMaxDepth::SetUp() { FromOsprayTesting::SetUp(); // set up max depth texture { cpp::Texture maxDepthTex("texture2d"); std::vector maxDepth = {3.f, 3.f, 3.f, 3.f}; maxDepthTex.setParam( "data", cpp::CopiedData(maxDepth.data(), vec2ul(2, 2))); maxDepthTex.setParam("format", OSP_TEXTURE_R32F); maxDepthTex.setParam("filter", OSP_TEXTURE_FILTER_NEAREST); maxDepthTex.commit(); renderer.setParam("map_maxDepth", maxDepthTex); } } void FromOsprayTestingVariance::SetUp() { FromOsprayTesting::SetUp(); frames = 22; framebuffer = cpp::FrameBuffer(imgSize.x, imgSize.y, frameBufferFormat, OSP_FB_COLOR | OSP_FB_ACCUM | OSP_FB_VARIANCE); renderer.setParam("varianceThreshold", 10.0f); } void FromOsprayTestingLightSamples::SetUp() { FromOsprayTesting::SetUp(); renderer.setParam("lightSamples", 8); } } // namespace OSPRayTestScenes RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_fixture.h000066400000000000000000000044361456566705700236720ustar00rootroot00000000000000// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include #include #include #include #include #include "environment.h" #include "test_tools.h" namespace OSPRayTestScenes { // Base class for all test fixtures. // Deriving classes can call CreateEmptyScene() to set up model, renderer, // camera etc. Behaviour of this method can be changed by modifying fields // rendererType, frames and samplesPerPixel beforehand. class Base { public: Base(); virtual ~Base() = default; virtual void SetUp(); Base &operator=(const Base &) = delete; Base(const Base &) = delete; void AddLight(cpp::Light new_light); void AddModel(cpp::GeometricModel model, affine3f xfm = one); void AddModel(cpp::VolumetricModel model, affine3f xfm = one); virtual void AddInstance(cpp::Instance instance); virtual void PerformRenderTest(); vec2i GetImgSize() const { return imgSize; } std::string GetTestName() const { return testName; } protected: void CreateEmptyScene(); void SetLights(); void RenderFrame(); // Data // vec2i imgSize; std::string testName; std::string rendererType; int frames; int samplesPerPixel; cpp::FrameBuffer framebuffer{nullptr}; cpp::Renderer renderer{nullptr}; cpp::Camera camera{nullptr}; cpp::World world{nullptr}; OSPFrameBufferFormat frameBufferFormat = OSP_FB_SRGBA; std::unique_ptr imageTool; std::vector lightsList; std::vector instances; }; // Fixture class used for tests that uses 'ospray_testing' scenes class FromOsprayTesting : public Base, public ::testing::TestWithParam> { public: FromOsprayTesting(); void SetUp() override; protected: std::string sceneName; }; // with map_maxDepth texture class FromOsprayTestingMaxDepth : public FromOsprayTesting { public: void SetUp() override; }; class FromOsprayTestingVariance : public FromOsprayTesting { public: void SetUp() override; }; class FromOsprayTestingLightSamples : public FromOsprayTesting { public: void SetUp() override; }; } // namespace OSPRayTestScenes RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_framebuffer.cpp000066400000000000000000000063041456566705700250170ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ArcballCamera.h" #include "ospray_testing.h" #include "rkcommon/utility/random.h" #include "test_fixture.h" extern OSPRayEnvironment *ospEnv; namespace OSPRayTestScenes { class IDBuffer : public Base, public ::testing::TestWithParam> { public: IDBuffer(); void SetUp() override; void PerformRenderTest() override; protected: OSPFrameBufferChannel idBuffer{OSP_FB_ID_PRIMITIVE}; bool appIDs{false}; }; IDBuffer::IDBuffer() { auto params = GetParam(); idBuffer = std::get<0>(params); appIDs = std::get<1>(params); rendererType = std::get<2>(params); samplesPerPixel = 2; } void IDBuffer::SetUp() { Base::SetUp(); framebuffer = cpp::FrameBuffer(imgSize.x, imgSize.y, frameBufferFormat, idBuffer); instances.clear(); auto builder = ospray::testing::newBuilder( idBuffer == OSP_FB_ID_PRIMITIVE ? "perlin_noise_volumes" : "instancing"); ospray::testing::setParam(builder, "rendererType", rendererType); ospray::testing::setParam(builder, "numInstances", vec2ui(10, 3)); ospray::testing::setParam(builder, "useIDs", appIDs); ospray::testing::commit(builder); world = ospray::testing::buildWorld(builder); ospray::testing::release(builder); } inline uint8_t to_uc(const float f) { return 255.f * clamp(f, 0.f, 1.0f); } inline uint32_t to_rgba8(const vec3f c) { return to_uc(c.x) | (to_uc(c.y) << 8) | (to_uc(c.z) << 16) | 0xff000000; } void IDBuffer::PerformRenderTest() { if (!instances.empty()) world.setParam("instance", cpp::CopiedData(instances)); world.commit(); ArcballCamera arcballCamera(world.getBounds(), imgSize); camera.setParam("position", arcballCamera.eyePos()); camera.setParam("direction", arcballCamera.lookDir()); camera.setParam("up", arcballCamera.upDir()); camera.setParam("fovy", 45.0f); camera.commit(); renderer.commit(); framebuffer.resetAccumulation(); RenderFrame(); auto *framebuffer_data = (uint32_t *)framebuffer.map(idBuffer); std::vector framebufferData(imgSize.product()); for (int i = 0; i < imgSize.product(); i++) framebufferData[i] = framebuffer_data[i] == -1u ? 0 : to_rgba8(rkcommon::utility::makeRandomColor(framebuffer_data[i])); framebuffer.unmap(framebuffer_data); if (ospEnv->GetDumpImg()) { EXPECT_EQ( imageTool->saveTestImage(framebufferData.data()), OsprayStatus::Ok); } else { EXPECT_EQ(imageTool->compareImgWithBaseline(framebufferData.data()), OsprayStatus::Ok); } } // Test Instantiations ////////////////////////////////////////////////////// TEST_P(IDBuffer, IDBuffer) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Primitive, IDBuffer, ::testing::Combine(::testing::Values(OSP_FB_ID_PRIMITIVE), ::testing::Values(false), ::testing::Values("scivis", "pathtracer"))); INSTANTIATE_TEST_SUITE_P(ObjectInstance, IDBuffer, ::testing::Combine(::testing::Values(OSP_FB_ID_OBJECT, OSP_FB_ID_INSTANCE), ::testing::Bool(), ::testing::Values("scivis", "pathtracer"))); } // namespace OSPRayTestScenes RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_geometry.cpp000066400000000000000000000203311456566705700243620ustar00rootroot00000000000000// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_geometry.h" #include "ArcballCamera.h" #include "ospray_testing.h" namespace OSPRayTestScenes { SpherePrecision::SpherePrecision() { auto params = GetParam(); radius = std::get<0>(params); dist = std::get<1>(params) * radius; move_cam = std::get<2>(params); rendererType = std::get<3>(params); } void SpherePrecision::SetUp() { Base::SetUp(); float fov = 160.0f * std::min(std::tan(radius / std::abs(dist)), 1.0f); float cent = move_cam ? 0.0f : dist + radius; camera.setParam( "position", vec3f(0.f, 0.f, move_cam ? -dist - radius : 0.0f)); camera.setParam("direction", vec3f(0.f, 0.f, 1.f)); camera.setParam("up", vec3f(0.f, 1.f, 0.f)); camera.setParam("fovy", fov); renderer.setParam("pixelSamples", 16); renderer.setParam("backgroundColor", vec4f(0.2f, 0.2f, 0.4f, 1.0f)); if (rendererType == "scivis") { renderer.setParam("shadows", true); renderer.setParam("aoSamples", 16); } else if (rendererType == "ao") { renderer.setParam("aoSamples", 16); renderer.setParam("aoIntensity", 1.f); } else if (rendererType == "pathtracer") { renderer.setParam("maxPathLength", 2); } cpp::Geometry sphere("sphere"); cpp::Geometry inst_sphere("sphere"); std::vector sph_center = {vec3f(-0.5f * radius, -0.3f * radius, cent), vec3f(0.8f * radius, -0.3f * radius, cent), vec3f(0.8f * radius, 1.5f * radius, cent), vec3f(0.0f, -10001.3f * radius, cent)}; std::vector sph_radius = { radius, 0.9f * radius, 0.9f * radius, 10000.f * radius}; sphere.setParam("sphere.position", cpp::CopiedData(sph_center)); sphere.setParam("sphere.radius", cpp::CopiedData(sph_radius)); sphere.commit(); inst_sphere.setParam("sphere.position", cpp::CopiedData(vec3f(0.f))); inst_sphere.setParam("sphere.radius", cpp::CopiedData(90.f * radius)); inst_sphere.commit(); cpp::GeometricModel model1(sphere); cpp::GeometricModel model2(inst_sphere); cpp::Material sphereMaterial("obj"); sphereMaterial.setParam("d", 1.0f); sphereMaterial.commit(); model1.setParam("material", sphereMaterial); model2.setParam("material", sphereMaterial); affine3f xfm(vec3f(0.01, 0, 0), vec3f(0, 0.01, 0), vec3f(0, 0, 0.01), vec3f(-0.5f * radius, 1.6f * radius, cent)); AddModel(model1); AddModel(model2, xfm); cpp::Light distant("distant"); distant.setParam("intensity", 3.0f); distant.setParam("direction", vec3f(0.3f, -4.0f, 0.8f)); distant.setParam("color", vec3f(1.0f, 0.5f, 0.5f)); distant.setParam("angularDiameter", 1.0f); AddLight(distant); cpp::Light ambient("ambient"); ambient.setParam("intensity", 0.1f); AddLight(ambient); } Curves::Curves() { auto params = GetParam(); curveVariant = std::get<0>(params); rendererType = std::get<1>(params); } void Curves::SetUp() { Base::SetUp(); auto builder = ospray::testing::newBuilder("curves"); ospray::testing::setParam(builder, "rendererType", rendererType); ospray::testing::setParam(builder, "curveVariant", curveVariant); ospray::testing::commit(builder); world = ospray::testing::buildWorld(builder); ospray::testing::release(builder); world.commit(); auto worldBounds = world.getBounds(); ArcballCamera arcballCamera(worldBounds, imgSize); camera.setParam("position", arcballCamera.eyePos()); camera.setParam("direction", arcballCamera.lookDir()); camera.setParam("up", arcballCamera.upDir()); } class ClippingParallel : public Base, public ::testing::Test { public: ClippingParallel(); void SetUp() override; }; ClippingParallel::ClippingParallel() { rendererType = "pathtracer"; } void ClippingParallel::SetUp() { Base::SetUp(); instances.clear(); auto builder = ospray::testing::newBuilder("clip_with_planes"); ospray::testing::setParam(builder, "rendererType", rendererType); ospray::testing::commit(builder); world = ospray::testing::buildWorld(builder); ospray::testing::release(builder); camera = cpp::Camera("orthographic"); camera.setParam("height", 2.5f); camera.setParam("direction", vec3f(-0.5f, -0.5f, 1.0f)); camera.setParam("position", vec3f(1.0f, 1.0f, -2.0f)); } // Test Instantiations ////////////////////////////////////////////////////// TEST_P(SpherePrecision, sphere) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Intersection, SpherePrecision, ::testing::Combine(::testing::Values(0.001f, 3.e5f), ::testing::Values(3.f, 8000.0f, 2.e5f), ::testing::Values(true, false), ::testing::Values("scivis", "pathtracer"))); TEST_P(FromOsprayTesting, test_scenes) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(TestScenesGeometry, FromOsprayTesting, ::testing::Combine(::testing::Values("cornell_box", "gravity_spheres_isosurface", "empty", "random_spheres", "streamlines", "subdivision_cube", "planes", "unstructured_volume_isosurface", "instancing", "nolight", "random_discs", "random_oriented_discs"), ::testing::Values("scivis", "pathtracer", "ao"), ::testing::Values(16))); // INSTANTIATE_TEST_SUITE_P(TestScenesInterpolation, // FromOsprayTesting, // ::testing::Combine(::testing::Values("interpolation_quads_color_fv", // "interpolation_subd_color_fv", // "interpolation_quads_color_vv", // "interpolation_subd_color_vv", // "interpolation_quads_color_u", // "interpolation_subd_color_u", // "interpolation_quads_color_c", // "interpolation_subd_color_c", // "interpolation_quads_tex_fv", // "interpolation_subd_tex_fv", // "interpolation_quads_tex_vv", // "interpolation_subd_tex_vv"), // ::testing::Values("scivis"), // ::testing::Values(1))); TEST_P(Curves, test_scenes) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(TestScenesGeometry, Curves, ::testing::Combine(::testing::Values("bspline", "hermite", "catmull-rom", "linear_deprecated", "linear", "cones"), ::testing::Values("scivis", "pathtracer", "ao"))); INSTANTIATE_TEST_SUITE_P(TestScenesClipping, FromOsprayTesting, ::testing::Combine(::testing::Values("clip_with_spheres", "clip_with_boxes", "clip_with_planes", "clip_with_meshes", "clip_with_subdivisions", "clip_with_linear_curves", "clip_with_bspline_curves", "clip_gravity_spheres_volume", "clip_perlin_noise_volumes"), ::testing::Values("scivis", "pathtracer", "ao"), ::testing::Values(16))); TEST_F(ClippingParallel, planes) { PerformRenderTest(); } TEST_P(FromOsprayTestingMaxDepth, test_scenes) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(TestScenesMaxDepth, FromOsprayTestingMaxDepth, ::testing::Combine( ::testing::Values( "cornell_box", "clip_with_spheres", "clip_gravity_spheres_volume"), ::testing::Values("ao"), ::testing::Values(16))); TEST_P(FromOsprayTestingVariance, testScenes) { PerformRenderTest(); EXPECT_LE(framebuffer.variance(), 10.0f); } INSTANTIATE_TEST_SUITE_P(TestScenesVariance, FromOsprayTestingVariance, ::testing::Values(std::make_tuple("cornell_box", "pathtracer", 4))); TEST_P(FromOsprayTestingLightSamples, testScenes) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(TestScenesLightSamples, FromOsprayTestingLightSamples, ::testing::Combine(::testing::Values("cornell_box", "nolight"), ::testing::Values("pathtracer"), ::testing::Values(1))); } // namespace OSPRayTestScenes RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_geometry.h000066400000000000000000000017171456566705700240360ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_fixture.h" namespace OSPRayTestScenes { // Fixture class to test cornercases of intersection precision and epsilon // handling; parametrized with renderer, sphere radius, distance factor, and // whether the sphere is in origin class SpherePrecision : public Base, public ::testing::TestWithParam> { public: SpherePrecision(); void SetUp() override; protected: float dist; float radius; bool move_cam; }; // Fixture class used for testing curves variants class Curves : public Base, public ::testing::TestWithParam> { public: Curves(); void SetUp() override; protected: std::string curveVariant; }; } // namespace OSPRayTestScenes RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_glm_compat.cpp000066400000000000000000000103421456566705700246520ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include // ospray_cpp #include "ospray/ospray_cpp.h" #include "ospray/ospray_cpp/ext/rkcommon.h" #define OSPRAY_GLM_DEFINITIONS #include "ospray/ospray_cpp/ext/glm.h" // glm extras #include "glm/gtc/matrix_transform.hpp" TEST(glm, TypeCompatibility) { static_assert(sizeof(rkcommon::math::vec2f) == sizeof(glm::vec2), ""); static_assert(sizeof(rkcommon::math::vec3f) == sizeof(glm::vec3), ""); static_assert(sizeof(rkcommon::math::vec4f) == sizeof(glm::vec4), ""); static_assert(sizeof(rkcommon::math::vec2i) == sizeof(glm::ivec2), ""); static_assert(sizeof(rkcommon::math::vec3i) == sizeof(glm::ivec3), ""); static_assert(sizeof(rkcommon::math::vec4i) == sizeof(glm::ivec4), ""); static_assert(sizeof(rkcommon::math::vec2ui) == sizeof(glm::uvec2), ""); static_assert(sizeof(rkcommon::math::vec3ui) == sizeof(glm::uvec3), ""); static_assert(sizeof(rkcommon::math::vec4ui) == sizeof(glm::uvec4), ""); static_assert(sizeof(rkcommon::math::linear2f) == sizeof(glm::mat2x2), ""); static_assert(sizeof(rkcommon::math::linear3f) == sizeof(glm::mat3x3), ""); static_assert(sizeof(rkcommon::math::affine2f) == sizeof(glm::mat3x2), ""); static_assert(sizeof(rkcommon::math::affine3f) == sizeof(glm::mat4x3), ""); // Test vecXf // glm::vec2 glm_vec2(1, 2); rkcommon::math::vec2f rk_vec2f; std::memcpy(&rk_vec2f, &glm_vec2, sizeof(rk_vec2f)); ASSERT_EQ(rk_vec2f.x, 1); ASSERT_EQ(rk_vec2f.y, 2); glm::vec3 glm_vec3(1, 2, 3); rkcommon::math::vec3f rk_vec3f; std::memcpy(&rk_vec3f, &glm_vec3, sizeof(rk_vec3f)); ASSERT_EQ(rk_vec3f.x, 1); ASSERT_EQ(rk_vec3f.y, 2); ASSERT_EQ(rk_vec3f.z, 3); glm::vec4 glm_vec4(1, 2, 3, 4); rkcommon::math::vec4f rk_vec4f; std::memcpy(&rk_vec4f, &glm_vec4, sizeof(rk_vec4f)); ASSERT_EQ(rk_vec4f.x, 1); ASSERT_EQ(rk_vec4f.y, 2); ASSERT_EQ(rk_vec4f.z, 3); ASSERT_EQ(rk_vec4f.w, 4); // Test vecXi // glm::ivec2 glm_ivec2(1, 2); rkcommon::math::vec2i rk_vec2i; std::memcpy(&rk_vec2i, &glm_ivec2, sizeof(rk_vec2i)); ASSERT_EQ(rk_vec2i.x, 1); ASSERT_EQ(rk_vec2i.y, 2); glm::ivec3 glm_ivec3(1, 2, 3); rkcommon::math::vec3i rk_vec3i; std::memcpy(&rk_vec3i, &glm_ivec3, sizeof(rk_vec3i)); ASSERT_EQ(rk_vec3i.x, 1); ASSERT_EQ(rk_vec3i.y, 2); ASSERT_EQ(rk_vec3i.z, 3); glm::ivec4 glm_ivec4(1, 2, 3, 4); rkcommon::math::vec4i rk_vec4i; std::memcpy(&rk_vec4i, &glm_ivec4, sizeof(rk_vec4i)); ASSERT_EQ(rk_vec4i.x, 1); ASSERT_EQ(rk_vec4i.y, 2); ASSERT_EQ(rk_vec4i.z, 3); ASSERT_EQ(rk_vec4i.w, 4); // Test vecXu // glm::uvec2 glm_uvec2(1, 2); rkcommon::math::vec2ui rk_vec2ui; std::memcpy(&rk_vec2ui, &glm_uvec2, sizeof(rk_vec2ui)); ASSERT_EQ(rk_vec2ui.x, 1); ASSERT_EQ(rk_vec2ui.y, 2); glm::uvec3 glm_uvec3(1, 2, 3); rkcommon::math::vec3ui rk_vec3ui; std::memcpy(&rk_vec3ui, &glm_uvec3, sizeof(rk_vec3ui)); ASSERT_EQ(rk_vec3ui.x, 1); ASSERT_EQ(rk_vec3ui.y, 2); ASSERT_EQ(rk_vec3ui.z, 3); glm::uvec4 glm_uvec4(1, 2, 3, 4); rkcommon::math::vec4ui rk_vec4ui; std::memcpy(&rk_vec4ui, &glm_uvec4, sizeof(rk_vec4ui)); ASSERT_EQ(rk_vec4ui.x, 1); ASSERT_EQ(rk_vec4ui.y, 2); ASSERT_EQ(rk_vec4ui.z, 3); ASSERT_EQ(rk_vec4ui.w, 4); // Matrix tests // // linear glm::mat2x2 glm_mat2x2(1.f); rkcommon::math::linear2f rk_linear2f; std::memcpy(&rk_linear2f, &glm_mat2x2, sizeof(rk_linear2f)); ASSERT_EQ(rk_linear2f.vx, rkcommon::math::vec2f(1, 0)); ASSERT_EQ(rk_linear2f.vy, rkcommon::math::vec2f(0, 1)); glm::mat3x3 glm_mat3x3(1.f); rkcommon::math::linear3f rk_linear3f; std::memcpy(&rk_linear3f, &glm_mat3x3, sizeof(rk_linear3f)); ASSERT_EQ(rk_linear3f.vx, rkcommon::math::vec3f(1, 0, 0)); ASSERT_EQ(rk_linear3f.vy, rkcommon::math::vec3f(0, 1, 0)); ASSERT_EQ(rk_linear3f.vz, rkcommon::math::vec3f(0, 0, 1)); // affine glm::mat4x3 glm_mat4x3 = glm::translate(glm::mat4(1.f), glm::vec3(1, 2, 3)); rkcommon::math::affine3f rk_affine3f; std::memcpy(&rk_affine3f, &glm_mat4x3, sizeof(rk_affine3f)); ASSERT_EQ(rk_affine3f.l.vx, rkcommon::math::vec3f(1, 0, 0)); ASSERT_EQ(rk_affine3f.l.vy, rkcommon::math::vec3f(0, 1, 0)); ASSERT_EQ(rk_affine3f.l.vz, rkcommon::math::vec3f(0, 0, 1)); ASSERT_EQ(rk_affine3f.p, rkcommon::math::vec3f(1, 2, 3)); } RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_imageop.cpp000066400000000000000000000034451456566705700241570ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ospray_testing.h" #include "test_fixture.h" namespace OSPRayTestScenes { class ImageOpBase : public Base { public: ImageOpBase() { samplesPerPixel = 4; } void SetUp() override; protected: std::string imageOp; }; void ImageOpBase::SetUp() { Base::SetUp(); instances.clear(); auto builder = ospray::testing::newBuilder("cornell_box"); ospray::testing::setParam(builder, "rendererType", rendererType); ospray::testing::commit(builder); world = ospray::testing::buildWorld(builder); ospray::testing::release(builder); camera.setParam("position", vec3f(0.f, 0.f, -2.5f)); cpp::ImageOperation imgOp(imageOp); framebuffer.setParam("imageOperation", cpp::CopiedData(imgOp)); framebuffer.commit(); } #ifdef OSPRAY_MODULE_DENOISER class DenoiserOp : public ImageOpBase, public ::testing::Test { public: DenoiserOp() { ospLoadModule("denoiser"); rendererType = "pathtracer"; imageOp = "denoiser"; } void SetUp() override { ImageOpBase::SetUp(); } }; #endif class ImageOp : public ImageOpBase, public ::testing::TestWithParam< std::tuple> { public: ImageOp() { auto params = GetParam(); imageOp = std::get<0>(params); rendererType = std::get<1>(params); } void SetUp() override { ImageOpBase::SetUp(); } }; // Test Instantiations ////////////////////////////////////////////////////// #ifdef OSPRAY_MODULE_DENOISER TEST_F(DenoiserOp, DenoiserOp) { PerformRenderTest(); } #endif TEST_P(ImageOp, ImageOp) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P( DebugOp, ImageOp, ::testing::Values(std::make_tuple("debug", "scivis"))); } // namespace OSPRayTestScenes RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_interpolation.cpp000066400000000000000000000067701456566705700254310ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ArcballCamera.h" #include "ospray_testing.h" #include "rkcommon/utility/random.h" #include "test_fixture.h" extern OSPRayEnvironment *ospEnv; namespace OSPRayTestScenes { class Interpolation : public Base, public ::testing::TestWithParam> { public: Interpolation(); void SetUp() override; void PerformRenderTest() override; protected: OSPFrameBufferChannel idBuffer{OSP_FB_COLOR}; bool useSubd{false}; unsigned int attribute{0}; unsigned int interpolation{0}; }; Interpolation::Interpolation() { samplesPerPixel = 2; rendererType = "scivis"; auto params = GetParam(); useSubd = std::get<0>(params); attribute = std::get<1>(params); interpolation = std::get<2>(params); if (attribute == 2) idBuffer = OSP_FB_NORMAL; } void Interpolation::SetUp() { Base::SetUp(); framebuffer = cpp::FrameBuffer(imgSize.x, imgSize.y, frameBufferFormat, idBuffer); instances.clear(); auto builder = ospray::testing::newBuilder("interpolation"); ospray::testing::setParam(builder, "rendererType", rendererType); ospray::testing::setParam(builder, "useSubd", useSubd); ospray::testing::setParam(builder, "attribute", attribute); ospray::testing::setParam(builder, "interpolation", interpolation); ospray::testing::commit(builder); world = ospray::testing::buildWorld(builder); ospray::testing::release(builder); } inline uint8_t to_uc(const float f) { return 255.f * clamp(f, 0.f, 1.0f); } inline uint32_t to_rgba8(const vec3f c) { return to_uc(c.x) | (to_uc(c.y) << 8) | (to_uc(c.z) << 16) | 0xff000000; } void Interpolation::PerformRenderTest() { if (!instances.empty()) world.setParam("instance", cpp::CopiedData(instances)); world.commit(); ArcballCamera arcballCamera(world.getBounds(), imgSize); camera.setParam("position", arcballCamera.eyePos()); camera.setParam("direction", arcballCamera.lookDir()); camera.setParam("up", arcballCamera.upDir()); camera.commit(); renderer.commit(); framebuffer.resetAccumulation(); RenderFrame(); auto *framebuffer_data = (uint32_t *)framebuffer.map(idBuffer); std::vector framebufferData(imgSize.product()); for (int i = 0; i < imgSize.product(); i++) { if (attribute == 2) { // normals const vec3f normal = ((vec3f *)framebuffer_data)[i]; framebufferData[i] = to_rgba8(0.5f * normal + 0.5f); } else framebufferData[i] = framebuffer_data[i]; } framebuffer.unmap(framebuffer_data); if (ospEnv->GetDumpImg()) { EXPECT_EQ( imageTool->saveTestImage(framebufferData.data()), OsprayStatus::Ok); } else { EXPECT_EQ(imageTool->compareImgWithBaseline(framebufferData.data()), OsprayStatus::Ok); } } // Test Instantiations ////////////////////////////////////////////////////// TEST_P(Interpolation, Interpolation) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Color, Interpolation, ::testing::Combine(::testing::Bool(), ::testing::Values(0), ::testing::Values(0, 1, 2, 3))); INSTANTIATE_TEST_SUITE_P(Texcoord, Interpolation, ::testing::Combine( ::testing::Bool(), ::testing::Values(1), ::testing::Values(0, 1))); INSTANTIATE_TEST_SUITE_P(Normal, Interpolation, ::testing::Combine(::testing::Values(false), ::testing::Values(2), ::testing::Values(0, 1))); } // namespace OSPRayTestScenes RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_light.cpp000066400000000000000000000505451456566705700236500ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_light.h" #include "ospray_testing.h" namespace OSPRayTestScenes { LightTest::LightTest() { samplesPerPixel = 16; // due to the way c0 in SpotLight is calculated we must rotate around X axis // to get the same result with SciVis and ring light (because its // approximation in SciVis is not rotation invariant) xfm = affine3f::translate(vec3f(1.f, 2.f, 3.f)) * affine3f::rotate(vec3f(1.f, 0.f, 0.f), pi); } void LightTest::SetUp() { Base::SetUp(); // set common renderer parameter if (rendererType == "pathtracer") renderer.setParam("maxPathLength", 1); if (rendererType == "scivis") { renderer.setParam("shadows", true); renderer.setParam("visibleLights", true); } // build cornell box scene auto builder = ospray::testing::newBuilder("cornell_box"); ospray::testing::setParam(builder, "rendererType", rendererType); ospray::testing::commit(builder); auto group = ospray::testing::buildGroup(builder); AddInstance(cpp::Instance(group)); ospray::testing::release(builder); // position camera camera.setParam("position", vec3f(0, 0, -2.4641)); } void LightTest::AddInstancedLightWithMB( cpp::Light light, const affine3f &xfm1, const affine3f &xfm2) { light.commit(); cpp::Group group; group.setParam("light", cpp::CopiedData(light)); group.commit(); cpp::Instance instance(group); const affine3f xfmR = rcp(xfm); if (motionBlur) { std::vector xfms; xfms.push_back(xfmR * xfm1); xfms.push_back(xfmR * xfm2); instance.setParam("motion.transform", cpp::CopiedData(xfms)); camera.setParam("shutter", range1f(0, 1)); } else instance.setParam("transform", xfmR); AddInstance(instance); } AmbientLight::AmbientLight() { rendererType = GetParam(); } void AmbientLight::SetUp() { LightTest::SetUp(); cpp::Light ambient = ospNewLight("ambient"); ambient.setParam("intensity", 0.5f); AddLight(ambient); if (rendererType == "scivis") renderer.setParam("aoSamples", 1); } DistantLight::DistantLight() { auto params = GetParam(); direction = std::get<0>(params); rendererType = std::get<1>(params); motionBlur = std::get<2>(params); } void DistantLight::SetUp() { LightTest::SetUp(); cpp::Light distant("distant"); distant.setParam("direction", xfmVector(xfm, direction)); distant.setParam("color", vec3f(1.0f, 0.75f, 0.25f)); distant.setParam("angularDiameter", 1.0f); AddInstancedLightWithRotateMB(distant); } GeometricLight::GeometricLight() { rendererType = "pathtracer"; auto params = GetParam(); size = std::get<0>(params); useMaterialList = std::get<1>(params); textureMode = std::get<2>(params); motionBlur = std::get<3>(params); } void GeometricLight::SetUp() { LightTest::SetUp(); const float area = size * size; const float halfSize = 0.5f * size; std::vector lightVertices = {{-halfSize, 0.98f, -halfSize}, {halfSize, 0.98f, -halfSize}, {halfSize, 0.98f, halfSize}, {-halfSize, 0.98f, halfSize}}; std::vector lightIndices = {{0, 1, 2, 3}}; cpp::Geometry lightMesh("mesh"); lightMesh.setParam("index", cpp::CopiedData(lightIndices)); if (motionBlur == 2) { // deformation for (vec3f &p : lightVertices) p.x -= 0.5f; std::vector mposdata; mposdata.push_back(cpp::CopiedData(lightVertices)); for (vec3f &p : lightVertices) p.x += 1.0f; mposdata.push_back(cpp::CopiedData(lightVertices)); lightMesh.setParam("motion.vertex.position", cpp::CopiedData(mposdata)); } else lightMesh.setParam("vertex.position", cpp::CopiedData(lightVertices)); if (textureMode == 2) { std::array data = {vec2f(0.3f, 0.4f), vec2f(1.3f, 0.4f), vec2f(1.3f, 1.4f), vec2f(0.3f, 1.4f)}; lightMesh.setParam("vertex.texcoord", cpp::CopiedData(data)); } lightMesh.commit(); cpp::GeometricModel lightModel(lightMesh); cpp::Material lightMaterial("luminous"); lightMaterial.setParam("intensity", 10.f / area); if (textureMode) { cpp::Texture tex("texture2d"); std::array data = {vec3f(0.f, 0.f, 0.f), vec3f(0.78f, 0.551f, 0.183f), vec3f(1.f, 1.f, 1.f), vec3f(0.f, 0.f, 1.f)}; cpp::CopiedData texData(data.data(), vec2ul(2, 2)); tex.setParam("format", OSP_TEXTURE_RGB32F); tex.setParam("filter", OSP_TEXTURE_FILTER_NEAREST); tex.setParam("data", texData); tex.commit(); lightMaterial.setParam("map_color", tex); if (textureMode == 2) lightMaterial.setParam("map_color.translation", vec2f(0.3f, 0.4f)); } else lightMaterial.setParam("color", vec3f(0.78f, 0.551f, 0.183f)); lightMaterial.commit(); if (useMaterialList) { std::vector materials{lightMaterial}; renderer.setParam("material", cpp::CopiedData(materials)); uint32_t materialIndex = 0; lightModel.setParam("material", materialIndex); } else { lightModel.setParam("material", lightMaterial); } if (motionBlur == 1) { // instance lightModel.commit(); cpp::Group group; group.setParam("geometry", cpp::CopiedData(lightModel)); group.commit(); cpp::Instance instance(group); std::vector xfms; xfms.push_back(affine3f::translate(vec3f(-0.5, 0, 0))); xfms.push_back(affine3f::translate(vec3f(0.5, 0, 0))); instance.setParam("motion.transform", cpp::CopiedData(xfms)); AddInstance(instance); } else AddModel(lightModel); if (motionBlur) camera.setParam("shutter", range1f(0, 1)); } PhotometricLight::PhotometricLight() { auto params = GetParam(); lightType = std::get<0>(params); size = std::get<1>(params); rendererType = std::get<2>(params); // area lights need a minimum size if (lightType == "quad") size = std::max(0.01f, size); } void PhotometricLight::SetUp() { LightTest::SetUp(); const vec3f pos1 = xfmPoint(xfm, vec3f(-0.6f, 0.8f, -0.5f)); const vec3f pos2 = xfmPoint(xfm, vec3f(0.3f, 0.6f, 0.f)); const vec3f dir = xfmVector(xfm, vec3f(0.0f, -1.0f, 0.0f)); const vec3f edge1 = xfmVector(xfm, vec3f(1.0f, 0.0f, 0.0f)); const vec3f edge2 = xfmVector(xfm, vec3f(0.0f, 0.0f, 1.0f)); cpp::Light light1d(lightType); light1d.setParam("intensity", 5.f); light1d.setParam("intensityQuantity", OSP_INTENSITY_QUANTITY_SCALE); float lid1d[] = {2.5f, 0.4f, 0.2f, 0.1f, 0.03f, 0.01f, 0.01f}; light1d.setParam("intensityDistribution", cpp::CopiedData(lid1d, 7)); if (lightType == "spot") { light1d.setParam("position", pos1); light1d.setParam("direction", dir); light1d.setParam("openingAngle", 360.f); light1d.setParam("penumbraAngle", 0.f); light1d.setParam("radius", size); } else if (lightType == "quad") { light1d.setParam("position", pos1 - size * edge1 - size * edge2); light1d.setParam("edge1", 2.0f * size * edge1); light1d.setParam("edge2", 2.0f * size * edge2); } else if (lightType == "sphere") { light1d.setParam("position", pos1); light1d.setParam("radius", size); light1d.setParam("direction", dir); } light1d.commit(); cpp::Light light2d(lightType); light2d.setParam("intensity", 1.f); light2d.setParam("intensityQuantity", OSP_INTENSITY_QUANTITY_SCALE); float lid2d[60] = { 1.5f, 5.0f, 6.0f, 0.3f, 0.01f, 0.15f, 0.5f, 1.6f, 0.1f, 0.01f}; light2d.setParam( "intensityDistribution", cpp::CopiedData(lid2d, vec2ul(5, 12))); light2d.setParam("c0", xfmVector(xfm, vec3f(1.0f, 0.0f, 0.0f))); if (lightType == "spot") { light2d.setParam("position", pos2); light2d.setParam("direction", dir); light2d.setParam("openingAngle", 270.f); light2d.setParam("penumbraAngle", 10.f); light2d.setParam("radius", size); } else if (lightType == "quad") { light2d.setParam("position", pos2 - size * edge1 - size * edge2); light2d.setParam("edge1", 2.0f * size * edge1); light2d.setParam("edge2", 2.0f * size * edge2); } else if (lightType == "sphere") { light2d.setParam("position", pos2); light2d.setParam("radius", size); light2d.setParam("direction", dir); } light2d.commit(); cpp::Group group; std::vector lights{light1d, light2d}; group.setParam("light", cpp::CopiedData(lights)); group.commit(); cpp::Instance instance(group); instance.setParam("transform", rcp(xfm)); AddInstance(instance); } QuadLight::QuadLight() { auto params = GetParam(); size = std::get<0>(params); rendererType = std::get<1>(params); intensityQuantity = std::get<2>(params); motionBlur = std::get<3>(params); } void QuadLight::SetUp() { LightTest::SetUp(); cpp::Light light("quad"); light.setParam("color", vec3f(0.78f, 0.551f, 0.183f)); light.setParam("intensity", 10.f); light.setParam("intensityQuantity", intensityQuantity); light.setParam( "position", xfmPoint(xfm, vec3f(size / -2.0f, 0.98f, size / -2.0f))); light.setParam("edge1", xfmVector(xfm, vec3f(size, 0.0f, 0.0f))); light.setParam("edge2", xfmVector(xfm, vec3f(0.0f, 0.0f, size))); AddInstancedLightWithTranslateMB(light); } CylinderLight::CylinderLight() { auto params = GetParam(); size = std::get<0>(params); rendererType = std::get<1>(params); intensityQuantity = std::get<2>(params); motionBlur = std::get<3>(params); } void CylinderLight::SetUp() { LightTest::SetUp(); cpp::Light light("cylinder"); light.setParam("color", vec3f(0.78f, 0.551f, 0.183f)); light.setParam("intensity", 5.0f); light.setParam("intensityQuantity", intensityQuantity); light.setParam( "position0", xfmPoint(xfm, vec3f(-0.2f - 2.0 * size, 0.65f, 0.0f))); light.setParam( "position1", xfmPoint(xfm, vec3f(0.2f + 2.0 * size, 0.65f, 0.0f))); light.setParam("radius", size); AddInstancedLightWithTranslateMB(light); } SphereLight::SphereLight() { auto params = GetParam(); radius = std::get<0>(params); rendererType = std::get<1>(params); intensityQuantity = std::get<2>(params); motionBlur = std::get<3>(params); } void SphereLight::SetUp() { LightTest::SetUp(); cpp::Light light("sphere"); light.setParam("color", vec3f(0.78f, 0.551f, 0.183f)); light.setParam("intensity", 2.5f); light.setParam("intensityQuantity", intensityQuantity); light.setParam("position", xfmPoint(xfm, vec3f(0.0f, 0.48f, 0.0f))); light.setParam("radius", radius); AddInstancedLightWithTranslateMB(light); } SpotLight::SpotLight() { auto params = GetParam(); innerOuterRadius = std::get<0>(params); rendererType = std::get<1>(params); intensityQuantity = std::get<2>(params); motionBlur = std::get<3>(params); } void SpotLight::SetUp() { LightTest::SetUp(); cpp::Light light("spot"); light.setParam("color", vec3f(0.78f, 0.551f, 0.183f)); light.setParam("intensity", 10.f); light.setParam("intensityQuantity", intensityQuantity); light.setParam("position", xfmPoint(xfm, vec3f(0.0f, 0.98f, 0.0f))); light.setParam("direction", xfmVector(xfm, vec3f(0.0f, -1.0f, 0.0f))); light.setParam("radius", innerOuterRadius[1]); light.setParam("innerRadius", innerOuterRadius[0]); AddInstancedLightWithTranslateMB(light); } HDRILight::HDRILight() { auto params = GetParam(); rendererType = std::get<0>(params); motionBlur = std::get<1>(params); } void HDRILight::SetUp() { Base::SetUp(); // set common renderer parameter if (rendererType == "pathtracer") renderer.setParam("maxPathLength", 1); if (rendererType == "scivis") { renderer.setParam("shadows", true); renderer.setParam("visibleLights", true); } // create sphere cpp::Group group; { cpp::Geometry sphere("sphere"); sphere.setParam("sphere.position", cpp::CopiedData(vec3f(0.f))); sphere.setParam("radius", 1.f); sphere.commit(); cpp::GeometricModel model(sphere); cpp::Material material("obj"); material.commit(); model.setParam("material", material); model.commit(); group.setParam("geometry", cpp::CopiedData(model)); group.commit(); } AddInstance(cpp::Instance(group)); // position camera camera.setParam("position", vec3f(0.f, 0.f, -3.f)); // prepare environment texture cpp::Texture envTex("texture2d"); { std::array data = {vec3f(0.f, 1.f, 1.f), vec3f(1.f, 0.f, 1.f), vec3f(1.f, 1.f, 0.f), vec3f(1.f, 1.f, 1.f), vec3f(0.f, 1.f, 1.f), vec3f(1.f, 0.f, 1.f), vec3f(1.f, 1.f, 0.f), vec3f(1.f, 1.f, 1.f), vec3f(1.f, 0.f, 0.f), vec3f(0.f, 1.f, 0.f), vec3f(0.f, 0.f, 1.f), vec3f(0.f, 0.f, 0.f), vec3f(1.f, 0.f, 0.f), vec3f(0.f, 1.f, 0.f), vec3f(0.f, 0.f, 1.f), vec3f(0.f, 0.f, 0.f)}; cpp::CopiedData texData(data.data(), vec2ul(4, 4)); envTex.setParam("format", OSP_TEXTURE_RGB32F); envTex.setParam("filter", OSP_TEXTURE_FILTER_NEAREST); envTex.setParam("data", texData); envTex.commit(); } // prepare light cpp::Light light("hdri"); light.setParam("color", vec3f(0.78f, 0.551f, 0.183f)); light.setParam("up", xfmVector(xfm, vec3f(0.f, 1.f, 0.f))); light.setParam("direction", xfmVector(xfm, vec3f(0.f, 0.f, 1.f))); light.setParam("map", envTex); AddInstancedLightWithRotateMB(light); renderer.setParam("backgroundColor", vec4f(0.f, 0.f, 0.f, 1.0f)); } SunSky::SunSky() { rendererType = "pathtracer"; samplesPerPixel = 1; auto params = GetParam(); motionBlur = std::get<5>(params); } void SunSky::SetUp() { Base::SetUp(); auto params = GetParam(); cpp::Light light("sunSky"); float turb = std::get<2>(params); light.setParam("up", xfmVector(xfm, std::get<0>(params))); light.setParam("direction", xfmVector(xfm, std::get<1>(params))); light.setParam("turbidity", turb); light.setParam("albedo", std::get<3>(params)); // lower brightness with high turbidity light.setParam("intensityQuantity", OSP_INTENSITY_QUANTITY_SCALE); light.setParam("intensity", 0.025f / turb); light.setParam("horizonExtension", std::get<4>(params)); AddInstancedLightWithRotateMB(light); renderer.setParam("backgroundColor", vec4f(0.f, 0.f, 0.f, 1.0f)); } // Test Instantiations ////////////////////////////////////////////////////// // Ambient Light TEST_P(AmbientLight, parameter) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P( Light, AmbientLight, ::testing::Values("scivis", "pathtracer")); // Distant Light TEST_P(DistantLight, parameter) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Light, DistantLight, ::testing::Combine( ::testing::Values(vec3f(0.0f, 0.0f, 1.0f), vec3f(-0.5f, 1.0f, 3.0f)), ::testing::Values("scivis", "pathtracer"), ::testing::Values(false))); INSTANTIATE_TEST_SUITE_P(LightMotionBlur, DistantLight, ::testing::Values( std::make_tuple(vec3f(-0.5f, 1.0f, 3.0f), "pathtracer", true))); // Geometric Light TEST_P(GeometricLight, parameter) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Light, GeometricLight, ::testing::Combine(::testing::Values(0.2f, 0.4f), ::testing::Bool(), ::testing::Values(0), ::testing::Values(0))); INSTANTIATE_TEST_SUITE_P(LightMotionBlur, GeometricLight, ::testing::Combine(::testing::Values(0.2f), ::testing::Values(false), ::testing::Values(0), ::testing::Values(1, 2))); INSTANTIATE_TEST_SUITE_P(LightTexture, GeometricLight, ::testing::Combine(::testing::Values(0.5f), ::testing::Values(false), ::testing::Values(1, 2), ::testing::Values(0))); // Quad Light TEST_P(QuadLight, parameter) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Light, QuadLight, ::testing::Combine(::testing::Values(0.2f, 0.4f), ::testing::Values("scivis", "pathtracer"), ::testing::Values(OSP_INTENSITY_QUANTITY_INTENSITY), ::testing::Values(false))); INSTANTIATE_TEST_SUITE_P(LightIntensityQuantity, QuadLight, ::testing::Combine(::testing::Values(0.2f, 0.4f), ::testing::Values("pathtracer"), ::testing::Values( OSP_INTENSITY_QUANTITY_RADIANCE, OSP_INTENSITY_QUANTITY_POWER), ::testing::Values(false))); INSTANTIATE_TEST_SUITE_P(LightMotionBlur, QuadLight, ::testing::Values(std::make_tuple( 0.2f, "pathtracer", OSP_INTENSITY_QUANTITY_INTENSITY, true))); // Cylinder Light TEST_P(CylinderLight, parameter) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Light, CylinderLight, ::testing::Combine(::testing::Values(0.02f, 0.15f), ::testing::Values("scivis", "pathtracer"), ::testing::Values(OSP_INTENSITY_QUANTITY_INTENSITY), ::testing::Values(false))); INSTANTIATE_TEST_SUITE_P(LightIntensityQuantity, CylinderLight, ::testing::Combine(::testing::Values(0.02f, 0.15), ::testing::Values("pathtracer"), ::testing::Values( OSP_INTENSITY_QUANTITY_RADIANCE, OSP_INTENSITY_QUANTITY_POWER), ::testing::Values(false))); INSTANTIATE_TEST_SUITE_P(LightMotionBlur, CylinderLight, ::testing::Values(std::make_tuple( 0.02f, "pathtracer", OSP_INTENSITY_QUANTITY_INTENSITY, true))); // Sphere Light TEST_P(SphereLight, parameter) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Light, SphereLight, ::testing::Combine(::testing::Values(0.0f, 0.2f, 0.3f), ::testing::Values("scivis", "pathtracer"), ::testing::Values(OSP_INTENSITY_QUANTITY_INTENSITY), ::testing::Values(false))); INSTANTIATE_TEST_SUITE_P(LightIntensityQuantity, SphereLight, ::testing::Combine(::testing::Values(0.0f, 0.2f, 0.3f), ::testing::Values("pathtracer"), ::testing::Values( OSP_INTENSITY_QUANTITY_RADIANCE, OSP_INTENSITY_QUANTITY_POWER), ::testing::Values(false))); INSTANTIATE_TEST_SUITE_P(LightMotionBlur, SphereLight, ::testing::Values(std::make_tuple( 0.3f, "pathtracer", OSP_INTENSITY_QUANTITY_RADIANCE, true))); // Spot Light TEST_P(SpotLight, parameter) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Light, SpotLight, ::testing::Combine(::testing::Values(vec2f(0.0f, 0.0f), vec2f(0.0f, 0.2f), vec2f(0.0f, 0.4f), vec2f(0.2f, 0.4f), vec2f(0.7f, 0.8f)), ::testing::Values("scivis", "pathtracer"), ::testing::Values(OSP_INTENSITY_QUANTITY_INTENSITY), ::testing::Values(false))); INSTANTIATE_TEST_SUITE_P(LightIntensityQuantity, SpotLight, ::testing::Combine( ::testing::Values( vec2f(0.0f, 0.0f), vec2f(0.0f, 0.2f), vec2f(0.0f, 0.4f)), ::testing::Values("pathtracer"), ::testing::Values( OSP_INTENSITY_QUANTITY_RADIANCE, OSP_INTENSITY_QUANTITY_POWER), ::testing::Values(false))); INSTANTIATE_TEST_SUITE_P(LightMotionBlur, SpotLight, ::testing::Values(std::make_tuple(vec2f(0.0f, 0.4f), "pathtracer", OSP_INTENSITY_QUANTITY_RADIANCE, true))); // Photometric (Spot) Light TEST_P(PhotometricLight, parameter) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Light, PhotometricLight, ::testing::Combine(::testing::Values("spot", "quad", "sphere"), ::testing::Values(0.0f, 0.1f), ::testing::Values("scivis", "pathtracer"))); // HDRI Light TEST_P(HDRILight, parameter) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Light, HDRILight, ::testing::Combine( ::testing::Values("scivis", "pathtracer"), ::testing::Values(false))); INSTANTIATE_TEST_SUITE_P(LightMotionBlur, HDRILight, ::testing::Values(std::make_tuple("pathtracer", true))); // SunSky Light TEST_P(SunSky, parameter) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Light, SunSky, ::testing::Combine(::testing::Values(vec3f(0.f, 0.8f, 0.4f)), ::testing::Values(vec3f(0.f, 0.7f, -1.f), vec3f(0.f, 0.4f, -1.f), vec3f(0.f, 0.1f, -1.f), vec3f(0.f, -0.3f, -1.f), vec3f(0.f, -0.8f, 0.4f)), ::testing::Values(1.0f, 3.0f, 10.0f), ::testing::Values(0.0f), ::testing::Values(0.01f), ::testing::Values(false))); INSTANTIATE_TEST_SUITE_P(Light2, SunSky, ::testing::Combine(::testing::Values(vec3f(0.2f, -0.5f, 0.f)), ::testing::Values(vec3f(0.2f, 0.4f, -1.f), vec3f(0.f, 0.f, -1.f)), ::testing::Values(2.0f), ::testing::Values(0.0f, 1.0f), ::testing::Values(0.1f), ::testing::Values(false))); INSTANTIATE_TEST_SUITE_P(LightMotionBlur, SunSky, ::testing::Values(std::make_tuple(vec3f(0.2f, -0.5f, 0.f), vec3f(0.2f, 0.4f, -1.f), 2.0f, 0.0f, 0.1f, true))); } // namespace OSPRayTestScenes RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_light.h000066400000000000000000000102731456566705700233070ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_fixture.h" namespace OSPRayTestScenes { class LightTest : public Base { public: LightTest(); void SetUp() override; void AddInstancedLightWithMB( cpp::Light light, const affine3f &xfm1, const affine3f &xfm2); void AddInstancedLightWithTranslateMB(cpp::Light light) { AddInstancedLightWithMB(light, affine3f::translate(vec3f(-0.5, 0, 0)), affine3f::translate(vec3f(0.5, 0, 0))); }; void AddInstancedLightWithRotateMB(cpp::Light light) { AddInstancedLightWithMB(light, affine3f::rotate(vec3f(0.f, 0.f, 1.f), -.25f * float(pi)), affine3f::rotate(vec3f(0.f, 0.f, 1.f), .25f * float(pi))); }; protected: affine3f xfm; bool motionBlur{false}; }; class AmbientLight : public LightTest, public ::testing::TestWithParam { public: AmbientLight(); void SetUp() override; }; class DistantLight : public LightTest, public ::testing::TestWithParam> { public: DistantLight(); void SetUp() override; private: vec3f direction{0.f, 0.f, 1.f}; }; class GeometricLight : public LightTest, public ::testing::TestWithParam> { public: GeometricLight(); void SetUp() override; private: float size{0.2}; bool useMaterialList{true}; int textureMode{0}; int motionBlur{0}; }; class PhotometricLight : public LightTest, public ::testing::TestWithParam> { public: PhotometricLight(); void SetUp() override; private: std::string lightType; float size{0.0}; }; class QuadLight : public LightTest, public ::testing::TestWithParam> { public: QuadLight(); void SetUp() override; private: float size{0.2}; OSPIntensityQuantity intensityQuantity{OSP_INTENSITY_QUANTITY_UNKNOWN}; }; class CylinderLight : public LightTest, public ::testing::TestWithParam> { public: CylinderLight(); void SetUp() override; private: float size{0.2}; OSPIntensityQuantity intensityQuantity{OSP_INTENSITY_QUANTITY_UNKNOWN}; }; class SphereLight : public LightTest, public ::testing::TestWithParam> { public: SphereLight(); void SetUp() override; private: float radius{0.0}; OSPIntensityQuantity intensityQuantity{OSP_INTENSITY_QUANTITY_UNKNOWN}; }; class SpotLight : public LightTest, public ::testing::TestWithParam> { public: SpotLight(); void SetUp() override; private: vec2f innerOuterRadius{0.0, 0.2}; OSPIntensityQuantity intensityQuantity{OSP_INTENSITY_QUANTITY_UNKNOWN}; }; class HDRILight : public LightTest, public ::testing::TestWithParam< std::tuple> { public: HDRILight(); void SetUp() override; }; class SunSky : public LightTest, public ::testing::TestWithParam> { public: SunSky(); void SetUp() override; }; } // namespace OSPRayTestScenes RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_motionblur.cpp000066400000000000000000000261021456566705700247230ustar00rootroot00000000000000// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ospray_testing.h" #include "test_fixture.h" namespace OSPRayTestScenes { class MotionBlurBoxes : public Base, public ::testing::TestWithParam> { public: MotionBlurBoxes(); void SetUp() override; protected: OSPStereoMode stereoMode{OSP_STEREO_NONE}; OSPShutterType shutterType{OSP_SHUTTER_GLOBAL}; float rollingShutterDuration{0.f}; }; MotionBlurBoxes::MotionBlurBoxes() { auto params = GetParam(); rendererType = std::get<0>(params); stereoMode = std::get<1>(params); shutterType = std::get<2>(params); rollingShutterDuration = std::get<3>(params); samplesPerPixel = rendererType == "pathtracer" ? 64 : 16; } void MotionBlurBoxes::SetUp() { Base::SetUp(); renderer.setParam("backgroundColor", vec4f(0.2, 0.2, 0.2, 1.0f)); camera.setParam("position", vec3f(0, 0, -9)); camera.setParam("stereoMode", stereoMode); camera.setParam("shutter", range1f(0.0f, 1.0f)); camera.setParam("shutterType", shutterType); camera.setParam("rollingShutterDuration", rollingShutterDuration); cpp::Geometry boxGeometry("box"); boxGeometry.setParam( "box", cpp::CopiedData(box3f(vec3f(-0.5f), vec3f(0.5f)))); boxGeometry.commit(); cpp::GeometricModel model(boxGeometry); cpp::Material material("obj"); material.setParam("kd", vec3f(0.8f, 0.1, 0.4)); material.setParam("ks", vec3f(0.2f)); material.setParam("ns", 99.f); material.commit(); model.setParam("material", material); model.commit(); cpp::Volume volume("structuredRegular"); std::vector volData(8); std::generate( volData.begin(), volData.end(), [n = 0]() mutable { return n++; }); volume.setParam("data", cpp::CopiedData(volData.data(), vec3ul(2))); volume.setParam("gridOrigin", vec3f(-0.5, 0.5, -0.5)); volume.setParam("filter", OSP_VOLUME_FILTER_NEAREST); volume.commit(); cpp::TransferFunction transferFun("piecewiseLinear"); transferFun.setParam("value", range1f(0.f, 7.f)); std::vector colors = {vec3f(1.0f, 0.5f, 0.5f), vec3f(0.5f, 1.0f, 0.5f), vec3f(0.5f, 1.0f, 1.0f), vec3f(0.5f, 0.5f, 1.0f)}; std::vector opacities = {0.1f, 1.0f}; transferFun.setParam("color", cpp::CopiedData(colors)); transferFun.setParam("opacity", cpp::CopiedData(opacities)); transferFun.commit(); cpp::VolumetricModel volModel(volume); volModel.setParam("transferFunction", transferFun); volModel.setParam("densityScale", 99.0f); volModel.commit(); cpp::Geometry sphereGeometry("sphere"); sphereGeometry.setParam( "sphere.position", cpp::CopiedData(vec3f(0.3f, 0.6f, -0.2f))); sphereGeometry.setParam("radius", 0.6f); sphereGeometry.commit(); cpp::GeometricModel clipModel(sphereGeometry); clipModel.commit(); cpp::Group group; group.setParam("geometry", cpp::CopiedData(model)); group.setParam("volume", cpp::CopiedData(volModel)); group.setParam("clippingGeometry", cpp::CopiedData(clipModel)); group.commit(); { // static original cpp::Instance instance(group); instance.setParam("transform", affine3f::rotate(vec3f(1, 1, 0.1), -0.4)); AddInstance(instance); } { // linear cpp::Instance instance(group); std::vector xfms; xfms.push_back(affine3f::translate(vec3f(3, -3, 0))); xfms.push_back(affine3f::translate(vec3f(2.5, -3, 0))); xfms.push_back(affine3f::translate(vec3f(2.2, -1, 0))); instance.setParam("motion.transform", cpp::CopiedData(xfms)); AddInstance(instance); } { // linear, time cpp::Instance instance(group); std::vector xfms; xfms.push_back(affine3f::translate(vec3f(5, -3, 0))); xfms.push_back(affine3f::translate(vec3f(4.5, -3, 0))); xfms.push_back(affine3f::translate(vec3f(4.2, -1, 0))); instance.setParam("motion.transform", cpp::CopiedData(xfms)); instance.setParam("time", range1f(-2, 0.8)); AddInstance(instance); } { // scale cpp::Instance instance(group); std::vector xfms; xfms.push_back(affine3f::translate(vec3f(1, 2, 0))); xfms.push_back(affine3f::translate(vec3f(1, 2, 0)) * affine3f::scale(vec3f(1.8, 0.9, 1))); instance.setParam("motion.transform", cpp::CopiedData(xfms)); AddInstance(instance); } { // rot cpp::Instance instance(group); std::vector xfms; xfms.push_back(affine3f::rotate(vec3f(0, 4, 0), vec3f(0, 0, 1), 0.8)); xfms.push_back(affine3f::rotate(vec3f(0, 4, 0), vec3f(0, 0, 1), 1.2)); xfms.push_back(affine3f::rotate(vec3f(0, 4, 0), vec3f(0, 0, 1), 1.6)); instance.setParam("motion.transform", cpp::CopiedData(xfms)); AddInstance(instance); } { // quaternion cpp::Instance instance(group); std::vector ss; ss.push_back(vec3f(0, -4, 0)); ss.push_back(vec3f(0, -4, 0)); ss.push_back(vec3f(0, -4, 0)); instance.setParam("motion.pivot", cpp::CopiedData(ss)); std::vector qs; qs.push_back(quatf::rotate(vec3f(0, 0, 1), -0.8)); qs.push_back(quatf::rotate(vec3f(0, 0, 1), -1.2)); qs.push_back(quatf::rotate(vec3f(0, 0, 1), -1.6)); instance.setParam("motion.rotation", cpp::CopiedData(qs)); std::vector ts; ts.push_back(vec3f(0, 4, 0)); ts.push_back(vec3f(0, 4, 0)); ts.push_back(vec3f(0, 4, 0)); instance.setParam("motion.translation", cpp::CopiedData(ts)); AddInstance(instance); } { // deformation std::vector pos = {vec3f(-3.0f, -3.5f, -0.5f), vec3f(-2.0f, -3.5f, -0.5f), vec3f(-2.0f, -2.5f, -0.5f), vec3f(-3.0f, -2.5f, -0.5f)}; std::vector nor(4, vec3f(0.0f, 0.0f, -1.0f)); std::vector mposdata; mposdata.push_back(cpp::CopiedData(pos)); std::vector mnordata; mnordata.push_back(cpp::CopiedData(nor)); for (vec3f &p : pos) p.x -= 1.5f; mposdata.push_back(cpp::CopiedData(pos)); for (vec3f &n : nor) n.x += 1.0f; mnordata.push_back(cpp::CopiedData(nor)); for (vec3f &p : pos) p = xfmPoint(quatf::rotate(vec3f(0.4, 0, 1), -0.1), p); mposdata.push_back(cpp::CopiedData(pos)); for (vec3f &n : nor) n.x -= 0.5f; mnordata.push_back(cpp::CopiedData(nor)); cpp::CopiedData mpos(mposdata); cpp::CopiedData mnor(mnordata); { // triangle cpp::Geometry geom("mesh"); geom.setParam("motion.vertex.position", mpos); geom.setParam("motion.vertex.normal", mnor); geom.setParam("index", cpp::CopiedData(vec3ui(0, 1, 2))); geom.commit(); cpp::GeometricModel model(geom); model.setParam("material", material); AddModel(model); } { // quad cpp::Geometry geom("mesh"); geom.setParam("motion.vertex.position", mpos); geom.setParam("motion.vertex.normal", mnor); geom.setParam("index", cpp::CopiedData(vec4ui(0, 1, 2, 3))); geom.commit(); cpp::GeometricModel model(geom); model.setParam("material", material); model.commit(); cpp::Group group; group.setParam("geometry", cpp::CopiedData(model)); group.commit(); cpp::Instance instance(group); instance.setParam("transform", affine3f::translate(vec3f(0, 1.5, 0))); AddInstance(instance); } } cpp::Light distant("distant"); distant.setParam("intensity", 3.0f); distant.setParam("direction", vec3f(0.3f, -4.0f, 2.8f)); distant.setParam("color", vec3f(1.0f, 0.5f, 0.5f)); distant.setParam("angularDiameter", 1.0f); AddLight(distant); cpp::Light ambient("ambient"); ambient.setParam("visible", false); ambient.setParam("intensity", 0.1f); AddLight(ambient); } // Test camera MB (also in combination with stereo) //////////////////////////// class MotionCamera : public Base, public ::testing::TestWithParam< std::tuple> { public: MotionCamera(); void SetUp() override; protected: std::string cameraType; vec3f pos{0.0f, 0.0f, -0.5f}; OSPStereoMode stereoMode{OSP_STEREO_NONE}; OSPShutterType shutterType{OSP_SHUTTER_GLOBAL}; }; MotionCamera::MotionCamera() { rendererType = "pathtracer"; samplesPerPixel = 64; auto params = GetParam(); cameraType = std::get<0>(params); stereoMode = std::get<1>(params); shutterType = std::get<2>(params); } void MotionCamera::SetUp() { Base::SetUp(); instances.clear(); auto builder = ospray::testing::newBuilder("cornell_box"); ospray::testing::setParam(builder, "rendererType", rendererType); ospray::testing::commit(builder); world = ospray::testing::buildWorld(builder); ospray::testing::release(builder); camera = cpp::Camera(cameraType); if (cameraType != "panoramic") { pos.z = -2.f; camera.setParam("aspect", imgSize.x / (float)imgSize.y); } camera.setParam("position", pos); if (cameraType == "orthographic") camera.setParam("height", 2.0f); else camera.setParam("stereoMode", stereoMode); std::vector xfms; xfms.push_back(affine3f::rotate(vec3f(0, 4, 0), vec3f(0, 0, 1), 0.1)); xfms.push_back(affine3f::rotate(vec3f(0, 4, 0), vec3f(0, 0, 1), 0.12)); camera.setParam("motion.transform", cpp::CopiedData(xfms)); camera.setParam("shutter", range1f(0.0f, 1.0f)); camera.setParam("shutterType", shutterType); } // Test Instantiations ////////////////////////////////////////////////////// TEST_P(MotionBlurBoxes, instance_mb) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(TestMotionBlur, MotionBlurBoxes, ::testing::Combine(::testing::Values("scivis", "pathtracer"), ::testing::Values(OSP_STEREO_NONE), ::testing::Values(OSP_SHUTTER_GLOBAL), ::testing::Values(0.f))); INSTANTIATE_TEST_SUITE_P(CameraRollingShutter, MotionBlurBoxes, ::testing::Combine(::testing::Values("pathtracer"), ::testing::Values(OSP_STEREO_NONE), ::testing::Values(OSP_SHUTTER_ROLLING_RIGHT, OSP_SHUTTER_ROLLING_LEFT, OSP_SHUTTER_ROLLING_DOWN, OSP_SHUTTER_ROLLING_UP), ::testing::Values(0.f, 0.1f))); INSTANTIATE_TEST_SUITE_P(CameraStereoRollingShutter, MotionBlurBoxes, ::testing::Combine(::testing::Values("pathtracer"), ::testing::Values(OSP_STEREO_TOP_BOTTOM), ::testing::Values(OSP_SHUTTER_ROLLING_DOWN), ::testing::Values(0.f))); TEST_P(MotionCamera, camera_mb) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Camera, MotionCamera, ::testing::Combine(::testing::Values("perspective", "panoramic"), ::testing::Values(OSP_STEREO_NONE, OSP_STEREO_RIGHT, OSP_STEREO_LEFT, OSP_STEREO_SIDE_BY_SIDE, OSP_STEREO_TOP_BOTTOM), ::testing::Values(OSP_SHUTTER_GLOBAL))); INSTANTIATE_TEST_SUITE_P(CameraOrtho, MotionCamera, ::testing::Values( std::make_tuple("orthographic", OSP_STEREO_NONE, OSP_SHUTTER_GLOBAL))); INSTANTIATE_TEST_SUITE_P(CameraStereoRollingShutter, MotionCamera, ::testing::Combine(::testing::Values("perspective"), ::testing::Values(OSP_STEREO_TOP_BOTTOM), ::testing::Values(OSP_SHUTTER_ROLLING_DOWN))); } // namespace OSPRayTestScenes RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_sharedusm_data.cpp000066400000000000000000000070131456566705700255150ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef SYCL_LANGUAGE_VERSION #include #include #include #include #include "test_fixture.h" extern OSPRayEnvironment *ospEnv; #include "sycl/sycl.hpp" namespace OSPRayTestScenes { // Fixture class for a unit test of gpu capable, data sharing class TestUSMSharing : public Base, public ::testing::TestWithParam { public: TestUSMSharing(); ~TestUSMSharing(); void SetUp() override; protected: std::string memoryType; // host, shared, device private: std::vector voxels; float *deviceVoxels = nullptr; }; TestUSMSharing::TestUSMSharing() { memoryType = GetParam(); } TestUSMSharing::~TestUSMSharing() { sycl::queue *appsSyclQueue = ospEnv->GetAppsSyclQueue(); if (appsSyclQueue) free(deviceVoxels, *appsSyclQueue); } void TestUSMSharing::SetUp() { Base::SetUp(); vec3i dims{100, 100, 100}; size_t numVoxels = dims.long_product(); voxels = std::vector(numVoxels); for (int x = 0; x < dims.x; ++x) { double dx = (double)x / (double)dims.x - 0.5; for (int y = 0; y < dims.y; ++y) { double dy = (double)y / (double)dims.y - 0.5; for (int z = 0; z < dims.z; ++z) { double dz = (double)z / (double)dims.z - 0.5; voxels[x * dims.y * dims.z + y * dims.z + z] = 1.0 - sqrt(dx * dx + dy * dy + dz * dz); } } } deviceVoxels = voxels.data(); sycl::queue *appsSyclQueue = ospEnv->GetAppsSyclQueue(); if (appsSyclQueue) { if (memoryType == "host") { deviceVoxels = sycl::malloc_host(numVoxels, *appsSyclQueue); } else if (memoryType == "device") { deviceVoxels = sycl::malloc_device(numVoxels, *appsSyclQueue); } else { deviceVoxels = sycl::malloc_shared(numVoxels, *appsSyclQueue); } appsSyclQueue->memcpy( deviceVoxels, voxels.data(), numVoxels * sizeof(float)); appsSyclQueue->wait(); } // create and setup camera camera.setParam("position", vec3f(200.f, 50.f, 50.f)); camera.setParam("up", vec3f(0.f, 1.f, 0.f)); camera.setParam("direction", vec3f(-1.f, 0.f, 0.f)); // create and setup model and mesh ospray::cpp::Volume volume("structuredRegular"); volume.setParam("data", cpp::SharedData(deviceVoxels, dims)); volume.commit(); ospray::cpp::TransferFunction tf("piecewiseLinear"); std::vector color = {vec3f(0.5f, 0.0f, 0.0f), vec3f(0.0f, 0.5f, 0.0f), vec3f(0.0f, 0.0f, 1.0f)}; std::vector opacity = {0.05f, 0.0f, 0.1f, 0.0f, 0.2f, 0.0f, 1.0f}; tf.setParam("value", box1f(0.14f, 1.0f)); tf.setParam("color", ospray::cpp::CopiedData(color)); tf.setParam("opacity", ospray::cpp::CopiedData(opacity)); tf.commit(); ospray::cpp::VolumetricModel vm(volume); vm.setParam("transferFunction", tf); vm.commit(); AddModel(vm); cpp::Light distant("distant"); distant.setParam("intensity", 3.0f); distant.setParam("direction", vec3f(0.3f, -4.0f, 0.8f)); distant.setParam("color", vec3f(1.0f, 0.5f, 0.5f)); distant.setParam("angularDiameter", 1.0f); AddLight(distant); cpp::Light ambient = ospNewLight("ambient"); ambient.setParam("intensity", 0.1f); AddLight(ambient); } // Test Instantiations ////////////////////////////////////////////////////// TEST_P(TestUSMSharing, structured_regular) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P( SharedData, TestUSMSharing, ::testing::Values("host", "shared", "device")); } // namespace OSPRayTestScenes #endif RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_tools.cpp000066400000000000000000000202411456566705700236670ustar00rootroot00000000000000// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #define STB_IMAGE_WRITE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION #include "test_tools.h" #include #include "rkcommon/utility/SaveImage.h" extern OSPRayEnvironment *ospEnv; OSPImageTools::OSPImageTools( vec2i imgSize, std::string testName, OSPFrameBufferFormat frameBufferFormat) : size(imgSize), imgName(testName) { switch (frameBufferFormat) { case OSP_FB_RGBA8: fileFormat = ".ppm"; break; case OSP_FB_SRGBA: fileFormat = ".png"; break; case OSP_FB_RGBA32F: fileFormat = ".pfm"; break; default: fileFormat = ".err"; break; } } OsprayStatus OSPImageTools::writePNG( std::string fileName, const uint32_t *pixel) { stbi_flip_vertically_on_write(true); int retCode = stbi_write_png( fileName.c_str(), size.x, size.y, ImgType::RGBA, (const void *)pixel, 0); if (!retCode) { std::cerr << "Failed to save image: " << fileName << std::endl; return OsprayStatus::Fail; } return OsprayStatus::Ok; } OsprayStatus OSPImageTools::writeHDR(std::string fileName, const float *pixel) { stbi_flip_vertically_on_write(true); int retCode = stbi_write_hdr(fileName.c_str(), size.x, size.y, ImgType::RGBA, pixel); if (!retCode) { std::cerr << "Failed to save image: " << fileName << std::endl; return OsprayStatus::Fail; } return OsprayStatus::Ok; } // helper function to write the rendered image OsprayStatus OSPImageTools::writeImg(std::string fileName, const void *pixel) { OsprayStatus writeErr = OsprayStatus::Error; fileName += GetFileFormat(); if (GetFileFormat() == ".ppm") { rkcommon::utility::writePPM( fileName, size.x, size.y, (const uint32_t *)pixel); writeErr = OsprayStatus::Ok; } else if (GetFileFormat() == ".png") { writeErr = writePNG(fileName, (const uint32_t *)pixel); } else if (GetFileFormat() == ".hdr") { writeErr = writeHDR(fileName, (const float *)pixel); } else if (GetFileFormat() == ".pfm") { try { rkcommon::utility::writePFM(fileName, size.x, size.y, (const vec4f *)pixel); writeErr = OsprayStatus::Ok; } catch (...) { writeErr = OsprayStatus::Fail; } } else { std::cerr << "Unsupported file format" << std::endl; writeErr = OsprayStatus::Error; } return writeErr; } OsprayStatus OSPImageTools::verifyBaselineImage(const int sizeX, const int sizeY, const void *baselineImage, const std::string &baselineName) { // Check if baseline image is suitable if (!baselineImage) { std::cerr << "Failed to load image: " << baselineName << std::endl; return OsprayStatus::Fail; } else if (sizeX != size.x || sizeY != size.y) { std::cerr << "Wrong image loaded for: " << baselineName << std::endl; return OsprayStatus::Fail; } return OsprayStatus::Ok; } vec4f OSPImageTools::getAveragedPixel(const vec4f *image, vec2i pixelIndex, const rkcommon::index_sequence_2D &imageIndices) { vec4f p(0.f); unsigned int count = 0; rkcommon::index_sequence_2D indices(vec2i(5)); for (vec2i id : indices) { vec2i pid = pixelIndex + (id - vec2i(2)); if ((reduce_min(pid) < 0) || (reduce_min(size - pid) < 1)) continue; p += image[imageIndices.flatten(pid)]; count++; } return p / float(count); } // compare the baseline image with the values form the framebuffer template OsprayStatus OSPImageTools::compareImgWithBaselineTmpl(const T *testImage, const T *baselineImage, const std::string &baselineName, const float pixelConversionFactor) { bool notPerfect = false; double totalError = 0.; rkcommon::index_sequence_2D imageIndices(size); std::vector diffAbsImage(imageIndices.total_indices()); { // Prepare temporary diff image with floats std::vector diffImage(imageIndices.total_indices()); for (vec2i i : imageIndices) { const unsigned int pixelIndex = imageIndices.flatten(i); const vec4f baselineValue = baselineImage[pixelIndex]; const vec4f renderedValue = testImage[pixelIndex]; diffImage[pixelIndex] = baselineValue - renderedValue; } for (vec2i i : imageIndices) { const unsigned int pixelIndex = imageIndices.flatten(i); const T diffValue = abs(diffImage[pixelIndex]); const vec4f diffAvgValue = abs(getAveragedPixel(diffImage.data(), i, imageIndices)); // Only count errors if above specified threshold, this removes blurred // noise const float pixelError = reduce_add(diffAvgValue) * pixelConversionFactor; if (pixelError > pixelThreshold) totalError += pixelError; // Not a perfect match if any difference detected notPerfect = notPerfect || reduce_add(diffValue); // Set values for output diff image diffAbsImage[pixelIndex] = diffValue; diffAbsImage[pixelIndex].w = std::numeric_limits::max(); } } if (notPerfect) std::cerr << "[ WARNING ] " << baselineName << " is not pixel perfect" << std::endl; double meanError = totalError / double(4 * size.x * size.y); if (totalError) { std::cerr << "[ STATISTIC] Total/mean error: " << totalError << "/" << std::fixed << std::setprecision(3) << meanError << std::endl; } bool failed = meanError > errorRate; if (failed) { writeImg( ospEnv->GetFailedDir() + "/" + imgName + "_baseline", baselineImage); writeImg(ospEnv->GetFailedDir() + "/" + imgName + "_rendered", testImage); writeImg( ospEnv->GetFailedDir() + "/" + imgName + "_diff", diffAbsImage.data()); } if (failed) return OsprayStatus::Fail; else return OsprayStatus::Ok; } OsprayStatus OSPImageTools::saveTestImage(const void *pixel) { return writeImg(ospEnv->GetBaselineDir() + "/" + imgName, pixel); } vec4f *loadPF4(std::string fileName, int &sizeX, int &sizeY) { std::ifstream ifs; ifs.open(fileName, std::ifstream::in | std::ifstream::binary); if (!ifs.good()) return nullptr; std::string header; std::getline(ifs, header); if (!ifs.good() || header != "PF4") return nullptr; ifs >> sizeX >> sizeY; std::getline(ifs, header); // eat newline after size information if (!ifs.good()) return nullptr; std::getline(ifs, header); if (!ifs.good() || header != "-1.0") return nullptr; size_t sz = sizeX * sizeY; vec4f *img = new vec4f[sz]; ifs.read((char*)img, sz * sizeof(float) * 4); if (!ifs.good()) return nullptr; ifs.close(); return img; } // compare the baseline image with the values form the framebuffer OsprayStatus OSPImageTools::compareImgWithBaseline(const void *testImage) { std::string baselineName = ospEnv->GetBaselineDir() + "/" + imgName + GetFileFormat(); stbi_set_flip_vertically_on_load(true); int dataX, dataY, dataN; OsprayStatus compErr = OsprayStatus::Error; if (GetFileFormat() == ".png") { vec4uc *baselineImage = (vec4uc *)stbi_load( baselineName.c_str(), &dataX, &dataY, &dataN, ImgType::RGBA); compErr = verifyBaselineImage(dataX, dataY, baselineImage, baselineName); if (compErr == OsprayStatus::Ok) compErr = compareImgWithBaselineTmpl( (vec4uc *)testImage, baselineImage, baselineName); if (baselineImage) stbi_image_free(baselineImage); } else if (GetFileFormat() == ".hdr") { vec4f *baselineImage = (vec4f *)stbi_loadf( baselineName.c_str(), &dataX, &dataY, &dataN, ImgType::RGBA); compErr = verifyBaselineImage(dataX, dataY, baselineImage, baselineName); if (compErr == OsprayStatus::Ok) compErr = compareImgWithBaselineTmpl( (vec4f *)testImage, baselineImage, baselineName, 255.0f); if (baselineImage) stbi_image_free(baselineImage); } else if (GetFileFormat() == ".pfm") { vec4f *baselineImage = loadPF4(baselineName, dataX, dataY); compErr = verifyBaselineImage(dataX, dataY, baselineImage, baselineName); if (compErr == OsprayStatus::Ok) compErr = compareImgWithBaselineTmpl( (vec4f *)testImage, baselineImage, baselineName, 255.0f); if (baselineImage) delete[] baselineImage; } else { std::cerr << "Unsupported file format" << std::endl; compErr = OsprayStatus::Error; } return compErr; } RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_tools.h000066400000000000000000000040721456566705700233400ustar00rootroot00000000000000// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include #include #include #include #include #include #include #include "environment.h" #include "stb_image.h" #include "stb_image_write.h" #include "rkcommon/utility/multidim_index_sequence.h" using pixelColorValue = float; const pixelColorValue pixelThreshold = 13.f; const float errorRate = 0.1; enum class OsprayStatus { Ok, Fail, Error, }; enum ImgType { Y = 1, YA, RGB, RGBA, }; class OSPImageTools { protected: vec2i size; std::string fileFormat; std::string imgName; std::string GetFileFormat() const { return fileFormat; } // helper method to write the rendered image as PNG file OsprayStatus writePNG(std::string fileName, const uint32_t *pixel); // helper method to write the rendered image as HDR file OsprayStatus writeHDR(std::string fileName, const float *pixel); // helper method to write the image with given format OsprayStatus writeImg(std::string fileName, const void *pixel); // average pixels over some window OsprayStatus verifyBaselineImage(const int sizeX, const int sizeY, const void *baselineImage, const std::string &baselineName); vec4f getAveragedPixel(const vec4f *image, vec2i pixelIndex, const rkcommon::index_sequence_2D &imageIndices); // compare gold image with fb but with storage type abstraction template OsprayStatus compareImgWithBaselineTmpl(const T *testImage, const T *baselineImage, const std::string &baselineName, const float pixelConversionFactor = 1.0f); public: OSPImageTools(vec2i imgSize, std::string testName, OSPFrameBufferFormat frameBufferFormat); ~OSPImageTools() = default; // helper method to saved rendered file OsprayStatus saveTestImage(const void *pixel); // helper method to compare gold image with current framebuffer render OsprayStatus compareImgWithBaseline(const void *testImage); }; RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_volumetric.cpp000066400000000000000000000177631456566705700247370ustar00rootroot00000000000000// Copyright 2017 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_volumetric.h" #include "ArcballCamera.h" #include "ospray_testing.h" #include "rkcommon/utility/multidim_index_sequence.h" namespace OSPRayTestScenes { // Helper functions ///////////////////////////////////////////////////////// // creates a torus // volumetric data: stores data of torus // returns created ospvolume of torus static cpp::Volume CreateTorus(const int size) { std::vector volumetricData(size * size * size); const float r = 30; const float R = 80; const int size_2 = size / 2; const vec3i dims = vec3i(size); rkcommon::index_sequence_3D idx(dims); for (vec3i i : idx) { const float X = i.x - size_2; const float Y = i.y - size_2; const float Z = i.z - size_2; const float d = (R - std::sqrt(Z * Z + Y * Y)); volumetricData[idx.flatten(i)] = r * r - d * d - X * X; } cpp::Volume torus("structuredRegular"); torus.setParam("data", cpp::CopiedData(volumetricData.data(), vec3ul(size))); torus.setParam("gridOrigin", vec3f(-0.5f)); torus.setParam("gridSpacing", vec3f(1.f / size)); torus.commit(); return torus; } ///////////////////////////////////////////////////////////////////////////// TextureVolumeTransform::TextureVolumeTransform() { rendererType = GetParam(); } void TextureVolumeTransform::SetUp() { Base::SetUp(); camera.setParam("position", vec3f(.66f, .66f, -2.5f)); camera.setParam("direction", vec3f(0.f, 0.f, 1.f)); camera.setParam("up", vec3f(0.f, 1.f, 0.f)); // Create transfer function cpp::TransferFunction transferFun("piecewiseLinear"); { std::vector colors = {vec3f(1.f, 0.f, 0.f), vec3f(0.f, 1.f, 0.f), vec3f(0.f, 1.f, 1.f), vec3f(1.f, 1.f, 0.f), vec3f(1.f, 1.f, 1.f), vec3f(1.f, 0.f, 1.f)}; std::vector opacities = {1.f, 1.f}; transferFun.setParam("value", range1f(-10000.f, 100.f)); transferFun.setParam("color", cpp::CopiedData(colors)); transferFun.setParam("opacity", cpp::CopiedData(opacities)); transferFun.commit(); } // Create volumetric model cpp::Volume volume = CreateTorus(256); volume.commit(); // Create volume texture cpp::Texture tex("volume"); tex.setParam("volume", volume); tex.setParam("transferFunction", transferFun); tex.commit(); // Create a single sphere geometry cpp::Geometry sphere("sphere"); { sphere.setParam("sphere.position", cpp::CopiedData(vec3f(0.f))); sphere.setParam("radius", 0.51f); sphere.commit(); } // Prepare material array constexpr uint32_t cols = 2; constexpr uint32_t rows = 2; std::array materials; { // Create materials for (uint32_t i = 0; i < cols * rows; i++) { cpp::Material mat("obj"); mat.setParam("map_kd", tex); mat.commit(); materials[i] = mat; } // Set scale materials[1].setParam("map_kd.transform", affine3f::scale(vec3f(1.2f))); materials[1].commit(); // Set rotation materials[2].setParam( "map_kd.transform", affine3f::rotate(vec3f(0.5, 0.2, 1), 1.f)); materials[2].commit(); } // Prepare instances rkcommon::index_sequence_2D idx(vec2i(cols, rows)); for (auto i : idx) { // Create geometric model cpp::GeometricModel model(sphere); model.setParam("material", materials[idx.flatten(i)]); model.commit(); // Create group cpp::Group group; group.setParam("geometry", cpp::CopiedData(model)); group.commit(); // Create instance cpp::Instance instance(group); instance.setParam( "transform", affine3f::translate(1.25f * vec3f(i.x, i.y, 0.f))); instance.commit(); AddInstance(instance); } cpp::Light ambient("ambient"); ambient.setParam("intensity", 0.5f); AddLight(ambient); } DepthCompositeVolume::DepthCompositeVolume() { auto params = GetParam(); rendererType = std::get<0>(params); bgColor = std::get<1>(params); } void DepthCompositeVolume::SetUp() { Base::SetUp(); camera.setParam("position", vec3f(0.f, 0.f, 1.f)); camera.setParam("direction", vec3f(0.f, 0.f, -1.f)); camera.setParam("up", vec3f(0.f, 1.f, 0.f)); cpp::Volume torus = CreateTorus(256); cpp::VolumetricModel volumetricModel(torus); cpp::TransferFunction transferFun("piecewiseLinear"); transferFun.setParam("value", range1f(-10000.f, 10000.f)); std::vector colors = { vec3f(1.0f, 0.0f, 0.0f), vec3f(0.0f, 1.0f, 0.0f)}; std::vector opacities = {0.05f, 1.0f}; transferFun.setParam("color", cpp::CopiedData(colors)); transferFun.setParam("opacity", cpp::CopiedData(opacities)); transferFun.commit(); volumetricModel.setParam("transferFunction", transferFun); volumetricModel.commit(); AddModel(volumetricModel); cpp::Texture depthTex("texture2d"); std::vector texData(imgSize.product()); for (int y = 0; y < imgSize.y; y++) { for (int x = 0; x < imgSize.x; x++) { const size_t index = imgSize.x * y + x; if (x < imgSize.x / 3) { texData[index] = 999.f; } else if (x < (imgSize.x * 2) / 3) { texData[index] = 0.75f; } else { texData[index] = 0.00001f; } } } depthTex.setParam("format", OSP_TEXTURE_R32F); depthTex.setParam("filter", OSP_TEXTURE_FILTER_NEAREST); depthTex.setParam("data", cpp::CopiedData(texData.data(), imgSize)); depthTex.commit(); renderer.setParam("map_maxDepth", depthTex); renderer.setParam("backgroundColor", bgColor); cpp::Light ambient("ambient"); ambient.setParam("intensity", 0.5f); AddLight(ambient); } UnstructuredVolume::UnstructuredVolume() { auto params = GetParam(); rendererType = std::get<0>(params); showCells = std::get<1>(params); } void UnstructuredVolume::SetUp() { Base::SetUp(); instances.clear(); auto builder = ospray::testing::newBuilder("unstructured_volume"); ospray::testing::setParam(builder, "rendererType", rendererType); ospray::testing::setParam(builder, "showCells", showCells); ospray::testing::commit(builder); world = ospray::testing::buildWorld(builder); ospray::testing::release(builder); world.commit(); auto worldBounds = world.getBounds(); ArcballCamera arcballCamera(worldBounds, imgSize); camera.setParam("position", arcballCamera.eyePos()); camera.setParam("direction", arcballCamera.lookDir()); camera.setParam("up", arcballCamera.upDir()); renderer.setParam("maxPathLength", 1); } // Test Instantiations ////////////////////////////////////////////////////// INSTANTIATE_TEST_SUITE_P(TestScenesVolumes, FromOsprayTesting, ::testing::Combine(::testing::Values("gravity_spheres_volume", "perlin_noise_volumes", "unstructured_volume_simple", "particle_volume", "vdb_volume", "vdb_volume_packed", "gravity_spheres_amr"), ::testing::Values("scivis", "pathtracer", "ao"), ::testing::Values(16))); INSTANTIATE_TEST_SUITE_P(TestScenesVolumesStrictParams, FromOsprayTesting, ::testing::Values(std::make_tuple("perlin_noise_many_volumes", "scivis", 4), std::make_tuple("perlin_noise_many_volumes", "pathtracer", 32), std::make_tuple("perlin_noise_many_volumes", "ao", 4))); TEST_P(UnstructuredVolume, simple) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(TestScenesVolumes, UnstructuredVolume, ::testing::Combine(::testing::Values("scivis", "pathtracer", "ao"), ::testing::Values(false, true))); TEST_P(TextureVolumeTransform, simple) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P( Renderers, TextureVolumeTransform, ::testing::Values("scivis")); TEST_P(DepthCompositeVolume, simple) { PerformRenderTest(); } INSTANTIATE_TEST_SUITE_P(Renderers, DepthCompositeVolume, ::testing::Combine(::testing::Values("scivis"), ::testing::Values(vec4f(0.f), vec4f(1.f), vec4f(0.f, 0.f, 0.f, 1.f), vec4f(1.f, 0.f, 0.f, 0.5f)))); } // namespace OSPRayTestScenes RenderKit-ospray-f2a61c2/apps/ospTestSuite/test_volumetric.h000066400000000000000000000025601456566705700243710ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_fixture.h" namespace OSPRayTestScenes { // Test a texture colored by a volume. Creates spheres colored by the torus // volume It's parametrized with type of the renderer. class TextureVolumeTransform_deprecated : public Base, public ::testing::TestWithParam { public: TextureVolumeTransform_deprecated(); void SetUp() override; }; class TextureVolumeTransform : public Base, public ::testing::TestWithParam { public: TextureVolumeTransform(); void SetUp() override; }; // Test a texture colored by a volume. Creates a sphere colored by the torus // volume It's parametrized with type of the renderer and background color class DepthCompositeVolume : public Base, public ::testing::TestWithParam> { public: DepthCompositeVolume(); void SetUp() override; private: vec4f bgColor; }; // Test an unstructured volume rendering. Generates a complex scene made of // different cell types. Parametrized with cells visibility boolean. class UnstructuredVolume : public Base, public ::testing::TestWithParam> { public: UnstructuredVolume(); void SetUp() override; private: bool showCells; }; } // namespace OSPRayTestScenes RenderKit-ospray-f2a61c2/apps/ospTutorial/000077500000000000000000000000001456566705700206375ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/ospTutorial/CMakeLists.txt000066400000000000000000000021071456566705700233770ustar00rootroot00000000000000## Copyright 2018 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 if (NOT OSPRAY_ENABLE_APPS_TUTORIALS) return() endif() # build ospTutorial, for demonstration and API testing add_executable(ospTutorial ${OSPRAY_RESOURCE} ospTutorial.c) target_link_libraries(ospTutorial PRIVATE ospray) ospray_sign_target(ospTutorial) # C++ version add_executable(ospTutorialCpp ${OSPRAY_RESOURCE} ospTutorial.cpp) target_link_libraries(ospTutorialCpp PRIVATE ospray_sdk) ospray_sign_target(ospTutorialCpp) # async version add_executable(ospTutorialAsync ${OSPRAY_RESOURCE} ospTutorialAsync.c) target_link_libraries(ospTutorialAsync PRIVATE ospray) ospray_sign_target(ospTutorialAsync) install(TARGETS ospTutorial ospTutorialCpp ospTutorialAsync DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT apps ) # GLM C++ version if (OSPRAY_APPS_ENABLE_GLM) add_executable(ospTutorialGLM ${OSPRAY_RESOURCE} ospTutorialGLM.cpp) target_link_libraries(ospTutorialGLM PRIVATE ospray ${GLM_TARGET}) install(TARGETS ospTutorialGLM DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT apps ) endif() RenderKit-ospray-f2a61c2/apps/ospTutorial/ospTutorial.c000066400000000000000000000160151456566705700233330ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This is a small example tutorial how to use OSPRay in an application. * * On Linux build it in the build_directory with * gcc -std=c99 ../apps/ospTutorial/ospTutorial.c \ * -I ../ospray/include -L . -lospray -Wl,-rpath,. -o ospTutorial * On Windows build it in the build_directory\$Configuration with * cl ..\..\apps\ospTutorial\ospTutorial.c -I ..\..\ospray\include ^ * -I ..\.. ospray.lib */ #include #include #include #ifdef _WIN32 #include #include #include #else #include #endif #include "ospray/ospray_util.h" // helper function to write the rendered image as PPM file void writePPM( const char *fileName, int size_x, int size_y, const uint32_t *pixel) { FILE *file = fopen(fileName, "wb"); if (!file) { fprintf(stderr, "fopen('%s', 'wb') failed: %d", fileName, errno); return; } fprintf(file, "P6\n%i %i\n255\n", size_x, size_y); unsigned char *out = (unsigned char *)alloca(3 * size_x); for (int y = 0; y < size_y; y++) { const unsigned char *in = (const unsigned char *)&pixel[(size_y - 1 - y) * size_x]; for (int x = 0; x < size_x; x++) { out[3 * x + 0] = in[4 * x + 0]; out[3 * x + 1] = in[4 * x + 1]; out[3 * x + 2] = in[4 * x + 2]; } fwrite(out, 3 * size_x, sizeof(char), file); } fprintf(file, "\n"); fclose(file); } int main(int argc, const char **argv) { // image size int imgSize_x = 1024; // width int imgSize_y = 768; // height // camera float cam_pos[] = {0.f, 0.f, 0.f}; float cam_up[] = {0.f, 1.f, 0.f}; float cam_view[] = {0.1f, 0.f, 1.f}; // triangle mesh data float vertex[] = {-1.0f, -1.0f, 3.0f, -1.0f, 1.0f, 3.0f, 1.0f, -1.0f, 3.0f, 0.1f, 0.1f, 0.3f}; float color[] = {0.9f, 0.5f, 0.5f, 1.0f, 0.8f, 0.8f, 0.8f, 1.0f, 0.8f, 0.8f, 0.8f, 1.0f, 0.5f, 0.9f, 0.5f, 1.0f}; int32_t index[] = {0, 1, 2, 1, 2, 3}; #ifdef _WIN32 int waitForKey = 0; CONSOLE_SCREEN_BUFFER_INFO csbi; if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) { // detect standalone console: cursor at (0,0)? waitForKey = csbi.dwCursorPosition.X == 0 && csbi.dwCursorPosition.Y == 0; } #endif printf("initialize OSPRay..."); // initialize OSPRay; OSPRay parses (and removes) its commandline parameters, // e.g. "--osp:debug" OSPError init_error = ospInit(&argc, argv); if (init_error != OSP_NO_ERROR) return init_error; printf("done\n"); printf("setting up camera..."); // create and setup camera OSPCamera camera = ospNewCamera("perspective"); ospSetFloat(camera, "aspect", imgSize_x / (float)imgSize_y); ospSetParam(camera, "position", OSP_VEC3F, cam_pos); ospSetParam(camera, "direction", OSP_VEC3F, cam_view); ospSetParam(camera, "up", OSP_VEC3F, cam_up); ospCommit(camera); // commit each object to indicate modifications are done printf("done\n"); printf("setting up scene..."); // create and setup model and mesh OSPGeometry mesh = ospNewGeometry("mesh"); OSPData data = ospNewSharedData1D(vertex, OSP_VEC3F, 4); // alternatively with an OSPRay managed OSPData // OSPData managed = ospNewData1D(OSP_VEC3F, 4); // ospCopyData1D(data, managed, 0); ospCommit(data); ospSetObject(mesh, "vertex.position", data); ospRelease(data); // we are done using this handle data = ospNewSharedData1D(color, OSP_VEC4F, 4); ospCommit(data); ospSetObject(mesh, "vertex.color", data); ospRelease(data); data = ospNewSharedData1D(index, OSP_VEC3UI, 2); ospCommit(data); ospSetObject(mesh, "index", data); ospRelease(data); ospCommit(mesh); OSPMaterial mat = ospNewMaterial("obj"); ospCommit(mat); // put the mesh into a model OSPGeometricModel model = ospNewGeometricModel(mesh); ospSetObject(model, "material", mat); ospCommit(model); ospRelease(mesh); ospRelease(mat); // put the model into a group (collection of models) OSPGroup group = ospNewGroup(); ospSetObjectAsData(group, "geometry", OSP_GEOMETRIC_MODEL, model); ospCommit(group); ospRelease(model); // put the group into an instance (give the group a world transform) OSPInstance instance = ospNewInstance(group); ospCommit(instance); ospRelease(group); // put the instance in the world OSPWorld world = ospNewWorld(); ospSetObjectAsData(world, "instance", OSP_INSTANCE, instance); ospRelease(instance); // create and setup light for Ambient Occlusion OSPLight light = ospNewLight("ambient"); ospCommit(light); ospSetObjectAsData(world, "light", OSP_LIGHT, light); ospRelease(light); ospCommit(world); printf("done\n"); // print out world bounds OSPBounds worldBounds = ospGetBounds(world); printf("world bounds: ({%f, %f, %f}, {%f, %f, %f}\n\n", worldBounds.lower[0], worldBounds.lower[1], worldBounds.lower[2], worldBounds.upper[0], worldBounds.upper[1], worldBounds.upper[2]); printf("setting up renderer..."); // create renderer OSPRenderer renderer = ospNewRenderer("pathtracer"); // choose path tracing renderer // complete setup of renderer ospSetFloat(renderer, "backgroundColor", 1.0f); // white, transparent ospCommit(renderer); // create and setup framebuffer OSPFrameBuffer framebuffer = ospNewFrameBuffer(imgSize_x, imgSize_y, OSP_FB_SRGBA, OSP_FB_COLOR | /*OSP_FB_DEPTH |*/ OSP_FB_ACCUM); ospResetAccumulation(framebuffer); printf("rendering initial frame to firstFrame.ppm..."); // render one frame ospRenderFrameBlocking(framebuffer, renderer, camera, world); // access framebuffer and write its content as PPM file const uint32_t *fb = (uint32_t *)ospMapFrameBuffer(framebuffer, OSP_FB_COLOR); writePPM("firstFrame.ppm", imgSize_x, imgSize_y, fb); ospUnmapFrameBuffer(fb, framebuffer); printf("done\n"); printf("rendering 10 accumulated frames to accumulatedFrame.ppm..."); // render 10 more frames, which are accumulated to result in a better // converged image for (int frames = 0; frames < 10; frames++) ospRenderFrameBlocking(framebuffer, renderer, camera, world); fb = (uint32_t *)ospMapFrameBuffer(framebuffer, OSP_FB_COLOR); writePPM("accumulatedFrame.ppm", imgSize_x, imgSize_y, fb); ospUnmapFrameBuffer(fb, framebuffer); printf("done\n\n"); OSPPickResult p; ospPick(&p, framebuffer, renderer, camera, world, 0.5f, 0.5f); printf("ospPick() center of screen --> [inst: %p, model: %p, prim: %u]\n", p.instance, p.model, p.primID); printf("cleaning up objects..."); // cleanup pick handles (because p.hasHit was 'true') ospRelease(p.instance); ospRelease(p.model); // final cleanups ospRelease(renderer); ospRelease(camera); ospRelease(framebuffer); ospRelease(world); printf("done\n"); ospShutdown(); #ifdef _WIN32 if (waitForKey) { printf("\n\tpress any key to exit"); _getch(); } #endif return 0; } RenderKit-ospray-f2a61c2/apps/ospTutorial/ospTutorial.cpp000066400000000000000000000126111456566705700236710ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This is a small example tutorial how to use OSPRay in an application. * * On Linux build it in the build_directory with * g++ ../apps/ospTutorial/ospTutorial.cpp -I ../ospray/include \ * -I ../../rkcommon -L . -lospray -Wl,-rpath,. -o ospTutorial * On Windows build it in the build_directory\$Configuration with * cl ..\..\apps\ospTutorial\ospTutorial.cpp /EHsc -I ..\..\ospray\include ^ * -I ..\.. -I ..\..\..\rkcommon ospray.lib * Above commands assume that rkcommon is present in a directory right "next * to" the OSPRay directory. If this is not the case, then adjust the include * path (alter "-I " appropriately). */ #include #include #include #ifdef _WIN32 #define NOMINMAX #include #include #include #else #include #endif #include #include "ospray/ospray_cpp.h" #include "ospray/ospray_cpp/ext/rkcommon.h" #include "rkcommon/utility/SaveImage.h" using namespace rkcommon::math; int main(int argc, const char **argv) { // image size vec2i imgSize; imgSize.x = 1024; // width imgSize.y = 768; // height // camera vec3f cam_pos{0.f, 0.f, 0.f}; vec3f cam_up{0.f, 1.f, 0.f}; vec3f cam_view{0.1f, 0.f, 1.f}; // triangle mesh data std::vector vertex = {vec3f(-1.0f, -1.0f, 3.0f), vec3f(-1.0f, 1.0f, 3.0f), vec3f(1.0f, -1.0f, 3.0f), vec3f(0.1f, 0.1f, 0.3f)}; std::vector color = {vec4f(0.9f, 0.5f, 0.5f, 1.0f), vec4f(0.8f, 0.8f, 0.8f, 1.0f), vec4f(0.8f, 0.8f, 0.8f, 1.0f), vec4f(0.5f, 0.9f, 0.5f, 1.0f)}; std::vector index = {vec3ui(0, 1, 2), vec3ui(1, 2, 3)}; #ifdef _WIN32 bool waitForKey = false; CONSOLE_SCREEN_BUFFER_INFO csbi; if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) { // detect standalone console: cursor at (0,0)? waitForKey = csbi.dwCursorPosition.X == 0 && csbi.dwCursorPosition.Y == 0; } #endif // initialize OSPRay; OSPRay parses (and removes) its commandline parameters, // e.g. "--osp:debug" OSPError init_error = ospInit(&argc, argv); if (init_error != OSP_NO_ERROR) return init_error; // use scoped lifetimes of wrappers to release everything before ospShutdown() { // create and setup camera ospray::cpp::Camera camera("perspective"); camera.setParam("aspect", imgSize.x / (float)imgSize.y); camera.setParam("position", cam_pos); camera.setParam("direction", cam_view); camera.setParam("up", cam_up); camera.commit(); // commit each object to indicate modifications are done // create and setup model and mesh ospray::cpp::Geometry mesh("mesh"); mesh.setParam("vertex.position", ospray::cpp::CopiedData(vertex)); mesh.setParam("vertex.color", ospray::cpp::CopiedData(color)); mesh.setParam("index", ospray::cpp::CopiedData(index)); mesh.commit(); // put the mesh into a model ospray::cpp::GeometricModel model(mesh); model.commit(); // put the model into a group (collection of models) ospray::cpp::Group group; group.setParam("geometry", ospray::cpp::CopiedData(model)); group.commit(); // put the group into an instance (give the group a world transform) ospray::cpp::Instance instance(group); instance.commit(); // put the instance in the world ospray::cpp::World world; world.setParam("instance", ospray::cpp::CopiedData(instance)); // create and setup light for Ambient Occlusion ospray::cpp::Light light("ambient"); light.commit(); world.setParam("light", ospray::cpp::CopiedData(light)); world.commit(); // create renderer, choose Scientific Visualization renderer ospray::cpp::Renderer renderer("scivis"); // complete setup of renderer renderer.setParam("aoSamples", 1); renderer.setParam("backgroundColor", 1.0f); // white, transparent renderer.commit(); // create and setup framebuffer ospray::cpp::FrameBuffer framebuffer( imgSize.x, imgSize.y, OSP_FB_SRGBA, OSP_FB_COLOR | OSP_FB_ACCUM); framebuffer.clear(); // render one frame framebuffer.renderFrame(renderer, camera, world); // access framebuffer and write its content as PPM file uint32_t *fb = (uint32_t *)framebuffer.map(OSP_FB_COLOR); rkcommon::utility::writePPM("firstFrameCpp.ppm", imgSize.x, imgSize.y, fb); framebuffer.unmap(fb); std::cout << "rendering initial frame to firstFrameCpp.ppm" << std::endl; // render 10 more frames, which are accumulated to result in a better // converged image for (int frames = 0; frames < 10; frames++) framebuffer.renderFrame(renderer, camera, world); fb = (uint32_t *)framebuffer.map(OSP_FB_COLOR); rkcommon::utility::writePPM( "accumulatedFrameCpp.ppm", imgSize.x, imgSize.y, fb); framebuffer.unmap(fb); std::cout << "rendering 10 accumulated frames to accumulatedFrameCpp.ppm" << std::endl; ospray::cpp::PickResult res = framebuffer.pick(renderer, camera, world, 0.5f, 0.5f); if (res.hasHit) { std::cout << "picked geometry [instance: " << res.instance.handle() << ", model: " << res.model.handle() << ", primitive: " << res.primID << "]" << std::endl; } } ospShutdown(); #ifdef _WIN32 if (waitForKey) { printf("\n\tpress any key to exit"); _getch(); } #endif return 0; } RenderKit-ospray-f2a61c2/apps/ospTutorial/ospTutorialAsync.c000066400000000000000000000270731456566705700243370ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This is a small example tutorial of how to use OSPRay's async API in an * application. We setup up two scenes which are rendered asynchronously * in parallel to each other. */ #include #include #include #ifdef _WIN32 #include #include #include #else #include #endif #include "ospray/ospray_util.h" typedef struct { int x, y; } vec2i; // helper function to write the rendered image as PPM file void writePPM(const char *fileName, const vec2i *size, const uint32_t *pixel) { FILE *file = fopen(fileName, "wb"); if (!file) { fprintf(stderr, "fopen('%s', 'wb') failed: %d", fileName, errno); return; } fprintf(file, "P6\n%i %i\n255\n", size->x, size->y); unsigned char *out = (unsigned char *)alloca(3 * size->x); for (int y = 0; y < size->y; y++) { const unsigned char *in = (const unsigned char *)&pixel[(size->y - 1 - y) * size->x]; for (int x = 0; x < size->x; x++) { out[3 * x + 0] = in[4 * x + 0]; out[3 * x + 1] = in[4 * x + 1]; out[3 * x + 2] = in[4 * x + 2]; } fwrite(out, 3 * size->x, sizeof(char), file); } fprintf(file, "\n"); fclose(file); } void buildScene1(OSPCamera *camera, OSPWorld *world, OSPRenderer *renderer, OSPFrameBuffer *framebuffer, vec2i imgSize); void buildScene2(OSPCamera *camera, OSPWorld *world, OSPRenderer *renderer, OSPFrameBuffer *framebuffer, vec2i imgSize); int main(int argc, const char **argv) { #ifdef _WIN32 int waitForKey = 0; CONSOLE_SCREEN_BUFFER_INFO csbi; if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) { // detect standalone console: cursor at (0,0)? waitForKey = csbi.dwCursorPosition.X == 0 && csbi.dwCursorPosition.Y == 0; } #endif // initialize OSPRay; OSPRay parses (and removes) its commandline parameters, // e.g. "--osp:debug" OSPError init_error = ospInit(&argc, argv); if (init_error != OSP_NO_ERROR) return init_error; vec2i imgSizes[2] = {0}; imgSizes[0].x = 1024; // width imgSizes[0].y = 768; // height imgSizes[1].x = 800; imgSizes[1].y = 600; OSPCamera cameras[2] = {0}; OSPWorld worlds[2] = {0}; OSPRenderer renderers[2] = {0}; OSPFrameBuffer framebuffers[2] = {0}; buildScene1( &cameras[0], &worlds[0], &renderers[0], &framebuffers[0], imgSizes[0]); buildScene2( &cameras[1], &worlds[1], &renderers[1], &framebuffers[1], imgSizes[1]); printf("starting renders...\n"); OSPFuture futures[2] = {0}; // render one frame for each scene for (int i = 0; i < 2; ++i) { futures[i] = ospRenderFrame(framebuffers[i], renderers[i], cameras[i], worlds[i]); } for (int i = 0; i < 2; ++i) { int isFinished = ospIsReady(futures[i], OSP_TASK_FINISHED); printf("status of 'futures[%i]' is %i\n", i, isFinished); } // We don't need to wait for them in the order they were started for (int i = 1; i >= 0; --i) { ospWait(futures[i], OSP_FRAME_FINISHED); printf("...done, variance of render %i was %f\n", i, ospGetVariance(framebuffers[i])); ospRelease(futures[i]); } // access framebuffer and write its content as PPM file const uint32_t *fb = (uint32_t *)ospMapFrameBuffer(framebuffers[0], OSP_FB_COLOR); writePPM("firstFrame-scene1.ppm", &imgSizes[0], fb); ospUnmapFrameBuffer(fb, framebuffers[0]); printf("wrote rendered scene 1 to firstFrame-scene1.ppm\n"); fb = (uint32_t *)ospMapFrameBuffer(framebuffers[1], OSP_FB_COLOR); writePPM("firstFrame-scene2.ppm", &imgSizes[1], fb); ospUnmapFrameBuffer(fb, framebuffers[1]); printf("wrote rendered scene 2 to firstFrame-scene2.ppm\n"); // render 10 more frames, which are accumulated to result in a better // converged image printf("starting accumulation...\n"); for (int frames = 0; frames < 10; frames++) { for (int i = 0; i < 2; ++i) { futures[i] = ospRenderFrame(framebuffers[i], renderers[i], cameras[i], worlds[i]); } for (int i = 0; i < 2; ++i) { ospWait(futures[i], OSP_FRAME_FINISHED); if (frames < 9) // don't release future of last frame yet ospRelease(futures[i]); } } for (int i = 1; i >= 0; --i) { printf("...done, variance of render %i is now %f\n", i, ospGetVariance(framebuffers[i])); ospRelease(futures[i]); } fb = (uint32_t *)ospMapFrameBuffer(framebuffers[0], OSP_FB_COLOR); writePPM("accumulatedFrame-scene1.ppm", &imgSizes[0], fb); ospUnmapFrameBuffer(fb, framebuffers[0]); printf("wrote accumulated scene 1 to accumulatedFrame-scene1.ppm\n"); fb = (uint32_t *)ospMapFrameBuffer(framebuffers[1], OSP_FB_COLOR); writePPM("accumulatedFrame-scene2.ppm", &imgSizes[1], fb); ospUnmapFrameBuffer(fb, framebuffers[1]); printf("wrote accumulated scene 2 to accumulatedFrame-scene2.ppm\n"); // final cleanups for (int i = 0; i < 2; ++i) { ospRelease(cameras[i]); ospRelease(worlds[i]); ospRelease(renderers[i]); ospRelease(framebuffers[i]); } printf("shutting down\n"); ospShutdown(); #ifdef _WIN32 if (waitForKey) { printf("\n\tpress any key to exit"); _getch(); } #endif return 0; } void buildScene1(OSPCamera *camera, OSPWorld *world, OSPRenderer *renderer, OSPFrameBuffer *framebuffer, vec2i imgSize) { // camera float cam_pos[] = {0.f, 0.f, 0.f}; float cam_up[] = {0.f, 1.f, 0.f}; float cam_view[] = {0.1f, 0.f, 1.f}; // triangle mesh data static float vertex[] = {-1.0f, -1.0f, 3.0f, -1.0f, 1.0f, 3.0f, 1.0f, -1.0f, 3.0f, 0.1f, 0.1f, 0.3f}; static float color[] = {0.9f, 0.5f, 0.5f, 1.0f, 0.8f, 0.8f, 0.8f, 1.0f, 0.8f, 0.8f, 0.8f, 1.0f, 0.5f, 0.9f, 0.5f, 1.0f}; static int32_t index[] = {0, 1, 2, 1, 2, 3}; // create and setup camera *camera = ospNewCamera("perspective"); ospSetFloat(*camera, "aspect", imgSize.x / (float)imgSize.y); ospSetParam(*camera, "pos", OSP_VEC3F, cam_pos); ospSetParam(*camera, "dir", OSP_VEC3F, cam_view); ospSetParam(*camera, "up", OSP_VEC3F, cam_up); ospCommit(*camera); // commit each object to indicate modifications are done // create and setup model and mesh OSPGeometry mesh = ospNewGeometry("mesh"); OSPData data = ospNewSharedData1D(vertex, OSP_VEC3F, 4); ospCommit(data); ospSetObject(mesh, "vertex.position", data); ospRelease(data); // we are done using this handle data = ospNewSharedData1D(color, OSP_VEC4F, 4); ospCommit(data); ospSetObject(mesh, "vertex.color", data); ospRelease(data); data = ospNewSharedData1D(index, OSP_VEC3UI, 2); ospCommit(data); ospSetObject(mesh, "index", data); ospRelease(data); ospCommit(mesh); // put the mesh into a model static OSPGeometricModel model; model = ospNewGeometricModel(mesh); ospCommit(model); ospRelease(mesh); // put the model into a group (collection of models) OSPGroup group = ospNewGroup(); OSPData models = ospNewSharedData1D(&model, OSP_GEOMETRIC_MODEL, 1); ospSetObject(group, "geometry", models); ospCommit(group); ospRelease(model); ospRelease(models); // put the group into an instance (give the group a world transform) static OSPInstance instance; instance = ospNewInstance(group); ospCommit(instance); ospRelease(group); // put the instance in the world *world = ospNewWorld(); OSPData instances = ospNewSharedData1D(&instance, OSP_INSTANCE, 1); ospSetObject(*world, "instance", instances); // create and setup light for Ambient Occlusion static OSPLight light; light = ospNewLight("ambient"); ospCommit(light); OSPData lights = ospNewSharedData1D(&light, OSP_LIGHT, 1); ospCommit(lights); ospSetObject(*world, "light", lights); ospCommit(*world); ospRelease(instance); ospRelease(instances); // create renderer *renderer = ospNewRenderer("scivis"); // choose Scientific Visualization renderer // complete setup of renderer ospSetInt(*renderer, "aoSamples", 1); ospSetFloat(*renderer, "backgroundColor", 1.0f); // white, transparent ospCommit(*renderer); ospRelease(light); ospRelease(lights); // create and setup framebuffer *framebuffer = ospNewFrameBuffer(imgSize.x, imgSize.y, OSP_FB_SRGBA, OSP_FB_COLOR | /*OSP_FB_DEPTH |*/ OSP_FB_ACCUM | OSP_FB_VARIANCE); } void buildScene2(OSPCamera *camera, OSPWorld *world, OSPRenderer *renderer, OSPFrameBuffer *framebuffer, vec2i imgSize) { // camera float cam_pos[] = {2.0f, -1.f, -4.f}; float cam_up[] = {0.f, 1.f, 0.f}; float cam_view[] = {-0.2f, 0.25f, 1.f}; // triangle mesh data static float vertex[] = {-2.0f, -2.0f, 2.0f, -2.0f, 3.0f, 2.0f, 2.0f, -2.0f, 2.0f, 0.1f, -0.1f, 1.f}; static float color[] = {0.0f, 0.1f, 0.8f, 1.0f, 0.8f, 0.8f, 0.0f, 1.0f, 0.8f, 0.8f, 0.0f, 1.0f, 0.9f, 0.1f, 0.0f, 1.0f}; static int32_t index[] = {0, 1, 2, 1, 2, 3}; // create and setup camera *camera = ospNewCamera("perspective"); ospSetFloat(*camera, "aspect", imgSize.x / (float)imgSize.y); ospSetParam(*camera, "pos", OSP_VEC3F, cam_pos); ospSetParam(*camera, "dir", OSP_VEC3F, cam_view); ospSetParam(*camera, "up", OSP_VEC3F, cam_up); ospCommit(*camera); // commit each object to indicate modifications are done // create and setup model and mesh OSPGeometry mesh = ospNewGeometry("mesh"); OSPData data = ospNewSharedData1D(vertex, OSP_VEC3F, 4); ospCommit(data); ospSetObject(mesh, "vertex.position", data); ospRelease(data); data = ospNewSharedData1D(color, OSP_VEC4F, 4); ospCommit(data); ospSetObject(mesh, "vertex.color", data); ospRelease(data); data = ospNewSharedData1D(index, OSP_VEC3UI, 2); ospCommit(data); ospSetObject(mesh, "index", data); ospRelease(data); ospCommit(mesh); // put the mesh into a model static OSPGeometricModel model; model = ospNewGeometricModel(NULL); ospSetObject(model, "geometry", mesh); ospCommit(model); ospRelease(mesh); // put the model into a group (collection of models) OSPGroup group = ospNewGroup(); OSPData models = ospNewSharedData1D(&model, OSP_GEOMETRIC_MODEL, 1); ospSetObject(group, "geometry", models); ospCommit(group); ospRelease(model); ospRelease(models); // put the group into an instance (give the group a world transform) static OSPInstance instance; instance = ospNewInstance(NULL); ospSetObject(instance, "group", group); ospCommit(instance); ospRelease(group); // put the instance in the world *world = ospNewWorld(); OSPData instances = ospNewSharedData1D(&instance, OSP_INSTANCE, 1); ospSetObject(*world, "instance", instances); // create and setup light for Ambient Occlusion static OSPLight light; light = ospNewLight("ambient"); ospCommit(light); OSPData lights = ospNewSharedData1D(&light, OSP_LIGHT, 1); ospCommit(lights); ospSetObject(*world, "light", lights); ospCommit(*world); ospRelease(instances); ospRelease(instance); // create renderer *renderer = ospNewRenderer("scivis"); // choose Scientific Visualization renderer // complete setup of renderer ospSetInt(*renderer, "aoSamples", 4); ospSetFloat(*renderer, "backgroundColor", 0.2f); // gray, transparent ospCommit(*renderer); ospRelease(light); ospRelease(lights); // create and setup framebuffer *framebuffer = ospNewFrameBuffer(imgSize.x, imgSize.y, OSP_FB_SRGBA, OSP_FB_COLOR | /*OSP_FB_DEPTH |*/ OSP_FB_ACCUM | OSP_FB_VARIANCE); } RenderKit-ospray-f2a61c2/apps/ospTutorial/ospTutorialFindospray/000077500000000000000000000000001456566705700252235ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/ospTutorial/ospTutorialFindospray/CMakeLists.txt000066400000000000000000000017771456566705700277770ustar00rootroot00000000000000## Copyright 2019 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # NOTE: This CMakeLists.txt is intended to be used to exercise an OSPRay # install and demonstrate how external applications can build against # OSPRay using CMake. # # Once you have done a 'make install' of an existing OSPRay # build (will install to CMAKE_INSTALL_PREFIX), create a separate build # directory and invoke CMake on this directory. If you have 'ospray_DIR' # setup correctly to point to where you just installed OSPRay, then this # should build the ospTutorial app from that install and NOT use your # local build. cmake_minimum_required(VERSION 3.1) project(ospTutorialFindospray LANGUAGES C) set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) find_package(ospray 3.0.0 REQUIRED) add_executable(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/../ospTutorial.c) target_link_libraries(${PROJECT_NAME} ospray::ospray) RenderKit-ospray-f2a61c2/apps/ospTutorial/ospTutorialGLM.cpp000066400000000000000000000105321456566705700242310ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This is a small example tutorial how to use OSPRay in an application using GLM instead of rkcommon for math types. */ #include #include #include #ifdef _WIN32 #define NOMINMAX #include #else #include #endif #include #include #include #include "ospray/ospray_cpp.h" #define OSPRAY_GLM_DEFINITIONS #include "ospray/ospray_cpp/ext/glm.h" #include "rkcommon/utility/SaveImage.h" int main(int argc, const char **argv) { // image size glm::ivec2 imgSize; imgSize.x = 1024; // width imgSize.y = 768; // height // camera glm::vec3 cam_pos{0.f, 0.f, 0.f}; glm::vec3 cam_up{0.f, 1.f, 0.f}; glm::vec3 cam_view{0.1f, 0.f, 1.f}; // triangle mesh data std::vector vertex = {glm::vec3(-1.0f, -1.0f, 3.0f), glm::vec3(-1.0f, 1.0f, 3.0f), glm::vec3(1.0f, -1.0f, 3.0f), glm::vec3(0.1f, 0.1f, 0.3f)}; std::vector color = {glm::vec4(0.9f, 0.5f, 0.5f, 1.0f), glm::vec4(0.8f, 0.8f, 0.8f, 1.0f), glm::vec4(0.8f, 0.8f, 0.8f, 1.0f), glm::vec4(0.5f, 0.9f, 0.5f, 1.0f)}; std::vector index = {glm::uvec3(0, 1, 2), glm::uvec3(1, 2, 3)}; // initialize OSPRay; OSPRay parses (and removes) its commandline parameters, // e.g. "--osp:debug" OSPError init_error = ospInit(&argc, argv); if (init_error != OSP_NO_ERROR) return init_error; // use scoped lifetimes of wrappers to release everything before ospShutdown() { // create and setup camera ospray::cpp::Camera camera("perspective"); camera.setParam("aspect", imgSize.x / (float)imgSize.y); camera.setParam("position", cam_pos); camera.setParam("direction", cam_view); camera.setParam("up", cam_up); camera.commit(); // commit each object to indicate modifications are done // create and setup model and mesh ospray::cpp::Geometry mesh("mesh"); mesh.setParam("vertex.position", ospray::cpp::CopiedData(vertex)); mesh.setParam("vertex.color", ospray::cpp::CopiedData(color)); mesh.setParam("index", ospray::cpp::CopiedData(index)); mesh.commit(); // put the mesh into a model ospray::cpp::GeometricModel model(mesh); model.commit(); // put the model into a group (collection of models) ospray::cpp::Group group; group.setParam("geometry", ospray::cpp::CopiedData(model)); group.commit(); // put the group into an instance (give the group a world transform) ospray::cpp::Instance instance(group); instance.commit(); // put the instance in the world ospray::cpp::World world; world.setParam("instance", ospray::cpp::CopiedData(instance)); // create and setup light for Ambient Occlusion ospray::cpp::Light light("ambient"); light.commit(); world.setParam("light", ospray::cpp::CopiedData(light)); world.commit(); // create renderer, choose Scientific Visualization renderer ospray::cpp::Renderer renderer("scivis"); // complete setup of renderer renderer.setParam("aoSamples", 1); renderer.setParam("backgroundColor", 1.0f); // white, transparent renderer.commit(); // create and setup framebuffer ospray::cpp::FrameBuffer framebuffer( imgSize.x, imgSize.y, OSP_FB_SRGBA, OSP_FB_COLOR | OSP_FB_ACCUM); framebuffer.clear(); // render one frame framebuffer.renderFrame(renderer, camera, world); // access framebuffer and write its content as PPM file uint32_t *fb = (uint32_t *)framebuffer.map(OSP_FB_COLOR); rkcommon::utility::writePPM("firstFrameCpp.ppm", imgSize.x, imgSize.y, fb); framebuffer.unmap(fb); // render 10 more frames, which are accumulated to result in a better // converged image for (int frames = 0; frames < 10; frames++) framebuffer.renderFrame(renderer, camera, world); fb = (uint32_t *)framebuffer.map(OSP_FB_COLOR); rkcommon::utility::writePPM( "accumulatedFrameCpp.ppm", imgSize.x, imgSize.y, fb); framebuffer.unmap(fb); ospray::cpp::PickResult res = framebuffer.pick(renderer, camera, world, 0.5f, 0.5f); if (res.hasHit) { std::cout << "Picked geometry [inst: " << res.instance.handle() << ", model: " << res.model.handle() << ", prim: " << res.primID << "]" << std::endl; } } ospShutdown(); return 0; } RenderKit-ospray-f2a61c2/apps/utility/000077500000000000000000000000001456566705700200155ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/apps/utility/CMakeLists.txt000066400000000000000000000006301456566705700225540ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 if (NOT OSPRAY_ENABLE_APPS_TESTING) return() endif() add_executable(ospConvertRawToAMR ${OSPRAY_RESOURCE} ospConvertRawToAMR.cpp) target_link_libraries(ospConvertRawToAMR PRIVATE raw_to_amr ospray) ospray_sign_target(ospConvertRawToAMR) install(TARGETS ospConvertRawToAMR DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT apps ) RenderKit-ospray-f2a61c2/apps/utility/ospConvertRawToAMR.cpp000066400000000000000000000126301456566705700242020ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "rawToAMR.h" static const std::string description = R"description( Creates an adaptive mesh refinement (AMR) representation of the provided structured volume data. The input structured volume data is used as the highest refinement level (i.e. the finest resolution data). From this level, data that does not meet the user-provided variance threshold is discarded. The average of the discarded block is used in the next level down. This simulates the effect that an adaptive simulation would have created regions of higher refinement in the highly varying portions of the volume. )description"; static const std::string usage = R"usage([-h | --help] input_volume variable_type x_dim y_dim z_dim num_levels block_size refinement_factor threshold output_basename )usage"; static const std::string help = R"help( input_volume Structured volume in binary brick-of-data format (string filepath) variable_type Type of structured volume, must be exactly one of: float (string) x_dim X dimensions of the structured volume grid (int) y_dim Y dimensions of the structured volume grid (int) z_dim Z dimensions of the structured volume grid (int) num_levels Number of refinement levels to simulate (int) block_size Size of blocks at each level in terms of cells. Blocks are defined as cubes with this number of cells per edge. Note that refinement levels change the width of the cells, NOT the width of the blocks. Blocks will always be this provided size in cell extents, but the width of the cells will be smaller/larger depending on level. For example, a block of 4x4x4 cells at the highest refinement level will be converted into a single cell at the next lower level, which would be part of that level's block of 4x4x4 cells. (int) refinement_factor How much larger/smaller, in terms of cell extents, each level's grid will be. Note that this is independent of block_size above! For example, if the input data is a 512^3 grid, and block_size is 4^3, the highest refinement level will have a 128^3 block grid. If this value is 2, the next level will have a 64^3 block grid, but will still be comprised of 4^3 blocks. That is, the number of cells decreases from 512^3 to 256^3, and the cell width increases to accommodate. (int) threshold Variance threshold used to determine whether a block belongs to a higher refinement level. If the variance within a block is above this threshold, it remains at the current level. Otherwise, if the variance is low, this block would have not have been selected for mesh refinement by a numerical simulation, so this block is discarded at this level. (variable_type, converted to float) output_basename Basename for the output files. This application creates three files with different extensions, with this basename in common. (string) )help"; using namespace rkcommon::math; static std::string inFileName; static std::string format; static vec3i inDims; static int numLevels; static int blockSize; static int refinementLevel; static float threshold; static std::string outFileBase; bool parseArguments(int argc, char **argv) { if (argc != 11) { if (argc > 1 && (std::string(argv[1]) == "-h" || std::string(argv[1]) == "--help")) { std::cerr << description << std::endl; std::cerr << "Usage: " << argv[0] << " " << usage << std::endl; std::cerr << help << std::endl; } else { std::cerr << argc - 1 << " argument" << ((argc == 1 || argc > 2) ? "s " : " "); std::cerr << "provided, but 10 are needed" << std::endl; std::cerr << "Usage: " << argv[0] << " " << usage << std::endl; } return false; } inFileName = argv[1]; format = argv[2]; inDims.x = atoi(argv[3]); inDims.y = atoi(argv[4]); inDims.z = atoi(argv[5]); numLevels = atoi(argv[6]); blockSize = atoi(argv[7]); refinementLevel = atoi(argv[8]); threshold = atof(argv[9]); outFileBase = argv[10]; return true; } int main(int argc, char **argv) { bool parseSucceed = parseArguments(argc, argv); if (!parseSucceed) { return 1; } // ALOK: TODO: // support more than float std::vector in; if (format == "float") { in = ospray::amr::mmapRAW(inFileName, inDims); } else { throw std::runtime_error("unsupported input voxel format"); } std::vector blockBounds; std::vector refinementLevels; std::vector cellWidths; std::vector> brickData; ospray::amr::makeAMR(in, inDims, numLevels, blockSize, refinementLevel, threshold, blockBounds, refinementLevels, cellWidths, brickData); ospray::amr::outputAMR(outFileBase, blockBounds, refinementLevels, cellWidths, brickData, blockSize); return 0; } RenderKit-ospray-f2a61c2/cmake/000077500000000000000000000000001456566705700164275ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/cmake/clang-format.cmake000066400000000000000000000013331456566705700220030ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # additional target to run clang-format on all source files set (EXCLUDE_DIRS ${CMAKE_SOURCE_DIR}/apps/external ${CMAKE_SOURCE_DIR}/build ${CMAKE_SOURCE_DIR}/ospray-doc ) # get all project files file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h *.hpp *.ih *.isph *.ispc) foreach (SOURCE_FILE ${ALL_SOURCE_FILES}) foreach (EXCLUDE_DIR ${EXCLUDE_DIRS}) string(FIND ${SOURCE_FILE} ${EXCLUDE_DIR} EXCLUDE_DIR_FOUND) if (NOT ${EXCLUDE_DIR_FOUND} EQUAL -1) list(REMOVE_ITEM ALL_SOURCE_FILES ${SOURCE_FILE}) endif() endforeach() endforeach() add_custom_target( format COMMAND clang-format -style=file -i ${ALL_SOURCE_FILES} ) RenderKit-ospray-f2a61c2/cmake/compiler/000077500000000000000000000000001456566705700202415ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/cmake/compiler/clang.cmake000066400000000000000000000071061456566705700223330ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(OSPRAY_CXX_FLAGS "-fno-strict-aliasing -Wno-narrowing") if(OSPRAY_STRICT_BUILD) # OK to turn off. set(OSPRAY_CXX_FLAGS "-Wno-c++98-compat-pedantic ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-documentation ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-documentation-unknown-command ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-zero-as-null-pointer-constant ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-newline-eof ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-keyword-macro ${OSPRAY_CXX_FLAGS}") #useful for unit testing set(OSPRAY_CXX_FLAGS "-Wno-undef ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-header-hygiene ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-covered-switch-default ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-date-time ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-unsafe-buffer-usage ${OSPRAY_CXX_FLAGS}") #we use pointer arithmetics on buffers set(OSPRAY_CXX_FLAGS "-Wno-reserved-identifier ${OSPRAY_CXX_FLAGS}") #used in autogenerated ISPC headers # Should try to fix and remove... set(OSPRAY_CXX_FLAGS "-Wno-unknown-warning-option ${OSPRAY_CXX_FLAGS}") #don't warn if pragmas are unknown set(OSPRAY_CXX_FLAGS "-Wno-conversion ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-reserved-id-macro ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-double-promotion ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-used-but-marked-unused ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-old-style-cast ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-missing-noreturn ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-missing-prototypes ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-shift-sign-overflow ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-padded ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-shadow-field-in-constructor ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-weak-template-vtables ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-weak-vtables ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-exit-time-destructors ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-global-constructors ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-unused-template ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-switch-enum ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-float-equal ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-cast-align ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-deprecated ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-mismatched-tags ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-disabled-macro-expansion ${OSPRAY_CXX_FLAGS}") #pesky 'stb_image.h'... set(OSPRAY_CXX_FLAGS "-Wno-over-aligned ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-shadow ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-format-nonliteral ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-cast-qual ${OSPRAY_CXX_FLAGS}") #Embree v3.x issue set(OSPRAY_CXX_FLAGS "-Wno-extra-semi-stmt ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-shadow-field ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-alloca ${OSPRAY_CXX_FLAGS}") set(OSPRAY_CXX_FLAGS "-Wno-cast-function-type-strict ${OSPRAY_CXX_FLAGS}") #ISPC exported functions casts # Options selected for Clang 5.0+ set(OSPRAY_CXX_FLAGS "-Weverything ${OSPRAY_CXX_FLAGS}") endif() if(OSPRAY_WARN_AS_ERRORS) set(OSPRAY_CXX_FLAGS "-Werror ${OSPRAY_CXX_FLAGS}") endif() set(CMAKE_CXX_FLAGS "${OSPRAY_CXX_FLAGS} ${CMAKE_CXX_FLAGS}") if (APPLE) set(CMAKE_CXX_FLAGS "-mmacosx-version-min=10.9 ${CMAKE_CXX_FLAGS}") # we only use MacOSX 10.9 features endif() RenderKit-ospray-f2a61c2/cmake/compiler/dpcpp.cmake000066400000000000000000000112741456566705700223560ustar00rootroot00000000000000## Copyright 2022 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # FIXME CMake does not always set "-x c++" to compile .ispc files as C++ (SYCL) # code, despite LANGUAGE is set for them set(OSPRAY_COMPILER_NEEDS_X_CPP TRUE) get_filename_component(SYCL_COMPILER_NAME ${CMAKE_CXX_COMPILER} NAME_WE) if (WIN32 AND (SYCL_COMPILER_NAME STREQUAL "icx" OR SYCL_COMPILER_NAME STREQUAL "icpx")) include(msvc) # icx on Windows behaves like msvc set(CMAKE_CXX_FLAGS "/fp:precise ${CMAKE_CXX_FLAGS}") set(OSPRAY_COMPILER_NEEDS_X_CPP FALSE) # icx on Win does not support "-x" set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /Qoption,link,/DEPENDENTLOADFLAG:0x2000") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /Qoption,link,/DEPENDENTLOADFLAG:0x2000") else() include(clang) # DPCPP compiler is based on Clang, so bring in clang options set(CMAKE_CXX_FLAGS "-ffp-model=precise ${CMAKE_CXX_FLAGS}") endif() # enable -static-intel # Note: this doesn't seem to be used/relevant to the DPC++ compiler? Maybe just the # DPCPP release one? The nightly clang compiler doesn't recognize this flag #set(CMAKE_EXE_LINKER_FLAGS "-static-intel ${CMAKE_EXE_LINKER_FLAGS}") #set(CMAKE_SHARED_LINKER_FLAGS "-static-intel ${CMAKE_SHARED_LINKER_FLAGS}") #set(CMAKE_MODULE_LINKER_FLAGS "-static-intel ${CMAKE_MODULE_LINKER_FLAGS}") # SYCL flags to match Embree list(APPEND OSPRAY_CXX_FLAGS_SYCL -fsycl -fsycl-unnamed-lambda -Xclang -fsycl-allow-func-ptr -Wno-mismatched-tags -Wno-pessimizing-move -Wno-reorder -Wno-unneeded-internal-declaration -Wno-delete-non-abstract-non-virtual-dtor -Wno-dangling-field -Wno-unknown-pragmas -Wno-logical-op-parentheses ) # IGC options from Embree # This works around some IGC bug in spill compression # TODO: Still true? list(APPEND OSPRAY_IGC_OPTIONS "VISAOptions=-scratchAllocForStackInKB 128") # Allow printf inside indirectly callable function, right now I have this in all for testing # TODO: Should only enable for debug builds, and this needs to be done using a generator expression # if we want to support it in VS #list(APPEND OSPRAY_IGC_OPTIONS "ForceInlineStackCallWithImplArg=0" "EnableGlobalStateBuffer=1") option(OSPRAY_IGC_ENABLE_ZE_BINARY "Enable ZEBinary (for GTPin)" OFF) mark_as_advanced(OSPRAY_IGC_ENABLE_ZE_BINARY) if (OSPRAY_IGC_ENABLE_ZE_BINARY) list(APPEND OSPRAY_IGC_OPTIONS "EnableZEBinary=1") endif() # This significantly improves compile times on 17028 and up, though also impacts performance some option(OSPRAY_IGC_FAST_COMPILE "Pass flags to improve compilation speed at the cost of some optimization" OFF) mark_as_advanced(OSPRAY_IGC_FAST_COMPILE) if (OSPRAY_IGC_FAST_COMPILE) set(OSPRAY_IGC_FAST_COMPILE_UNIT_SIZE_THRESHOLD "18000" CACHE STRING "Set the partition unit unit size threshold (default 18000)") list(APPEND OSPRAY_IGC_OPTIONS "PartitionUnit=1") list(APPEND OSPRAY_IGC_OPTIONS "UnitSizeThreshold=${OSPRAY_IGC_FAST_COMPILE_UNIT_SIZE_THRESHOLD}") endif() #list(APPEND OSPRAY_IGC_OPTIONS "ForceOCLSIMDWidth=8") # Development option to dump shaders, when we compile AOT this has to be done at build time option(OSPRAY_IGC_DUMP_SHADERS "Dump IGC shaders during build" OFF) mark_as_advanced(OSPRAY_IGC_DUMP_SHADERS) if (OSPRAY_IGC_DUMP_SHADERS) list(APPEND OSPRAY_IGC_OPTIONS "ShaderDumpEnable=1" "ShowFullVectorsInShaderDumps=1" "DumpToCustomDir=${PROJECT_BINARY_DIR}/ospray_igc_shader_dump") endif() # enables support for buffers larger than 4GB list(APPEND OSPRAY_OCL_OPTIONS -cl-intel-greater-than-4GB-buffer-required) list(APPEND OSPRAY_OCL_OTHER_OPTIONS -cl-intel-force-global-mem-allocation -cl-intel-no-local-to-generic) if (CMAKE_BUILD_TYPE MATCHES "Release") list(APPEND OSPRAY_OCL_OTHER_OPTIONS -O2) elseif (CMAKE_BUILD_TYPE MATCHES "Debug") # SYCL applies some optimization flags by default, make sure we're # really building with no optimizations for debug builds. RelWithDebInfo # builds currently hit a compiler crash. list(APPEND OSPRAY_OCL_OTHER_OPTIONS -O0) endif() # Large GRF mode option(OSPRAY_SYCL_LARGEGRF "Enable SYCL Large GRF Support" ON) mark_as_advanced(OSPRAY_SYCL_LARGEGRF) if (OSPRAY_SYCL_LARGEGRF) list(APPEND OSPRAY_OCL_OTHER_OPTIONS "-ze-opt-large-register-file") endif() string(REPLACE ";" "," OSPRAY_IGC_OPTIONS_STR "${OSPRAY_IGC_OPTIONS}") set(OSPRAY_OCL_OPTIONS_STR "${OSPRAY_OCL_OPTIONS}") string(REPLACE ";" " " OSPRAY_OCL_OPTIONS_STR "${OSPRAY_OCL_OPTIONS}") set(OSPRAY_OCL_OTHER_OPTIONS_STR "${OSPRAY_OCL_OTHER_OPTIONS}") string(REPLACE ";" " " OSPRAY_OCL_OTHER_OPTIONS_STR "${OSPRAY_OCL_OTHER_OPTIONS}") set(OSPRAY_LINKER_FLAGS_SYCL -fsycl -Xsycl-target-backend=spir64 "${OSPRAY_OCL_OPTIONS_STR} -options \"${OSPRAY_OCL_OTHER_OPTIONS_STR} -igc_opts='${OSPRAY_IGC_OPTIONS_STR}'\"") RenderKit-ospray-f2a61c2/cmake/compiler/gcc.cmake000066400000000000000000000012151456566705700217760ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(OSPRAY_CXX_FLAGS "-fno-strict-aliasing -Wno-narrowing -Wno-unknown-pragmas") if(OSPRAY_STRICT_BUILD) # Should try to fix and remove... set(OSPRAY_CXX_FLAGS "-Wno-aligned-new ${OSPRAY_CXX_FLAGS}") # Options selected for GCC 7.1+ set(OSPRAY_CXX_FLAGS "-Wall ${OSPRAY_CXX_FLAGS}") endif() if(OSPRAY_WARN_AS_ERRORS) set(OSPRAY_CXX_FLAGS "-Werror ${OSPRAY_CXX_FLAGS}") endif() set(CMAKE_CXX_FLAGS "${OSPRAY_CXX_FLAGS} ${CMAKE_CXX_FLAGS}") if (APPLE) set(CMAKE_CXX_FLAGS "-mmacosx-version-min=10.9 ${CMAKE_CXX_FLAGS}") # we only use MacOSX 10.9 features endif() RenderKit-ospray-f2a61c2/cmake/compiler/icc.cmake000066400000000000000000000014721456566705700220050ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(OSPRAY_CXX_FLAGS "-fno-strict-aliasing -no-ansi-alias -Wno-unknown-pragmas") if (OSPRAY_STRICT_BUILD) set(OSPRAY_CXX_FLAGS "-Wall ${OSPRAY_CXX_FLAGS}") endif() set(CMAKE_CXX_FLAGS "${OSPRAY_CXX_FLAGS} ${CMAKE_CXX_FLAGS}") if (APPLE) set(CMAKE_SHARED_LINKER_FLAGS "-dynamiclib ${CMAKE_SHARED_LINKER_FLAGS_INIT}") set(CMAKE_CXX_FLAGS "-mmacosx-version-min=10.8 ${CMAKE_CXX_FLAGS}") # we only use MacOSX 10.8 features set(CMAKE_CXX_FLAGS "-stdlib=libc++ ${CMAKE_CXX_FLAGS}") # link against C++11 stdlib else() # avoid exporting ICC specific symbols from OSPRay set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--exclude-libs=ALL ${CMAKE_SHARED_LINKER_FLAGS}") endif() # enable -static-intel set(CMAKE_CXX_FLAGS "-static-intel ${CMAKE_CXX_FLAGS}") RenderKit-ospray-f2a61c2/cmake/compiler/msvc.cmake000066400000000000000000000040261456566705700222150ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMMON_CXX_FLAGS "/EHsc /MP /GR /bigobj") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${COMMON_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${COMMON_CXX_FLAGS} /Ox /fp:fast /Oi /Gy ") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${COMMON_CXX_FLAGS} /Ox /fp:fast /Oi /Gy ") # optionally use static runtime library option(USE_STATIC_RUNTIME "Use the static version of the C/C++ runtime library.") mark_as_advanced(USE_STATIC_RUNTIME) if (USE_STATIC_RUNTIME) foreach(FLAG CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO ) string(REPLACE "/MD" "/MT" ${FLAG} ${${FLAG}}) endforeach() else() # remove libmmd dependency if (OSPRAY_COMPILER_ICC) # prevents sin(x),cos(x) -> sincos(x) optimization, which is only present in libmmd foreach(FLAG CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO ) string(APPEND ${FLAG} " /Qfast-transcendentals-") endforeach() # use default math lib instead of libmmd[d] string(APPEND CMAKE_EXE_LINKER_FLAGS_DEBUG " /nodefaultlib:libmmdd.lib") string(APPEND CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO " /nodefaultlib:libmmd.lib") string(APPEND CMAKE_EXE_LINKER_FLAGS_RELEASE " /nodefaultlib:libmmd.lib") string(APPEND CMAKE_SHARED_LINKER_FLAGS_DEBUG " /nodefaultlib:libmmdd.lib") string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO " /nodefaultlib:libmmd.lib") string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELEASE " /nodefaultlib:libmmd.lib") endif() endif() if (OSPRAY_COMPILER_MSVC) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEPENDENTLOADFLAG:0x2000") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEPENDENTLOADFLAG:0x2000") endif() RenderKit-ospray-f2a61c2/cmake/ospray_cmake_config.cmake000066400000000000000000000034401456566705700234340ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # Version header configure_file( ${CMAKE_SOURCE_DIR}/ospray/version.h.in ${CMAKE_BINARY_DIR}/ospray/version.h @ONLY ) install(FILES ${CMAKE_BINARY_DIR}/ospray/version.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ospray COMPONENT devel ) # CMake config module set(OSPRAY_MODULE_CONFIG_INPUT_DIR ${CMAKE_SOURCE_DIR}/cmake/ospray_cmake_config) set(OSPRAY_MODULE_CONFIG_OUTPUT_DIR ${CMAKE_BINARY_DIR}/cmake) set(OSPRAY_MODULE_FILES osprayConfig.cmake osprayConfigVersion.cmake osprayUse.cmake ) ## find relative path to make package relocatable # this is a bit involved to handle these cases: # - CMAKE_INSTALL_LIBDIR is overridden by the user # - CMAKE_INSTALL_LIBDIR contains multiple levels for Debian multiarch support if (IS_ABSOLUTE "${CMAKE_INSTALL_PREFIX}") set(ABS_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") else() get_filename_component(ABS_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" ABSOLUTE) endif() if (IS_ABSOLUTE "${OSPRAY_CMAKECONFIG_DIR}") MESSAGE(WARNING "CMAKE_INSTALL_LIBDIR needs to be a relative path!") set(ABS_CMAKECONFIG_DIR "${OSPRAY_CMAKECONFIG_DIR}") else() set(ABS_CMAKECONFIG_DIR "${ABS_INSTALL_PREFIX}/${OSPRAY_CMAKECONFIG_DIR}") endif() file(RELATIVE_PATH OSPRAY_RELATIV_ROOT_DIR "${ABS_CMAKECONFIG_DIR}" "${ABS_INSTALL_PREFIX}" ) foreach(MODULE_FILE ${OSPRAY_MODULE_FILES}) LIST(APPEND OSPRAY_MODULE_INSTALL_FILES ${OSPRAY_MODULE_CONFIG_OUTPUT_DIR}/${MODULE_FILE} ) configure_file( ${OSPRAY_MODULE_CONFIG_INPUT_DIR}/${MODULE_FILE}.in ${OSPRAY_MODULE_CONFIG_OUTPUT_DIR}/${MODULE_FILE} @ONLY ) endforeach() install(FILES ${OSPRAY_MODULE_INSTALL_FILES} ${CMAKE_SOURCE_DIR}/cmake/ospray_macros.cmake DESTINATION ${OSPRAY_CMAKECONFIG_DIR} COMPONENT devel ) RenderKit-ospray-f2a61c2/cmake/ospray_cmake_config/000077500000000000000000000000001456566705700224315ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/cmake/ospray_cmake_config/osprayConfig.cmake.in000066400000000000000000000176071456566705700265160ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # Called if we failed to find OSPRay or any of it's required dependencies, # unsets all public (designed to be used externally) variables and reports # error message at priority depending upon [REQUIRED/QUIET/] argument. macro(ospray_report_not_found REASON_MSG) unset(OSPRAY_FOUND) unset(OSPRAY_INCLUDE_DIRS) unset(OSPRAY_LIBRARIES) # Reset the CMake module path to its state when this script was called. set(CMAKE_MODULE_PATH ${CALLERS_CMAKE_MODULE_PATH}) # Note _FIND_[REQUIRED/QUIETLY] variables defined by FindPackage() # use the camelcase library name, not uppercase. if (OSPRAY_FIND_QUIETLY) set(MSG_TYPE STATUS) elseif(OSPRAY_FIND_REQUIRED) set(MSG_TYPE FATAL_ERROR) else() # Neither QUIETLY nor REQUIRED, use SEND_ERROR which emits an error # that prevents generation, but continues configuration. set(MSG_TYPE SEND_ERROR) endif() message(${MSG_TYPE} "Failed to find OSPRay - " ${REASON_MSG} ${ARGN}) return() endmacro() ############################################################################### # Attempt to find OSPRay # Get the (current, i.e. installed) directory containing this file. set(CURRENT_CONFIG_INSTALL_DIR ${CMAKE_CURRENT_LIST_DIR}) # Record the state of the CMake module path when this script was called so # that we can ensure that we leave it in the same state on exit as it was # on entry, but modify it locally. set(OSPRAY_CALLERS_CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}) # Reset CMake module path to the installation directory of this script, # thus we will use the FindPackage() scripts shipped with OSPRay to find # OSPRay's dependencies, even if the user has equivalently named FindPackage() # scripts in their project. set(CMAKE_MODULE_PATH ${CURRENT_CONFIG_INSTALL_DIR}) # Build the absolute root install directory as a relative path (determined when # OSPRay was configured & built) from the current install directory for this # this file. This allows for the install tree to be relocated, after OSPRay # was built, outside of CMake. get_filename_component(CURRENT_ROOT_INSTALL_DIR ${CURRENT_CONFIG_INSTALL_DIR}/@OSPRAY_RELATIV_ROOT_DIR@ ABSOLUTE ) if (NOT EXISTS ${CURRENT_ROOT_INSTALL_DIR}) ospray_report_not_found( "OSPRay install root: ${CURRENT_ROOT_INSTALL_DIR}, " "determined from relative path from osprayConfig.cmake install location: " "${CURRENT_CONFIG_INSTALL_DIR}, does not exist. Either the install " "directory was deleted, or the install tree was only partially relocated " "outside of CMake after OSPRay was built.") endif() set(OSPRAY_ROOT ${CURRENT_ROOT_INSTALL_DIR}) # Set the include directories for OSPRay (itself). set(OSPRAY_INCLUDE_DIR "${OSPRAY_ROOT}/include") if (NOT EXISTS ${OSPRAY_INCLUDE_DIR}/ospray/version.h) ospray_report_not_found( "OSPRay install root: ${OSPRAY_ROOT}, " "determined from relative path from osprayConfg.cmake install location: " "${CURRENT_CONFIG_INSTALL_DIR}, does not contain OSPRay headers. " "Either the install directory was deleted, or the install tree was only " "partially relocated outside of CMake after OSPRay was built.") endif() ############################################################################### # OSPRay build configuration set(OSPRAY_VERSION @OSPRAY_VERSION@) set(OSPRAY_SOVERSION @OSPRAY_SOVERSION@) set(OSPRAY_INSTALL_DEPENDENCIES @OSPRAY_INSTALL_DEPENDENCIES@) set(OSPRAY_BUILD_DEBUG @OSPRAY_BUILD_DEBUG@) set(OSPRAY_BUILD_RELWITHDEBINFO @OSPRAY_BUILD_RELWITHDEBINFO@) set(OSPRAY_BUILD_RELEASE @OSPRAY_BUILD_RELEASE@) set(OSPRAY_COMPILER_ICC @OSPRAY_COMPILER_ICC@) set(OSPRAY_COMPILER_GCC @OSPRAY_COMPILER_GCC@) set(OSPRAY_COMPILER_CLANG @OSPRAY_COMPILER_CLANG@) set(OSPRAY_COMPILER_MSVC @OSPRAY_COMPILER_MSVC@) set(OSPRAY_COMPILER_DPCPP @OSPRAY_COMPILER_DPCPP@) set(OSPRAY_ISPC_TARGET_LIST @OSPRAY_ISPC_TARGET_LIST@) set(OSPRAY_ISPC_ADDRESSING @OSPRAY_ISPC_ADDRESSING@) set(OSPRAY_ENABLE_VOLUMES @OSPRAY_ENABLE_VOLUMES@) set(OSPRAY_TILE_SIZE @OSPRAY_TILE_SIZE@) set(RKCOMMON_VERSION_REQUIRED @RKCOMMON_VERSION_REQUIRED@) set(EMBREE_VERSION_REQUIRED @EMBREE_VERSION_REQUIRED@) if (OSPRAY_ENABLE_VOLUMES) set(OPENVKL_VERSION_REQUIRED @OPENVKL_VERSION_REQUIRED@) endif() if (OSPRAY_MODULE_DENOISER) set(OIDN_VERSION_REQUIRED @OIDN_VERSION_REQUIRED@) endif() ############################################################################### # OSPRay dependencies # Save state set(OSPRAY_CMAKE_CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_DIR}) set(OSPRAY_CURRENT_CONFIG_INSTALL_DIR ${CURRENT_CONFIG_INSTALL_DIR}) set(OSPRAY_CURRENT_ROOT_INSTALL_DIR ${CURRENT_ROOT_INSTALL_DIR}) # Setup library path vars if (WIN32) set(LIBRARY_PATH_PREFIX ${OSPRAY_ROOT}/@CMAKE_INSTALL_LIBDIR@/${CMAKE_IMPORT_LIBRARY_PREFIX}) set(LIBRARY_SUFFIX ${CMAKE_IMPORT_LIBRARY_SUFFIX}) else() set(LIBRARY_PATH_PREFIX ${OSPRAY_ROOT}/@CMAKE_INSTALL_LIBDIR@/${CMAKE_SHARED_LIBRARY_PREFIX}) set(LIBRARY_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}) endif() # Include macros for finding embree include(ospray_macros) if (OSPRAY_INSTALL_DEPENDENCIES) # Dependencies installed with OSPRay if (WIN32) file(GLOB_RECURSE EMBREE_LIBRARY ${LIBRARY_PATH_PREFIX}embree*.lib) file(GLOB_RECURSE RKCOMMON_LIBRARY ${LIBRARY_PATH_PREFIX}rkcommon*.lib) if (OSPRAY_ENABLE_VOLUMES) file(GLOB_RECURSE OPENVKL_LIBRARY ${LIBRARY_PATH_PREFIX}openvkl*.lib) endif() if (OSPRAY_MODULE_DENOISER) file(GLOB_RECURSE OIDN_LIBRARY ${LIBRARY_PATH_PREFIX}OpenImageDenoise*.lib) endif() else() file(GLOB_RECURSE EMBREE_LIBRARY ${LIBRARY_PATH_PREFIX}embree*) file(GLOB_RECURSE RKCOMMON_LIBRARY ${LIBRARY_PATH_PREFIX}rkcommon*) if (OSPRAY_MODULE_DENOISER) file(GLOB_RECURSE OIDN_LIBRARY ${LIBRARY_PATH_PREFIX}OpenImageDenoise*) endif() endif() else() # Find existing Dependencies on the machine if (NOT TARGET embree) ospray_find_embree(${EMBREE_VERSION_REQUIRED} TRUE) ospray_verify_embree_features() endif() if (NOT TARGET rkcommon::rkcommon) find_dependency(rkcommon ${RKCOMMON_VERSION_REQUIRED}) get_target_property(RKCOMMON_INCLUDE_DIRS rkcommon::rkcommon INTERFACE_INCLUDE_DIRECTORIES) endif() if (OSPRAY_ENABLE_VOLUMES) if (NOT TARGET openvkl::openvkl) ospray_find_openvkl(${OPENVKL_VERSION_REQUIRED} TRUE) endif() set(OPENVKL_LIBRARY openvkl::openvkl) endif() if (OSPRAY_MODULE_DENOISER) if (NOT TARGET OpenImageDenoise) find_dependency(OpenImageDenoise ${OIDN_VERSION_REQUIRED} TRUE) endif() set(OIDN_LIBRARY OpenImageDenoise) endif() set(EMBREE_LIBRARY embree) set(RKCOMMON_LIBRARY rkcommon::rkcommon) endif() # Restore state set(CMAKE_CURRENT_LIST_DIR ${OSPRAY_CMAKE_CURRENT_LIST_DIR}) set(CURRENT_CONFIG_INSTALL_DIR ${OSPRAY_CURRENT_CONFIG_INSTALL_DIR}) set(CURRENT_ROOT_INSTALL_DIR ${OSPRAY_CURRENT_ROOT_INSTALL_DIR}) ############################################################################### # Finish OSPRay # Include target exports include(${CMAKE_CURRENT_LIST_DIR}/ospray_Exports.cmake) # Add missing targets to libraries set_target_properties(ospray::ospray PROPERTIES INTERFACE_LINK_LIBRARIES "${RKCOMMON_LIBRARY}") set_target_properties(ospray::ospray_module_cpu PROPERTIES INTERFACE_LINK_LIBRARIES "ospray::ospray;${OPENVKL_LIBRARY};${EMBREE_LIBRARY}") # Reset CMake module path to its state when this script was called. set(CMAKE_MODULE_PATH ${OSPRAY_CALLERS_CMAKE_MODULE_PATH}) set(OSPRAY_CMAKE_ROOT ${OSPRAY_ROOT}/@CMAKE_INSTALL_LIBDIR@/cmake/ospray-@OSPRAY_VERSION@) # Include definitions for clients to use ospray header files set(OSPRAY_USE_FILE ${OSPRAY_CMAKE_ROOT}/osprayUse.cmake) set(OSPRAY_SDK_USE_FILE ${OSPRAY_USE_FILE}) # OSPRAY_REPORT_NOT_FOUND() aborts, so if we made it this far, # we have found ospray and all required dependencies. include(FindPackageMessage) find_package_MESSAGE(ospray "Found OSPRay: ${OSPRAY_ROOT}" "[${OSPRAY_ROOT}]") RenderKit-ospray-f2a61c2/cmake/ospray_cmake_config/osprayConfigVersion.cmake.in000066400000000000000000000012171456566705700300520ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(PACKAGE_VERSION "@OSPRAY_VERSION@") set(PACKAGE_VERSION_MAJOR "@OSPRAY_VERSION_MAJOR@") # Check whether the requested PACKAGE_FIND_VERSION is compatible if (PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) set(PACKAGE_VERSION_COMPATIBLE FALSE) else() # Major version needs to be the same if (PACKAGE_FIND_VERSION_MAJOR STREQUAL PACKAGE_VERSION_MAJOR) set(PACKAGE_VERSION_COMPATIBLE TRUE) else() set(PACKAGE_VERSION_COMPATIBLE FALSE) endif() if (PACKAGE_VERSION VERSION_EQUAL PACKAGE_FIND_VERSION) set(PACKAGE_VERSION_EXACT TRUE) endif() endif() RenderKit-ospray-f2a61c2/cmake/ospray_cmake_config/osprayUse.cmake.in000066400000000000000000000017061456566705700260360ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # NOTE(jda) - Add CMake commands which will be invoked when find_package(ospray) # is called by client applications. For example, it may be useful # to automatically have an add_definitions(...) call for clients # which need certain preprocessor definitions based on how ospray # was built. set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${OSPRAY_CMAKE_ROOT}) include(ispc) message(STATUS "Using found OSPRay ISA targets: ${OSPRAY_ISPC_TARGET_LIST}") if (NOT TARGET openvkl::openvkl OR NOT TARGET embree) message(FATAL_ERROR "OSPRay pre-built binary redistributables cannot be extended with the SDK. Please build OSPRay from source to enable extending OSPRay!") endif() include_directories_ispc( ${OSPRAY_INCLUDE_DIR} ${OSPRAY_INCLUDE_DIR}/ospray/SDK ${RKCOMMON_INCLUDE_DIRS} ${EMBREE_INCLUDE_DIRS} ${OPENVKL_INCLUDE_DIRS} ) RenderKit-ospray-f2a61c2/cmake/ospray_macros.cmake000066400000000000000000000364041456566705700223210ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 include(CMakeFindDependencyMacro) ## Macro for printing CMake variables ## macro(print var) message("${var} = ${${var}}") endmacro() ## Get a list of subdirectories (single level) under a given directory macro(get_subdirectories result curdir) file(GLOB children RELATIVE ${curdir} ${curdir}/*) set(dirlist "") foreach(child ${children}) if(IS_DIRECTORY ${curdir}/${child}) list(APPEND dirlist ${child}) endif() endforeach() set(${result} ${dirlist}) endmacro() ## Get all subdirectories and call add_subdirectory() if it has a CMakeLists.txt macro(add_all_subdirectories_except except) set(e ${except}) file(GLOB dirs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/ *) foreach(dir ${dirs}) if (NOT "${dir}X" STREQUAL "${except}X" AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/CMakeLists.txt) add_subdirectory(${dir}) endif() endforeach() endmacro() macro(add_all_subdirectories) add_all_subdirectories_except("") endmacro() ## Setup CMAKE_BUILD_TYPE to have a default + cycle between options in UI macro(ospray_configure_build_type) set(CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo") if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the build type." FORCE) endif() if (WIN32) if (NOT OSPRAY_DEFAULT_CMAKE_CONFIGURATION_TYPES_SET) set(CMAKE_CONFIGURATION_TYPES "${CONFIGURATION_TYPES}" CACHE STRING "List of generated configurations." FORCE) set(OSPRAY_DEFAULT_CMAKE_CONFIGURATION_TYPES_SET ON CACHE INTERNAL "Default CMake configuration types set.") endif() else() set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CONFIGURATION_TYPES}) endif() if (${CMAKE_BUILD_TYPE} STREQUAL "Release") set(OSPRAY_BUILD_RELEASE TRUE ) set(OSPRAY_BUILD_DEBUG FALSE) set(OSPRAY_BUILD_RELWITHDEBINFO FALSE) elseif (${CMAKE_BUILD_TYPE} STREQUAL "Debug") set(OSPRAY_BUILD_RELEASE FALSE) set(OSPRAY_BUILD_DEBUG TRUE ) set(OSPRAY_BUILD_RELWITHDEBINFO FALSE) else() set(OSPRAY_BUILD_RELEASE FALSE) set(OSPRAY_BUILD_DEBUG FALSE) set(OSPRAY_BUILD_RELWITHDEBINFO TRUE ) endif() endmacro() # workaround link issues to Embree ISPC exports # ISPC only adds the ISA suffix during name mangling (and dynamic dispatch # code) when compiling for multiple targets. Thus, when only one OSPRay ISA is # selected, but Embree was compiled for multiple ISAs, we need to add a # second, different, supported dummy target. macro(ospray_fix_ispc_target_list) list(LENGTH OSPRAY_ISPC_TARGET_LIST NUM_TARGETS) if (NUM_TARGETS EQUAL 1 AND NOT OSPRAY_ISPC_TARGET_LIST STREQUAL "neon-i32x4" AND NOT OSPRAY_ISPC_TARGET_LIST STREQUAL "neon-i32x8") if (EMBREE_ISA_SSE42 AND NOT OSPRAY_ISPC_TARGET_LIST STREQUAL "sse4") list(APPEND OSPRAY_ISPC_TARGET_LIST sse4) elseif (EMBREE_ISA_AVX AND NOT OSPRAY_ISPC_TARGET_LIST STREQUAL "avx") list(APPEND OSPRAY_ISPC_TARGET_LIST avx) elseif (EMBREE_ISA_AVX2 AND NOT OSPRAY_ISPC_TARGET_LIST STREQUAL "avx2") list(APPEND OSPRAY_ISPC_TARGET_LIST avx2) elseif (EMBREE_ISA_AVX512 AND NOT OSPRAY_ISPC_TARGET_LIST STREQUAL "avx512skx-i32x16") list(APPEND OSPRAY_ISPC_TARGET_LIST avx512skx-i32x16) elseif (EMBREE_ISA_NEON AND NOT OSPRAY_ISPC_TARGET_LIST STREQUAL "neon-i32x4") list(APPEND OSPRAY_ISPC_TARGET_LIST neon-i32x4) elseif (EMBREE_ISA_NEON2X AND NOT OSPRAY_ISPC_TARGET_LIST STREQUAL "neon-i32x8") list(APPEND OSPRAY_ISPC_TARGET_LIST neon-i32x8) endif() endif() endmacro() ## Macro configure ISA targets for ispc ## macro(ospray_configure_ispc_isa) set(OSPRAY_BUILD_ISA "ALL" CACHE STRING "Target ISA (SSE4, AVX, AVX2, AVX512SKX, NEON, NEON2X, or ALL)") string(TOUPPER ${OSPRAY_BUILD_ISA} OSPRAY_BUILD_ISA) if(EMBREE_ISA_SSE42 AND OPENVKL_ISA_SSE4) set(OSPRAY_SUPPORTED_ISAS ${OSPRAY_SUPPORTED_ISAS} SSE4) endif() if(EMBREE_ISA_AVX AND OPENVKL_ISA_AVX) set(OSPRAY_SUPPORTED_ISAS ${OSPRAY_SUPPORTED_ISAS} AVX) endif() if(EMBREE_ISA_AVX2 AND OPENVKL_ISA_AVX2) set(OSPRAY_SUPPORTED_ISAS ${OSPRAY_SUPPORTED_ISAS} AVX2) endif() if(EMBREE_ISA_AVX512 AND OPENVKL_ISA_AVX512SKX) set(OSPRAY_SUPPORTED_ISAS ${OSPRAY_SUPPORTED_ISAS} AVX512SKX) endif() if(EMBREE_ISA_NEON AND OPENVKL_ISA_NEON) set(OSPRAY_SUPPORTED_ISAS ${OSPRAY_SUPPORTED_ISAS} NEON) endif() if(EMBREE_ISA_NEON2X AND OPENVKL_ISA_NEON2X) set(OSPRAY_SUPPORTED_ISAS ${OSPRAY_SUPPORTED_ISAS} NEON2X) endif() set_property(CACHE OSPRAY_BUILD_ISA PROPERTY STRINGS ALL ${OSPRAY_SUPPORTED_ISAS}) unset(OSPRAY_ISPC_TARGET_LIST) if (OSPRAY_BUILD_ISA STREQUAL "ALL") if(EMBREE_ISA_SSE42 AND OPENVKL_ISA_SSE4) set(OSPRAY_ISPC_TARGET_LIST ${OSPRAY_ISPC_TARGET_LIST} sse4) message(STATUS "OSPRay SSE4 ISA target enabled.") endif() if(EMBREE_ISA_AVX AND OPENVKL_ISA_AVX) set(OSPRAY_ISPC_TARGET_LIST ${OSPRAY_ISPC_TARGET_LIST} avx) message(STATUS "OSPRay AVX ISA target enabled.") endif() if(EMBREE_ISA_AVX2 AND OPENVKL_ISA_AVX2) set(OSPRAY_ISPC_TARGET_LIST ${OSPRAY_ISPC_TARGET_LIST} avx2) message(STATUS "OSPRay AVX2 ISA target enabled.") endif() if(EMBREE_ISA_AVX512 AND OPENVKL_ISA_AVX512SKX) set(OSPRAY_ISPC_TARGET_LIST ${OSPRAY_ISPC_TARGET_LIST} avx512skx-i32x16) message(STATUS "OSPRay AVX512SKX ISA target enabled.") endif() if(EMBREE_ISA_NEON AND OPENVKL_ISA_NEON) set(OSPRAY_ISPC_TARGET_LIST ${OSPRAY_ISPC_TARGET_LIST} neon-i32x4) message(STATUS "OSPRay NEON ISA target enabled.") endif() if(EMBREE_ISA_NEON2X AND OPENVKL_ISA_NEON2X) set(OSPRAY_ISPC_TARGET_LIST ${OSPRAY_ISPC_TARGET_LIST} neon-i32x8) message(STATUS "OSPRay NEON2X ISA target enabled.") endif() elseif (OSPRAY_BUILD_ISA STREQUAL "AVX512SKX") if(NOT EMBREE_ISA_AVX512) message(FATAL_ERROR "Your Embree build does not support AVX512SKX!") endif() if(NOT OPENVKL_ISA_AVX512SKX) message(FATAL_ERROR "Your Open VKL build does not support AVX512SKX!") endif() set(OSPRAY_ISPC_TARGET_LIST avx512skx-i32x16) elseif (OSPRAY_BUILD_ISA STREQUAL "AVX2") if(NOT EMBREE_ISA_AVX2) message(FATAL_ERROR "Your Embree build does not support AVX2!") endif() if(NOT OPENVKL_ISA_AVX2) message(FATAL_ERROR "Your Open VKL build does not support AVX2!") endif() set(OSPRAY_ISPC_TARGET_LIST avx2) elseif (OSPRAY_BUILD_ISA STREQUAL "AVX") if(NOT EMBREE_ISA_AVX) message(FATAL_ERROR "Your Embree build does not support AVX!") endif() if(NOT OPENVKL_ISA_AVX) message(FATAL_ERROR "Your Open VKL build does not support AVX!") endif() set(OSPRAY_ISPC_TARGET_LIST avx) elseif (OSPRAY_BUILD_ISA STREQUAL "SSE4") if(NOT EMBREE_ISA_SSE42) message(FATAL_ERROR "Your Embree build does not support SSE4!") endif() if(NOT OPENVKL_ISA_SSE4) message(FATAL_ERROR "Your Open VKL build does not support SSE4!") endif() set(OSPRAY_ISPC_TARGET_LIST sse4) elseif (OSPRAY_BUILD_ISA STREQUAL "NEON") if (NOT EMBREE_ISA_NEON) message(FATAL_ERROR "Your Embree build does not support NEON!") endif() if (NOT OPENVKL_ISA_NEON) message(FATAL_ERROR "Your OpenVKL build does not support NEON!") endif() set(OSPRAY_ISPC_TARGET_LIST neon-i32x4) elseif (OSPRAY_BUILD_ISA STREQUAL "NEON2X") if (NOT EMBREE_ISA_NEON2X) message(FATAL_ERROR "Your Embree build does not support NEON2X!") endif() if (NOT OPENVKL_ISA_NEON2X) message(FATAL_ERROR "Your OpenVKL build does not support NEON2X!") endif() set(OSPRAY_ISPC_TARGET_LIST neon-i32x8) else() message(FATAL_ERROR "Invalid OSPRAY_BUILD_ISA value. " "Please select one of ${OSPRAY_SUPPORTED_ISAS}, or ALL.") endif() ospray_fix_ispc_target_list() endmacro() macro(ospray_add_sycl_target target) target_compile_features(${target} PUBLIC cxx_std_17) target_compile_options(${target} PUBLIC ${OSPRAY_CXX_FLAGS_SYCL}) target_link_options(${target} PUBLIC ${OSPRAY_LINKER_FLAGS_SYCL}) endmacro() ## Target creation macros ## macro(ospray_sign_target name) if (OSPRAY_SIGN_FILE AND NOT APPLE) add_custom_command(TARGET ${name} POST_BUILD COMMAND ${OSPRAY_SIGN_FILE} -q $ COMMENT "Signing target" VERBATIM ) endif() endmacro() macro(ospray_install_library name component) set_target_properties(${name} PROPERTIES VERSION ${OSPRAY_VERSION} SOVERSION ${OSPRAY_SOVERSION}) ospray_install_target(${name} ${component}) ospray_sign_target(${name}) if (${ARGN}) # Install the namelink in the devel component. This command also includes the # RUNTIME and ARCHIVE components a second time to prevent an "install TARGETS # given no ARCHIVE DESTINATION for static library target" error. Installing # these components twice doesn't hurt anything. install(TARGETS ${name} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel NAMELINK_ONLY RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${component} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel ) endif() endmacro() macro(ospray_install_target name component) install(TARGETS ${name} EXPORT ospray_Exports LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${component} NAMELINK_SKIP # on Windows put the dlls into bin RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${component} # ... and the import lib into the devel package ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel ) install(EXPORT ospray_Exports DESTINATION ${OSPRAY_CMAKECONFIG_DIR} NAMESPACE ospray:: COMPONENT devel ) endmacro() ## Compiler configuration macros ## macro(ospray_configure_compiler) # unhide compiler to make it easier for users to see what they are using mark_as_advanced(CLEAR CMAKE_CXX_COMPILER) option(OSPRAY_STRICT_BUILD "Build with additional warning flags" ON) mark_as_advanced(OSPRAY_STRICT_BUILD) option(OSPRAY_WARN_AS_ERRORS "Treat warnings as errors" OFF) mark_as_advanced(OSPRAY_WARN_AS_ERRORS) set(OSPRAY_COMPILER_ICC FALSE) set(OSPRAY_COMPILER_GCC FALSE) set(OSPRAY_COMPILER_CLANG FALSE) set(OSPRAY_COMPILER_MSVC FALSE) set(OSPRAY_COMPILER_DPCPP FALSE) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "IntelLLVM" OR OSPRAY_MODULE_GPU) set(OSPRAY_COMPILER_DPCPP TRUE) include(dpcpp) if(WIN32) set(CMAKE_NINJA_CMCLDEPS_RC OFF) # workaround for https://gitlab.kitware.com/cmake/cmake/-/issues/18311 endif() elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") set(OSPRAY_COMPILER_ICC TRUE) if(WIN32) set(CMAKE_NINJA_CMCLDEPS_RC OFF) # workaround for https://gitlab.kitware.com/cmake/cmake/-/issues/18311 include(msvc) # icc on Windows behaves like msvc else() include(icc) endif() elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(OSPRAY_COMPILER_GCC TRUE) include(gcc) elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") set(OSPRAY_COMPILER_CLANG TRUE) include(clang) elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") set(OSPRAY_COMPILER_MSVC TRUE) include(msvc) else() message(FATAL_ERROR "Unsupported compiler specified: '${CMAKE_CXX_COMPILER_ID}'") endif() set(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG ${CMAKE_CXX_FLAGS_DEBUG}") if (WIN32) # increase stack to 8MB (the default size of 1MB is too small for our apps) if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Xlinker") endif() set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:8388608") endif() endmacro() macro(ospray_disable_compiler_warnings) if (NOT OSPRAY_COMPILER_MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w") endif() endmacro() ## Embree functions/macros ## function(ospray_check_embree_feature FEATURE VALUE DESC) set(FEATURE EMBREE_${FEATURE}) if (${ARGN}) if (${FEATURE} STREQUAL ${VALUE}) return() endif() else() if ((${VALUE} AND ${FEATURE}) OR (NOT ${VALUE} AND NOT ${FEATURE})) return() endif() endif() message(FATAL_ERROR "OSPRay requires Embree to ${DESC} (compiled with ${FEATURE}=${VALUE}).") endfunction() function(ospray_verify_embree_features) ospray_check_embree_feature(ISPC_SUPPORT ON "support ISPC") ospray_check_embree_feature(FILTER_FUNCTION ON "support intersection filter") ospray_check_embree_feature(GEOMETRY_TRIANGLE ON "support triangle geometries") ospray_check_embree_feature(GEOMETRY_CURVE ON "support spline curve geometries") ospray_check_embree_feature(GEOMETRY_USER ON "support user geometries") ospray_check_embree_feature(RAY_PACKETS ON "support ray packets") ospray_check_embree_feature(BACKFACE_CULLING OFF "have backface culling disabled") ospray_check_embree_feature(GEOMETRY_INSTANCE ON "support instances") ospray_check_embree_feature(MAX_INSTANCE_LEVEL_COUNT 1 "only support single-level instancing" ON) if (OSPRAY_MODULE_GPU) ospray_check_embree_feature(SYCL_SUPPORT ON "support DPC++/SYCL") endif() endfunction() macro(ospray_find_embree EMBREE_VERSION_REQUIRED FIND_AS_DEPENDENCY) if (${FIND_AS_DEPENDENCY}) find_dependency(embree ${EMBREE_VERSION_REQUIRED}) else() find_package(embree ${EMBREE_VERSION_REQUIRED}) endif() if (NOT embree_FOUND) message(FATAL_ERROR "We did not find Embree installed on your system. OSPRay requires" " an Embree installation >= v${EMBREE_VERSION_REQUIRED}, please" " download and extract Embree (or compile Embree from source), then" " set the 'embree_DIR' variable to the installation (or build)" " directory.") endif() # Get Embree CPU info get_target_property(EMBREE_INCLUDE_DIRS embree INTERFACE_INCLUDE_DIRECTORIES) get_target_property(CONFIGURATIONS embree IMPORTED_CONFIGURATIONS) list(GET CONFIGURATIONS 0 CONFIGURATION) get_target_property(EMBREE_LIBRARY embree IMPORTED_LOCATION_${CONFIGURATION}) # Get Embree SYCL info if DPCPP was enabled if (EMBREE_SYCL_SUPPORT) get_target_property(CONFIGURATIONS embree_sycl IMPORTED_CONFIGURATIONS) list(GET CONFIGURATIONS 0 CONFIGURATION) get_target_property(EMBREE_SYCL_LIBRARY embree_sycl IMPORTED_LOCATION_${CONFIGURATION}) endif() message(STATUS "Found Embree v${embree_VERSION}: ${EMBREE_LIBRARY}") endmacro() macro(ospray_find_openvkl OPENVKL_VERSION_REQUIRED FIND_AS_DEPENDENCY) if (${FIND_AS_DEPENDENCY}) find_dependency(openvkl ${OPENVKL_VERSION_REQUIRED}) else() find_package(openvkl ${OPENVKL_VERSION_REQUIRED}) endif() if (openvkl_FOUND) get_target_property(OPENVKL_INCLUDE_DIRS openvkl::openvkl INTERFACE_INCLUDE_DIRECTORIES) get_target_property(OPENVKL_CPU_DEVICE_INCLUDE_DIRS openvkl::openvkl_module_cpu_device INTERFACE_INCLUDE_DIRECTORIES) get_target_property(CONFIGURATIONS openvkl::openvkl IMPORTED_CONFIGURATIONS) list(GET CONFIGURATIONS 0 CONFIGURATION) get_target_property(OPENVKL_LIBRARY openvkl::openvkl IMPORTED_LOCATION_${CONFIGURATION}) message(STATUS "Found Open VKL v${openvkl_VERSION}: ${OPENVKL_LIBRARY}") endif() endmacro() RenderKit-ospray-f2a61c2/cmake/ospray_options.cmake000066400000000000000000000074551456566705700225340ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ############################################################## # Global configuration options ############################################################## include(GNUInstallDirs) include(CMakeDependentOption) set(OSPRAY_CMAKECONFIG_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/ospray-${OSPRAY_VERSION}") set(ISPC_VERSION_REQUIRED 1.23.0) set(RKCOMMON_VERSION_REQUIRED 1.13.0) set(EMBREE_VERSION_REQUIRED 4.3.1) set(OPENVKL_VERSION_REQUIRED 2.0.1) set(OIDN_VERSION_REQUIRED 2.2.0) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) ospray_configure_build_type() ospray_configure_compiler() ########################################################### # OSPRay specific build options ########################################################### option(OSPRAY_ENABLE_APPS "Enable the 'apps' subtree in the build." ON) option(OSPRAY_ENABLE_TARGET_CLANGFORMAT "Enable 'format' target, requires clang-format too") mark_as_advanced(OSPRAY_ENABLE_TARGET_CLANGFORMAT) # Dependent options cmake_dependent_option( OSPRAY_ENABLE_APPS_BENCHMARK "Enable building, installing, and packaging of benchmark tools." ON OSPRAY_ENABLE_APPS OFF ) cmake_dependent_option( OSPRAY_ENABLE_APPS_EXAMPLES "Enable building, installing, and packaging of ospExamples." ON OSPRAY_ENABLE_APPS OFF ) cmake_dependent_option( OSPRAY_ENABLE_APPS_TUTORIALS "Enable building, installing, and packaging of tutorial apps." ON OSPRAY_ENABLE_APPS OFF ) cmake_dependent_option( OSPRAY_ENABLE_APPS_TESTING "Enable building, installing, and packaging of test tools." ON OSPRAY_ENABLE_APPS OFF ) option(OSPRAY_ENABLE_VOLUMES "Enable volume rendering using OpenVKL." ON) ########################################################### # OSPRay's dependencies and configuration selection ########################################################### # rkcommon find_package(rkcommon ${RKCOMMON_VERSION_REQUIRED} EXACT REQUIRED) get_target_property(RKCOMMON_INCLUDE_DIRS rkcommon::rkcommon INTERFACE_INCLUDE_DIRECTORIES) # Embree ospray_find_embree(${EMBREE_VERSION_REQUIRED} FALSE) ospray_verify_embree_features() # ISPC set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS ON) find_package(ispcrt ${ISPC_VERSION_REQUIRED} REQUIRED) set(ISPC_FAST_MATH ON) # Open VKL if (OSPRAY_ENABLE_VOLUMES) ospray_find_openvkl(${OPENVKL_VERSION_REQUIRED} FALSE) if (NOT openvkl_FOUND) message(FATAL_ERROR "We did not find Open VKL installed on your system. OSPRay requires" " an Open VKL installation >= v${OPENVKL_VERSION_REQUIRED}, please" " download and extract Open VKL (or compile from source), then" " set the 'openvkl_DIR' variable to the installation directory.") endif() else() set(OPENVKL_ISA_SSE4 TRUE) set(OPENVKL_ISA_AVX TRUE) set(OPENVKL_ISA_AVX2 TRUE) set(OPENVKL_ISA_AVX512SKX TRUE) set(OPENVKL_ISA_NEON TRUE) set(OPENVKL_ISA_NEON2X TRUE) endif() # OpenImageDenoise if (OSPRAY_MODULE_DENOISER) find_package(OpenImageDenoise ${OIDN_VERSION_REQUIRED} REQUIRED) endif() # Configure OSPRay ISA last after we've detected what we got w/ Embree ospray_configure_ispc_isa() set(ISPC_TARGET_CPU ${OSPRAY_ISPC_TARGET_LIST}) ##################################################################### # Binary package options, before any install() invocation/definition ##################################################################### option(OSPRAY_ZIP_MODE "Use tarball/zip CPack generator instead of RPM" ON) mark_as_advanced(OSPRAY_ZIP_MODE) option(OSPRAY_INSTALL_DEPENDENCIES "Install OSPRay dependencies in binary packages and install") mark_as_advanced(OSPRAY_INSTALL_DEPENDENCIES) RenderKit-ospray-f2a61c2/cmake/ospray_redistribute_deps.cmake000066400000000000000000000123211456566705700245450ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 macro(ospray_get_target_configuration TARGET_NAME) set(TARGETName ${TARGET_NAME}) get_target_property(CONFIGURATIONS ${TARGET_NAME} IMPORTED_CONFIGURATIONS) string(TOUPPER ${CMAKE_BUILD_TYPE} CONFIGURATION) list(FIND CONFIGURATIONS ${CONFIGURATION} IDX) if (IDX LESS 0) set(IDX 0) # first/default configuration endif() list(GET CONFIGURATIONS ${IDX} CONFIGURATION) endmacro() macro(ospray_add_dependent_lib TARGET_NAME) if (TARGET ${TARGET_NAME}) ospray_get_target_configuration(${TARGET_NAME}) get_target_property(LIBRARY ${TARGET_NAME} IMPORTED_LOCATION_${CONFIGURATION}) get_target_property(LIBRARY_SO ${TARGET_NAME} IMPORTED_SONAME_${CONFIGURATION}) if (LIBRARY_SO) get_filename_component(LIBRARY_DIR ${LIBRARY} DIRECTORY) get_filename_component(LIBRARY_NAME ${LIBRARY_SO} NAME) set(LIBRARY "${LIBRARY_DIR}/${LIBRARY_NAME}") endif() list(APPEND DEPENDENT_LIBS ${LIBRARY}) else() message(STATUS "Skipping target '${TARGET_NAME}'") endif() endmacro() macro(ospray_add_dependent_lib_plugins TARGET_NAME PLUGINS_PATTERN VER_PATTERN) if (TARGET ${TARGET_NAME}) ospray_get_target_configuration(${TARGET_NAME}) # retrieve library directory get_target_property(LIBRARY ${TARGET_NAME} IMPORTED_LOCATION_${CONFIGURATION}) get_filename_component(LIBRARY_DIR ${LIBRARY} DIRECTORY) # search for plugins with given file pattern if (WIN32) file(GLOB LIBRARY_PLUGINS LIST_DIRECTORIES FALSE "${LIBRARY_DIR}/${PLUGINS_PATTERN}.dll" ) elseif (APPLE) file(GLOB LIBRARY_PLUGINS LIST_DIRECTORIES FALSE "${LIBRARY_DIR}/lib${PLUGINS_PATTERN}${VER_PATTERN}.dylib" ) else() file(GLOB LIBRARY_PLUGINS LIST_DIRECTORIES FALSE "${LIBRARY_DIR}/lib${PLUGINS_PATTERN}.so${VER_PATTERN}" ) endif() list(APPEND DEPENDENT_LIBS ${LIBRARY_PLUGINS}) else() message(STATUS "Skipping target '${TARGET_NAME}' plugins") endif() endmacro() ospray_add_dependent_lib(ispcrt::ispcrt) ospray_add_dependent_lib_plugins(ispcrt::ispcrt "ispcrt_device_*" "") ospray_add_dependent_lib(rkcommon::rkcommon) if (RKCOMMON_TASKING_TBB) ospray_add_dependent_lib(TBB::tbb) ospray_add_dependent_lib(TBB::tbbmalloc) if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") set(TBB_DEBUG_SUFFIX "_debug") endif() ospray_add_dependent_lib_plugins(TBB::tbb "tbbbind${TBB_DEBUG_SUFFIX}" ".[0-9]") ospray_add_dependent_lib_plugins(TBB::tbb "tbbbind_?_?${TBB_DEBUG_SUFFIX}" ".[0-9]") endif() ospray_add_dependent_lib(embree) ospray_add_dependent_lib(openvkl::openvkl) ospray_add_dependent_lib(openvkl::openvkl_module_cpu_device) ospray_add_dependent_lib(openvkl::openvkl_module_cpu_device_4) ospray_add_dependent_lib(openvkl::openvkl_module_cpu_device_8) ospray_add_dependent_lib(openvkl::openvkl_module_cpu_device_16) if (OSPRAY_MODULE_DENOISER) ospray_add_dependent_lib(OpenImageDenoise) ospray_add_dependent_lib(OpenImageDenoise_core) ospray_add_dependent_lib_plugins(OpenImageDenoise "OpenImageDenoise_device_*" ".[0-9].[0-9].[0-9]") endif() if (OSPRAY_MODULE_GPU OR OSPRAY_MODULE_DENOISER) if (OSPRAY_MODULE_GPU) get_filename_component(SYCL_DIR ${CMAKE_CXX_COMPILER} DIRECTORY) if (NOT WIN32) set(SYCL_DIR "${SYCL_DIR}/../lib") endif() else() get_target_property(CONFIGURATIONS OpenImageDenoise IMPORTED_CONFIGURATIONS) list(GET CONFIGURATIONS 0 CONFIGURATION) # use first/default configuration get_target_property(OIDN_LIB OpenImageDenoise IMPORTED_LOCATION_${CONFIGURATION}) get_filename_component(SYCL_DIR ${OIDN_LIB} DIRECTORY) endif() if (WIN32) file(GLOB SYCL_LIB LIST_DIRECTORIES FALSE "${SYCL_DIR}/sycl?.dll" "${SYCL_DIR}/pi_level_zero.dll" "${SYCL_DIR}/pi_win_proxy_loader.dll" "${SYCL_DIR}/win_proxy_loader.dll" ) else() file(GLOB SYCL_LIB LIST_DIRECTORIES FALSE "${SYCL_DIR}/libsycl.so.?" "${SYCL_DIR}/libpi_level_zero.so" ) endif() list(APPEND DEPENDENT_LIBS ${SYCL_LIB}) endif() if (WIN32) set(INSTALL_DIR ${CMAKE_INSTALL_BINDIR}) else() set(INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}) endif() if (OSPRAY_SIGN_FILE) add_custom_target(sign_files COMMAND ${OSPRAY_SIGN_FILE} -q ${DEPENDENT_LIBS} COMMENT "Signing files" VERBATIM ) else() add_custom_target(sign_files COMMENT "Not signing files") endif() foreach(LIB ${DEPENDENT_LIBS}) install(CODE "file(INSTALL \"${LIB}\" DESTINATION \${CMAKE_INSTALL_PREFIX}/${INSTALL_DIR} FOLLOW_SYMLINK_CHAIN)" COMPONENT redist ) endforeach() # Install MSVC runtime if (WIN32) set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE) include(InstallRequiredSystemLibraries) # FIXME WA for OSPRay to build with GNU-style options file(TO_CMAKE_PATH ${OSPRAY_MODULE_PATH} OSPRAY_MODULE_PATH) list(APPEND CMAKE_MODULE_PATH ${OSPRAY_MODULE_PATH}) include(ospray_system_runtime OPTIONAL) list(APPEND CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS "${OSPRAY_INSTALL_SYSTEM_RUNTIME_LIBS}") list(FILTER CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS INCLUDE REGEX ".*msvcp[0-9]+\.dll|.*vcruntime[0-9]+\.dll|.*vcruntime[0-9]+_[0-9]+\.dll") install(FILES ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT redist) endif() RenderKit-ospray-f2a61c2/cmake/ospray_version.cmake000066400000000000000000000024341456566705700225160ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(OSPRAY_VERSION_MAJOR 3) set(OSPRAY_VERSION_MINOR 1) set(OSPRAY_VERSION_PATCH 0) set(OSPRAY_SOVERSION 3) set(OSPRAY_VERSION_GITHASH 0) set(OSPRAY_VERSION_NOTE "") if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git AND IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/.git) find_package(Git) if (GIT_FOUND) execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse HEAD WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" OUTPUT_VARIABLE "OSPRAY_VERSION_GITHASH" OUTPUT_STRIP_TRAILING_WHITESPACE) string(SUBSTRING ${OSPRAY_VERSION_GITHASH} 0 8 OSPRAY_VERSION_GITHASH_SHORT) execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" OUTPUT_VARIABLE "OSPRAY_VERSION_GITBRANCH" OUTPUT_STRIP_TRAILING_WHITESPACE) if (NOT OSPRAY_VERSION_GITBRANCH MATCHES "^master$|^release-") if (NOT OSPRAY_VERSION_GITBRANCH STREQUAL "HEAD") set(OSPRAY_VERSION_NOTE "-${OSPRAY_VERSION_GITBRANCH}") endif() set(OSPRAY_VERSION_NOTE "${OSPRAY_VERSION_NOTE} (${OSPRAY_VERSION_GITHASH_SHORT})") endif() endif() endif() set(OSPRAY_VERSION ${OSPRAY_VERSION_MAJOR}.${OSPRAY_VERSION_MINOR}.${OSPRAY_VERSION_PATCH} ) RenderKit-ospray-f2a61c2/cmake/package.cmake000066400000000000000000000151621456566705700210310ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(CMAKE_INSTALL_SCRIPTDIR scripts) if (OSPRAY_ZIP_MODE) # in tgz / zip let's have relative RPath set(CMAKE_SKIP_INSTALL_RPATH OFF) if (APPLE) set(CMAKE_MACOSX_RPATH ON) set(CMAKE_INSTALL_RPATH "@loader_path/" "@loader_path/../${CMAKE_INSTALL_LIBDIR}") else() set(CMAKE_INSTALL_RPATH "\$ORIGIN:\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}") # on per target basis: #set_TARGET_PROPERTIES(apps INSTALL_RPATH "$ORIGIN:$ORIGIN/../lib") #set_TARGET_PROPERTIES(libs INSTALL_RPATH "$ORIGIN") endif() else() set(CMAKE_INSTALL_NAME_DIR ${CMAKE_INSTALL_FULL_LIBDIR}) if (APPLE) # use RPath on OSX set(CMAKE_SKIP_INSTALL_RPATH OFF) else() # we do not want any RPath for installed binaries set(CMAKE_SKIP_INSTALL_RPATH ON) endif() if (NOT WIN32) # for RPMs install docu in versioned folder set(CMAKE_INSTALL_DOCDIR ${CMAKE_INSTALL_DOCDIR}-${OSPRAY_VERSION}) set(CMAKE_INSTALL_SCRIPTDIR ${CMAKE_INSTALL_DATAROOTDIR}/OSPRay-${OSPRAY_VERSION}/scripts) endif() endif() ############################################################## # install headers ############################################################## install(DIRECTORY ${PROJECT_SOURCE_DIR}/ospray/include/ospray DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel FILES_MATCHING PATTERN "*.h" ) ############################################################## # install documentation ############################################################## install(FILES ${PROJECT_SOURCE_DIR}/third-party-programs.txt ${PROJECT_SOURCE_DIR}/third-party-programs-oneTBB.txt ${PROJECT_SOURCE_DIR}/third-party-programs-Embree.txt ${PROJECT_SOURCE_DIR}/third-party-programs-OpenVKL.txt ${PROJECT_SOURCE_DIR}/third-party-programs-OIDN.txt ${PROJECT_SOURCE_DIR}/third-party-programs-oneDNN.txt ${PROJECT_SOURCE_DIR}/third-party-programs-DPCPP.txt ${PROJECT_SOURCE_DIR}/third-party-programs-oneAPI-DPCPP.txt ${PROJECT_SOURCE_DIR}/third-party-programs-ISPC.txt ${PROJECT_SOURCE_DIR}/CHANGELOG.md ${PROJECT_SOURCE_DIR}/README.md DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib) install(FILES ${PROJECT_SOURCE_DIR}/readme.pdf DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib OPTIONAL) if (OSPRAY_INSTALL_DEPENDENCIES AND OSPRAY_MODULE_DENOISER AND OIDN_DEVICE_CUDA) install(FILES ${PROJECT_SOURCE_DIR}/doc/BINARY-LICENSE.txt RENAME LICENSE.txt DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib) else() install(FILES ${PROJECT_SOURCE_DIR}/LICENSE.txt DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT lib) endif() ############################################################## # CPack specific stuff ############################################################## set(CPACK_PACKAGE_NAME "OSPRay") set(CPACK_PACKAGE_FILE_NAME "ospray-${OSPRAY_VERSION}") #set(CPACK_PACKAGE_ICON ${PROJECT_SOURCE_DIR}/ospray-doc/images/icon.png) #set(CPACK_PACKAGE_RELOCATABLE TRUE) # do not disable, stripping symbols is important for security reasons set(CPACK_STRIP_FILES TRUE) set(CPACK_PACKAGE_VERSION_MAJOR ${OSPRAY_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${OSPRAY_VERSION_MINOR}) set(CPACK_PACKAGE_VERSION_PATCH ${OSPRAY_VERSION_PATCH}) set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "OSPRay: A Ray Tracing Based Rendering Engine for High-Fidelity Visualization") set(CPACK_PACKAGE_VENDOR "Intel Corporation") set(CPACK_PACKAGE_CONTACT ospray@googlegroups.com) set(CPACK_COMPONENT_LIB_DISPLAY_NAME "Library") set(CPACK_COMPONENT_LIB_DESCRIPTION "The OSPRay library including documentation.") set(CPACK_COMPONENT_DEVEL_DISPLAY_NAME "Development") set(CPACK_COMPONENT_DEVEL_DESCRIPTION "Header files for C and C++ required to develop applications with OSPRay.") set(CPACK_COMPONENT_APPS_DISPLAY_NAME "Applications") set(CPACK_COMPONENT_APPS_DESCRIPTION "Example, viewer and test applications as well as tutorials demonstrating how to use OSPRay.") set(CPACK_COMPONENT_MPI_DISPLAY_NAME "MPI Module") set(CPACK_COMPONENT_MPI_DESCRIPTION "OSPRay module for MPI-based distributed rendering.") set(CPACK_COMPONENT_GPU_DISPLAY_NAME "GPU Module") set(CPACK_COMPONENT_GPU_DESCRIPTION "OSPRay module for Intel Xe GPU-based rendering.") set(CPACK_COMPONENT_REDIST_DISPLAY_NAME "Redistributables") set(CPACK_COMPONENT_REDIST_DESCRIPTION "Dependencies of OSPRay (such as Embree, TBB, imgui) that may or may not be already installed on your system.") # dependencies between components set(CPACK_COMPONENT_DEVEL_DEPENDS lib) set(CPACK_COMPONENT_APPS_DEPENDS lib) set(CPACK_COMPONENT_MPI_DEPENDS lib) set(CPACK_COMPONENT_GPU_DEPENDS lib) set(CPACK_COMPONENT_LIB_REQUIRED ON) # always install the libs # point to readme and license files set(CPACK_RESOURCE_FILE_README ${PROJECT_SOURCE_DIR}/README.md) set(CPACK_RESOURCE_FILE_LICENSE ${PROJECT_SOURCE_DIR}/LICENSE.txt) if (OSPRAY_ZIP_MODE) set(CPACK_MONOLITHIC_INSTALL ON) else() set(CPACK_COMPONENTS_ALL lib devel apps) endif() if (WIN32) # Windows specific settings if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8) message(FATAL_ERROR "Only 64bit architecture supported.") endif() set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.x86_64.windows") if (OSPRAY_ZIP_MODE) set(CPACK_GENERATOR ZIP) else() set(CPACK_GENERATOR WIX) set(CPACK_WIX_ROOT_FEATURE_DESCRIPTION "OSPRay is an open source, scalable, and portable ray tracing engine for high-performance, high-fidelity visualization.") set(CPACK_WIX_PROPERTY_ARPURLINFOABOUT http://www.ospray.org/) set(CPACK_PACKAGE_NAME "OSPRay v${OSPRAY_VERSION}") list(APPEND CPACK_COMPONENTS_ALL redist) if (OSPRAY_MODULE_MPI) list(APPEND CPACK_COMPONENTS_ALL mpi) endif() if (OSPRAY_MODULE_GPU) list(APPEND CPACK_COMPONENTS_ALL gpu) endif() set(CPACK_PACKAGE_INSTALL_DIRECTORY "Intel\\\\OSPRay v${OSPRAY_VERSION_MAJOR}") math(EXPR OSPRAY_VERSION_NUMBER "10000*${OSPRAY_VERSION_MAJOR} + 100*${OSPRAY_VERSION_MINOR} + ${OSPRAY_VERSION_PATCH}") set(CPACK_WIX_PRODUCT_GUID "9D64D525-2603-4E8C-9108-845A146${OSPRAY_VERSION_NUMBER}") set(CPACK_WIX_UPGRADE_GUID "9D64D525-2603-4E8C-9108-845A146${OSPRAY_VERSION_MAJOR}0000") # upgrade as long as major version is the same set(CPACK_WIX_CMAKE_PACKAGE_REGISTRY TRUE) endif() elseif(APPLE) # MacOSX specific settings configure_file(${PROJECT_SOURCE_DIR}/README.md ${PROJECT_BINARY_DIR}/ReadMe.txt COPYONLY) set(CPACK_RESOURCE_FILE_README ${PROJECT_BINARY_DIR}/ReadMe.txt) set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.${CMAKE_SYSTEM_PROCESSOR}.macosx") set(CPACK_GENERATOR ZIP) else() # Linux specific settings set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}.${CMAKE_SYSTEM_PROCESSOR}.linux") set(CPACK_GENERATOR TGZ) endif() RenderKit-ospray-f2a61c2/doc/000077500000000000000000000000001456566705700161145ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/doc/.gitignore000066400000000000000000000001021456566705700200750ustar00rootroot00000000000000# generated files&folders changelog.md www tmp __pycache__ images RenderKit-ospray-f2a61c2/doc/BINARY-LICENSE.txt000066400000000000000000000435661456566705700207370ustar00rootroot00000000000000INTEL® OSPRAY SOFTWARE BINARY SOFTWARE LICENSE AGREEMENT IMPORTANT NOTICE – PLEASE READ AND AGREE BEFORE DOWNLOADING, INSTALLING, COPYING OR USING THE SOFTWARE This agreement (the "Agreement") is between you, or the company or other legal entity that you represent and warrant you have the legal authority to bind, (each, "You" or "Your") and Intel Corporation and its subsidiaries (collectively, "Intel") regarding Your use of the Software. By downloading, installing, copying or otherwise using the Software, You agree to be bound by the terms of this Agreement. If You do not agree to the terms of this Agreement, or do not have legal authority or required age to agree to them, do not download, install, copy or otherwise use the Software. 1. DEFINITIONS. "Derivative Works" means derivative works of the Software as defined in 17 U.S.C. § 101 et seq. "Reciprocal Open Source Software" means any software that is subject to a license which requires that (a) it must be distributed in source code form; (b) it must be licensed under the same open source license terms; and (c) its Derivative Works must be licensed under the same open source license terms. Examples of this type of license are the GNU General Public License or the Mozilla Public License. "Software" means the Intel® Open Image Denoise software in binary form, printed or electronic documentation, and any other collateral including any updates and upgrades that are made available to You by Intel under this Agreement. The Software does not include Third Party Software. "Third Party Software" mean the third party software (if any) listed in the "third-party-programs.txt" or other similarly-named text file that may be included in the Software. 2. LIMITED LICENSE. Subject to compliance with the terms and conditions of this Agreement, Intel grants You a limited, nonexclusive, nontransferable, revocable, worldwide, no fee license during the term of this Agreement, without the right to sublicense, under Intel’s copyrights, for Your (a) reasonable internal reproduction and internal use, and (b) redistribution of the Software to end users provided that: (i) the Software is provided under a written, legally enforceable end user license agreement that has the effect of protecting the Software and the rights of Intel and its licensors under terms no less restrictive than this Agreement, and (ii) You indemnify, defend, and hold harmless Intel and its licensors from any claims, including attorneys’ fees, related to the Your redistribution or use of the Software. 3. OWNERSHIP/LICENSE RESTRICTIONS. All right, title and interest in and to the Software are and will remain the exclusive property of Intel and its licensors. Unless expressly permitted under the Agreement, You will not, and will not allow any third party to (i) use, copy, distribute, transfer, sublicense, rent, sell or offer to sell the Software or associated documentation; (ii) modify, adapt, enhance, disassemble, decompile, reverse engineer, change or create Derivative Works from the Software except and only to the extent as specifically required by mandatory applicable laws; (iii) use or make the Software available for the use or benefit of third parties; (iv) modify, create a Derivative Work, link, or distribute the Software so that any part of it becomes subject to the license requirements of Reciprocal Open Source Software; (v) remove or alter any copyright, trademark or patent notice in the Software or any portion; (vi) use Intel’s or its licensors’ trademarks in Your distribution names or in a way that suggests Your distributions comes from or is endorsed by Intel or its licensors; (vii) bypass, disable, or circumvent any encryption, security, digital rights management or authentication mechanism in the Software; (viii) include the Software in malicious, deceptive or unlawful programs; (ix) distribute the Software in source code form; (x) grant the right to modify the Software; or (xi) reverse engineer, decompile or disassemble any portion of the output generated using the Software for the purpose of translating such output artifacts to target a non-NVIDIA platform if the output is intended for use on an NVIDIA platform. Furthermore, You: (a) acknowledge that an essential basis of the bargain in this Agreement is that Intel grants You no licenses or other rights including, but not limited to, patent, copyright, and trade secret, or other intellectual property licenses or rights to the Software, by implication, estoppel or otherwise, except for the licenses expressly granted above; (b) acknowledge there are significant uses of the Software in its original, unmodified and uncombined form. You may not remove any copyright notices from the Software; (c) agree to notify Intel in writing of any known or suspected distribution or use of the Software not in compliance with the requirements of this Agreement, and to enforce the terms of your agreements with respect to distributed Software; (d) agree to cooperate with Intel and provide reasonably requested information to verify your compliance with this Agreement; and (e) are solely responsible for ensuring that any product or service developed with the Software includes sufficient features to comply with all applicable legal and regulatory standards and requirements. 4. THIRD PARTY SOFTWARE. Third Party Software, even if included with the distribution of the Software, may be governed by separate license terms, including without limitation, open source software notices and terms, third party license terms, other Intel software license terms. Such separate license terms (and not this Agreement) govern Your use of the Third Party Programs. 5. Media Format Codecs and Digital Rights Management. You acknowledge and agree that Your use of the Software as permitted by this Agreement may require You to procure license(s) from third parties that may hold intellectual property rights applicable to any media decoding, encoding or transcoding technology (e.g., the use of an audio or video codec) or software, content, and/or digital rights management capabilities (the "Technology") of the Software, if any. Should any such additional licenses be required, You are solely responsible for obtaining any such licenses and agree to obtain any such licenses at Your own expense. Intel does not grant any necessary patent or other rights with respect to the Technology. 6. LICENSE TO FEEDBACK. This Agreement does not obligate You to provide Intel with materials, information, comments, suggestions, or other communication regarding the features, functions, performance or use of the Software ("Feedback"). To the extent You provide Intel with Feedback in a tangible form, You grant to Intel and its affiliates a non-exclusive, perpetual, sublicensable, irrevocable, worldwide, royalty-free, fully paid-up and transferable license, to and under all of Your intellectual property rights, whether perfected or not, to publicly perform, publicly display, reproduce, use, make, have made, sell, offer for sale, distribute, import, create Derivative Works of and otherwise exploit any comments, suggestions, descriptions, ideas or other feedback regarding the Software provided by You or on Your behalf. 7. SAFETY-CRITICAL, AND LIFE-SAVING APPLICATIONS; INDEMNITY. The Software may provide information relevant to safety-critical applications ("Safety-Critical Applications") to allow compliance with functional safety standards or requirements. You acknowledge and agree that safety is Your responsibility. To the extent You use the Software to create, or as part of, products used in Safety-Critical Applications, it is Your responsibility to design, manage, and ensure that there are system-level safeguards to anticipate, monitor, and control system failures, and You agree that You are solely responsible for all applicable regulatory standards and safety-related requirements concerning Your use of the Software in Safety Critical Applications. Should You use the Software for Safety-Critical Applications or in any type of a system or application in which the failure of the Software could create a situation where personal injury or death may occur (e.g., medical systems, life-sustaining or life-saving systems) ("Life-Saving Applications"), You agree to indemnify, defend, and hold Intel and its representatives harmless against any claims or lawsuits, costs, damages, and expenses, including reasonable attorney fees, arising in any way out of Your use of the Software in Safety-Critical Applications or Life-Saving Applications and claims of product liability, personal injury or death associated with those applications; even if such claims allege that Intel was negligent or strictly liable regarding the design or manufacture of the Software or its failure to warn regarding the Software. 8. NO OBLIGATION; NO AGENCY. Intel may make changes to the Software, or items referenced therein, at any time without notice. Intel is not obligated to support, update, provide training for, or develop any further versions of the Software or to grant any license thereto. No agency, franchise, partnership, joint venture, or employee-employer relationship is intended or created by this Agreement. 9. NO WARRANTY. DISCLAIMER. THE SOFTWARE IS PROVIDED "AS IS" AND "WITH ALL FAULTS.’ INTEL AND ITS LICENSORS EXPRESSLY DISCLAIM ALL WARRANTIES OF ANY KIND OR NATURE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, TITLE, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, OR THE ABSENCE OF ANY DEFECTS THEREIN, WHETHER LATENT OR PATENT. NO WARRANTY IS MADE ON THE BASIS OF TRADE USAGE, COURSE OF DEALING OR COURSE OF TRADE. Intel does not assume, and does not authorize any person to assume on its behalf, any other liability. Intel may make changes to the Software, or to items referenced therein, at any time without notice, but is not obligated to support, update or provide training for the Software under the terms of this Agreement. 10. LIMITATION OF LIABILITY. IN NO EVENT WILL INTEL OR ITS AFFILIATES, LICENSORS OR SUPPLIERS (INCLUDING THEIR RESPECTIVE DIRECTORS, OFFICERS, EMPLOYEES, AND AGENTS) BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, LOST PROFITS, LOSS OF USE, LOSS OF GOODWILL, BUSINESS INTERRUPTION, COSTS OF PROCURING SUBSTITUTE PRODUCTS OR LOST DATA) ARISING OUT OF OR IN RELATION TO THIS AGREEMENT, INCLUDING THE USE OF OR INABILITY TO USE THE SOFTWARE, WHETHER SUCH LIABILITY ARISES FROM ANY CLAIM BASED UPON BREACH OF CONTRACT, BREACH OF WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCT LIABILITY OR ANY OTHER CAUSE OF ACTION OR THEORY OF LIABILITY, EVEN IF INTEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME JURISDICTIONS PROHIBIT EXCLUSION OR LIMITATION OF LIABILITY FOR IMPLIED WARRANTIES OR CONSEQUENTIAL OR INCIDENTAL DAMAGES, SO THE ABOVE LIMITATION MAY IN PART NOT APPLY TO YOU. YOU MAY ALSO HAVE OTHER LEGAL RIGHTS THAT VARY FROM JURISDICTION TO JURISDICTION. IN NO EVENT WILL INTEL’S, ITS AFFILIATES’ AND LICENSORS’ TOTAL CUMULATIVE LIABILITY UNDER OR ARISING OUT OF THIS AGREEMENT EXCEED US$10.00. THE LIMITED REMEDIES, WARRANTY DISCLAIMER AND LIMITED LIABILITY ARE FUNDAMENTAL ELEMENTS OF THE BASIS OF THE BARGAIN BETWEEN INTEL AND YOU. YOU ACKNOWLEDGE INTEL WOULD BE UNABLE TO PROVIDE THE SOFTWARE WITHOUT SUCH LIMITATIONS. 11. TERMINATION AND SURVIVAL. This Agreement will terminate immediately if You violate any of its terms or conditions. Intel may, at any time, terminate this Agreement if (i) you commence or participate in any legal proceeding against Intel or its licensors with respect to the Software; (ii) if Intel decides to no longer provide the Software in a particular country; or (iii) if Intel, in its sole discretion, decides to no longer make the Software commercially available. Upon any termination of this Agreement, all licenses granted to You hereunder terminate immediately. Upon termination, You will immediately stop use of the Software, permanently remove the Software from your systems, destroy the Software, and keep no copies. If requested in writing, you will certify in writing that you have complied with your obligations under this Section. The following sections will survive termination of this Agreement: Section 1, 3 (only with respect to the first sentence), 4, 5, 6, 7, 9, 10, 11, 12, 16, 17, 18 and 19. 12. GOVERNING LAW AND JURISDICTION. This Agreement and any dispute arising out of or relating to it will be governed by the laws of the U.S.A. and Delaware, without regard to conflict of laws principles. The parties exclude the application of the United Nations Convention on Contracts for the International Sale of Goods (1980). The state and federal courts sitting in Delaware, U.S.A. will have exclusive jurisdiction over any dispute arising out of or relating to this Agreement. The parties consent to personal jurisdiction and venue in those courts. A party that obtains a judgment against the other party in the courts identified in this Section may enforce that judgment in any court that has jurisdiction over the parties. 13. EXPORT. You acknowledge that the Software and all related technical information are subject to export controls and You agree to comply with all laws and regulations of the United States and other applicable governments governing export, re-export, import, transfer, distribution, and use of the Software. In particular, but without limitation, the Software may not be exported or re-exported (a) into any U.S. embargoed countries or (b) to any person or entity listed on a denial order published by the U.S. government or any other applicable governments. By using the Software, You represent and warrant that You are not located in any such country or on any such list. You also agree that You will not use the Software for, or sell or transfer them to a third party who is known or suspected to be involved in, any purposes prohibited by the U.S. government or other applicable governments, including, without limitation, the development, design, manufacture, or production of nuclear, missile, chemical or biological weapons. 14. GOVERNMENT RESTRICTED RIGHTS. The technical data and computer software covered by this license is a "Commercial Item," as such term is defined by the FAR 2.101 (48 C.F.R. 2.101) and is "commercial computer software" and "commercial computer software documentation" as specified under FAR 12.212 (48 C.F.R. 12.212) or DFARS 227.7202 (48 C.F.R. 227.7202), as applicable. This commercial computer software and related documentation is provided to end users for use by and on behalf of the U.S. Government, with only those rights as are granted to all other end users pursuant to the terms and conditions herein. 15. ASSIGNMENT. You may not delegate, assign or transfer this Agreement, the license(s) granted or any of Your rights or duties hereunder, expressly, by implication, by operation of law, or otherwise and any attempt to do so, without Intel’s express prior written consent, will be null and void. Intel may assign, delegate and transfer this Agreement, and its rights and obligations hereunder, in its sole discretion. 16. ENTIRE AGREEMENT. This Agreement contains the complete and exclusive agreement and understanding between the parties concerning the subject matter of this Agreement, and supersedes all prior and contemporaneous proposals, agreements, understanding, negotiations, representations, warranties, conditions, and communications, oral or written, between the parties relating to the same subject matter. You acknowledge and agree that in entering into this Agreement You have not relied on, and will not be entitled to rely on, any oral or written representations, warranties, conditions, understanding, or communications that are not expressly set forth in this Agreement. The express provisions of this Agreement control over any course of performance, course of dealing, or usage of the trade inconsistent with any of the provisions of this Agreement. The provisions of this Agreement will prevail notwithstanding any different, conflicting, or additional provisions that may appear on any purchase order, acknowledgement, invoice, or other writing issued by either party in connection with this Agreement. No modification or amendment to this Agreement will be effective unless in writing and signed by authorized representatives of each party, and must specifically identify this Agreement by its title and version; , except that Intel may make changes to the Agreement as it distributes new versions of the Software. If You received a copy of this Agreement translated into another language, the English language version of this Agreement will prevail in the event of any conflict between versions. 17. SEVERABILITY AND WAIVER. The parties intend that if a court holds that any provision or part of this Agreement is invalid or unenforceable under applicable law, the court will modify the provision to the minimum extent necessary to make it valid and enforceable, or if it cannot be made valid and enforceable, the parties intend that the court will sever and delete the provision or part from this Agreement. Any change to or deletion of a provision or part of this Agreement under this Section will not affect the validity or enforceability of the remainder of this Agreement, which will continue in full force and effect. The failure of a party to require performance by the other party of any provision hereof will not affect the full right to require such performance at any time thereafter; nor will waiver by a party of a breach of any provision hereof constitute a waiver of the provision itself. 18. PRIVACY. YOUR PRIVACY RIGHTS ARE SET FORTH IN INTEL’S PRIVACY NOTICE, WHICH FORMS A PART OF THIS AGREEMENT. PLEASE REVIEW THE PRIVACY NOTICE AT HTTP://WWW.INTEL.COM/PRIVACY TO LEARN HOW INTEL COLLECTS, USES AND SHARES INFORMATION ABOUT YOU. 19. THIRD PARTY BENEFICIARIES. The Software includes software and materials from Intel’s licensors. These licensors are intended third party beneficiaries that may enforce this Agreement with respect to their intellectual property rights. RenderKit-ospray-f2a61c2/doc/Makefile000066400000000000000000000222351456566705700175600ustar00rootroot00000000000000SHELL := /bin/bash webpages := $(addprefix www/, $(addsuffix .html, index tutorials documentation gallery downloads related_projects displaywall ospray2_porting_guide legal)) process_version := $(addprefix tmp/, $(addsuffix .md, tutorials getting_ospray readme_head)) tmptexfiles := $(addprefix tmp/, $(addsuffix .tex, overview changelog compilation api tutorials)) images_jpg := $(addprefix images/, $(addsuffix .jpg, exampleViewer $(addprefix camera_, perspective architectural stereo orthographic panoramic) $(addprefix material_, OBJ Principled CarPaint Metal Alloy Glass ThinGlass MetallicPaint Luminous) ColoredWindow $(addprefix ospMPIDistribTutorial, Volume Spheres _firstFrame _accumulatedFrame))) images_png := $(addprefix images/, $(addsuffix .png, diffuse_rooms normalmap_frustum tutorial_accumulatedframe tutorial_firstframe ospExamples renderSunSky)) images_fig := spot_light c-gamma_coords quad_light hdri_light images_svg := structured_spherical_coords vdb_structure images_fig2pdf := $(addprefix tmp/, $(addsuffix .pdf, $(images_fig))) images_svg2pdf := $(addprefix images/, $(addsuffix .pdf, $(images_svg))) images_fig2png := $(addprefix images/, $(addsuffix .png, $(images_fig))) webimages := $(addprefix www/, $(images_jpg) $(images_png) $(images_fig2png) $(addprefix images/, vdb_structure.png $(addsuffix .svg, $(images_svg)))) pdfimages := $(images_jpg) $(images_png) $(images_fig2pdf) $(images_svg2pdf) PANDOC := pandoc PDMINVERSION := 2000000 PDVERSION := $(shell $(PANDOC) --version|head -n 1) $(info Using $(PDVERSION)) PDOK := $(shell expr `$(PANDOC) --version|head -n 1|cut -d' ' -f 2| sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/' -e 's/^[0-9]\{5,6\}$$/&00/'` \>= $(PDMINVERSION)) ifneq "$(PDOK)" "1" $(error You need at least pandoc v2.0) endif all: www doc pdf www: $(webpages) www/stylesheet.css $(webimages) | wwwscripts doc: ../README.md pdf: ../readme.pdf spec: ospray-spec.html ospray-spec.rst $(webimages) checklinks: tmp/brokenlinks.txt @if [[ -s $^ ]] ; then \ echo "Found broken link:" ;\ cat $^ ;\ exit 1 ;\ else \ echo "All links good." ;\ fi .PHONY: all www doc pdf clean realclean submodule checklinks spec submodule: git submodule update --init --remote if_is_devel_then = if [[ "${CI_BUILD_REF_NAME}" == *"devel" || (-d ../.git && "`git rev-parse --abbrev-ref HEAD`" == *"devel") ]] ; then tmp/version: ../cmake/ospray_version.cmake $(wildcard ../.git/HEAD) sed -n $< -e "s/^set(OSPRAY_VERSION_MAJOR \([0-9]\+\))/\1./ip" | tr -d '\n' > $@ sed -n $< -e "s/^set(OSPRAY_VERSION_MINOR \([0-9]\+\))/\1./ip" | tr -d '\n' >> $@ sed -n $< -e "s/^set(OSPRAY_VERSION_PATCH \([0-9]\+\))/\1/ip" | tr -d '\n' >> $@ sed -n $< -e 's/^set(OSPRAY_VERSION_NOTE "")//;t;s/^set(OSPRAY_VERSION_NOTE "\([^"]\+\)")/ (\1)/ip' | tr -d '\n' >> $@ $(if_is_devel_then) echo " (devel)"; else echo; fi >> $@ replace_version = sed -e "s//`cat tmp/version`/g" $< > $@ tmp/%.md: %.md tmp/version tmp/links_local.md tmp/images_web.md $(replace_version) $(PANDOC) $@ tmp/links_local.md tmp/images_web.md -o $@ tmp/links.md: links.md $(wildcard ../.git/HEAD) $(if_is_devel_then) \ sed -e "s/OSPRay_readme.pdf/OSPRay_readme_devel.pdf/g" $< > $@;\ else cp $< $@ ;\ fi tmp/links_local.md: tmp/links.md sed -e "s@: [a-z]\+\.html#@: #@" $< > $@ tmp/images_web.md: images.md sed -e "s/\.fig/.png/" -e "s/vdb_structure\.svg/vdb_structure.png/" -e "s@: @: https://ospray.github.io/images/@" $< > $@ tmp/images_local_png.md: images.md sed -e "s@: @: images/@" -e "s/vdb_structure\.svg/vdb_structure.png/" -e "s/\.fig/.png/" $< > $@ tmp/images_local_pdf.md: images.md sed -e "s@: @: images/@" -e "s@images/\(.*\)\.fig@tmp/\1.pdf@" -e "s@\.svg@.pdf@" $< > $@ ### directories ######################################################################## $(webpages) www/stylesheet.css: | wwwdir wwwdir: @mkdir -p www $(webimages): | wwwimgdir wwwimgdir: @mkdir -p www/images wwwscripts: | wwwdir if [[ -d ospray-doc/scripts ]] ; then \ cp -r ospray-doc/scripts/ www ;\ fi $(process_version) tmp/version ../readme.pdf $(tmptexfiles) $(images_fig2pdf) tmp/api.md tmp/api_web.md tmp/changelog.md tmp/compilation.md tmp/compilation_web.md tmp/links.md tmp/links_local.md tmp/images_web.md tmp/images_local_png.md tmp/images_local_pdf.md: | tmpdir tmpdir: @mkdir -p tmp ### spec ######################################################################## ospray-spec.rst: api.md tmp/links_local.md tmp/images_local_png.md $(PANDOC) --wrap=none --indented-code-classes=cpp --email-obfuscation=none $+ -t rst | sed -e 's@½@\\frac{1}{2}@g' > $@ ospray-spec.html: ospray-spec.rst rst2html $+ $@ ### webpages ######################################################################## markdown2web = $(PANDOC) --email-obfuscation=none -f markdown $(filter-out webtemplate.html,$+) --template webtemplate -V select_$(basename $(@F)) -o $@ $(webpages): tmp/links.md tmp/images_local_png.md webtemplate.html www/%.html: $(markdown2web) www/stylesheet.css: stylesheet.css cp $< $@ tmp/api_web.md: api.md tmp/links.md tmp/images_local_png.md $(PANDOC) $+ --indented-code-classes=cpp -t markdown-fenced_code_attributes -o $@ tmp/compilation_web.md: prerequisites.md ../scripts/superbuild/README.md compilation.md tmp/links.md $(PANDOC) $+ --indented-code-classes=sh -t markdown-fenced_code_attributes -o $@ tmp/changelog.md: filter-sectionnumbers.py ../CHANGELOG.md $(PANDOC) --top-level-division=chapter --filter $+ -o $@ echo -e '\nFor the complete history of changes have a look at the [CHANGELOG](https://github.com/ospray/ospray/blob/master/CHANGELOG.md).' >> $@ www/index.html: teaser.html overview.md tmp/changelog.md www/tutorials.html: tutorials.md $(markdown2web) --indented-code-classes=sh www/gallery.html: gallery.md www/downloads.html: tmp/getting_ospray.md tmp/compilation_web.md www/related_projects.html: related_projects.md www/displaywall.html: displaywall.md www/legal.html: legal.md www/documentation.html: documentation.md tmp/api_web.md $(markdown2web) --toc www/ospray2_porting_guide.html: ospray2_porting_guide.md $(markdown2web) --indented-code-classes=cpp ### images ######################################################################## www/images/%.png: %.fig fig2dev -L png -S 4 $+ $@ www/images/%.svg: %.svg cp $+ $@ tmp/%.pdf: %.fig fig2dev -L pdf $+ $@ www/images/%: images/% cp $< $@ # try to download images if not linked; images may not be up to date images/%: if [[ -d ospray-doc/images ]] ; then \ ln -fs ospray-doc/images ;\ else \ if [[ -x "`which wget 2> /dev/null`" ]] ; then \ mkdir -p images ;\ wget https://ospray.github.io/$@ -O $@ ;\ else \ curl https://ospray.github.io/$@ --create-dirs -Lo $@ ;\ fi \ fi ### markdown ######################################################################## # also works around pandoc #5121, should be fixed in v2.5.1 convert_nbsp_width = sed -e 's@\\ @ @g' -e 's/" style="width:/" width="/g' -e "s@^@\0\n\n@" tmp/api.md: api.md tmp/links_local.md tmp/images_web.md $(PANDOC) $+ --indented-code-classes=cpp -t markdown-fenced_code_attributes -o $@ tmp/compilation.md: prerequisites.md ../scripts/superbuild/README.md compilation.md tmp/links_local.md $(PANDOC) $+ --indented-code-classes=sh -t markdown-fenced_code_attributes -o $@ tmp/tutorials.md: tutorials.md tmp/links_local.md tmp/images_web.md $(PANDOC) $+ --indented-code-classes=sh -t markdown-fenced_code_attributes -o $@ ../README.md: tmp/readme_head.md tmp/overview.md tmp/compilation.md tmp/documentation.md tmp/api.md tmp/tutorials.md $(PANDOC) --file-scope $+ --markdown-headings=setext -t gfm | $(convert_nbsp_width) > $@ ### pdf ######################################################################## markdown2tex = $(PANDOC) --columns=72 --top-level-division=chapter --filter $+ -o $@ tmp/%.tex: filter-latex.py %.md tmp/links_local.md tmp/images_local_pdf.md $(markdown2tex) tmp/api.tex: filter-latex.py api.md tmp/links_local.md tmp/images_local_pdf.md $(markdown2tex) --indented-code-classes=cpp tmp/compilation.tex: filter-latex.py prerequisites.md ../scripts/superbuild/README.md compilation.md tmp/links_local.md tmp/images_local_pdf.md $(markdown2tex) --indented-code-classes=sh tmp/tutorials.tex: filter-latex.py tutorials.md tmp/links_local.md tmp/images_local_pdf.md $(markdown2tex) --indented-code-classes=sh tmp/changelog.tex: filter-latex.py tmp/changelog.md tmp/links_local.md tmp/images_local_pdf.md $(markdown2tex) ../readme.pdf: readme.tex $(tmptexfiles) $(wildcard ospray-doc/intel-spec.cls) preamble.tex tmp/version $(pdfimages) md5s=0;\ auxf="tmp/`basename $< tex`aux";\ newmd5s=`md5sum $$auxf 2> /dev/null`;\ until [[ $$md5s == $$newmd5s ]]; do \ md5s=$$newmd5s;\ xelatex -halt-on-error -output-directory=tmp $< || exit 2;\ newmd5s=`md5sum $$auxf`;\ done cp tmp/$(basename $<).pdf $@ # crude way to detect broken pdf links tmp/%.txt: $(tmptexfiles) fgrep -h $* $^ | sed -e 's@.*$*{\([^}]*\)}.*@\1@'|sort -u > $@ tmp/brokenlinks.txt: tmp/hypertarget.txt tmp/hyperlink.txt -diff -u $^ | grep "^+[^+]" > $@ ### clean ######################################################################## clean: rm -rf www tmp __pycache__ ospray-spec.html ospray-spec.rst realclean: clean rm -irf images RenderKit-ospray-f2a61c2/doc/api.md000066400000000000000000005211621456566705700172160ustar00rootroot00000000000000OSPRay API ========== To access the OSPRay API you first need to include the OSPRay header #include "ospray/ospray.h" where the API is compatible with C99 and C++. Initialization and Shutdown --------------------------- To use the API, OSPRay must be initialized with a "device". A device is the object which implements the API. Creating and initializing a device can be done in either of two ways: command line arguments using `ospInit` or manually instantiating a device and setting parameters on it. ### Command Line Arguments The first is to do so by giving OSPRay the command line from `main()` by calling OSPError ospInit(int *argc, const char **argv); OSPRay parses (and removes) its known command line parameters from your application's `main` function. For an example see the [tutorial]. For possible error codes see section [Error Handling and Status Messages]. It is important to note that the arguments passed to `ospInit` are processed in order they are listed. The following parameters (which are prefixed by convention with "`--osp:`") are understood: -------------------------------------------- ----------------------------------------------------- Parameter Description -------------------------------------------- ----------------------------------------------------- `--osp:debug` enables various extra checks and debug output, and disables multi-threading `--osp:num-threads=` use `n` threads instead of per default using all detected hardware threads `--osp:log-level=` set logging level; valid values (in order of severity) are `none`, `error`, `warning`, `info`, and `debug` `--osp:warn-as-error` send `warning` and `error` messages through the error callback, otherwise send `warning` messages through the message callback; must have sufficient `logLevel` to enable warnings `--osp:verbose` shortcut for `--osp:log-level=info` and enable debug output on `cout`, error output on `cerr` `--osp:vv` shortcut for `--osp:log-level=debug` and enable debug output on `cout`, error output on `cerr` `--osp:load-modules=[,...]` load one or more modules during initialization; equivalent to calling `ospLoadModule(name)` `--osp:log-output=` convenience for setting where status messages go; valid values for `dst` are `cerr` and `cout` `--osp:error-output=` convenience for setting where error messages go; valid values for `dst` are `cerr` and `cout` `--osp:device=` use `name` as the type of device for OSPRay to create; e.g., `--osp:device=cpu` gives you the default `cpu` device; Note if the device to be used is defined in a module, remember to pass `--osp:load-modules=` first `--osp:set-affinity=` if `1`, bind software threads to hardware threads; `0` disables binding; default is `0` `--osp:device-params=:[,...]` set one or more other device parameters; equivalent to calling `ospDeviceSet*(param, value)` -------------------------------------------- ----------------------------------------------------- : Command line parameters accepted by OSPRay's `ospInit`. ### Manual Device Instantiation The second method of initialization is to explicitly create the device and possibly set parameters. This method looks almost identical to how other [objects] are created and used by OSPRay (described in later sections). The first step is to create the device with OSPDevice ospNewDevice(const char *type); where the `type` string maps to a specific device implementation. OSPRay always provides the "`cpu`" device, which maps to a fast, local CPU implementation. Other devices can also be added through additional modules, such as distributed MPI device implementations. See next Chapter for details. Once a device is created, you can call void ospDeviceSetParam(OSPObject, const char *id, OSPDataType type, const void *mem); to set parameters on the device. The semantics of setting parameters is exactly the same as `ospSetParam`, which is documented below in the [parameters] section. The following parameters can be set on all devices: ------ ------------ ---------------------------------------------------------- Type Name Description ------ ------------ ---------------------------------------------------------- int numThreads number of threads which OSPRay should use uint logLevel logging level; valid values (in order of severity) are `OSP_LOG_NONE`, `OSP_LOG_ERROR`, `OSP_LOG_WARNING`, `OSP_LOG_INFO`, and `OSP_LOG_DEBUG` string logOutput convenience for setting where status messages go; valid values are `cerr` and `cout` string errorOutput convenience for setting where error messages go; valid values are `cerr` and `cout` bool debug set debug mode; equivalent to `logLevel=debug` and `numThreads=1` bool warnAsError send `warning` and `error` messages through the error callback, otherwise send `warning` messages through the message callback; must have sufficient `logLevel` to enable warnings bool setAffinity bind software threads to hardware threads if set to 1; 0 disables binding omitting the parameter will let OSPRay choose ------ ------------ ---------------------------------------------------------- : Parameters shared by all devices. Once parameters are set on the created device, the device must be committed with void ospDeviceCommit(OSPDevice); To use the newly committed device, you must call void ospSetCurrentDevice(OSPDevice); This then sets the given device as the object which will respond to all other OSPRay API calls. Device handle lifetimes are managed with two calls, the first which increments the internal reference count to the given `OSPDevice` void ospDeviceRetain(OSPDevice) and the second which decrements the reference count void ospDeviceRelease(OSPDevice) Users can change parameters on the device after initialization (from either method above), by calling OSPDevice ospGetCurrentDevice(); This function returns the handle to the device currently used to respond to OSPRay API calls, where users can set/change parameters and recommit the device. If changes are made to the device that is already set as the current device, it does not need to be set as current again. Note this API call will increment the ref count of the returned device handle, so applications must use `ospDeviceRelease` when finished using the handle to avoid leaking the underlying device object. If there is no current device set, this will return an invalid `NULL` handle. When a device is created, its reference count is initially `1`. When a device is set as the current device, it internally has its reference count incremented. Note that `ospDeviceRetain` and `ospDeviceRelease` should only be used with reference counts that the application tracks: removing reference held by the current set device should be handled by `ospShutdown`. Thus, `ospDeviceRelease` should only decrement the reference counts that come from `ospNewDevice`, `ospGetCurrentDevice`, and the number of explicit calls to `ospDeviceRetain`. OSPRay allows applications to query runtime properties of a device in order to do enhanced validation of what device was loaded at runtime. The following function can be used to get these device-specific properties (attributes about the device, not parameter values) int64_t ospDeviceGetProperty(OSPDevice, OSPDeviceProperty); It returns an integer value of the queried property and the following properties can be provided as parameter: OSP_DEVICE_VERSION OSP_DEVICE_VERSION_MAJOR OSP_DEVICE_VERSION_MINOR OSP_DEVICE_VERSION_PATCH OSP_DEVICE_SO_VERSION ### Environment Variables OSPRay's generic device parameters can be overridden via environment variables for easy changes to OSPRay's behavior without needing to change the application (variables are prefixed by convention with "`OSPRAY_`"): --------------------- -------------------------------------------------------- Variable Description --------------------- -------------------------------------------------------- OSPRAY_NUM_THREADS equivalent to `--osp:num-threads` OSPRAY_LOG_LEVEL equivalent to `--osp:log-level` OSPRAY_LOG_OUTPUT equivalent to `--osp:log-output` OSPRAY_ERROR_OUTPUT equivalent to `--osp:error-output` OSPRAY_DEBUG equivalent to `--osp:debug` OSPRAY_WARN_AS_ERROR equivalent to `--osp:warn-as-error` OSPRAY_SET_AFFINITY equivalent to `--osp:set-affinity` OSPRAY_LOAD_MODULES equivalent to `--osp:load-modules`, can be a comma separated list of modules which will be loaded in order OSPRAY_DEVICE equivalent to `--osp:device:` --------------------- -------------------------------------------------------- : Environment variables interpreted by OSPRay. Note that these environment variables take precedence over values specified through `ospInit` or manually set device parameters. ### Error Handling and Status Messages The following errors are currently used by OSPRay: Name Description ---------------------- ------------------------------------------------------- OSP_NO_ERROR no error occurred OSP_UNKNOWN_ERROR an unknown error occurred OSP_INVALID_ARGUMENT an invalid argument was specified OSP_INVALID_OPERATION the operation is not allowed for the specified object OSP_OUT_OF_MEMORY there is not enough memory to execute the command OSP_UNSUPPORTED_CPU the CPU is not supported (minimum ISA is SSE4.1 on x86_64 and NEON on ARM64) OSP_VERSION_MISMATCH a module could not be loaded due to mismatching version ---------------------- ------------------------------------------------------- : Possible error codes, i.e., valid named constants of type `OSPError`. These error codes are either directly return by some API functions, or are recorded to be later queried by the application via OSPError ospDeviceGetLastErrorCode(OSPDevice); A more descriptive error message can be queried by calling const char* ospDeviceGetLastErrorMsg(OSPDevice); Alternatively, the application can also register a callback function of type typedef void (*OSPErrorCallback)(void *userData, OSPError, const char* errorDetails); via void ospDeviceSetErrorCallback(OSPDevice, OSPErrorCallback, void *userData); to get notified when errors occur. Applications may be interested in messages which OSPRay emits, whether for debugging or logging events. Applications can call void ospDeviceSetStatusCallback(OSPDevice, OSPStatusCallback, void *userData); in order to register a callback function of type typedef void (*OSPStatusCallback)(void *userData, const char* messageText); which OSPRay will use to emit status messages. By default, OSPRay uses a callback which does nothing, so any output desired by an application will require that a callback is provided. Note that callbacks for C++ `std::cout` and `std::cerr` can be alternatively set through `ospInit` or the `OSPRAY_LOG_OUTPUT` environment variable. Applications can clear either callback by passing `NULL` instead of an actual function pointer. ### Loading OSPRay Extensions at Runtime OSPRay's functionality can be extended via plugins (which we call "modules"), which are implemented in shared libraries. To load module `name` from `libospray_module_.so` (on Linux and Mac OS\ X) or `ospray_module_.dll` (on Windows) use OSPError ospLoadModule(const char *name); Modules are searched in OS-dependent paths. `ospLoadModule` returns `OSP_NO_ERROR` if the plugin could be successfully loaded. ### Shutting Down OSPRay When the application is finished using OSPRay (typically on application exit), the OSPRay API should be finalized with void ospShutdown(); This API call ensures that the current device is cleaned up appropriately. Due to static object allocation having non-deterministic ordering, it is recommended that applications call `ospShutdown` before the calling application process terminates. Objects ------- All entities of OSPRay (the [renderer], [volumes], [geometries], [lights], [cameras], ...) are a logical specialization of `OSPObject` and share common mechanism to deal with parameters and lifetime. An important aspect of object parameters is that parameters do not get passed to objects immediately. Instead, parameters are not visible at all to objects until they get explicitly committed to a given object via a call to void ospCommit(OSPObject); at which time all previously additions or changes to parameters are visible at the same time. If a user wants to change the state of an existing object (e.g., to change the origin of an already existing camera) it is perfectly valid to do so, as long as the changed parameters are recommitted. The commit semantic allow for batching up multiple small changes, and specifies exactly when changes to objects will occur. This can impact performance and consistency for devices crossing a PCI bus or across a network. Note that OSPRay uses reference counting to manage the lifetime of all objects, so one cannot explicitly "delete" any object. Instead, to indicate that the application does not need and does not access the given object anymore, call void ospRelease(OSPObject); This decreases its reference count and if the count reaches `0` the object will automatically get deleted. Passing `NULL` is not an error. Note that every handle returned via the API needs to be released when the object is no longer needed, to avoid memory leaks. Sometimes applications may want to have more than one reference to an object, where it is desirable for the application to increment the reference count of an object. This is done with void ospRetain(OSPObject); It is important to note that this is only necessary if the application wants to call `ospRelease` on an object more than once: objects which contain other objects as parameters internally increment/decrement ref counts and should not be explicitly done by the application. ### Parameters Parameters allow to configure the behavior of and to pass data to objects. However, objects do _not_ have an explicit interface for reasons of high flexibility and a more stable compile-time API. Instead, parameters are passed separately to objects in an arbitrary order, and unknown parameters will simply be ignored (though a warning message will be posted). The following function allows adding various types of parameters with name `id` to a given object: void ospSetParam(OSPObject, const char *id, OSPDataType type, const void *mem); The valid parameter names for all `OSPObject`s and what types are valid are discussed in future sections. Note that `mem` must always be a pointer _to_ the object, otherwise accidental type casting can occur. This is especially true for pointer types (`OSP_VOID_PTR` and `OSPObject` handles), as they will implicitly cast to `void\ *`, but be incorrectly interpreted. To help with some of these issues, there also exist variants of `ospSetParam` for specific types, such as `ospSetInt` and `ospSetVec3f` in the OSPRay utility library (found in `ospray_util.h`). Note that half precision float parameters `OSP_HALF, OSP_VEC[234]H` are not supported. Users can also remove parameters that have been explicitly set from `ospSetParam`. Any parameters which have been removed will go back to their default value during the next commit unless a new parameter was set after the parameter was removed. To remove a parameter, use void ospRemoveParam(OSPObject, const char *id); ### Data OSPRay consumes data arrays from the application using a specific object type, `OSPData`. There are several components to describing a data array: element type, 1/2/3 dimensional striding, and whether the array is shared with the application or copied into opaque, OSPRay-owned memory. Shared data arrays require that the application's array memory outlives the lifetime of the created `OSPData`, as OSPRay is referring to application memory. Where this is not preferable, applications use opaque arrays to allow the `OSPData` to own the lifetime of the array memory. However, opaque arrays dictate the cost of copying data into it, which should be kept in mind. Thus, the most efficient way to specify a data array from the application is to created a shared data array, which is done with OSPData ospNewSharedData(const void *sharedData, OSPDataType, uint64_t numItems1, int64_t byteStride1 = 0, uint64_t numItems2 = 1, int64_t byteStride2 = 0, uint64_t numItems3 = 1, int64_t byteStride3 = 0, OSPDeleterCallback = NULL, void *userData = NULL); The call returns an `OSPData` handle to the created array. The calling program guarantees that the `sharedData` pointer will remain valid for the duration that this data array is being used. The number of elements `numItems` must be positive (there cannot be an empty data object). The data is arranged in three dimensions, with specializations to two or one dimension (if some `numItems` are 1). The distance between consecutive elements (per dimension) is given in bytes with `byteStride` and can also be negative. If `byteStride` is zero it will be determined automatically (e.g., as `sizeof(type)`). Strides do not need to be ordered, i.e., `byteStride2` can be smaller than `byteStride1`, which is equivalent to a transpose. However, if the stride should be calculated, then an ordering in dimensions is assumed to disambiguate, i.e., `byteStride1 < byteStride2 < byteStride3`. An application can pass ownership of shared data to OSPRay (for example, when it temporarily created a modified version of its data only to make it compatible with OSPRay) by providing a deleter function that OSPRay will call whenever the time comes to deallocate the shared buffer. The deleter function has the following signature: typedef void (*OSPDeleterCallback)(const void *userData, const void *sharedData); where `sharedData` will receive the address of the buffer and `userData` will receive whatever additional state the function needs to perform the deletion (both provided to `ospNewSharedData` when sharing the data with OSPRay). The enum type `OSPDataType` describes the different element types that can be represented in OSPRay; valid constants are listed in the table below. -------------------------- --------------------------------------------------- Type / Name Description -------------------------- --------------------------------------------------- OSP_DEVICE API device object reference OSP_DATA data reference OSP_OBJECT generic object reference OSP_CAMERA camera object reference OSP_FRAMEBUFFER framebuffer object reference OSP_LIGHT light object reference OSP_MATERIAL material object reference OSP_TEXTURE texture object reference OSP_RENDERER renderer object reference OSP_WORLD world object reference OSP_GEOMETRY geometry object reference OSP_VOLUME volume object reference OSP_TRANSFER_FUNCTION transfer function object reference OSP_IMAGE_OPERATION image operation object reference OSP_STRING C-style zero-terminated character string OSP_CHAR, OSP_VEC[234]C 8\ bit signed character scalar and [234]-element vector OSP_UCHAR, OSP_VEC[234]UC 8\ bit unsigned character scalar and [234]-element vector OSP_SHORT, OSP_VEC[234]S 16\ bit unsigned integer scalar and [234]-element vector OSP_USHORT, OSP_VEC[234]US 16\ bit unsigned integer scalar and [234]-element vector OSP_INT, OSP_VEC[234]I 32\ bit signed integer scalar and [234]-element vector OSP_UINT, OSP_VEC[234]UI 32\ bit unsigned integer scalar and [234]-element vector OSP_LONG, OSP_VEC[234]L 64\ bit signed integer scalar and [234]-element vector OSP_ULONG, OSP_VEC[234]UL 64\ bit unsigned integer scalar and [234]-element vector OSP_HALF, OSP_VEC[234]H 16\ bit half precision floating-point scalar and [234]-element vector (IEEE 754 `binary16`) OSP_FLOAT, OSP_VEC[234]F 32\ bit single precision floating-point scalar and [234]-element vector OSP_DOUBLE, OSP_VEC[234]D 64\ bit double precision floating-point scalar and [234]-element vector OSP_BOX[1234]I 32\ bit integer box (lower + upper bounds) OSP_BOX[1234]F 32\ bit single precision floating-point box (lower + upper bounds) OSP_LINEAR[23]F 32\ bit single precision floating-point linear transform ([23] vectors) OSP_AFFINE[23]F 32\ bit single precision floating-point affine transform (linear transform plus translation) OSP_QUATF 32\ bit single precision floating-point quaternion, in $(i, j, k, w)$ layout OSP_VOID_PTR raw memory address (only found in module extensions) -------------------------- --------------------------------------------------- : Valid named constants for `OSPDataType`. If the elements of the array are handles to objects, then their reference counter is incremented. An opaque `OSPData` with memory allocated by OSPRay is created with OSPData ospNewData(OSPDataType, uint64_t numItems1, uint64_t numItems2 = 1, uint64_t numItems3 = 1); To allow for (partial) copies or updates of data arrays use void ospCopyData(const OSPData source, OSPData destination, uint64_t destinationIndex1 = 0, uint64_t destinationIndex2 = 0, uint64_t destinationIndex3 = 0); which will copy the whole^[The number of items to be copied is defined by the size of the source array.] content of the `source` array into `destination` at the given location `destinationIndex`. The `OSPDataType`s of the data objects must match. The region to be copied must be valid inside the destination, i.e., in all dimensions, `destinationIndex + sourceSize <= destinationSize`. The affected region `[destinationIndex, destinationIndex + sourceSize)` is marked as dirty, which may be used by OSPRay to only process or update that sub-region (e.g., updating an acceleration structure). If the destination array is shared with OSPData by the application (created with `ospNewSharedData`), then - the source array must be shared as well (thus `ospCopyData` cannot be used to read opaque data) - if source and destination memory overlaps (aliasing), then behavior is undefined - except if source and destination regions are identical (including matching strides), which can be used by application to mark that region as dirty (instead of the whole `OSPData`) To add a data array as parameter named `id` to another object call also use void ospSetObject(OSPObject, const char *id, OSPData); Volumes ------- Volumes are volumetric data sets with discretely sampled values in 3D space, typically a 3D scalar field. To create a new volume object of given type `type` use OSPVolume ospNewVolume(const char *type); Note that OSPRay's implementation forwards `type` directly to Open VKL, allowing new Open VKL volume types to be usable within OSPRay without the need to change (or even recompile) OSPRay. ### Structured Regular Volume Structured volumes only need to store the values of the samples, because their addresses in memory can be easily computed from a 3D position. A common type of structured volumes are regular grids. Structured regular volumes are created by passing the type string "`structuredRegular`" to `ospNewVolume`. Structured volumes are represented through an `OSPData` 3D array `data` (which may or may not be shared with the application). The voxel data must be laid out in xyz-order^[For consecutive memory addresses the x-index of the corresponding voxel changes the quickest.] and can be compact (best for performance) or can have a stride between voxels, specified through the `byteStride1` parameter when creating the `OSPData`. Only 1D strides are supported, additional strides between scanlines (2D, `byteStride2`) and slices (3D, `byteStride3`) are not. The parameters understood by structured volumes are summarized in the table below. ------- -------------- ----------------------------- -------------------------- Type Name Default Description ------- -------------- ----------------------------- -------------------------- vec3f gridOrigin $(0, 0, 0)$ origin of the grid in object-space vec3f gridSpacing $(1, 1, 1)$ size of the grid cells in object-space OSPData data the actual voxel 3D [data] bool cellCentered false whether the data is provided per cell (as opposed to per vertex) uint filter `OSP_VOLUME_FILTER_LINEAR` filter used for reconstructing the field, also allowed is `OSP_VOLUME_FILTER_NEAREST` and `OSP_VOLUME_FILTER_CUBIC` uint gradientFilter same as `filter` filter used during gradient computations float background `NaN` value that is used when sampling an undefined region outside the volume domain ------- -------------- ----------------------------- -------------------------- : Configuration parameters for structured regular volumes. The size of the volume is inferred from the size of the 3D array `data`, as is the type of the voxel values (currently supported are: `OSP_UCHAR`, `OSP_SHORT`, `OSP_USHORT`, `OSP_HALF`, `OSP_FLOAT`, and `OSP_DOUBLE`). Data can be provided either per cell or per vertex (the default), selectable via the `cellCentered` parameter (which will also affect the computed bounding box). ### Structured Spherical Volume Structured spherical volumes are also supported, which are created by passing a type string of "`structuredSpherical`" to `ospNewVolume`. The grid dimensions and parameters are defined in terms of radial distance $r$, inclination angle $\theta$, and azimuthal angle $\phi$, conforming with the ISO convention for spherical coordinate systems. The coordinate system and parameters understood by structured spherical volumes are summarized below. ![Coordinate system of structured spherical volumes.][imgStructuredSphericalCoords] ------- -------------- ----------------------------- -------------------------- Type Name Default Description ------- -------------- ----------------------------- -------------------------- vec3f gridOrigin $(0, 0, 0)$ origin of the grid in units of $(r, \theta, \phi)$; angles in degrees vec3f gridSpacing $(1, 180/dim.y, 360/dim.z)$ size of the grid cells in units of $(r, \theta, \phi)$, per default covering the full sphere; angles in degrees OSPData data the actual voxel 3D [data] uint filter `OSP_VOLUME_FILTER_LINEAR` filter used for reconstructing the field, also allowed is `OSP_VOLUME_FILTER_NEAREST` uint gradientFilter same as `filter` filter used during gradient computations float background `NaN` value that is used when sampling an undefined region outside the volume domain ------- -------------- ----------------------------- -------------------------- : Configuration parameters for structured spherical volumes. The dimensions $(r, \theta, \phi)$ of the volume are inferred from the size of the 3D array `data`, as is the type of the voxel values (currently supported are: `OSP_UCHAR`, `OSP_SHORT`, `OSP_USHORT`, `OSP_HALF`, `OSP_FLOAT`, and `OSP_DOUBLE`). These grid parameters support flexible specification of spheres, hemispheres, spherical shells, spherical wedges, and so forth. The grid extents (computed as `[gridOrigin, gridOrigin + (dimensions - 1) * gridSpacing]`) however must be constrained such that: * $r \geq 0$ * $0 \leq \theta \leq 180$ * $0 \leq \phi \leq 360$ ### Adaptive Mesh Refinement (AMR) Volume OSPRay currently supports block-structured (Berger-Colella) AMR volumes. Volumes are specified as a list of blocks, which exist at levels of refinement in potentially overlapping regions. Blocks exist in a tree structure, with coarser refinement level blocks containing finer blocks. The cell width is equal for all blocks at the same refinement level, though blocks at a coarser level have a larger cell width than finer levels. There can be any number of refinement levels and any number of blocks at any level of refinement. An AMR volume type is created by passing the type string "`amr`" to `ospNewVolume`. Blocks are defined by three parameters: their bounds, the refinement level in which they reside, and the scalar data contained within each block. Note that cell widths are defined _per refinement level_, not per block. -------------- --------------- ----------------- ----------------------------------- Type Name Default Description -------------- --------------- ----------------- ----------------------------------- uint method `OSP_AMR_CURRENT` `OSPAMRMethod` sampling method. Supported methods are: `OSP_AMR_CURRENT` `OSP_AMR_FINEST` `OSP_AMR_OCTANT` float[] cellWidth NULL array of each level's cell width box3i[] block.bounds NULL [data] array of grid sizes (in voxels) for each AMR block int[] block.level NULL array of each block's refinement level OSPData[] block.data NULL [data] array of OSPData containing the actual scalar voxel data, only `OSP_FLOAT` is supported as `OSPDataType` vec3f gridOrigin $(0, 0, 0)$ origin of the grid vec3f gridSpacing $(1, 1, 1)$ size of the grid cells float background `NaN` value that is used when sampling an undefined region outside the volume domain -------------- --------------- ----------------- ----------------------------------- : Configuration parameters for AMR volumes. Lastly, note that the `gridOrigin` and `gridSpacing` parameters act just like the structured volume equivalent, but they only modify the root (coarsest level) of refinement. In particular, OSPRay's / Open VKL's AMR implementation was designed to cover Berger-Colella [1]\ and Chombo\ [2] AMR data. The `method` parameter above determines the interpolation method used when sampling the volume. OSP_AMR_CURRENT : finds the finest refinement level at that cell and interpolates through this "current" level OSP_AMR_FINEST : will interpolate at the closest existing cell in the volume-wide finest refinement level regardless of the sample cell's level OSP_AMR_OCTANT : interpolates through all available refinement levels at that cell. This method avoids discontinuities at refinement level boundaries at the cost of performance Details and more information can be found in the publication for the implementation\ [3]. 1. M.J. Berger and P. Colella, "Local adaptive mesh refinement for shock hydrodynamics." Journal of Computational Physics 82.1 (1989): 64-84. DOI: 10.1016/0021-9991(89)90035-1 2. M. Adams, P. Colella, D.T. Graves, J.N. Johnson, N.D. Keen, T.J. Ligocki, D.F. Martin. P.W. McCorquodale, D. Modiano. P.O. Schwartz, T.D. Sternberg, and B. Van Straalen, "Chombo Software Package for AMR Applications – Design Document", Lawrence Berkeley National Laboratory Technical Report LBNL-6616E. 3. I. Wald, C. Brownlee, W. Usher, and A. Knoll, "CPU volume rendering of adaptive mesh refinement data". SIGGRAPH Asia 2017 Symposium on Visualization – SA ’17, 18(8), 1–8. DOI: 10.1145/3139295.3139305 ### Unstructured Volume Unstructured volumes can have their topology and geometry freely defined. Geometry can be composed of tetrahedral, hexahedral, wedge or pyramid cell types. The data format used is compatible with VTK and consists of multiple arrays: vertex positions and values, vertex indices, cell start indices, cell types, and cell values. An unstructured volume type is created by passing the type string "`unstructured`" to `ospNewVolume`. Sampled cell values can be specified either per-vertex (`vertex.data`) or per-cell (`cell.data`). If both arrays are set, `cell.data` takes precedence. Similar to a mesh, each cell is formed by a group of indices into the vertices. For each vertex, the corresponding (by array index) data value will be used for sampling when rendering, if specified. The index order for a tetrahedron is the same as `VTK_TETRA`: bottom triangle counterclockwise, then the top vertex. For hexahedral cells, each hexahedron is formed by a group of eight indices into the vertices and data values. Vertex ordering is the same as `VTK_HEXAHEDRON`: four bottom vertices counterclockwise, then top four counterclockwise. For wedge cells, each wedge is formed by a group of six indices into the vertices and data values. Vertex ordering is the same as `VTK_WEDGE`: three bottom vertices counterclockwise, then top three counterclockwise. For pyramid cells, each cell is formed by a group of five indices into the vertices and data values. Vertex ordering is the same as `VTK_PYRAMID`: four bottom vertices counterclockwise, then the top vertex. To maintain VTK data compatibility, the `index` array may be specified with cell sizes interleaved with vertex indices in the following format: $n, id_1, ..., id_n, m, id_1, ..., id_m$. This alternative `index` array layout can be enabled through the `indexPrefixed` flag (in which case, the `cell.type` parameter must be omitted). ------------------- ------------------ -------- --------------------------------------- Type Name Default Description ------------------- ------------------ -------- --------------------------------------- vec3f[] vertex.position [data] array of vertex positions float[] vertex.data [data] array of vertex data values to be sampled uint32[] / uint64[] index [data] array of indices (into the vertex array(s)) that form cells bool indexPrefixed false indicates that the `index` array is compatible to VTK, where the indices of each cell are prefixed with the number of vertices uint32[] / uint64[] cell.index [data] array of locations (into the index array), specifying the first index of each cell float[] cell.data [data] array of cell data values to be sampled uint8[] cell.type [data] array of cell types (VTK compatible), only set if `indexPrefixed = false` false. Supported types are: `OSP_TETRAHEDRON` `OSP_HEXAHEDRON` `OSP_WEDGE` `OSP_PYRAMID` bool hexIterative false hexahedron interpolation method, defaults to fast non-iterative version which could have rendering inaccuracies may appear if hex is not parallelepiped bool precomputedNormals false whether to accelerate by precomputing, at a cost of 12 bytes/face float background `NaN` value that is used when sampling an undefined region outside the volume domain ------------------- ------------------ -------- --------------------------------------- : Configuration parameters for unstructured volumes. ### VDB Volume VDB volumes implement a data structure that is very similar to the data structure outlined in Museth\ [1], they are created by passing the type string "`vdb`" to `ospNewVolume`. The data structure is a hierarchical regular grid at its core: Nodes are regular grids, and each grid cell may either store a constant value (this is called a tile), or child pointers. Nodes in VDB trees are wide: Nodes on the first level have a resolution of 32^3^ voxels, on the next level 16^3^, and on the leaf level 8^3^ voxels. All nodes on a given level have the same resolution. This makes it easy to find the node containing a coordinate using shift operations (see\ [1]). VDB leaf nodes are implicit in OSPRay / Open VKL: they are stored as pointers to user-provided data. ![Topology of VDB volumes.][imgVdbStructure] VDB volumes interpret input data as constant cells (which are then potentially filtered). This is in contrast to `structuredRegular` volumes, which have a vertex-centered interpretation. The VDB implementation in OSPRay / Open VKL follows the following goals: - Efficient data structure traversal on vector architectures. - Enable the use of industry-standard `.vdb` files created through the OpenVDB library. - Compatibility with OpenVDB on a leaf data level, so that `.vdb` file may be loaded with minimal overhead. VDB volumes have the following parameters: ---------- ----------------- ------------------------------------------------- Type Name Description ---------- ----------------- ------------------------------------------------- int maxSamplingDepth do not descend further than to this depth during sampling, the maximum value and the default is 3 uint32[] node.level level on which each input node exists, may be 1, 2 or 3 (levels are counted from the root level = 0 down) vec3i[] node.origin the node origin index (per input node) OSPData[] node.data [data] arrays with the node data (per input node). Nodes that are tiles are expected to have single-item arrays. Leaf-nodes with grid data expected to have compact 3D arrays in zyx layout (z changes most quickly) with the correct number of voxels for the `level`. Only `OSP_FLOAT` is supported as field `OSPDataType`. OSPData nodesPackedDense optionally provided instead of `node.data`, a single array of all dense node data in a contiguous zyx layout, provided in the same order as the corresponding `node.*` parameters OSPData nodesPackedTile optionally provided instead of `node.data`, a single array of all tile node data in a contiguous layout, provided in the same order as the corresponding `node.*` parameters uint32[] node.format for each input node, whether it is of format `OSP_VOLUME_FORMAT_DENSE_ZYX` (and thus stored in `nodesPackedDense`), or `OSP_VOLUME_FORMAT_TILE` (stored in `nodesPackedTile`) uint filter filter used for reconstructing the field, default is `OSP_VOLUME_FILTER_LINEAR`, alternatively `OSP_VOLUME_FILTER_NEAREST`, or `OSP_VOLUME_FILTER_CUBIC`. uint gradientFilter filter used for reconstructing the field during gradient computations, default same as `filter` float background value that is used when sampling an undefined region outside the volume domain, default `NaN` ---------- ----------------- ------------------------------------------------- : Configuration parameters for VDB volumes. The `nodesPackedDense` and `nodesPackedTile` together with `node.format` parameters may be provided instead of `node.data`; this packed data layout may provide better performance. 1. Museth, K. VDB: High-Resolution Sparse Volumes with Dynamic Topology. ACM Transactions on Graphics 32(3), 2013. DOI: 10.1145/2487228.2487235 ### Particle Volume Particle volumes consist of a set of points in space. Each point has a position, a radius, and a weight typically associated with an attribute. Particle volumes are created by passing the type string "`particle`" to `ospNewVolume`. A radial basis function defines the contribution of that particle. Currently, we use the Gaussian radial basis function $$\phi(P) = w \exp\left(-\frac{(P - p)^2}{2 r^2}\right),$$ where $P$ is the particle position, $p$ is the sample position, $r$ is the radius and $w$ is the weight. At each sample, the scalar field value is then computed as the sum of each radial basis function $\phi$, for each particle that overlaps it. The OSPRay / Open VKL implementation is similar to direct evaluation of samples in Reda et al.\ [2]. It uses an Embree-built BVH with a custom traversal, similar to the method in\ [1]. -------- ----------------------- -------- --------------------------------------- Type Name Default Description -------- ----------------------- -------- --------------------------------------- vec3f[] particle.position [data] array of particle positions float[] particle.radius [data] array of particle radii float[] particle.weight NULL optional [data] array of particle weights, specifying the height of the kernel. float radiusSupportFactor 3.0 The multiplier of the particle radius required for support. Larger radii ensure smooth results at the cost of performance. In the Gaussian kernel, the radius is one standard deviation ($\sigma$), so a value of 3 corresponds to $3 \sigma$. float clampMaxCumulativeValue 0 The maximum cumulative value possible, set by user. All cumulative values will be clamped to this, and further traversal (RBF summation) of particle contributions will halt when this value is reached. A value of zero or less turns this off. bool estimateValueRanges true Enable heuristic estimation of value ranges which are used in internal acceleration structures as well as for determining the volume's overall value range. When set to `false`, the user *must* specify `clampMaxCumulativeValue`, and all value ranges will be assumed [0–`clampMaxCumulativeValue`]. Disabling this switch may improve volume commit time, but will make volume rendering less efficient. -------- ----------------------- -------- --------------------------------------- : Configuration parameters for particle volumes. 1. A. Knoll, I. Wald, P. Navratil, A. Bowen, K. Reda, M.E., Papka, and K. Gaither, "RBF Volume Ray Casting on Multicore and Manycore CPUs", 2014, Computer Graphics Forum, 33: 71–80. doi:10.1111/cgf.12363 2. K. Reda, A. Knoll, K. Nomura, M. E. Papka, A. E. Johnson and J. Leigh, "Visualizing large-scale atomistic simulations in ultra-resolution immersive environments", 2013 IEEE Symposium on Large-Scale Data Analysis and Visualization (LDAV), Atlanta, GA, 2013, pp. 59–65. ### Transfer Function Transfer functions map the scalar values of volumes to color and opacity and thus they can be used to visually emphasize certain features of the volume. To create a new transfer function of given type `type` use OSPTransferFunction ospNewTransferFunction(const char *type); The returned handle can be assigned to a volumetric model (described below) as parameter "`transferFunction`" using `ospSetObject`. One type of transfer function that is supported by OSPRay is the linear transfer function, which interpolates between given equidistant colors and opacities. It is create by passing the string "`piecewiseLinear`" to `ospNewTransferFunction` and it is controlled by these parameters: Type Name Description ------------ ----------- ---------------------------------------------- vec3f[] color [data] array of colors (linear RGB) float[] opacity [data] array of opacities box1f value domain (scalar range) this function maps from ------------ ----------- ---------------------------------------------- : Parameters accepted by the linear transfer function. The arrays `color` and `opacity` can be of different length. ### VolumetricModels Volumes in OSPRay are given volume rendering appearance information through VolumetricModels. This decouples the physical representation of the volume (and possible acceleration structures it contains) to rendering-specific parameters (where more than one set may exist concurrently). To create a volume instance, call OSPVolumetricModel ospNewVolumetricModel(OSPVolume); The passed volume can be `NULL` as long as the volume to be used is passed as a parameter. If both a volume is specified on object creation and as a parameter, the parameter value is used. If the parameter value is later removed, the volume object passed on object creation is again used. -------------------- ----------------- -------- -------------------------------------- Type Name Default Description -------------------- ----------------- -------- -------------------------------------- OSPVolume volume optional [volume] object this model references OSPTransferFunction transferFunction [transfer function] to use float densityScale 1.0 makes volumes uniformly thinner or thicker float anisotropy 0.0 anisotropy of the (Henyey-Greenstein) phase function in [-1–1] ([path tracer] only), default to isotropic scattering uint32 id -1u optional user ID, for [framebuffer] channel `OSP_FB_ID_OBJECT` -------------------- ----------------- -------- --------------------------------------- : Parameters understood by VolumetricModel. Geometries ---------- Geometries in OSPRay are objects that describe intersectable surfaces. To create a new geometry object of given type `type` use OSPGeometry ospNewGeometry(const char *type); Note that in the current implementation geometries are limited to a maximum of 2^32^ primitives. ### Mesh A mesh consisting of either triangles or quads is created by calling `ospNewGeometry` with type string "`mesh`". Once created, a mesh recognizes the following parameters: Type Name Description -------------------- ----------------------- ------------------------------------------------- vec3f[] vertex.position [data] array of vertex positions, overridden by `motion.*` arrays vec3f[] normal [data] array of face-varying normals, overridden by `motion.*` arrays vec3f[] vertex.normal [data] array of vertex-varying normals, overridden by `motion.*` arrays vec4f[] / vec3f[] color [data] array of face-varying colors (linear RGBA/RGB) vec4f[] / vec3f[] vertex.color [data] array of vertex-varying colors (linear RGBA/RGB) vec2f[] texcoord [data] array of face-varying texture coordinates vec2f[] vertex.texcoord [data] array of vertex-varying texture coordinates vec3ui[] / vec4ui[] index [data] array of (either triangle or quad) indices (into the vertex array(s)) bool quadSoup when no explicit `index` is given, indicates whether to assume a 'soup' of quads instead of triangles, default false vec3f[][] motion.vertex.position [data] array of vertex position arrays (uniformly distributed keys for deformation motion blur) vec3f[][] motion.normal [data] array of face-varying normal arrays (uniformly distributed keys for deformation motion blur) vec3f[][] motion.vertex.normal [data] array of vertex-varying normal arrays (uniformly distributed keys for deformation motion blur) box1f time time associated with first and last key in `motion.*` arrays (for deformation motion blur), default [0, 1] -------------------- ----------------------- ------------------------------------------------- : Parameters defining a mesh geometry. The data type of index arrays differentiates between the underlying geometry, triangles are used for a index with `vec3ui` type and quads for `vec4ui` type. Quads are internally handled as a pair of two triangles, thus mixing triangles and quads is supported by encoding some triangle as a quad with the last two vertex indices being identical (`w=z`). The `vertex.position` array is mandatory to create a valid mesh. The `index` array is optional. If none is provided, a 'triangle soup' is assumed, i.e., each three consecutive vertices form one triangle; unless the boolean `quadSoup` is set to true, then a 'quad soup' is assumed i.e., each four subsequent vertices form one quad. If the size of the `vertex.position` array is not a multiple of three for triangles or four for quads, the remainder vertices are ignored. ### Subdivision A mesh consisting of subdivision surfaces, created by specifying a geometry of type "`subdivision`". Once created, a subdivision recognizes the following parameters: ------- ------------------- -------------------------------------------------- Type Name Description ------- ------------------- -------------------------------------------------- vec3f[] vertex.position [data] array of vertex positions vec4f[] color optional [data] array of face-varying colors (linear RGBA) vec4f[] vertex.color optional [data] array of vertex-varying colors (linear RGBA) vec2f[] texcoord optional [data] array of vertex-varying texture coordinates vec2f[] vertex.texcoord optional [data] array of vertex-varying texture coordinates float level global level of tessellation, default 5 uint[] index [data] array of indices (into the vertex array(s)) float[] index.level optional [data] array of per-edge levels of tessellation, overrides global level uint[] face optional [data] array holding the number of indices/edges (3 to 15) per face, defaults to 4 (a pure quad mesh) vec2i[] edgeCrease.index optional [data] array of edge crease indices float[] edgeCrease.weight optional [data] array of edge crease weights uint[] vertexCrease.index optional [data] array of vertex crease indices float[] vertexCrease.weight optional [data] array of vertex crease weights uint mode `OSPSubdivisionMode` subdivision edge boundary mode, supported modes are: `OSP_SUBDIVISION_NO_BOUNDARY` `OSP_SUBDIVISION_SMOOTH_BOUNDARY` (default) `OSP_SUBDIVISION_PIN_CORNERS` `OSP_SUBDIVISION_PIN_BOUNDARY` `OSP_SUBDIVISION_PIN_ALL` ------- ------------------- -------------------------------------------------- : Parameters defining a Subdivision geometry. The `vertex` and `index` arrays are mandatory to create a valid subdivision surface. If no `face` array is present then a pure quad mesh is assumed (the number of indices must be a multiple of 4). Optionally supported are edge and vertex creases. ### Spheres A geometry consisting of individual spheres, each of which can have an own radius, is created by calling `ospNewGeometry` with type string "`sphere`". The spheres will not be tessellated but rendered procedurally and are thus perfectly round. To allow a variety of sphere representations in the application this geometry allows a flexible way of specifying the data of center position and radius within a [data] array: -------- ---------------- -------- --------------------------------------- Type Name Default Description -------- ---------------- -------- --------------------------------------- vec3f[] sphere.position [data] array of center positions float[] sphere.radius NULL optional [data] array of the per-sphere radius vec3f[] sphere.normal NULL optional [data](#data) array of normals (only for “oriented discâ€) vec2f[] sphere.texcoord NULL optional [data] array of texture coordinates (constant per sphere) float radius 0.01 default radius for all spheres (if `sphere.radius` is not set) uint type `OSPSphereType` for rendering the sphere. Supported types are: `OSP_SPHERE` (default) `OSP_DISC` `OSP_ORIENTED_DISC` -------- ---------------- -------- --------------------------------------- : Parameters defining a spheres geometry. ### Curves A geometry consisting of multiple curves is created by calling `ospNewGeometry` with type string "`curve`". The parameters defining this geometry are listed in the table below. ------------------ ---------------------- ------------------------------------------- Type Name Description ------------------ ---------------------- ------------------------------------------- vec4f[] vertex.position_radius [data] array of vertex position and per-vertex radius vec2f[] vertex.texcoord [data] array of per-vertex texture coordinates vec4f[] vertex.color [data] array of corresponding vertex colors (linear RGBA) vec3f[] vertex.normal [data] array of curve normals (only for "ribbon" curves) vec4f[] vertex.tangent [data] array of curve tangents (only for "hermite" curves) uint32[] index [data] array of indices to the first vertex or tangent of a curve segment uint type `OSPCurveType` for rendering the curve. Supported types are: `OSP_FLAT` `OSP_ROUND` `OSP_RIBBON` `OSP_DISJOINT` uint basis `OSPCurveBasis` for defining the curve. Supported bases are: `OSP_LINEAR` `OSP_BEZIER` `OSP_BSPLINE` `OSP_HERMITE` `OSP_CATMULL_ROM` ------------------ ---------------------- ------------------------------------------- : Parameters defining a curves geometry. Positions in `vertex.position_radius` parameter supports per-vertex varying radii with data type `vec4f[]` and instantiate Embree curves internally for the relevant type/basis mapping. The following section describes the properties of different curve basis' and how they use the data provided in data buffers: OSP_LINEAR : The indices point to the first of 2 consecutive control points in the vertex buffer. The first control point is the start and the second control point the end of the line segment. The curve goes through all control points listed in the vertex buffer. OSP_BEZIER : The indices point to the first of 4 consecutive control points in the vertex buffer. The first control point represents the start point of the curve, and the 4th control point the end point of the curve. The Bézier basis is interpolating, thus the curve does go exactly through the first and fourth control vertex. OSP_BSPLINE : The indices point to the first of 4 consecutive control points in the vertex buffer. This basis is not interpolating, thus the curve does in general not go through any of the control points directly. Using this basis, 3 control points can be shared for two continuous neighboring curve segments, e.g., the curves $(p0, p1, p2, p3)$ and $(p1, p2, p3, p4)$ are C1 continuous. This feature make this basis a good choice to construct continuous multi-segment curves, as memory consumption can be kept minimal. OSP_HERMITE : It is necessary to have both vertex buffer and tangent buffer for using this basis. The indices point to the first of 2 consecutive points in the vertex buffer, and the first of 2 consecutive tangents in the tangent buffer. This basis is interpolating, thus does exactly go through the first and second control point, and the first order derivative at the begin and end matches exactly the value specified in the tangent buffer. When connecting two segments continuously, the end point and tangent of the previous segment can be shared. OSP_CATMULL_ROM : The indices point to the first of 4 consecutive control points in the vertex buffer. If $(p0, p1, p2, p3)$ represent the points then this basis goes through $p1$ and $p2$, with tangents as $(p2-p0)/2$ and $(p3-p1)/2$. The following section describes the properties of different curve types' and how they define the geometry of a curve: OSP_FLAT : This type enables faster rendering as the curve is rendered as a connected sequence of ray facing quads. OSP_ROUND : This type enables rendering a real geometric surface for the curve which allows closeup views. This mode renders a sweep surface by sweeping a varying radius circle tangential along the curve. OSP_RIBBON : The type enables normal orientation of the curve and requires a normal buffer be specified along with vertex buffer. The curve is rendered as a flat band whose center approximately follows the provided vertex buffer and whose normal orientation approximately follows the provided normal buffer. Not supported for basis `OSP_LINEAR`. OSP_DISJOINT : Only supported for basis `OSP_LINEAR`; the segments are open and not connected at the joints, i.e., the curve segments are either individual cones or cylinders. ### Boxes OSPRay can directly render axis-aligned bounding boxes without the need to convert them to quads or triangles. To do so create a boxes geometry by calling `ospNewGeometry` with type string "`box`". Type Name Description ---------- ---------- ------------------------------------------------------ box3f[] box [data] array of boxes ---------- ---------- ------------------------------------------------------ : Parameters defining a boxes geometry. ### Planes OSPRay can directly render planes defined by plane equation coefficients in its implicit form $ax + by + cz + d = 0$. By default planes are infinite but their extents can be limited by defining optional bounding boxes. A planes geometry can be created by calling `ospNewGeometry` with type string "`plane`". Type Name Description ---------- ------------------ ------------------------------------------------- vec4f[] plane.coefficients [data] array of plane coefficients $(a, b, c, d)$ box3f[] plane.bounds optional [data] array of bounding boxes ---------- ------------------ ------------------------------------------------- : Parameters defining a planes geometry. ### Isosurfaces OSPRay can directly render multiple isosurfaces of a volume without first tessellating them. To do so create an isosurfaces geometry by calling `ospNewGeometry` with type string "`isosurface`". The appearance information of the surfaces is set through the Geometric Model. Per-isosurface colors can be set by passing per-primitive colors to the Geometric Model, in order of the isosurface array. Type Name Description ------------------ --------- -------------------------------------------------- float isovalue single isovalues float[] isovalue [data] array of isovalues OSPVolume volume handle of the [Volume] to be isosurfaced ------------------ --------- -------------------------------------------------- : Parameters defining an isosurfaces geometry. ### GeometricModels Geometries are matched with surface appearance information through GeometricModels. These take a geometry, which defines the surface representation, and applies either full-object or per-primitive color and material information. To create a geometric model, call OSPGeometricModel ospNewGeometricModel(OSPGeometry); The passed geometry can be `NULL` as long as the geometry to be used is passed as a parameter. If both a geometry is specified on object creation and as a parameter, the parameter value is used. If the parameter value is later removed, the geometry object passed on object creation is again used. Color and material are fetched with the primitive ID of the hit (clamped to the valid range, thus a single color or material is fine), or mapped first via the `index` array (if present). All parameters are optional, however, some renderers (notably the [path tracer]) require a material to be set. Materials are either handles of `OSPMaterial`, or indices into the `material` array on the [renderer], which allows to build a [world] which can be used by different types of renderers. An `invertNormals` flag allows to invert (shading) normal vectors of the rendered geometry. That is particularly useful for clipping. By changing normal vectors orientation one can control whether inside or outside of the clipping geometry is being removed. For example, a clipping geometry with normals oriented outside clips everything what's inside. ----------------------------------------------- ------------- ---------------------------------------------------- Type Name Description ----------------------------------------------- ------------- ---------------------------------------------------- OSPGeometry geometry optional [geometry] object this model references OSPMaterial / OSPMaterial[] / uint32 / uint32[] material optional ([data] array of per-primitive) [material], may be an index into the `material` parameter on the renderer (if it exists) vec4f / vec4f[] color optional ([data] array of per-primitive) color assigned to the geometry (linear RGBA) uint8[] index optional [data] array of per-primitive indices into `color` and `material` bool invertNormals inverts all shading normals (Ns), default false uint32 id optional user ID, for [framebuffer] channel `OSP_FB_ID_OBJECT`, default -1u ----------------------------------------------- ------------- ---------------------------------------------------- : Parameters understood by GeometricModel. Lights ------ To create a new light source of given type `type` use OSPLight ospNewLight(const char *type); All light sources accept the following parameters: --------- ------------------ -------- -------------------------------------------- Type Name Default Description --------- ------------------ -------- -------------------------------------------- vec3f color white color of the light (linear RGB) float intensity 1 intensity of the light (a factor) uint intensityQuantity `OSPIntensityQuantity` to set the radiometric quantity represented by `intensity`. The default value depends on the light source. bool visible true whether the light can be directly seen --------- ------------------ -------- -------------------------------------------- : Parameters accepted by all lights. In OSPRay the `intensity` parameter of a light source can correspond to different types of radiometric quantities. The type of the value represented by a light's `intensity` parameter is set using `intensityQuantity`, which accepts values from the enum type `OSPIntensityQuantity`. The supported types of `OSPIntensityQuantity` differ between the different light sources (see documentation of each specific light source). ---------------------------------- ---------------------------------------------------- Name Description ---------------------------------- ---------------------------------------------------- OSP_INTENSITY_QUANTITY_POWER the overall amount of light energy emitted by the light source into the scene, unit is W OSP_INTENSITY_QUANTITY_INTENSITY the overall amount of light emitted by the light in a given direction, unit is W/sr OSP_INTENSITY_QUANTITY_RADIANCE the amount of light emitted by a point on the light source in a given direction, unit is W/sr/m^2^ OSP_INTENSITY_QUANTITY_IRRADIANCE the amount of light arriving at a surface point, assuming the light is oriented towards to the surface, unit is W/m^2^ OSP_INTENSITY_QUANTITY_SCALE a linear scaling factor for light sources with a built-in quantity (e.g., `HDRI`, or `sunSky`, or when using `intensityDistribution`). ---------------------------------- ---------------------------------------------------- : Types of radiometric quantities used to interpret a light's `intensity` parameter. ### Photometric Lights Measured light sources (IES, EULUMDAT, ...) are supported by the `sphere`, `spot`, and `quad` lights when setting an `intensityDistribution` [data] array to modulate the intensity per direction. The mapping is using the C-γ coordinate system (see also below figure): the values of the first (or only) dimension of `intensityDistribution` are uniformly mapped to γ in [0–π]; the first intensity value to 0, the last value to Ï€, thus at least two values need to be present. ![C-γ coordinate system for the mapping of `intensityDistribution` with photometric lights.][imgCGammaCoords] If the array has a second dimension then the intensities are not rotational symmetric around the main direction (where angle γ is zero), but are accordingly mapped to the C-halfplanes in [0–2Ï€]; the first "row" of values to 0 and 2Ï€, the other rows such that they have uniform distance to its neighbors. The orientation of the C0-plane is specified via `c0`. ---------- --------------------- --------------------------------------------- Type Name Description ---------- --------------------- --------------------------------------------- float[] intensityDistribution luminous intensity distribution for photometric lights; can be 2D for asymmetric illumination; values are assumed to be uniformly distributed vec3f c0 orientation, i.e., direction of the C0-(half)plane (only needed if illumination via `intensityDistribution` is asymmetric) ---------- --------------------- --------------------------------------------- : Special parameters for photometric lights. When using an `intensityDistribution` then the default and only valid value for `intensityQuantity` is `OSP_INTENSITY_QUANTITY_SCALE`. The following light types are supported by most OSPRay renderers. ### Directional Light / Distant Light The distant light (or traditionally the directional light) is thought to be far away (outside of the scene), thus its light arrives (almost) as parallel rays. It is created by passing the type string "`distant`" to `ospNewLight`. The distant light supports `OSP_INTENSITY_QUANTITY_RADIANCE` and `OSP_INTENSITY_QUANTITY_IRRADIANCE` (default) as `intensityQuantity` parameter value. In addition to the [general parameters](#lights) understood by all lights the distant light supports the following special parameters: Type Name Default Description --------- ---------------- ------------ --------------------------------------------- vec3f direction $(0, 0, 1)$ main emission direction of the distant light float angularDiameter 0 apparent size (angle in degree) of the light --------- ---------------- ------------ --------------------------------------------- : Special parameters accepted by the distant light. Setting the angular diameter to a value greater than zero will result in soft shadows when the renderer uses stochastic sampling (like the [path tracer]). For instance, the apparent size of the sun is about 0.53°. ### Point Light / Sphere Light The sphere light (or the special case point light) is a light emitting uniformly in all directions from the surface toward the outside. It does not emit any light toward the inside of the sphere. It is created by passing the type string "`sphere`" to `ospNewLight`. The point light supports only `OSP_INTENSITY_QUANTITY_SCALE` when `intensityDistribution` is set, or otherwise `OSP_INTENSITY_QUANTITY_POWER`, `OSP_INTENSITY_QUANTITY_INTENSITY` (then default) and `OSP_INTENSITY_QUANTITY_RADIANCE` as `intensityQuantity` parameter value. In addition to the [general parameters](#lights) understood by all lights and the [photometric parameters](#photometric-lights) the sphere light supports the following special parameters: Type Name Default Description ------- ---------- ------------ -------------------------------- vec3f position $(0, 0, 0)$ the center of the sphere light float radius 0 the size of the sphere light vec3f direction $(0, 0, 1)$ main orientation of `intensityDistribution` ------- ---------- ------------ -------------------------------- : Special parameters accepted by the sphere light. Setting the radius to a value greater than zero will result in soft shadows when the renderer uses stochastic sampling (like the [path tracer]). ### Spotlight / Ring Light The spotlight is a light emitting into a cone of directions. It is created by passing the type string "`spot`" to `ospNewLight`. The spotlight supports only `OSP_INTENSITY_QUANTITY_SCALE` when `intensityDistribution` is set, or otherwise `OSP_INTENSITY_QUANTITY_POWER`, `OSP_INTENSITY_QUANTITY_INTENSITY` (then default) and `OSP_INTENSITY_QUANTITY_RADIANCE` as `intensityQuantity` parameter value. In addition to the [general parameters](#lights) understood by all lights and the [photometric parameters](#photometric-lights) the spotlight supports the special parameters listed in the table. ---------- --------------------- ----------- --------------------------------- Type Name Default Description ---------- --------------------- ----------- --------------------------------- vec3f position $(0, 0, 0)$ the center of the spotlight vec3f direction $(0, 0, 1)$ main emission direction of the spot float openingAngle 180 full opening angle (in degree) of the spot; outside of this cone is no illumination float penumbraAngle 5 size (angle in degree) of the "penumbra", the region between the rim (of the illumination cone) and full intensity of the spot; should be smaller than half of `openingAngle` float radius 0 the size of the spotlight, the radius of a disk with normal `direction` float innerRadius 0 in combination with `radius` turns the disk into a ring ---------- --------------------- ----------- --------------------------------- : Special parameters accepted by the spotlight. ![Angles used by the spotlight.][imgSpotLight] Setting the radius to a value greater than zero will result in soft shadows when the renderer uses stochastic sampling (like the [path tracer]). Additionally setting the inner radius will result in a ring instead of a disk emitting the light. ### Quad Light The quad^[actually a parallelogram] light is a planar, procedural area light source emitting uniformly on one side into the half-space. It is created by passing the type string "`quad`" to `ospNewLight`. The quad light supports only `OSP_INTENSITY_QUANTITY_SCALE` when `intensityDistribution` is set, or otherwise `OSP_INTENSITY_QUANTITY_POWER`, `OSP_INTENSITY_QUANTITY_INTENSITY` and `OSP_INTENSITY_QUANTITY_RADIANCE` (then default) as `intensityQuantity` parameter. In addition to the [general parameters](#lights) understood by all lights and the [photometric parameters](#photometric-lights) the quad light supports the following special parameters: Type Name Default Description ------ --------- ------------ ----------------------------------------- vec3f position $(0, 0, 0)$ position of one vertex of the quad light vec3f edge1 $(1, 0, 0)$ vector to one adjacent vertex vec3f edge2 $(0, 1, 0)$ vector to the other adjacent vertex ------ --------- ------------ ----------------------------------------- : Special parameters accepted by the quad light. ![Defining a quad light which emits toward the reader.][imgQuadLight] The emission side is determined by the cross product of `edge1`×`edge2`. which is also the main emission direction for `intensityDistribution`. Note that only renderers that use stochastic sampling (like the path tracer) will compute soft shadows from the quad light. Other renderers will just sample the center of the quad light, which results in hard shadows. ### Cylinder Light The cylinder light is a cylinderical, procedural area light source emitting uniformly outwardly into the space beyond the boundary. It is created by passing the type string "`cylinder`" to `ospNewLight`. The cylinder light supports `OSP_INTENSITY_QUANTITY_POWER`, `OSP_INTENSITY_QUANTITY_INTENSITY` and `OSP_INTENSITY_QUANTITY_RADIANCE` (default) as `intensityQuantity` parameter. In addition to the [general parameters](#lights) understood by all lights the cylinder light supports the following special parameters: Type Name Default Description ------- ----------- ------------ -------------------------------------- vec3f position0 $(0, 0, 0)$ position of the start of the cylinder vec3f position1 $(0, 0, 1)$ position of the end of the cylinder float radius 1 radius of the cylinder ------- ----------- ------------ -------------------------------------- : Special parameters accepted by the cylinder light. Note that only renderers that use stochastic sampling (like the path tracer) will compute soft shadows from the cylinder light. Other renderers will just sample the closest point on the cylinder light, which results in hard shadows. ### HDRI Light The HDRI light is a textured light source surrounding the scene and illuminating it from infinity. It is created by passing the type string "`hdri`" to `ospNewLight`. The values of the HDRI correspond to radiance and therefore the HDRI light only accepts `OSP_INTENSITY_QUANTITY_SCALE` as `intensityQuantity` parameter value. In addition to the [general parameters](#lights) the HDRI light supports the following special parameters: ------------ --------- ------------ -------------------------------------------------- Type Name Default Description ------------ --------- ------------ -------------------------------------------------- vec3f up $(0, 1, 0)$ up direction of the light vec3f direction $(0, 0, 1)$ direction to which the center of the texture will be mapped to (analog to [panoramic camera]) OSPTexture map environment map in latitude / longitude format ------------ --------- ------------ -------------------------------------------------- : Special parameters accepted by the HDRI light. ![Orientation and Mapping of an HDRI Light.][imgHDRILight] Note that the [SciVis renderer] only shows the HDRI light in the background (like an environment map) without computing illumination of the scene. ### Ambient Light The ambient light surrounds the scene and illuminates it from infinity with constant radiance (determined by combining the [parameters `color` and `intensity`](#lights)). It is created by passing the type string "`ambient`" to `ospNewLight`. The ambient light supports `OSP_INTENSITY_QUANTITY_RADIANCE` and `OSP_INTENSITY_QUANTITY_IRRADIANCE` (default) as `intensityQuantity` parameter value. Note that the [SciVis renderer] uses ambient lights to control the color and intensity of the computed ambient occlusion (AO). ### Sun-Sky Light The sun-sky light is a combination of a `distant` light for the sun and a procedural `hdri` light for the sky. It is created by passing the type string "`sunSky`" to `ospNewLight`. The sun-sky light surrounds the scene and illuminates it from infinity and can be used for rendering outdoor scenes. The radiance values are calculated using the HoÅ¡ek-Wilkie sky model and solar radiance function. The underlying model of the sun-sky light returns radiance values and therefore the light only accepts `OSP_INTENSITY_QUANTITY_SCALE` as `intensityQuantity` parameter value. To rescale the returned radiance of the sky model the default value for the `intensity` parameter is set to `0.025`. In addition to the [general parameters](#lights) the following special parameters are supported: --------- ---------------- ------------ ------------------------------------- Type Name Default Description --------- ---------------- ------------ ------------------------------------- vec3f up $(0, 1, 0)$ zenith of sky vec3f direction $(0, -1, 0)$ main emission direction of the sun float turbidity 3 atmospheric turbidity due to particles, in [1–10] float albedo 0.3 ground reflectance, in [0–1] float horizonExtension 0.01 extend the sky dome by stretching the horizon, fraction of the lower hemisphere to cover, in [0–1] --------- ---------------- ------------ ------------------------------------- : Special parameters accepted by the `sunSky` light. The lowest elevation for the sun is restricted to the horizon. Note that the [SciVis renderer] only computes illumination from the sun (yet the sky is still shown in the background, like an environment map). ### Emissive Objects The [path tracer] will consider illumination by [geometries] which have a light emitting material assigned (for example the [Luminous] or [Principled] material). Materials --------- Materials describe how light interacts with surfaces, they give objects their distinctive look. To create a new material of given type `type` call OSPMaterial ospNewMaterial(const char *material_type); The returned handle can then be used to assign the material to a given geometry with void ospSetObject(OSPGeometricModel, "material", OSPMaterial); ### OBJ Material The OBJ material is the workhorse material supported by both the [SciVis renderer] and the [path tracer] (the [Ambient Occlusion renderer] only uses the `kd` and `d` parameter). It offers widely used common properties like diffuse and specular reflection and is based on the [MTL material format](http://paulbourke.net/dataformats/mtl/) of Lightwave's OBJ scene files. To create an OBJ material pass the type string "`obj`" to `ospNewMaterial`. Its main parameters are Type Name Default Description ------------- --------- ---------- ----------------------------------------- vec3f kd white 0.8 diffuse color (linear RGB) vec3f ks black specular color (linear RGB) float ns 10 shininess (Phong exponent), usually in \[2–10^4^\] float d opaque opacity vec3f tf black transparency filter color (linear RGB) OSPTexture map_bump NULL normal map ------------- --------- ---------- ----------------------------------------- : Main parameters of the OBJ material. In particular when using the path tracer it is important to adhere to the principle of energy conservation, i.e., that the amount of light reflected by a surface is not larger than the light arriving. Therefore the path tracer issues a warning and renormalizes the color parameters if the sum of `kd`, `ks`, and `tf` is larger than one in any color channel. Similarly important to mention is that almost all materials of the real world reflect at most only about 80% of the incoming light. So even for a white sheet of paper or white wall paint do better not set `kd` larger than 0.8; otherwise rendering times are unnecessary long and the contrast in the final images is low (for example, the corners of a white room would hardly be discernible, as can be seen in the figure below). ![Comparison of diffuse rooms with 100% reflecting white paint (left) and realistic 80% reflecting white paint (right), which leads to higher overall contrast. Note that exposure has been adjusted to achieve similar brightness levels.][imgDiffuseRooms] If present, the color component of [geometries] is also used for the diffuse color `kd` and the alpha component is also used for the opacity `d`. Normal mapping can simulate small geometric features via the texture `map_bump`. The normals $n$ in the normal map are with respect to the local tangential shading coordinate system and are encoded as $½(n+1)$, thus a texel $(0.5, 0.5, 1)$^[respectively $(127, 127, 255)$ for 8\ bit textures and $(32767, 32767, 65535)$ for 16\ bit textures] represents the unperturbed shading normal $(0, 0, 1)$. Because of this encoding an sRGB gamma [texture] format is ignored and normals are always fetched as linear from a normal map. Note that the orientation of normal maps is important for a visually consistent look: by convention OSPRay uses a coordinate system with the origin in the lower left corner; thus a convexity will look green toward the top of the texture image (see also the example image of a normal map). If this is not the case flip the normal map vertically or invert its green channel. ![Normal map representing an exalted square pyramidal frustum.][imgNormalMap] Note that `tf` colored transparency is implemented in the SciVis and the path tracer but normal mapping with `map_bump` is currently supported in the path tracer only. All parameters (except `tf`) can be textured by passing a [texture] handle, prefixed with "`map_`". The fetched texels are multiplied by the respective parameter value. If only the texture is given (but not the corresponding parameter), only the texture is used (the default value of the parameter is *not* multiplied). The color textures `map_kd` and `map_ks` are typically in one of the sRGB gamma encoded formats, whereas textures `map_ns` and `map_d` are usually in a linear format (and only the first component is used). Additionally, all textures support [texture transformations]. ![Rendering of a OBJ material with wood textures.][imgMaterialOBJ] ### Principled The Principled material is the most complex material offered by the [path tracer], which is capable of producing a wide variety of materials (e.g., plastic, metal, wood, glass) by combining multiple different layers and lobes. It uses the GGX microfacet distribution with approximate multiple scattering for dielectrics and metals, uses the Oren-Nayar model for diffuse reflection, and is energy conserving. To create a Principled material, pass the type string "`principled`" to `ospNewMaterial`. Its parameters are listed in the table below. ------ ----------------- ---------- ------------------------------------------------------ Type Name Default Description ------ ----------------- ---------- ------------------------------------------------------ vec3f baseColor white 0.8 base reflectivity (diffuse and/or metallic, linear RGB) vec3f edgeColor white edge tint (metallic only, linear RGB) float metallic 0 mix between dielectric (diffuse and/or specular) and metallic (specular only with complex IOR) in [0–1] float diffuse 1 diffuse reflection weight in [0–1] float specular 1 specular reflection/transmission weight in [0–1] float ior 1 dielectric index of refraction float transmission 0 specular transmission weight in [0–1] vec3f transmissionColor white attenuated color due to transmission (Beer's law, linear RGB) float transmissionDepth 1 distance at which color attenuation is equal to transmissionColor float roughness 0 diffuse and specular roughness in [0–1], 0 is perfectly smooth float anisotropy 0 amount of specular anisotropy in [0–1] float rotation 0 rotation of the direction of anisotropy in [0–1], 1 is going full circle float normal 1 default normal map/scale for all layers float baseNormal 1 base normal map/scale (overrides default normal) bool thin false flag specifying whether the material is thin or solid float thickness 1 thickness of the material (thin only), affects the amount of color attenuation due to specular transmission float backlight 0 amount of diffuse transmission (thin only) in [0–2], 1 is 50% reflection and 50% transmission, 2 is transmission only float coat 0 clear coat layer weight in [0–1] float coatIor 1.5 clear coat index of refraction vec3f coatColor white clear coat color tint (linear RGB) float coatThickness 1 clear coat thickness, affects the amount of color attenuation float coatRoughness 0 clear coat roughness in [0–1], 0 is perfectly smooth float coatNormal 1 clear coat normal map/scale (overrides default normal) float sheen 0 sheen layer weight in [0–1] vec3f sheenColor white sheen color tint (linear RGB) float sheenTint 0 how much sheen is tinted from sheenColor toward baseColor float sheenRoughness 0.2 sheen roughness in [0–1], 0 is perfectly smooth float opacity 1 cut-out opacity/transparency, 1 is fully opaque vec3f emissiveColor black color (and intensity) of the emitted light ------ ----------------- ---------- ------------------------------------------------------ : Parameters of the Principled material. All parameters can be textured by passing a [texture] handle, prefixed with "`map_`" (e.g., "`map_baseColor`"). [texture transformations] are supported as well. ![Rendering of a Principled coated brushed metal material with textured anisotropic rotation and a dust layer (sheen) on top.][imgMaterialPrincipled] ### CarPaint The CarPaint material is a specialized version of the Principled material for rendering different types of car paints. To create a CarPaint material, pass the type string "`carPaint`" to `ospNewMaterial`. Its parameters are listed in the table below. ------ ----------------- ---------- ------------------------------------------------------ Type Name Default Description ------ ----------------- ---------- ------------------------------------------------------ vec3f baseColor white 0.8 diffuse base reflectivity (linear RGB) float roughness 0 diffuse roughness in [0–1], 0 is perfectly smooth float normal 1 normal map/scale vec3f flakeColor Aluminium color of metallic flakes (linear RGB) float flakeDensity 0 density of metallic flakes in [0–1], 0 disables flakes, 1 fully covers the surface with flakes float flakeScale 100 scale of the flake structure, higher values increase the amount of flakes float flakeSpread 0.3 flake spread in [0–1] float flakeJitter 0.75 flake randomness in [0–1] float flakeRoughness 0.3 flake roughness in [0–1], 0 is perfectly smooth float coat 1 clear coat layer weight in [0–1] float coatIor 1.5 clear coat index of refraction vec3f coatColor white clear coat color tint (linear RGB) float coatThickness 1 clear coat thickness, affects the amount of color attenuation float coatRoughness 0 clear coat roughness in [0–1], 0 is perfectly smooth float coatNormal 1 clear coat normal map/scale vec3f flipflopColor white reflectivity of coated flakes at grazing angle, used together with coatColor produces a pearlescent paint (linear RGB) float flipflopFalloff 1 flip flop color falloff, 1 disables the flip flop effect ------------------------------------------------------------------------------------------- : Parameters of the CarPaint material. All parameters can be textured by passing a [texture] handle, prefixed with "`map_`" (e.g., "`map_baseColor`"). [texture transformations] are supported as well. ![Rendering of a pearlescent CarPaint material.][imgMaterialCarPaint] ### Metal The [path tracer] offers a physical metal, supporting changing roughness and realistic color shifts at edges. To create a Metal material pass the type string "`metal`" to `ospNewMaterial`. Its parameters are -------- ---------- ---------- -------------------------------------------- Type Name Default Description -------- ---------- ---------- -------------------------------------------- vec3f[] ior Aluminium [data] array of spectral samples of complex refractive index, each entry in the form (wavelength, eta, k), ordered by wavelength (which is in nm) vec3f eta RGB complex refractive index, real part vec3f k RGB complex refractive index, imaginary part float roughness 0.1 roughness in [0–1], 0 is perfect mirror -------- ---------- ---------- -------------------------------------------- : Parameters of the Metal material. The main appearance (mostly the color) of the Metal material is controlled by the physical parameters `eta` and `k`, the wavelength-dependent, complex index of refraction. These coefficients are quite counter-intuitive but can be found in [published measurements](https://refractiveindex.info/). For accuracy the index of refraction can be given as an array of spectral samples in `ior`, each sample a triplet of wavelength (in nm), eta, and k, ordered monotonically increasing by wavelength; OSPRay will then calculate the Fresnel in the spectral domain. Alternatively, `eta` and `k` can also be specified as approximated RGB coefficients; some examples are given in below table. Metal eta k -------------- ----------------------- ----------------- Ag, Silver (0.051, 0.043, 0.041) (5.3, 3.6, 2.3) Al, Aluminium (1.5, 0.98, 0.6) (7.6, 6.6, 5.4) Au, Gold (0.07, 0.37, 1.5) (3.7, 2.3, 1.7) Cr, Chromium (3.2, 3.1, 2.3) (3.3, 3.3, 3.1) Cu, Copper (0.1, 0.8, 1.1) (3.5, 2.5, 2.4) -------------- ----------------------- ----------------- : Index of refraction of selected metals as approximated RGB coefficients, based on data from https://refractiveindex.info/. The `roughness` parameter controls the variation of microfacets and thus how polished the metal will look. The roughness can be modified by a [texture] `map_roughness` ([texture transformations] are supported as well) to create notable edging effects. ![Rendering of golden Metal material with textured roughness.][imgMaterialMetal] ### Alloy The [path tracer] offers an alloy material, which behaves similar to [Metal], but allows for more intuitive and flexible control of the color. To create an Alloy material pass the type string "`alloy`" to `ospNewMaterial`. Its parameters are Type Name Default Description ------ ---------- ---------- -------------------------------------------------------- vec3f color white 0.9 reflectivity at normal incidence (0 degree, linear RGB) vec3f edgeColor white reflectivity at grazing angle (90 degree, linear RGB) float roughness 0.1 roughness, in [0–1], 0 is perfect mirror ------ ---------- ---------- -------------------------------------------------------- : Parameters of the Alloy material. The main appearance of the Alloy material is controlled by the parameter `color`, while `edgeColor` influences the tint of reflections when seen at grazing angles (for real metals this is always 100% white). If present, the color component of [geometries] is also used for reflectivity at normal incidence `color`. As in [Metal] the `roughness` parameter controls the variation of microfacets and thus how polished the alloy will look. All parameters can be textured by passing a [texture] handle, prefixed with "`map_`"; [texture transformations] are supported as well. ![Rendering of a fictional Alloy material with textured color.][imgMaterialAlloy] ### Glass The [path tracer] offers a realistic a glass material, supporting refraction and volumetric attenuation (i.e., the transparency color varies with the geometric thickness). To create a Glass material pass the type string "`glass`" to `ospNewMaterial`. Its parameters are Type Name Default Description ------ -------------------- -------- ----------------------------------------------- float eta 1.5 index of refraction vec3f attenuationColor white resulting color due to attenuation (linear RGB) float attenuationDistance 1 distance affecting attenuation ------ -------------------- -------- ----------------------------------------------- : Parameters of the Glass material. For convenience, the rather counter-intuitive physical attenuation coefficients will be calculated from the user inputs in such a way, that the `attenuationColor` will be the result when white light traveled through a glass of thickness `attenuationDistance`. ![Rendering of a Glass material with orange attenuation.][imgMaterialGlass] ### ThinGlass The [path tracer] offers a thin glass material useful for objects with just a single surface, most prominently windows. It models a thin, transparent slab, i.e., it behaves as if a second, virtual surface is parallel to the real geometric surface. The implementation accounts for multiple internal reflections between the interfaces (including attenuation), but neglects parallax effects due to its (virtual) thickness. To create a such a thin glass material pass the type string "`thinGlass`" to `ospNewMaterial`. Its parameters are Type Name Default Description --------- -------------------- -------- ------------------------------------------------ float eta 1.5 index of refraction vec3f attenuationColor white resulting color due to attenuation (linear RGB) float attenuationDistance 1 distance affecting attenuation float thickness 1 virtual thickness --------- -------------------- -------- ------------------------------------------------ : Parameters of the ThinGlass material. For convenience the attenuation is controlled the same way as with the [Glass] material. Additionally, the color due to attenuation can be modulated with a [texture] `map_attenuationColor` ([texture transformations] are supported as well). If present, the color component of [geometries] is also used for the attenuation color. The `thickness` parameter sets the (virtual) thickness and allows for easy exchange of parameters with the (real) [Glass] material; internally just the ratio between `attenuationDistance` and `thickness` is used to calculate the resulting attenuation and thus the material appearance. ![Rendering of a ThinGlass material with red attenuation.][imgMaterialThinGlass] ![Example image of a colored window made with textured attenuation of the ThinGlass material.][imgColoredWindow] ### MetallicPaint The [path tracer] offers a metallic paint material, consisting of a base coat with optional flakes and a clear coat. To create a MetallicPaint material pass the type string "`metallicPaint`" to `ospNewMaterial`. Its parameters are listed in the table below. Type Name Default Description --------- ------------ ---------- -------------------------------------- vec3f baseColor white 0.8 color of base coat (linear RGB) float flakeAmount 0.3 amount of flakes, in [0–1] vec3f flakeColor Aluminium color of metallic flakes (linear RGB) float flakeSpread 0.5 spread of flakes, in [0–1] float eta 1.5 index of refraction of clear coat --------- ------------ ---------- -------------------------------------- : Parameters of the MetallicPaint material. The color of the base coat `baseColor` can be textured by a [texture] `map_baseColor`, which also supports [texture transformations]. If present, the color component of [geometries] is also used for the color of the base coat. Parameter `flakeAmount` controls the proportion of flakes in the base coat, so when setting it to 1 the `baseColor` will not be visible. The shininess of the metallic component is governed by `flakeSpread`, which controls the variation of the orientation of the flakes, similar to the `roughness` parameter of [Metal]. Note that the effect of the metallic flakes is currently only computed on average, thus individual flakes are not visible. ![Rendering of a MetallicPaint material.][imgMaterialMetallicPaint] ### Luminous The [path tracer] supports the Luminous material which emits light uniformly in all directions and which can thus be used to turn any geometric object into a light source. It is created by passing the type string "`luminous`" to `ospNewMaterial`. The amount of constant radiance that is emitted is determined by combining the general parameters of lights: [`color` and `intensity`](#lights) (which essentially means that parameter `intensityQuantity` is not needed because it is always `OSP_INTENSITY_QUANTITY_RADIANCE`). Type Name Default Description ------ ------------ -------- --------------------------------------- vec3f color white color of the emitted light (linear RGB) float intensity 1 intensity of the light (a factor) float transparency 1 material transparency ------ ------------ -------- --------------------------------------- : Parameters accepted by the Luminous material. The emission can be textured by passing a `map_color` [texture] handle, [texture transformations] are supported as well. ![Rendering of a yellow Luminous material.][imgMaterialLuminous] Texture ------- OSPRay currently implements two texture types (`texture2d` and `volume`) and is open for extension to other types by applications. More types may be added in future releases. To create a new texture use OSPTexture ospNewTexture(const char *type); ### Texture2D The `texture2d` texture type implements an image-based texture, where its parameters are as follows Type Name Description -------------- --------- ---------------------------------- uint format `OSPTextureFormat` for the texture uint filter default `OSP_TEXTURE_FILTER_LINEAR`, alternatively `OSP_TEXTURE_FILTER_NEAREST` OSPData data the actual texel 2D [data] uint / vec2ui wrapMode `OSPTextureWrapMode` for the texture coordinates s and t; supported wrap modes are: `OSP_TEXTURE_WRAP_REPEAT` (default) `OSP_TEXTURE_WRAP_MIRRORED_REPEAT` `OSP_TEXTURE_WRAP_CLAMP_TO_EDGE` -------------- --------- ---------------------------------- : Parameters of `texture2d` texture type. The supported texture formats for `texture2d` are: Name Description ------------------- ---------------------------------------------------------- OSP_TEXTURE_RGBA8 8\ bit [0–255] linear components red, green, blue, alpha OSP_TEXTURE_SRGBA 8\ bit sRGB gamma encoded color components, and linear alpha OSP_TEXTURE_RGBA32F 32\ bit float components red, green, blue, alpha OSP_TEXTURE_RGB8 8\ bit [0–255] linear components red, green, blue OSP_TEXTURE_SRGB 8\ bit sRGB gamma encoded components red, green, blue OSP_TEXTURE_RGB32F 32\ bit float components red, green, blue OSP_TEXTURE_R8 8\ bit [0–255] linear single component red OSP_TEXTURE_RA8 8\ bit [0–255] linear two components red, alpha OSP_TEXTURE_L8 8\ bit [0–255] gamma encoded luminance (replicated into red, green, blue) OSP_TEXTURE_LA8 8\ bit [0–255] gamma encoded luminance, and linear alpha OSP_TEXTURE_R32F 32\ bit float single component red OSP_TEXTURE_RGBA16 16\ bit [0–65535] linear components red, green, blue, alpha OSP_TEXTURE_RGB16 16\ bit [0–65535] linear components red, green, blue OSP_TEXTURE_RA16 16\ bit [0–65535] linear two components red, alpha OSP_TEXTURE_R16 16\ bit [0–65535] linear single component red ------------------- ---------------------------------------------------------- : Supported texture formats by `texture2d`, i.e., valid constants of type `OSPTextureFormat`. The size of the texture is inferred from the size of the 2D array `data`, which also needs have a compatible type to `format`. The texel data in `data` starts with the texels in the lower left corner of the texture image, like in OpenGL. Per default a texture fetch is filtered by performing bi-linear interpolation of the nearest 2×2 texels; if instead fetching only the nearest texel is desired (i.e., no filtering) then pass the `OSP_TEXTURE_FILTER_NEAREST` flag. Texturing with `texture2d` image textures requires [geometries] with texture coordinates, e.g., a [mesh] with `vertex.texcoord` provided. ### Volume Texture The `volume` texture type implements texture lookups based on 3D object coordinates of the surface hit point on the associated geometry. If the given hit point is within the attached volume, the volume is sampled and classified with the transfer function attached to the volume. This implements the ability to visualize volume values (as colored by a transfer function) on arbitrary surfaces inside the volume (as opposed to an isosurface showing a particular value in the volume). Its parameters are as follows Type Name Description ------------------- ---------------- ----------------------------------------- OSPVolume volume [Volume] used to generate color lookups OSPTransferFunction transferFunction [transfer function] applied to `volume` ------------------- ---------------- ----------------------------------------- : Parameters of `volume` texture type. TextureVolume can be used for implementing slicing of volumes with any geometry type. It enables coloring of the slicing geometry with a different transfer function than that of the sliced volume. ### Texture Transformations All materials with textures also offer to manipulate the placement of these textures with the help of texture transformations. If so, this convention shall be used: the following parameters are prefixed with "`texture_name.*`"). Type Name Description --------- ------------ ------------------------------------------------- linear2f transform linear transformation (rotation, scale) float rotation angle in degree, counterclockwise, around center vec2f scale enlarge texture, relative to center $(0.5, 0.5)$ vec2f translation move texture in positive direction (right/up) --------- ------------ ------------------------------------------------- : Parameters to define 2D texture coordinate transformations. Above parameters are combined into a single `affine2d` transformation matrix and the transformations are applied in the given order. Rotation, scale and translation are interpreted "texture centric", i.e., their effect seen by an user are relative to the texture (although the transformations are applied to the texture coordinates). Type Name Description -------- ------------ -------------------------------------------------------- affine3f transform linear transformation (rotation, scale) plus translation -------- ------------ -------------------------------------------------------- : Parameter to define 3D volume texture transformations. Similarly, volume texture placement can also be modified by an `affine3f` transformation matrix. Cameras ------- To create a new camera of given type `type` use OSPCamera ospNewCamera(const char *type); All cameras accept these parameters: ----------- ----------------------- --------------------- ------------------------------------------ Type Name Default Description ----------- ----------------------- --------------------- ------------------------------------------ vec3f position $(0, 0, 0)$ position of the camera vec3f direction $(0, 0, 1)$ main viewing direction of the camera vec3f up $(0, 1, 0)$ up direction of the camera affine3f transform identity additional world-space transform, overridden by `motion.*` arrays float nearClip 10^-6^ near clipping distance vec2f imageStart $(0, 0)$ start of image region (lower left corner) vec2f imageEnd $(1, 1)$ end of image region (upper right corner) affine3f[] motion.transform additional uniformly distributed world-space transforms vec3f[] motion.scale additional uniformly distributed world-space scale, overridden by `motion.transform` vec3f[] motion.pivot additional uniformly distributed world-space translation which is applied before `motion.rotation` (i.e., the rotation center), overridden by `motion.transform` quatf[] motion.rotation additional uniformly distributed world-space quaternion rotation, overridden by `motion.transform` vec3f[] motion.translation additional uniformly distributed world-space translation, overridden by `motion.transform` box1f time [0, 1] time associated with first and last key in `motion.*` arrays box1f shutter [0.5, 0.5] start and end of shutter time (for motion blur), in [0, 1] uint shutterType `OSP_SHUTTER_GLOBAL` `OSPShutterType` for motion blur, also allowed are: `OSP_SHUTTER_ROLLING_RIGHT` `OSP_SHUTTER_ROLLING_LEFT` `OSP_SHUTTER_ROLLING_DOWN` `OSP_SHUTTER_ROLLING_UP` float rollingShutterDuration 0 for a rolling shutter (see `shutterType`) the "open" time per line, in [0, `shutter`.upper-`shutter`.lower] ----------- ----------------------- --------------------- ------------------------------------------ : Parameters accepted by all cameras. The camera is placed and oriented in the world with `position`, `direction` and `up`. Additionally, an extra transformation `transform` can be specified, which will only be applied to 3D vectors (i.e., `position`, `direction` and `up`), but does *not* affect any sizes (e.g., `nearClip`, `apertureRadius`, or `height`). The same holds for the array of transformations `motion.transform` to achieve camera motion blur (in combination with `time` and `shutter`). OSPRay uses a right-handed coordinate system. The region of the camera sensor that is rendered to the image can be specified in normalized screen-space coordinates with `imageStart` (lower left corner) and `imageEnd` (upper right corner). This can be used, for example, to crop the image, to achieve asymmetrical view frusta, or to horizontally flip the image to view scenes which are specified in a left-handed coordinate system. Note that values outside the default range of [0–1] are valid, which is useful to easily realize overscan or film gate, or to emulate a shifted sensor. ### Perspective Camera The perspective camera implements a simple thin lens camera for perspective rendering, supporting optionally depth of field and stereo rendering (with the [path tracer]). It is created by passing the type string "`perspective`" to `ospNewCamera`. In addition to the [general parameters](#cameras) understood by all cameras the perspective camera supports the special parameters listed in the table below. ----- ----------------------- ----------------- ----------------------------------------- Type Name Default Description ----- ----------------------- ----------------- ----------------------------------------- float fovy 60 the field of view (angle in degree) of the frame's height float aspect 1 ratio of width by height of the frame (and image region) float apertureRadius 0 size of the aperture, controls the depth of field float focusDistance 1 distance at where the image is sharpest when depth of field is enabled bool architectural false vertical edges are projected to be parallel uint stereoMode `OSP_STEREO_NONE` `OSPStereoMode` for stereo rendering, also allowed are: `OSP_STEREO_LEFT` `OSP_STEREO_RIGHT` `OSP_STEREO_SIDE_BY_SIDE` `OSP_STEREO_TOP_BOTTOM` (left eye at top half) float interpupillaryDistance 0.0635 distance between left and right eye when stereo is enabled ----- ----------------------- ----------------- ----------------------------------------- : Additional parameters accepted by the perspective camera. Note that when computing the `aspect` ratio a potentially set image region (using `imageStart` & `imageEnd`) needs to be regarded as well. In architectural photography it is often desired for aesthetic reasons to display the vertical edges of buildings or walls vertically in the image as well, regardless of how the camera is tilted. Enabling the `architectural` mode achieves this by internally leveling the camera parallel to the ground (based on the `up` direction) and then shifting the lens such that the objects in direction `dir` are centered in the image. If finer control of the lens shift is needed use `imageStart` & `imageEnd`. Because the camera is now effectively leveled its image plane and thus the plane of focus is oriented parallel to the front of buildings, the whole façade appears sharp, as can be seen in the example images below. The resolution of the [framebuffer] is not altered by `imageStart`/`imageEnd`. ![Example image created with the perspective camera, featuring depth of field.][imgCameraPerspective] ![Enabling the `architectural` flag corrects the perspective projection distortion, resulting in parallel vertical edges.][imgCameraArchitectural] ![Example 3D stereo image using `stereoMode = OSP_STEREO_SIDE_BY_SIDE`.][imgCameraStereo] ### Orthographic Camera The orthographic camera implements a simple camera with orthographic projection, without support for depth. It is created by passing the type string "`orthographic`" to `ospNewCamera`. In addition to the [general parameters](#cameras) understood by all cameras the orthographic camera supports the following special parameters: Type Name Description ------ ------- ------------------------------------------------------------ float height size of the camera's image plane in y, in world coordinates float aspect ratio of width by height of the frame ------ ------- ------------------------------------------------------------ : Additional parameters accepted by the orthographic camera. For convenience the size of the camera sensor, and thus the extent of the scene that is captured in the image, can be controlled with the `height` parameter. The same effect can be achieved with `imageStart` and `imageEnd`, and both methods can be combined. In any case, the `aspect` ratio needs to be set accordingly to get an undistorted image. ![Example image created with the orthographic camera.][imgCameraOrthographic] ### Panoramic Camera The panoramic camera implements a simple camera with support for stereo rendering. It captures the complete surrounding with a latitude / longitude mapping and thus the rendered images should best have a ratio of 2:1. A panoramic camera is created by passing the type string "`panoramic`" to `ospNewCamera`. It is placed and oriented in the scene by using the [general parameters](#cameras) understood by all cameras. ----- ---------------------- ----------------------------------------- Type Name Description ----- ---------------------- ----------------------------------------- uint stereoMode `OSPStereoMode` for stereo rendering, possible values are: `OSP_STEREO_NONE` (default) `OSP_STEREO_LEFT` `OSP_STEREO_RIGHT` `OSP_STEREO_SIDE_BY_SIDE` `OSP_STEREO_TOP_BOTTOM` (left eye at top half) float interpupillaryDistance distance between left and right eye when stereo is enabled, default 0.0635 ----- ---------------------- ----------------------------------------- : Additional parameters accepted by the panoramic camera. ![Latitude / longitude map created with the panoramic camera.][imgCameraPanoramic] Scene Hierarchy --------------- ### Groups Groups in OSPRay represent collections of GeometricModels, VolumetricModels and Lights which share a common local-space coordinate system. To create a group call OSPGroup ospNewGroup(); Groups take arrays of geometric models, volumetric models, clipping geometric models and lights, but they are all optional. In other words, there is no need to create empty arrays if there are no geometries, volumes or lights in the group. By adding `OSPGeometricModel`s to the `clippingGeometry` array a clipping geometry feature is enabled. Geometries assigned to this parameter will be used as clipping geometries. Any supported geometry can be used for clipping^[including spheres, boxes, infinite planes, closed meshes, closed subdivisions and curves], the only requirement is that it has to distinctly partition space into clipping and non-clipping one. The use of clipping geometry that is not closed or infinite could result in rendering artifacts. User can decide which part of space is clipped by changing shading normals orientation with the `invertNormals` flag of the [GeometricModel]. All geometries and volumes assigned to `geometry` or `volume` will be clipped. All clipping geometries from all groups and [Instances] will be combined together – a union of these areas will be applied to all other objects in the [world]. -------------------- ---------------- ---------- -------------------------------------- Type Name Default Description -------------------- ---------------- ---------- -------------------------------------- OSPGeometricModel[] geometry NULL [data] array of [GeometricModels] OSPVolumetricModel[] volume NULL [data] array of [VolumetricModels] OSPGeometricModel[] clippingGeometry NULL [data] array of [GeometricModels] used for clipping OSPLight[] light NULL [data] array of [lights] bool dynamicScene false tell Embree to use faster BVH build (slower ray traversal), otherwise optimized for faster ray traversal (slightly slower BVH build) bool compactMode false tell Embree to use a more compact BVH in memory by trading ray traversal performance bool robustMode false tell Embree to enable more robust ray intersection code paths (slightly slower) -------------------- ---------------- ---------- --------------------------------------- : Parameters understood by groups. ### Instances Instances in OSPRay represent a single group's placement into the world via a transform. To create and instance call OSPInstance ospNewInstance(OSPGroup); The passed group can be `NULL` as long as the group to be instanced is passed as a parameter. If both a group is specified on object creation and as a parameter, the parameter value is used. If the parameter value is later removed, the group object passed on object creation is again used. ------------ ----------------- ---------- -------------------------------------------------------- Type Name Default Description ------------ ----------------- ---------- -------------------------------------------------------- OSPGroup group optional [group] object to be instanced affine3f transform identity world-space transform for all attached geometries and volumes, overridden by `motion.*` arrays affine3f[] motion.transform uniformly distributed world-space transforms vec3f[] motion.scale uniformly distributed world-space scale, overridden by `motion.transform` vec3f[] motion.pivot uniformly distributed world-space translation which is applied before `motion.rotation` (i.e., the rotation center), overridden by `motion.transform` quatf[] motion.rotation uniformly distributed world-space quaternion rotation, overridden by `motion.transform` vec3f[] motion.translation uniformly distributed world-space translation, overridden by `motion.transform` box1f time [0, 1] time associated with first and last key in `motion.*` arrays (for motion blur) uint32 id -1u optional user ID, for [framebuffer] channel `OSP_FB_ID_INSTANCE` ------------ ----------------- ---------- -------------------------------------------------------- : Parameters understood by instances. ### World Worlds are a container of scene data represented by [instances]. To create an (empty) world call OSPWorld ospNewWorld(); Objects are placed in the world through an array of instances. Similar to [groups], the array of instances is optional: there is no need to create empty arrays if there are no instances (though there will be nothing to render). Applications can query the world (axis-aligned) bounding box after the world has been committed. To get this information, call OSPBounds ospGetBounds(OSPObject); The result is returned in the provided `OSPBounds`^[`OSPBounds` has essentially the same layout as the `OSP_BOX3F` [`OSPDataType`][data].] struct: typedef struct { float lower[3]; float upper[3]; } OSPBounds; This call can also take `OSPGroup` and `OSPInstance` as well: all other object types will return an empty bounding box. Finally, Worlds can be configured with parameters for making various feature/performance trade-offs (similar to groups). ------------- ---------------- -------- ------------------------------------- Type Name Default Description ------------- ---------------- -------- ------------------------------------- OSPInstance[] instance NULL [data] array with handles of the [instances] OSPLight[] light NULL [data] array with handles of the [lights] bool dynamicScene false tell Embree to use faster BVH build (slower ray traversal), otherwise optimized for faster ray traversal (slightly slower BVH build) bool compactMode false tell Embree to use a more compact BVH in memory by trading ray traversal performance bool robustMode false tell Embree to enable more robust ray intersection code paths (slightly slower) ------------- ---------------- -------- ------------------------------------- : Parameters understood by worlds. Renderers --------- A renderer is the central object for rendering in OSPRay. Different renderers implement different features and support different materials. To create a new renderer of given type `type` use OSPRenderer ospNewRenderer(const char *type); General parameters of all renderers are -------------- ------------------ ----------------------- ----------------------------------------- Type Name Default Description -------------- ------------------ ----------------------- ----------------------------------------- int pixelSamples 1 samples per pixel int maxPathLength 20 maximum ray recursion depth float minContribution 0.001 sample contributions below this value will be neglected to speedup rendering float varianceThreshold 0 threshold for adaptive accumulation float / backgroundColor black, background color and alpha (linear vec3f / vec4f transparent A/RGB/RGBA), if no `map_backplate` is set OSPTexture map_backplate optional [texture] image used as background (use texture type `texture2d`) OSPTexture map_maxDepth optional screen-sized float [texture] with maximum far distance per pixel (use texture type `texture2d`) OSPMaterial[] material optional [data] array of [materials] which can be indexed by a [GeometricModel]'s `material` parameter uint pixelFilter `OSP_PIXELFILTER_GAUSS` `OSPPixelFilterType` to select the pixel filter used by the renderer for antialiasing. Possible pixel filters are listed below. -------------- ------------------ ----------------------- ----------------------------------------- : Parameters understood by all renderers. OSPRay's renderers support a feature called adaptive accumulation, which accelerates progressive [rendering] by stopping the rendering and refinement of image regions that have an estimated variance below the `varianceThreshold`. This feature requires a [framebuffer] with an `OSP_FB_VARIANCE` channel. Per default the background of the rendered image will be transparent black, i.e., the alpha channel holds the opacity of the rendered objects. This eases transparency-aware blending of the image with an arbitrary background image by the application. The parameter `backgroundColor` or `map_backplate` can be used to already blend with a constant background color or backplate texture, respectively, (and alpha) during rendering. OSPRay renderers support depth composition with images of other renderers, for example to incorporate help geometries of a 3D UI that were rendered with OpenGL. The screen-sized [texture] `map_maxDepth` must have format `OSP_TEXTURE_R32F` and flag `OSP_TEXTURE_FILTER_NEAREST`. The fetched values are used to limit the distance of primary rays, thus objects of other renderers can hide objects rendered by OSPRay. OSPRay supports antialiasing in image space by using pixel filters, which are centered around the center of a pixel. The size $w×w$ of the filter depends on the selected filter type. The types of supported pixel filters are defined by the `OSPPixelFilterType` enum and can be set using the `pixelFilter` parameter. -------------------------------- --------------------------------------------- Name Description -------------------------------- --------------------------------------------- OSP_PIXELFILTER_POINT a point filter only samples the center of the pixel, therefore the filter width is $w = 0$ OSP_PIXELFILTER_BOX a uniform box filter with a width of $w = 1$ OSP_PIXELFILTER_GAUSS a truncated, smooth Gaussian filter with a standard deviation of $\sigma = 0.5$ and a filter width of $w = 3$ OSP_PIXELFILTER_MITCHELL the Mitchell-Netravali filter with a width of $w = 4$ OSP_PIXELFILTER_BLACKMAN_HARRIS the Blackman-Harris filter with a width of $w = 3$ -------------------------------- --------------------------------------------- : Pixel filter types supported by OSPRay for antialiasing in image space. ### SciVis Renderer The SciVis renderer is a fast ray tracer for scientific visualization which supports volume rendering and ambient occlusion (AO). It is created by passing the type string "`scivis`" to `ospNewRenderer`. In addition to the [general parameters](#renderer) understood by all renderers, the SciVis renderer supports the following parameters: ------ ------------------- --------- ---------------------------------- Type Name Default Description ------ ------------------- --------- ---------------------------------- bool shadows false whether to compute (hard) shadows int aoSamples 0 number of rays per sample to compute ambient occlusion float aoDistance 10^20^ maximum distance to consider for ambient occlusion float volumeSamplingRate 1 sampling rate for volumes bool visibleLights false whether light sources are potentially visible (as in the [path tracer], regarding each light's `visible`) ------ ------------------- --------- ---------------------------------- : Special parameters understood by the SciVis renderer. Note that the intensity (and color) of AO is deduced from an [ambient light] in the `lights` array.^[If there are multiple ambient lights then their contribution is added.] If `aoSamples` is zero (the default) then ambient lights cause ambient illumination (without occlusion). ### Ambient Occlusion Renderer This renderer supports only a subset of the features of the [SciVis renderer] to gain performance. As the name suggest its main shading method is ambient occlusion (AO), [lights] are *not* considered at all. Volume rendering is supported. The Ambient Occlusion renderer is created by passing the type string "`ao`" to `ospNewRenderer`. In addition to the [general parameters](#renderer) understood by all renderers the following parameters are supported as well: ------------- ---------------------- ------------ ---------------------------- Type Name Default Description ------------- ---------------------- ------------ ---------------------------- int aoSamples 1 number of rays per sample to compute ambient occlusion float aoDistance 10^20^ maximum distance to consider for ambient occlusion float aoIntensity 1 ambient occlusion strength float volumeSamplingRate 1 sampling rate for volumes ------------- ---------------------- ------------ ---------------------------- : Special parameters understood by the Ambient Occlusion renderer. ### Path Tracer The path tracer supports soft shadows, indirect illumination and realistic materials. This renderer is created by passing the type string "`pathtracer`" to `ospNewRenderer`. In addition to the [general parameters](#renderer) understood by all renderers the path tracer supports the following special parameters: ---------- -------------------- -------- ------------------------------------ Type Name Default Description ---------- -------------------- -------- ------------------------------------ int lightSamples all number of random light samples per path vertex, per default all light sources are sampled int roulettePathLength 5 ray recursion depth at which to start Russian roulette termination int maxScatteringEvents 20 maximum number of non-specular (i.e., diffuse and glossy) bounces float maxContribution ∞ samples are clamped to this value before they are accumulated into the framebuffer bool backgroundRefraction false allow for alpha blending even if background is seen through refractive objects like glass ---------- -------------------- -------- ------------------------------------ : Special parameters understood by the path tracer. The path tracer requires that [materials] are assigned to [geometries], otherwise surfaces are treated as completely black. The path tracer supports [volumes](#volumes) with multiple scattering. The scattering albedo can be specified using the [transfer function]. Extinction is assumed to be spectrally constant. Framebuffer ----------- The framebuffer holds the rendered 2D image (and optionally auxiliary information associated with pixels). To create a new framebuffer object of given size `size` (in pixels), color format, and channels use OSPFrameBuffer ospNewFrameBuffer(int size_x, int size_y, OSPFrameBufferFormat format = OSP_FB_SRGBA, uint32_t frameBufferChannels = OSP_FB_COLOR); The parameter `format` describes the format the color buffer has _on the host_, and the format that `ospMapFrameBuffer` will eventually return. Valid values are: Name Description --------------- ------------------------------------------------------------- OSP_FB_NONE framebuffer will not be mapped by the application OSP_FB_RGBA8 8\ bit [0–255] linear component red, green, blue, alpha OSP_FB_SRGBA 8\ bit sRGB gamma encoded color components, and linear alpha OSP_FB_RGBA32F 32\ bit float components red, green, blue, alpha --------------- ------------------------------------------------------------- : Supported color formats of the framebuffer that can be passed to `ospNewFrameBuffer`, i.e., valid constants of type `OSPFrameBufferFormat`. The parameter `frameBufferChannels` specifies which channels the framebuffer holds, and can be combined together by bitwise OR from the values of `OSPFrameBufferChannel` listed in the table below. Name Description ------------------- ---------------------------------------------------------- OSP_FB_COLOR RGB color including alpha OSP_FB_DEPTH euclidean distance to the camera (_not_ to the image plane), as linear 32\ bit float; for multiple samples per pixel their minimum is taken OSP_FB_ACCUM accumulation buffer for progressive refinement OSP_FB_VARIANCE for estimation of the current noise level if OSP_FB_ACCUM is also present, see [rendering] OSP_FB_NORMAL accumulated world-space normal of the first non-specular hit, as vec3f OSP_FB_ALBEDO accumulated material albedo (color without illumination) at the first hit, as vec3f OSP_FB_ID_PRIMITIVE primitive index of the first hit, as uint32 OSP_FB_ID_OBJECT geometric/volumetric model `id`, if specified, or index in [group] of first hit, as uint32 OSP_FB_ID_INSTANCE user defined [instance] `id`, if specified, or instance index of first hit, as uint32 ------------------- ---------------------------------------------------------- : Framebuffer channels constants (of type `OSPFrameBufferChannel`), naming optional information the framebuffer can store. These values can be combined by bitwise OR when passed to `ospNewFrameBuffer`. If a certain channel value is _not_ specified, the given buffer channel will not be present. Note that OSPRay makes a clear distinction between the _external_ format of the framebuffer and the internal one: The external format is the format the user specifies in the `format` parameter; it specifies what color format OSPRay will eventually _return_ the framebuffer to the application (when calling `ospMapFrameBuffer`): no matter what OSPRay uses internally, it will simply return a 2D array of pixels of that format, with possibly all kinds of reformatting, compression/decompression, etc., going on in-between the generation of the _internal_ framebuffer and the mapping of the externally visible one. In particular, `OSP_FB_NONE` is a perfectly valid pixel format for a framebuffer that an application will never map. For example, an application driving a display wall may well generate an intermediate framebuffer and eventually transfer its pixel to the individual displays using an `OSPImageOperation` [image operation]. The application can map the given channel of a framebuffer – and thus access the stored pixel information – via const void *ospMapFrameBuffer(OSPFrameBuffer, OSPFrameBufferChannel = OSP_FB_COLOR); Note that `OSP_FB_ACCUM` or `OSP_FB_VARIANCE` cannot be mapped. The origin of the screen coordinate system in OSPRay is the lower left corner (as in OpenGL), thus the first pixel addressed by the returned pointer is the lower left pixel of the image. A previously mapped channel of a framebuffer can be unmapped by passing the received pointer `mapped` to void ospUnmapFrameBuffer(const void *mapped, OSPFrameBuffer); The individual channels of a framebuffer can be cleared with void ospResetAccumulation(OSPFrameBuffer); This function will clear *all* accumulating buffers (`OSP_FB_VARIANCE`, `OSP_FB_NORMAL`, and `OSP_FB_ALBEDO`, if present) and resets the accumulation counter `accumID`. It is unspecified if the existing color and depth buffers are physically cleared when `ospResetAccumulation` is called. If `OSP_FB_VARIANCE` is specified, an estimate of the variance of the last accumulated frame can be queried with float ospGetVariance(OSPFrameBuffer); Note this value is only updated after synchronizing with `OSP_FRAME_FINISHED`, as further described in [asynchronous rendering]. The estimated variance can be used by the application as a quality indicator and thus to decide whether to stop or to continue progressive rendering. The framebuffer takes a list of pixel operations to be applied to the image in sequence as an `OSPData`. The pixel operations will be run in the order they are in the array. Type Name Description -------------------- --------------- --------------------------------------- OSPImageOperation[] imageOperation ordered sequence of image operations -------------------- --------------- --------------------------------------- : Parameters accepted by the framebuffer. ### Image Operation Image operations are functions that are applied to every pixel of a frame. Examples include post-processing, filtering, blending, tone mapping, or sending tiles to a display wall. To create a new pixel operation of given type `type` use OSPImageOperation ospNewImageOperation(const char *type); #### Tone Mapper The tone mapper is a pixel operation which implements a generic filmic tone mapping operator. Using the default parameters it approximates the Academy Color Encoding System (ACES). The tone mapper is created by passing the type string "`tonemapper`" to `ospNewImageOperation`. The tone mapping curve can be customized using the parameters listed in the table below. ------ ---------- --------- ----------------------------------------- Type Name Default Description ------ ---------- --------- ----------------------------------------- float exposure 1.0 amount of light per unit area float contrast 1.6773 contrast (toe of the curve); typically is in [1–2] float shoulder 0.9714 highlight compression (shoulder of the curve); typically is in [0.9–1] float midIn 0.18 mid-level anchor input; default is 18% gray float midOut 0.18 mid-level anchor output; default is 18% gray float hdrMax 11.0785 maximum HDR input that is not clipped bool acesColor true apply the ACES color transforms ------ ---------- --------- ----------------------------------------- : Parameters accepted by the tone mapper. To use the popular "Uncharted 2" filmic tone mapping curve instead, set the parameters to the values listed in the table below. Name Value --------- -------- contrast 1.1759 shoulder 0.9746 midIn 0.18 midOut 0.18 hdrMax 6.3704 acesColor false --------- -------- : Filmic tone mapping curve parameters. Note that the curve includes an exposure bias to match 18% middle gray. #### Denoiser OSPRay comes with a module that adds support for Intel® Open Image Denoise (OIDN). This is provided as an optional module as it creates an additional project dependency at compile time. The module implements a "`denoiser`" frame operation, which denoises the entire frame before the frame is completed. OIDN will automatically select the fastest device, using a GPU when available. The device selection be overridden by the environment variable `OIDN_DEFAULT_DEVICE`, possible values are `cpu`, `sycl`, `cuda`, `hip`, or a physical device ID Rendering --------- ### Asynchronous Rendering Rendering is by default asynchronous (non-blocking), and is done by combining a framebuffer, renderer, camera, and world. What to render and how to render it depends on the renderer's parameters. If the framebuffer supports accumulation (i.e., it was created with `OSP_FB_ACCUM`) then successive calls to `ospRenderFrame` will progressively refine the rendered image. To start an render task, use OSPFuture ospRenderFrame(OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld); This returns an `OSPFuture` handle, which can be used to synchronize with the application, cancel, or query for progress of the running task. When `ospRenderFrame` is called, there is no guarantee when the associated task will begin execution. Progress of a running frame can be queried with the following API function float ospGetProgress(OSPFuture); This returns the approximated progress of the task in [0-1]. Applications can cancel a currently running asynchronous operation via void ospCancel(OSPFuture); Applications can wait on the result of an asynchronous operation, or choose to only synchronize with a specific event. To synchronize with an `OSPFuture` use void ospWait(OSPFuture, OSPSyncEvent = OSP_TASK_FINISHED); The following are values which can be synchronized with the application -------------------- -------------------------------------------------------- Name Description -------------------- -------------------------------------------------------- OSP_NONE_FINISHED Do not wait for anything to be finished (immediately return from `ospWait`) OSP_WORLD_COMMITTED Wait for the world to be committed (not yet implemented) OSP_WORLD_RENDERED Wait for the world to be rendered, but not post-processing operations (Pixel/Tile/Frame Op) OSP_FRAME_FINISHED Wait for all rendering operations to complete OSP_TASK_FINISHED Wait on full completion of the task associated with the future. The underlying task may involve one or more of the above synchronization events -------------------- -------------------------------------------------------- : Supported events that can be passed to `ospWait`. Currently only rendering can be invoked asynchronously. However, future releases of OSPRay may add more asynchronous versions of API calls (and thus return `OSPFuture`). Applications can query whether particular events are complete with int ospIsReady(OSPFuture, OSPSyncEvent = OSP_TASK_FINISHED); As the given running task runs (as tracked by the `OSPFuture`), applications can query a boolean [0, 1] result if the passed event has been completed. Applications can query how long an async task ran with float ospGetTaskDuration(OSPFuture); This returns the wall clock execution time of the task in seconds. If the task is still running, this will block until the task is completed. This is useful for applications to query exactly how long an asynchronous task executed without the overhead of measuring both task execution + synchronization by the calling application. ### Synchronous Rendering For convenience in certain use cases, `ospray_util.h` provides a synchronous version of `ospRenderFrame`: float ospRenderFrameBlocking(OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld); This version is the equivalent of: ospRenderFrame ospWait(f, OSP_TASK_FINISHED) return ospGetVariance(fb) This version is closest to `ospRenderFrame` from OSPRay v1.x. ### Rendering and ospCommit The use of either `ospRenderFrame` or `ospRenderFrameBlocking` requires that all objects in the scene being rendered have been committed before rendering occurs. If a call to `ospCommit` happens while a frame is rendered, the result is undefined behavior and should be avoided. ### Picking To get the world-space position of the geometry (if any) seen at [0–1] normalized screen-space pixel coordinates `screenPos_x` and `screenPos_y` use void ospPick(OSPPickResult *, OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld, float screenPos_x, float screenPos_y); The result is returned in the provided `OSPPickResult` struct: typedef struct { int hasHit; float worldPosition[3]; OSPInstance instance; OSPGeometricModel model; uint32_t primID; } OSPPickResult; Note that `ospPick` considers exactly the same camera of the given renderer that is used to render an image, thus matching results can be expected. If the camera supports depth of field then the center of the lens and thus the center of the circle of confusion is used for picking. Note that the caller needs to `ospRelease` the `instance` and `model` handles of `OSPPickResult` once the information is not needed anymore. Modules and Devices =================== CPU ---- The CPU module is implicitly loaded and the `cpu` device is automatically used if no other options are specified. GPU (Beta) --------- To use the GPU for rendering load the `gpu` module and select the `gpu` device: ```sh ./ospExamples --osp:load-modules=gpu --osp:device=gpu ``` or via explicit device creation by the application: ospLoadModule("gpu"); OSPDevice dev = ospNewDevice("gpu"); ospDeviceCommit(dev); ospSetCurrentDevice(dev); Type Name Description -------- ------------- -------------------------------- void\ * syclContext SYCL context void\ * syclDevice SYCL device void\ * zeContext Level Zero context void\ * zeDevice Level Zero device -------- ------------- -------------------------------- : Parameters specific to the `gpu` device. Applications can either set their SYCL context and device or their Level Zero context and device, to share device memory with OSPRay or to control which device should be used (e.g., in case multiple GPUs are present). If neither parameter is set, the `gpu` device will automatically create a context internally and select a GPU (that selection can be influenced via environment variable `ONEAPI_DEVICE_SELECTOR`). Compile times for just in time compilation (JIT compilation) can be large. To resolve this issue we recommend enabling persistent JIT compilation caching inside your application before the SYCL device is created, by setting environment variables `SYCL_CACHE_PERSISTENT=1` (and optionally `SYCL_CACHE_DIR=` to some proper directory where the JIT cache should get stored). To reduce GPU memory allocation overhead when rendering scenes with many objects (geometries, instances, etc.), memory pooling should be enabled by setting the environment variable `ISPCRT_MEM_POOL=1`. ### Known Issues {-} The following features are not implemented yet or are not working correctly on the GPU device: - Multiple volumes in the scene - Clipping - Motion blur - Subdivision surfaces - Progress reporting via `ospGetProgress` or canceling the frame via `ospCancel` - Picking via `ospPick` - Adaptive accumulation via `OSP_FB_VARIANCE` and `varianceThreshold` - Framebuffer channels `OSP_FB_ID_*` (id buffers) - Experimental support for shared device-only data, works only for `structuredRegular` volume There will be some delay on start-up as the kernel code is JIT compiled for the device, and similar pauses when changing the scene configuration, because the kernel specialized and re-compiled. For some combination of compiler, GPU driver and scene the rendered images might show artifacts (e.g., vertical lines or small blocks). Distributed Rendering with MPI ------------------------------ The purpose of OSPRay's MPI modules is to provide distributed rendering capabilities for OSPRay. The modules enables image- and data-parallel rendering across HPC clusters using MPI, allowing applications to transparently distribute rendering work, or to render data sets which are too large to fit in memory on a single machine. OSPRay provides multiple MPI modules that expose different distributed rendering capabilities. The `mpi_offload` module provides image-parallel rendering through the `mpiOffload` device; it enables OSPRay applications written for local rendering to be replicated across multiple nodes to distribute the rendering work without code changes. And the `mpi_distributed_cpu` and `mpi_distributed_gpu` modules provides data-parallel rendering through the `mpiDistributed` device, which allows MPI distributed applications to use OSPRay for distributed rendering. Each rank using the `mpiDistributed` device can render an independent piece of a global data set, or perform hybrid rendering where ranks partially or completely share data. The `mpiDistributed` device's image-parallel rendering support can be used to accelerate data loading for image-parallel applications, where all ranks load the same data from a shared disk and then perform image-parallel rendering on the replicated data, as if the `mpiOffload` device where being used. ### MPI Offload Rendering The `mpiOffload` device can be used to distribute image rendering tasks across a cluster without requiring modifications to the application itself. Existing applications using OSPRay for local rendering simply be passed command line arguments to load the module and indicate that the `mpiOffload` device should be used for image-parallel rendering. To load the module, pass `--osp:load-modules=mpi_offload`, to select the MPIOffloadDevice, pass `--osp:device=mpiOffload`. For example, the `ospExamples` application can be run as: ```sh mpirun -n ./ospExamples --osp:load-modules=mpi_offload --osp:device=mpiOffload ``` and will automatically distribute the image rendering tasks among the corresponding `N` nodes. Note that in this configuration rank 0 will act as a master/application rank, and will run the user application code but not perform rendering locally. Thus, a minimum of 2 ranks are required, one master to run the application and one worker to perform the rendering. Running with 3 ranks for example would now distribute half the image rendering work to rank 1 and half to rank 2. If more control is required over the placement of ranks to nodes, or you want to run a worker rank on the master node as well you can run the application and the `ospray_mpi_worker` program through MPI's MPMD mode. The `ospray_mpi_worker` will load the MPI module and select the offload device by default. ```sh mpirun -n 1 ./ospExamples --osp:load-modules=mpi_offload --osp:device=mpiOffload \ : -n ./ospray_mpi_worker ``` If initializing the `mpiOffload` device manually, or passing parameters through the command line, the following parameters can be set: -------- ------------------------ --------- --------------------------------- Type Name Default Description -------- ------------------------ --------- --------------------------------- string mpiMode mpi The mode to communicate with the worker ranks. `mpi` will assume you are launching the application and workers in the same mpi command (or split launch command). `mpi` is the only supported mode uint maxCommandBufferEntries 8192 Set the max number of commands to buffer before submitting the command buffer to the workers uint commandBufferSize 512\ MiB Set the max command buffer size to allow. Units are in MiB. Max size is 1.8\ GiB uint maxInlineDataSize 32\ MiB Set the max size of an OSPData which can be inline'd into the command buffer instead of being sent separately. Max size is half the commandBufferSize. Units are in MiB -------- ------------------------ --------- --------------------------------- : Parameters specific to the `mpiOffload` device. The `maxCommandBufferEntries`, `commandBufferSize`, and `maxInlineDataSize` can also be set via the environment variables: `OSPRAY_MPI_MAX_COMMAND_BUFFER_ENTRIES`, `OSPRAY_MPI_COMMAND_BUFFER_SIZE`, and `OSPRAY_MPI_MAX_INLINE_DATA_SIZE`, respectively. The `mpiOffload` device uses a dynamic load balancer by default. If you wish to use a static load balancer you can do so by setting the `OSPRAY_STATIC_BALANCER` environment variable to 1. For the worker ranks to create GPU devices instead of the default CPU devices set the environment variable `OSPRAY_MPI_DISTRIBUTED_GPU`, e.g., ```sh export OSPRAY_MPI_DISTRIBUTED_GPU=1 ``` or ```sh mpiexec -genv OSPRAY_MPI_DISTRIBUTED_GPU 1 \ -n 1 ./ospExamples --osp:load-modules=mpi_offload --osp:device=mpiOffload \ : -n 2 ./ospray_mpi_worker ``` The `mpiOffload` device does not support multiple init/shutdown cycles. Thus, to run `ospBenchmark` for this device make sure to exclude the init/shutdown test by passing `--benchmark_filter=-ospInit_ospShutdown` through the command line. ### MPI Distributed Rendering While MPI Offload rendering is used to transparently distribute rendering work without requiring modification to the application, MPI Distributed rendering is targeted at use of OSPRay within MPI-parallel applications. The MPI distributed device can be selected by loading the `mpi_distributed_cpu` module for CPU rendering or `mpi_distributed_gpu` for GPU rendering, and manually creating and using an instance of the `mpiDistributed` device, for example: ospLoadModule("mpi_distributed_cpu"); OSPDevice mpiDevice = ospNewDevice("mpiDistributed"); ospDeviceCommit(mpiDevice); ospSetCurrentDevice(mpiDevice); Your application can either initialize MPI before-hand, ensuring that `MPI_THREAD_SERIALIZED` or higher is supported, or allow the device to initialize MPI on commit. Thread multiple support is required if your application will make MPI calls while rendering asynchronously with OSPRay. When using the distributed device each rank can specify independent local data using the OSPRay API, as if rendering locally. However, when calling `ospRenderFrameAsync` the ranks will work collectively to render the data. The distributed device supports both image-parallel, where the data is replicated, and data-parallel, where the data is distributed, rendering modes. The `mpiDistributed` device will by default use each rank in `MPI_COMM_WORLD` as a render worker; however, it can also take a specific MPI communicator to use as the world communicator. Only those ranks in the specified communicator will participate in rendering. -------- ------------------ ---------------- -------------------------------- Type Name Default Description -------- ------------------ ---------------- -------------------------------- void\ * worldCommunicator MPI_COMM_WORLD The MPI communicator which the OSPRay workers should treat as their world -------- ------------------ ---------------- -------------------------------- : Parameters specific to the `mpiDistributed` device. -------- ------- --------- ----------------------------------------------- Type Name Default Description -------- ------- --------- ----------------------------------------------- box3f[] region NULL A list of bounding boxes which bound the owned local data to be rendered by the rank -------- ------- --------- ----------------------------------------------- : Parameters specific to the distributed `OSPWorld`. ------ ------------------- --------- ------------------------------------------------ Type Name Default Description ------ ------------------- --------- ------------------------------------------------ int aoSamples 0 The number of AO samples to take per-pixel float aoDistance 10^20^ The AO ray length to use. Note that if the AO ray would have crossed a rank boundary and ghost geometry is not available, there will be visible artifacts in the shading float volumeSamplingRate 1 sampling rate for volumes ------ ------------------- --------- ------------------------------------------------ : Parameters specific to the `mpiRaycast` renderer. #### Image Parallel Rendering in the MPI Distributed Device If all ranks specify exactly the same data, the distributed device can be used for image-parallel rendering. This works identical to the offload device, except that the MPI-aware application is able to load data in parallel on each rank rather than loading on the master and shipping data out to the workers. When a parallel file system is available, this can improve data load times. Image-parallel rendering is selected by specifying the same data on each rank, and using any of the existing local renderers (e.g., `scivis`, `pathtracer`). See [ospMPIDistribTutorialReplicated](https://github.com/ospray/ospray/blob/master/modules/mpi/tutorials/ospMPIDistribTutorialReplicated.cpp) for an example. #### Data Parallel Rendering in the MPI Distributed Device The MPI Distributed device also supports data-parallel rendering with sort-last compositing. Each rank can specify a different piece of data, as long as the bounding boxes of each rank's data are non-overlapping. The rest of the scene setup is similar to local rendering; however, for distributed rendering only the `mpiRaycast` renderer is supported. This renderer implements a subset of the `scivis` rendering features which are suitable for implementation in a distributed environment. By default the aggregate bounding box of the instances in the local world will be used as the bounds of that rank's data. However, when using ghost zones for volume interpolation, geometry or ambient occlusion, each rank's data can overlap. To clip these non-owned overlap regions out a set of regions (the `region` parameter) can pass as a parameter to the `OSPWorld` being rendered. Each rank can specify one or more non-overlapping `box3f`'s which bound the portions of its local data which it is responsible for rendering. See the [ospMPIDistribTutorialVolume](https://github.com/ospray/ospray/blob/master/modules/mpi/tutorials/ospMPIDistribTutorialVolume.cpp) for an example. Finally, the MPI distributed device also supports hybrid-parallel rendering, where multiple ranks can share a single piece of data. For each shared piece of data the rendering work will be assigned image-parallel among the ranks. Partially-shared regions are determined by finding those ranks specifying data with the same bounds (matching regions) and merging them. See the [ospMPIDistribTutorialPartialRepl](https://github.com/ospray/ospray/blob/master/modules/mpi/tutorials/ospMPIDistribTutorialPartialRepl.cpp) for an example. #### Picking on Distributed Data in the MPI Distributed Device {-} Calling `ospPick` in the distributed device will find and return the closest global object at the screen position on the rank that owns that object. The other ranks will report no hit. Picking in the distributed device takes into account data clipping applied through the `regions` parameter to avoid picking ghost data. ### Interaction with User Modules The MPI Offload rendering mode trivially supports user modules, with the caveat that attempting to share data directly with the application (e.g., passing a `void *` or other tricks to the module) will not work in a distributed environment. Instead, use the `ospNewSharedData` API to share data from the application with OSPRay, which will in turn be copied over the network to the workers. The MPI Distributed device also supports user modules, as all that is required for compositing the distributed data are the bounds of each rank's local data. MultiDevice ----------- The multidevice module is an experimental OSPRay device type that renders images by delegating off pixel tiles to a number of internal delegate OSPRay devices. If you wish to try it set the `OSPRAY_NUM_SUBDEVICES` environmental variable to the number of subdevices you want to create and tell OSPRay to both load the `multidevice_cpu` extension and create a multidevice for rendering instead of the default CPU device. One example in a bash like shell is as follows: ```sh OSPRAY_NUM_SUBDEVICES=6 ./ospTutorial --osp:load-modules=multidevice_cpu --osp:device=multidevice ``` Note that the multidevice currently does not support `OSPImageOperation`s for denoising nor tone mapping. RenderKit-ospray-f2a61c2/doc/c-gamma_coords.fig000066400000000000000000000015371456566705700214640ustar00rootroot00000000000000#FIG 3.2 Produced by xfig version 3.2.7 Landscape Center Metric Letter 100.00 Single -2 1200 2 5 1 0 1 0 7 50 -1 -1 0.000 0 0 0 1 4951.758 905.273 5400 1800 5130 1890 4950 1906 1 1 2.00 60.00 135.00 5 1 0 1 0 7 50 -1 -1 0.000 0 1 1 0 5265.000 1192.500 5850 900 5760 765 5310 540 1 1 1.00 60.00 135.00 2 1 0 3 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 1 1 2.00 120.00 270.00 4950 900 5850 900 2 1 0 3 0 7 50 -1 -1 0.000 0 0 7 1 0 2 1 1 2.00 120.00 270.00 4950 900 4950 2250 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 4950 900 5400 1800 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 4950 900 5310 540 4 2 0 50 -1 16 14 0.0000 4 240 825 4860 990 position\001 4 0 0 50 -1 16 14 0.0000 4 180 900 5040 2340 direction\001 4 0 0 50 -1 16 14 0.0000 4 180 255 5850 990 c0\001 4 0 0 50 -1 16 14 0.0000 4 180 390 5490 450 c90\001 4 0 0 50 -1 32 14 0.0000 4 195 105 5085 1755 g\001 RenderKit-ospray-f2a61c2/doc/compilation.md000066400000000000000000000105661456566705700207640ustar00rootroot00000000000000Standard CMake Build -------------------- ### Compiling OSPRay on Linux and Mac OS\ X Assuming the above requisites are all fulfilled, building OSPRay through CMake is easy: - Create a build directory, and go into it mkdir ospray/build cd ospray/build (We do recommend having separate build directories for different configurations such as release, debug, etc.). - The compiler CMake will use will default to whatever the `CC` and `CXX` environment variables point to. Should you want to specify a different compiler, run cmake manually while specifying the desired compiler. The default compiler on most linux machines is `gcc`, but it can be pointed to `clang` instead by executing the following: cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang .. CMake will now use Clang instead of GCC. If you are OK with using the default compiler on your system, then simply skip this step. Note that the compiler variables cannot be changed after the first `cmake` or `ccmake` run. - Open the CMake configuration dialog ccmake .. - Make sure to properly set build mode and enable the components you need, etc.; then type 'c'onfigure and 'g'enerate. When back on the command prompt, build it using make - You should now have `libospray.[so,dylib]` as well as a set of [example applications]. ### Compiling OSPRay on Windows On Windows using the CMake GUI (`cmake-gui.exe`) is the most convenient way to configure OSPRay and to create the Visual Studio solution files: - Browse to the OSPRay sources and specify a build directory (if it does not exist yet CMake will create it). - Click "Configure" and select as generator the Visual Studio version you have; OSPRay needs "Visual Studio 15 2017 Win64" or newer, 32\ bit builds are not supported, e.g., "Visual Studio 17 2022". - If the configuration fails because some dependencies could not be found then follow the instructions given in the error message, e.g., set the variable `embree_DIR` to the folder where Embree was installed and `openvkl_DIR` to where Open VKL was installed. - Optionally change the default build options, and then click "Generate" to create the solution and project files in the build directory. - Open the generated `OSPRay.sln` in Visual Studio, select the build configuration and compile the project. Alternatively, OSPRay can also be built without any GUI, entirely on the console. In the Visual Studio command prompt type: cd path\to\ospray mkdir build cd build cmake -G "Visual Studio 17 2022" [-D VARIABLE=value] .. cmake --build . --config Release Use `-D` to set variables for CMake, e.g., the path to Embree with "`-D embree_DIR=\path\to\embree`". You can also build only some projects with the `--target` switch. Additional parameters after "`--`" will be passed to `msbuild`. For example, to build in parallel only the OSPRay library without the example applications use cmake --build . --config Release --target ospray -- /m Finding an OSPRay Install with CMake ------------------------------------ Client applications using OSPRay can find it with CMake's `find_package()` command. For example, find_package(ospray 3.0.0 REQUIRED) finds OSPRay via OSPRay's configuration file `osprayConfig.cmake`^[This file is usually in `${install_location}/[lib|lib64]/cmake/ospray-${version}/`. If CMake does not find it automatically, then specify its location in variable `ospray_DIR` (either an environment variable or CMake variable).]. Once found, the following is all that is required to use OSPRay: target_link_libraries(${client_target} ospray::ospray) This will automatically propagate all required include paths, linked libraries, and compiler definitions to the client CMake target (either an executable or library). Advanced users may want to link to additional targets which are exported in OSPRay's CMake config, which includes all installed modules. All targets built with OSPRay are exported in the `ospray::` namespace, therefore all targets locally used in the OSPRay source tree can be accessed from an install. For example, `ospray_module_cpu` can be consumed directly via the `ospray::ospray_module_cpu` target. All targets have their libraries, includes, and definitions attached to them for public consumption (please [report bugs] if this is broken!). RenderKit-ospray-f2a61c2/doc/displaywall.md000066400000000000000000000015311456566705700207630ustar00rootroot00000000000000OSPRay parallel rendering on TACC's "Stallion" display wall =========================================================== [![](gallery/thumbnails/ospray_stallion-thumb.jpg)](gallery/ospray_stallion.jpg) This photo shows OSPRay running on the [Stallion 328 megapixel tiled display](https://www.tacc.utexas.edu/vislab/stallion) at the Texas Advanced Computing Center (TACC) visualization lab. OSPRay is rendering in an MPI parallel mode and interactively streaming to the tiled display via its [DisplayCluster](https://www.tacc.utexas.edu/research-development/tacc-software/displaycluster) interface. These features are scheduled to be released in OSPRay v0.9. The model used is courtesy Florida International University and the Texas Advanced Computing Center, and stems from a simulation of Ground Water Flow performed by Florida International University. RenderKit-ospray-f2a61c2/doc/documentation.md000066400000000000000000000011551456566705700213110ustar00rootroot00000000000000Documentation ============= The following [API documentation][OSPRayReadme] of OSPRay can also be found as a [pdf document][OSPRayReadme]. For a deeper explanation of the concepts, design, features and performance of OSPRay also have a look at the IEEE Vis 2016 paper "[OSPRay – A CPU Ray Tracing Framework for Scientific Visualization](https://www.ospray.org/talks/IEEEVis2016_OSPRay_paper.pdf)" (49MB, or get the [smaller version](https://www.ospray.org/talks/IEEEVis2016_OSPRay_paper_small.pdf) 1.8MB). The [slides of the talk](https://www.ospray.org/talks/IEEEVis2016_OSPRay_talk.pdf) (5.2MB) are also available. RenderKit-ospray-f2a61c2/doc/filter-latex.py000066400000000000000000000035341456566705700210730ustar00rootroot00000000000000# 1. convert tables to use 'tabu' # Based on Wagner Macedo's filter.py posted at # https://groups.google.com/forum/#!msg/pandoc-discuss/RUC-tuu_qf0/h-H3RRVt1coJ import pandocfilters as pf def latex(s): return pf.RawBlock('latex', s) def inlatex(s): return pf.RawInline('latex', s) def tbl_caption(s): return pf.Para([inlatex(r'\caption{')] + s + [inlatex(r'}')]) def tbl_alignment(a): aligns = { "AlignDefault": 'l', "AlignLeft": 'l', "AlignCenter": 'c', "AlignRight": 'r', } s = ''.join(map(lambda al: aligns[al['t']], a[:-1])) s += 'X[1,'+aligns[a[-1]['t']]+']' return s def tbl_headers(s): result = s[0][0]['c'][:] for i in range(1, len(s)): result.append(inlatex(' & ')) result.extend(s[i][0]['c']) result.append(inlatex(r'\\' '\n')) return pf.Para(result) def tbl_contents(s): result = [] for row in s: para = [] for col in row: if col: para.extend(col[0]['c']) para.append(inlatex(' & ')) result.extend(para) result[-1] = inlatex(r'\\' '\n') return pf.Para(result) def do_filter(k, v, f, m): if k == "Table": w = v[2] if sum(w) == 0: w = [1 for e in w] wd = '' ha = r'\centering' else: wd = '*' ha = r'\raggedright' return [latex(r'\begin{table'+wd+'}[!h]'), tbl_caption(v[0]), latex(ha), latex(r'\begin{tabu}{' + tbl_alignment(v[1]) + '}'), latex(r'\toprule'), tbl_headers(v[3]), latex(r'\midrule'), tbl_contents(v[4]), latex(r'\bottomrule' '\n' r'\end{tabu}'), latex(r'\end{table'+wd+'}')] if __name__ == "__main__": pf.toJSONFilter(do_filter) RenderKit-ospray-f2a61c2/doc/filter-sectionnumbers.py000066400000000000000000000007701456566705700230150ustar00rootroot00000000000000# remove section numbers for subheadings # Based on Wagner Macedo's filter.py posted at # https://groups.google.com/forum/#!msg/pandoc-discuss/RUC-tuu_qf0/h-H3RRVt1coJ import pandocfilters as pf sec = 0 def do_filter(k, v, f, m): global sec if sec > 2 or (k == "Header" and v[0] < 3): return [] if k == "Header" and v[0] > 2: sec += 1 v[1][1].append('unnumbered') return pf.Header(v[0], v[1], v[2]) if __name__ == "__main__": pf.toJSONFilter(do_filter) RenderKit-ospray-f2a61c2/doc/fiu_comparison.md000066400000000000000000000017261456566705700214610ustar00rootroot00000000000000FIU Data Set: Shadows and Ambient Occlusion vs. OpenGL-like local shading ========================================================================= (click on images to see higher-res versions) [![](demos/fiu/fiu-gl-small.jpg)](demos/fiu/fiu-gl.png) FIU with local (OpenGL-like) Shading : Without shadows and/or ambient occlusion (i.e., using a OpenGL-like local shading model), the FIU data set looks like this. \ [![](demos/fiu/fiu-obj-small.jpg)](demos/fiu/fiu-obj.png) FIU with ray traced shadows : Simply adding shadows already greatly enhances the user's perception of depth (e.g., the relative positions of streamlines and base geometry, the actual shape of the geometry, etc.). \ [![](demos/fiu/fiu-ao-small.jpg)](demos/fiu/fiu-ao.png) FIU with OSPRay's Ambient Occlusion Renderer : Ambient Occlusion further increases perception of depth. In OSPRay, enabling (true, ray-cast) Ambient Occlusion is as simple as selecting the "ao" renderer. RenderKit-ospray-f2a61c2/doc/gallery.md000066400000000000000000000142161456566705700201010ustar00rootroot00000000000000OSPRay Gallery ============== This page contains a few sample screenshots of different renderings done with OSPRay. If *you* have created any notable images through OSPRay and would like to share them on this page, please [send us an email](mailto:ospray@googlegroups.com). RenderKit-ospray-f2a61c2/doc/getting_ospray.md000066400000000000000000000047641456566705700215070ustar00rootroot00000000000000Download Precompiled OSPRay Binary Packages =========================================== Prerequisites ------------- Your CPU must support at least SSE4.1 or NEON to run OSPRay. The TGZ/ZIP packages contain most needed 3rd party dependencies. Additionally you need - To run the example viewer: OpenGL - To use the distributed, multi-node rendering feature: Intel® [MPI Library](https://software.intel.com/en-us/intel-mpi-library/) We recommend the latest version of both TBB and Embree libraries. GPU Runtime Requirements ------------------------ To run OSPRay on Intel GPUs you will need to first have drivers installed on your system. ### GPU drivers on Linux Install the latest GPGPU drivers for your Intel GPU from: . Follow the driver installation instructions for your graphics card. ### GPU drivers on Windows Install the latest GPGPU drivers for your Intel GPU from: . Follow the driver installation instructions for your graphics card. Packages -------- Packages for x86_64 are provided, OSPRay can be built for ARM64/NEON using the superbuild (see [Building and Finding OSPRay](#building-and-finding-ospray)). For Linux we provide OSPRay precompiled for 64\ bit (including the GPU module) as a TGZ archive. [ospray-.x86_64.linux.tar.gz](https://github.com/ospray/OSPRay/releases/download/v/ospray-.x86_64.linux.tar.gz) For Mac OS\ X we provide OSPRay as a ZIP archive: [ospray-.x86_64.macosx.zip](https://github.com/ospray/OSPRay/releases/download/v/ospray-.x86_64.macosx.zip) For Windows we provide OSPRay binaries precompiled for 64\ bit (including the GPU module) as an MSI installer as well as a ZIP archive. [ospray-.x86_64.windows.msi](https://github.com/ospray/OSPRay/releases/download/v/ospray-.x86_64.windows.msi) [ospray-.x86_64.windows.zip](https://github.com/ospray/OSPRay/releases/download/v/ospray-.x86_64.windows.zip) The source code of the latest OSPRay version can be downloaded here: [ospray-.zip](https://github.com/ospray/OSPRay/archive/v.zip) [ospray-.tar.gz](https://github.com/ospray/OSPRay/archive/v.tar.gz) You can also access [previous OSPRay releases](https://github.com/ospray/OSPRay/releases). RenderKit-ospray-f2a61c2/doc/hdri_light.fig000066400000000000000000000006151456566705700207220ustar00rootroot00000000000000#FIG 3.2 Produced by xfig version 3.2.7 Landscape Center Metric Letter 100.00 Single -2 1200 2 2 1 0 3 0 7 60 -1 -1 0.000 0 0 -1 0 0 1 4500 1125 2 1 0 1 0 7 60 -1 -1 0.000 0 0 7 0 0 4 5850 450 5850 1800 3150 1800 3150 450 2 1 0 3 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 3150 450 5850 450 4 0 0 50 -1 16 14 0.0000 4 195 270 5895 495 up\001 4 0 0 50 -1 16 14 0.0000 4 180 900 4590 1215 direction\001 RenderKit-ospray-f2a61c2/doc/images.md000066400000000000000000000033041456566705700177030ustar00rootroot00000000000000[imgTutorial1]: tutorial_firstframe.png [imgTutorial2]: tutorial_accumulatedframe.png [imgRenderSunSky]: renderSunSky.png { width=90% } [imgOspExamples]: ospExamples.png { width=90% } [imgMPIDistribTutorial1]: ospMPIDistribTutorial_firstFrame.jpg { width=60% } [imgMPIDistribTutorial2]: ospMPIDistribTutorial_accumulatedFrame.jpg { width=60% } [imgMPIDistribTutorialSpheres]: ospMPIDistribTutorialSpheres.jpg { width=60% } [imgMPIDistribTutorialVolume]: ospMPIDistribTutorialVolume.jpg { width=60% } [imgCGammaCoords]: c-gamma_coords.fig [imgSpotLight]: spot_light.fig [imgQuadLight]: quad_light.fig [imgHDRILight]: hdri_light.fig [imgCameraPerspective]: camera_perspective.jpg { width=60% } [imgCameraArchitectural]: camera_architectural.jpg { width=60% } [imgCameraStereo]: camera_stereo.jpg { width=90% } [imgCameraOrthographic]: camera_orthographic.jpg { width=60% } [imgCameraPanoramic]: camera_panoramic.jpg { width=90% } [imgDiffuseRooms]: diffuse_rooms.png { width=80% } [imgNormalMap]: normalmap_frustum.png { width=60% } [imgMaterialOBJ]: material_OBJ.jpg { width=60% } [imgMaterialPrincipled]: material_Principled.jpg { width=60% } [imgMaterialCarPaint]: material_CarPaint.jpg { width=60% } [imgMaterialMetal]: material_Metal.jpg { width=60% } [imgMaterialAlloy]: material_Alloy.jpg { width=60% } [imgMaterialGlass]: material_Glass.jpg { width=60% } [imgMaterialThinGlass]: material_ThinGlass.jpg { width=60% } [imgMaterialMetallicPaint]: material_MetallicPaint.jpg { width=60% } [imgMaterialLuminous]: material_Luminous.jpg { width=60% } [imgColoredWindow]: ColoredWindow.jpg { width=60% } [imgStructuredSphericalCoords]: structured_spherical_coords.svg { width=60% } [imgVdbStructure]: vdb_structure.svg { width=80% } RenderKit-ospray-f2a61c2/doc/legal.md000066400000000000000000000011451456566705700175230ustar00rootroot00000000000000Disclaimer and Legal Information ================================ © 2013 Intel Corporation [Privacy Notice](https://www.intel.com/privacy) Intel, the Intel logo, Xeon, Intel Xeon Phi, and Intel Core are trademarks of Intel Corporation in the U.S. and/or other countries. *Other names and brands may be claimed as the property of others. Performance varies by use, configuration and other factors. Learn more at [www.Intel.com/PerformanceIndex](https://www.intel.com/PerformanceIndex). Intel optimizations, for Intel compilers or other products, may not optimize to the same degree for non-Intel products. RenderKit-ospray-f2a61c2/doc/links.md000066400000000000000000000023271456566705700175620ustar00rootroot00000000000000 [Embree]: https://www.embree.org/ [Open VKL]: https://www.openvkl.org/ [Open Image Denoise]: https://openimagedenoise.github.io/ [OSPRayReadme]: https://www.ospray.org/OSPRay_readme.pdf "OSPRay Documentation" [doc/ospray2_porting_guide.md]: https://www.ospray.org/ospray2_porting_guide.html [camera]: documentation.html#cameras [geometry]: documentation.html#geometries [volume]: documentation.html#volumes [curves]: documentation.html#curves [group]: documentation.html#groups [instance]: documentation.html#instances [world]: documentation.html#world [data]: documentation.html#data [GeometricModel]: documentation.html#geometricmodels [VolumetricModel]: documentation.html#volumetricmodels [texture transformations]: documentation.html#texture-transformations [renderer]: documentation.html#renderers [SciVis renderer]: documentation.html#scivis-renderer [path tracer]: documentation.html#path-tracer [material]: documentation.html#materials [OBJ material]: documentation.html#obj-material [point light]: documentation.html#point-light-sphere-light [example applications]: tutorials.html#tutorials [tutorial]: tutorials.html#osptutorial [ospExamples]: tutorials.html#ospexamples [report bugs]: index.html#ospray-support-and-contact RenderKit-ospray-f2a61c2/doc/ospray2_porting_guide.md000066400000000000000000000265511456566705700227650ustar00rootroot00000000000000OSPRay v2.0 Porting Guide ========================= OSPRay v2.0.0 introduces a number of new features and updates, as well as some API changes. This guide is intended as an introduction to the new features and the concepts behind them, and as a guide to porting applications using OSPRay v1.8.x to v2.0.0. Parameters ---------- ### Setting parameters OSPRay traded having a limited number of parameter types (with a unique function signature for each type) by instead having a single generic function that takes any type found in the `OSPDataType` enum. The new function signature is as follows: void ospSetParam(OSPObject, const char *name, OSPDataType type, const void *mem) This function takes the address of the value being set, where care should be taken when setting pointer-based types. For example, consider the following C-array: float myValues[] = {0.f, 1.f, 2.f} If the application wants to set these values as an OSP_VEC3F, note that the `const void *mem` parameter to `ospSetParam` should point to what is the address of what would be a `vec3f`. Thus either of the following are valid: void ospSetParam(object, "some_parameter", OSP_VEC3F, &myValues[0]); or void ospSetParam(object, "some_parameter", OSP_VEC3F, myValues); The second variant relies on implicit casting from `float[]` to `float *`, which will point to the address of the first value. This then gets casted to a `vec3f` to be set on the target `object`. Some of the `ospSet*` functions were preserved as utility wrapper functions outlined later in this document (and can be found in `ospray_util.h`). ### OSPDataType type checking Where it was previously accepted to create data of generic type `OSP_OBJECT` to represent a list of any object type, the `OSPDataType` must now match the object(s) it contains. Objects ------- ### New Object Hierarchy OSPRay objects, such as `OSPGeometry` and `OSPVolume`, have a new hierarchy that affords more control over geometry and volume transformation and instancing in the scene. Previously, the workflow was to create an object, fill it with the necessary parameters, and then place the object into an `OSPModel` via, for example, `ospAddGeometry`. An example is shown below using the C API. OSPGeometry mesh = ospNewGeometry("triangles"); // set parameters on mesh ospCommit(mesh); OSPModel world = ospNewModel(); ospAddGeometry(world, mesh); ospRelease(mesh); ospCommit(world); In OSPRay v2.0.0, there is now an `OSPWorld`, which effectively replaces the old `OSPModel`. In addition, there are now 3 new objects that exist "in between" the geometry and the world: `OSPGeometricModel`, `OSPGroup`, and `OSPInstance`. There is also an `OSPVolumetricModel` equivalent for working with `OSPVolume` objects. The new workflow is shown below. Note that calls to `ospRelease()` have been removed for brevity. // create a geometry OSPGeometry mesh = ospNewGeometry("triangles"); // set parameters on mesh ospCommit(mesh); // put the geometry in a model (a geometry can exist in more than one model) OSPGeometricModel model = ospNewGeometricModel(mesh); ospCommit(model); // put the geometric model(s) in a group OSPGroup group = ospNewGroup(); OSPData geometricModels = ospNewSharedData1D(&model, OSP_GEOMETRIC_MODEL, 1); ospSetObject(group, "geometry", geometricModels); ospCommit(group); // put the group in an instance (a group can be instanced more than once) OSPInstance = ospNewInstance(group); ospCommit(instance); // put the instance in the world OSPWorld world = ospNewWorld(); OSPData instances = ospNewSharedData1D(&instance, OSP_INSTANCE, 1); ospSetObject(world, "instance", instances); ospCommit(world); While this looks more complex at first, the new hierarchy structure provides more fine control over appearance information and instance transformations. In OSPRay v1.x, geometries and volumes contained both structural and appearance information which limited their reuse in other objects. For example, the volume's transfer function can now be different between an isosurface, slice, and rendered volume all in the same scene without duplicating the actual volume itself. #### OSPGeometry and OSPVolume `OSPGeometry` and `OSPVolume` contain the physical data represented by the object. For geometries, this is the intersectable surface. For volumes, it is the scalar field to be sampled. #### OSPGeometricModel and OSPVolumetricModel `OSPGeometricModel` and `OSPVolumetricModel` contain appearance information about the geometry or volume that they hold. They have a one-to-N relationship with `OSPGeometry` and `OSPVolume` objects (i.e. a geometry or volume can exist in more than one model), but commonly exist as one-to-one. This could be used to create multiple copies of a geometry with different materials, for example. `OSPGeometricModel`s can hold primitive color information (e.g. the color used for each sphere in a `Spheres` geometry), a material or list of materials, and primitive material IDs (i.e. indexes into the list of materials if it is used). `OSPVolumetricModel`s can hold transfer functions. #### OSPGroup `OSPGroup` objects contain zero or more `OSPGeometricModel` and `OSPVolumetricModel` objects. They can hold geometries and volumes simultaneously. This is useful to collect together any objects that are logically grouped together in the scene. #### OSPInstance `OSPInstance` contains transformation information on an `OSPGroup` object. It has a one-to-one relationship with `OSPGroup`. This means that each `OSPInstance` contains exactly one `OSPGroup`. Similar to models and groups, a single `OSPGroup` may be placed into multiple `OSPInstace` objects. This allows for *instancing* of multiple objects throughout the scene, each with different transformations. `OSPInstance` objects holds an affine transformation matrix that is applied to all objects in its group. #### OSPWorld `OSPWorld` is the final container for all `OSPInstance` and `OSPLight` objects. It can contain one or more instances and lights. The world is passed along with a renderer, camera, and framebuffer to `ospRenderFrame` to generate an image. ### void ospRetain(OSPObject) To allow the user greater control over the lifetime of objects, a new API `ospRetain` has been introduced. This call increments an object's reference count, and can delay automatic deletion. Updated Public Parameter Names ------------------------------ OSPRay v2.0.0 has updated public parameter names (the strings used in `ospSetParam`) to a more consistent naming convention. OSPRay now will print a warning (visible if debug logs are enabled) if a parameter provided by the user is not used by an object. This can help catch cases where applications are using parameter names from OSPRay v1.8.5 or mistyped names. Some objects have required parameters. In these cases, OSPRay will invoke the error callback indicating which object and which parameter. OSPRay now universally uses the camelCase naming convention for all object types and parameter names. Furthermore, parameter names which are data arrays now use singular names to indicate what the elements are, and parameters which form a logical "struture-of-arrays" are communicated via the `"[structure_name].[member_name]"` naming convention. For example, the `"opacities"` array for `linear` transfer functions is now named `"opacity"`. Finally, some parameters have changed from being string-based to enum-based. All enums can be found in `OSPEnums.h`, where their usage can be found in the main API documentation. ospRenderFrame -------------- `ospRenderFrame` has changed in two ways. The signature has changed from: float ospRenderFrame(OSPFrameBuffer, OSPRenderer, const uint32_t frameBufferChannels = OSP_FB_COLOR); to OSPFuture ospRenderFrame(OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld); And, notably, it is no longer blocking. Two new calls `ospIsReady`, and `ospWait` are available to manage synchronization. Utility Library --------------- As a convenience, a lightweight utility library has been provided to help users port from the previous versions and reduce boilerplate code. This set of additional API calls are all implemented in terms of the core API found in `ospray.h`, where they can be found in `ospray_util.h`. Their definitions are compiled into `libospray` (the `ospray::ospray` CMake target) and are compatible with any valid device implementation. ### OSPData and Parameter helpers The core OSPRay API has been simplified by removing many of the type specializations from the data and parameter set calls. The utility library provides wrappers to the familiar calls listed below: ospSetString(OSPObject, const char *n, const char *s); ospSetObject(OSPObject, const char *n, OSPObject obj); ospSetBool(OSPObject, const char *n, int x); ospSetFloat(OSPObject, const char *n, float x); ospSetInt(OSPObject, const char *n, int x); ospSetVec2f(OSPObject, const char *n, float x, float y); ospSetVec3f(OSPObject, const char *n, float x, float y, float z); ospSetVec4f(OSPObject, const char *n, float x, float y, float z, float w); ospSetVec2i(OSPObject, const char *n, int x, int y); ospSetVec3i(OSPObject, const char *n, int x, int y, int z); ospSetVec4i(OSPObject, const char *n, int x, int y, int z, int w); ospSetObjectAsData(OSPObject, const char *n, OSPDataType type, OSPObject obj); OSPRay v1.x calls to `ospSetData` have been replaced with `ospSetObject`. Convenience wrappers have also been provided to specialize `ospNewData`, and the new `ospNewSharedData` and `ospCopyData` APIs. ospNewSharedData1D(const void *sharedData, OSPDataType type, uint32_t numItems); ospNewSharedData1DStride(const void *sharedData, OSPDataType type, uint32_t numItems, int64_t byteStride); ospNewSharedData2D(const void *sharedData, OSPDataType type, uint32_t numItems1, uint32_t numItems2); ospNewSharedData2DStride(const void *sharedData, OSPDataType type, uint32_t numItems1, int64_t byteStride1, uint32_t numItems2, int64_t byteStride2); ospNewSharedData3D(const void *sharedData, OSPDataType type, uint32_t numItems1, uint32_t numItems2, uint32_t numItems3); ospNewData1D(OSPDataType type, uint32_t numItems); ospNewData2D(OSPDataType type, uint32_t numItems1, uint32_t numItems2); ospCopyData1D(const OSPData source, OSPData destination, uint32_t destinationIndex); ospCopyData2D(const OSPData source, OSPData destination, uint32_t destinationIndex1, uint32_t destinationIndex2); ### Object Usage Simplification To simplify setting data onto an object, if there is only a single data item, the wrapper `ospSetObjectAsData` permits the user to assign this item without first creating a data object containing that item. For example: OSPData geometricModels = ospNewSharedData1D(&model, OSP_GEOMETRIC_MODEL, 1); ospSetObject(group, "geometry", geometricModels); ospRelease(geometricModels); simply becomes: ospSetObjectAsData(group, "geometry", OSP_GEOMETRIC_MODEL, model); ### Rendering helpers While `ospRenderFrame` is now asynchronous, some users will prefer the original blocking behavior that returns the frame variance. The utility library provides a wrapper to this functionality: float ospRenderFrameBlocking(OSPFrameBuffer fb, OSPRenderer renderer, OSPCamera camera, OSPWorld world) RenderKit-ospray-f2a61c2/doc/overview.md000066400000000000000000000044421456566705700203100ustar00rootroot00000000000000OSPRay Overview =============== Intel® OSPRay is an **o**pen source, **s**calable, and **p**ortable **ray** tracing engine for high-performance, high-fidelity visualization on Intel Architecture CPUs, Intel Xe GPUs, and ARM64 CPUs. OSPRay is part of the [Intel oneAPI Rendering Toolkit](https://software.intel.com/en-us/rendering-framework) and is released under the permissive [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0). The purpose of OSPRay is to provide an open, powerful, and easy-to-use rendering library that allows one to easily build applications that use ray tracing based rendering for interactive applications (including both surface- and volume-based visualizations). OSPRay runs on anything from laptops, to workstations, to compute nodes in HPC systems. OSPRay internally builds on top of Intel [Embree], Intel [Open VKL], and Intel [Open Image Denoise]. The CPU implementation is based on Intel [ISPC (Implicit SPMD Program Compiler)](https://ispc.github.io/) and fully exploits modern instruction sets like Intel SSE4, AVX, AVX2, AVX-512 and NEON to achieve high rendering performance. Hence, a CPU with support for at least SSE4.1 is required to run OSPRay on x86_64 architectures, or a CPU with support for NEON is required to run OSPRay on ARM64 architectures. OSPRay's GPU implementation (beta status) is based on the [SYCL](https://www.khronos.org/sycl/) cross-platform programming language implemented by [Intel oneAPI Data Parallel C++ (DPC++)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/data-parallel-c-plus-plus.html) and currently supports Intel Arcâ„¢ GPUs on Linux and Windows, and Intel Data Center GPU Flex and Max Series on Linux, exploiting ray tracing hardware support. OSPRay Support and Contact -------------------------- OSPRay is under active development, and though we do our best to guarantee stable release versions a certain number of bugs, as-yet-missing features, inconsistencies, or any other issues are still possible. For any such requests or findings please use [OSPRay's GitHub Issue Tracker](https://github.com/ospray/OSPRay/issues) (or, if you should happen to have a fix for it, you can also send us a pull request). To receive release announcements simply ["Watch" the OSPRay repository](https://github.com/ospray/OSPRay) on GitHub. RenderKit-ospray-f2a61c2/doc/preamble.tex000066400000000000000000000150061456566705700204270ustar00rootroot00000000000000\usepackage{polyglossia} \setdefaultlanguage{english} \usepackage{amssymb,amsmath} \usepackage{nicefrac} \usepackage{ifxetex,ifluatex} \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \else % if luatex or xelatex \ifxetex % \usepackage{mathspec} \usepackage[no-sscript]{xltxtra} \usepackage{xunicode} \else \usepackage{fontspec} \fi \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase} \newcommand{\euro}{€} \fi % use upquote if available, for straight quotes in verbatim environments \IfFileExists{upquote.sty}{\usepackage{upquote}}{} % use microtype if available \IfFileExists{microtype.sty}{% \usepackage{microtype} \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts }{} \PassOptionsToPackage{hyphens}{url} % url is loaded by hyperref \usepackage{tabu,booktabs} \tabulinesep=3pt \usepackage{graphicx} \usepackage{color} \usepackage{fancyvrb} \newcommand{\VerbBar}{|} \newcommand{\VERB}{\Verb[commandchars=\\\{\}]} \DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}} % fix issue with linebreaks and letter spacing in non-cpp blocks \DefineVerbatimEnvironment{verbatim}{Verbatim}{} % Add ',fontsize=\small' for more characters per line \newenvironment{Shaded}{}{} \newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}} \newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{#1}} \newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} \newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} \newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}} \newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.53,0.00,0.00}{#1}} \newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} \newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} \newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} \newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}} \newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.73,0.40,0.53}{#1}} \newcommand{\ImportTok}[1]{#1} \newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{#1}}} \newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.73,0.13,0.13}{\textit{#1}}} \newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} \newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} \newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{#1}} \newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{#1}} \newcommand{\VariableTok}[1]{\textcolor[rgb]{0.10,0.09,0.49}{#1}} \newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}} \newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.40,0.40,0.40}{#1}} \newcommand{\BuiltInTok}[1]{#1} \newcommand{\ExtensionTok}[1]{#1} \newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.74,0.48,0.00}{#1}} \newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.49,0.56,0.16}{#1}} \newcommand{\RegionMarkerTok}[1]{#1} \newcommand{\InformationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} \newcommand{\WarningTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}} \newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}} \newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}} \newcommand{\NormalTok}[1]{#1} \providecommand{\tightlist}{% \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} \makeatletter \def\maxwidth{\ifdim\Gin@nat@width>\columnwidth\columnwidth\else\Gin@nat@width\fi} \def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi} \def\fps@figure{htp}% set default figure placement \makeatother % Scale images if necessary, so that they will not overflow the page % margins by default, and it is still possible to overwrite the defaults % using explicit options in \includegraphics[width, height, ...]{} \setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio} \ifxetex \usepackage[setpagesize=false, % page size defined by xetex unicode=false, % unicode breaks when used with xetex xetex]{hyperref} \else \usepackage[unicode=true]{hyperref} \fi % read version into \osprayversion \newread\versionfile \openin\versionfile=tmp/version \read\versionfile to\osprayversion \closein\versionfile \hypersetup{breaklinks=true, bookmarks=true, pdfauthor={Intel Corporation}, pdftitle={OSPRay: An Open, Scalable, Parallel, Ray Tracing Based Rendering Engine for High-Fidelity Visualization \osprayversion}, colorlinks=true, citecolor=blue, urlcolor=blue, linkcolor=blue, pdfborder={0 0 0}} \copyrightyears{2013} \trademarkacknowledgment{% Intel, the Intel logo, Xeon, Intel Xeon Phi, and Intel Core are trademarks of Intel Corporation in the U.S. and/or other countries. } \performancedisclaimer \optimizationdisclaimer % no hyphenation (e.g. for trademarks) \hyphenation{Intel Xeon} % fix missing unicode chars in used font \catcode`\â‡\active \defâ‡{\ensuremath{\Leftarrow}} \catcode`\⇒\active \def⇒{\ensuremath{\Rightarrow}} \catcode`\â†\active \defâ†{\ensuremath{\leftarrow}} \catcode`\→\active \def→{\ensuremath{\rightarrow}} \catcode`\∞\active \def∞{\ensuremath{\infty}} \catcode`\½\active \def½{\nicefrac12} \catcode`\â…“\active \defâ…“{\nicefrac13} \catcode`\â…”\active \defâ…”{\nicefrac23} \catcode`\¼\active \def¼{\nicefrac14} \catcode`\¾\active \def¾{\nicefrac34} \catcode`\∙\active \def∙{\ensuremath{\cdot}} % fix overfull hboxes, somehow required for xelatex % pdflatex and lualatex is fine without \emergencystretch=0.5em \makeatletter% \newcommand*{\BreakableChar}{% \leavevmode% \nobreak\hskip\z@skip% \discretionary{}{}{}% \nobreak\hskip\z@skip% }% \makeatother % enable (more flexible) linebreaks in \texttt \renewcommand{\texttt}[1]{% \begingroup% \protect\renewcommand{\_}{\textunderscore\BreakableChar}% \ttfamily% \fontdimen3\font=0.1em% interword stretch \fontdimen4\font=0.1em% interword shrink \hyphenchar\font=`\-% to allow hyphenation \begingroup\lccode`~=`/\lowercase{\endgroup\def~}{/\BreakableChar}% \catcode`/=\active% \begingroup\lccode`~=`*\lowercase{\endgroup\def~}{*\BreakableChar}% \catcode`*=\active% \begingroup\lccode`~=`?\lowercase{\endgroup\def~}{?\BreakableChar}% \catcode`?=\active% \begingroup\lccode`~=`)\lowercase{\endgroup\def~}{)\BreakableChar}% \catcode`)=\active% \begingroup\lccode`~=`.\lowercase{\endgroup\def~}{.\BreakableChar}% \catcode`.=\active% \begingroup\lccode`~=`;\lowercase{\endgroup\def~}{;\BreakableChar}% \catcode`;=\active% \scantokens{#1\noexpand}% \endgroup% } RenderKit-ospray-f2a61c2/doc/prerequisites.md000066400000000000000000000116741456566705700213530ustar00rootroot00000000000000Building and Finding OSPRay =========================== The latest OSPRay sources are always available at the [OSPRay GitHub repository](http://github.com/ospray/ospray). The default `master` branch should always point to the latest bugfix release. Prerequisites ------------- OSPRay currently supports Linux, Mac OS\ X, and Windows. In addition, before you can build OSPRay you need the following prerequisites: - You can clone the latest OSPRay sources via: git clone https://github.com/ospray/ospray.git - To build OSPRay you need [CMake](http://www.cmake.org), any form of C++11 compiler (we recommend using GCC, but also support Clang, MSVC, and [Intel® C++ Compiler (icc)](https://software.intel.com/en-us/c-compilers)), and standard Linux development tools. - Additionally you require a copy of the [Intel® Implicit SPMD Program Compiler (ISPC)](http://ispc.github.io), version 1.23.0 or later. Please obtain a release of ISPC from the [ISPC downloads page](https://ispc.github.io/downloads.html). If ISPC is not found by CMake its location can be hinted with the variable `ispcrt_DIR`. - OSPRay builds on top of the [Intel oneAPI Rendering Toolkit common library (rkcommon)](https://www.github.com/ospray/rkcommon). The library provides abstractions for tasking, aligned memory allocation, vector math types, among others. For users who also need to build rkcommon, we recommend the default the Intel [Threading Building Blocks (TBB)](https://www.threadingbuildingblocks.org/) as tasking system for performance and flexibility reasons. TBB must be built from source when targeting ARM CPUs, or can be built from source as part of the [superbuild](#cmake-superbuild). Alternatively you can set CMake variable `RKCOMMON_TASKING_SYSTEM` to `OpenMP` or `Internal`. - OSPRay also heavily uses Intel [Embree], installing version 4.3.1 or newer is required. If Embree is not found by CMake its location can be hinted with the variable `embree_DIR`. - OSPRay supports volume rendering (enabled by default via `OSPRAY_ENABLE_VOLUMES`), which heavily uses Intel [Open VKL], version 2.0.1 or newer is required. If Open VKL is not found by CMake its location can be hinted with the variable `openvkl_DIR`, or disable `OSPRAY_ENABLE_VOLUMES`. - OSPRay also provides an optional module implementing the `denoiser` image operation, which is enabled by `OSPRAY_MODULE_DENOISER`. This module requires Intel [Open Image Denoise] in version 2.2.0 or newer. You may need to hint the location of the library with the CMake variable `OpenImageDenoise_DIR`. - For the optional MPI modules (enabled by `OSPRAY_MODULE_MPI`), which provide the `mpiOffload` and `mpiDistributed` devices, you need an MPI library and [Google Snappy](https://github.com/google/snappy). - The optional example application, the test suit and benchmarks need some version of OpenGL and GLFW as well as [GoogleTest](https://github.com/google/googletest) and [Google Benchmark](https://github.com/google/benchmark/) Depending on your Linux distribution you can install these dependencies using `yum` or `apt-get`. Some of these packages might already be installed or might have slightly different names. Type the following to install the dependencies using `yum`: sudo yum install cmake.x86_64 sudo yum install tbb.x86_64 tbb-devel.x86_64 Type the following to install the dependencies using `apt-get`: sudo apt-get install cmake-curses-gui sudo apt-get install libtbb-dev Under Mac OS\ X these dependencies can be installed using [MacPorts](http://www.macports.org/): sudo port install cmake tbb Under Windows please directly use the appropriate installers for [CMake](https://cmake.org/download/), [TBB](https://github.com/oneapi-src/oneTBB/releases), [ISPC](https://ispc.github.io/downloads.html) (for your Visual Studio version) and [Embree](https://github.com/embree/embree/releases/). ### Additional Prerequisites for GPU Build {-} To build OSPRay's GPU module you need - a SYCL compiler, either the open source [oneAPI DPC++ Compiler 2023-10-26](https://github.com/intel/llvm/releases/tag/nightly-2023-10-26) or the latest [Intel oneAPI DPC++/C++ Compiler](https://www.intel.com/content/www/us/en/developer/articles/tool/oneapi-standalone-components.html#dpcpp-cpp) - a recent [CMake](http://www.cmake.org), version 3.25.3 or higher - the [oneAPI Level Zero Loader v1.12.0](https://github.com/oneapi-src/level-zero/releases/tag/v1.12.0) development packages - On Linux Ubuntu 22.04 there are prebuilt packages available for this: `level-zero-devel` and `level-zero` - Other Linux distributions require building these packages from source - On Windows, you can use the single package `level-zero__win-sdk`; note you will need to set the environment variable `LEVEL_ZERO_ROOT` to the location of the SDK RenderKit-ospray-f2a61c2/doc/pvospray.md000066400000000000000000000013021456566705700203150ustar00rootroot00000000000000OSPRay running inside ParaView ============================== [![](related_projects/vtk-paraview/screenshot-paraview-fiu-thumb.jpg)](related_projects/vtk-paraview/screenshot-paraview-fiu.jpg) This picture shows a ParaView plugin that allows ParaView to render through OSPRay, using a ParaView/VTK plugin developed by the Texas Advanced Computing Center. (click on the image for a full-resolution version) The particular model used in this screenshot is courtesy Florida International University and the Texas Advanced Computing Center, and stems from a simulation of Ground Water Flow performed by Florida International University. Screenshot courtesy Carson Brownlee, Texas Advanced Computing Center. RenderKit-ospray-f2a61c2/doc/quad_light.fig000066400000000000000000000014571456566705700207330ustar00rootroot00000000000000#FIG 3.2 Produced by xfig version 3.2.7 Landscape Center Metric Letter 100.00 Single -2 1200 2 5 1 0 1 0 7 50 -1 -1 0.000 0 0 1 0 3204.068 1745.932 3150 1080 3678 1275 3870 1800 1 1 1.00 60.00 135.00 2 1 0 3 0 7 50 -1 -1 0.000 0 0 7 1 0 2 1 1 2.00 120.00 270.00 3150 1800 5400 1800 2 1 0 3 0 7 50 -1 -1 0.000 0 0 7 1 0 2 1 1 2.00 120.00 270.00 3150 1800 3150 450 2 2 0 1 0 7 60 -1 -1 0.000 0 0 7 0 0 5 3150 450 5400 450 5400 1800 3150 1800 3150 450 2 1 0 3 0 7 50 -1 -1 0.000 0 0 7 1 0 2 1 1 2.00 120.00 270.00 3150 1800 3150 990 4 1 0 50 -1 16 14 0.0000 4 240 825 3105 2070 position\001 4 0 0 50 -1 16 14 0.0000 4 240 675 3240 720 edge2\001 4 2 0 50 -1 16 14 0.0000 4 240 675 5175 2070 edge1\001 4 0 0 50 -1 16 14 0.0000 4 180 255 3240 1305 c0\001 4 0 0 50 -1 16 14 0.0000 4 180 390 3915 1710 c90\001 RenderKit-ospray-f2a61c2/doc/readme.tex000066400000000000000000000016521456566705700200770ustar00rootroot00000000000000\IfFileExists{ospray-doc/intel-spec.cls} { \documentclass[oneside]{ospray-doc/intel-spec} }{ \documentclass[oneside]{report} \newcommand{\copyrightyears}[1] {} \newcommand{\trademarkacknowledgment}[1] {} \newcommand{\performancedisclaimer}{} \newcommand{\optimizationdisclaimer}{} \newcommand{\makedisclaimers}{} \newcommand{\version}[1] { \author{Version ##1} } } \include{preamble} \begin{document} \title{Intel® OSPRay\vskip0.3\baselineskip\LARGE \noindent An Open, Scalable, Parallel, Ray Tracing Based Rendering Engine for High-Fidelity Visualization} \version{\osprayversion} \maketitle \tableofcontents \input{tmp/overview} \input{tmp/changelog} \input{tmp/compilation} \addtocontents{toc}{\protect\setcounter{tocdepth}{2}} \hypersetup{bookmarksdepth=2} \input{tmp/api} \addtocontents{toc}{\protect\setcounter{tocdepth}{1}} \hypersetup{bookmarksdepth=1} \input{tmp/tutorials} \makedisclaimers \end{document} RenderKit-ospray-f2a61c2/doc/readme_head.md000066400000000000000000000002671456566705700206610ustar00rootroot00000000000000OSPRay ====== This is release v of Intel® OSPRay. For changes and new features see the [changelog](CHANGELOG.md). Visit http://www.ospray.org for more information. RenderKit-ospray-f2a61c2/doc/related_projects.md000066400000000000000000000073671456566705700220040ustar00rootroot00000000000000Projects that make use of OSPRay ================================ This page gives a brief (and incomplete) list of other projects that make use of OSPRay, as well as a set of related links to other projects and related information. If you have a project that makes use of OSPRay and would like this to be listed here, please let us know. VTK, ParaView and VisIt ----------------------- VTK and Paraview 5.x+ have direct integrations for OSPRay rendering, as has [VisIt 3.x+](https://wci.llnl.gov/simulation/computer-codes/visit). Code and documentation are available on Kitware's instance of [GitLab](https://gitlab.kitware.com/paraview/paraview). Furthermore, interested users can also access Kitware's [tutorial on using OSPRay](https://www.paraview.org/Wiki/Intel_HPC_Dev_Con_ParaView_and_OSPRay_Tutorial). For information on using the path tracer inside ParaView, see [this Kitware blog post](https://blog.kitware.com/virtual-tour-and-high-quality-visualization-with-paraview-5-6-ospray/). HdOSPRay -------- HdOSPRay is a rendering plugin for the Hydra rendering layer in USD. For more information see the project's [page on GitHub](https://github.com/ospray/hdospray). OSPRay Studio -------- [Studio](https://github.com/ospray/ospray_studio) is the OSPRay team's lightweight visualization application used to showcase the latest features of OSPRay. "osprey" Rhino Viewport Plugin -------- [osprey](https://github.com/darbyjohnston/Osprey) is a rendering plugin written by Darby Johnston for Rhino3D that greatly accelerates rendering over the built-in renderer. BLOSPRAY -------- [BLOSPRAY](https://github.com/surfsara-visualization/blospray) is a rendering plugin for Blender that uses OSPRay for fast previews and final path traced rendering. Tapestry -------- Tapestry is a microservice for delivering scientific visualization on the cloud. With OSPRay, Tapestry can provide interactive visualization of large datasets accessible to many users throughout the web ecosystem. See the [demo page](https://seelabutk.github.io/tapestry/) and the project's [page on GitHub](https://github.com/seelabutk/tapestry) for more information. Megamol ------- [Megamol](https://megamol.org/2018/07/02/megamol-at-isc-2018/) is a molecular dynamics framework. With OSPRay, it can render billions of particles interactively. VESTEC ------ [![VESTEC](images/VESTEC-Logo-web.png){style="display:inline"}](https://vestec-project.eu/) [VESTEC](https://vestec-project.eu/) – Visual Exploration and Sampling Toolkit for Extreme Computing – is an European funded project that builds a flexible toolchain to combine multiple data sources, efficiently extract essential features, enable flexible scheduling and interactive supercomputing, and realize 3D visualization environments (partly using OSPRay) for interactive explorations by stakeholders and decision makers. VMD --- VMD is a popular molecular dynamics visualization package, where OSPRay is integrated as one its renderers. For more information see VMD's [release notes](https://www.ks.uiuc.edu/Research/vmd/current/). pCon.planner --- [pCon.planner](https://pcon-planner.com/en/) is an architectural design and rendering application that utilizes OSPRay for path traced photorealistic renderings. Projects that are closely related to OSPRay =========================================== - The Intel® [Embree] Ray Tracing Kernel Framework - Intel [Open Image Denoise], a high-performance denoising library - OSPRay's "sister project" [OpenSWR](http://openswr.org/) (**o**pen **s**oft**w**are **r**asterizer), a high-performance, highly-scalable, software OpenGL implementation that runs entirely on CPUs. OpenSWR is now included in [Mesa](http://mesa3d.org/). - The [Intel Implicit SPMD Program Compiler](http://ispc.github.io) (ISPC) RenderKit-ospray-f2a61c2/doc/spot_light.fig000066400000000000000000000010271456566705700207570ustar00rootroot00000000000000#FIG 3.2 Produced by xfig version 3.2.5c Landscape Center Metric Letter 100.00 Single -2 1200 2 5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 4275.000 1974.375 3600 3150 4275 3330 4950 3150 5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 4972.500 3307.500 5175 4140 5310 4095 5400 4050 2 1 0 3 0 7 50 -1 -1 0.000 0 0 7 0 0 3 2250 5850 4275 1800 6300 5850 2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 2700 5850 4275 1800 5850 5850 4 0 0 50 -1 16 14 0.0000 4 225 1500 4950 2970 openingAngle\001 4 0 0 50 -1 16 14 0.0000 4 225 1710 5400 3870 penumbraAngle\001 RenderKit-ospray-f2a61c2/doc/stylesheet.css000066400000000000000000000324511456566705700210240ustar00rootroot00000000000000body { font-size: 16px; font-weight: normal; letter-spacing: normal; color:#373737; background: #f2f2f2; font-family: "Myriad Set Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; text-rendering: optimizeLegibility; font-style: normal; line-height: 1.5; -webkit-font-smoothing: antialiased; text-align: justify; margin: 0; } h1, h2, h3, h4, h5, h6 { margin: 5px 0; font-weight: 700; color: #0071C5; letter-spacing: normal; clear: both; } h2 { background: none; border-top: 1pt solid #333; padding-top: 0.5em; } h1 { font-size: 24px; } h2 { font-size: 20px; } h3 { font-size: 16px; } h4 { font-size: 16px; } p { margin: 10px 0 15px 0; } dl dt { font-weight:bold; } code { font-size: 90%; } li p { margin: 0 } img { display: block; margin-left: auto; margin-right: auto; padding: 0 2em 1ex 0; } figcaption { color: #666; text-align: center; } div.left { float: left; max-width: 250px; margin: 0; padding: 0; } br { clear:both; } #TOC { max-height: 100%; max-width: calc(190px + 4em); top: 125px; left: -4em; position: fixed; z-index: 1; overflow-x: hidden; background: #e0e0e0; padding-right: 10px; text-align: left; } /* hide top-level items */ #TOC > ul > li { list-style: none; } #TOC > ul > li > a { display: none; } #TOC > ul > li > ul { list-style: none; } #demo-bullets { font-size: 90%; } #footer { padding-top: 5px; margin: 0; text-align: center; background:#212121; position:fixed; bottom:0px; height:22px; width:100%; font-size: 12px; color: #ffffff; } #footer_padding { margin: 0; text-align: center; background:#212121; bottom:0px; width:100%; height:100%; font-size: 12px; color: #ffffff; } #footer a:hover { color:#ff0000; } #footer a { color:#ffffff; } #header { color: #fff; position: fixed; width: 100%; letter-spacing: -1px; background: #379; z-index: 2; display: block; } #content-wrap { width:100%; height:calc(100% - 134px); position:fixed; top:107px; overflow:auto; background: #f2f2f2; } #content, #content-wtoc { padding-left: 5px; padding-right: 0px; position:static; max-width: 1024px; margin-left: auto; margin-right: auto; background: #f2f2f2; padding-top:10px; padding-bottom:10px; } /* prevent content to reach into TOC if not enough space */ @media screen and ( max-width: 1444px ) { #content-wtoc { margin-left: 200px; margin-right: 0px; } } #header-title { /*display:inline-block;*/ margin: 0; color: #fff; font-size: 42px; /*background:#212121; */ font-weight: 700; padding: 20px 0px 0px 10px; text-shadow: #111 0px 0px 10px; /*padding-left: 100px;*/ padding-top:10px; letter-spacing: -1px; max-width: 1024px; margin-left: auto; margin-right: auto; } #header-subtitle { display:inline-block; color: #fff; font-size: 21px; font-weight: 300; /*background: none;*/ text-shadow: #111 0px 0px 10px; /*padding-top: 10px;*/ /*padding-left: 100px;*/ padding-left: 10px; /*padding-bottom: 10px;*/ /*background:#212121; */ letter-spacing: -1px; } #header-github { color: #fff; font-size: 16px; font-weight: 300; background: none; } #forkme-banner { display: block; position: absolute; top:0; right: 20px; width:250px; z-index: 10; padding: 10px 0px 10px 20px; color: #fff; background: url('images/blacktocat.png') #0090ff no-repeat 80% 50%; font-weight: 700; } #header-spacing { color: #fff; font-size: 16px; font-weight: 300; height:5px; background: #f2f2f2; } #footer-spacing { color: #fff; font-size: 16px; font-weight: 300; height:5px; background: #f2f2f2; } #header-navbar { font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif; color: #fff; font-size: 14px; font-weight: normal; letter-spacing: normal; background: #444; padding-top: 0px; padding-bottom: 4px; height:18px; } #header-navbar ul { list-style : none; margin: 0; padding: 0; padding-top: 2px; max-width: 1024px; margin-left: auto; margin-right: auto; } #header-navbar ul li { display: inline; } #header-navbar ul li a { display: block; float: left; padding-left: 8px; padding-right: 8px; color: #DFDFDF; text-decoration: none; } #header-navbar ul li a:hover { color: #FAFAFA; } #header-navbar ul li#selected a { color: #fff; } .title { border: 0; padding: 0; margin: 0; margin-bottom: 20px; } .title h1 { color: #333; font-size: 60px; font-weight: 300; text-align: center; border: 0; padding: 0; margin: 0; border: 0; } .title h2 { color: #888; font-size: 24px; font-weight: 200; text-align: center; border: 0; padding: 0; margin: 0; border: 0; } .teaser-features { margin: 10px auto 150px auto; } div.feature { /* display:inline-block; */ /* width: 100%; */ margin-left: 10px; margin-right: 10px; margin-top: 10px; margin-bottom: 10px; float: left; /* width: 40%; */ width: 400px; height: 200px; display: block; } div.feature a { color:#373737; } div.feature img { float: left; display:inline-block; width: 360px; height: 260px; padding:0; box-shadow: 4px 4px 18px -5px rgba(0,0,0,0.86); } .feature-alt { display: block; float: left; padding-left: 184px; } .feature-alt img { float: right !important; } .feature .container { /* margin-left: 20px; margin-right: 20px; display:inline-block; max-width: 544px; color: #666; font-size: 18px; font-weight: 200; */ } div.feature p { /* padding-left: 20px; */ color: #777; } div.feature h2 { text-align: center; border: 0; color:#555; font-size: 26px; } .fadein { display: block; margin-left: auto; margin-right: auto; margin-bottom: 20px; margin-top: 0px; padding: 0; position: relative; padding-bottom: 58.59375%; /* 600/1024 */ max-width: 1000px; } #f1 { box-shadow: 4px 4px 18px -5px rgba(0,0,0,0.86); } .fadein img { margin-left: auto; max-width: 100%; height: 100%; padding: 0; position: absolute; } .teaser-img { margin-top: 60px; margin-bottom: 60px; } .fade { animation: fade 30s 1; } @keyframes fade { 0% {opacity: 0;} 5% {opacity: 0;} 20% {opacity: 1;} 25% {opacity: 1;} 45% {opacity: 0;} 50% {opacity: 0;} 60% {opacity: 1;} 65% {opacity: 1;} 75% {opacity: 0;} 80% {opacity: 0;} 100% {opacity: 1;} } hr { width: 60%; display: block; height: 1px; margin-left: auto; margin-right: auto; margin-top: 0px; margin-bottom: 0px; border: 0; border-top: 1.5px solid #aaa; padding: 0; } table { counter-increment: table; border-collapse: collapse; border-spacing: 0; border: 0px solid #373737; margin-top: 20px; margin-bottom: 20px; text-align: left; } table > caption:before { content: 'Table ' counter(table) ': '; color: #0071C5; } th { font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif; padding: 10px; background: #0071C5; color: #fff; } td { padding: 10px; border: 0px solid #373737; color: #222; background-color: #fff; vertical-align:top; } div.figure { clear: both; counter-increment: figure; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; margin: 0 0 3em 0; display: inline-block; width: 100%; } p.caption { margin-top: 3ex; font-size: 1.1rem; line-height: 1.6; text-align: left; } p.caption:before { content: 'Figure ' counter(figure) ': '; color: #0071C5; } .carousel { position: relative; } .carousel.pointer-event { -ms-touch-action: pan-y; touch-action: pan-y; } .carousel-inner { position: relative; width: 100%; overflow: hidden; padding-bottom: 4em; margin-top: 15px; margin-bottom: 15px; } .carousel-inner img { width: 100%; height: 100%; } .carousel-inner::after { display: block; clear: both; content: ""; } .carousel-item { position: relative; display: none; float: left; margin-right: -100%; -webkit-backface-visibility: hidden; backface-visibility: hidden; transition: -webkit-transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out; transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; height: 428px; } @media (prefers-reduced-motion: reduce) { .carousel-item { transition: none; } } .carousel-item.active, .carousel-item-next, .carousel-item-prev { display: block; } .carousel-item-next:not(.carousel-item-left), .active.carousel-item-right { -webkit-transform: translateX(100%); transform: translateX(100%); } .carousel-item-prev:not(.carousel-item-right), .active.carousel-item-left { -webkit-transform: translateX(-100%); transform: translateX(-100%); } .carousel-fade .carousel-item { opacity: 0; transition-property: opacity; -webkit-transform: none; transform: none; } .carousel-fade .carousel-item.active, .carousel-fade .carousel-item-next.carousel-item-left, .carousel-fade .carousel-item-prev.carousel-item-right { z-index: 1; opacity: 1; } .carousel-fade .active.carousel-item-left, .carousel-fade .active.carousel-item-right { z-index: 0; opacity: 0; transition: 0s 0.6s opacity; } @media (prefers-reduced-motion: reduce) { .carousel-fade .active.carousel-item-left, .carousel-fade .active.carousel-item-right { transition: none; } } .carousel-control-prev, .carousel-control-next { position: absolute; top: 0; bottom: 4em; z-index: 1; display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; width: 15%; color: #fff; text-align: center; opacity: 0.5; transition: opacity 0.15s ease; } @media (prefers-reduced-motion: reduce) { .carousel-control-prev, .carousel-control-next { transition: none; } } .carousel-control-prev:hover, .carousel-control-prev:focus, .carousel-control-next:hover, .carousel-control-next:focus { color: #fff; text-decoration: none; outline: 0; opacity: 0.9; } .carousel-control-prev { left: 0; } .carousel-control-next { right: 0; } .carousel-control-prev-icon, .carousel-control-next-icon { display: inline-block; width: 20px; height: 20px; background: no-repeat 50% / 100% 100%; } .carousel-control-prev-icon { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e"); } .carousel-control-next-icon { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e"); } .carousel-indicators { position: absolute; right: 0; bottom: 0; left: 0; z-index: 1; display: -ms-flexbox; display: flex; -ms-flex-pack: center; justify-content: center; padding-left: 0; margin-right: 15%; margin-left: 15%; list-style: none; padding-bottom: 20px; } .carousel-indicators li { box-sizing: content-box; -ms-flex: 0 1 auto; flex: 0 1 auto; width: 30px; height: 3px; margin-right: 3px; margin-left: 3px; text-indent: -999px; cursor: pointer; background-color: #fff; background-clip: padding-box; border-top: 10px solid transparent; border-bottom: 45px solid transparent; opacity: .5; transition: opacity 0.6s ease; } @media (prefers-reduced-motion: reduce) { .carousel-indicators li { transition: none; } } .carousel-indicators .active { opacity: 1; } .carousel-caption { position: absolute; right: 15%; bottom: -80px; left: 15%; z-index: 1; padding-top: 40px; color: #fff; text-align: center; overflow: visible; line-height: normal; } .carousel-caption h3 { color: #555; } .carousel-caption p { color: #777; } .carousel img { padding: 0px; margin-bottom:8px; box-shadow: 0 8px 10px -6px black; } .gallery { display: grid; #border: 2px dashed rgba(114, 186, 94, 0.35); height: 250px; grid-template-columns: 1fr 1fr 1fr; grid-template-rows: auto; #background: rgba(114, 186, 94, 0.05); } .exhibit { display: block; margin-left: auto; margin-right: auto; padding: 0 2em 1ex 0; # width: 50%; # height: 50%; font-size: 16px; margin: 5px 0; font-weight: 700; color: #0071C5; letter-spacing: normal; clear: both; text-align: center; } .exhibit img { margin: 0; padding: 0; #float: left; #display:inline-block; display: block; float: left; width: 300px; box-shadow: 3px 3px 12px -5px rgba(0,0,0,0.86); } .exhibit .caption { font-size: 12px; color: #555; text-align: center; }RenderKit-ospray-f2a61c2/doc/teaser.html000066400000000000000000000074461456566705700203000ustar00rootroot00000000000000

The Open, Scalable, and Portable Ray Tracing Engine



Interactive Rendering on CPU or GPU

OSPRay features scalable CPU and GPU rendering capabilities geared toward Scientific Visualization applications. Advanced shading effects such as ambient occlusion, shadows, and transparency can be rendered interactively to enable new insights into huge data.

Global Illumination

OSPRay includes a path tracer capable of interactively rendering photorealistic global illumination with phyiscally-based materials.

Volume Rendering

OSPRay supports high-fidelity, interactive direct volume rendering with a number of state of the art visualization features.

MPI Distributed

Run on large scale distributed-memory systems with high-performance MPI backends to both decrease render time and increase total scene size.

Industry Adoption

OSPRay is directly integrated into ParaView 5.x. Implementations for VisIt, VMD, and other popular tools have also freely available.

Open Source

OSPRay is Open Sourced under the Apache 2.0 license.

RenderKit-ospray-f2a61c2/doc/tutorials.md000066400000000000000000000213021456566705700204620ustar00rootroot00000000000000Tutorials ========= ospTutorial ----------- A minimal working example demonstrating how to use OSPRay can be found at [`apps/tutorials/ospTutorial.c`](https://github.com/ospray/ospray/blob/master/apps/ospTutorial/ospTutorial.c)^[A C++ version that uses the C++ convenience wrappers of OSPRay's C99 API via [`include/ospray/ospray_cpp.h`](https://github.com/ospray/ospray/blob/master/ospray/include/ospray/ospray_cpp.h) is available at [`apps/tutorials/ospTutorial.cpp`](https://github.com/ospray/ospray/blob/master/apps/ospTutorial/ospTutorial.cpp).]. An example of building `ospTutorial.c` with CMake can be found in [`apps/tutorials/ospTutorialFindospray/`](https://github.com/ospray/ospray/tree/master/apps/ospTutorial/ospTutorialFindospray). To build the tutorial on Linux, build it in a build directory with gcc -std=c99 ../apps/ospTutorial/ospTutorial.c \ -I ../ospray/include -L . -lospray -Wl,-rpath,. -o ospTutorial On Windows build it can be build manually in a "build_directory\\$Configuration" directory with cl ..\..\apps\ospTutorial\ospTutorial.c -I ..\..\ospray\include -I ..\.. ospray.lib Running `ospTutorial` will create two images of two triangles, rendered with the Scientific Visualization renderer with full Ambient Occlusion. The first image `firstFrame.ppm` shows the result after one call to `ospRenderFrame` – jagged edges and noise in the shadow can be seen. Calling `ospRenderFrame` multiple times enables progressive refinement, resulting in antialiased edges and converged shadows, shown after ten frames in the second image `accumulatedFrames.ppm`. ![First frame.][imgTutorial1] ![After accumulating ten frames.][imgTutorial2] ospExamples ----------- Apart from tutorials, `OSPRay` comes with a C++ app called [`ospExamples`](https://github.com/ospray/ospray/tree/master/apps/ospExamples) which is an elaborate easy-to-use tutorial, with a single interface to try various `OSPRay` features. It is aimed at providing users with multiple simple scenes composed of basic geometry types, lights, volumes etc. to get started with OSPRay quickly. `ospExamples` app runs a `GLFWOSPRayWindow` instance that manages instances of the camera, framebuffer, renderer and other OSPRay objects necessary to render an interactive scene. The scene is rendered on a `GLFW` window with an `imgui` GUI controls panel for the user to manipulate the scene at runtime. The application is located in [`apps/ospExamples/`](https://github.com/ospray/ospray/tree/master/apps/ospExamples) directory and can be built with CMake. It can be run from the build directory via: ``` ./ospExamples ``` The command line parameter is optional however. ![`ospExamples` application with default `boxes` scene.][imgOspExamples] ### Scenes Different scenes can be selected from the `scenes` dropdown and each scene corresponds to an instance of a special `detail::Builder` struct. Example builders are located in [`apps/common/ospray_testing/builders/`](https://github.com/ospray/ospray/tree/master/apps/common/ospray_testing/builders). These builders provide a usage guide for the OSPRay scene hierarchy and OSPRay API in the form of `cpp` wrappers. They instantiate and manage objects for the specific scene like `cpp::Geometry`, `cpp::Volume`, `cpp::Light` etc. The `detail::Builder` base struct is mostly responsible for setting up OSPRay `world` and objects common in all scenes (for example lighting and ground plane), which can be conveniently overridden in the derived builders. ### Renderer This app comes with four [renderer] options: `scivis`, `pathtracer`, `ao` and `debug`. The app provides some common rendering controls like `pixelSamples` and other more specific to the renderer type like `aoSamples` for the `scivis` and `ao` renderer or `maxPathLength` for the `pathtracer`. The sun-sky lighting can be used in a sample scene by enabling the `renderSunSky` option of the `pathtracer` renderer. It allows the user to change `turbidity` and `sunDirection`. ![Rendering an evening sky with the `renderSunSky` option.][imgRenderSunSky] ospMPIDistribTutorial --------------------- A minimal working example demonstrating how to use OSPRay for rendering distributed data can be found at [`modules/mpi/tutorials/ospMPIDistribTutorial.c`](https://github.com/ospray/ospray/blob/master/modules/mpi/tutorials/ospMPIDistribTutorial.c)^[A C++ version that uses the C++ convenience wrappers of OSPRay's C99 API via [`include/ospray/ospray_cpp.h`](https://github.com/ospray/ospray/blob/master/ospray/include/ospray/ospray_cpp.h) is available at [`modules/mpi/tutorials/ospMPIDistribTutorial.cpp`](https://github.com/ospray/ospray/blob/master/modules/mpi/tutorials/ospMPIDistribTutorial.cpp).]. The compilation process via CMake is the similar to [`apps/tutorials/ospTutorialFindospray/`](https://github.com/ospray/ospray/tree/master/apps/ospTutorial/ospTutorialFindospray), with the addition of finding and linking MPI. To build the tutorial on Linux, build it in a build directory with mpicc -std=c99 ../modules/mpi/tutorials/ospMPIDistribTutorial.c \ -I ../ospray/include -L . -lospray -Wl,-rpath,. -o ospMPIDistribTutorial On Windows build it can be build manually in a "build_directory\\$Configuration" directory with cl ..\..\modules\mpi\tutorials\ospMPIDistribTutorial.c -I ..\..\ospray\include -I ..\.. ospray.lib The MPI module does not need to be linked explicitly, as it is loaded as a module at runtime. ![The first frame output by the `ospMPIDistribTutorial` or C++ tutorial with 4 ranks.][imgMPIDistribTutorial1] ![The accumulated frame output by the `ospMPIDistribTutorial` or C++ tutorial with 4 ranks.][imgMPIDistribTutorial2] ospMPIDistribTutorialSpheres and ospMPIDistribTutorialVolume ------------------------------------------------------------ The spheres and volume distributed tutorials are built as part of the MPI tutorials when building OSPRay with the MPI module and tutorials enabled. These tutorials demonstrate using OSPRay to render distributed data sets where each rank owns some subregion of the data, and displaying the output in an interactive window. The domain is distributed in a grid among the processes, each of which will generate a subset of the data corresponding to its subdomain. In `ospMPIDistribTutorialSpheres`, each process generates a set of spheres within its assigned domain. The spheres are colored from dark to light blue, where lighter colors correspond to higher ranks. ![Running `ospMPIDistribTutorialSpheres` on 4 ranks.][imgMPIDistribTutorialSpheres] In `ospMPIDistribTutorialVolume`, each process generates a subbrick of volume data, which is colored by its rank. ![Running `ospMPIDistribTutorialVolume` on 4 ranks.][imgMPIDistribTutorialVolume] ospMPIDistribTutorialPartialRepl -------------------------------- The partially replicated MPI tutorial demonstrates how to use OSPRay's distributed rendering capabilities to render data sets that are partially replicated among the processes. Each pair of ranks generates the same volume brick, allowing them to subdivide the rendering workload between themselves. For example, when run with two ranks, each will generate the same brick and be responsible for rendering half of the image tiles it projects to. When run with four ranks, the pairs of ranks 0,1 and 2,3 will generate the same data and divide the rendering workload for that data among themselves. The image work subdivision happens automatically, based on which ranks specify the same bounding box for their data, as demonstrated in the tutorial. The partially replicated distribution is useful to support load-balanced rendering of data sets that are too large to be fully replicated among the processes, but are small enough to be partially replicated among them. ospMPIDistribTutorialReplicated ------------------------------- The replicated MPI tutorial demonstrates how OSPRay's distributed rendering capabilities can be used to render data sets that are fully replicated among the ranks with advanced illumination effects. In this case, although the processes are run MPI parallel, each rank specifies the exact same data. OSPRay's MPI parallel renderer will detect that the data is replicated in this case and use the same image-parallel rendering algorithms employed in the MPI offload rendering configuration to render the data. This image-parallel rendering algorithm supports all rendering configurations that are used in local rendering, e.g., path tracing, to provide high-quality images. The replicated MPI tutorial supports the same scenes and parameters as the [`ospExamples`][ospExamples] app described above. This mode can be useful when high-quality rendering is desired and it is possible to copy the entire data set on to each rank, or to accelerate loading of a large model by leveraging a parallel file system. RenderKit-ospray-f2a61c2/doc/webtemplate.html000066400000000000000000000044361456566705700213220ustar00rootroot00000000000000 Intel OSPRay$if(select_downloads)$ Download$endif$$if(select_documentation)$ Documentation$endif$$if(select_tutorials)$ Tutorials$endif$$if(select_gallery)$ Gallery$endif$$if(select_related_projects)$ – RelatedProjects$endif$ $if(highlighting-css)$ $endif$ $if(select_index)$ $endif$ $if(toc)$ $endif$
$body$
$if(select_legal)$ $else$ $endif$ RenderKit-ospray-f2a61c2/modules/000077500000000000000000000000001456566705700170175ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/CMakeLists.txt000066400000000000000000000005171456566705700215620ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 add_subdirectory(cpu) if(OSPRAY_MODULE_CPU) get_target_property(OSPRAY_CPU_MODULE_INCLUDE_DIRS ospray_module_cpu INTERFACE_INCLUDE_DIRECTORIES) include_directories_ispc(${OSPRAY_CPU_MODULE_INCLUDE_DIRS}) endif() add_all_subdirectories_except(cpu) RenderKit-ospray-f2a61c2/modules/cpu/000077500000000000000000000000001456566705700176065ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/CMakeLists.txt000066400000000000000000000345071456566705700223570ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 option(OSPRAY_MODULE_CPU "Build the CPU module" ON) mark_as_advanced(OSPRAY_MODULE_CPU) cmake_dependent_option( OSPRAY_MODULE_GPU "Build the GPU module (beta)" OFF EMBREE_SYCL_SUPPORT OFF ) if ((NOT OSPRAY_MODULE_CPU) AND (NOT OSPRAY_MODULE_GPU)) return() endif() # ------------------------------------------------------- # Setup module include directories and source files # ------------------------------------------------------- set(OSPRAY_CPP_SOURCES ${OSPRAY_RESOURCE} ModuleInit.cpp ispc_tasksys.cpp ispc_tasksys.h ISPCDevice.h ISPCDevice.cpp common/Data.cpp common/Future.cpp common/Group.cpp common/Instance.cpp common/MotionTransform.cpp common/World.cpp fb/FrameBuffer.cpp fb/LocalFB.cpp fb/SparseFB.cpp fb/FrameOp.cpp fb/TaskError.cpp fb/registration.cpp fb/frame_ops/Blur.cpp fb/frame_ops/ColorConversion.cpp fb/frame_ops/Debug.cpp fb/frame_ops/ToneMapper.cpp fb/frame_ops/Variance.cpp pf/PixelFilter.cpp camera/Camera.cpp camera/PerspectiveCamera.cpp camera/OrthographicCamera.cpp camera/PanoramicCamera.cpp camera/registration.cpp geometry/Geometry.cpp geometry/GeometricModel.cpp geometry/Boxes.cpp geometry/Curves.cpp geometry/Spheres.cpp geometry/Planes.cpp geometry/Mesh.cpp geometry/registration.cpp lights/Light.cpp lights/AmbientLight.cpp lights/DirectionalLight.cpp lights/PointLight.cpp lights/IntensityDistribution.cpp lights/SpotLight.cpp lights/QuadLight.cpp lights/CylinderLight.cpp lights/HDRILight.cpp lights/SunSkyLight.cpp lights/sky_model/sky_model.cpp lights/registration.cpp math/spectrum.h math/halton.cpp math/sobol.cpp math/MathConstants.cpp math/Distribution2D.cpp render/LoadBalancer.cpp render/Material.cpp render/Renderer.cpp render/registration.cpp render/debug/DebugRenderer.cpp render/ao/AORenderer.cpp render/scivis/SciVis.cpp render/scivis/SciVisData.cpp render/pathtracer/PathTracer.cpp render/pathtracer/PathTracerData.cpp render/materials/OBJ.cpp render/materials/Principled.cpp render/materials/CarPaint.cpp render/materials/Velvet.cpp render/materials/Metal.cpp render/materials/Alloy.cpp render/materials/ThinGlass.cpp render/materials/Glass.cpp render/materials/MetallicPaint.cpp render/materials/Plastic.cpp render/materials/Luminous.cpp render/materials/Mix.cpp render/bsdfs/MicrofacetAlbedoTables.cpp texture/Texture.cpp texture/Texture2D.cpp texture/registration.cpp ) set(OSPRAY_ISPC_SOURCES ISPCDevice.ispc common/World.ispc fb/FrameBufferDispatch.ispc fb/LocalFB.ispc fb/SparseFB.ispc fb/frame_ops/Blur.ispc fb/frame_ops/ColorConversion.ispc fb/frame_ops/Debug.ispc fb/frame_ops/ToneMapper.ispc fb/frame_ops/Variance.ispc pf/PixelFilterDispatch.ispc pf/LUTPixelFilter.ispc camera/CameraDispatch.ispc camera/PerspectiveCamera.ispc camera/OrthographicCamera.ispc camera/PanoramicCamera.ispc geometry/GeometryDispatch.ispc geometry/GeometricModel.ispc geometry/Boxes.ispc geometry/Curves.ispc geometry/Spheres.ispc geometry/Planes.ispc geometry/Mesh.ispc lights/LightDispatch.ispc lights/Light.ispc lights/AmbientLight.ispc lights/DirectionalLight.ispc lights/PointLight.ispc lights/SpotLight.ispc lights/QuadLight.ispc lights/CylinderLight.ispc lights/HDRILight.ispc math/Distribution1D.ispc math/Distribution2D.ispc math/spectrum.ispc render/Material.ispc render/MaterialDispatch.ispc render/Renderer.ispc render/util.ispc render/debug/DebugRenderer.ispc render/ao/AORenderer.ispc render/ao/surfaces.ispc render/scivis/SciVis.ispc render/scivis/surfaces.ispc render/scivis/lightAlpha.ispc render/pathtracer/PathTracer.ispc render/pathtracer/PathSampler.ispc render/pathtracer/GeometryLight.ispc render/pathtracer/VirtualLight.ispc render/pathtracer/TransparentShadow.ispc render/pathtracer/ShadowCatcher.ispc render/pathtracer/NextEventEstimation.ispc render/bsdfs/BSDF.ispc render/bsdfs/MicrofacetAlbedoTables.ispc render/materials/OBJ.ispc render/materials/Principled.ispc render/materials/CarPaint.ispc render/materials/Velvet.ispc render/materials/Metal.ispc render/materials/Alloy.ispc render/materials/ThinGlass.ispc render/materials/Glass.ispc render/materials/MetallicPaint.ispc render/materials/Plastic.ispc render/materials/Luminous.ispc render/materials/Mix.ispc texture/TextureDispatch.ispc texture/Texture2D.ispc ) if (OSPRAY_ENABLE_VOLUMES) set(OSPRAY_VOLUMES_CPP_SOURCES geometry/Isosurfaces.cpp texture/TextureVolume.cpp volume/Volume.cpp volume/VolumetricModel.cpp volume/transferFunction/LinearTransferFunction.cpp volume/transferFunction/TransferFunction.cpp volume/transferFunction/registration.cpp ) set(OSPRAY_VOLUMES_ISPC_SOURCES geometry/Isosurfaces.ispc render/ao/volumes.ispc render/scivis/volumes.ispc render/pathtracer/volumes/VolumeSampler.ispc texture/TextureVolume.ispc volume/Volume.ispc volume/transferFunction/LinearTransferFunction.ispc volume/transferFunction/TransferFunctionDispatch.ispc ) endif() ############################################################## # Build ISPC device ############################################################## ## Windows-specifc ISPC symbol exports ## if (WIN32) file(READ def_header.txt OSPRAY_DEF) file(READ ispc_symbols.txt OSPRAY_ISPC_SYMBOLS_IN) if (OSPRAY_ENABLE_VOLUMES) file(READ ispc_symbols_volume.txt OSPRAY_ISPC_SYMBOLS_VOLUME) list(APPEND OSPRAY_ISPC_SYMBOLS_IN ${OSPRAY_ISPC_SYMBOLS_VOLUME}) endif() list(LENGTH OSPRAY_ISPC_TARGET_LIST NUM_TARGETS) foreach(isa ${OSPRAY_ISPC_TARGET_LIST}) string(REPLACE "-i32x16" "" isa ${isa}) # strip avx512skx-i32x16 if (NUM_TARGETS EQUAL 1) set(isa "") # for single target no suffix endif() # add isa suffix string(REPLACE "," "${isa}" OSPRAY_ISPC_SYMBOLS ${OSPRAY_ISPC_SYMBOLS_IN}) string(APPEND OSPRAY_DEF ${OSPRAY_ISPC_SYMBOLS}) endforeach() file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/ospray_module_cpu.def.in "${OSPRAY_DEF}") # changes .def only if content changed, avoids unnecessary re-linking configure_file(${CMAKE_CURRENT_BINARY_DIR}/ospray_module_cpu.def.in ospray_module_cpu.def COPYONLY) set(OSPRAY_ISPC_DEF ospray_module_cpu.def) endif() ## ISPC Device-specific options ## set(OSPRAY_TILE_SIZE 64 CACHE STRING "Tile size (x,y dimensions)") set_property(CACHE OSPRAY_TILE_SIZE PROPERTY STRINGS 8 16 32 64 128 256 512) mark_as_advanced(OSPRAY_TILE_SIZE) set(OSPRAY_RENDER_TASK_SIZE 8 CACHE STRING "Render task size (x,y dimensions). 8 is the default, -1 indicates to use a SIMD-width render task size determined at runtime. Must be less than OSPRAY_TILE_SIZE.") set_property(CACHE OSPRAY_RENDER_TASK_SIZE PROPERTY STRINGS -1 2 4 8 16 32 64) mark_as_advanced(OSPRAY_RENDER_TASK_SIZE) if (WIN32) set(TILE_STACK_DEFAULT_SIZE 64) elseif (APPLE) set(TILE_STACK_DEFAULT_SIZE 32) else () set(TILE_STACK_DEFAULT_SIZE 128) endif() set(OSPRAY_MAX_STACK_TILE_SIZE ${TILE_STACK_DEFAULT_SIZE} CACHE STRING "Max size for tile to remain allocated on the stack") set_property(CACHE OSPRAY_MAX_STACK_TILE_SIZE PROPERTY STRINGS 8 16 32 64 128 256 512) mark_as_advanced(OSPRAY_MAX_STACK_TILE_SIZE) configure_file(common/OSPConfig.h.in ${PROJECT_BINARY_DIR}/OSPConfig.h) install(FILES ${CMAKE_BINARY_DIR}/OSPConfig.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ospray/SDK COMPONENT devel ) ## Build the module ## if (OSPRAY_MODULE_CPU) include_directories_ispc( ${PROJECT_SOURCE_DIR}/ospray/include ${PROJECT_SOURCE_DIR}/ospray ${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR} ${RKCOMMON_INCLUDE_DIRS} ${EMBREE_INCLUDE_DIRS} ) add_definitions_ispc( -DOSPRAY_BEGIN_ISPC_NAMESPACE= -DOSPRAY_END_ISPC_NAMESPACE= -DSYCL_EXTERNAL= ) if (OSPRAY_ENABLE_VOLUMES) include_directories_ispc( ${OPENVKL_INCLUDE_DIRS} ) # Keep the NOTFOUND out of the ISPC include dirs list, because CMake will # see the variable ending with NOTFOUND and evaluate it to false and not # pass our include directories if (OPENVKL_CPU_DEVICE_INCLUDE_DIRS) include_directories_ispc( ${OPENVKL_CPU_DEVICE_INCLUDE_DIRS} ) endif() add_definitions_ispc( -DOSPRAY_ENABLE_VOLUMES ) endif() add_library(ospray_module_cpu SHARED) ispc_target_add_sources(ospray_module_cpu ${OSPRAY_CPP_SOURCES} ${OSPRAY_VOLUMES_CPP_SOURCES} ${OSPRAY_ISPC_SOURCES} ${OSPRAY_VOLUMES_ISPC_SOURCES} ${OSPRAY_ISPC_DEF} geometry/Subdivision.cpp geometry/Subdivision.ispc) ospray_install_library(ospray_module_cpu lib) target_link_libraries(ospray_module_cpu PUBLIC ospray rkcommon::rkcommon $ $ ) target_include_directories(ospray_module_cpu PUBLIC $ $ $ $ $ $ # NOTE(jda) - the following includes are missing despite PUBLIC linking $ $ ####################################################################### $ $ ) target_compile_definitions(ospray_module_cpu PUBLIC TILE_SIZE=${OSPRAY_TILE_SIZE} MAX_TILE_SIZE=${OSPRAY_MAX_STACK_TILE_SIZE} SYCL_EXTERNAL= ) if (OSPRAY_ENABLE_VOLUMES) target_link_libraries(ospray_module_cpu PUBLIC $ $ ) target_include_directories(ospray_module_cpu PUBLIC $ ) target_compile_definitions(ospray_module_cpu PUBLIC OSPRAY_ENABLE_VOLUMES ) endif() endif() if (OSPRAY_MODULE_GPU) if (WIN32) cmake_minimum_required(VERSION 3.25) else() cmake_minimum_required(VERSION 3.20.5) endif() include(${ISPCRT_DIR}/interop.cmake) # Have CMake's build infrastructure treat the ISPC files as C++ for SYCL set_source_files_properties(${OSPRAY_ISPC_SOURCES} ${OSPRAY_VOLUMES_ISPC_SOURCES} PROPERTIES LANGUAGE CXX) add_library(ospray_module_gpu_kernels OBJECT ${OSPRAY_ISPC_SOURCES} ${OSPRAY_VOLUMES_ISPC_SOURCES} ) ospray_add_sycl_target(ospray_module_gpu_kernels) target_link_libraries(ospray_module_gpu_kernels PUBLIC ospray rkcommon::rkcommon $ $ ) target_include_directories(ospray_module_gpu_kernels PUBLIC $ $ $ $ $ $ # NOTE(jda) - the following includes are missing despite PUBLIC linking $ $ ####################################################################### $ $ ) target_compile_definitions(ospray_module_gpu_kernels PUBLIC TILE_SIZE=${OSPRAY_TILE_SIZE} MAX_TILE_SIZE=${OSPRAY_MAX_STACK_TILE_SIZE} RKCOMMON_NO_SIMD ) if (OSPRAY_COMPILER_NEEDS_X_CPP) target_compile_options(ospray_module_gpu_kernels PRIVATE -x c++) endif() target_compile_options(ospray_module_gpu_kernels PRIVATE -g0 # XXX debug on device broken -Wdouble-promotion ) target_compile_definitions(ospray_module_gpu_kernels PUBLIC OSPRAY_TARGET_SYCL OSPRAY_BEGIN_ISPC_NAMESPACE=namespace\ ispc{ OSPRAY_END_ISPC_NAMESPACE=} _ALLOW_KEYWORD_MACROS # avoid error when redefining reserved keywords like "export" uniform= varying= unmasked= export= rtcIntersectV=rtcIntersect1 rtcOccludedV=rtcOccluded1 rtcInterpolateV1=rtcInterpolate1 vklComputeSampleV=vklComputeSample vklComputeGradientV=vklComputeGradient vklInitIntervalIteratorV=vklInitIntervalIterator vklIterateIntervalV=vklIterateInterval vklInitHitIteratorV=vklInitHitIterator vklIterateHitV=vklIterateHit programCount=1 programIndex=0 ) if (OSPRAY_ENABLE_VOLUMES) target_link_libraries(ospray_module_gpu_kernels PUBLIC $ $ ) target_include_directories(ospray_module_gpu_kernels PUBLIC $ ) target_compile_definitions(ospray_module_gpu_kernels PUBLIC OSPRAY_ENABLE_VOLUMES ) endif() # Install and export without DESTINATION to turn it into INTERFACE library install(TARGETS ospray_module_gpu_kernels EXPORT ospray_Exports) add_library(ospray_module_gpu SHARED ${OSPRAY_CPP_SOURCES} ${OSPRAY_VOLUMES_CPP_SOURCES} ) target_link_libraries(ospray_module_gpu PUBLIC ospray_module_gpu_kernels ) ospray_install_library(ospray_module_gpu gpu) endif() # ------------------------------------------------------- # Install SDK headers # ------------------------------------------------------- get_subdirectories(SUBDIRS ${CMAKE_CURRENT_LIST_DIR}) foreach(dir . ${SUBDIRS}) install(DIRECTORY ${dir} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ospray/SDK/modules/cpu COMPONENT devel FILES_MATCHING PATTERN *.h PATTERN *.ih ) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${dir} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ospray/SDK/modules/cpu COMPONENT devel FILES_MATCHING PATTERN *_ispc.h ) endforeach() ############################################################## # Additional interface targets ############################################################## add_library(ospray_sdk INTERFACE) target_link_libraries(ospray_sdk INTERFACE ospray rkcommon::rkcommon ) ospray_install_target(ospray_sdk devel) RenderKit-ospray-f2a61c2/modules/cpu/ISPCDevice.cpp000066400000000000000000000535361456566705700222040ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_TARGET_SYCL #include #endif // ospray #include "ISPCDevice.h" #include "camera/Camera.h" #include "common/Data.h" #include "common/Group.h" #include "common/Instance.h" #include "common/Library.h" #include "common/World.h" #include "fb/ImageOp.h" #include "fb/LocalFB.h" #include "geometry/GeometricModel.h" #include "ispc_tasksys.h" #include "lights/Light.h" #include "render/LoadBalancer.h" #include "render/Material.h" #ifdef OSPRAY_TARGET_SYCL #include "render/RenderTaskSycl.h" #else #include "render/RenderTask.h" #endif #include "render/Renderer.h" #include "texture/Texture.h" #include "texture/Texture2D.h" #ifdef OSPRAY_ENABLE_VOLUMES #include "volume/VolumetricModel.h" #include "volume/transferFunction/TransferFunction.h" #endif // stl #include #include #include #include "rkcommon/tasking/tasking_system_init.h" #include "rkcommon/utility/CodeTimer.h" #ifndef OSPRAY_TARGET_SYCL #include "ISPCDevice_ispc.h" #endif namespace ospray { namespace api { using SetParamFcn = void(OSPObject, const char *, const void *); template static void setParamOnObject(OSPObject _obj, const char *p, const T &v) { auto *obj = (ManagedObject *)_obj; obj->setParam(p, v); } #define declare_param_setter(TYPE) \ { \ OSPTypeFor::value, [](OSPObject o, const char *p, const void *v) { \ setParamOnObject(o, p, *(TYPE *)v); \ } \ } #define declare_param_setter_object(TYPE) \ { \ OSPTypeFor::value, [](OSPObject o, const char *p, const void *v) { \ ManagedObject *obj = *(TYPE *)v; \ setParamOnObject(o, p, obj); \ } \ } #define declare_param_setter_string(TYPE) \ { \ OSPTypeFor::value, [](OSPObject o, const char *p, const void *v) { \ const char *str = (const char *)v; \ setParamOnObject(o, p, std::string(str)); \ } \ } static std::map> setParamFcns = { declare_param_setter(Device *), declare_param_setter(void *), declare_param_setter(bool), declare_param_setter_object(ManagedObject *), declare_param_setter_object(Camera *), declare_param_setter_object(Data *), declare_param_setter_object(FrameBuffer *), declare_param_setter_object(Future *), declare_param_setter_object(Geometry *), declare_param_setter_object(GeometricModel *), declare_param_setter_object(Group *), declare_param_setter_object(ImageOp *), declare_param_setter_object(Instance *), declare_param_setter_object(Light *), declare_param_setter_object(Material *), declare_param_setter_object(Renderer *), declare_param_setter_object(Texture *), #ifdef OSPRAY_ENABLE_VOLUMES declare_param_setter_object(TransferFunction *), declare_param_setter_object(Volume *), declare_param_setter_object(VolumetricModel *), #endif declare_param_setter_object(World *), declare_param_setter_string(const char *), declare_param_setter(char *), declare_param_setter(char), declare_param_setter(vec2c), declare_param_setter(vec3c), declare_param_setter(vec4c), declare_param_setter(unsigned char), declare_param_setter(vec2uc), declare_param_setter(vec3uc), declare_param_setter(vec4uc), declare_param_setter(short), declare_param_setter(vec2s), declare_param_setter(vec3s), declare_param_setter(vec4s), declare_param_setter(unsigned short), declare_param_setter(vec2us), declare_param_setter(vec3us), declare_param_setter(vec4us), declare_param_setter(int), declare_param_setter(vec2i), declare_param_setter(vec3i), declare_param_setter(vec4i), declare_param_setter(unsigned int), declare_param_setter(vec2ui), declare_param_setter(vec3ui), declare_param_setter(vec4ui), declare_param_setter(int64_t), declare_param_setter(vec2l), declare_param_setter(vec3l), declare_param_setter(vec4l), declare_param_setter(uint64_t), declare_param_setter(vec2ul), declare_param_setter(vec3ul), declare_param_setter(vec4ul), declare_param_setter(float), declare_param_setter(vec2f), declare_param_setter(vec3f), declare_param_setter(vec4f), declare_param_setter(double), declare_param_setter(vec2d), declare_param_setter(vec3d), declare_param_setter(vec4d), declare_param_setter(box1i), declare_param_setter(box2i), declare_param_setter(box3i), declare_param_setter(box4i), declare_param_setter(box1f), declare_param_setter(box2f), declare_param_setter(box3f), declare_param_setter(box4f), declare_param_setter(linear2f), declare_param_setter(linear3f), declare_param_setter(affine2f), declare_param_setter(affine3f)}; #undef declare_param_setter ISPCDevice::ISPCDevice() : loadBalancer(std::make_shared()) { #if (defined(__APPLE__) || defined(MACOSX) || defined(__MACOSX__)) \ && (defined(__x86_64__) || defined(__ia64__) || defined(_M_X64)) // trigger enabling AVX512, see e.g. https://github.com/ispc/ispc/issues/1854 float vf[16]; float f = ispc::ISPCDevice_dummyCompute(vf); #endif } ISPCDevice::~ISPCDevice() { try { if (embreeDevice) { rtcReleaseDevice(embreeDevice); } } catch (...) { // silently move on, sometimes a pthread mutex lock fails in Embree } #ifdef OSPRAY_ENABLE_VOLUMES if (vklDevice) { vklReleaseDevice(vklDevice); } #endif } static void embreeErrorFunc(void *, const RTCError code, const char *str) { postStatusMsg() << "#osp: Embree internal error " << code << " : " << str; OSPError e = (code > RTC_ERROR_UNSUPPORTED_CPU) ? OSP_UNKNOWN_ERROR : (OSPError)code; handleError(e, "Embree internal error '" + std::string(str) + "'"); } #ifdef OSPRAY_ENABLE_VOLUMES static void vklErrorFunc(void *, const VKLError code, const char *str) { postStatusMsg() << "#osp: Open VKL internal error " << code << " : " << str; OSPError e = (code > VKL_UNSUPPORTED_CPU) ? OSP_UNKNOWN_ERROR : (OSPError)code; handleError(e, "Open VKL internal error '" + std::string(str) + "'"); } #endif void ISPCDevice::commit() { Device::commit(); if (!userContext) { #ifdef OSPRAY_TARGET_SYCL sycl::context *appSyclCtx = static_cast(getParam("syclContext", nullptr)); sycl::device *appSyclDevice = static_cast(getParam("syclDevice", nullptr)); if ((appSyclCtx && !appSyclDevice) || (!appSyclCtx && appSyclDevice)) { handleError(OSP_INVALID_OPERATION, "OSPRay ISPCDevice invalid configuration: if providing a syclContext and syclDevice both must be provided"); return; } ze_context_handle_t appZeCtx = static_cast( getParam("zeContext", nullptr)); ze_device_handle_t appZeDevice = static_cast(getParam("zeDevice", nullptr)); if ((appZeCtx && !appZeDevice) || (!appZeCtx && appZeDevice)) { handleError(OSP_INVALID_OPERATION, "OSPRay ISPCDevice invalid configuration: if providing a zeContext and zeDevice both must be provided"); return; } if (appSyclCtx && appZeCtx) { handleError(OSP_INVALID_OPERATION, "OSPRay ISPCDevice invalid configuration: For SYCL or Level Zero context interopability only a SYCL or Level Zero context & device can be provided, not both."); return; } // If we got a SYCL context just get the native handles and set the "app" L0 // context/device to them, since we can take the same code path from there if (appSyclCtx) { appZeCtx = sycl::get_native(*appSyclCtx); appZeDevice = sycl::get_native( *appSyclDevice); } const bool newContext = appZeCtx || !ispcrtContext; if (appZeCtx) { userContext = true; ispcrtContext = ispcrt::Context( ISPCRT_DEVICE_TYPE_GPU, (ISPCRTGenericHandle)appZeCtx); ispcrtDevice = ispcrt::Device(ispcrtContext, (ISPCRTGenericHandle)appZeDevice); } else if (!ispcrtContext) { // internally, from Multidevice GPU ispcrt::Context *ispcrtContextPtr = static_cast( getParam("ispcrtContext", nullptr)); ispcrt::Device *ispcrtDevicePtr = static_cast( getParam("ispcrtDevice", nullptr)); if (ispcrtContextPtr != nullptr && ispcrtDevicePtr != nullptr) { ispcrtContext = *ispcrtContextPtr; ispcrtDevice = *ispcrtDevicePtr; } else { ispcrtContext = ispcrt::Context(ISPCRT_DEVICE_TYPE_GPU); ispcrtDevice = ispcrt::Device(ispcrtContext); } } if (newContext) { syclPlatform = appSyclCtx ? appSyclCtx->get_platform() : sycl::ext::oneapi::level_zero::make_platform( reinterpret_cast( ispcrtDevice.nativePlatformHandle())); syclDevice = sycl::ext::oneapi::level_zero::make_device(syclPlatform, reinterpret_cast( ispcrtDevice.nativeDeviceHandle())); syclContext = sycl::ext::oneapi::level_zero::make_context( std::vector{syclDevice}, reinterpret_cast( ispcrtDevice.nativeContextHandle()), true); syclQueue = sycl::queue(syclContext, syclDevice, {sycl::property::queue::enable_profiling(), sycl::property::queue::in_order()}); if (embreeDevice) { rtcReleaseDevice(embreeDevice); embreeDevice = nullptr; } #ifdef OSPRAY_ENABLE_VOLUMES if (vklDevice) { vklReleaseDevice(vklDevice); vklDevice = nullptr; } #endif } #else userContext = true; // on CPU there is no other choice ispcrtContext = ispcrt::Context(ISPCRT_DEVICE_TYPE_CPU); ispcrtDevice = ispcrt::Device(ispcrtContext); #endif ispcrtQueue = ispcrt::TaskQueue(ispcrtDevice); } setIspcrtTaskingCallbacks(); if (!embreeDevice) { #ifdef OSPRAY_TARGET_SYCL embreeDevice = rtcNewSYCLDevice(syclContext, generateEmbreeDeviceCfg(*this).c_str()); rtcSetDeviceSYCLDevice(embreeDevice, syclDevice); #else embreeDevice = rtcNewDevice(generateEmbreeDeviceCfg(*this).c_str()); #endif rtcSetDeviceErrorFunction(embreeDevice, embreeErrorFunc, nullptr); RTCError erc = rtcGetDeviceError(embreeDevice); if (erc != RTC_ERROR_NONE) { // why did the error function not get called !? postStatusMsg() << "#osp:init: embree internal error number " << erc; throw std::runtime_error("failed to initialize Embree"); } } #ifdef OSPRAY_ENABLE_VOLUMES if (!vklDevice) { vklInit(); #ifdef OSPRAY_TARGET_SYCL vklDevice = vklNewDevice("gpu"); vklDeviceSetVoidPtr( vklDevice, "syclContext", static_cast(&syclContext)); #else int cpu_width = ispc::ISPCDevice_programCount(); switch (cpu_width) { case 4: vklDevice = vklNewDevice("cpu_4"); break; case 8: vklDevice = vklNewDevice("cpu_8"); break; case 16: vklDevice = vklNewDevice("cpu_16"); break; default: vklDevice = vklNewDevice("cpu"); break; } #endif vklDeviceSetErrorCallback(vklDevice, vklErrorFunc, nullptr); vklDeviceSetLogCallback( vklDevice, [](void *, const char *message) { postStatusMsg(OSP_LOG_INFO) << message; }, nullptr); vklDeviceSetInt(vklDevice, "logLevel", logLevel); vklDeviceSetInt(vklDevice, "numThreads", numThreads); vklCommitDevice(vklDevice); } #endif #ifndef OSPRAY_TARGET_SYCL // Output device info string const char *isaNames[] = { "unknown", "SSE2", "SSE4", "AVX", "AVX2", "AVX512SKX", "NEON"}; postStatusMsg(OSP_LOG_INFO) << "Using ISPC device with " << isaNames[ispc::ISPCDevice_isa()] << " instruction set"; #else postStatusMsg(OSP_LOG_INFO) << "Using SYCL GPU device on " << syclDevice.get_info() << " device"; #endif } /////////////////////////////////////////////////////////////////////////// // Device Implementation ////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// int ISPCDevice::loadModule(const char *name) { return loadLocalModule(name); } /////////////////////////////////////////////////////////////////////////// // OSPRay Data Arrays ///////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// OSPData ISPCDevice::newSharedData(const void *sharedData, OSPDataType type, const vec3ul &numItems, const vec3l &byteStride, OSPDeleterCallback freeFunction, const void *userPtr) { return (OSPData) new Data( *this, sharedData, type, numItems, byteStride, freeFunction, userPtr); } OSPData ISPCDevice::newData(OSPDataType type, const vec3ul &numItems) { return (OSPData) new Data(*this, type, numItems); } void ISPCDevice::copyData( const OSPData source, OSPData destination, const vec3ul &destinationIndex) { Data *dst = (Data *)destination; dst->copy(*(Data *)source, destinationIndex); } /////////////////////////////////////////////////////////////////////////// // Renderable Objects ///////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// OSPLight ISPCDevice::newLight(const char *type) { return (OSPLight)Light::createInstance(type, *this); } OSPCamera ISPCDevice::newCamera(const char *type) { return (OSPCamera)Camera::createInstance(type, *this); } OSPGeometry ISPCDevice::newGeometry(const char *type) { return (OSPGeometry)Geometry::createInstance(type, *this); } OSPVolume ISPCDevice::newVolume(const char *type) { #ifdef OSPRAY_ENABLE_VOLUMES return (OSPVolume) new Volume(*this, type); #else (void)type; return (OSPVolume) nullptr; #endif } OSPGeometricModel ISPCDevice::newGeometricModel(OSPGeometry _geom) { auto *geom = (Geometry *)_geom; auto *model = new GeometricModel(*this, geom); return (OSPGeometricModel)model; } OSPVolumetricModel ISPCDevice::newVolumetricModel(OSPVolume _volume) { #ifdef OSPRAY_ENABLE_VOLUMES auto *volume = (Volume *)_volume; auto *model = new VolumetricModel(*this, volume); return (OSPVolumetricModel)model; #else (void)_volume; return (OSPVolumetricModel) nullptr; #endif } /////////////////////////////////////////////////////////////////////////// // Model Meta-Data //////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// OSPMaterial ISPCDevice::newMaterial(const char *material_type) { return (OSPMaterial)Material::createInstance(material_type, *this); } OSPTransferFunction ISPCDevice::newTransferFunction(const char *type) { #ifdef OSPRAY_ENABLE_VOLUMES return (OSPTransferFunction)TransferFunction::createInstance(type, *this); #else (void)type; return (OSPTransferFunction) nullptr; #endif } OSPTexture ISPCDevice::newTexture(const char *type) { return (OSPTexture)Texture::createInstance(type, *this); } /////////////////////////////////////////////////////////////////////////// // Instancing ///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// OSPGroup ISPCDevice::newGroup() { return (OSPGroup) new Group(*this); } OSPInstance ISPCDevice::newInstance(OSPGroup _group) { auto *group = (Group *)_group; auto *instance = new Instance(*this, group); return (OSPInstance)instance; } /////////////////////////////////////////////////////////////////////////// // Top-level Worlds /////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// OSPWorld ISPCDevice::newWorld() { return (OSPWorld) new World(*this); } box3f ISPCDevice::getBounds(OSPObject _obj) { auto *obj = (ManagedObject *)_obj; return obj->getBounds(); } /////////////////////////////////////////////////////////////////////////// // Object + Parameter Lifetime Management ///////////////////////////////// /////////////////////////////////////////////////////////////////////////// void ISPCDevice::setObjectParam( OSPObject object, const char *name, OSPDataType type, const void *mem) { if (type == OSP_UNKNOWN) throw std::runtime_error("cannot set OSP_UNKNOWN parameter type"); if (type == OSP_BYTE || type == OSP_RAW) { setParamOnObject(object, name, *(const byte_t *)mem); return; } setParamFcns[type](object, name, mem); } void ISPCDevice::removeObjectParam(OSPObject _object, const char *name) { ManagedObject *object = (ManagedObject *)_object; ManagedObject *existing = object->getParamObject(name); if (existing) existing->refDec(); object->removeParam(name); } void ISPCDevice::commit(OSPObject _object) { ManagedObject *object = (ManagedObject *)_object; object->commit(); object->checkUnused(); object->resetAllParamQueryStatus(); } void ISPCDevice::release(OSPObject _obj) { ManagedObject *obj = (ManagedObject *)_obj; obj->refDec(); } void ISPCDevice::retain(OSPObject _obj) { ManagedObject *obj = (ManagedObject *)_obj; obj->refInc(); } /////////////////////////////////////////////////////////////////////////// // FrameBuffer Manipulation /////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// OSPFrameBuffer ISPCDevice::frameBufferCreate( const vec2i &size, const OSPFrameBufferFormat mode, const uint32 channels) { FrameBuffer::ColorBufferFormat colorBufferFormat = mode; FrameBuffer *fb = new LocalFrameBuffer(*this, size, colorBufferFormat, channels); return (OSPFrameBuffer)fb; } OSPImageOperation ISPCDevice::newImageOp(const char *type) { ospray::ImageOp *ret = ImageOp::createImageOp(type, *this); return (OSPImageOperation)ret; } const void *ISPCDevice::frameBufferMap( OSPFrameBuffer _fb, OSPFrameBufferChannel channel) { FrameBuffer *fb = (FrameBuffer *)_fb; return fb->mapBuffer(channel); } void ISPCDevice::frameBufferUnmap(const void *mapped, OSPFrameBuffer _fb) { FrameBuffer *fb = (FrameBuffer *)_fb; fb->unmap(mapped); } float ISPCDevice::getVariance(OSPFrameBuffer _fb) { FrameBuffer *fb = (FrameBuffer *)_fb; return fb->getVariance(); } void ISPCDevice::resetAccumulation(OSPFrameBuffer _fb) { FrameBuffer *fb = (FrameBuffer *)_fb; fb->clear(); } /////////////////////////////////////////////////////////////////////////// // Frame Rendering //////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// OSPRenderer ISPCDevice::newRenderer(const char *type) { return (OSPRenderer)Renderer::createInstance(type, *this); } OSPFuture ISPCDevice::renderFrame(OSPFrameBuffer _fb, OSPRenderer _renderer, OSPCamera _camera, OSPWorld _world) { FrameBuffer *fb = (FrameBuffer *)_fb; Renderer *renderer = (Renderer *)_renderer; Camera *camera = (Camera *)_camera; World *world = (World *)_world; #ifndef OSPRAY_TARGET_SYCL fb->setCompletedEvent(OSP_NONE_FINISHED); fb->refInc(); renderer->refInc(); camera->refInc(); world->refInc(); return (OSPFuture) new RenderTask(fb, [=]() { utility::CodeTimer timer; timer.start(); loadBalancer->renderFrame(fb, renderer, camera, world); timer.stop(); fb->refDec(); renderer->refDec(); camera->refDec(); world->refDec(); return timer.seconds(); }); #else std::pair events = loadBalancer->renderFrame(fb, renderer, camera, world, false); return (OSPFuture) new RenderTask(events.first, events.second); #endif } int ISPCDevice::isReady(OSPFuture _task, OSPSyncEvent event) { auto *task = (Future *)_task; return task->isFinished(event); } void ISPCDevice::wait(OSPFuture _task, OSPSyncEvent event) { auto *task = (Future *)_task; task->wait(event); } void ISPCDevice::cancel(OSPFuture _task) { auto *task = (Future *)_task; return task->cancel(); } float ISPCDevice::getProgress(OSPFuture _task) { auto *task = (Future *)_task; return task->getProgress(); } float ISPCDevice::getTaskDuration(OSPFuture _task) { auto *task = (Future *)_task; return task->getTaskDuration(); } OSPPickResult ISPCDevice::pick(OSPFrameBuffer _fb, OSPRenderer _renderer, OSPCamera _camera, OSPWorld _world, const vec2f &screenPos) { FrameBuffer *fb = (FrameBuffer *)_fb; Renderer *renderer = (Renderer *)_renderer; Camera *camera = (Camera *)_camera; World *world = (World *)_world; return renderer->pick(fb, camera, world, screenPos); } #ifdef OSPRAY_TARGET_SYCL sycl::nd_range<1> ISPCDevice::computeDispatchRange( const size_t globalSize, const size_t workgroupSize) const { // roundedRange global size must be at least workgroupSize const size_t roundedRange = std::max(size_t(1), (globalSize + workgroupSize - 1) / workgroupSize) * workgroupSize; return sycl::nd_range<1>(roundedRange, workgroupSize); } #endif } // namespace api } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/ISPCDevice.h000066400000000000000000000133731456566705700216440ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray #include "Device.h" // ispcrt #include "ispcrt.hpp" // embree #include "common/Embree.h" #ifdef OSPRAY_ENABLE_VOLUMES // openvkl #include "openvkl/openvkl.h" // comment break to prevent clang-format from reordering openvkl includes #include "openvkl/device/openvkl.h" #endif /*! \file ISPCDevice.h Implements the "local" device for local rendering */ #ifdef OSPRAY_TARGET_SYCL namespace ispc { int ISPCDevice_programCount(); int ISPCDevice_isa(); } // namespace ispc #endif namespace ospray { struct LocalTiledLoadBalancer; #ifdef OSPRAY_TARGET_SYCL using AsyncEvent = sycl::event; #else struct AsyncEvent { }; #endif namespace api { struct OSPRAY_SDK_INTERFACE ISPCDevice : public Device { ISPCDevice(); virtual ~ISPCDevice() override; ///////////////////////////////////////////////////////////////////////// // ManagedObject Implementation ///////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// void commit() override; ///////////////////////////////////////////////////////////////////////// // Device Implementation //////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// int loadModule(const char *name) override; // OSPRay Data Arrays /////////////////////////////////////////////////// OSPData newSharedData(const void *sharedData, OSPDataType, const vec3ul &numItems, const vec3l &byteStride, OSPDeleterCallback, const void *userPtr) override; OSPData newData(OSPDataType, const vec3ul &numItems) override; void copyData(const OSPData source, OSPData destination, const vec3ul &destinationIndex) override; // Renderable Objects /////////////////////////////////////////////////// OSPLight newLight(const char *type) override; OSPCamera newCamera(const char *type) override; OSPGeometry newGeometry(const char *type) override; OSPVolume newVolume(const char *type) override; OSPGeometricModel newGeometricModel(OSPGeometry geom) override; OSPVolumetricModel newVolumetricModel(OSPVolume volume) override; // Model Meta-Data ////////////////////////////////////////////////////// OSPMaterial newMaterial(const char *material_type) override; OSPTransferFunction newTransferFunction(const char *type) override; OSPTexture newTexture(const char *type) override; // Instancing /////////////////////////////////////////////////////////// OSPGroup newGroup() override; OSPInstance newInstance(OSPGroup group) override; // Top-level Worlds ///////////////////////////////////////////////////// OSPWorld newWorld() override; box3f getBounds(OSPObject) override; // Object + Parameter Lifetime Management /////////////////////////////// void setObjectParam(OSPObject object, const char *name, OSPDataType type, const void *mem) override; void removeObjectParam(OSPObject object, const char *name) override; void commit(OSPObject object) override; void release(OSPObject _obj) override; void retain(OSPObject _obj) override; // FrameBuffer Manipulation ///////////////////////////////////////////// OSPFrameBuffer frameBufferCreate(const vec2i &size, const OSPFrameBufferFormat mode, const uint32 channels) override; OSPImageOperation newImageOp(const char *type) override; const void *frameBufferMap( OSPFrameBuffer fb, const OSPFrameBufferChannel) override; void frameBufferUnmap(const void *mapped, OSPFrameBuffer fb) override; float getVariance(OSPFrameBuffer) override; void resetAccumulation(OSPFrameBuffer _fb) override; // Frame Rendering ////////////////////////////////////////////////////// OSPRenderer newRenderer(const char *type) override; OSPFuture renderFrame( OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld) override; int isReady(OSPFuture, OSPSyncEvent) override; void wait(OSPFuture, OSPSyncEvent) override; void cancel(OSPFuture) override; float getProgress(OSPFuture) override; float getTaskDuration(OSPFuture) override; OSPPickResult pick( OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld, const vec2f &) override; std::shared_ptr loadBalancer; RTCDevice getEmbreeDevice() { return embreeDevice; } #ifdef OSPRAY_ENABLE_VOLUMES VKLDevice getVklDevice() { return vklDevice; } #endif ispcrt::Device &getIspcrtDevice() { return ispcrtDevice; } ispcrt::Context &getIspcrtContext() { return ispcrtContext; } ispcrt::TaskQueue &getIspcrtQueue() { return ispcrtQueue; } void *getPostProcessingCommandQueuePtr() override { #ifdef OSPRAY_TARGET_SYCL return &syclQueue; #else return nullptr; #endif } #ifdef OSPRAY_TARGET_SYCL sycl::queue &getSyclQueue() { return syclQueue; } /* Compute the rounded dispatch global size for the given work group size. * SYCL requires that globalSize % workgroupSize == 0, ths function will * round up globalSize and return nd_range(roundedSize, workgroupSize). * The kernel being launched must discard tasks that are out of bounds * bounds due to this rounding */ sycl::nd_range<1> computeDispatchRange( const size_t globalSize, const size_t workgroupSize) const; #endif private: ispcrt::Context ispcrtContext; ispcrt::Device ispcrtDevice; ispcrt::TaskQueue ispcrtQueue; RTCDevice embreeDevice = nullptr; #ifdef OSPRAY_ENABLE_VOLUMES VKLDevice vklDevice = nullptr; #endif #ifdef OSPRAY_TARGET_SYCL sycl::platform syclPlatform; sycl::device syclDevice; sycl::context syclContext; sycl::queue syclQueue; #endif bool userContext{false}; // app can set context only once }; } // namespace api } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/ISPCDevice.ispc000066400000000000000000000017501456566705700223470ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 OSPRAY_BEGIN_ISPC_NAMESPACE #ifdef OSPRAY_TARGET_SYCL int ISPCDevice_programCount() { // TODO: This should query the GPU width for ISPC, // But for SYCL we're in a scalar context, so just 1 program wide return 1; } int ISPCDevice_isa() { // TODO: GPU ISA/width detection // Not relevant for SYCL return 0; } #else export uniform int ISPCDevice_programCount() { return programCount; } export uniform int ISPCDevice_isa() { #if defined(ISPC_TARGET_SSE2) return 1; #elif defined(ISPC_TARGET_SSE4) return 2; #elif defined(ISPC_TARGET_AVX) return 3; #elif defined(ISPC_TARGET_AVX2) return 4; #elif defined(ISPC_TARGET_AVX512SKX) return 5; #elif defined(ISPC_TARGET_NEON) return 6; #else return 0; #endif } export uniform float ISPCDevice_dummyCompute(const float *uniform fp) { const float f = *((const varying float *uniform)fp); return reduce_add(f * f); } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/ISPCDeviceObject.h000066400000000000000000000012611456566705700227640ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray #include "ISPCDevice.h" #include "common/Managed.h" namespace ospray { struct OSPRAY_SDK_INTERFACE ISPCDeviceObject : public ManagedObject { ISPCDeviceObject(api::ISPCDevice &device) : ispcDevice(&device) {} inline api::ISPCDevice &getISPCDevice() const { return *ispcDevice; } template const Ref> getParamDataT( const char *name, bool required = false, bool promoteScalar = false); private: // Ref ispcDevice; TODO: const problem api::ISPCDevice *ispcDevice{nullptr}; }; } // namespace osprayRenderKit-ospray-f2a61c2/modules/cpu/ModuleInit.cpp000066400000000000000000000026151456566705700223670ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // We don't want an instance of ObjectFactory static table in this library // so we have to include it with import define so the table will be imported // from 'ospray' library #define OBJECTFACTORY_IMPORT #include "common/ObjectFactory.h" #include "ISPCDevice.h" #include "OSPCommon.h" #include "camera/registration.h" #include "fb/registration.h" #include "geometry/registration.h" #include "lights/registration.h" #include "render/registration.h" #include "texture/registration.h" #ifdef OSPRAY_ENABLE_VOLUMES #include "volume/transferFunction/registration.h" #endif using namespace ospray; extern "C" OSPError OSPRAY_DLLEXPORT #ifdef OSPRAY_TARGET_SYCL ospray_module_init_gpu #else ospray_module_init_cpu #endif (int16_t versionMajor, int16_t versionMinor, int16_t /*versionPatch*/) { auto status = moduleVersionCheck(versionMajor, versionMinor); if (status == OSP_NO_ERROR) { #ifdef OSPRAY_TARGET_SYCL api::Device::registerType("gpu"); #else api::Device::registerType("cpu"); #endif registerAllCameras(); registerAllImageOps(); registerAllGeometries(); registerAllLights(); registerAllMaterials(); registerAllRenderers(); registerAllTextures(); #ifdef OSPRAY_ENABLE_VOLUMES registerAllTransferFunctions(); #endif } return status; } RenderKit-ospray-f2a61c2/modules/cpu/camera/000077500000000000000000000000001456566705700210365ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/camera/Camera.cpp000066400000000000000000000071211456566705700227330ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Camera.h" namespace ospray { Camera::Camera(api::ISPCDevice &device, const FeatureFlagsOther featureFlags) : AddStructShared(device.getIspcrtContext(), device), featureFlags(featureFlags) { managedObjectType = OSP_CAMERA; } Camera::~Camera() { if (embreeGeometry) { rtcReleaseGeometry(embreeGeometry); rtcReleaseScene(embreeScene); } } std::string Camera::toString() const { return "ospray::Camera"; } box3f Camera::projectBox(const box3f &) const { return box3f(vec3f(0.f), vec3f(1.f)); } void Camera::commit() { motionTransform.readParams(*this); // "parse" the general expected parameters pos = getParam("position", vec3f(0.f)); dir = getParam("direction", vec3f(0.f, 0.f, 1.f)); up = getParam("up", vec3f(0.f, 1.f, 0.f)); nearClip = std::max(getParam("nearClip", 1e-6f), 0.f); imageStart = getParam("imageStart", vec2f(0.f)); imageEnd = getParam("imageEnd", vec2f(1.f)); shutter = getParam("shutter", range1f(0.5f, 0.5f)); clamp(shutter.lower); clamp(shutter.upper); if (shutter.lower > shutter.upper) shutter.lower = shutter.upper; shutterType = (OSPShutterType)getParam("shutterType", OSP_SHUTTER_GLOBAL); rollingShutterDuration = clamp( getParam("rollingShutterDuration", 0.0f), 0.0f, shutter.size()); if (motionTransform.motionBlur || motionTransform.quaternion) { // create dummy RTCGeometry for transform interpolation or conversion if (!embreeGeometry) { embreeGeometry = rtcNewGeometry( getISPCDevice().getEmbreeDevice(), RTC_GEOMETRY_TYPE_INSTANCE); embreeScene = rtcNewScene(getISPCDevice().getEmbreeDevice()); rtcAttachGeometryByID(embreeScene, embreeGeometry, 0); } motionTransform.setEmbreeTransform(embreeGeometry); if (shutter.lower == shutter.upper || !motionTransform.motionBlur) { // directly interpolate to single shutter time rtcGetGeometryTransformFromScene(embreeScene, 0, shutter.lower, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, &motionTransform.transform); motionTransform.motionBlur = false; } } if (!motionTransform.motionBlur) { if (embreeGeometry) { rtcReleaseGeometry(embreeGeometry); embreeGeometry = nullptr; rtcReleaseScene(embreeScene); embreeScene = nullptr; } // apply transform right away pos = xfmPoint(motionTransform.transform, pos); dir = normalize(xfmVector(motionTransform.transform, dir)); up = normalize(xfmVector(motionTransform.transform, up)); } if (shutterType != OSP_SHUTTER_GLOBAL) { // rolling shutter shutter.upper -= rollingShutterDuration; if (shutterType == OSP_SHUTTER_ROLLING_LEFT || shutterType == OSP_SHUTTER_ROLLING_DOWN) std::swap(shutter.lower, shutter.upper); } getSh()->nearClip = nearClip; getSh()->subImage.lower = imageStart; getSh()->subImage.upper = imageEnd; getSh()->shutter = shutter; getSh()->motionBlur = motionTransform.motionBlur; getSh()->scene = embreeScene; getSh()->globalShutter = shutterType == OSP_SHUTTER_GLOBAL; getSh()->rollingShutterHorizontal = (shutterType == OSP_SHUTTER_ROLLING_RIGHT || shutterType == OSP_SHUTTER_ROLLING_LEFT); getSh()->rollingShutterDuration = rollingShutterDuration; if (motionTransform.motionBlur) featureFlags |= FFO_CAMERA_MOTION_BLUR; else featureFlags = (FeatureFlagsOther)(featureFlags & ~FFO_CAMERA_MOTION_BLUR); } OSPTYPEFOR_DEFINITION(Camera *); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/camera/Camera.h000066400000000000000000000042201456566705700223750ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ISPCDeviceObject.h" #include "common/FeatureFlagsEnum.h" #include "common/MotionTransform.h" #include "common/ObjectFactory.h" #include "common/StructShared.h" // ispc shared #include "CameraShared.h" namespace ospray { // base camera class abstraction // the base class itself does not do anything useful; look into // perspectivecamera etc for that struct OSPRAY_SDK_INTERFACE Camera : public AddStructShared, public ObjectFactory { Camera(api::ISPCDevice &device, const FeatureFlagsOther featureFlags); ~Camera() override; std::string toString() const override; void commit() override; // Project the bounding box to the screen // The projected box will be returned in normalized [0, 1] coordinates in // the framebuffer, the z coordinate will store the min and max depth, in // box.lower, box.upper respectively // Assume no motion blur nor depth of field (true for SciVis) virtual box3f projectBox(const box3f &b) const; FeatureFlags getFeatureFlags() const; // Data members // // if motionBlur in local camera space; otherwise in world-space: vec3f pos{0.f, 0.f, 0.f}; // position of the camera vec3f dir{0.f, 0.f, 1.f}; // main direction of the camera vec3f up{0.f, 1.f, 0.f}; // up direction of the camera float nearClip{1e-6f}; // near clipping distance // definition of the image region, may even be outside of [0..1]^2 // to simulate sensor shift vec2f imageStart{0.f, 0.f}; // lower left corner vec2f imageEnd{1.f, 1.f}; // upper right corner range1f shutter{0.5f, 0.5f}; // start and end time of camera shutter time float rollingShutterDuration{0.0f}; OSPShutterType shutterType{OSP_SHUTTER_GLOBAL}; private: RTCGeometry embreeGeometry{nullptr}; RTCScene embreeScene{nullptr}; MotionTransform motionTransform; FeatureFlagsOther featureFlags{FFO_NONE}; }; OSPTYPEFOR_SPECIALIZATION(Camera *, OSP_CAMERA); inline FeatureFlags Camera::getFeatureFlags() const { FeatureFlags ff; ff.other = featureFlags; return ff; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/camera/Camera.ih000066400000000000000000000021221456566705700225450ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // camera.ih Defines the abstract base class of an ISPC-side camera #pragma once #include "common/Ray.ih" #include "rkcommon/math/box.ih" // c++ shared #include "CameraShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE struct FeatureFlagsHandler; // Specifies the input parameters (time, screen, and lens // samples) required for 'initRay' to generate a primary ray struct CameraSample { vec2f screen; // normalized screen sample, in [0..1] vec2f lens; float time; }; inline vec2f Camera_subRegion(const Camera *uniform self, const vec2f &screen) { return lerp(screen, self->subImage.lower, self->subImage.upper); } inline float Camera_shutterTime( const Camera *uniform self, const vec2f &screen, float time) { if (self->globalShutter) return lerp(time, self->shutter.lower, self->shutter.upper); time *= self->rollingShutterDuration; const float pos = self->rollingShutterHorizontal ? screen.x : screen.y; return clamp(time + lerp(pos, self->shutter.lower, self->shutter.upper)); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/camera/CameraDispatch.ih000066400000000000000000000005471456566705700242360ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/FeatureFlags.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL void Camera_dispatch_initRay(const Camera *uniform self, varying Ray &ray, const varying CameraSample &sample, const uniform FeatureFlagsHandler &ffh); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/camera/CameraDispatch.ispc000066400000000000000000000023071456566705700245700ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Camera.ih" #include "CameraDispatch.ih" #include "OrthographicCamera.ih" #include "PanoramicCamera.ih" #include "PerspectiveCamera.ih" #include "common/FeatureFlagsEnum.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL void Camera_dispatch_initRay(const Camera *uniform self, varying Ray &ray, const varying CameraSample &sample, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlagsOther ffo = getFeatureFlagsOther(ffh); if ((self->type == CAMERA_TYPE_PERSPECTIVE) && (ffo & FFO_CAMERA_PERSPECTIVE)) { if (self->motionBlur && (ffo & FFO_CAMERA_MOTION_BLUR)) PerspectiveCamera_initRayMB(self, ray, sample, ffh); else PerspectiveCamera_initRay(self, ray, sample, ffh); } else if ((self->type == CAMERA_TYPE_ORTHOGRAPHIC) && (ffo & FFO_CAMERA_ORTHOGRAPHIC)) { OrthographicCamera_initRay(self, ray, sample, ffh); } else if ((self->type == CAMERA_TYPE_PANORAMIC) && (ffo & FFO_CAMERA_PANORAMIC)) { PanoramicCamera_initRay(self, ray, sample, ffh); } else { #ifndef OSPRAY_TARGET_SYCL self->initRay(self, ray, sample); #endif } } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/camera/CameraShared.h000066400000000000000000000030131456566705700235230ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus #if defined(__cplusplus) && !defined(OSPRAY_TARGET_SYCL) typedef void *Camera_initRay; #else struct Camera; struct CameraSample; struct Ray; // Fct pointer type for 'virtual' method that sets a pixel, // generated ray.dir must be normalized to ensure ray.t is world-space distance typedef void (*Camera_initRay)(const Camera *uniform, varying Ray &ray, const varying CameraSample &sample); #endif enum CameraType { CAMERA_TYPE_PERSPECTIVE, CAMERA_TYPE_ORTHOGRAPHIC, CAMERA_TYPE_PANORAMIC, CAMERA_TYPE_UNKNOWN, }; struct Camera { CameraType type; Camera_initRay initRay; // the 'virtual' initRay() method bool motionBlur; // for the camera itself only, not in general float nearClip; box2f subImage; // viewable tile / subrange to compute, in [0..1]^2 x [0..1]^2 range1f shutter; // camera shutter open start and end time, in [0..1] bool globalShutter; bool rollingShutterHorizontal; float rollingShutterDuration; RTCScene scene; // only to call rtcGetGeometryTransformFromScene #ifdef __cplusplus Camera() : type(CAMERA_TYPE_UNKNOWN), initRay(nullptr), motionBlur(false), nearClip(1e-6f), subImage(0.f), shutter(0.f), globalShutter(false), rollingShutterHorizontal(false), rollingShutterDuration(0.f), scene(nullptr) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/camera/OrthographicCamera.cpp000066400000000000000000000061051456566705700253060ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "OrthographicCamera.h" #ifndef OSPRAY_TARGET_SYCL // ispc exports #include "camera/OrthographicCamera_ispc.h" #endif namespace ospray { OrthographicCamera::OrthographicCamera(api::ISPCDevice &device) : AddStructShared( device.getIspcrtContext(), device, FFO_CAMERA_ORTHOGRAPHIC) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.initRay = reinterpret_cast( ispc::OrthographicCamera_initRay_addr()); #endif } std::string OrthographicCamera::toString() const { return "ospray::OrthographicCamera"; } void OrthographicCamera::commit() { Camera::commit(); height = getParam("height", 1.f); aspect = getParam("aspect", 1.f); vec2f size = height; size.x *= aspect; if (getSh()->super.motionBlur) { getSh()->dir = dir; getSh()->du_size = vec3f(size.x, size.y, 1.0f); getSh()->dv_up = up; getSh()->org = pos; } else { getSh()->dir = normalize(dir); getSh()->du_size = normalize(cross(getSh()->dir, up)); getSh()->dv_up = cross(getSh()->du_size, getSh()->dir) * size.y; getSh()->du_size = getSh()->du_size * size.x; getSh()->org = pos - 0.5f * getSh()->du_size - 0.5f * getSh()->dv_up; // shift } } box3f OrthographicCamera::projectBox(const box3f &b) const { box3f projection; // normalize to image plane size const vec3f dun = getSh()->du_size / dot(getSh()->du_size, getSh()->du_size); const vec3f dvn = getSh()->dv_up / dot(getSh()->dv_up, getSh()->dv_up); vec3f projectedPt(-1.f, -1.f, 1e20f); for (uint32_t i = 0; i < 8; ++i) { // Get the point we should be projecting vec3f p; switch (i) { case 0: p = b.lower; break; case 1: p.x = b.upper.x; p.y = b.lower.y; p.z = b.lower.z; break; case 2: p.x = b.upper.x; p.y = b.upper.y; p.z = b.lower.z; break; case 3: p.x = b.lower.x; p.y = b.upper.y; p.z = b.lower.z; break; case 4: p.x = b.lower.x; p.y = b.lower.y; p.z = b.upper.z; break; case 5: p.x = b.upper.x; p.y = b.lower.y; p.z = b.upper.z; break; case 6: p = b.upper; break; case 7: p.x = b.lower.x; p.y = b.upper.y; p.z = b.upper.z; break; } // Project the point on to the film plane const float depth = dot(p - getSh()->org, getSh()->dir); const vec3f screenPt = p - depth * getSh()->dir; const vec3f screenDir = screenPt - getSh()->org; projectedPt.x = dot(screenDir, dun); projectedPt.y = dot(screenDir, dvn); projectedPt.z = depth; projection.lower.x = min(projectedPt.x, projection.lower.x); projection.lower.y = min(projectedPt.y, projection.lower.y); projection.lower.z = min(projectedPt.z, projection.lower.z); projection.upper.x = max(projectedPt.x, projection.upper.x); projection.upper.y = max(projectedPt.y, projection.upper.y); projection.upper.z = max(projectedPt.z, projection.upper.z); } return projection; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/camera/OrthographicCamera.h000066400000000000000000000021041456566705700247460ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "camera/Camera.h" // ispc shared #include "OrthographicCameraShared.h" namespace ospray { // The Orthographic Camera ("orthographic") // // Implements a straightforward orthographic camera for orthographic // projections, without support for Depth of Field // // A simple orthographic camera. This camera type is loaded by passing // the type string "orthographic" to ospNewCamera // // The functionality for a orthographic camera is implemented via the // ospray::OrthographicCamera class. struct OSPRAY_SDK_INTERFACE OrthographicCamera : public AddStructShared { OrthographicCamera(api::ISPCDevice &device); ~OrthographicCamera() override = default; virtual std::string toString() const override; virtual void commit() override; box3f projectBox(const box3f &b) const override; // Data members // float height{ 1.f}; // size of the camera's image plane in y, in world coordinates float aspect{1.f}; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/camera/OrthographicCamera.ih000066400000000000000000000005071456566705700251240ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "camera/Camera.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL void OrthographicCamera_initRay(const Camera *uniform, varying Ray &, const varying CameraSample &, const uniform FeatureFlagsHandler &); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/camera/OrthographicCamera.ispc000066400000000000000000000036131456566705700254630ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Camera.ih" #include "common/Embree.h" #include "common/FeatureFlags.ih" #include "common/FeatureFlagsEnum.h" // c++ shared #include "OrthographicCameraShared.h" #include "rkcommon/math/AffineSpace.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL void OrthographicCamera_initRay(const Camera *uniform _self, varying Ray &ray, const varying CameraSample &sample, const uniform FeatureFlagsHandler &ffh) { const OrthographicCamera *uniform self = (const OrthographicCamera *uniform)_self; const vec2f screen = Camera_subRegion(_self, sample.screen); const float time = Camera_shutterTime(_self, screen, sample.time); vec3f dir; vec3f org; const uniform FeatureFlagsOther ffo = getFeatureFlagsOther(ffh); if (self->super.motionBlur && (ffo & FFO_CAMERA_MOTION_BLUR)) { AffineSpace3f xfm; rtcGetGeometryTransformFromScene( self->super.scene, 0, time, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, &xfm); // we cannot just transform the final org & dir, because interpolated // transforms can scale (even if original transforms are without scale) dir = normalize(xfmVector(xfm, self->dir)); const vec3f up = xfmVector(xfm, self->dv_up); org = xfmPoint(xfm, self->org); const vec3f du = normalize(cross(dir, up)); const vec3f dv = cross(du, dir); const float x = (screen.x - 0.5f) * self->du_size.x; const float y = (screen.y - 0.5f) * self->du_size.y; org = org + x * du + y * dv; } else { dir = self->dir; org = self->org + screen.x * self->du_size + screen.y * self->dv_up; } setRay(ray, org, dir, self->super.nearClip, inf, time); } // Exports (called from C++) ////////////////////////////////////////////////// export void *uniform OrthographicCamera_initRay_addr() { return (void *uniform)OrthographicCamera_initRay; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/camera/OrthographicCameraShared.h000066400000000000000000000014541456566705700261040ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "CameraShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct OrthographicCamera { Camera super; vec3f dir; // below are essentially unions: 1. if no motionBlur; 2. if motionBlur vec3f org; // lower left position of the camera image plane; // origin of camera vec3f du_size; // delta of ray origin between two pixels in x; // sensor size (in x and y) vec3f dv_up; // delta of ray origin between two pixels in y; // up direction of camera #ifdef __cplusplus OrthographicCamera() : dir(0.f), org(0.f), du_size(0.f), dv_up(0.f) { super.type = CAMERA_TYPE_ORTHOGRAPHIC; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/camera/PanoramicCamera.cpp000066400000000000000000000025731456566705700245730ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "PanoramicCamera.h" // ispc exports #ifndef OSPRAY_TARGET_SYCL #include "camera/PanoramicCamera_ispc.h" #else namespace ispc { void *PanoramicCamera_initRay_addr(); } #endif namespace ospray { PanoramicCamera::PanoramicCamera(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFO_CAMERA_PANORAMIC) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.initRay = reinterpret_cast( ispc::PanoramicCamera_initRay_addr()); #endif } std::string PanoramicCamera::toString() const { return "ospray::PanoramicCamera"; } void PanoramicCamera::commit() { Camera::commit(); getSh()->org = pos; if (getSh()->super.motionBlur) { getSh()->frame.vz = -dir; getSh()->frame.vy = up; } else { getSh()->frame.vz = -normalize(dir); getSh()->frame.vx = normalize(cross(up, getSh()->frame.vz)); getSh()->frame.vy = cross(getSh()->frame.vz, getSh()->frame.vx); } getSh()->stereoMode = (OSPStereoMode)getParam("stereoMode", OSP_STEREO_NONE); getSh()->ipd_offset = 0.5f * getParam("interpupillaryDistance", 0.0635f); // flip offset to have left eye at top (image coord origin at lower left) if (getSh()->stereoMode == OSP_STEREO_TOP_BOTTOM) getSh()->ipd_offset = -getSh()->ipd_offset; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/camera/PanoramicCamera.h000066400000000000000000000010621456566705700242300ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "camera/Camera.h" // ispc shared #include "PanoramicCameraShared.h" namespace ospray { // Implements a panoramic camera with latitude/longitude mapping struct OSPRAY_SDK_INTERFACE PanoramicCamera : public AddStructShared { PanoramicCamera(api::ISPCDevice &device); virtual ~PanoramicCamera() override = default; virtual std::string toString() const override; virtual void commit() override; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/camera/PanoramicCamera.ih000066400000000000000000000005031456566705700244000ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "camera/Camera.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL void PanoramicCamera_initRay(const Camera *uniform, varying Ray &, const varying CameraSample &, const uniform FeatureFlagsHandler &); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/camera/PanoramicCamera.ispc000066400000000000000000000053511456566705700247440ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Camera.ih" #include "common/Embree.h" #include "common/FeatureFlags.ih" #include "common/FeatureFlagsEnum.h" #include "math/sampling.ih" #include "ospray/OSPEnums.h" // c++ shared #include "PanoramicCameraShared.h" #include "rkcommon/math/AffineSpace.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL void PanoramicCamera_initRay(const Camera *uniform _self, varying Ray &ray, const varying CameraSample &sample, const uniform FeatureFlagsHandler &ffh) { const PanoramicCamera *uniform self = (const PanoramicCamera *uniform)_self; vec2f screen = sample.screen; varying float *uniform split = self->stereoMode == OSP_STEREO_SIDE_BY_SIDE ? &screen.x : &screen.y; float offset = 0.f; switch (self->stereoMode) { case OSP_STEREO_LEFT: offset = -self->ipd_offset; break; case OSP_STEREO_RIGHT: offset = self->ipd_offset; break; case OSP_STEREO_SIDE_BY_SIDE: case OSP_STEREO_TOP_BOTTOM: *split *= 2.f; if (*split < 1.f) { offset = -self->ipd_offset; } else { offset = self->ipd_offset; *split -= 1.f; } break; } screen = Camera_subRegion(_self, screen); const float phi = (float)two_pi * screen.x; const float theta = (float)pi * screen.y; float sinTheta, cosTheta; sincos(theta, &sinTheta, &cosTheta); const vec3f localDir = cartesian(phi, sinTheta, cosTheta); const float time = Camera_shutterTime(_self, screen, sample.time); // transform to camera- and then to world-space vec3f dir; vec3f org; const uniform FeatureFlagsOther ffo = getFeatureFlagsOther(ffh); if (self->super.motionBlur && (ffo & FFO_CAMERA_MOTION_BLUR)) { AffineSpace3f xfm; rtcGetGeometryTransformFromScene( self->super.scene, 0, time, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, &xfm); // we cannot just transform the final org & dir, because interpolated // transforms can scale (even if original transforms are without scale) linear3f frameMB; frameMB.vz = normalize(xfmVector(xfm, self->frame.vz)); frameMB.vx = normalize(cross(xfmVector(xfm, self->frame.vy), frameMB.vz)); frameMB.vy = cross(frameMB.vz, frameMB.vx); dir = frameMB * make_vec3f(-localDir.y, -localDir.z, localDir.x); org = xfmPoint(xfm, self->org) + offset * cross(dir, frameMB.vy); } else { dir = self->frame * make_vec3f(-localDir.y, -localDir.z, localDir.x); org = self->org + offset * cross(dir, self->frame.vy); } setRay(ray, org, dir, self->super.nearClip, inf, time); } // Exports (called from C++) ////////////////////////////////////////////////// export void *uniform PanoramicCamera_initRay_addr() { return (void *uniform)PanoramicCamera_initRay; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/camera/PanoramicCameraShared.h000066400000000000000000000011361456566705700253610ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "CameraShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct PanoramicCamera { Camera super; vec3f org; linear3f frame; // union: precomputed frame; or (xxx, up, -dir) if motion blur int stereoMode; float ipd_offset; // half of the interpupillary distance #ifdef __cplusplus PanoramicCamera() : org(0.f), frame(one), stereoMode(OSP_STEREO_NONE), ipd_offset(0.f) { super.type = CAMERA_TYPE_PANORAMIC; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/camera/PerspectiveCamera.cpp000066400000000000000000000141531456566705700251500ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "PerspectiveCamera.h" #ifndef OSPRAY_TARGET_SYCL // ispc exports #include "camera/PerspectiveCamera_ispc.h" #endif namespace ospray { PerspectiveCamera::PerspectiveCamera(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFO_CAMERA_PERSPECTIVE) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.initRay = reinterpret_cast( ispc::PerspectiveCamera_initRay_addr()); #endif } std::string PerspectiveCamera::toString() const { return "ospray::PerspectiveCamera"; } void PerspectiveCamera::commit() { Camera::commit(); fovy = getParam("fovy", 60.f); aspect = getParam("aspect", 1.f); apertureRadius = getParam("apertureRadius", 0.f); focusDistance = getParam("focusDistance", 1.f); architectural = getParam("architectural", false); stereoMode = (OSPStereoMode)getParam("stereoMode", OSP_STEREO_NONE); // the default 63.5mm represents the average human IPD interpupillaryDistance = getParam("interpupillaryDistance", 0.0635f); switch (stereoMode) { case OSP_STEREO_SIDE_BY_SIDE: aspect *= 0.5f; break; case OSP_STEREO_TOP_BOTTOM: aspect *= 2.f; break; default: break; } vec2f imgPlaneSize; imgPlaneSize.y = 2.f * tanf(deg2rad(0.5f * fovy)); imgPlaneSize.x = imgPlaneSize.y * aspect; // Set shared structure members { getSh()->scaledAperture = apertureRadius ? apertureRadius / (imgPlaneSize.x * focusDistance) : 0.0f; getSh()->aspect = aspect; getSh()->stereoMode = stereoMode; getSh()->dir_00 = normalize(dir); getSh()->org = pos; getSh()->imgPlaneSize = imgPlaneSize; if (getSh()->super.motionBlur) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.initRay = reinterpret_cast( ispc::PerspectiveCamera_initRayMB_addr()); #endif getSh()->du_size = vec3f(imgPlaneSize.x, imgPlaneSize.y, architectural); getSh()->dv_up = up; getSh()->ipd_offset = vec3f(0.5f * interpupillaryDistance, focusDistance, 0.0f); } else { #ifndef OSPRAY_TARGET_SYCL getSh()->super.initRay = reinterpret_cast( ispc::PerspectiveCamera_initRay_addr()); #endif getSh()->du_size = normalize(cross(getSh()->dir_00, up)); if (architectural) // orient film to be parallel to 'up' getSh()->dv_up = normalize(up); else // rotate film to be perpendicular to 'dir' getSh()->dv_up = cross(getSh()->du_size, getSh()->dir_00); getSh()->ipd_offset = 0.5f * interpupillaryDistance * getSh()->du_size; switch (stereoMode) { case OSP_STEREO_LEFT: getSh()->org = getSh()->org - getSh()->ipd_offset; break; case OSP_STEREO_RIGHT: getSh()->org = getSh()->org + getSh()->ipd_offset; break; case OSP_STEREO_TOP_BOTTOM: // flip offset to have left eye at top (image coord origin at lower // left) getSh()->ipd_offset = -getSh()->ipd_offset; break; default: break; } getSh()->du_size = getSh()->du_size * imgPlaneSize.x; getSh()->dv_up = getSh()->dv_up * imgPlaneSize.y; getSh()->dir_00 = getSh()->dir_00 - 0.5f * getSh()->du_size - 0.5f * getSh()->dv_up; // prescale to focal plane if (getSh()->scaledAperture > 0.f) { getSh()->du_size = getSh()->du_size * focusDistance; getSh()->dv_up = getSh()->dv_up * focusDistance; getSh()->dir_00 = getSh()->dir_00 * focusDistance; } } } } box3f PerspectiveCamera::projectBox(const box3f &b) const { if (stereoMode != OSP_STEREO_NONE) { return box3f(vec3f(0.f), vec3f(1.f)); } box3f projection; const vec3f dir = normalize( getSh()->dir_00 + 0.5f * getSh()->du_size + 0.5f * getSh()->dv_up); const vec3f dun = normalize(getSh()->du_size) / getSh()->imgPlaneSize.x; const vec3f dvn = normalize(getSh()->dv_up) / getSh()->imgPlaneSize.y; vec3f projectedPt(-1.f, -1.f, 1e20f); for (uint32_t i = 0; i < 8; ++i) { // Get the point we should be projecting vec3f p; switch (i) { case 0: p = b.lower; break; case 1: p.x = b.upper.x; p.y = b.lower.y; p.z = b.lower.z; break; case 2: p.x = b.upper.x; p.y = b.upper.y; p.z = b.lower.z; break; case 3: p.x = b.lower.x; p.y = b.upper.y; p.z = b.lower.z; break; case 4: p.x = b.lower.x; p.y = b.lower.y; p.z = b.upper.z; break; case 5: p.x = b.upper.x; p.y = b.lower.y; p.z = b.upper.z; break; case 6: p = b.upper; break; case 7: p.x = b.lower.x; p.y = b.upper.y; p.z = b.upper.z; break; } // We find the intersection of the ray through the point with the virtual // film plane, then find the vector to this point from the origin of the // film plane (screenDir) and project this point onto the x/y axes of // the plane. const vec3f v = p - getSh()->org; const vec3f r = normalize(v); const float denom = dot(-r, -dir); if (denom != 0.f) { float t = 1.f / denom; const vec3f screenDir = r * t - getSh()->dir_00; projectedPt.x = dot(screenDir, dun); projectedPt.y = dot(screenDir, dvn); projectedPt.z = std::signbit(t) ? -length(v) : length(v); projection.lower.x = min(projectedPt.x, projection.lower.x); projection.lower.y = min(projectedPt.y, projection.lower.y); projection.lower.z = min(projectedPt.z, projection.lower.z); projection.upper.x = max(projectedPt.x, projection.upper.x); projection.upper.y = max(projectedPt.y, projection.upper.y); projection.upper.z = max(projectedPt.z, projection.upper.z); } } // If some points are behind and some are in front mark the box // as covering the full screen if (projection.lower.z < 0.f && projection.upper.z > 0.f) { projection.lower.x = 0.f; projection.lower.y = 0.f; projection.upper.x = 1.f; projection.upper.y = 1.f; } return projection; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/camera/PerspectiveCamera.h000066400000000000000000000017161456566705700246160ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "camera/Camera.h" #include "rkcommon/math/box.h" // ispc shared #include "PerspectiveCameraShared.h" namespace ospray { struct OSPRAY_SDK_INTERFACE PerspectiveCamera : public AddStructShared { PerspectiveCamera(api::ISPCDevice &device); virtual ~PerspectiveCamera() override = default; virtual std::string toString() const override; virtual void commit() override; box3f projectBox(const box3f &b) const override; // Data members // float fovy{60.f}; float aspect{1.f}; float apertureRadius{0.f}; float focusDistance{1.f}; bool architectural{false}; // orient image plane to be parallel to 'up' and // shift the lens OSPStereoMode stereoMode{OSP_STEREO_NONE}; float interpupillaryDistance{ 0.0635f}; // distance between the two cameras (stereo) }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/camera/PerspectiveCamera.ih000066400000000000000000000007531456566705700247670ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "camera/Camera.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL void PerspectiveCamera_initRay(const Camera *uniform, varying Ray &, const varying CameraSample &, const uniform FeatureFlagsHandler &); SYCL_EXTERNAL void PerspectiveCamera_initRayMB(const Camera *uniform, varying Ray &, const varying CameraSample &, const uniform FeatureFlagsHandler &); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/camera/PerspectiveCamera.ispc000066400000000000000000000103171456566705700253220ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Camera.ih" #include "common/Embree.h" #include "common/FeatureFlags.ih" #include "common/FeatureFlagsEnum.h" #include "math/sampling.ih" #include "ospray/OSPEnums.h" // c++ shared #include "PerspectiveCameraShared.h" #include "rkcommon/math/AffineSpace.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL void PerspectiveCamera_initRay(const Camera *uniform _self, varying Ray &ray, const varying CameraSample &sample, const uniform FeatureFlagsHandler &) { const PerspectiveCamera *uniform self = (const PerspectiveCamera *uniform)_self; vec2f screen = sample.screen; vec3f org = self->org; const uniform bool sbs = self->stereoMode == OSP_STEREO_SIDE_BY_SIDE; varying float *uniform split = sbs ? &screen.x : &screen.y; if (sbs || self->stereoMode == OSP_STEREO_TOP_BOTTOM) { *split *= 2.f; if (*split < 1.f) { org = org - self->ipd_offset; } else { org = org + self->ipd_offset; *split -= 1.f; } } screen = Camera_subRegion(_self, screen); vec3f dir = self->dir_00 + screen.x * self->du_size + screen.y * self->dv_up; if (self->scaledAperture > 0.f) { const vec3f llp = uniformSampleDisk(self->scaledAperture, sample.lens); // transform local lens point to focal plane (dir_XX are prescaled) const vec3f lp = (llp.x * self->du_size) + ((llp.y * self->aspect) * self->dv_up); org = org + lp; dir = dir - lp; } const float time = Camera_shutterTime(_self, screen, sample.time); setRay(ray, org, normalize(dir), self->super.nearClip, inf, time); } SYCL_EXTERNAL void PerspectiveCamera_initRayMB(const Camera *uniform _self, varying Ray &ray, const varying CameraSample &sample, const uniform FeatureFlagsHandler &) { const PerspectiveCamera *uniform self = (const PerspectiveCamera *uniform)_self; vec2f screen = sample.screen; float ipd_offset1 = self->ipd_offset.x; const uniform bool sbs = self->stereoMode == OSP_STEREO_SIDE_BY_SIDE; varying float *uniform split = sbs ? &screen.x : &screen.y; if (sbs || self->stereoMode == OSP_STEREO_TOP_BOTTOM) { *split *= 2.f; if (*split < 1.f) ipd_offset1 = -ipd_offset1; else *split -= 1.f; } screen = Camera_subRegion(_self, screen); const float time = Camera_shutterTime(_self, screen, sample.time); AffineSpace3f xfm; rtcGetGeometryTransformFromScene( self->super.scene, 0, time, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, &xfm); vec3f org = xfmPoint(xfm, self->org); vec3f dir = normalize(xfmVector(xfm, self->dir_00)); const vec3f up = xfmVector(xfm, self->dv_up); vec3f du = normalize(cross(dir, up)); vec3f dv; if (self->du_size.z > 0.f) // architectural: orient img to be parallel to 'up' dv = normalize(up); else // rotate film to be perpendicular to 'dir' dv = cross(du, dir); vec3f ipd_offset = ipd_offset1 * du; switch (self->stereoMode) { case OSP_STEREO_LEFT: case OSP_STEREO_TOP_BOTTOM: // flipped to have left eye at top org = org - ipd_offset; break; case OSP_STEREO_RIGHT: case OSP_STEREO_SIDE_BY_SIDE: org = org + ipd_offset; break; default: break; } du = du * self->du_size.x; dv = dv * self->du_size.y; dir = dir - 0.5f * du - 0.5f * dv; // prescale to focal plane if (self->scaledAperture > 0.f) { du = du * self->ipd_offset.y; // focusDistance dv = dv * self->ipd_offset.y; // focusDistance dir = dir * self->ipd_offset.y; // focusDistance } dir = dir + screen.x * du + screen.y * dv; if (self->scaledAperture > 0.f) { const vec3f llp = uniformSampleDisk(self->scaledAperture, sample.lens); // transform local lens point to focal plane (dir_XX are prescaled) const vec3f lp = (llp.x * du) + ((llp.y * self->aspect) * dv); org = org + lp; dir = dir - lp; } setRay(ray, org, normalize(dir), self->super.nearClip, inf, time); } // Exports (called from C++) ////////////////////////////////////////////////// export void *uniform PerspectiveCamera_initRay_addr() { return (void *uniform)PerspectiveCamera_initRay; } export void *uniform PerspectiveCamera_initRayMB_addr() { return (void *uniform)PerspectiveCamera_initRayMB; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/camera/PerspectiveCameraShared.h000066400000000000000000000030211456566705700257340ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "CameraShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct PerspectiveCamera { Camera super; vec3f org; // position of camera, already contains shift when // STEREO_{LEFT|RIGHT} vec3f dir_00; // direction of ray with screenSample=(0,0); scaled to // focusDistance if no motionBlur // below are essentially unions: 1. if no motionBlur; 2. if motionBlur vec3f du_size; // delta of ray direction between two pixels in x, scaled to // focusDistance; sensor size (in x and y) and architectural vec3f dv_up; // delta of ray direction between two pixels in y, scaled to // focusDistance; up direction of camera vec3f ipd_offset; // shift of camera position for left/right eye (only when // SIDE_BY_SIDE or TOP_BOTTOM); (0.5*ipd, focusDistance, 0) vec2f imgPlaneSize; float scaledAperture; // radius of aperture prescaled to focal plane, i.e., // divided by horizontal image plane size float aspect; // image plane size x / y int stereoMode; #ifdef __cplusplus PerspectiveCamera() : org(0.f), dir_00(0.f), du_size(0.f), dv_up(0.f), ipd_offset(0.f), imgPlaneSize(0.f), scaledAperture(0.f), aspect(1.f), stereoMode(OSP_STEREO_NONE) { super.type = CAMERA_TYPE_PERSPECTIVE; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/camera/registration.cpp000066400000000000000000000006361456566705700242610ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "OrthographicCamera.h" #include "PanoramicCamera.h" #include "PerspectiveCamera.h" namespace ospray { void registerAllCameras() { Camera::registerType("orthographic"); Camera::registerType("panoramic"); Camera::registerType("perspective"); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/camera/registration.h000066400000000000000000000002221456566705700237150ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 namespace ospray { void registerAllCameras(); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/common/000077500000000000000000000000001456566705700210765ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/common/Clipping.ih000066400000000000000000000023031456566705700231630ustar00rootroot00000000000000// Copyright 2019 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray #include "rkcommon/math/AffineSpace.ih" #include "rkcommon/math/box.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // Array of all ray intervals across ray #define CLIPPING_INTERVALS_MAX_COUNT 64 struct RayIntervals { uint32 count; range1f intervals[CLIPPING_INTERVALS_MAX_COUNT]; }; // Maximum number of intersections with clipping geometries #define CLIPPING_HITS_MAX_COUNT ((CLIPPING_INTERVALS_MAX_COUNT - 1) * 2) // Single clipping hit structure struct ClippingHit { float t; int primID; int geomID; int instID; }; // Compare two floats using ULP distance inline bool floatUlpCompare(float a, float b, uniform unsigned int ulpMaxDiff) { if (a == b) return true; int ulpDiff = (int)intbits(a) - (int)intbits(b); // Integer absolute value, equivalent to: // if (ulpDiff < 0) ulpDiff = -ulpDiff; int mask = (ulpDiff >> 31); unsigned int ulpDiffUnsigned = (ulpDiff ^ mask) - mask; if (ulpDiffUnsigned <= ulpMaxDiff) return true; return false; } inline bool overlapped(const range1f &a, const range1f &b) { return (a.upper > b.lower) && (a.lower < b.upper); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/common/DGEnum.h000066400000000000000000000014371456566705700223730ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef __cplusplus namespace ospray { #endif // __cplusplus typedef enum { DG_FACEFORWARD = (1 << 0), // face-forward normals DG_NORMALIZE = (1 << 1), // normalize normals DG_NG = (1 << 2), // need geometry normal Ng DG_NS = (1 << 3), // need shading normal Ns DG_COLOR = (1 << 5), // hack for now - need interpolated vertex color DG_TEXCOORD = (1 << 6), // calculate texture coords st DG_TANGENTS = (1 << 7), // calculate tangents, i.e. the partial derivatives of // position wrt. texture coordinates DG_MOTIONBLUR = (1 << 8), // calculate interpolated transformations for MB } DG_PostIntersectFlags; #ifdef __cplusplus } // namespace ospray #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/common/Data.cpp000066400000000000000000000160351456566705700224600ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Data.h" #include "common/ISPCRTBuffers.h" #include "ospray/ospray.h" #include "rkcommon/utility/getEnvVar.h" #include "rkcommon/utility/multidim_index_sequence.h" namespace ospray { Data::Data(api::ISPCDevice &device, const void *sharedData, OSPDataType type, const vec3ul &numItems, const vec3l &byteStride, OSPDeleterCallback freeFunction, const void *userData) : ISPCDeviceObject(device), appSharedPtr((char *)sharedData), shared(true), type(type), numItems(numItems), byteStride(byteStride), freeFunction(freeFunction), userData(userData) { if (sharedData == nullptr) { throw std::runtime_error("OSPData: shared buffer is NULL"); } addr = appSharedPtr; init(); if (isObjectType(type)) { for (auto &&child : as()) { if (child) child->refInc(); } } } Data::Data(api::ISPCDevice &device, OSPDataType type, const vec3ul &numItems) : ISPCDeviceObject(device), shared(false), type(type), numItems(numItems), byteStride(0) { // TODO: is this pad out by 16 still needed? view = make_buffer_shared_unique(device.getIspcrtContext(), size() * sizeOf(type) + 16, ispcrt::SharedMemoryUsageHint::HostWriteDeviceRead); addr = view->data(); init(); if (isObjectType(type)) // XXX initialize always? or never? memset(addr, 0, size() * sizeOf(type)); } Data::~Data() { if (isObjectType(type)) { for (auto &&child : as()) { if (child) child->refDec(); } } if (freeFunction) { freeFunction(userData, appSharedPtr); } } ispc::Data1D Data::emptyData1D; void Data::init() { managedObjectType = OSP_DATA; if (reduce_min(numItems) == 0) throw std::out_of_range("OSPData: all numItems must be positive"); dimensions = std::max(1, (numItems.x > 1) + (numItems.y > 1) + (numItems.z > 1)); // compute strides if requested if (byteStride.x == 0) byteStride.x = sizeOf(type); if (byteStride.y == 0) byteStride.y = numItems.x * byteStride.x; if (byteStride.z == 0) byteStride.z = numItems.y * byteStride.y; #ifdef OSPRAY_TARGET_SYCL // Check if the shared data the app gave is actually in USM, if not we still // need to make a copy of it internally so it's accessible on the GPU if (shared) { ispcrt::Context &ispcrtContext = getISPCDevice().getIspcrtContext(); ispcrt::Device &ispcrtDevice = getISPCDevice().getIspcrtDevice(); const size_t sizeBytes = byteStride.z * numItems.z; auto memType = ispcrtDevice.getMemoryAllocType(addr); switch (memType) { case ISPCRT_ALLOC_TYPE_HOST: default: // std::cerr << "HOST..COPYING" << std::endl; shared = false; view = make_buffer_shared_unique(ispcrtContext, sizeBytes, // TODO: is a padding of +16 still needed? ispcrt::SharedMemoryUsageHint::HostWriteDeviceRead); addr = view->data(); std::memcpy(addr, appSharedPtr, sizeBytes); break; case ISPCRT_ALLOC_TYPE_SHARED: // std::cerr << "SHARED..USE IN PLACE" << std::endl; break; case ISPCRT_ALLOC_TYPE_DEVICE: static bool useDeviceMemory = (rkcommon::utility::getEnvVar("OSPRAY_ALLOW_DEVICE_MEMORY") .value_or(0) != 0); if (useDeviceMemory) { // std::cerr << "DEVICE..USE IN PLACE" << std::endl; addr = appSharedPtr; } else { // std::cerr << "DEVICE..COPYING" << std::endl; shared = false; // make a handle for the app's memory ISPCRTNewMemoryViewFlags memFlags = { ISPCRT_ALLOC_TYPE_DEVICE, ISPCRT_SM_APPLICATION_MANAGED_DEVICE}; ISPCRTMemoryView handleOnAppsMemory = ispcrtNewMemoryView( ispcrtDevice.handle(), appSharedPtr, sizeBytes, &memFlags); // make ospray's shared buffer view = make_buffer_shared_unique(ispcrtContext, sizeBytes, ispcrt::SharedMemoryUsageHint::HostWriteDeviceRead); // copy to it ispcrt::TaskQueue &ispcrtTaskQueue = getISPCDevice().getIspcrtQueue(); ispcrtCopyMemoryView(ispcrtTaskQueue.handle(), view->handle(), handleOnAppsMemory, sizeBytes); ispcrtTaskQueue.sync(); ispcrtRelease(handleOnAppsMemory); addr = view->data(); } break; } } #endif // precompute dominant axis and set at ispc-side proxy if (dimensions != 1) return; ispc.byteStride = byteStride.x; size_t numItems1D = numItems.x; if (numItems.y > 1) { ispc.byteStride = byteStride.y; numItems1D = numItems.y; } else if (numItems.z > 1) { ispc.byteStride = byteStride.z; numItems1D = numItems.z; } // finalize ispc-side ispc.addr = reinterpret_cast(addr); ispc.huge = std::abs(ispc.byteStride) * numItems1D > (size_t)std::numeric_limits::max(); ispc.numItems = (uint32_t)numItems1D; } bool Data::compact() const { return data() + sizeOf(type) * (size() - 1) == data(numItems - 1); } void Data::copy(const Data &source, const vec3ul &destinationIndex) { if (type != source.type && !(type == OSP_OBJECT && isObjectType(source.type))) { throw std::runtime_error(toString() + "::copy: types must match (cannot copy '" + stringFor(source.type) + "' into '" + stringFor(type) + "')"); } if (shared && !source.shared) { throw std::runtime_error( "OSPData::copy: cannot copy opaque (non-shared) data into shared " "data"); } if (anyLessThan(numItems, destinationIndex + source.numItems)) { throw std::out_of_range( "OSPData::copy: source does not fit into destination"); } if (byteStride == source.byteStride && data(destinationIndex) == source.data()) { // NoOP, no need to copy identical region // TODO markDirty(destinationIndex, destinationIndex + source.numItems); return; } index_sequence_3D srcIndices(source.numItems); for (auto srcIdx : srcIndices) { char *dst = data(srcIdx + destinationIndex); const char *src = source.data(srcIdx); if (isObjectType(type)) { const ManagedObject **srcO = (const ManagedObject **)src; if (*srcO) (*srcO)->refInc(); const ManagedObject **dstO = (const ManagedObject **)dst; if (*dstO) (*dstO)->refDec(); *dstO = *srcO; } else { memcpy(dst, src, sizeOf(type)); } } } #ifdef OSPRAY_TARGET_SYCL void Data::commit() { // If we were passed "shared" data that was not actually in USM we made a USM // copy of it, and need to update that copy on commit if (appSharedPtr && addr != appSharedPtr) { // FIXME: handle ISPCRT_ALLOC_TYPE_DEVICE memory (needs device copy) const size_t sizeBytes = byteStride.z * numItems.z; std::memcpy(addr, appSharedPtr, sizeBytes); } } #endif bool Data::isShared() const { return shared; } std::string Data::toString() const { return "ospray::Data"; } OSPTYPEFOR_DEFINITION(Data *); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/common/Data.h000066400000000000000000000237211456566705700221250ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include "ISPCDeviceObject.h" #include "StructShared.h" #include "ispcrt.hpp" // including "Data_ispc.h" breaks app code using SDK headers #ifndef __ISPC_STRUCT_Data1D__ #define __ISPC_STRUCT_Data1D__ namespace ispc { struct Data1D { uint8_t *addr; int64_t byteStride; uint32_t numItems; bool huge; }; } // namespace ispc #endif namespace ospray { template struct DataT; /*! \brief defines a data array (aka "buffer") type that contains 'n' items of a given type */ struct OSPRAY_SDK_INTERFACE Data : public ISPCDeviceObject { Data(api::ISPCDevice &device, const void *sharedData, OSPDataType, const vec3ul &numItems, const vec3l &byteStride, OSPDeleterCallback freeFunction = nullptr, const void *userData = nullptr); Data(api::ISPCDevice &device, OSPDataType, const vec3ul &numItems); virtual ~Data() override; virtual std::string toString() const override; size_t size() const; vec3l stride() const; char *data() const; char *data(const vec3ul &idx) const; bool compact() const; // all strides are natural void copy(const Data &source, const vec3ul &destinationIndex); #ifdef OSPRAY_TARGET_SYCL void commit() override; #endif bool isShared() const; template const DataT &as() const; template DataT &as(); template typename std::enable_if::value, bool>::type is() const; template typename std::enable_if::value, bool>::type is() const; protected: // The actual buffer storing the data std::unique_ptr> view; char *addr{nullptr}; // We need to track the appSharedPtr separately for the GPU backend, if we // were passed a shared ptr to memory that was not in USM we made a copy that // addr points to and we need to keep it in sync with the shared data from the // app. char *appSharedPtr{nullptr}; bool shared; public: OSPDataType type{OSP_UNKNOWN}; vec3ul numItems; protected: vec3l byteStride; public: int dimensions{0}; ispc::Data1D ispc; static ispc::Data1D emptyData1D; // dummy, zero-initialized private: void init(); // init dimensions and byteStride protected: OSPDeleterCallback freeFunction{nullptr}; const void *userData{nullptr}; }; OSPTYPEFOR_SPECIALIZATION(Data *, OSP_DATA); template class Iter { const Data &data; vec3ul idx; public: using iterator_category = std::forward_iterator_tag; using value_type = T; using difference_type = std::ptrdiff_t; using pointer = T *; using reference = T &; Iter(const Data &data, vec3ul idx) : data(data), idx(idx) {} Iter &operator++() { if (++idx.x >= data.numItems.x) { idx.x = 0; if (++idx.y >= data.numItems.y) { idx.y = 0; ++idx.z; } } return *this; } Iter operator++(int) { Iter retv(*this); ++(*this); return retv; } bool operator!=(Iter &other) const { return &data != &other.data || idx != other.idx; } T &operator*() const { return *reinterpret_cast(data.data(idx)); } }; template class Iter1D { char *addr{nullptr}; int64_t byteStride{1}; public: using iterator_category = std::forward_iterator_tag; using value_type = T; using difference_type = std::ptrdiff_t; using pointer = T *; using reference = T &; Iter1D(char *addr, int64_t byteStride) : addr(addr), byteStride(byteStride) {} Iter1D &operator++() { addr += byteStride; return *this; } Iter1D operator++(int) { Iter1D retv(*this); ++(*this); return retv; } bool operator==(const Iter1D &other) const { return addr == other.addr; } bool operator!=(const Iter1D &other) const { return addr != other.addr; } T &operator*() const { return *reinterpret_cast(addr); } T *operator->() const { return reinterpret_cast(addr); } }; template struct DataT : public Data { static_assert(DIM == 2 || DIM == 3, "only 1D, 2D or 3D DataT supported"); using value_type = T; using iterator = Iter; Iter begin() const { return Iter(*this, vec3ul(0)); } Iter end() const { return Iter(*this, vec3ul(0, 0, numItems.z)); } T &operator[](const vec_t &idx) { return *reinterpret_cast(data(idx)); } const T &operator[](const vec_t &idx) const { return const_cast *>(this)->operator[](idx); } T *data() const { return reinterpret_cast(addr); } }; template struct DataT : public Data { using value_type = T; using iterator = Iter1D; Iter1D begin() const { return Iter1D(addr, ispc.byteStride); } Iter1D end() const { return Iter1D(addr + ispc.byteStride * size(), ispc.byteStride); } T &operator[](int64_t idx) { return *reinterpret_cast(addr + ispc.byteStride * idx); } const T &operator[](int64_t idx) const { return const_cast *>(this)->operator[](idx); } T *data() const { return reinterpret_cast(addr); } int64_t stride() const { return ispc.byteStride; } }; template struct OSPTypeFor *> { static constexpr OSPDataType value = OSP_DATA; }; // Inlined definitions ////////////////////////////////////////////////////// inline const ispc::Data1D *ispc(Ref &dataRef) { if (dataRef && dataRef->size() > std::numeric_limits::max()) throw std::runtime_error( "data array too large (over 4B elements, index is limited to 32bit"); return dataRef && dataRef->dimensions == 1 ? &dataRef->ispc : &Data::emptyData1D; } template const ispc::Data1D *ispc(Ref> &dataRef) { return dataRef ? &dataRef->ispc : &Data::emptyData1D; } template ispc::Data1D *ispc(Ref> &dataRef) { return dataRef ? &dataRef->ispc : &Data::emptyData1D; } inline size_t Data::size() const { return numItems.x * numItems.y * numItems.z; } inline vec3l Data::stride() const { return byteStride; } inline char *Data::data() const { return addr; } inline char *Data::data(const vec3ul &idx) const { return addr + idx.x * byteStride.x + idx.y * byteStride.y + idx.z * byteStride.z; } template inline typename std::enable_if::value, bool>::type Data::is() const { auto toType = OSPTypeFor::type>::type *>::value; return (type == toType || (toType == OSP_OBJECT && isObjectType(type))) && dimensions <= DIM; // can iterate with higher dimensionality } template inline typename std::enable_if::value, bool>::type Data::is() const { // can iterate with higher dimensionality return type == OSPTypeFor::value && dimensions <= DIM; } template inline const DataT &Data::as() const { if (is()) return (DataT &)*this; else { std::stringstream ss; ss << "Incompatible type or dimension for DataT; requested type[dim]: " << stringFor(OSPTypeFor::value) << "[" << DIM << "], actual: " << stringFor(type) << "[" << dimensions << "]."; throw std::runtime_error(ss.str()); } } template inline DataT &Data::as() { if (is()) return (DataT &)*this; else { std::stringstream ss; ss << "Incompatible type or dimension for DataT; requested type[dim]: " << stringFor(OSPTypeFor::value) << "[" << DIM << "], actual: " << stringFor(type) << "[" << dimensions << "]."; throw std::runtime_error(ss.str()); } } template inline const Ref> ISPCDeviceObject::getParamDataT( const char *name, bool required, bool promoteScalar) { Data *data = getParamObject(name); if (data && data->is()) return &(data->as()); // if no data array is found, look for single item of same type if (promoteScalar) { auto item = getOptParam(name); if (item) { // create data array and its reference object data = new Data(getISPCDevice(), OSPTypeFor::value, vec3ul(1)); Ref> refDataT = &data->as(); // 'data' reference counter equals to 2 now, // but we want it to be 1 and the 'data' to be referenced only by the // returned object for proper destruction data->refDec(); // place value into 'data' array T *p = refDataT->data(); *p = item.value(); // if we are inserting 'ManagedObject' we need to increase its reference // counter, too if (isObjectType(data->type)) (*data->as().begin())->refInc(); return refDataT; } } if (required) { std::string msg(toString() + " must have '" + name + "' " + std::to_string(DIM) + "D array with element type " + stringFor(OSPTypeFor::value)); if (data) msg.append(", found " + std::to_string(data->dimensions) + "D array with element type " + stringFor(data->type)); throw std::runtime_error(msg); } else { if (data) { postStatusMsg(OSP_LOG_DEBUG) << toString() << " ignoring '" << name << "' " << data->dimensions << "D array with element type " << stringFor(data->type) << " (while looking for " << DIM << "D array of " << stringFor(OSPTypeFor::value) << ")"; } return nullptr; } } template std::vector createArrayOfSh(const DataT &data) { std::vector retval; retval.reserve(data.size()); for (auto &&obj : data) retval.push_back(obj->getSh()); return retval; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/common/Data.ih000066400000000000000000000067751456566705700223100ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/LinearSpace.ih" #include "rkcommon/math/box.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Data1D { uint8 *addr; int64 byteStride; uint32 numItems; bool huge; // 64bit address calculation necessary }; inline void Data1D_Constructor(Data1D *uniform self) { self->addr = NULL; self->byteStride = 0; self->numItems = 0; self->huge = false; } // ok to pass-by-value, will be inlined and optimized inline uniform bool valid(const uniform Data1D data) { return data.addr != NULL; } // special 64-bit safe code: #define BITS 20 template inline varying T get(const uniform Data1D &data, const varying int index) { return *((const uniform T *)(data.addr + data.byteStride * index)); } // ok to pass-by-value, will be inlined and optimized #ifdef OSPRAY_TARGET_SYCL // SYCL execution in a thread is scalar // Old macro version (kept for compatibility with older code) #define __define_get(T) \ inline uniform T get_##T(const uniform Data1D data, const uniform int index) \ { \ return *((const T *)(data.addr + data.byteStride * index)); \ } #else #define __define_get(T) \ inline T get_##T(const uniform Data1D data, const varying int index) \ { \ if (data.huge) { \ T v; \ const int index_lo = index & ((1 << BITS) - 1); \ const int index_hi = index - index_lo; \ const int scaledIndexLo = index_lo * data.byteStride; \ foreach_unique (hi in index_hi) { \ /* uniform offset for upper bits */ \ const uniform uint64 scaledIndexHi = (uint64)(hi)*data.byteStride; \ /* properly shifted base address (shifted by 64-bits) */ \ const uint8 *uniform base_hi = data.addr + scaledIndexHi; \ v = *((const T *)(base_hi + scaledIndexLo)); \ } \ return v; \ } else \ return *((const T *)(data.addr + data.byteStride * index)); \ } \ inline uniform T get_##T(const uniform Data1D data, const uniform int index) \ { \ return *((const T *)(data.addr + data.byteStride * index)); \ } #endif __define_get(int32); __define_get(vec2i); __define_get(vec3i); __define_get(vec4i); __define_get(uint8); __define_get(uint32); __define_get(vec2ui); __define_get(vec3ui); __define_get(vec4ui); __define_get(float); __define_get(vec2f); __define_get(vec3f); __define_get(vec4f); __define_get(box1f); __define_get(box2f); __define_get(box3f); __define_get(box4f); __define_get(linear3f); #undef __define_get #undef BITS OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/common/DifferentialGeometry.ih000066400000000000000000000042611456566705700255330ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "DGEnum.h" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Material; struct Renderer; /* differential geometry information that gives more detailed information on the actual geometry that a ray has hit */ struct DifferentialGeometry { vec3f P; // world space location of the hit-point, includes epsilon offset // towards front side vec3f lP; // local instance space location of the hit-point vec3f Ng; // geometry normal if DG_NG was set, possibly not // normalized/facefordwarded if DG_NORMALIZE and/or DG_FACEFORWARD // weren't specified vec3f Ns; // shading normal if DG_NS was set, possibly not // normalized/facefordwarded if DG_NORMALIZE and/or DG_FACEFORWARD // weren't specified vec3f dPds; // tangent, the partial derivative of the hit-point wrt. tc s vec3f dPdt; // bi-tangent, the partial derivative of the hit-point wrt. tc t vec2f st; // texture coordinates if DG_TEXCOORD was set vec4f color; // interpolated vertex color (rgba) if DG_COLOR was set; defaults // to vec4f(1.f) if queried but not present in geometry int32 primID; // hit primitive (-1 if no hit), e.g. for Ptex float areaPDF; // for geometryLights float epsilon; // adaptive epsilon, isotropic in object-space Material *material; // pointer to hit-point's material const Renderer *uniform renderer; // pointer to renderer being used unsigned int objID; // user definable model id (0xffff none) unsigned int instID; // user definable instance id (0xffff none) }; // assumed precision of intersection routines #define ulpEpsilon 0x1.0fp-21f inline float calcEpsilon(const vec3f &P, const vec3f &dir, float t) { // convert ray-space t to object-/world-space using max(dir) instead of // costly length; the error is at most sqrt(3)~1.7, quite acceptable for eps return reduce_max(make_vec4f(abs(P), reduce_max(abs(dir)) * t)) * ulpEpsilon; } inline float calcEpsilon(const vec3f &P, float dist) { const vec3f dummy_dir = make_vec3f(1.0f); return calcEpsilon(P, dummy_dir, dist); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/common/Embree.h000066400000000000000000000003511456566705700224450ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef OSPRAY_TARGET_SYCL #include #endif #ifdef ISPC #include "embree4/rtcore.isph" #else #include "embree4/rtcore.h" #endif RenderKit-ospray-f2a61c2/modules/cpu/common/FeatureFlags.ih000066400000000000000000000026001456566705700237660ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef OSPRAY_TARGET_SYCL #include #endif #include "FeatureFlagsEnum.h" OSPRAY_BEGIN_ISPC_NAMESPACE #ifdef OSPRAY_TARGET_SYCL using namespace ospray; inline constexpr sycl::specialization_id specFeatureFlags; #endif struct FeatureFlagsHandler { #ifdef OSPRAY_TARGET_SYCL sycl::kernel_handler &kernel_handler; FeatureFlagsHandler(sycl::kernel_handler &kh) : kernel_handler(kh) {} #endif }; inline uniform FeatureFlags ffAll() { uniform FeatureFlags ff; ff.geometry = FFG_ALL; #ifdef OSPRAY_ENABLE_VOLUMES ff.volume = VKL_FEATURE_FLAGS_DEFAULT; #endif ff.other = FFO_ALL; return ff; } inline uniform FeatureFlags getFeatureFlags( const uniform FeatureFlagsHandler &ffh) { #ifdef OSPRAY_TARGET_SYCL return ffh.kernel_handler.get_specialization_constant(); #else return ffAll(); #endif } // For working around https://github.com/ispc/ispc/issues/2533 inline uniform FeatureFlagsGeometry getFeatureFlagsGeometry( const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlags ff = getFeatureFlags(ffh); return ff.geometry; } inline uniform FeatureFlagsOther getFeatureFlagsOther( const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlags ff = getFeatureFlags(ffh); return ff.other; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/common/FeatureFlagsEnum.h000066400000000000000000000124751456566705700244550ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef OSPRAY_ENABLE_VOLUMES #ifdef ISPC #include #else #include #endif #endif #include "common/Embree.h" #ifdef __cplusplus #include #include namespace ospray { #endif // __cplusplus enum FeatureFlagsGeometry #ifdef __cplusplus : uint32_t #endif { FFG_NONE = RTC_FEATURE_FLAG_NONE, FFG_MOTION_BLUR = RTC_FEATURE_FLAG_MOTION_BLUR, FFG_TRIANGLE = RTC_FEATURE_FLAG_TRIANGLE, FFG_QUAD = RTC_FEATURE_FLAG_QUAD, FFG_GRID = RTC_FEATURE_FLAG_GRID, FFG_SUBDIVISION = RTC_FEATURE_FLAG_SUBDIVISION, FFG_CONE_LINEAR_CURVE = RTC_FEATURE_FLAG_CONE_LINEAR_CURVE, FFG_ROUND_LINEAR_CURVE = RTC_FEATURE_FLAG_ROUND_LINEAR_CURVE, FFG_FLAT_LINEAR_CURVE = RTC_FEATURE_FLAG_FLAT_LINEAR_CURVE, FFG_ROUND_BEZIER_CURVE = RTC_FEATURE_FLAG_ROUND_BEZIER_CURVE, FFG_FLAT_BEZIER_CURVE = RTC_FEATURE_FLAG_FLAT_BEZIER_CURVE, FFG_NORMAL_ORIENTED_BEZIER_CURVE = RTC_FEATURE_FLAG_NORMAL_ORIENTED_BEZIER_CURVE, FFG_ROUND_BSPLINE_CURVE = RTC_FEATURE_FLAG_ROUND_BSPLINE_CURVE, FFG_FLAT_BSPLINE_CURVE = RTC_FEATURE_FLAG_FLAT_BSPLINE_CURVE, FFG_NORMAL_ORIENTED_BSPLINE_CURVE = RTC_FEATURE_FLAG_NORMAL_ORIENTED_BSPLINE_CURVE, FFG_ROUND_HERMITE_CURVE = RTC_FEATURE_FLAG_ROUND_HERMITE_CURVE, FFG_FLAT_HERMITE_CURVE = RTC_FEATURE_FLAG_FLAT_HERMITE_CURVE, FFG_NORMAL_ORIENTED_HERMITE_CURVE = RTC_FEATURE_FLAG_NORMAL_ORIENTED_HERMITE_CURVE, FFG_ROUND_CATMULL_ROM_CURVE = RTC_FEATURE_FLAG_ROUND_CATMULL_ROM_CURVE, FFG_FLAT_CATMULL_ROM_CURVE = RTC_FEATURE_FLAG_FLAT_CATMULL_ROM_CURVE, FFG_NORMAL_ORIENTED_CATMULL_ROM_CURVE = RTC_FEATURE_FLAG_NORMAL_ORIENTED_CATMULL_ROM_CURVE, FFG_SPHERE = RTC_FEATURE_FLAG_SPHERE_POINT, FFG_DISC_POINT = RTC_FEATURE_FLAG_DISC_POINT, FFG_ORIENTED_DISC_POINT = RTC_FEATURE_FLAG_ORIENTED_DISC_POINT, FFG_SPHERES = RTC_FEATURE_FLAG_POINT, FFG_CURVES = RTC_FEATURE_FLAG_CURVES, // OSPRay specific flags // repurposing unused flags below from Embree for FFG_BOX/PLANE/ISOSURFACE FFG_OSPRAY_MASK = 0 | RTC_FEATURE_FLAG_USER_GEOMETRY_CALLBACK_IN_GEOMETRY | RTC_FEATURE_FLAG_FILTER_FUNCTION_IN_GEOMETRY | RTC_FEATURE_FLAG_32_BIT_RAY_MASK, FFG_BOX = 0 | RTC_FEATURE_FLAG_USER_GEOMETRY_CALLBACK_IN_ARGUMENTS | RTC_FEATURE_FLAG_USER_GEOMETRY_CALLBACK_IN_GEOMETRY, FFG_PLANE = 0 | RTC_FEATURE_FLAG_USER_GEOMETRY_CALLBACK_IN_ARGUMENTS | RTC_FEATURE_FLAG_FILTER_FUNCTION_IN_GEOMETRY, FFG_ISOSURFACE = 0 | RTC_FEATURE_FLAG_USER_GEOMETRY_CALLBACK_IN_ARGUMENTS | RTC_FEATURE_FLAG_32_BIT_RAY_MASK, FFG_ALL = RTC_FEATURE_FLAG_ALL }; enum FeatureFlagsOther #ifdef __cplusplus : uint32_t #endif { FFO_NONE = 0, FFO_FB_LOCAL = 1 << 0, FFO_FB_SPARSE = 1 << 1, FFO_CAMERA_PERSPECTIVE = 1 << 2, FFO_CAMERA_ORTHOGRAPHIC = 1 << 3, FFO_CAMERA_PANORAMIC = 1 << 4, FFO_LIGHT_AMBIENT = 1 << 5, FFO_LIGHT_CYLINDER = 1 << 6, FFO_LIGHT_DIRECTIONAL = 1 << 7, FFO_LIGHT_HDRI = 1 << 8, FFO_LIGHT_POINT = 1 << 9, FFO_LIGHT_QUAD = 1 << 10, FFO_LIGHT_SPOT = 1 << 11, FFO_LIGHT_GEOMETRY = 1 << 12, FFO_MATERIAL_ALLOY = 1 << 13, FFO_MATERIAL_CARPAINT = 1 << 14, FFO_MATERIAL_GLASS = 1 << 15, FFO_MATERIAL_LUMINOUS = 1 << 16, FFO_MATERIAL_METAL = 1 << 17, FFO_MATERIAL_METALLICPAINT = 1 << 18, FFO_MATERIAL_MIX = 1 << 19, FFO_MATERIAL_OBJ = 1 << 20, FFO_MATERIAL_PLASTIC = 1 << 21, FFO_MATERIAL_PRINCIPLED = 1 << 22, FFO_MATERIAL_THINGLASS = 1 << 23, FFO_MATERIAL_VELVET = 1 << 24, FFO_TEXTURE_IN_MATERIAL = 1 << 25, FFO_TEXTURE_IN_RENDERER = 1 << 26, // We track if there's a volume object in the scene separately from the volume // feature flags to distinguish between needing the volume rendering/sampling // code paths or just needing the isosurface traversal code path. FFO_VOLUME_IN_SCENE = 1 << 27, // Volume shading in SciVis renderer FFO_VOLUME_SCIVIS_SHADING = 1 << 28, FFO_CAMERA_MOTION_BLUR = 1 << 29, FFO_ALL = 0xffffffff }; struct FeatureFlags { FeatureFlagsGeometry geometry; FeatureFlagsOther other; #ifdef OSPRAY_ENABLE_VOLUMES VKLFeatureFlags volume; #endif #ifdef __cplusplus constexpr FeatureFlags() : geometry(FFG_NONE), other(FFO_NONE) #ifdef OSPRAY_ENABLE_VOLUMES , volume(VKL_FEATURE_FLAGS_NONE) #endif {} void reset() { geometry = FFG_NONE; other = FFO_NONE; #ifdef OSPRAY_ENABLE_VOLUMES volume = VKL_FEATURE_FLAGS_NONE; #endif } #endif }; #ifdef __cplusplus template ::value>::type> inline T operator|(T a, T b) { return static_cast(static_cast(a) | static_cast(b)); } template ::value>::type> inline T &operator|=(T &a, T b) { return a = a | b; } inline FeatureFlags operator|(const FeatureFlags &a, const FeatureFlags &b) { FeatureFlags ff; ff.geometry = a.geometry | b.geometry; #ifdef OSPRAY_ENABLE_VOLUMES ff.volume = a.volume | b.volume; #endif ff.other = a.other | b.other; return ff; } inline FeatureFlags &operator|=(FeatureFlags &a, const FeatureFlags &b) { a.geometry |= b.geometry; #ifdef OSPRAY_ENABLE_VOLUMES a.volume |= b.volume; #endif a.other |= b.other; return a; } #endif #ifdef __cplusplus } // namespace ospray #endif RenderKit-ospray-f2a61c2/modules/cpu/common/FilterIntersect.ih000066400000000000000000000062021456566705700245260ustar00rootroot00000000000000// Copyright 2019 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Intersect.ih" #include "Ray.ih" #include "RayQueryContext.ih" OSPRAY_BEGIN_ISPC_NAMESPACE #ifndef OSPRAY_TARGET_SYCL unmasked void clippingIntersectionFilterV( const RTCFilterFunctionNArguments *uniform args); inline bool filterCall(const RTCIntersectFunctionNArguments *uniform args, const RTCHit &rtcHitTemp) { varying int imask; varying bool mask = __mask; unmasked { imask = mask ? -1 : 0; } // call filter intersection callback uniform RTCFilterFunctionNArguments filterArgs; filterArgs.valid = (int *uniform) & imask; filterArgs.geometryUserPtr = args->geometryUserPtr; filterArgs.context = args->context; filterArgs.ray = (RTCRayN * uniform) args->rayhit; filterArgs.hit = (RTCHitN * uniform) & rtcHitTemp; filterArgs.N = args->N; clippingIntersectionFilterV(&filterArgs); // return true if hit has been accepted return imask == -1; } #endif inline bool filterIntersectionSingle( const RTCIntersectFunctionNArguments *uniform args, const Hit &hit, const uniform bool isOcclusionTest, const uniform bool alwaysReject) { // if there is a hit varying Ray *uniform ray = (varying Ray * uniform) args->rayhit; if (hit.hit && hit.t > ray->t0 && hit.t <= ray->t) { // set a new hit value const float tOld = ray->t; ray->t = hit.t; // prepare temporary hit structure RTCHit rtcHitTemp; rtcHitTemp.Ng_x = hit.N.x; rtcHitTemp.Ng_y = hit.N.y; rtcHitTemp.Ng_z = hit.N.z; rtcHitTemp.u = hit.u; rtcHitTemp.v = 0.f; rtcHitTemp.primID = args->primID; rtcHitTemp.geomID = args->geomID; rtcHitTemp.instID[0] = args->context->instID[0]; // call filter intersection callback if needed #ifndef OSPRAY_TARGET_SYCL RayQueryContextDefault *uniform ctx = (RayQueryContextDefault * uniform) args->context; const uniform bool noFilter = ctx->type != RQCT_CLIPPING; const bool accept = noFilter || filterCall(args, rtcHitTemp); #else const bool accept = true; #endif if (alwaysReject) { // the hit is always rejected ray->t = tOld; } else { if (accept) { // hit has been accepted if (isOcclusionTest) { ray->t = neg_inf; } else { ray->Ng.x = hit.N.x; ray->Ng.y = hit.N.y; ray->Ng.z = hit.N.z; ray->u = hit.u; ray->v = 0.f; ray->primID = args->primID; ray->geomID = args->geomID; ray->instID = args->context->instID[0]; } return true; } else { // the hit has been rejected in the filter function, // restore initial ray dimensions ray->t = tOld; } } } // no hit or not accepted return false; } inline bool filterIntersectionBoth( const RTCIntersectFunctionNArguments *uniform args, const Intersections &isect, const uniform bool isOcclusionTest) { if (!filterIntersectionSingle(args, isect.entry, isOcclusionTest, false)) { return filterIntersectionSingle(args, isect.exit, isOcclusionTest, false); } return true; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/common/Future.cpp000066400000000000000000000004521456566705700230550ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Future.h" namespace ospray { Future::Future() { managedObjectType = OSP_FUTURE; } std::string Future::toString() const { return "ospray::Future"; } OSPTYPEFOR_DEFINITION(Future *); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/common/Future.h000066400000000000000000000011121456566705700225140ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "./Managed.h" namespace ospray { struct OSPRAY_SDK_INTERFACE Future : public ManagedObject { Future(); ~Future() override = default; std::string toString() const override; virtual bool isFinished(OSPSyncEvent = OSP_TASK_FINISHED) = 0; virtual void wait(OSPSyncEvent = OSP_TASK_FINISHED) = 0; virtual void cancel() = 0; virtual float getProgress() = 0; virtual float getTaskDuration() = 0; }; OSPTYPEFOR_SPECIALIZATION(Future *, OSP_FUTURE); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/common/Group.cpp000066400000000000000000000146051456566705700227040ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Group.h" #include "ISPCDevice.h" #include "geometry/GeometricModel.h" #include "lights/Light.h" #ifdef OSPRAY_ENABLE_VOLUMES #include "volume/VolumetricModel.h" #endif namespace ospray { // Embree helper functions ////////////////////////////////////////////////// template inline void createEmbreeScene(RTCScene &scene, FeatureFlags &featureFlags, const DataT &objects, const int embreeFlags, const RTCBuildQuality buildQuality) { for (auto &&obj : objects) { rtcAttachGeometry(scene, obj->embreeGeometryHandle()); featureFlags |= obj->getFeatureFlags(); } rtcSetSceneFlags(scene, static_cast(embreeFlags)); rtcSetSceneBuildQuality(scene, buildQuality); } static void freeAndNullifyEmbreeScene(RTCScene &scene) { if (scene) rtcReleaseScene(scene); scene = nullptr; } // Group definitions //////////////////////////////////////////////////////// Group::Group(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device) { managedObjectType = OSP_GROUP; } Group::~Group() { freeAndNullifyEmbreeScene(sceneGeometries); #ifdef OSPRAY_ENABLE_VOLUMES freeAndNullifyEmbreeScene(sceneVolumes); #endif freeAndNullifyEmbreeScene(sceneClippers); getSh()->geometricModels = nullptr; #ifdef OSPRAY_ENABLE_VOLUMES getSh()->volumetricModels = nullptr; #endif getSh()->clipModels = nullptr; } std::string Group::toString() const { return "ospray::Group"; } void Group::commit() { geometricModels = getParamDataT("geometry"); #ifdef OSPRAY_ENABLE_VOLUMES volumetricModels = getParamDataT("volume"); #endif clipModels = getParamDataT("clippingGeometry"); lights = getParamDataT("light"); size_t numGeometries = geometricModels ? geometricModels->size() : 0; #ifdef OSPRAY_ENABLE_VOLUMES size_t numVolumes = volumetricModels ? volumetricModels->size() : 0; #endif size_t numClippers = clipModels ? clipModels->size() : 0; size_t numLights = lights ? lights->size() : 0; postStatusMsg(OSP_LOG_DEBUG) << "=======================================================\n" << "Finalizing instance, which has " << numGeometries << " geometries, " #ifdef OSPRAY_ENABLE_VOLUMES << numVolumes << " volumes, " #endif << numClippers << " clipping geometries and " << numLights << " lights"; int sceneFlags = RTC_SCENE_FLAG_NONE; RTCBuildQuality buildQuality = RTC_BUILD_QUALITY_HIGH; if (getParam("dynamicScene", false)) { sceneFlags |= RTC_SCENE_FLAG_DYNAMIC; buildQuality = RTC_BUILD_QUALITY_LOW; } sceneFlags |= (getParam("compactMode", false) ? RTC_SCENE_FLAG_COMPACT : 0); sceneFlags |= (getParam("robustMode", false) ? RTC_SCENE_FLAG_ROBUST : 0); freeAndNullifyEmbreeScene(sceneGeometries); #ifdef OSPRAY_ENABLE_VOLUMES freeAndNullifyEmbreeScene(sceneVolumes); #endif freeAndNullifyEmbreeScene(sceneClippers); geometricModelsArray = nullptr; #ifdef OSPRAY_ENABLE_VOLUMES volumetricModelsArray = nullptr; #endif clipModelsArray = nullptr; getSh()->geometricModels = nullptr; #ifdef OSPRAY_ENABLE_VOLUMES getSh()->volumetricModels = nullptr; #endif getSh()->clipModels = nullptr; RTCDevice embreeDevice = getISPCDevice().getEmbreeDevice(); if (!embreeDevice) { throw std::runtime_error("invalid Embree device"); } featureFlags.reset(); if (numGeometries > 0) { sceneGeometries = rtcNewScene(embreeDevice); createEmbreeScene(sceneGeometries, featureFlags, *geometricModels, sceneFlags, buildQuality); geometricModelsArray = make_buffer_shared_unique( getISPCDevice().getIspcrtContext(), createArrayOfSh(*geometricModels)); getSh()->geometricModels = geometricModelsArray->sharedPtr(); rtcCommitScene(sceneGeometries); } #ifdef OSPRAY_ENABLE_VOLUMES if (numVolumes > 0) { sceneVolumes = rtcNewScene(embreeDevice); createEmbreeScene(sceneVolumes, featureFlags, *volumetricModels, sceneFlags, buildQuality); volumetricModelsArray = make_buffer_shared_unique( getISPCDevice().getIspcrtContext(), createArrayOfSh(*volumetricModels)); getSh()->volumetricModels = volumetricModelsArray->sharedPtr(); rtcCommitScene(sceneVolumes); } #endif if (numClippers > 0) { sceneClippers = rtcNewScene(embreeDevice); createEmbreeScene(sceneClippers, featureFlags, *clipModels, sceneFlags | RTC_SCENE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS | RTC_SCENE_FLAG_ROBUST, buildQuality); clipModelsArray = make_buffer_shared_unique( getISPCDevice().getIspcrtContext(), createArrayOfSh(*clipModels)); getSh()->clipModels = clipModelsArray->sharedPtr(); numInvertedClippers = 0; for (auto &&obj : *clipModels) numInvertedClippers += obj->invertedNormals() ? 1 : 0; rtcCommitScene(sceneClippers); } getSh()->numGeometricModels = numGeometries; #ifdef OSPRAY_ENABLE_VOLUMES getSh()->numVolumetricModels = numVolumes; #endif getSh()->numClipModels = numClippers; if (numLights > 0) { // Gather light types for (auto &&light : *lights) featureFlags |= light->getFeatureFlags(); // Create empty scene for lights-only group, // it is needed to have rtcGeometry created in Instance object // which in turn is needed for motion blur matrices interpolation if ((numGeometries == 0) #ifdef OSPRAY_ENABLE_VOLUMES && (numVolumes == 0) #endif && (numClippers == 0)) { sceneGeometries = rtcNewScene(embreeDevice); rtcCommitScene(sceneGeometries); } } } box3f Group::getBounds() const { box3f sceneBounds; box4f bounds; // NOTE(jda) - Embree expects box4f, NOT box3f... if (sceneGeometries) { rtcGetSceneBounds(sceneGeometries, (RTCBounds *)&bounds); sceneBounds.extend(box3f(vec3f(&bounds.lower[0]), vec3f(&bounds.upper[0]))); } #ifdef OSPRAY_ENABLE_VOLUMES if (sceneVolumes) { rtcGetSceneBounds(sceneVolumes, (RTCBounds *)&bounds); sceneBounds.extend(box3f(vec3f(&bounds.lower[0]), vec3f(&bounds.upper[0]))); } #endif return sceneBounds; } OSPTYPEFOR_DEFINITION(Group *); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/common/Group.h000066400000000000000000000030721456566705700223450ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray stuff #include "Data.h" #include "FeatureFlagsEnum.h" #include "ISPCDeviceObject.h" #include "StructShared.h" // stl #include // ispc shared #include "GroupShared.h" namespace ospray { struct GeometricModel; #ifdef OSPRAY_ENABLE_VOLUMES struct VolumetricModel; #endif struct Light; struct OSPRAY_SDK_INTERFACE Group : public AddStructShared { Group(api::ISPCDevice &device); ~Group() override; std::string toString() const override; void commit() override; box3f getBounds() const override; // Data members // Ref> geometricModels; #ifdef OSPRAY_ENABLE_VOLUMES Ref> volumetricModels; #endif Ref> clipModels; int numInvertedClippers{0}; Ref> lights; RTCScene sceneGeometries{nullptr}; #ifdef OSPRAY_ENABLE_VOLUMES RTCScene sceneVolumes{nullptr}; #endif RTCScene sceneClippers{nullptr}; const FeatureFlags &getFeatureFlags() const; private: FeatureFlags featureFlags; std::unique_ptr> geometricModelsArray; #ifdef OSPRAY_ENABLE_VOLUMES std::unique_ptr> volumetricModelsArray; #endif std::unique_ptr> clipModelsArray; }; OSPTYPEFOR_SPECIALIZATION(Group *, OSP_GROUP); inline const FeatureFlags &Group::getFeatureFlags() const { return featureFlags; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/common/GroupShared.h000066400000000000000000000014161456566705700234740ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct GeometricModel; #ifdef OSPRAY_ENABLE_VOLUMES struct VolumetricModel; #endif struct Group { GeometricModel **geometricModels; int32 numGeometricModels; #ifdef OSPRAY_ENABLE_VOLUMES VolumetricModel **volumetricModels; int32 numVolumetricModels; #endif GeometricModel **clipModels; int32 numClipModels; #ifdef __cplusplus Group() : geometricModels(nullptr), numGeometricModels(0), #ifdef OSPRAY_ENABLE_VOLUMES volumetricModels(nullptr), numVolumetricModels(0), #endif clipModels(nullptr), numClipModels(0) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/common/ISPCRTBuffers.h000066400000000000000000000147541456566705700236030ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include #include "ispcrt.hpp" namespace ospray { ///////////////////////////////////////////////////////////////////// // BufferDevice template struct BufferDevice : public ispcrt::Array { using ispcrt::Array::devicePtr; BufferDevice(ispcrt::Device &device, T *hostPtr = nullptr); BufferDevice(ispcrt::Device &device, size_t size); }; template BufferDevice::BufferDevice(ispcrt::Device &device, T *hostPtr) : ispcrt::Array(device, hostPtr) {} template BufferDevice::BufferDevice(ispcrt::Device &device, size_t size) : ispcrt::Array(device, nullptr, size) {} template inline std::unique_ptr> make_buffer_device_unique( Args &&...args) { return std::unique_ptr>( new BufferDevice(std::forward(args)...)); } ///////////////////////////////////////////////////////////////////// // BufferDeviceShadowed template struct BufferDeviceShadowed : public std::vector, public ispcrt::Array { using ispcrt::Array::devicePtr; using std::vector::size; BufferDeviceShadowed(ispcrt::Device &device, size_t size); BufferDeviceShadowed(ispcrt::Device &device, std::vector &v); BufferDeviceShadowed(ispcrt::Device &device, T *data, size_t size); }; template BufferDeviceShadowed::BufferDeviceShadowed( ispcrt::Device &device, size_t size) : std::vector(size), ispcrt::Array( device, std::vector::data(), size) {} template BufferDeviceShadowed::BufferDeviceShadowed( ispcrt::Device &device, std::vector &v) : std::vector(v), ispcrt::Array( device, std::vector::data(), v.size()) {} template BufferDeviceShadowed::BufferDeviceShadowed( ispcrt::Device &device, T *data, size_t size) : std::vector(data, data + size), ispcrt::Array( device, std::vector::data(), size) {} template inline std::unique_ptr> make_buffer_device_shadowed_unique(Args &&...args) { return std::unique_ptr>( new BufferDeviceShadowed(std::forward(args)...)); } ///////////////////////////////////////////////////////////////////// // BufferShared C version inline ISPCRTMemoryView BufferSharedCreate(ISPCRTContext context, size_t size, ISPCRTSharedMemoryAllocationHint allocHint = ISPCRT_SM_HOST_DEVICE_READ_WRITE) { ISPCRTNewMemoryViewFlags flags; flags.allocType = ISPCRT_ALLOC_TYPE_SHARED; flags.smHint = allocHint; return ispcrtNewMemoryViewForContext(context, nullptr, size, &flags); } inline void BufferSharedDelete(ISPCRTMemoryView view) { ispcrtRelease(view); } ///////////////////////////////////////////////////////////////////// // BufferShared C++ version template struct BufferShared : public ispcrt::Array { using ispcrt::Array::size; BufferShared(ispcrt::Context &context, ispcrt::SharedMemoryUsageHint allocHint = ispcrt::SharedMemoryUsageHint::HostDeviceReadWrite); BufferShared(ispcrt::Context &context, size_t size, ispcrt::SharedMemoryUsageHint allocHint = ispcrt::SharedMemoryUsageHint::HostDeviceReadWrite); BufferShared(ispcrt::Context &context, const std::vector &v, ispcrt::SharedMemoryUsageHint allocHint = ispcrt::SharedMemoryUsageHint::HostDeviceReadWrite); BufferShared(ispcrt::Context &context, const T *data, size_t size, ispcrt::SharedMemoryUsageHint allocHint = ispcrt::SharedMemoryUsageHint::HostDeviceReadWrite); T *data(); const T *data() const; T *begin(); T *end(); const T *cbegin() const; const T *cend() const; T &operator[](const size_t i); const T &operator[](const size_t i) const; T *sharedPtr() const; }; template BufferShared::BufferShared( ispcrt::Context &context, ispcrt::SharedMemoryUsageHint allocHint) : ispcrt::Array(context, allocHint) {} template BufferShared::BufferShared(ispcrt::Context &context, size_t size, ispcrt::SharedMemoryUsageHint allocHint) : ispcrt::Array(context, size, allocHint) {} template BufferShared::BufferShared(ispcrt::Context &context, const std::vector &v, ispcrt::SharedMemoryUsageHint allocHint) : ispcrt::Array(context, v.size(), allocHint) { std::memcpy(sharedPtr(), v.data(), sizeof(T) * v.size()); } template BufferShared::BufferShared(ispcrt::Context &context, const T *data, size_t size, ispcrt::SharedMemoryUsageHint allocHint) : ispcrt::Array(context, size, allocHint) { std::memcpy(sharedPtr(), data, sizeof(T) * size); } template T *BufferShared::data() { return sharedPtr(); } template const T *BufferShared::data() const { return sharedPtr(); } template T *BufferShared::begin() { return data(); } template T *BufferShared::end() { return begin() + size(); } template const T *BufferShared::cbegin() const { return data(); } template const T *BufferShared::cend() const { return cbegin() + size(); } template T &BufferShared::operator[](const size_t i) { return *(data() + i); } template const T &BufferShared::operator[](const size_t i) const { return *(data() + i); } // The below method is WA for Level Zero bug, when running on GPU sharedPtr() // crashes on 0-sized ispcrt::Array template T *BufferShared::sharedPtr() const { return size() ? ispcrt::Array::sharedPtr() : nullptr; } template inline std::unique_ptr> make_buffer_shared_unique( Args &&...args) { return std::unique_ptr>( new BufferShared(std::forward(args)...)); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/common/Instance.cpp000066400000000000000000000040371456566705700233520ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Instance.h" namespace ospray { Instance::Instance(api::ISPCDevice &device, Group *_group) : AddStructShared(device.getIspcrtContext(), device), groupAPI(_group) { managedObjectType = OSP_INSTANCE; } std::string Instance::toString() const { return "ospray::Instance"; } void Instance::commit() { group = getParamObject("group", groupAPI.ptr); if (!group) throw std::runtime_error(toString() + " received NULL 'group'"); motionTransform.readParams(*this); // Initialize shared structure getSh()->group = group->getSh(); getSh()->xfm = motionTransform.transform; getSh()->rcp_xfm = rcp(getSh()->xfm); getSh()->motionBlur = motionTransform.motionBlur; getSh()->userID = getParam("id", RTC_INVALID_GEOMETRY_ID); } box3f Instance::getBounds() const { box3f bounds; const box3f groupBounds = group->getBounds(); // TODO get better bounds: // - uses bounds at time 0.5, wrong if different shutter is used and does not // include motion at all // alternatives: // - merge linear bounds from Embree (which is for time [0, 1]), but this // needs a temporary RTCScene just for this instance // - extend over all transformed bounds // - this is too big, because keys outside of time [0, 1] are included // - yet is is also too small, because interpolated transformations can // lead to leaving the bounds of keys bounds.extend(xfmBounds(motionTransform.transform, groupBounds)); return bounds; } void Instance::setEmbreeGeom(RTCScene scene, unsigned int geomID) { RTCGeometry geom = rtcGetGeometry(scene, geomID); motionTransform.setEmbreeTransform(geom); getSh()->scene = scene; getSh()->geomID = geomID; if (getSh()->motionBlur) { rtcGetGeometryTransformFromScene(scene, geomID, .5f, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, &getSh()->xfm); // for SciVis getSh()->rcp_xfm = rcp(getSh()->xfm); } } OSPTYPEFOR_DEFINITION(Instance *); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/common/Instance.h000066400000000000000000000013401456566705700230110ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray stuff #include "Group.h" #include "MotionTransform.h" // ispc shared #include "InstanceShared.h" namespace ospray { struct OSPRAY_SDK_INTERFACE Instance : public AddStructShared { Instance(api::ISPCDevice &device, Group *group); ~Instance() override = default; std::string toString() const override; void commit() override; box3f getBounds() const override; void setEmbreeGeom(RTCScene scene, unsigned int geomID); Ref group; const Ref groupAPI; MotionTransform motionTransform; }; OSPTYPEFOR_SPECIALIZATION(Instance *, OSP_INSTANCE); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/common/Instance.ih000066400000000000000000000062771456566705700232000ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray stuff #include "../geometry/GeometricModel.ih" #include "DifferentialGeometry.ih" #include "OSPCommon.ih" #include "Ray.ih" // c++ shared #include "GroupShared.h" #include "InstanceShared.h" #include "common/FeatureFlagsEnum.h" #include "rkcommon/math/AffineSpace.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Renderer; inline uniform AffineSpace3f Instance_getTransform( const Instance *uniform self, const uniform float time) { uniform AffineSpace3f xfm; rtcGetGeometryTransformFromScene( self->scene, self->geomID, time, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, &xfm); return xfm; } #ifndef OSPRAY_TARGET_SYCL inline AffineSpace3f Instance_getTransform( const Instance *uniform self, const float time) { AffineSpace3f xfm; rtcGetGeometryTransformFromScene( self->scene, self->geomID, time, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, &xfm); return xfm; } #endif inline void Instance_postIntersect(const Instance *uniform self, const Renderer *uniform renderer, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags, const uniform bool clip, const uniform FeatureFlagsHandler &ffh) { GeometricModel **uniform models = clip ? self->group->clipModels : self->group->geometricModels; foreach_unique (geomID in ray.geomID) GeometricModel_postIntersect(models[geomID], renderer, dg, ray, flags, ffh); dg.instID = (self->userID == RTC_INVALID_GEOMETRY_ID) ? ray.instID : self->userID; uniform AffineSpace3f uxfm = self->xfm; uniform AffineSpace3f rcp_uxfm = self->rcp_xfm; const uniform FeatureFlagsGeometry ffg = getFeatureFlagsGeometry(ffh); if ((flags & DG_MOTIONBLUR) == DG_MOTIONBLUR && self->motionBlur && (ffg & FFG_MOTION_BLUR)) { uniform float utime; uniform int cnt = 0; foreach_unique (t in ray.time) { utime = t; cnt++; } if (cnt > 1) { // varying xfm const AffineSpace3f xfm = Instance_getTransform(self, ray.time); const AffineSpace3f rcp_xfm = rcp(xfm); dg.lP = xfmPoint(rcp_xfm, dg.P); dg.Ns = xfmVector(transposed(rcp_xfm.l), dg.Ns); dg.Ng = xfmVector(transposed(rcp_xfm.l), dg.Ng); // scale dg.epsilon by max (epsilon is scalar and thus assumed to be // isotropic anyway and hence cannot better handle non-uniform scaling) dg.epsilon *= max(abs(xfm.l.vx.x), max(abs(xfm.l.vy.y), abs(xfm.l.vz.z))); if (flags & DG_TANGENTS) { dg.dPds = xfmVector(xfm, dg.dPds); dg.dPdt = xfmVector(xfm, dg.dPdt); } return; } else { // uniform xfm uxfm = Instance_getTransform(self, utime); rcp_uxfm = rcp(uxfm); } } dg.lP = xfmPoint(rcp_uxfm, dg.P); dg.Ns = xfmVector(transposed(rcp_uxfm.l), dg.Ns); dg.Ng = xfmVector(transposed(rcp_uxfm.l), dg.Ng); // scale dg.epsilon by max (epsilon is scalar and thus assumed to be // isotropic anyway and hence cannot better handle non-uniform scaling) dg.epsilon *= max(abs(uxfm.l.vx.x), max(abs(uxfm.l.vy.y), abs(uxfm.l.vz.z))); if (flags & DG_TANGENTS) { dg.dPds = xfmVector(uxfm, dg.dPds); dg.dPdt = xfmVector(uxfm, dg.dPdt); } } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/common/InstanceShared.h000066400000000000000000000012701456566705700241420ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Group; struct Instance { Group *group; // Scene and geomID are used to call rtcGetGeometryTransformFromScene only RTCScene scene; unsigned int geomID; AffineSpace3f xfm; AffineSpace3f rcp_xfm; bool motionBlur; // user defined id. Typically used for picking uint32 userID; #ifdef __cplusplus Instance() : group(nullptr), scene(nullptr), geomID(0), xfm(one), rcp_xfm(one), motionBlur(false), userID(-1u) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/common/Intersect.ih000066400000000000000000000162061456566705700233650ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/box.ih" // Ray intersection structures ////////////////////////////////////////////// OSPRAY_BEGIN_ISPC_NAMESPACE struct Hit { bool hit; float t; vec3f N; float u; }; struct Intersections { Hit entry; Hit exit; }; // Ray intersection helpers /////////////////////////////////////////////////// // robust ray-sphere intersection inline Intersections intersectSphere(const vec3f &rayOrg, const vec3f &rayDir, const uniform vec3f ¢er, const uniform float radius) { Intersections isect; isect.entry.hit = false; isect.exit.hit = false; isect.entry.t = inf; isect.exit.t = -(float)inf; const vec3f d = rayDir; const float rd2 = 1.0f / dot(d, d); // 1/a const vec3f CO = center - rayOrg; // transformation to avoid missing a small sphere which is far away: // the standard c=CO^2-r^2 would quickly loose term r due to float arithmetic const float projCO = dot(CO, d) * rd2; // in ray-space const vec3f perp = CO - projCO * d; const float l2 = dot(perp, perp); const uniform float r2 = sqr(radius); if (l2 > r2) return isect; float td = sqrt((r2 - l2) * rd2); isect.entry.hit = true; isect.exit.hit = true; isect.entry.t = projCO - td; isect.exit.t = projCO + td; // above solutions are problematic if rays starts close to the sphere // (due to catastrophic cancellation, because then |projCO| ~ td) // the usual recommendation is to choose the one solution with same sign: // const float t1 = projCO + floatbits(signbits(projCO)|intbits(td)); // and compute the other solution via t1*t2=c/a: // const float t2 = (dot(CO, CO) - r2) / t1 * rd2; // this is more precise, but still problematic in particular for large // spheres, because |CO| ~ r; slightly better alternative, but costly sqrt: // const float f = sqrt(dot(CO, CO)); // const float t2 = (f - radius) * (f + radius) / t1 * rd2; // the only variant I found that has high enough precision to avoid // self-intersections of 2ndary rays is to (re-)compute most terms (CO, dot, // r2, t2) with doubles; large spheres are a rare usecase for OSPRay, thus we // use instead as a workaround an additional, radius-dependent epsilon // cannot easily be moved to postIntersect // we need hit in object space, in postIntersect it is in world-space isect.entry.N = -td * d - perp; isect.exit.N = td * d - perp; return isect; } inline Intersections intersectCylinder(const vec3f &rayOrg, const vec3f &rayDir, const uniform vec3f &v0, const uniform vec3f &v1, const uniform float radius) { Intersections isect; isect.entry.hit = false; isect.exit.hit = false; isect.entry.t = inf; isect.exit.t = -(float)inf; const uniform vec3f cZ = v1 - v0; const vec3f q = rayOrg - v0; const uniform float z2 = dot(cZ, cZ); const float d = dot(cZ, rayDir); const float c = dot(cZ, q); const float A = z2 - sqr(d); const float B = z2 * dot(q, rayDir) - c * d; const float C = z2 * dot(q, q) - sqr(c) - sqr(radius) * z2; float radical = B * B - A * C; if (radical < 0.f) { return isect; } radical = sqrt(radical); const float tin = (-B - radical) / A; const float tout = (-B + radical) / A; // first hit const float yin = c + tin * d; if (yin > 0.f && yin < z2) { // body hit isect.entry.hit = true; isect.entry.t = tin; isect.entry.u = yin * rcp(z2); isect.entry.N = (q + tin * rayDir - cZ * yin * rcp(z2)) * rcp(radius); } else { const float tcapin = (((yin < 0.f) ? 0.f : z2) - c) / d; if (abs(B + A * tcapin) < radical) { // cap hit isect.entry.hit = false; isect.entry.t = tin; isect.entry.u = (yin < 0.f) ? 0.f : 1.f; const float us = signbits(yin) ? -1.f : 1.f; isect.entry.N = cZ * us / z2; } } // second hit const float yout = c + tout * d; if (yout > 0.f && yout < z2) { // body hit isect.exit.hit = true; isect.exit.t = tout; isect.exit.u = yout * rcp(z2); isect.exit.N = (q + tout * rayDir - cZ * yout * rcp(z2)) * rcp(radius); } else { const float tcapout = (((yout < 0.f) ? 0.f : z2) - c) / d; if (abs(B + A * tcapout) < radical) { // cap hit isect.exit.hit = false; isect.exit.t = tout; isect.exit.u = (yout < 0.f) ? 0.f : 1.f; const float us = signbits(yout) ? -1.f : 1.f; isect.exit.N = cZ * us / z2; } } return isect; } inline Intersections intersectCapsule(const vec3f &rayOrg, const vec3f &rayDir, const uniform vec3f &v0, const uniform vec3f &v1, const uniform float radius) { Intersections isect_pipe = intersectCylinder(rayOrg, rayDir, v0, v1, radius); const Intersections isect_sph1 = intersectSphere(rayOrg, rayDir, v0, radius); const Intersections isect_sph2 = intersectSphere(rayOrg, rayDir, v1, radius); const float t_in = min(min(isect_sph1.entry.t, isect_sph2.entry.t), isect_pipe.entry.t); const float t_out = max(max(isect_sph1.exit.t, isect_sph2.exit.t), isect_pipe.exit.t); isect_pipe.entry.hit |= isect_sph1.entry.hit | isect_sph2.entry.hit; isect_pipe.entry.t = t_in; isect_pipe.exit.hit |= isect_sph1.exit.hit | isect_sph2.exit.hit; isect_pipe.exit.t = t_out; if (isect_sph1.entry.t == t_in) { isect_pipe.entry.u = 0.f; isect_pipe.entry.N = isect_sph1.entry.N; } else if (isect_sph2.entry.t == t_in) { isect_pipe.entry.u = 1.f; isect_pipe.entry.N = isect_sph2.entry.N; } if (isect_sph1.exit.t == t_out) { isect_pipe.exit.u = 0.f; isect_pipe.exit.N = isect_sph1.exit.N; } else if (isect_sph2.exit.t == t_out) { isect_pipe.exit.u = 1.f; isect_pipe.exit.N = isect_sph2.exit.N; } return isect_pipe; } inline Intersections intersectBox( const vec3f &rayOrg, const vec3f &rayDir, const uniform box3f &box) { Intersections isect; const vec3f mins = (box.lower - rayOrg) * rcp_safe(rayDir); const vec3f maxs = (box.upper - rayOrg) * rcp_safe(rayDir); const vec3f nears = min(mins, maxs); const vec3f fars = max(mins, maxs); isect.entry.t = reduce_max(nears); if (isect.entry.t == nears.x) isect.entry.N = make_vec3f(rayDir.x > 0.0f ? -1.0f : 1.0f, 0.0f, 0.0f); else if (isect.entry.t == nears.y) isect.entry.N = make_vec3f(0.0f, rayDir.y > 0.0f ? -1.0f : 1.0f, 0.0f); else isect.entry.N = make_vec3f(0.0f, 0.0f, rayDir.z > 0.0f ? -1.0f : 1.0f); isect.exit.t = reduce_min(fars); if (isect.exit.t == fars.x) isect.exit.N = make_vec3f(rayDir.x > 0.0f ? 1.0f : -1.0f, 0.0f, 0.0f); else if (isect.exit.t == fars.y) isect.exit.N = make_vec3f(0.0f, rayDir.y > 0.0f ? 1.0f : -1.0f, 0.0f); else isect.exit.N = make_vec3f(0.0f, 0.0f, rayDir.z > 0.0f ? 1.0f : -1.0f); isect.entry.hit = isect.entry.t < isect.exit.t; isect.exit.hit = isect.entry.hit; return isect; } inline Hit intersectPlane( const vec3f &rayOrg, const vec3f &rayDir, const uniform vec4f &plane) { Hit hit; hit.hit = false; const uniform vec3f normal = make_vec3f(plane); const float DdN = dot(rayDir, normal); hit.hit = DdN != 0.0f; hit.N = normal; hit.t = (plane.w - dot(rayOrg, normal)) * rcpf(DdN); return hit; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/common/MotionTransform.cpp000066400000000000000000000062721456566705700247520ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "MotionTransform.h" namespace ospray { void MotionTransform::readParams(ISPCDeviceObject &obj) { transforms = obj.getParamDataT("motion.transform"); if (transforms) { motionBlur = transforms->size() > 1; quaternion = false; transform = (*transforms)[0]; } else { // look for SRT auto shift = obj.getParamDataT("motion.pivot"); auto scale = obj.getParamDataT("motion.scale"); auto rotation = obj.getParamDataT("motion.rotation"); auto translation = obj.getParamDataT("motion.translation"); quaternion = shift || scale || rotation || translation; if (quaternion) { // determine (minimum) size size_t size = std::numeric_limits::max(); if (shift) size = shift->size(); if (scale) size = std::min(size, scale->size()); if (rotation) size = std::min(size, rotation->size()); if (translation) size = std::min(size, translation->size()); motionBlur = size > 1; quaternions.resize(size); for (size_t i = 0; i < size; i++) { auto *qdecomp = &quaternions[i]; rtcInitQuaternionDecomposition(qdecomp); if (shift) { const vec3f &s = (*shift)[i]; rtcQuaternionDecompositionSetShift(qdecomp, s.x, s.y, s.z); } if (scale) { const vec3f &s = (*scale)[i]; rtcQuaternionDecompositionSetScale(qdecomp, s.x, s.y, s.z); } if (rotation) { const quatf &q = (*rotation)[i]; rtcQuaternionDecompositionSetQuaternion(qdecomp, q.r, q.i, q.j, q.k); } if (translation) { const vec3f &t = (*translation)[i]; rtcQuaternionDecompositionSetTranslation(qdecomp, t.x, t.y, t.z); } } } else { // add single transform quaternions.clear(); motionBlur = false; transform = obj.getParam( "transform", obj.getParam("xfm", affine3f(one))); } } time = range1f(0.0f, 1.0f); if (motionBlur) { time = obj.getParam("time", range1f(0.0f, 1.0f)); if (time.upper < time.lower) time.upper = time.lower; } } void MotionTransform::setEmbreeTransform(RTCGeometry embreeGeometry) const { if (quaternion) { rtcSetGeometryTimeStepCount(embreeGeometry, quaternions.size()); for (size_t i = 0; i < quaternions.size(); i++) rtcSetGeometryTransformQuaternion(embreeGeometry, i, &quaternions[i]); rtcSetGeometryTimeRange(embreeGeometry, time.lower, time.upper); } else { if (motionBlur) { rtcSetGeometryTimeStepCount(embreeGeometry, transforms->size()); for (size_t i = 0; i < transforms->size(); i++) rtcSetGeometryTransform(embreeGeometry, i, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, &(*transforms)[i]); rtcSetGeometryTimeRange(embreeGeometry, time.lower, time.upper); } else { rtcSetGeometryTimeStepCount(embreeGeometry, 1); rtcSetGeometryTransform( embreeGeometry, 0, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR, transform); } } rtcCommitGeometry(embreeGeometry); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/common/MotionTransform.h000066400000000000000000000010431456566705700244060ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray stuff #include "Group.h" // embree #include "Embree.h" namespace ospray { struct OSPRAY_SDK_INTERFACE MotionTransform { void readParams(ISPCDeviceObject &); void setEmbreeTransform(RTCGeometry) const; affine3f transform{one}; bool motionBlur{false}; bool quaternion{false}; private: Ref> transforms; std::vector quaternions; range1f time{0.0f, 1.0f}; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/common/OSPCommon.ih000066400000000000000000000070041456566705700232330ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef OSPRAY_TARGET_SYCL #include #define __noinline __attribute__((noinline)) #define in , #define foreach_unique(var_in_set) FOREACH_UNIQUE(var_in_set) #define FOREACH_UNIQUE(var, set) for (const auto &var : {set}) namespace ispc { using uint64 = uint64_t; using uint32 = uint32_t; using uint16 = uint16_t; using uint8 = uint8_t; using int64 = int64_t; using int32 = int32_t; using int16 = int16_t; using int8 = int8_t; } // namespace ispc #define LOG(x) #undef PRINT #undef PRINT3 #define PRINT(x) #define PRINT3(x) #define PRINTU(x) #define PRINT3U(x) /* // Note: SYCL printf needs the type specifier, unlike ISPC. So instead of a // macro we make a function that looks like the macro but overloads based on the // type #ifdef __SYCL_DEVICE_ONLY__ // rkcommon has its own macros for the host that we conflict with #undef PRINT #undef PRINT3 void PRINT(const int &x) { sycl::ext::oneapi::experimental::printf("#x = %d\n", x); } void PRINT(const uint32_t &x) { sycl::ext::oneapi::experimental::printf("#x = %u\n", x); } void PRINT(const float &x) { sycl::ext::oneapi::experimental::printf("#x = %f\n", x); } void PRINT3(const rkcommon::math::vec3i &x) { sycl::ext::oneapi::experimental::printf( "#x = (%d, %d, %d)\n", x.x, x.y, x.z); } void PRINT3(const rkcommon::math::vec3ui &x) { sycl::ext::oneapi::experimental::printf( "#x = (%u, %u, %u)\n", x.x, x.y, x.z); } void PRINT3(const rkcommon::math::vec3f &x) { sycl::ext::oneapi::experimental::printf( "#x = (%f, %f, %f)\n", x.x, x.y, x.z); } // SYCL is scalar, PRINTU = PRINT, PRINT3U = PRINT3 #define PRINTU(x) PRINT #define PRINT3U(x) PRINT3 #define PRINT_STR(s) sycl::ext::oneapi::experimental::printf(s); #endif */ #else #define __noinline #define LOG(x) #define PRINT(x) print(#x " = %\n", x) #define PRINT3(v) print(#v " = (%, %, %)\n", v.x, v.y, v.z) // prints first unmasked element #define PRINTU(x) \ print(#x "[%] = %\n", \ count_trailing_zeros(lanemask()), \ extract(x, count_trailing_zeros(lanemask()))) #define PRINT2U(v) \ print(#v "[%] = (%, %)\n", \ count_trailing_zeros(lanemask()), \ extract(v.x, count_trailing_zeros(lanemask())), \ extract(v.y, count_trailing_zeros(lanemask()))) #define PRINT3U(v) \ print(#v "[%] = (%, %, %)\n", \ count_trailing_zeros(lanemask()), \ extract(v.x, count_trailing_zeros(lanemask())), \ extract(v.y, count_trailing_zeros(lanemask())), \ extract(v.z, count_trailing_zeros(lanemask()))) #define PRINT_STR(s) print(s); #endif #ifndef OSPRAY_TARGET_SYCL /*! 64-bit malloc. allows for alloc'ing memory larger than 64 bits */ extern "C" void *uniform malloc64(uniform uint64 size); extern "C" void free64(void *uniform ptr); /*! Thread Local Storage functions */ extern "C" void *uniform pushTLS(uniform uint64 size); extern "C" void *uniform reallocTLS(void *uniform ptr, uniform uint64 size); extern "C" void popTLS(void *uniform ptr); #endif RenderKit-ospray-f2a61c2/modules/cpu/common/OSPConfig.h.in000066400000000000000000000003541456566705700234450ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #define TILE_SIZE @OSPRAY_TILE_SIZE@ #define MAX_TILE_SIZE @OSPRAY_MAX_STACK_TILE_SIZE@ #define OSPRAY_RENDER_TASK_SIZE @OSPRAY_RENDER_TASK_SIZE@ RenderKit-ospray-f2a61c2/modules/cpu/common/Ray.ih000066400000000000000000000044261456566705700221610ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray #include "rkcommon/math/AffineSpace.ih" #include "rkcommon/math/vec.ih" // embree #include "Embree.h" OSPRAY_BEGIN_ISPC_NAMESPACE // NOTE(jda) - this MUST match Embree's RayHit structure layout! struct Ray { /* ray input data */ vec3f org; /*!< ray origin */ float t0; /*!< start of valid ray interval */ vec3f dir; /*!< ray direction */ float time; //!< Time of this ray for motion blur, in 0..1 float t; /*!< end of valid ray interval, or distance to hit point after 'intersect' */ uint32 mask; //!< Used to mask out objects during traversal uint32 rayID; uint32 flags; /* hit data */ vec3f Ng; /*! geometry normal*/ float u; //!< Barycentric u coordinate of hit float v; //!< Barycentric v coordinate of hit uint32 primID; //!< primitive ID uint32 geomID; //!< geometry ID uint32 instID; //!< instance ID #ifdef RTC_GEOMETRY_INSTANCE_ARRAY uint32 instPrimID; // not used, but need to pad #endif }; // Hit query functions //////////////////////////////////////////////////////// inline bool noHit(const Ray &ray) { return ray.geomID == RTC_INVALID_GEOMETRY_ID; } inline bool hadHit(const Ray &ray) { return !noHit(ray); } // Ray initialization ///////////////////////////////////////////////////////// inline void setRay(Ray &ray, const vec3f &ray_org, const vec3f &ray_dir, const float t0, const float t1, const float time = 0.5f) { ray.org = ray_org; ray.dir = ray_dir; ray.t0 = t0; ray.t = t1; ray.time = time; ray.mask = -1; ray.geomID = RTC_INVALID_GEOMETRY_ID; ray.primID = RTC_INVALID_GEOMETRY_ID; ray.instID = RTC_INVALID_GEOMETRY_ID; } inline void setRay(Ray &ray, const vec3f &ray_org, const vec3f &ray_dir, const float time = 0.5f) { setRay(ray, ray_org, ray_dir, 0.f, inf, time); } inline void setRay(Ray &ray, const float t0, const float t1) { setRay(ray, ray.org, ray.dir, t0, t1, ray.time); } // Ray transformation helpers ///////////////////////////////////////////////// inline void transformRay(Ray &ray, const AffineSpace3f &xfm) { ray.org = xfmPoint(xfm, ray.org); ray.dir = xfmVector(xfm, ray.dir); ray.Ng = xfmVector(transposed(xfm.l), ray.Ng); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/common/RayQueryContext.ih000066400000000000000000000013051456566705700245450ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray #include "FeatureFlags.ih" // embree #include "Embree.h" OSPRAY_BEGIN_ISPC_NAMESPACE #ifdef OSPRAY_TARGET_SYCL using namespace ospray; #endif enum RayQueryContextType { RQCT_DEFAULT, RQCT_CLIPPING, RQCT_UNKNOWN }; struct RayQueryContextDefault { RTCRayQueryContext ectx; RayQueryContextType type; const FeatureFlagsHandler *uniform ffh; }; inline void initRayQueryContextDefault(RayQueryContextDefault *uniform context, const uniform FeatureFlagsHandler &ffh) { rtcInitRayQueryContext(&context->ectx); context->type = RQCT_DEFAULT; context->ffh = &ffh; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/common/StructShared.h000066400000000000000000000104451456566705700236660ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include #include "rkcommon/common.h" #include "rkcommon/math/rkmath.h" #include "rkcommon/math/vec.h" #include "ISPCRTBuffers.h" namespace ispc { // Shared structure members may use types from rkcommon using namespace rkcommon; using namespace rkcommon::math; // Shared structure members may use ispc specific types using uint8 = uint8_t; using int32 = int32_t; using uint32 = uint32_t; using int64 = int64_t; } // namespace ispc namespace ospray { /* Usage: derive from AddStructShared We use multiple inheritance with a virtual base class, thus only a single instance of structSharedView is present, which will be initialized first. StructSharedGet adds getSh returning the correctly typed pointer. It is derived from first to handle the memory allocation with the maximum size of the final StructShared. StructSharedGet does not have any data to ensure final classes can be C-style casted to ManagedObject* (this pointer stays the same). */ template inline ISPCRTMemoryView StructSharedCreate(ISPCRTContext context) { ISPCRTMemoryView view = BufferSharedCreate(context, sizeof(T), ISPCRT_SM_HOST_WRITE_DEVICE_READ); new (ispcrtSharedPtr(view)) T; return view; } struct StructSharedView { ~StructSharedView(); template friend struct StructSharedGet; template friend struct AddStructShared; private: ISPCRTMemoryView _view{nullptr}; }; template struct StructSharedGet { StructSharedGet(ISPCRTContext, ISPCRTMemoryView *); T *getSh() const; }; // Traits ///////////////////////////////////////////////////// template struct make_void { using type = void; }; template using void_t = typename make_void::type; template struct get_base_structshared_or { using type = S; }; template struct get_base_structshared_or> { using type = typename T::StructShared_t; }; template struct get_super_or { using type = S; }; template struct get_super_or> { using type = decltype(S::super); }; // AddStructShared //////////////////////////////////////////// template struct AddStructShared : public StructSharedGet>, public Base, public virtual StructSharedView { using StructShared_t = Struct; using StructSharedGet>::getSh; static_assert( std::is_same::type, typename get_super_or::type>::value, "StructShared_t needs to have 'super' member of type Base::StructShared_t"); template AddStructShared(ispcrt::Context &context, Args &&...args) : StructSharedGet>( context.handle(), &_view), Base(std::forward(args)...) {} }; // Inlined definitions //////////////////////////////////////// inline StructSharedView::~StructSharedView() { BufferSharedDelete(_view); } template StructSharedGet::StructSharedGet( ISPCRTContext device, ISPCRTMemoryView *view) { if (!*view) *view = StructSharedCreate(device); } template T *StructSharedGet::getSh() const { return static_cast(ispcrtHostPtr(static_cast(this)->_view)); } // Testing //////////////////////////////////////////////////// namespace test { // clang-format off struct A {}; struct B { char b; }; struct D1 { B super; }; struct D2 { D1 super; char c; }; struct ShouldPass1 : public AddStructShared {}; struct ShouldPass2 : public AddStructShared {}; struct ShouldPass3 : public AddStructShared {}; //struct ShouldFail1 : public AddStructShared {}; //struct ShouldFail2 : public AddStructShared {}; //struct ShouldFail3 : public AddStructShared {}; // clang-format on } // namespace test } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/common/VolumeIntervals.ih000066400000000000000000000031541456566705700245620ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #pragma once #include "Instance.ih" #include "OSPCommon.ih" #include "rkcommon/math/AffineSpace.ih" #include "rkcommon/math/box.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct VolumetricModel; // Volume hit structure /////////////////////////////////////////////////////// struct VolumeInterval { VolumetricModel *volumetricModel; Instance *instance; range1f interval; unsigned int primID; unsigned int geomID; unsigned int instID; }; inline void initVolumeInterval(VolumeInterval &hit) { hit.volumetricModel = NULL; hit.interval.lower = inf; hit.interval.upper = -hit.interval.lower; } inline bool hasInterval(const VolumeInterval &vi) { return !isEmpty(vi.interval); } struct VolumeIntervals { unsigned int numVolumeIntervals; uniform unsigned int numAllocated; varying VolumeInterval *uniform intervals; }; #ifndef OSPRAY_TARGET_SYCL inline void allocVolumeIntervals(VolumeIntervals &intervals) { intervals.numVolumeIntervals = 0; intervals.numAllocated = 0; intervals.intervals = (varying VolumeInterval * uniform) pushTLS(0); } inline void freeVolumeIntervals(VolumeIntervals &intervals) { popTLS(intervals.intervals); intervals.intervals = NULL; } #endif struct RayQueryContextVolume { RTCRayQueryContext ectx; varying VolumeIntervals *intervals; }; inline void InitRayQueryContextVolume(RayQueryContextVolume *uniform context, varying VolumeIntervals *uniform intervals) { rtcInitRayQueryContext(&context->ectx); context->intervals = intervals; } OSPRAY_END_ISPC_NAMESPACE #endif RenderKit-ospray-f2a61c2/modules/cpu/common/World.cpp000066400000000000000000000135611456566705700226770ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "World.h" #include "Instance.h" #include "common/FeatureFlagsEnum.h" #include "lights/Light.h" #include "render/pathtracer/PathTracerData.h" #include "render/scivis/SciVisData.h" namespace ospray { // Embree helper functions /////////////////////////////////////////////////// static void addGeometryInstance(RTCScene &scene, RTCScene instScene, Instance *inst, RTCDevice embreeDevice, unsigned int id) { if (!embreeDevice) throw std::runtime_error("invalid Embree device"); // Create parent scene if not yet created if (!scene) scene = rtcNewScene(embreeDevice); // Create geometry instance auto eInst = rtcNewGeometry(embreeDevice, RTC_GEOMETRY_TYPE_INSTANCE); rtcSetGeometryInstancedScene(eInst, instScene); rtcAttachGeometryByID(scene, eInst, id); inst->setEmbreeGeom(scene, id); rtcReleaseGeometry(eInst); } static void freeAndNullifyEmbreeScene(RTCScene &scene) { if (scene) rtcReleaseScene(scene); scene = nullptr; } // World definitions //////////////////////////////////////////////////////// World::~World() { // Release Embree scenes freeAndNullifyEmbreeScene(getSh()->embreeSceneHandleGeometries); #ifdef OSPRAY_ENABLE_VOLUMES freeAndNullifyEmbreeScene(getSh()->embreeSceneHandleVolumes); #endif #ifndef OSPRAY_TARGET_SYCL freeAndNullifyEmbreeScene(getSh()->embreeSceneHandleClippers); #endif } World::World(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device) { managedObjectType = OSP_WORLD; } std::string World::toString() const { return "ospray::World"; } void World::commit() { RTCScene &esGeom = getSh()->embreeSceneHandleGeometries; #ifdef OSPRAY_ENABLE_VOLUMES RTCScene &esVol = getSh()->embreeSceneHandleVolumes; #endif #ifndef OSPRAY_TARGET_SYCL RTCScene &esClip = getSh()->embreeSceneHandleClippers; #endif freeAndNullifyEmbreeScene(esGeom); #ifdef OSPRAY_ENABLE_VOLUMES freeAndNullifyEmbreeScene(esVol); #endif #ifndef OSPRAY_TARGET_SYCL freeAndNullifyEmbreeScene(esClip); #endif scivisData = nullptr; pathtracerData = nullptr; instances = getParamDataT("instance"); lights = getParamDataT("light"); auto numInstances = instances ? instances->size() : 0; int sceneFlags = RTC_SCENE_FLAG_NONE; RTCBuildQuality buildQuality = RTC_BUILD_QUALITY_HIGH; if (getParam("dynamicScene", false)) { sceneFlags |= RTC_SCENE_FLAG_DYNAMIC; buildQuality = RTC_BUILD_QUALITY_LOW; } sceneFlags |= (getParam("compactMode", false) ? RTC_SCENE_FLAG_COMPACT : 0); sceneFlags |= (getParam("robustMode", false) ? RTC_SCENE_FLAG_ROBUST : 0); postStatusMsg(OSP_LOG_DEBUG) << "=======================================================\n" << "Committing world, which has " << numInstances << " instances and " << (lights ? lights->size() : 0) << " lights"; instanceArray = nullptr; getSh()->numInvertedClippers = 0; RTCDevice embreeDevice = getISPCDevice().getEmbreeDevice(); if (instances) { for (auto &&inst : *instances) #ifndef OSPRAY_TARGET_SYCL if (inst->group->sceneClippers) getSh()->numInvertedClippers += inst->group->numInvertedClippers; #endif // Create shared buffers for instance pointers instanceArray = make_buffer_shared_unique( getISPCDevice().getIspcrtContext(), sizeof(ispc::Instance *) * numInstances); getSh()->instances = instanceArray->sharedPtr(); // Populate shared buffer with instance pointers, // create Embree instances featureFlags.reset(); unsigned int id = 0; for (auto &&inst : *instances) { getSh()->instances[id] = inst->getSh(); if (inst->group->sceneGeometries) { addGeometryInstance( esGeom, inst->group->sceneGeometries, inst, embreeDevice, id); } #ifdef OSPRAY_ENABLE_VOLUMES if (inst->group->sceneVolumes) { addGeometryInstance( esVol, inst->group->sceneVolumes, inst, embreeDevice, id); } #endif #ifndef OSPRAY_TARGET_SYCL if (inst->group->sceneClippers) { addGeometryInstance( esClip, inst->group->sceneClippers, inst, embreeDevice, id); } #endif // Gather feature flags from all groups const FeatureFlags &gff = inst->group->getFeatureFlags(); if (inst->motionTransform.motionBlur) featureFlags.geometry |= FFG_MOTION_BLUR; featureFlags |= gff; id++; } } // Gather light types if (lights) { for (auto &&light : *lights) { featureFlags |= light->getFeatureFlags(); } } if (esGeom) { rtcSetSceneFlags(esGeom, static_cast(sceneFlags)); rtcSetSceneBuildQuality(esGeom, buildQuality); rtcCommitScene(esGeom); } #ifdef OSPRAY_ENABLE_VOLUMES if (esVol) { rtcSetSceneFlags(esVol, static_cast(sceneFlags)); rtcSetSceneBuildQuality(esVol, buildQuality); rtcCommitScene(esVol); } #endif #ifndef OSPRAY_TARGET_SYCL if (esClip) { rtcSetSceneFlags(esClip, static_cast( sceneFlags | RTC_SCENE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS)); rtcSetSceneBuildQuality(esClip, buildQuality); rtcCommitScene(esClip); } #endif } box3f World::getBounds() const { box3f sceneBounds; box4f bounds; // NOTE(jda) - Embree expects box4f, NOT box3f... if (getSh()->embreeSceneHandleGeometries) { rtcGetSceneBounds( getSh()->embreeSceneHandleGeometries, (RTCBounds *)&bounds); sceneBounds.extend(box3f(vec3f(&bounds.lower[0]), vec3f(&bounds.upper[0]))); } #ifdef OSPRAY_ENABLE_VOLUMES if (getSh()->embreeSceneHandleVolumes) { rtcGetSceneBounds(getSh()->embreeSceneHandleVolumes, (RTCBounds *)&bounds); sceneBounds.extend(box3f(vec3f(&bounds.lower[0]), vec3f(&bounds.upper[0]))); } #endif return sceneBounds; } OSPTYPEFOR_DEFINITION(World *); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/common/World.h000066400000000000000000000021341456566705700223360ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray stuff #include "Data.h" #include "FeatureFlagsEnum.h" #include "ISPCDeviceObject.h" // stl #include // ispc shared #include "WorldShared.h" namespace ospray { struct Instance; struct Light; struct PathTracerData; struct SciVisData; struct OSPRAY_SDK_INTERFACE World : public AddStructShared { World(api::ISPCDevice &device); virtual ~World() override; std::string toString() const override; void commit() override; box3f getBounds() const override; const FeatureFlags &getFeatureFlags() const; // Data members // Ref> instances; Ref> lights; std::unique_ptr> instanceArray; std::unique_ptr scivisData; std::unique_ptr pathtracerData; private: FeatureFlags featureFlags; }; OSPTYPEFOR_SPECIALIZATION(World *, OSP_WORLD); inline const FeatureFlags &World::getFeatureFlags() const { return featureFlags; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/common/World.ih000066400000000000000000000326441456566705700225200ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray stuff #include "common/Clipping.ih" #include "common/DGEnum.h" #include "common/DifferentialGeometry.ih" #include "common/FeatureFlags.ih" #include "common/FeatureFlagsEnum.h" #include "common/Instance.ih" #include "common/Ray.ih" #include "common/RayQueryContext.ih" #include "common/VolumeIntervals.ih" #include "geometry/GeometryDispatch.ih" #include "volume/Volume.ih" // c++ shared #include "WorldShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE #ifdef OSPRAY_TARGET_SYCL using namespace ospray; #endif struct Renderer; inline void traceGeometryRay(const World *uniform world, varying Ray &ray, const uniform FeatureFlagsHandler &ffh) { // Skip if no geometries scene if (!world->embreeSceneHandleGeometries) return; const uniform FeatureFlags ff = getFeatureFlags(ffh); uniform RayQueryContextDefault context; initRayQueryContextDefault(&context, ffh); uniform RTCIntersectArguments intersectArgs; rtcInitIntersectArguments(&intersectArgs); intersectArgs.context = &context.ectx; intersectArgs.intersect = (RTCIntersectFunctionN)Geometry_dispatch_intersect; intersectArgs.feature_mask = (uniform RTCFeatureFlags)( ff.geometry & ~FFG_OSPRAY_MASK | RTC_FEATURE_FLAG_INSTANCE); rtcIntersectV(world->embreeSceneHandleGeometries, (varying RTCRayHit * uniform) & ray, &intersectArgs); } #ifdef OSPRAY_ENABLE_VOLUMES inline void traceVolumeRay( const World *uniform world, varying Ray &ray, VolumeInterval &interval) { initVolumeInterval(interval); if (!world->embreeSceneHandleVolumes) return; VolumeIntervals intervals; #ifdef OSPRAY_TARGET_SYCL // We don't have access to TLS/dynamic memory on the kernel, so we only // support one interval on the GPU (i.e., no overlapping volumes) intervals.numVolumeIntervals = 0; intervals.numAllocated = 1; intervals.intervals = &interval; #else allocVolumeIntervals(intervals); #endif uniform RayQueryContextVolume context; InitRayQueryContextVolume(&context, &intervals); uniform RTCIntersectArguments intersectArgs; rtcInitIntersectArguments(&intersectArgs); intersectArgs.context = &context.ectx; intersectArgs.intersect = (RTCIntersectFunctionN)Volume_intersect_kernel; intersectArgs.feature_mask = RTC_FEATURE_FLAG_INSTANCE | RTC_FEATURE_FLAG_USER_GEOMETRY_CALLBACK_IN_ARGUMENTS; rtcIntersectV(world->embreeSceneHandleVolumes, (varying RTCRayHit * uniform) & ray, &intersectArgs); // In the SYCL case we write to the interval parameter directly. In the // non-sycl case we need to get the first interval to return to the caller if (intervals.numVolumeIntervals > 0 && hasInterval(intervals.intervals[0])) { interval.instance = *(world->instances + intervals.intervals[0].instID); interval.volumetricModel = interval.instance->group ->volumetricModels[intervals.intervals[0].geomID]; interval.interval = intervals.intervals[0].interval; } #ifndef OSPRAY_TARGET_SYCL freeVolumeIntervals(intervals); #endif } inline void traceVolumeRay( const World *uniform world, varying Ray &ray, VolumeIntervals &intervals) { if (!world->embreeSceneHandleVolumes) return; uniform RayQueryContextVolume context; InitRayQueryContextVolume(&context, &intervals); uniform RTCIntersectArguments intersectArgs; rtcInitIntersectArguments(&intersectArgs); intersectArgs.context = &context.ectx; intersectArgs.intersect = (RTCIntersectFunctionN)Volume_intersect_kernel; intersectArgs.feature_mask = RTC_FEATURE_FLAG_INSTANCE | RTC_FEATURE_FLAG_USER_GEOMETRY_CALLBACK_IN_ARGUMENTS; rtcIntersectV(world->embreeSceneHandleVolumes, (varying RTCRayHit * uniform) & ray, &intersectArgs); if (intervals.numVolumeIntervals > 0) { for (uniform uint32 i = 0; i < intervals.numVolumeIntervals; ++i) { Instance *instance = *(world->instances + intervals.intervals[i].instID); intervals.intervals[i].instance = instance; intervals.intervals[i].volumetricModel = instance->group->volumetricModels[intervals.intervals[i].geomID]; } } } #endif // Intersection context structure used for clipping geometries struct RayQueryContextClipping { uniform RayQueryContextDefault super; const World *uniform world; varying int32 corrClippingDepth; varying uint32 hitsCount; varying ClippingHit hits[CLIPPING_HITS_MAX_COUNT]; }; unmasked void clippingIntersectionFilterV( const RTCFilterFunctionNArguments *uniform args); inline void traceClippingRay(const World *uniform world, varying Ray &ray, varying RayIntervals &rayIntervals, const uniform FeatureFlagsHandler &ffh) { // Clipping disabled on GPU for now #ifdef OSPRAY_TARGET_SYCL (void)world; (void)ffh; rayIntervals.intervals[0] = make_box1f(ray.t0, ray.t); rayIntervals.count = 1; return; #else // A scene with clipping geometries has to exist if (!world->embreeSceneHandleClippers) { rayIntervals.intervals[0] = make_box1f(ray.t0, ray.t); rayIntervals.count = 1; return; } // Create and initialize intersection context RayQueryContextClipping context; rtcInitRayQueryContext(&context.super.ectx); context.super.type = RQCT_CLIPPING; context.super.ffh = &ffh; context.world = world; context.corrClippingDepth = 0; context.hitsCount = 0; // Create and initialize intersection arguments uniform RTCIntersectArguments intersectArgs; rtcInitIntersectArguments(&intersectArgs); intersectArgs.context = &context.super.ectx; intersectArgs.intersect = (RTCIntersectFunctionN)Geometry_dispatch_intersect; intersectArgs.filter = clippingIntersectionFilterV; intersectArgs.flags = RTC_RAY_QUERY_FLAG_INVOKE_ARGUMENT_FILTER; // Intersect all geometry along given ray, // we have to temporarily extend the ray to inf because // even distant intersections affect visibility of close objects float origT = ray.t; ray.t = inf; rtcIntersectV(world->embreeSceneHandleClippers, (varying RTCRayHit * uniform) & ray, &intersectArgs); ray.t = origT; // Set initial clipping depth, // we have to apply correction because ray origin can be inside clipping area const uniform int32 voidClippingDepth = world->numInvertedClippers; int32 clippingDepth = voidClippingDepth - context.corrClippingDepth; // Variables used for intervals construction uint32 intervalId = 0; bool intervalCompleted = true; // Start ray interval if not in clipping area if (clippingDepth == 0) { rayIntervals.intervals[intervalId].lower = ray.t0; intervalCompleted = false; } // Iterate through collected hits and build ray intervals for (uint32 i = 0; i < context.hitsCount; i++) { // Do not build ray intervals that are further than ray.t float t = context.hits[i].t; float absT = abs(t); if (absT > ray.t) break; // Check if coming into or out of clipping area if (t < 0.0f) { clippingDepth--; // out of clipping area } else { clippingDepth++; // into clipping area } // Start interval if previous one is closed and we are not in clipping area if (clippingDepth == 0 && intervalCompleted) { rayIntervals.intervals[intervalId].lower = absT; intervalCompleted = false; } // End interval if current one is not closed and we enter clipping area if (clippingDepth > 0 && !intervalCompleted) { rayIntervals.intervals[intervalId].upper = absT; intervalCompleted = true; intervalId++; } } // Complete ray interval if started if (!intervalCompleted) { rayIntervals.intervals[intervalId].upper = ray.t; intervalId++; } // Save number of ray intervals rayIntervals.count = intervalId; #endif } inline void traceGeometryRayIntervals(const World *uniform world, Ray &ray, RayIntervals &rayIntervals, const uniform FeatureFlagsHandler &ffh) { // Save the ray const float t0 = ray.t0; const float t = ray.t; // Iterate through ray intervals for (uint32 i = 0; i < rayIntervals.count; i++) { // Set ray interval ray.t0 = rayIntervals.intervals[i].lower; ray.t = rayIntervals.intervals[i].upper; // Skip intervals outside of the ray range if (t < ray.t0 || ray.t < t0) { ray.t0 = t0; ray.t = t; continue; } // Clip interval to the ray range ray.t0 = max(ray.t0, t0); ray.t = min(ray.t, t); // Shoot the ray traceGeometryRay(world, ray, ffh); // Exit loop if geometry hit if (hadHit(ray)) { ray.t0 = t0; return; } } // Restore the ray ray.t0 = t0; ray.t = t; } inline void traceRay(const World *uniform world, varying Ray &ray, const uniform FeatureFlagsHandler &ffh) { #ifdef OSPRAY_TARGET_SYCL // Clipping disabled for now traceGeometryRay(world, ray, ffh); #else // Fast path if no clipping geometry if (!world->embreeSceneHandleClippers) { traceGeometryRay(world, ray, ffh); return; } // Trace ray in clipping geometries scene, fill array with ray intervals varying RayIntervals rayIntervals; traceClippingRay(world, ray, rayIntervals, ffh); // Trace ray intervals traceGeometryRayIntervals(world, ray, rayIntervals, ffh); #endif } inline bool isOccludedNoClipping(const World *uniform world, varying Ray &ray, const uniform FeatureFlagsHandler &ffh) { // Skip if no geometries scene if (!world->embreeSceneHandleGeometries) return false; const uniform FeatureFlags ff = getFeatureFlags(ffh); uniform RayQueryContextDefault context; initRayQueryContextDefault(&context, ffh); uniform RTCOccludedArguments occludedArgs; rtcInitOccludedArguments(&occludedArgs); occludedArgs.context = &context.ectx; occludedArgs.occluded = (RTCOccludedFunctionN)Geometry_dispatch_occluded; occludedArgs.feature_mask = (uniform RTCFeatureFlags)( ff.geometry & ~FFG_OSPRAY_MASK | RTC_FEATURE_FLAG_INSTANCE); rtcOccludedV(world->embreeSceneHandleGeometries, (varying RTCRay * uniform) & ray, &occludedArgs); return ray.t < ray.t0; } inline bool areIntervalsOccluded(const World *uniform world, varying Ray &ray, varying RayIntervals &rayIntervals, const uniform FeatureFlagsHandler &ffh) { // Iterate through ray intervals for (uint32 i = 0; i < rayIntervals.count; i++) { // Set ray interval ray.t0 = rayIntervals.intervals[i].lower; ray.t = rayIntervals.intervals[i].upper; // Check for occluders if (isOccludedNoClipping(world, ray, ffh)) return true; } // No occluder found return false; } inline bool isOccluded(const World *uniform world, varying Ray &ray, const uniform FeatureFlagsHandler &ffh) { #ifdef OSPRAY_TARGET_SYCL // Clipping disabled for now return isOccludedNoClipping(world, ray, ffh); #else // Fast path if no clipping geometry if (!world->embreeSceneHandleClippers) { return isOccludedNoClipping(world, ray, ffh); } // Allocate array for ray intervals varying RayIntervals rayIntervals; rayIntervals.count = 0; // Trace ray in clipping geometries scene, fill array with ray intervals traceClippingRay(world, ray, rayIntervals, ffh); // Is there any occluder within given ray intervals return areIntervalsOccluded(world, ray, rayIntervals, ffh); #endif } /*! Perform post-intersect computations, i.e. fill the members of DifferentialGeometry. Should only get called for rays that actually hit that given world. Variables are calculated according to 'flags', a bit-combination of DG_PostIntersectFlags. The ray, dg.P, dg.Ng, and dg.Ns are in world-coordinates. Color defaults to vec4f(1.f) if queried but not present in geometry. */ inline void postIntersect(const World *uniform world, const Renderer *uniform renderer, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags, const uniform FeatureFlagsHandler &ffh) { dg.primID = ray.primID; dg.st = make_vec2f(ray.u, ray.v); dg.material = NULL; dg.renderer = renderer; if (flags & DG_COLOR) dg.color = make_vec4f(1.f); if (flags & DG_TANGENTS) { dg.dPds = make_vec3f(1.f, 0.f, 0.f); dg.dPdt = make_vec3f(0.f, 1.f, 0.f); } dg.P = ray.org + ray.t * ray.dir; dg.epsilon = 0.f; // per default no geometry-type specific epsilon foreach_unique (instID in ray.instID) { if (instID != RTC_INVALID_GEOMETRY_ID) { Instance *uniform instance = *(world->instances + instID); Instance_postIntersect(instance, renderer, dg, ray, flags, false, ffh); } else { dg.Ns = dg.Ng = ray.Ng; } } // merge geometry-type specific epsilon with general epsilon dg.epsilon = max(dg.epsilon, calcEpsilon(dg.P, ray.dir, ray.t)); // some useful combinations; enums unfortunately don't work :-( #define DG_NG_FACEFORWARD (DG_NG | DG_FACEFORWARD) #define DG_NS_FACEFORWARD (DG_NS | DG_FACEFORWARD) #define DG_NG_NORMALIZE (DG_NG | DG_NORMALIZE) #define DG_NS_NORMALIZE (DG_NS | DG_NORMALIZE) vec3f ffnng = normalize(dg.Ng); if ((flags & DG_NG_NORMALIZE) == DG_NG_NORMALIZE) dg.Ng = ffnng; if ((flags & DG_NS_NORMALIZE) == DG_NS_NORMALIZE) dg.Ns = normalize(dg.Ns); const bool flip = dot(ray.dir, dg.Ng) >= 0.f; if (flip) ffnng = neg(ffnng); if ((flags & DG_NG_FACEFORWARD) == DG_NG_FACEFORWARD && flip) dg.Ng = neg(dg.Ng); if ((flags & DG_NS_FACEFORWARD) == DG_NS_FACEFORWARD) { if (dot(dg.Ng, dg.Ns) < 0.f) dg.Ns = neg(dg.Ns); } dg.P = dg.P + dg.epsilon * ffnng; #undef DG_NG_FACEFORWARD #undef DG_NS_FACEFORWARD #undef DG_NG_NORMALIZE #undef DG_NS_NORMALIZE } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/common/World.ispc000066400000000000000000000064071456566705700230540ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "World.ih" OSPRAY_BEGIN_ISPC_NAMESPACE #ifndef OSPRAY_TARGET_SYCL unmasked void clippingIntersectionFilterV( const RTCFilterFunctionNArguments *uniform args) { // Set execution mask uniform int *uniform valid = args->valid; if (!valid[programIndex]) return; // Get pointer to the intersection context RayQueryContextClipping *uniform context = (RayQueryContextClipping * uniform) args->context; // We skip this intersection to collect all remaining intersections valid[programIndex] = 0; // Skip if array is full if (context->hitsCount >= CLIPPING_HITS_MAX_COUNT) return; // Get ray and hit varying Ray *uniform ray = (varying Ray * uniform) args->ray; varying const RTCHit *uniform hit = (varying const RTCHit *uniform)args->hit; // Prepare clipping normal vec3f Nc; { // The postIntersect function needs the hit part of the Ray structure to be // initialized. Making a ray copy here is quite costly. That is why just // the necessary ray fields are set here. DifferentialGeometry dg; ray->Ng = make_vec3f(hit->Ng_x, hit->Ng_y, hit->Ng_z); ray->u = hit->u; ray->v = hit->v; ray->primID = hit->primID; ray->geomID = hit->geomID; // We need to call postIntersect on clipping geometry foreach_unique (instID in hit->instID[0]) { // Call postIntersect to get shading normal Instance *uniform instance = *(context->world->instances + instID); Instance_postIntersect( instance, NULL, dg, *ray, DG_NG | DG_NS, true, *context->super.ffh); // Use geometry normal for clipping // but use shading normal to check if invertion is needed Nc = (dot(dg.Ns, dg.Ng) > 0.f) ? ray->Ng : neg(ray->Ng); } // Restore IDs initial values ray->primID = RTC_INVALID_GEOMETRY_ID; ray->geomID = RTC_INVALID_GEOMETRY_ID; } // Based on clipping normal vector decide if the ray is // entering clipping geometry (set positive hit value) or exitting clipping // geometry (set negative hit value) const bool exitsClipping = (dot(ray->dir, Nc) > 0.f); ClippingHit cHit; cHit.t = (exitsClipping) ? -ray->t : ray->t; cHit.primID = hit->primID; cHit.geomID = hit->geomID; cHit.instID = hit->instID[0]; // Some geometry types (e.g. curves, subdivisions) // may give more than 2 intersections, we have to filter them out for (uint32 i = 0; i < context->hitsCount; i++) { if ((context->hits[i].primID == cHit.primID) && (context->hits[i].geomID == cHit.geomID) && (context->hits[i].instID == cHit.instID) && floatUlpCompare(context->hits[i].t, cHit.t, 512)) return; } // Now we know that this intersection will be taken into account, // so we can update clipping depth correction value accordingly if (exitsClipping) { context->corrClippingDepth--; } else { context->corrClippingDepth++; } // Insert hit value into sorted array for (uint32 i = 0; i < context->hitsCount; i++) { if (abs(context->hits[i].t) > abs(cHit.t)) { const ClippingHit tmp = context->hits[i]; context->hits[i] = cHit; cHit = tmp; } } context->hits[context->hitsCount] = cHit; context->hitsCount++; } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/common/WorldShared.h000066400000000000000000000017401456566705700234670ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/pathtracer/PathTracerDataShared.h" #include "render/scivis/SciVisDataShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Instance; struct World { Instance **instances; int32 numInvertedClippers; RTCScene embreeSceneHandleGeometries; #ifdef OSPRAY_ENABLE_VOLUMES RTCScene embreeSceneHandleVolumes; #endif #ifndef OSPRAY_TARGET_SYCL RTCScene embreeSceneHandleClippers; #endif SciVisData *scivisData; PathTracerData *pathtracerData; #ifdef __cplusplus World() : instances(nullptr), numInvertedClippers(0), embreeSceneHandleGeometries(nullptr), #ifdef OSPRAY_ENABLE_VOLUMES embreeSceneHandleVolumes(nullptr), #endif #ifndef OSPRAY_TARGET_SYCL embreeSceneHandleClippers(nullptr), #endif scivisData(nullptr), pathtracerData(nullptr) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/def_header.txt000066400000000000000000000000201456566705700224050ustar00rootroot00000000000000EXPORTS z_order RenderKit-ospray-f2a61c2/modules/cpu/fb/000077500000000000000000000000001456566705700201755ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/fb/FrameBuffer.cpp000066400000000000000000000117501456566705700230710ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "FrameBuffer.h" #include "FrameOp.h" #include "OSPConfig.h" #include "fb/FrameBufferView.h" #ifndef OSPRAY_TARGET_SYCL #include "ISPCDevice_ispc.h" #endif namespace { // Internal utilities for thread local progress tracking thread_local int threadLastFrameID = -1; thread_local uint32_t threadNumPixelsRendered = 0; extern "C" uint32_t *getThreadNumPixelsRendered() { return &threadNumPixelsRendered; } extern "C" int *getThreadLastFrameID() { return &threadLastFrameID; } }; // namespace namespace ospray { FrameBuffer::FrameBuffer(api::ISPCDevice &device, const vec2i &_size, ColorBufferFormat _colorBufferFormat, const uint32 channels, const FeatureFlagsOther ffo) : AddStructShared(device.getIspcrtContext(), device), size(_size), colorBufferFormat(_colorBufferFormat), hasColorBuffer(channels & OSP_FB_COLOR), hasDepthBuffer(channels & OSP_FB_DEPTH), hasVarianceBuffer((channels & OSP_FB_COLOR) && (channels & OSP_FB_VARIANCE) && (channels & OSP_FB_ACCUM)), hasNormalBuffer(channels & OSP_FB_NORMAL), hasAlbedoBuffer(channels & OSP_FB_ALBEDO), hasPrimitiveIDBuffer(channels & OSP_FB_ID_PRIMITIVE), hasObjectIDBuffer(channels & OSP_FB_ID_OBJECT), hasInstanceIDBuffer(channels & OSP_FB_ID_INSTANCE), doAccum(channels & OSP_FB_ACCUM), featureFlags(ffo) { managedObjectType = OSP_FRAMEBUFFER; if (_size.x <= 0 || _size.y <= 0) { throw std::runtime_error( "framebuffer has invalid size. Dimensions must be greater than 0"); } getSh()->size = _size; getSh()->rcpSize = vec2f(1.f) / vec2f(_size); getSh()->channels = channels; getSh()->doAccumulation = doAccum; getSh()->accumulateVariance = false; #if OSPRAY_RENDER_TASK_SIZE == -1 #ifdef OSPRAY_TARGET_SYCL vec2i renderTaskSize(8); #else // Compute render task size based on the simd width to get as "square" as // possible a task size that has simdWidth pixels const int simdWidth = ispc::ISPCDevice_programCount(); vec2i renderTaskSize(simdWidth, 1); while (renderTaskSize.x / 2 > renderTaskSize.y) { renderTaskSize.y *= 2; renderTaskSize.x /= 2; } #endif #else // Note: we could also allow changing this at runtime if we want to add this // to the API vec2i renderTaskSize(OSPRAY_RENDER_TASK_SIZE); #endif getSh()->renderTaskSize = renderTaskSize; } void FrameBuffer::commit() { // Read image operations array set by user imageOpData = getParamDataT("imageOperation"); } void FrameBuffer::clear() { getSh()->frameID = -1; // we increment at the start of the frame if (hasVarianceBuffer) { mtGen.seed(mtSeed); // reset the RNG with same seed frameVariance = inf; } } vec2i FrameBuffer::getRenderTaskSize() const { return getSh()->renderTaskSize; } float FrameBuffer::getVariance() const { return frameVariance; } void FrameBuffer::beginFrame() { cancelRender = false; getSh()->frameID++; #ifndef OSPRAY_TARGET_SYCL // TODO: Cancellation isn't supported on the GPU getSh()->cancelRender = 0; // TODO: Maybe better as a kernel to avoid USM thrash to host getSh()->numPixelsRendered = 0; #endif if (hasVarianceBuffer) { // collect half of the samples // To not run into correlation issues with low discrepancy sequences used // in renders, we randomly pick whether the even or the odd frame is // accumulated into the variance buffer. const bool evenFrame = (getSh()->frameID & 1) == 0; if (evenFrame) pickOdd = mtGen() & 1; // coin flip every other frame getSh()->accumulateVariance = evenFrame != pickOdd; } } std::string FrameBuffer::toString() const { return "ospray::FrameBuffer"; } void FrameBuffer::setCompletedEvent(OSPSyncEvent event) { #ifndef OSPRAY_TARGET_SYCL // We won't be running ISPC-side rendering tasks when updating the // progress values here in C++ if (event == OSP_NONE_FINISHED) getSh()->numPixelsRendered = 0; if (event == OSP_FRAME_FINISHED) getSh()->numPixelsRendered = getNumPixels().long_product(); #endif stagesCompleted = event; } OSPSyncEvent FrameBuffer::getLatestCompleteEvent() const { return stagesCompleted; } void FrameBuffer::waitForEvent(OSPSyncEvent event) const { // TODO: condition variable to sleep calling thread instead of spinning? while (stagesCompleted < event) ; } float FrameBuffer::getCurrentProgress() const { #ifdef OSPRAY_TARGET_SYCL // TODO: Continually polling this will cause a lot of USM thrashing return 0.f; #else return static_cast(getSh()->numPixelsRendered) / getNumPixels().long_product(); #endif } void FrameBuffer::cancelFrame() { cancelRender = true; // TODO: Cancellation isn't supported on the GPU #ifndef OSPRAY_TARGET_SYCL getSh()->cancelRender = 1; #endif } bool FrameBuffer::frameCancelled() const { return cancelRender; } uint32 FrameBuffer::getChannelFlags() const { return getSh()->channels; } OSPTYPEFOR_DEFINITION(FrameBuffer *); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/FrameBuffer.h000066400000000000000000000123231456566705700225330ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray #include "ISPCDeviceObject.h" #include "common/Data.h" #include "common/FeatureFlagsEnum.h" #include "fb/ImageOp.h" #include "ospray/ospray.h" #include "rkcommon/utility/ArrayView.h" // ispc shared #include "FrameBufferShared.h" #include #include namespace ospray { struct Camera; struct FrameBufferView; // abstract frame buffer class struct OSPRAY_SDK_INTERFACE FrameBuffer : public AddStructShared { // app-mappable format of the color buffer. make sure that this // matches the definition on the ISPC side using ColorBufferFormat = OSPFrameBufferFormat; FrameBuffer(api::ISPCDevice &device, const vec2i &size, ColorBufferFormat colorBufferFormat, const uint32 channels, const FeatureFlagsOther ffo); virtual ~FrameBuffer() override = default; virtual void commit() override; virtual const void *mapBuffer(OSPFrameBufferChannel channel) = 0; virtual void unmap(const void *mappedMem) = 0; // clear (the specified channels of) this frame buffer virtual void clear(); // Get number of pixels per render task, in x and y direction vec2i getRenderTaskSize() const; // Return the number of render tasks in the x and y direction // This is the kernel launch dims to render the image virtual vec2i getNumRenderTasks() const = 0; virtual uint32_t getTotalRenderTasks() const = 0; // Get the device-side render task IDs virtual utility::ArrayView getRenderTaskIDs( const float errorThreshold, const uint32_t spp) = 0; // get number of pixels in x and y diretion vec2i getNumPixels() const; // get the color format type for this Buffer ColorBufferFormat getColorBufferFormat() const; virtual float getVariance() const; virtual float taskError(const uint32_t taskID) const = 0; virtual void beginFrame(); // Invoke post-processing by calling all FrameOps virtual AsyncEvent postProcess(bool wait) = 0; // common function to help printf-debugging, every derived class should // override this virtual std::string toString() const override; void setCompletedEvent(OSPSyncEvent event); OSPSyncEvent getLatestCompleteEvent() const; void waitForEvent(OSPSyncEvent event) const; virtual float getCurrentProgress() const; virtual void cancelFrame(); bool frameCancelled() const; bool hasColorBuf() const; bool hasVarianceBuf() const; bool hasNormalBuf() const; bool hasAlbedoBuf() const; bool hasPrimitiveIDBuf() const; bool hasObjectIDBuf() const; bool hasInstanceIDBuf() const; bool doAccumulation() const; uint32 getChannelFlags() const; int32_t getFrameID() const; void setFrameID(int32_t id); FeatureFlags getFeatureFlags() const; #ifdef OSPRAY_TARGET_SYCL sycl::nd_range<3> getDispatchRange(const size_t numTasks) const; #endif protected: const vec2i size; ColorBufferFormat colorBufferFormat; // Frame buffer optional buffers bool hasColorBuffer; bool hasDepthBuffer; bool hasVarianceBuffer; bool hasNormalBuffer; bool hasAlbedoBuffer; bool hasPrimitiveIDBuffer; bool hasObjectIDBuffer; bool hasInstanceIDBuffer; // indicates whether the app requested this frame buffer to do accumulation bool doAccum; float frameVariance{inf}; std::atomic cancelRender{false}; std::atomic stagesCompleted{OSP_FRAME_FINISHED}; Ref> imageOpData; FeatureFlagsOther featureFlags{FFO_NONE}; int32_t minimumAdaptiveFrames(const uint32_t spp) const; private: // for consistent reproducability of variance accumulation constexpr static uint32_t mtSeed = 43; std::mt19937 mtGen{mtSeed}; bool pickOdd{false}; }; OSPTYPEFOR_SPECIALIZATION(FrameBuffer *, OSP_FRAMEBUFFER); inline vec2i FrameBuffer::getNumPixels() const { return size; } inline FrameBuffer::ColorBufferFormat FrameBuffer::getColorBufferFormat() const { return colorBufferFormat; } inline bool FrameBuffer::hasColorBuf() const { return hasColorBuffer; } inline bool FrameBuffer::hasVarianceBuf() const { return hasVarianceBuffer; } inline bool FrameBuffer::hasNormalBuf() const { return hasNormalBuffer; } inline bool FrameBuffer::hasAlbedoBuf() const { return hasAlbedoBuffer; } inline bool FrameBuffer::hasPrimitiveIDBuf() const { return hasPrimitiveIDBuffer; } inline bool FrameBuffer::hasObjectIDBuf() const { return hasObjectIDBuffer; } inline bool FrameBuffer::hasInstanceIDBuf() const { return hasInstanceIDBuffer; } inline bool FrameBuffer::doAccumulation() const { return doAccum; } inline int32_t FrameBuffer::getFrameID() const { return getSh()->frameID; } inline void FrameBuffer::setFrameID(int32_t id) { getSh()->frameID = id; } inline FeatureFlags FrameBuffer::getFeatureFlags() const { FeatureFlags ff; ff.other = featureFlags; return ff; } #ifdef OSPRAY_TARGET_SYCL inline sycl::nd_range<3> FrameBuffer::getDispatchRange( const size_t numTasks) const { const vec2i ts = getRenderTaskSize(); return sycl::nd_range<3>({numTasks, ts.y, ts.x}, {1, ts.y, ts.x}); } #endif inline int32_t FrameBuffer::minimumAdaptiveFrames(const uint32_t spp) const { return std::max(2u, 16 / spp); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/FrameBuffer.ih000066400000000000000000000026351456566705700227110ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "OSPConfig.h" #include "rkcommon/math/vec.ih" // c++ shared #include "FrameBufferShared.h" #ifndef OSPRAY_TARGET_SYCL extern "C" uint32 *uniform getThreadNumPixelsRendered(); extern "C" int *uniform getThreadLastFrameID(); #endif #define FRAMEBUFFER_ACCUMULATE_VALUE(value, new_value, factor) \ value = (factor >= 1.f) ? new_value : lerp(factor, value, new_value) OSPRAY_BEGIN_ISPC_NAMESPACE #ifndef OSPRAY_TARGET_SYCL inline void FrameBuffer_updateProgress( FrameBuffer *uniform self, const uniform uint32 numPixelsRendered) { uint32 *uniform pixelsRendered = getThreadNumPixelsRendered(); // Reset the pixels rendered counter for each new frame int *uniform lastFrameID = getThreadLastFrameID(); if (self->frameID != *lastFrameID) { *pixelsRendered = 0; *lastFrameID = self->frameID; } // Update the pixels rendered count and report back to the atomic if we've // reached the reporting threshold *pixelsRendered += numPixelsRendered; // Report rendering results at the same frequency they would have been // reported (each tile) when using the old nested parallel fors over tiles // then pixels. if (*pixelsRendered >= TILE_SIZE * TILE_SIZE) { atomic_add_global(&self->numPixelsRendered, *pixelsRendered); *pixelsRendered = 0; } } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/fb/FrameBufferDispatch.ih000066400000000000000000000015631456566705700243700ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/FeatureFlags.ih" #include "common/FeatureFlagsEnum.h" #include "common/OSPCommon.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct FrameBuffer; struct RenderTaskDesc; struct ScreenSample; SYCL_EXTERNAL uniform RenderTaskDesc FrameBuffer_dispatch_getRenderTaskDesc( FrameBuffer *uniform fb, const uniform uint32 taskID, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL void FrameBuffer_dispatch_accumulateSample( FrameBuffer *uniform fb, const varying ScreenSample &screenSample, uniform RenderTaskDesc &taskDesc, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL void FrameBuffer_dispatch_completeTask(FrameBuffer *uniform fb, const uniform RenderTaskDesc &taskDesc, const uniform FeatureFlagsHandler &ffh); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/fb/FrameBufferDispatch.ispc000066400000000000000000000044341456566705700247260ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/FeatureFlagsEnum.h" #include "fb/FrameBufferDispatch.ih" #include "fb/LocalFB.ih" #include "fb/RenderTaskDesc.ih" #include "fb/SparseFB.ih" #include "render/ScreenSample.ih" // c++ shared #include "fb/FrameBufferShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL uniform RenderTaskDesc FrameBuffer_dispatch_getRenderTaskDesc( FrameBuffer *uniform fb, const uniform uint32 taskID, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlagsOther ffo = getFeatureFlagsOther(ffh); if ((fb->type == FRAMEBUFFER_TYPE_LOCAL) && (ffo & FFO_FB_LOCAL)) { return LocalFB_getRenderTaskDesc(fb, taskID); } else if ((fb->type == FRAMEBUFFER_TYPE_SPARSE) && (ffo & FFO_FB_SPARSE)) { return SparseFB_getRenderTaskDesc(fb, taskID); } else { #ifndef OSPRAY_TARGET_SYCL return fb->getRenderTaskDesc(fb, taskID); #endif } // TODO: Should be an error here uniform RenderTaskDesc rt; rt.region.lower = make_vec2i(0, 0); rt.region.upper = rt.region.lower; return rt; } SYCL_EXTERNAL void FrameBuffer_dispatch_accumulateSample( FrameBuffer *uniform fb, const varying ScreenSample &screenSample, uniform RenderTaskDesc &taskDesc, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlagsOther ffo = getFeatureFlagsOther(ffh); if ((fb->type == FRAMEBUFFER_TYPE_LOCAL) && (ffo & FFO_FB_LOCAL)) { LocalFB_accumulateSample(fb, screenSample, taskDesc); } else if ((fb->type == FRAMEBUFFER_TYPE_SPARSE) && (ffo & FFO_FB_SPARSE)) { SparseFB_accumulateSample(fb, screenSample, taskDesc); } else { #ifndef OSPRAY_TARGET_SYCL fb->accumulateSample(fb, screenSample, taskDesc); #endif } } SYCL_EXTERNAL void FrameBuffer_dispatch_completeTask(FrameBuffer *uniform fb, const uniform RenderTaskDesc &taskDesc, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlagsOther ffo = getFeatureFlagsOther(ffh); if ((fb->type == FRAMEBUFFER_TYPE_LOCAL) && (ffo & FFO_FB_LOCAL)) { LocalFB_completeTask(fb, taskDesc); } else if ((fb->type == FRAMEBUFFER_TYPE_SPARSE) && (ffo & FFO_FB_SPARSE)) { SparseFB_completeTask(fb, taskDesc); } else { #ifndef OSPRAY_TARGET_SYCL fb->completeTask(fb, taskDesc); #endif } } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/fb/FrameBufferShared.h000066400000000000000000000065341456566705700236710ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus #if defined(__cplusplus) && !defined(OSPRAY_TARGET_SYCL) typedef void *FrameBuffer_accumulateSampleFct; typedef void *FrameBuffer_getRenderTaskDescFct; typedef void *FrameBuffer_completeTaskFct; #else struct FrameBuffer; struct ScreenSample; struct RenderTaskDesc; typedef void (*FrameBuffer_accumulateSampleFct)(FrameBuffer *uniform fb, const varying ScreenSample &sample, uniform RenderTaskDesc &taskDesc); typedef uniform RenderTaskDesc (*FrameBuffer_getRenderTaskDescFct)( FrameBuffer *uniform fb, const uniform uint32 taskID); typedef void (*FrameBuffer_completeTaskFct)( FrameBuffer *uniform fb, const uniform RenderTaskDesc &taskDesc); #endif enum FrameBufferType { FRAMEBUFFER_TYPE_LOCAL, FRAMEBUFFER_TYPE_SPARSE, FRAMEBUFFER_TYPE_UNKNOWN, }; /* The ISPC-side FrameBuffer allows tasks to write directly to the framebuffer * memory from ISPC. Given the set of task IDs to be rendered, a renderer must: * * 1. Get the RenderTaskDesc by calling getRenderTaskDesc and render the region * of pixels specified in the task description. * * 2. Write the result of rendering each pixel to the framebuffer by calling * accumulateSample * * 3. Update task-level values (accum ID and error) by calling completeTask */ struct FrameBuffer { FrameBufferType type; /* Get the task description for a given render task ID. The task description * stores the region that should be rendered for the task and its accumID */ FrameBuffer_getRenderTaskDescFct getRenderTaskDesc; /* Accumulate samples taken for this render task into the framebuffer. * Task error will also be computed and accumulated on the render task, * to handle cases where there are more pixels in a task than the SIMD width. */ FrameBuffer_accumulateSampleFct accumulateSample; /* Perform final task updates for the given task, updating its accum ID (if * accumulation buffering is enabled) and its error if variance termination is * enabled */ FrameBuffer_completeTaskFct completeTask; // The size of the framebuffer, in pixels vec2i size; // 1/size (precomputed) vec2f rcpSize; // The default size of each each render task, in pixels vec2i renderTaskSize; // Rendered frame index int32 frameID; // The channels stored in the framebuffer uint32 channels; // If the frame has been cancelled or not. Note: we don't share bools between // ISPC and C++ as the true value representation may differ (as it does with // gcc) uint32 cancelRender; // The number of pixels rendered this frame, for tracking rendering progress // Not used on GPU to avoid USM thrashing uint32 numPixelsRendered; // Accumulate frames if true bool doAccumulation; // Variance accumulation bool accumulateVariance; // do frame accumulation in this frame #ifdef __cplusplus FrameBuffer() : type(FRAMEBUFFER_TYPE_UNKNOWN), getRenderTaskDesc(nullptr), accumulateSample(nullptr), completeTask(nullptr), size(0), rcpSize(0.f), renderTaskSize(4), frameID(-1), channels(0), cancelRender(0), numPixelsRendered(0), doAccumulation(false), accumulateVariance(false) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/fb/FrameBufferView.ih000066400000000000000000000003441456566705700235370ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus #include "fb/FrameBufferViewDef.h" #ifdef __cplusplus } #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/fb/FrameOp.cpp000066400000000000000000000011271456566705700222330ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "FrameOp.h" #include "ISPCDevice.h" namespace ospray { LiveFrameOp::LiveFrameOp(api::ISPCDevice &device, FrameBufferView &fbView) : AddStructShared(device.getIspcrtContext()), device(device) { // We need `FrameBufferView` to be in `ospray` namespace for external modules // to reach it, and we need it to be in `ispc` namespace for ISPC automatic // headers generator, copying between those two requires a cast *getSh() = *reinterpret_cast(&fbView); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/FrameOp.h000066400000000000000000000013361456566705700217020ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/StructShared.h" #include "fb/ImageOp.h" // ispc shared #include "fb/FrameBufferView.ih" namespace ospray { namespace api { struct ISPCDevice; } struct OSPRAY_SDK_INTERFACE FrameOp : public FrameOpInterface { FrameOp(api::ISPCDevice &device) : device(device) {} ~FrameOp() override = default; protected: api::ISPCDevice &device; }; struct OSPRAY_SDK_INTERFACE LiveFrameOp : public AddStructShared { LiveFrameOp(api::ISPCDevice &device, FrameBufferView &fbView); ~LiveFrameOp() override = default; protected: api::ISPCDevice &device; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/FrameOpKernelLaunch.ih000066400000000000000000000060711456566705700243500ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #define ROUND_RANGE(global, group) ((global - 1) / group + 1) * group #ifndef OSPRAY_TARGET_SYCL #define DEFINE_KERNEL_LAUNCHER(kernel_name) \ task static void kernel_name##Task(const FrameBufferView *uniform self) \ { \ const vec2ui id = \ make_vec2ui(taskIndex0 * programCount + programIndex, taskIndex1); \ if (id.x < self->viewDims.x) \ kernel_name(self, id); \ } \ \ export void kernel_name##Launcher( \ const FrameBufferView *uniform self, void *uniform, void *uniform) \ { \ launch[ROUND_RANGE(self->viewDims.x, programCount), \ self->viewDims.y] kernel_name##Task(self); \ sync; \ } #else #define DEFINE_KERNEL_LAUNCHER(kernel_name) \ void kernel_name##Launcher( \ const FrameBufferView *self, void *cmdQueue, void *waitEvent) \ { \ const vec2ui workgroupSize = vec2ui(16, 1); \ const vec2ui roundedSize = ROUND_RANGE(self->viewDims, workgroupSize); \ sycl::nd_range<2> dispatchRange( \ {roundedSize.x, roundedSize.y}, {workgroupSize.x, workgroupSize.y}); \ sycl::queue *syclQueue = static_cast(cmdQueue); \ sycl::event event = syclQueue->submit([&](sycl::handler &cgh) { \ cgh.parallel_for(dispatchRange, [=](sycl::nd_item<2> taskIndex) { \ if (taskIndex.get_global_id(0) < self->viewDims.x) \ kernel_name(self, \ vec2ui(taskIndex.get_global_id(0), taskIndex.get_global_id(1))); \ }); \ }); \ sycl::event *syclEvent = static_cast(waitEvent); \ if (!syclEvent) \ event.wait_and_throw(); \ else \ *syclEvent = event; \ } #endif RenderKit-ospray-f2a61c2/modules/cpu/fb/LocalFB.cpp000066400000000000000000000401451456566705700221470ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "LocalFB.h" #include "FrameOp.h" #include "SparseFB.h" #include "fb/FrameBufferView.h" #include "frame_ops/ColorConversion.h" #include "frame_ops/Variance.h" #include "render/util.h" #include "rkcommon/common.h" #include "rkcommon/tasking/parallel_for.h" #include "rkcommon/utility/ArrayView.h" #ifndef OSPRAY_TARGET_SYCL #include "fb/LocalFB_ispc.h" #else namespace ispc { SYCL_EXTERNAL void LocalFrameBuffer_writeColorTile( void *_fb, const void *_tile); SYCL_EXTERNAL void LocalFrameBuffer_writeDepthTile(void *_fb, const void *uniform _tile); SYCL_EXTERNAL void LocalFrameBuffer_writeAuxTile(void *_fb, const void *_tile, void *aux, const void *_ax, const void *_ay, const void *_az); SYCL_EXTERNAL void LocalFrameBuffer_writeIDTile(void *uniform _fb, const void *uniform _tile, uniform uint32 *uniform dst, const void *uniform src); } // namespace ispc #endif #include #include #include #include namespace ospray { LocalFrameBuffer::LocalFrameBuffer(api::ISPCDevice &device, const vec2i &_size, ColorBufferFormat _colorBufferFormat, const uint32 channels) : AddStructShared(device.getIspcrtContext(), device, _size, _colorBufferFormat, channels, FFO_FB_LOCAL), device(device), numRenderTasks(divRoundUp(size, getRenderTaskSize())) { const size_t numPixels = _size.long_product(); if (hasColorBuffer) colorBuffer = make_buffer_device_shadowed_unique( device.getIspcrtDevice(), numPixels); if (hasDepthBuffer) depthBuffer = make_buffer_device_shadowed_unique( device.getIspcrtDevice(), numPixels); // If variance is going to be used we need to construct helper buffer and // FrameOp to do the calculations if (hasVarianceBuffer) { varianceBuffer = make_buffer_device_unique(device.getIspcrtDevice(), numPixels); // Create and initialize FrameBufferView structure which define domain for // VarianceFrameOp. Since the VarianceFrameOp calculates per-RenderTask // error, the viewDims member is RenderTasks dimensions rather then // FrameBuffer dimensions. Perhaps FrameBufferView should be renamed to // FrameOpDomain or similar in future. FrameBufferView fbv(getNumPixels(), colorBuffer->devicePtr()); fbv.viewDims = getNumRenderTasks(); varianceFrameOp = rkcommon::make_unique( device, fbv, varianceBuffer->devicePtr()); } if (hasNormalBuffer) normalBuffer = make_buffer_device_shadowed_unique( device.getIspcrtDevice(), numPixels); if (hasAlbedoBuffer) albedoBuffer = make_buffer_device_shadowed_unique( device.getIspcrtDevice(), numPixels); if (hasPrimitiveIDBuffer) primitiveIDBuffer = make_buffer_device_shadowed_unique( device.getIspcrtDevice(), numPixels); if (hasObjectIDBuffer) objectIDBuffer = make_buffer_device_shadowed_unique( device.getIspcrtDevice(), numPixels); if (hasInstanceIDBuffer) instanceIDBuffer = make_buffer_device_shadowed_unique( device.getIspcrtDevice(), numPixels); // Create color conversion FrameOp if needed if ((hasColorBuffer) && (getColorBufferFormat() != OSP_FB_RGBA32F)) { FrameBufferView fbv(getNumPixels(), colorBuffer->devicePtr()); colorConversionFrameOp = rkcommon::make_unique( device, fbv, getColorBufferFormat()); } // TODO: Better way to pass the task IDs that doesn't require just storing // them all? Maybe as blocks/tiles similar to when we just had tiles? Will // make task ID lookup more expensive for sparse case though renderTaskIDs = make_buffer_device_shadowed_unique( device.getIspcrtDevice(), getTotalRenderTasks()); std::iota(renderTaskIDs->begin(), renderTaskIDs->end(), 0); if (hasVarianceBuffer) activeTaskIDs = make_buffer_device_shadowed_unique( device.getIspcrtDevice(), getTotalRenderTasks()); // TODO: Could use TBB parallel sort here if it's exposed through the // rkcommon tasking system #ifndef OSPRAY_TARGET_SYCL // We use a 1x1 task size in SYCL and this sorting may not pay off for the // cost it adds std::sort(renderTaskIDs->begin(), renderTaskIDs->end(), [&](const uint32_t &a, const uint32_t &b) { const vec2i p_a = getTaskStartPos(a); const vec2i p_b = getTaskStartPos(b); return interleaveZOrder(p_a.x, p_a.y) < interleaveZOrder(p_b.x, p_b.y); }); #endif { // Upload the task IDs to the device ispcrt::TaskQueue &tq = device.getIspcrtQueue(); tq.copyToDevice(*renderTaskIDs); tq.sync(); } #ifndef OSPRAY_TARGET_SYCL getSh()->super.accumulateSample = reinterpret_cast( ispc::LocalFrameBuffer_accumulateSample_addr()); getSh()->super.getRenderTaskDesc = reinterpret_cast( ispc::LocalFrameBuffer_getRenderTaskDesc_addr()); getSh()->super.completeTask = reinterpret_cast( ispc::LocalFrameBuffer_completeTask_addr()); #endif getSh()->colorBuffer = colorBuffer ? colorBuffer->devicePtr() : nullptr; getSh()->varianceBuffer = varianceBuffer ? varianceBuffer->devicePtr() : nullptr; getSh()->depthBuffer = depthBuffer ? depthBuffer->devicePtr() : nullptr; getSh()->normalBuffer = normalBuffer ? normalBuffer->devicePtr() : nullptr; getSh()->albedoBuffer = albedoBuffer ? albedoBuffer->devicePtr() : nullptr; getSh()->numRenderTasks = numRenderTasks; getSh()->primitiveIDBuffer = primitiveIDBuffer ? primitiveIDBuffer->devicePtr() : nullptr; getSh()->objectIDBuffer = objectIDBuffer ? objectIDBuffer->devicePtr() : nullptr; getSh()->instanceIDBuffer = instanceIDBuffer ? instanceIDBuffer->devicePtr() : nullptr; } LocalFrameBuffer::~LocalFrameBuffer() { #ifdef OSPRAY_TARGET_SYCL device.getSyclQueue().wait_and_throw(); device.getIspcrtQueue().sync(); #endif } void LocalFrameBuffer::commit() { FrameBuffer::commit(); // No frame operations if there is no color buffer if (!hasColorBuffer) return; FrameBufferView fbv(getNumPixels(), colorBuffer ? colorBuffer->devicePtr() : nullptr, depthBuffer ? depthBuffer->devicePtr() : nullptr, normalBuffer ? normalBuffer->devicePtr() : nullptr, albedoBuffer ? albedoBuffer->devicePtr() : nullptr); // Initialize user defined image operations ppColorBuffer.reset(); frameOps.clear(); if (imageOpData) { // Create buffer for post-processing output ppColorBuffer = make_buffer_device_shadowed_unique( device.getIspcrtDevice(), getNumPixels().long_product()); fbv.colorBufferOutput = ppColorBuffer->devicePtr(); // Build FrameOps chain by iterating through all image operations set on // commit for (auto &&obj : *imageOpData) { // Populate frame operations FrameOpInterface *fopi = dynamic_cast(obj); if (fopi) { // Create live FrameOp object frameOps.push_back(fopi->attach(fbv)); // Connect previous FrameOp output with the next FrameOp input fbv.colorBufferInput = fbv.colorBufferOutput; } } } // Create color conversion FrameOp if needed colorConversionFrameOp.reset(); if (getColorBufferFormat() != OSP_FB_RGBA32F) { colorConversionFrameOp = rkcommon::make_unique( device, fbv, getColorBufferFormat()); } } vec2i LocalFrameBuffer::getNumRenderTasks() const { return numRenderTasks; } uint32_t LocalFrameBuffer::getTotalRenderTasks() const { return numRenderTasks.long_product(); } utility::ArrayView LocalFrameBuffer::getRenderTaskIDs( const float errorThreshold_, const uint32_t spp) { errorThreshold = errorThreshold_; // remember if (errorThreshold > 0.0f && varianceFrameOp && (getFrameID() >= minimumAdaptiveFrames(spp))) { // Select render tasks that needs to be processed auto last = std::copy_if(renderTaskIDs->begin(), renderTaskIDs->end(), activeTaskIDs->begin(), [=](uint32_t i) { return varianceFrameOp->getError(i) > errorThreshold; }); const size_t numActive = last - activeTaskIDs->begin(); if (numActive) { ispcrt::TaskQueue &tq = device.getIspcrtQueue(); tq.copyToDevice(*activeTaskIDs); tq.sync(); } return utility::ArrayView(activeTaskIDs->devicePtr(), numActive); } else return utility::ArrayView( renderTaskIDs->devicePtr(), renderTaskIDs->size()); } float LocalFrameBuffer::getVariance() const { // Return maximum error over all tasks if variance has been calculated in a // FrameOp if (varianceFrameOp && varianceFrameOp->validError()) return varianceFrameOp->getAvgError(errorThreshold); // Return set value otherwise return FrameBuffer::getVariance(); } std::string LocalFrameBuffer::toString() const { return "ospray::LocalFrameBuffer"; } void LocalFrameBuffer::clear() { FrameBuffer::clear(); if (hasVarianceBuffer && varianceFrameOp) varianceFrameOp->restart(); } void LocalFrameBuffer::writeTiles(const utility::ArrayView &tiles) { // TODO: The parallel dispatch part of this should be moved into ISPC as an // ISPC launch that calls the individual (currently) exported functions that // we call below in this loop #ifndef OSPRAY_TARGET_SYCL tasking::parallel_for(tiles.size(), [&](const size_t i) { const Tile *tile = &tiles[i]; if (hasColorBuffer) { ispc::LocalFrameBuffer_writeColorTile(getSh(), tile); } if (hasDepthBuffer) { ispc::LocalFrameBuffer_writeDepthTile(getSh(), tile); } if (hasAlbedoBuffer) { ispc::LocalFrameBuffer_writeAuxTile(getSh(), tile, (ispc::vec3f *)albedoBuffer->data(), tile->ar, tile->ag, tile->ab); } if (hasPrimitiveIDBuffer) { ispc::LocalFrameBuffer_writeIDTile( getSh(), tile, getSh()->primitiveIDBuffer, tile->pid); } if (hasObjectIDBuffer) { ispc::LocalFrameBuffer_writeIDTile( getSh(), tile, getSh()->objectIDBuffer, tile->gid); } if (hasInstanceIDBuffer) { ispc::LocalFrameBuffer_writeIDTile( getSh(), tile, getSh()->instanceIDBuffer, tile->iid); } if (hasNormalBuffer) { ispc::LocalFrameBuffer_writeAuxTile(getSh(), tile, (ispc::vec3f *)normalBuffer->data(), tile->nx, tile->ny, tile->nz); } }); #else auto *fbSh = getSh(); const size_t numTasks = tiles.size(); const Tile *tilesPtr = tiles.data(); const int colorFormat = getColorBufferFormat(); vec3f *albedoBufferPtr = fbSh->super.channels & OSP_FB_ALBEDO ? albedoBuffer->devicePtr() : nullptr; vec3f *normalBufferPtr = fbSh->super.channels & OSP_FB_NORMAL ? normalBuffer->devicePtr() : nullptr; device.getSyclQueue() .submit([&](sycl::handler &cgh) { const sycl::nd_range<1> dispatchRange = device.computeDispatchRange(numTasks, 16); cgh.parallel_for(dispatchRange, [=](sycl::nd_item<1> taskIndex) { if (taskIndex.get_global_id(0) < numTasks) { const Tile *tile = &tilesPtr[taskIndex.get_global_id(0)]; if (fbSh->super.channels & OSP_FB_COLOR) { ispc::LocalFrameBuffer_writeColorTile(fbSh, tile); } if (fbSh->super.channels & OSP_FB_DEPTH) { ispc::LocalFrameBuffer_writeDepthTile(fbSh, tile); } if (fbSh->super.channels & OSP_FB_ALBEDO) { ispc::LocalFrameBuffer_writeAuxTile( fbSh, tile, albedoBufferPtr, tile->ar, tile->ag, tile->ab); } if (fbSh->super.channels & OSP_FB_ID_PRIMITIVE) { ispc::LocalFrameBuffer_writeIDTile( fbSh, tile, fbSh->primitiveIDBuffer, tile->pid); } if (fbSh->super.channels & OSP_FB_ID_OBJECT) { ispc::LocalFrameBuffer_writeIDTile( fbSh, tile, fbSh->objectIDBuffer, tile->gid); } if (fbSh->super.channels & OSP_FB_ID_INSTANCE) { ispc::LocalFrameBuffer_writeIDTile( fbSh, tile, fbSh->instanceIDBuffer, tile->iid); } if (fbSh->super.channels & OSP_FB_NORMAL) { ispc::LocalFrameBuffer_writeAuxTile( fbSh, tile, normalBufferPtr, tile->nx, tile->ny, tile->nz); } } }); }) .wait_and_throw(); #endif } void LocalFrameBuffer::writeTiles(SparseFrameBuffer *sparseFb) { // Write tiles operates on device memory writeTiles(sparseFb->getTilesDevice()); assert(getRenderTaskSize() == sparseFb->getRenderTaskSize()); const vec2i renderTaskSize = getRenderTaskSize(); if (!hasVarianceBuffer) { return; } // Task error is not calculated by varianceFrameOp but is being written // directly from SparseFB, the varianceFrameOp needs to be removed to not // interfere with frameVariance calculation varianceFrameOp.reset(); // Now we do need the tile memory on the host to read the region information frameVariance = 0.f; const auto tileIDs = sparseFb->getTileIDs(); uint32_t renderTaskID = 0; for (size_t i = 0; i < tileIDs.size(); ++i) { const box2i tileRegion = sparseFb->getTileRegion(tileIDs[i]); const box2i taskRegion( tileRegion.lower / renderTaskSize, tileRegion.upper / renderTaskSize); for (int y = taskRegion.lower.y; y < taskRegion.upper.y; ++y) { for (int x = taskRegion.lower.x; x < taskRegion.upper.x; ++x, ++renderTaskID) { frameVariance = max(frameVariance, sparseFb->taskError(renderTaskID)); } } } } vec2i LocalFrameBuffer::getTaskStartPos(const uint32_t taskID) const { const vec2i numRenderTasks = getNumRenderTasks(); vec2i taskStart(taskID % numRenderTasks.x, taskID / numRenderTasks.x); return taskStart * getRenderTaskSize(); } AsyncEvent LocalFrameBuffer::postProcess(bool wait) { // Calculate per-task variance if any samples accumulated into variance // buffer, skip it if frameVariance overriden in writeTiles() AsyncEvent event; const bool oddFrame = (getSh()->super.frameID & 1) == 1; if (varianceFrameOp && oddFrame && (frameVariance == float(inf))) varianceFrameOp->process((wait) ? nullptr : &event); // Execute user-defined post-processing kernels for (auto &p : frameOps) p->process((wait) ? nullptr : &event); // Run final color conversion if needed if (colorConversionFrameOp) colorConversionFrameOp->process((wait) ? nullptr : &event); // Return asynchronous event return event; } namespace { template const void *copyToHost(ispcrt::TaskQueue &tq, const T &buffer) { tq.copyToHost(buffer); tq.sync(); return static_cast(buffer.data()); } } // namespace const void *LocalFrameBuffer::mapBuffer(OSPFrameBufferChannel channel) { const void *buf = nullptr; ispcrt::TaskQueue &tq = device.getIspcrtQueue(); if (channel == OSP_FB_COLOR) { if (colorConversionFrameOp) buf = copyToHost(tq, colorConversionFrameOp->getConvertedBuffer()); else if (ppColorBuffer) buf = copyToHost(tq, *ppColorBuffer); else if (colorBuffer) buf = copyToHost(tq, *colorBuffer); } else if ((channel == OSP_FB_DEPTH) && (depthBuffer)) { buf = copyToHost(tq, *depthBuffer); } else if ((channel == OSP_FB_NORMAL) && (normalBuffer)) { buf = copyToHost(tq, *normalBuffer); } else if ((channel == OSP_FB_ALBEDO) && (albedoBuffer)) { buf = copyToHost(tq, *albedoBuffer); } else if ((channel == OSP_FB_ID_PRIMITIVE) && (primitiveIDBuffer)) { buf = copyToHost(tq, *primitiveIDBuffer); } else if ((channel == OSP_FB_ID_OBJECT) && (objectIDBuffer)) { buf = copyToHost(tq, *objectIDBuffer); } else if ((channel == OSP_FB_ID_INSTANCE) && (instanceIDBuffer)) { buf = copyToHost(tq, *instanceIDBuffer); } if (buf) this->refInc(); return buf; } void LocalFrameBuffer::unmap(const void *mappedMem) { if (mappedMem) this->refDec(); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/LocalFB.h000066400000000000000000000076561456566705700216260ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray #include "common/ISPCRTBuffers.h" #include "fb/FrameBuffer.h" // rkcommon #include "rkcommon/containers/AlignedVector.h" #include "rkcommon/utility/ArrayView.h" // ispc shared #include "LocalFBShared.h" #include "TileShared.h" namespace ospray { struct SparseFrameBuffer; struct LiveVarianceFrameOp; struct LiveColorConversionFrameOp; struct OSPRAY_SDK_INTERFACE LocalFrameBuffer : public AddStructShared { LocalFrameBuffer(api::ISPCDevice &device, const vec2i &size, ColorBufferFormat colorBufferFormat, const uint32 channels); virtual ~LocalFrameBuffer() override; virtual void commit() override; // Return the number of render tasks in the x and y direction // This is the kernel launch dims to render the image virtual vec2i getNumRenderTasks() const override; virtual uint32_t getTotalRenderTasks() const override; virtual utility::ArrayView getRenderTaskIDs( const float errorThreshold, const uint32_t spp) override; virtual float getVariance() const override; // common function to help printf-debugging, every derived class should // override this! virtual std::string toString() const override; AsyncEvent postProcess(bool wait) override; const void *mapBuffer(OSPFrameBufferChannel channel) override; void unmap(const void *mappedMem) override; void clear() override; /* Write the tile into this framebuffer's row-major storage. This does not * perform accumulation or buffering, data is taken directly from the tile and * written to the row-major image stored by the LocalFrameBuffer * Safe to call in parallel from multiple threads, as long as each thread is * writing different tiles */ void writeTiles(const utility::ArrayView &tiles); /* Write the tiles of the sparse fb into this framebuffer's row-major storage. * Will also copy error data from the sparseFb the full framebuffer task error * buffer, if variance buffer is enabled. * Safe to call in parallel from multiple threads, as long as each thread is * writing different tiles */ void writeTiles(SparseFrameBuffer *sparseFb); // NOTE: All per-pixel data is only allocated if the corresponding channel // flag was passed on construction // one RGBA per pixel std::unique_ptr> colorBuffer; // one RGBA per pixel, post-processing output std::unique_ptr> ppColorBuffer; // one RGBA per pixel, does not accumulate all samples, for variance // estimation std::unique_ptr> varianceBuffer; // one float per pixel std::unique_ptr> depthBuffer; // accumulated world-space normal per pixel std::unique_ptr> normalBuffer; // accumulated, one RGB per pixel std::unique_ptr> albedoBuffer; // primitive ID, object ID, and instance ID std::unique_ptr> primitiveIDBuffer; std::unique_ptr> objectIDBuffer; std::unique_ptr> instanceIDBuffer; protected: vec2i getTaskStartPos(const uint32_t taskID) const; //// Data //// api::ISPCDevice &device; vec2i numRenderTasks; std::unique_ptr> renderTaskIDs; std::unique_ptr> activeTaskIDs; // Array of frame operations std::vector> frameOps; // Variance frame operation std::unique_ptr varianceFrameOp; // Color conversion frame operation std::unique_ptr colorConversionFrameOp; private: float errorThreshold; // remember // Not used, to be removed after mpi module refactor float taskError(const uint32_t) const override { return 0.f; } }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/LocalFB.ih000066400000000000000000000011571456566705700217650ustar00rootroot00000000000000// Copyright 2009-2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "fb/FrameBuffer.ih" #include "fb/Tile.ih" // c++ shared #include "LocalFBShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL void LocalFB_accumulateSample(FrameBuffer *uniform _fb, const varying ScreenSample &screenSample, uniform RenderTaskDesc &taskDesc); SYCL_EXTERNAL uniform RenderTaskDesc LocalFB_getRenderTaskDesc( FrameBuffer *uniform _fb, const uniform uint32 taskID); SYCL_EXTERNAL void LocalFB_completeTask( FrameBuffer *uniform _fb, const uniform RenderTaskDesc &taskDesc); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/fb/LocalFB.ispc000066400000000000000000000171341456566705700223250ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "FrameBuffer.ih" #include "RenderTaskDesc.ih" #include "Tile.ih" #include "render/ScreenSample.ih" // c++ shared #include "LocalFBShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL void LocalFB_accumulateSample(FrameBuffer *uniform _fb, const varying ScreenSample &screenSample, uniform RenderTaskDesc &) { LocalFB *uniform fb = (LocalFB * uniform) _fb; const int pixelID = screenSample.sampleID.x + fb->super.size.x * screenSample.sampleID.y; // Calculate accumulation scale const uniform int accumID = fb->super.frameID; const uniform float accScale = (fb->super.doAccumulation) ? rcpf(accumID + 1) : 1.f; // Accumulate color const vec4f colorSample = make_vec4f(screenSample.rgb, screenSample.alpha); if (fb->colorBuffer) FRAMEBUFFER_ACCUMULATE_VALUE( fb->colorBuffer[pixelID], colorSample, accScale); // Accumulate color in variance buffer if (fb->super.accumulateVariance) { const uniform float accVarScale = rcpf(accumID / 2 + 1); FRAMEBUFFER_ACCUMULATE_VALUE( fb->varianceBuffer[pixelID], colorSample, accVarScale); } // Accumulate depth buffer if (fb->depthBuffer) { if (fb->super.doAccumulation) { float acc = accumID > 0 ? fb->depthBuffer[pixelID] : inf; fb->depthBuffer[pixelID] = min(acc, screenSample.z); } else { fb->depthBuffer[pixelID] = screenSample.z; } } // Accumulate normal buffer if (fb->normalBuffer) FRAMEBUFFER_ACCUMULATE_VALUE( fb->normalBuffer[pixelID], screenSample.normal, accScale); // Accumulate albedo buffer if (fb->albedoBuffer) FRAMEBUFFER_ACCUMULATE_VALUE( fb->albedoBuffer[pixelID], screenSample.albedo, accScale); if (fb->primitiveIDBuffer) { if (accumID == 0) fb->primitiveIDBuffer[pixelID] = screenSample.primID; } if (fb->objectIDBuffer) { if (accumID == 0) fb->objectIDBuffer[pixelID] = screenSample.geomID; } if (fb->instanceIDBuffer) { if (accumID == 0) fb->instanceIDBuffer[pixelID] = screenSample.instID; } #ifndef OSPRAY_TARGET_SYCL FrameBuffer_updateProgress(&fb->super, popcnt(lanemask())); #endif } SYCL_EXTERNAL uniform RenderTaskDesc LocalFB_getRenderTaskDesc( FrameBuffer *uniform _fb, const uniform uint32 taskID) { LocalFB *uniform fb = (LocalFB * uniform) _fb; uniform RenderTaskDesc desc; desc.taskID = taskID; desc.error = 0.f; uniform vec2i renderTaskSize = fb->super.renderTaskSize; uniform vec2i taskStart = make_vec2i(taskID % fb->numRenderTasks.x, taskID / fb->numRenderTasks.x); desc.region.lower = taskStart * renderTaskSize; desc.region.upper = min(desc.region.lower + renderTaskSize, fb->super.size); return desc; } SYCL_EXTERNAL void LocalFB_completeTask( FrameBuffer *uniform, const uniform RenderTaskDesc &) { // Do nothing } // TODO: Unify all writeTile functions below into a single one export SYCL_EXTERNAL void LocalFrameBuffer_writeColorTile( void *uniform _fb, const void *uniform _tile) { Tile *uniform tile = (Tile * uniform) _tile; uniform LocalFB *uniform fb = (uniform LocalFB * uniform) _fb; uniform vec4f *uniform color = (uniform vec4f * uniform) fb->colorBuffer; color += (uniform uint64)tile->region.lower.y * fb->super.size.x; VaryingTile *uniform varyTile = (VaryingTile * uniform) tile; for (uniform uint32 iiy = tile->region.lower.y; iiy < (uniform uint32)tile->region.upper.y; iiy++) { uniform uint32 chunkID = (iiy - tile->region.lower.y) * (TILE_SIZE / programCount); for (uint32 iix = tile->region.lower.x + programIndex; iix < (uniform uint32)tile->region.upper.x; iix += programCount, chunkID++) { color[iix] = make_vec4f(varyTile->r[chunkID], varyTile->g[chunkID], varyTile->b[chunkID], varyTile->a[chunkID]); } color += fb->super.size.x; } } // Write the input tile into the row-major framebuffer's depth buffer export SYCL_EXTERNAL void LocalFrameBuffer_writeDepthTile( void *uniform _fb, const void *uniform _tile) { uniform LocalFB *uniform fb = (uniform LocalFB * uniform) _fb; const Tile *uniform tile = (const Tile *uniform)_tile; VaryingTile *uniform varyTile = (VaryingTile * uniform) tile; uniform float *uniform depth = (uniform float *uniform)fb->depthBuffer; depth += (uniform uint64)tile->region.lower.y * fb->super.size.x; for (uniform uint32 iiy = tile->region.lower.y; iiy < (uniform uint32)tile->region.upper.y; iiy++) { uniform uint32 chunkID = (iiy - tile->region.lower.y) * (TILE_SIZE / programCount); for (uint32 iix = tile->region.lower.x + programIndex; iix < (uniform uint32)tile->region.upper.x; iix += programCount, chunkID++) { depth[iix] = varyTile->z[chunkID]; } depth += fb->super.size.x; } } // "accumulate" first frame only and write into buffer export SYCL_EXTERNAL void LocalFrameBuffer_writeIDTile(void *uniform _fb, const void *uniform _tile, uniform uint32 *uniform dst, const void *uniform src) { uniform LocalFB *uniform fb = (uniform LocalFB * uniform) _fb; const Tile *uniform tile = (const Tile *uniform)_tile; uniform uint32 *uniform buffer = dst; //(uniform uint32 *uniform)fb->primitiveIDBuffer; buffer += (uniform uint64)tile->region.lower.y * fb->super.size.x; const void *uniform upid = src; //(const void* uniform)tile->pid; const varying int32 *uniform pid = (const varying int32 *uniform)upid; for (uniform uint32 iiy = tile->region.lower.y; iiy < (uniform uint32)tile->region.upper.y; iiy++) { uniform uint32 chunkID = (iiy - tile->region.lower.y) * (TILE_SIZE / programCount); for (uint32 iix = tile->region.lower.x + programIndex; iix < (uniform uint32)tile->region.upper.x; iix += programCount, chunkID++) { if (tile->accumID == 0) { varying uint32 val = -1; unmasked { val = pid[chunkID]; } buffer[iix] = val; } } buffer += fb->super.size.x; } } // Write a Tile's auxiliary buffer into the framebuffer's row major storage export SYCL_EXTERNAL void LocalFrameBuffer_writeAuxTile(void *uniform _fb, const void *uniform _tile, void *uniform _aux, const void *uniform _ax, const void *uniform _ay, const void *uniform _az) { uniform LocalFB *uniform fb = (uniform LocalFB * uniform) _fb; const Tile *uniform tile = (const Tile *uniform)_tile; uniform vec3f *uniform aux = (uniform vec3f * uniform) _aux; const varying float *uniform ax = (const varying float *uniform)_ax; const varying float *uniform ay = (const varying float *uniform)_ay; const varying float *uniform az = (const varying float *uniform)_az; aux += (uniform uint64)tile->region.lower.y * fb->super.size.x; for (uniform uint32 iiy = tile->region.lower.y; iiy < (uniform uint32)tile->region.upper.y; iiy++) { uniform uint32 chunkID = (iiy - tile->region.lower.y) * (TILE_SIZE / programCount); for (uint32 iix = tile->region.lower.x + programIndex; iix < (uint32)tile->region.upper.x; iix += programCount, chunkID++) { aux[iix] = make_vec3f(ax[chunkID], ay[chunkID], az[chunkID]); } aux += fb->super.size.x; } } export void *uniform LocalFrameBuffer_accumulateSample_addr() { return (void *uniform)LocalFB_accumulateSample; } export void *uniform LocalFrameBuffer_getRenderTaskDesc_addr() { return (void *uniform)LocalFB_getRenderTaskDesc; } export void *uniform LocalFrameBuffer_completeTask_addr() { return (void *uniform)LocalFB_completeTask; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/fb/LocalFBShared.h000066400000000000000000000021471456566705700227430ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "FrameBufferShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus // a Local FrameBuffer that stores all pixel values (color, depth, // accum) in a plain 2D array of pixels (one array per component) struct LocalFB { FrameBuffer super; // superclass that we inherit from vec4f *colorBuffer; vec4f *varianceBuffer; // accumulates every other sample, for variance // estimation / stopping float *depthBuffer; vec3f *normalBuffer; vec3f *albedoBuffer; vec2i numRenderTasks; uint32 *primitiveIDBuffer; uint32 *objectIDBuffer; uint32 *instanceIDBuffer; #ifdef __cplusplus LocalFB() : colorBuffer(nullptr), varianceBuffer(nullptr), depthBuffer(nullptr), normalBuffer(nullptr), albedoBuffer(nullptr), numRenderTasks(0), primitiveIDBuffer(nullptr), objectIDBuffer(nullptr), instanceIDBuffer(nullptr) { super.type = FRAMEBUFFER_TYPE_LOCAL; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/fb/RenderTaskDesc.ih000066400000000000000000000004641456566705700233640ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/box.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct RenderTaskDesc { box2i region; // screen region that this corresponds to uint32 taskID; float error; int count; }; OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/fb/SparseFB.cpp000066400000000000000000000307711456566705700223560ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "SparseFB.h" #include "OSPConfig.h" #include "fb/ImageOp.h" #include "render/util.h" #include "rkcommon/common.h" #include "rkcommon/tasking/parallel_for.h" #include "rkcommon/tracing/Tracing.h" #include "rkcommon/utility/ArrayView.h" #ifndef OSPRAY_TARGET_SYCL #include "fb/SparseFB_ispc.h" #endif #include #include namespace ospray { // A global function so we can call it from the tile initialization SYCL kernel box2i getTileRegion(uint32_t tileID, const vec2i fbSize, const vec2i totalTiles) { const vec2i tilePos(tileID % totalTiles.x, tileID / totalTiles.x); return box2i( tilePos * TILE_SIZE, min(tilePos * TILE_SIZE + TILE_SIZE, fbSize)); } SparseFrameBuffer::SparseFrameBuffer(api::ISPCDevice &device, const vec2i &_size, ColorBufferFormat _colorBufferFormat, const uint32 channels, const std::vector &_tileIDs) : AddStructShared(device.getIspcrtContext(), device, _size, _colorBufferFormat, channels, FFO_FB_SPARSE), device(device), totalTiles(divRoundUp(size, vec2i(TILE_SIZE))) { if (size.x <= 0 || size.y <= 0) { throw std::runtime_error( "local framebuffer has invalid size. Dimensions must be greater than " "0"); } setTiles(_tileIDs); } SparseFrameBuffer::SparseFrameBuffer(api::ISPCDevice &device, const vec2i &_size, ColorBufferFormat _colorBufferFormat, const uint32 channels) : AddStructShared(device.getIspcrtContext(), device, _size, _colorBufferFormat, channels, FFO_FB_SPARSE), device(device), totalTiles(divRoundUp(size, vec2i(TILE_SIZE))) { if (size.x <= 0 || size.y <= 0) { throw std::runtime_error( "local framebuffer has invalid size. Dimensions must be greater than " "0"); } } vec2i SparseFrameBuffer::getNumRenderTasks() const { return numRenderTasks; } uint32_t SparseFrameBuffer::getTotalRenderTasks() const { return numRenderTasks.product(); } utility::ArrayView SparseFrameBuffer::getRenderTaskIDs( const float errorThreshold, const uint32_t) { if (!renderTaskIDs) return utility::ArrayView(nullptr, 0); if (errorThreshold > 0.0f && hasVarianceBuffer) { RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::beginEvent("buildActiveTaskIDs", "SparseFb")); auto last = std::copy_if(renderTaskIDs->begin(), renderTaskIDs->end(), activeTaskIDs->begin(), [=](uint32_t i) { return taskError(i) > errorThreshold; }); const size_t numActive = last - activeTaskIDs->begin(); ispcrt::TaskQueue &tq = device.getIspcrtQueue(); tq.copyToDevice(*activeTaskIDs); tq.sync(); RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); return utility::ArrayView(activeTaskIDs->devicePtr(), numActive); } else { RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::setMarker("returnAllTaskIDs", "SparseFB")); return utility::ArrayView( renderTaskIDs->devicePtr(), renderTaskIDs->size()); } } std::string SparseFrameBuffer::toString() const { return "ospray::SparseFrameBuffer"; } float SparseFrameBuffer::taskError(const uint32_t taskID) const { // If this SparseFB doesn't have any tiles return 0. This should not // typically be called in this case anyways if (!tiles) { return 0.f; } if (!taskErrorBuffer) { throw std::runtime_error( "SparseFrameBuffer::taskError: trying to get task error on FB without variance/error buffers"); } // TODO: Should sync taskError back in endFrame return (*taskErrorBuffer)[taskID]; } void SparseFrameBuffer::setTaskError(const uint32_t taskID, const float error) { // If this SparseFB doesn't have any tiles then do nothing. This should not // typically be called in this case anyways if (!tiles) { return; } if (!taskErrorBuffer) { throw std::runtime_error( "SparseFrameBuffer::setTaskError: trying to set task error on FB without variance/error buffers"); } // TODO: dirty tracking for task error, sync in begin frame (*taskErrorBuffer)[taskID] = error; } void SparseFrameBuffer::beginFrame() { FrameBuffer::beginFrame(); if (tiles) { #ifndef OSPRAY_TARGET_SYCL for (auto &tile : *tiles) { tile.accumID = getFrameID(); } #else const size_t numTasks = tiles->size(); auto *fbSh = getSh(); const int32 frameID = getFrameID(); device.getSyclQueue() .submit([&](sycl::handler &cgh) { const sycl::nd_range<1> dispatchRange = device.computeDispatchRange(numTasks, 16); cgh.parallel_for(dispatchRange, [=](sycl::nd_item<1> taskIndex) { if (taskIndex.get_global_id(0) < numTasks) { fbSh->tiles[taskIndex.get_global_id(0)].accumID = frameID; } }); }) .wait_and_throw(); #endif } tilesDirty = true; } const void *SparseFrameBuffer::mapBuffer(OSPFrameBufferChannel) { return nullptr; } void SparseFrameBuffer::unmap(const void *) {} void SparseFrameBuffer::clear() { FrameBuffer::clear(); // also clear the task error buffer if present if (taskErrorBuffer) { std::fill(taskErrorBuffer->begin(), taskErrorBuffer->end(), inf); } } size_t SparseFrameBuffer::getNumTiles() const { return tiles ? tiles->size() : 0; } const utility::ArrayView SparseFrameBuffer::getTiles() { if (!tiles) { return utility::ArrayView(nullptr, 0); } if (tilesDirty) { RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::beginEvent("SparseFB::getTiles", "ospray")); tilesDirty = false; ispcrt::TaskQueue &tq = device.getIspcrtQueue(); tq.copyToHost(*tiles); tq.sync(); RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); } return utility::ArrayView(tiles->hostPtr(), tiles->size()); } const utility::ArrayView SparseFrameBuffer::getTilesDevice() const { if (!tiles) { return utility::ArrayView(nullptr, 0); } return utility::ArrayView(tiles->devicePtr(), tiles->size()); } const utility::ArrayView SparseFrameBuffer::getTileIDs() { if (tileIDs.empty()) { return utility::ArrayView(nullptr, 0); } return utility::ArrayView(tileIDs.data(), tileIDs.size()); } uint32_t SparseFrameBuffer::getTileIndexForTask(uint32_t taskID) const { // Find which tile this task falls into // tileIdx -> index in the SparseFB's list of tiles return taskID / getNumTasksPerTile(); } void SparseFrameBuffer::setTiles(const std::vector &_tileIDs) { RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::beginEvent("SparseFB::setTiles", "ospray"); rkcommon::tracing::setCounter("SparseFB::numTiles", _tileIDs.size()); }); // (Re-)configure the sparse framebuffer based on the tileIDs we're passed tileIDs = _tileIDs; numRenderTasks = vec2i(tileIDs.size() * TILE_SIZE, TILE_SIZE) / getRenderTaskSize(); ispcrt::TaskQueue &tq = device.getIspcrtQueue(); if (hasVarianceBuffer && !tileIDs.empty()) { taskErrorBuffer = make_buffer_shared_unique( getISPCDevice().getIspcrtContext(), numRenderTasks.long_product()); std::fill(taskErrorBuffer->begin(), taskErrorBuffer->end(), inf); } else { taskErrorBuffer = nullptr; } if (!tileIDs.empty()) { tiles = make_buffer_device_shadowed_unique( getISPCDevice().getIspcrtDevice(), tileIDs.size()); const vec2f rcpSize = rcp(vec2f(size)); #ifndef OSPRAY_TARGET_SYCL rkcommon::tasking::parallel_for(tiles->size(), [&](size_t i) { Tile &t = (*tiles)[i]; t.fbSize = size; t.rcp_fbSize = rcpSize; t.region = getTileRegion(tileIDs[i]); t.accumID = 0; }); #else BufferDeviceShadowed deviceTileIDs( device.getIspcrtDevice(), tileIDs); tq.copyToDevice(deviceTileIDs); tq.sync(); // In SYCL, populate the tiles on the device. // TODO: Best to unify the codepaths more here and do the ISPC device // tile population in ISPC so it also runs on the "device" const uint32_t *deviceTileIDsPtr = deviceTileIDs.devicePtr(); const size_t numTasks = tiles->size(); const vec2i fbSize = size; const vec2i fbTotalTiles = totalTiles; Tile *tilesDevice = tiles->devicePtr(); device.getSyclQueue() .submit([&](sycl::handler &cgh) { const sycl::nd_range<1> dispatchRange = device.computeDispatchRange(numTasks, 16); cgh.parallel_for(dispatchRange, [=](sycl::nd_item<1> taskIndex) { if (taskIndex.get_global_id(0) < numTasks) { const size_t tid = taskIndex.get_global_id(0); tilesDevice[tid].fbSize = fbSize; tilesDevice[tid].rcp_fbSize = rcpSize; tilesDevice[tid].region = ospray::getTileRegion( deviceTileIDsPtr[tid], fbSize, fbTotalTiles); tilesDevice[tid].accumID = 0; } }); }) .wait_and_throw(); #endif tilesDirty = true; } else { tiles = nullptr; } const size_t numPixels = tiles ? tileIDs.size() * TILE_SIZE * TILE_SIZE : 0; if (hasVarianceBuffer && !tileIDs.empty()) { varianceBuffer = make_buffer_device_unique( getISPCDevice().getIspcrtDevice(), numPixels); } else { varianceBuffer = nullptr; } // TODO: Should find a better way for allowing sparse task id sets // here we have this array b/c the tasks will be filtered down based on // variance termination if (!tileIDs.empty()) { renderTaskIDs = make_buffer_device_shadowed_unique( getISPCDevice().getIspcrtDevice(), getTotalRenderTasks()); std::iota(renderTaskIDs->begin(), renderTaskIDs->end(), 0); } else { renderTaskIDs = nullptr; } if (hasVarianceBuffer && !tileIDs.empty()) { activeTaskIDs = make_buffer_device_shadowed_unique( getISPCDevice().getIspcrtDevice(), getTotalRenderTasks()); } else { activeTaskIDs = nullptr; } const uint32_t nTasksPerTile = getNumTasksPerTile(); // Sort each tile's tasks in Z order // TODO: is this worth doing in the dynamicLB case? We make // a new sparseFb for each tile set we receive, it seems like // this won't be worth it. if (tiles) { #ifndef OSPRAY_TARGET_SYCL // We use a 1x1 task size in SYCL and this sorting may not pay off for the // cost it adds rkcommon::tasking::parallel_for(tiles->size(), [&](const size_t i) { std::sort(renderTaskIDs->begin() + i * nTasksPerTile, renderTaskIDs->begin() + (i + 1) * nTasksPerTile, [&](const uint32_t &a, const uint32_t &b) { const vec2i p_a = getTaskPosInTile(a); const vec2i p_b = getTaskPosInTile(b); return interleaveZOrder(p_a.x, p_a.y) < interleaveZOrder(p_b.x, p_b.y); }); }); #endif // Upload the task IDs to the device tq.copyToDevice(*renderTaskIDs); } tq.sync(); #ifndef OSPRAY_TARGET_SYCL getSh()->super.accumulateSample = reinterpret_cast( ispc::SparseFrameBuffer_accumulateSample_addr()); getSh()->super.getRenderTaskDesc = reinterpret_cast( ispc::SparseFrameBuffer_getRenderTaskDesc_addr()); getSh()->super.completeTask = reinterpret_cast( ispc::SparseFrameBuffer_completeTask_addr()); #endif getSh()->numRenderTasks = numRenderTasks; getSh()->totalTiles = totalTiles; getSh()->tiles = tiles ? tiles->devicePtr() : nullptr; getSh()->numTiles = tiles ? tiles->size() : 0; getSh()->varianceBuffer = varianceBuffer ? varianceBuffer->devicePtr() : nullptr; getSh()->taskRegionError = taskErrorBuffer ? taskErrorBuffer->data() : nullptr; RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); } box2i SparseFrameBuffer::getTileRegion(uint32_t tileID) const { return ospray::getTileRegion(tileID, size, totalTiles); } vec2i SparseFrameBuffer::getTaskPosInTile(const uint32_t taskID) const { // Find where this task is supposed to render within this tile const vec2i tasksPerTile = vec2i(TILE_SIZE) / getRenderTaskSize(); const uint32 taskTileID = taskID % (tasksPerTile.x * tasksPerTile.y); vec2i taskStart(taskTileID % tasksPerTile.x, taskTileID / tasksPerTile.x); return taskStart * getRenderTaskSize(); } uint32_t SparseFrameBuffer::getNumTasksPerTile() const { const vec2i tileDims(TILE_SIZE); const vec2i tasksPerTile = tileDims / getRenderTaskSize(); return tasksPerTile.long_product(); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/SparseFB.h000066400000000000000000000114031456566705700220120ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ISPCDevice.h" #include "fb/FrameBuffer.h" #include "fb/LocalFB.h" #include "rkcommon/containers/AlignedVector.h" #include "rkcommon/utility/ArrayView.h" // ispc shared #include "TileShared.h" #include "common/ISPCRTBuffers.h" #include "fb/SparseFBShared.h" namespace ospray { /* The sparse framebuffer stores a subset of tiles of a larger framebuffer * to allow rendering tasks to directly write to this allocated tile memory, * rather than requiring on the fly allocation of tiles. The sparse framebuffer * is used as a component of a "parent" framebuffer that is responsible for * distributing the full image among different sparse framebuffers and * collecting the tiles from them into a complete image in some way. * * The sparse framebuffer doesn't store the entire image data and thus doesn't * support frame/tile operations or mapping. */ struct OSPRAY_SDK_INTERFACE SparseFrameBuffer : public AddStructShared { // Create a sparse framebuffer holding the tiles specified in tileIDs SparseFrameBuffer(api::ISPCDevice &device, const vec2i &size, ColorBufferFormat colorBufferFormat, const uint32 channels, const std::vector &tileIDs); // Create a sparse framebuffer that stores no image tiles. Tiles can be added // to the empty sparse framebuffer by calling setTiles SparseFrameBuffer(api::ISPCDevice &device, const vec2i &size, ColorBufferFormat colorBufferFormat, const uint32 channels); // Return the number of render tasks in the x and y direction // This is the kernel launch dims to render the image virtual vec2i getNumRenderTasks() const override; virtual uint32_t getTotalRenderTasks() const override; virtual utility::ArrayView getRenderTaskIDs( const float errorThreshold = 0.f, const uint32_t spp = 1) override; //! \brief common function to help printf-debugging /*! \detailed Every derived class should override this! */ virtual std::string toString() const override; float taskError(const uint32_t taskID) const override; /* Set the error for a given task, used by the parent framebuffer managing the * sparse framebuffers to sync error computed over the entire image */ void setTaskError(const uint32_t taskID, const float error); void beginFrame() override; AsyncEvent postProcess(bool) override { AsyncEvent e; // Do not run post-processing on sparse frame buffer return e; } // Mapping sparse framebuffers is not supported, will return null const void *mapBuffer(OSPFrameBufferChannel channel) override; void unmap(const void *mappedMem) override; void clear() override; size_t getNumTiles() const; const utility::ArrayView getTiles(); // Get a view of the device memory of the tiles const utility::ArrayView getTilesDevice() const; const utility::ArrayView getTileIDs(); // Get the index of the tile in the tile ID and Tiles lists that this task // falls into uint32_t getTileIndexForTask(uint32_t taskID) const; /* Change the tiles stored in this SparseFrameBuffer, re-using the existing * storage. New tiles will be allocated if the size of the tileIDs passed * exceeds those currently stored in the SparseFrameBuffer */ void setTiles(const std::vector &tileIDs); // Return the image region for the tile box2i getTileRegion(uint32_t tileID) const; //// Data //// protected: // Get the position of a task in its tile vec2i getTaskPosInTile(const uint32_t taskID) const; uint32_t getNumTasksPerTile() const; api::ISPCDevice &device; // The tiles in this framebuffer std::unique_ptr> tiles; // Track if we need to read back tiles to the host bool tilesDirty = false; // Variance data for the image, stored in tiled order with one RGBA value per // pixel, accumulates every other sample, for variance estimation std::unique_ptr> varianceBuffer; // Does this need to be USM at all? std::vector tileIDs; // Total number of tiles that the framebuffer is divided into, including those // not owned by this sparsefb vec2i totalTiles; // Total number of render tasks that the framebuffer is divided into, // including those not owned by this sparsefb vec2i numRenderTasks{0}; // holds error per task for each tile, stored in tiled order. // The SparseFB doesn't do its own error refinement since it doesn't have // access to error data for the entire framebuffer std::unique_ptr> taskErrorBuffer; std::unique_ptr> renderTaskIDs; std::unique_ptr> activeTaskIDs; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/SparseFB.ih000066400000000000000000000020341456566705700221630ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "fb/Tile.ih" // c++ shared #include "SparseFBShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL uniform RenderTaskDesc SparseFB_getRenderTaskDesc( FrameBuffer *uniform _fb, const uniform uint32 taskID); SYCL_EXTERNAL void SparseFB_accumulateSample(FrameBuffer *uniform _fb, const varying ScreenSample &screenSample, uniform RenderTaskDesc &taskDesc); SYCL_EXTERNAL void SparseFB_completeTask( FrameBuffer *uniform _fb, const uniform RenderTaskDesc &taskDesc); inline uniform uint32 SparseFB_getTileIndexForTask( const SparseFB *uniform fb, const uniform uint32 taskID) { // Find which tile this task falls into const uniform vec2i tileDims = make_vec2i(TILE_SIZE); const uniform vec2i tasksPerTile = tileDims / fb->super.renderTaskSize; const uniform int nTasksPerTile = tasksPerTile.x * tasksPerTile.y; // tileIdx -> index in the SparseFB's list of tiles return taskID / nTasksPerTile; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/fb/SparseFB.ispc000066400000000000000000000156711456566705700225340ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "SparseFB.ih" #include "fb/FrameBuffer.ih" #include "fb/RenderTaskDesc.ih" #include "fb/Tile.ih" #include "ospray/OSPEnums.h" #include "render/Renderer.ih" #include "render/ScreenSample.ih" #include "render/util.ih" OSPRAY_BEGIN_ISPC_NAMESPACE /* Return the position of the screen sample within its tile */ inline vec2i SparseFB_getTilePixelPos(SparseFB *uniform fb, const ScreenSample &screenSample, const uniform uint32 tileIdx) { uniform vec2i tilePos = fb->tiles[tileIdx].region.lower; const vec2i tilePixelPos = make_vec2i(screenSample.sampleID.x, screenSample.sampleID.y) - tilePos; return tilePixelPos; } // Accumulates the screenSample color and alpha into the framebuffer's // accumulation buffer. // I.e., the color to be written to the final framebuffer for display for // the current frame // // tileIdx is the index of the tile that this task/sample belongs to, as // computed by SparseFB_getTileIndexForTask. sampleTilePos is the position of // the sample within this tile, via SparseFB_getTilePixelPos inline void SparseFB_accumulateTileSample(SparseFB *uniform fb, const ScreenSample &screenSample, const uniform uint32 tileIdx, const vec2i &sampleTilePos, uniform RenderTaskDesc &taskDesc) { // The location of this pixel's data within the tiled accumulation and // variance buffers const uint32 tilePixelIdx = sampleTilePos.x + TILE_SIZE * sampleTilePos.y; const vec4f sampleValue = make_vec4f(screenSample.rgb, screenSample.alpha); uniform Tile *uniform tile = fb->tiles + tileIdx; const uniform int accumID = fb->super.frameID; const uniform float accScale = (fb->super.doAccumulation) ? rcpf(accumID + 1) : 1.f; // Accumulate color vec4f color = make_vec4f(tile->r[tilePixelIdx], tile->g[tilePixelIdx], tile->b[tilePixelIdx], tile->a[tilePixelIdx]); FRAMEBUFFER_ACCUMULATE_VALUE(color, sampleValue, accScale); tile->r[tilePixelIdx] = color.x; tile->g[tilePixelIdx] = color.y; tile->b[tilePixelIdx] = color.z; tile->a[tilePixelIdx] = color.w; // Accumulate depth float depth = screenSample.z; if (fb->super.doAccumulation) depth = min(tile->z[tilePixelIdx], screenSample.z); tile->z[tilePixelIdx] = depth; // Accumulate normal vec3f normal = make_vec3f( tile->nx[tilePixelIdx], tile->ny[tilePixelIdx], tile->nz[tilePixelIdx]); FRAMEBUFFER_ACCUMULATE_VALUE(normal, screenSample.normal, accScale); tile->nx[tilePixelIdx] = normal.x; tile->ny[tilePixelIdx] = normal.y; tile->nz[tilePixelIdx] = normal.z; // Accumulate albedo vec3f albedo = make_vec3f( tile->ar[tilePixelIdx], tile->ag[tilePixelIdx], tile->ab[tilePixelIdx]); FRAMEBUFFER_ACCUMULATE_VALUE(albedo, screenSample.albedo, accScale); tile->ar[tilePixelIdx] = albedo.x; tile->ag[tilePixelIdx] = albedo.y; tile->ab[tilePixelIdx] = albedo.z; tile->pid[tilePixelIdx] = screenSample.primID; tile->gid[tilePixelIdx] = screenSample.geomID; tile->iid[tilePixelIdx] = screenSample.instID; uniform vec4f *uniform variance = fb->varianceBuffer; if (fb->super.accumulateVariance) { const uniform float accVarScale = rcpf(accumID / 2 + 1); const uint32 varianceAccumIndex = tileIdx * TILE_SIZE * TILE_SIZE + sampleTilePos.x + TILE_SIZE * sampleTilePos.y; FRAMEBUFFER_ACCUMULATE_VALUE( variance[varianceAccumIndex], sampleValue, accVarScale); // Calculate error float err = 0.f; int cnt = 0; const float den2 = reduce_add(make_vec3f(color)) + (1.f - color.w); // invert alpha (bright alpha is more important) if (den2 > 0.f) { const vec4f diff = absf(color - variance[varianceAccumIndex]); err = reduce_add(diff) * rsqrtf(den2); cnt = 1; } // We max over the task because we may have more pixels in the task than // the SIMD width taskDesc.error += reduce_add(err); taskDesc.count += reduce_add(cnt); } } SYCL_EXTERNAL void SparseFB_accumulateSample(FrameBuffer *uniform _fb, const varying ScreenSample &screenSample, uniform RenderTaskDesc &taskDesc) { SparseFB *uniform fb = (SparseFB * uniform) _fb; // tileIdx -> index in the SparseFB's list of tiles const uniform uint32 tileIdx = SparseFB_getTileIndexForTask(fb, taskDesc.taskID); const vec2i sampleTilePos = SparseFB_getTilePixelPos(fb, screenSample, tileIdx); SparseFB_accumulateTileSample( fb, screenSample, tileIdx, sampleTilePos, taskDesc); #ifndef OSPRAY_TARGET_SYCL FrameBuffer_updateProgress(&fb->super, popcnt(lanemask())); #endif } SYCL_EXTERNAL uniform RenderTaskDesc SparseFB_getRenderTaskDesc( FrameBuffer *uniform _fb, const uniform uint32 taskID) { SparseFB *uniform fb = (SparseFB * uniform) _fb; // Map to the tile and then the set of pixels within that tile. uniform RenderTaskDesc desc; desc.taskID = taskID; desc.error = 0.f; desc.count = 0; const uniform uint32 tileIdx = SparseFB_getTileIndexForTask(fb, taskID); // Find where this task is supposed to render within this tile const uniform vec2i tileDims = make_vec2i(TILE_SIZE); const uniform vec2i tasksPerTile = tileDims / fb->super.renderTaskSize; const uniform uint32 taskTileID = taskID % (tasksPerTile.x * tasksPerTile.y); uniform vec2i taskStart = make_vec2i(taskTileID % tasksPerTile.x, taskTileID / tasksPerTile.x); desc.region.lower = taskStart * fb->super.renderTaskSize; desc.region.upper = desc.region.lower + fb->super.renderTaskSize; // Offset the task's region by the tile location const uniform vec2i tilePos = fb->tiles[tileIdx].region.lower; desc.region.lower = desc.region.lower + tilePos; desc.region.upper = min(desc.region.upper + tilePos, fb->super.size); // TODO: In the end, shouldn't generate these out of bounds tasks for the // padded framebuffer region? For now just mark them as having no error // In the past the tiled load balancer would also generate these though, with // how we padded out to the tile dims if (isEmpty(desc.region) && fb->taskRegionError) { fb->taskRegionError[taskID] = 0.f; } return desc; } SYCL_EXTERNAL void SparseFB_completeTask( FrameBuffer *uniform _fb, const uniform RenderTaskDesc &taskDesc) { // Write error for the task SparseFB *uniform fb = (SparseFB * uniform) _fb; if (fb->super.accumulateVariance) { uniform float err = taskDesc.error; if (taskDesc.count) err *= rcp((uniform float)taskDesc.count); // avg // scale to be backwards compatible with the old default tile size of 64x64 fb->taskRegionError[taskDesc.taskID] = err * 64.f; } } #ifndef OSPRAY_TARGET_SYCL export void *uniform SparseFrameBuffer_accumulateSample_addr() { return (void *uniform)SparseFB_accumulateSample; } export void *uniform SparseFrameBuffer_getRenderTaskDesc_addr() { return (void *uniform)SparseFB_getRenderTaskDesc; } export void *uniform SparseFrameBuffer_completeTask_addr() { return (void *uniform)SparseFB_completeTask; } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/fb/SparseFBShared.h000066400000000000000000000021111456566705700231350ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "FrameBufferShared.h" #include "TileShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus // a SparseFrameBuffer stores a subset of the full framebuffer as Tiles struct SparseFB { // superclass that we inherit from FrameBuffer super; // Number of tasks being used to render the image in x & y vec2i numRenderTasks; // The total number of tiles that the framebuffer is divided into vec2i totalTiles; uint32 numTiles; // Image data for the tiles in this SparseFrameBuffer Tile *tiles; // accumulates every other sample, for variance estimation / stopping vec4f *varianceBuffer; // holds error per task region, for adaptive accumulation float *taskRegionError; #ifdef __cplusplus SparseFB() : numRenderTasks(0), totalTiles(0), numTiles(0), tiles(nullptr), varianceBuffer(nullptr), taskRegionError(nullptr) { super.type = FRAMEBUFFER_TYPE_SPARSE; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/fb/TaskError.cpp000066400000000000000000000070031456566705700226150ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "TaskError.h" #include namespace ospray { TaskError::TaskError(ispcrt::Context &context, const vec2i &_numTasks) : numTasks(_numTasks) { if (numTasks.long_product() > 0) { taskErrorBuffer = make_buffer_shared_unique(context, numTasks.long_product()); // maximum number of regions: all regions are of size 3 are split in // half errorRegion.reserve(divRoundUp(taskErrorBuffer->size() * 2, size_t(3))); clear(); } } void TaskError::clear() { if (!taskErrorBuffer) { return; } std::fill(taskErrorBuffer->begin(), taskErrorBuffer->end(), inf); errorRegion.clear(); // initially create one region covering the complete tile/image errorRegion.push_back(box2i(vec2i(0), numTasks)); } float TaskError::operator[](const int id) const { if (!taskErrorBuffer) { return inf; } return (*taskErrorBuffer)[id]; } void TaskError::update(const vec2i &task, const float err) { if (taskErrorBuffer) { (*taskErrorBuffer)[task.y * numTasks.x + task.x] = err; } } float TaskError::refine(const float errorThreshold) { if (!taskErrorBuffer) { return inf; } float maxErr = 0.f; float sumActErr = 0.f; int activeTasks = 0; for (const auto &err : *taskErrorBuffer) { maxErr = std::max(maxErr, err); if (err > errorThreshold) { sumActErr += err; activeTasks++; } } const float error = activeTasks ? sumActErr / activeTasks : maxErr; // process regions first, but don't process newly split regions again int regions = errorThreshold > 0.f ? errorRegion.size() : 0; for (int i = 0; i < regions; i++) { box2i ®ion = errorRegion[i]; float err = 0.f; float maxErr = 0.f; for (int y = region.lower.y; y < region.upper.y; y++) for (int x = region.lower.x; x < region.upper.x; x++) { int idx = y * numTasks.x + x; err += (*taskErrorBuffer)[idx]; maxErr = std::max(maxErr, (*taskErrorBuffer)[idx]); } if (maxErr > errorThreshold) { // set all tasks of this region to >errorThreshold to enforce their // refinement as a group const float minErr = nextafter(errorThreshold, inf); for (int y = region.lower.y; y < region.upper.y; y++) for (int x = region.lower.x; x < region.upper.x; x++) { int idx = y * numTasks.x + x; (*taskErrorBuffer)[idx] = std::max((*taskErrorBuffer)[idx], minErr); } } const vec2i size = region.size(); const int area = reduce_mul(size); err /= area; // == avg if (err <= 4.f * errorThreshold) { // split region? // if would just contain single task after split or wholly done: remove if (area <= 2 || maxErr <= errorThreshold) { regions--; errorRegion[i] = errorRegion[regions]; errorRegion[regions] = errorRegion.back(); errorRegion.pop_back(); i--; continue; } const vec2i split = region.lower + size / 2; // TODO: find split with // equal variance errorRegion.push_back(region); // region ref might become invalid if (size.x > size.y) { errorRegion[i].upper.x = split.x; errorRegion.back().lower.x = split.x; } else { errorRegion[i].upper.y = split.y; errorRegion.back().lower.y = split.y; } } } return error; } float *TaskError::errorBuffer() { return taskErrorBuffer ? taskErrorBuffer->data() : nullptr; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/TaskError.h000066400000000000000000000022661456566705700222700ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include "common/ISPCRTBuffers.h" #include "common/OSPCommon.h" #include "rkcommon/containers/AlignedVector.h" namespace ospray { /* manages error per tile and adaptive regions, for variance estimation Implementation based on Dammertz et al., "A Hierarchical Automatic Stopping Condition for Monte Carlo Global Illumination", WSCG 2010 */ class OSPRAY_SDK_INTERFACE TaskError { public: TaskError(ispcrt::Context &ispcrtContext, const vec2i &numTasks); // The default constructor will make an empty task error region TaskError() = default; void clear(); float operator[](const int id) const; void update(const vec2i &task, const float error); float refine(const float errorThreshold); // Return the error buffer, or null if there are no tiles that error is // tracked for float *errorBuffer(); protected: vec2i numTasks = vec2i(0); // holds error per task std::unique_ptr> taskErrorBuffer; // image regions (in #tasks) that do not yet estimate the error on // per-task basis std::vector errorRegion; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/Tile.ih000066400000000000000000000022001456566705700214060ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/box.ih" // c++ shared #include "TileShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE inline void setRGBA(uniform Tile &tile, const varying uint32 i, const varying vec3f rgb, const varying float alpha = 0.f) { tile.r[i] = rgb.x; tile.g[i] = rgb.y; tile.b[i] = rgb.z; tile.a[i] = alpha; } inline void setRGBAZ(uniform Tile &tile, const varying uint32 i, const varying vec3f rgb, const varying float alpha, const varying float z) { tile.r[i] = rgb.x; tile.g[i] = rgb.y; tile.b[i] = rgb.z; tile.a[i] = alpha; tile.z[i] = z; } inline void setRGBA( uniform Tile &tile, const varying uint32 i, const varying vec4f rgba) { tile.r[i] = rgba.x; tile.g[i] = rgba.y; tile.b[i] = rgba.z; tile.a[i] = rgba.w; } inline void setNormalAlbedo( uniform Tile &tile, const uint32 i, const vec3f normal, const vec3f albedo) { tile.nx[i] = normal.x; tile.ny[i] = normal.y; tile.nz[i] = normal.z; tile.ar[i] = albedo.x; tile.ag[i] = albedo.y; tile.ab[i] = albedo.z; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/fb/TileShared.h000066400000000000000000000105761456566705700224030ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "OSPConfig.h" #ifdef __cplusplus namespace ispc { #endif #ifdef __cplusplus static_assert(TILE_SIZE > 0 && (TILE_SIZE & (TILE_SIZE - 1)) == 0, "OSPRay config error: TILE_SIZE must be a positive power of two."); #endif // Extra defines to hide some differences between ISPC/C++ to unify the // declaration // TODO: remove all uniform/varying modifiers from Tile and VaryingTile #ifdef __cplusplus #ifndef OSPRAY_TARGET_SYCL #define uniform #endif #else #define OSPRAY_SDK_INTERFACE #endif #ifndef OSPRAY_SDK_INTERFACE #define OSPRAY_SDK_INTERFACE #endif //! a tile of pixels used by any tile-based renderer /*! pixels in the tile are in a row-major TILE_SIZE x TILE_SIZE pattern. the 'region' specifies which part of the screen this tile belongs to: tile.lower is the lower-left coordinate of this tile (and a multiple of TILE_SIZE); the 'upper' value may be smaller than the upper-right edge of the "full" tile. note that a tile contains "all" of the values a renderer might want to use. not all renderers nor all frame buffers will use all those values; it's up to the renderer and frame buffer to agree on which fields will be set. Similarly, the frame buffer may actually use uchars, but the tile will always store floats. */ struct OSPRAY_SDK_INTERFACE Tile { uniform range2i region; uniform vec2i fbSize; uniform vec2f rcp_fbSize; uniform int32 generation; uniform int32 children; uniform int32 sortOrder; uniform int32 accumID; uniform float pad[4]; // padding to match the varying tile layout uniform float r[TILE_SIZE * TILE_SIZE]; // red uniform float g[TILE_SIZE * TILE_SIZE]; // green uniform float b[TILE_SIZE * TILE_SIZE]; // blue uniform float a[TILE_SIZE * TILE_SIZE]; // alpha uniform float z[TILE_SIZE * TILE_SIZE]; // depth uniform float nx[TILE_SIZE * TILE_SIZE]; // normal x uniform float ny[TILE_SIZE * TILE_SIZE]; // normal y uniform float nz[TILE_SIZE * TILE_SIZE]; // normal z uniform float ar[TILE_SIZE * TILE_SIZE]; // albedo red uniform float ag[TILE_SIZE * TILE_SIZE]; // albedo green uniform float ab[TILE_SIZE * TILE_SIZE]; // albedo blue uniform uint32 pid[TILE_SIZE * TILE_SIZE]; // primID uniform uint32 gid[TILE_SIZE * TILE_SIZE]; // objID uniform uint32 iid[TILE_SIZE * TILE_SIZE]; // instanceID #ifdef __cplusplus Tile() : region(empty), fbSize(0), rcp_fbSize(0.f), generation(0), children(0), sortOrder(0), accumID(0) {} Tile(const vec2i &tile, const vec2i &fbsize, const int32 accumId) : fbSize(fbsize), accumID(accumId) { rcp_fbSize.x = rcp(float(fbSize.x)); rcp_fbSize.y = rcp(float(fbSize.y)); region.lower = tile * TILE_SIZE; region.upper = min(region.lower + TILE_SIZE, fbsize); } #endif }; #if !defined(__cplusplus) || defined(OSPRAY_TARGET_SYCL) struct VaryingTile { uniform range2i region; // 4 ints uniform vec2i fbSize; // 2 ints uniform vec2f rcp_fbSize; // 2 floats uniform int32 generation; uniform int32 children; uniform int32 sortOrder; uniform int32 accumID; uniform float pad[4]; // explicit padding to match on SSE, this padding is // implicitly added on AVX and AVX512 to align the // vectors though. We need it here to match on SSE varying float r[TILE_SIZE * TILE_SIZE / programCount]; varying float g[TILE_SIZE * TILE_SIZE / programCount]; varying float b[TILE_SIZE * TILE_SIZE / programCount]; varying float a[TILE_SIZE * TILE_SIZE / programCount]; varying float z[TILE_SIZE * TILE_SIZE / programCount]; varying float nx[TILE_SIZE * TILE_SIZE / programCount]; varying float ny[TILE_SIZE * TILE_SIZE / programCount]; varying float nz[TILE_SIZE * TILE_SIZE / programCount]; varying float ar[TILE_SIZE * TILE_SIZE / programCount]; varying float ag[TILE_SIZE * TILE_SIZE / programCount]; varying float ab[TILE_SIZE * TILE_SIZE / programCount]; varying uint32 pid[TILE_SIZE * TILE_SIZE / programCount]; // primID varying uint32 gid[TILE_SIZE * TILE_SIZE / programCount]; // objID varying uint32 iid[TILE_SIZE * TILE_SIZE / programCount]; // instanceID }; #endif #ifdef __cplusplus #ifndef OSPRAY_TARGET_SYCL #undef uniform #endif #else #undef OSPRAY_SDK_INTERFACE #endif #ifdef __cplusplus } namespace ospray { using Tile = ispc::Tile; } #endif RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/000077500000000000000000000000001456566705700221505ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/Blur.cpp000066400000000000000000000035771456566705700235740ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Blur.h" #include "ISPCDevice.h" #include "fb/FrameBufferView.h" #ifndef OSPRAY_TARGET_SYCL extern "C" { #endif namespace ispc { void BlurHorizontal_kernelLauncher(const FrameBufferView *, void *, void *); void BlurVertical_kernelLauncher(const FrameBufferView *, void *, void *); } // namespace ispc #ifndef OSPRAY_TARGET_SYCL } #endif namespace ospray { BlurFrameOp::BlurFrameOp(api::Device &device) : FrameOp(static_cast(device)) {} std::unique_ptr BlurFrameOp::attach( FrameBufferView &fbView) { return rkcommon::make_unique(device, fbView); } std::string BlurFrameOp::toString() const { return "ospray::BlurFrameOp"; } LiveBlurFrameOp::LiveBlurFrameOp( api::ISPCDevice &device, FrameBufferView &fbView) : AddStructShared(device.getIspcrtContext(), device, fbView), scratch(device.getIspcrtDevice(), fbView.viewDims.long_product()) { // Set pointer to scratch buffer getSh()->scratchBuffer = scratch.devicePtr(); // Calculate blur weights const float variance = 9.f; for (uint32_t i = 0; i <= BLUR_RADIUS; i++) { getSh()->weights[i] = 1.f / std::sqrt(2.f * M_PI * variance) * std::exp(-float(i * i) / (2.f * variance)); } float weightSum = 0.f; for (int32_t i = -BLUR_RADIUS; i <= BLUR_RADIUS; i++) weightSum += getSh()->weights[abs(i)]; for (uint32_t i = 0; i <= BLUR_RADIUS; i++) getSh()->weights[i] /= weightSum; } void LiveBlurFrameOp::process(void *waitEvent) { void *cmdQueue = nullptr; #ifdef OSPRAY_TARGET_SYCL cmdQueue = &device.getSyclQueue(); #endif // Horizontal copying pass ispc::BlurHorizontal_kernelLauncher(&getSh()->super, cmdQueue, waitEvent); // Vertical in-place pass ispc::BlurVertical_kernelLauncher(&getSh()->super, cmdQueue, waitEvent); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/Blur.h000066400000000000000000000014051456566705700232250ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/ISPCRTBuffers.h" #include "fb/FrameOp.h" // ispc shared #include "BlurShared.h" namespace ospray { // The blur frame op is a test which applies a Gaussian blur to the frame struct OSPRAY_SDK_INTERFACE BlurFrameOp : public FrameOp { BlurFrameOp(api::Device &device); std::unique_ptr attach( FrameBufferView &fbView) override; std::string toString() const override; }; struct OSPRAY_SDK_INTERFACE LiveBlurFrameOp : public AddStructShared { LiveBlurFrameOp(api::ISPCDevice &device, FrameBufferView &fbView); void process(void *) override; private: BufferDevice scratch; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/Blur.ispc000066400000000000000000000027271456566705700237440ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "fb/FrameOpKernelLaunch.ih" #include "rkcommon/math/vec.ih" // c++ shared #include "BlurShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE inline void BlurHorizontal_kernel( const FrameBufferView *uniform fbvSelf, const vec2ui id) { const LiveBlur *uniform self = (const LiveBlur *uniform)fbvSelf; uniform const vec2ui &dims = fbvSelf->viewDims; const vec4f *uniform inputBuffer = fbvSelf->colorBufferInput; vec4f v = make_vec4f(0.f); for (int32 i = -BLUR_RADIUS; i <= BLUR_RADIUS; i++) { const uint32 i0 = id.x + i; const uint32 absi = abs(i); if (i0 < dims.x) { v = v + inputBuffer[id.y * dims.x + i0] * self->weights[absi]; } } self->scratchBuffer[id.y * dims.x + id.x] = v; } inline void BlurVertical_kernel( const FrameBufferView *uniform fbvSelf, const vec2ui id) { const LiveBlur *uniform self = (const LiveBlur *uniform)fbvSelf; uniform const vec2ui &dims = fbvSelf->viewDims; const vec4f *uniform inputBuffer = self->scratchBuffer; vec4f v = make_vec4f(0.f); for (int32 i = -BLUR_RADIUS; i <= BLUR_RADIUS; i++) { const uint32 i0 = id.y + i; const uint32 absi = abs(i); if (i0 < dims.y) { v = v + inputBuffer[i0 * dims.x + id.x] * self->weights[absi]; } } fbvSelf->colorBufferOutput[id.y * dims.x + id.x] = v; } DEFINE_KERNEL_LAUNCHER(BlurHorizontal_kernel); DEFINE_KERNEL_LAUNCHER(BlurVertical_kernel); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/BlurShared.h000066400000000000000000000005021456566705700243510ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "fb/FrameBufferView.ih" #ifdef __cplusplus namespace ispc { #endif #define BLUR_RADIUS 4 struct LiveBlur { FrameBufferView super; vec4f *scratchBuffer; float weights[BLUR_RADIUS + 1]; }; #ifdef __cplusplus } #endif RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/ColorConversion.cpp000066400000000000000000000020431456566705700257770ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ColorConversion.h" #include "ISPCDevice.h" #include "fb/FrameBufferView.h" #ifndef OSPRAY_TARGET_SYCL extern "C" { #endif namespace ispc { void ColorConversion_kernelLauncher(const FrameBufferView *, void *, void *); } #ifndef OSPRAY_TARGET_SYCL } #endif namespace ospray { LiveColorConversionFrameOp::LiveColorConversionFrameOp(api::ISPCDevice &device, FrameBufferView &fbView, OSPFrameBufferFormat targetColorFormat) : AddStructShared(device.getIspcrtContext(), device, fbView), convBuffer(device.getIspcrtDevice(), fbView.viewDims.long_product() * sizeOf(targetColorFormat)) { getSh()->targetColorFormat = targetColorFormat; getSh()->convBuffer = convBuffer.devicePtr(); } void LiveColorConversionFrameOp::process(void *waitEvent) { void *cmdQueue = nullptr; #ifdef OSPRAY_TARGET_SYCL cmdQueue = &device.getSyclQueue(); #endif ispc::ColorConversion_kernelLauncher(&getSh()->super, cmdQueue, waitEvent); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/ColorConversion.h000066400000000000000000000012161456566705700254450ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "fb/FrameOp.h" // ispc shared #include "ColorConversionShared.h" namespace ospray { struct OSPRAY_SDK_INTERFACE LiveColorConversionFrameOp : public AddStructShared { LiveColorConversionFrameOp(api::ISPCDevice &device, FrameBufferView &fbView, OSPFrameBufferFormat targetColorFormat); void process(void *waitEvent) override; const BufferDeviceShadowed &getConvertedBuffer() { return convBuffer; } private: BufferDeviceShadowed convBuffer; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/ColorConversion.ispc000066400000000000000000000017751456566705700261660ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "fb/FrameOpKernelLaunch.ih" #include "rkcommon/math/vec.ih" // c++ shared #include "ColorConversionShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE inline void ColorConversion_kernel( const FrameBufferView *uniform fbvSelf, const vec2ui id) { const LiveColorConversion *uniform self = (const LiveColorConversion *uniform)fbvSelf; const uint32 i = id.y * fbvSelf->viewDims.x + id.x; vec4f v = fbvSelf->colorBufferInput[i]; switch (self->targetColorFormat) { case OSP_FB_RGBA8: { uint32 *uniform typedCB = (uint32 * uniform) self->convBuffer; typedCB[i] = cvt_uint32(v); } break; case OSP_FB_SRGBA: { uint32 *uniform typedCB = (uint32 * uniform) self->convBuffer; typedCB[i] = linear_to_srgba8(v); } break; case OSP_FB_RGBA32F: { // Should never get here } break; default: // Should never get here break; } } DEFINE_KERNEL_LAUNCHER(ColorConversion_kernel); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/ColorConversionShared.h000066400000000000000000000006171456566705700266000ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "fb/FrameBufferView.ih" #include "ospray/OSPEnums.h" #ifdef __cplusplus namespace ispc { #endif struct LiveColorConversion { FrameBufferView super; // Target color format OSPFrameBufferFormat targetColorFormat; // Converted color buffer void *convBuffer; }; #ifdef __cplusplus } #endif RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/Debug.cpp000066400000000000000000000016331456566705700237050ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Debug.h" #include "ISPCDevice.h" #include "fb/FrameBufferView.h" #ifndef OSPRAY_TARGET_SYCL extern "C" { #endif namespace ispc { void Debug_kernelLauncher(const FrameBufferView *, void *, void *); } #ifndef OSPRAY_TARGET_SYCL } #endif namespace ospray { DebugFrameOp::DebugFrameOp(api::Device &device) : FrameOp(static_cast(device)) {} std::unique_ptr DebugFrameOp::attach( FrameBufferView &fbView) { return rkcommon::make_unique(device, fbView); } std::string DebugFrameOp::toString() const { return "ospray::DebugFrameOp"; } void LiveDebugFrameOp::process(void *waitEvent) { void *cmdQueue = nullptr; #ifdef OSPRAY_TARGET_SYCL cmdQueue = &device.getSyclQueue(); #endif ispc::Debug_kernelLauncher(getSh(), cmdQueue, waitEvent); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/Debug.h000066400000000000000000000011431456566705700233460ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "fb/FrameOp.h" namespace ospray { struct OSPRAY_SDK_INTERFACE DebugFrameOp : public FrameOp { DebugFrameOp(api::Device &device); std::unique_ptr attach( FrameBufferView &fbView) override; std::string toString() const override; }; struct OSPRAY_SDK_INTERFACE LiveDebugFrameOp : public LiveFrameOp { LiveDebugFrameOp(api::ISPCDevice &device, FrameBufferView &fbView) : LiveFrameOp(device, fbView) {} void process(void *waitEvent) override; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/Debug.ispc000066400000000000000000000007741456566705700240660ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "fb/FrameOpKernelLaunch.ih" #include "rkcommon/math/vec.ih" // c++ shared #include "fb/FrameBufferView.ih" OSPRAY_BEGIN_ISPC_NAMESPACE inline void Debug_kernel(const FrameBufferView *uniform self, const vec2ui id) { const uint32 i = id.y * self->viewDims.x + id.x; vec4f v = self->colorBufferInput[i]; v.x = 1.f; self->colorBufferOutput[i] = v; } DEFINE_KERNEL_LAUNCHER(Debug_kernel); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/ToneMapper.cpp000066400000000000000000000054131456566705700247310ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ToneMapper.h" #include "ISPCDevice.h" #include "fb/FrameBufferView.h" #ifndef OSPRAY_TARGET_SYCL extern "C" { #endif namespace ispc { void ToneMapper_kernelLauncher(const FrameBufferView *, void *, void *); } #ifndef OSPRAY_TARGET_SYCL } #endif namespace ospray { ToneMapperFrameOp::ToneMapperFrameOp(api::Device &device) : FrameOp(static_cast(device)) {} void ToneMapperFrameOp::commit() { FrameOp::commit(); exposure = getParam("exposure", 1.f); // Default parameters fitted to the ACES 1.0 grayscale curve // (RRT.a1.0.3 + ODT.Academy.Rec709_100nits_dim.a1.0.3) // We included exposure adjustment to match 18% middle gray // (ODT(RRT(0.18)) = 0.18) const float aces_contrast = 1.6773f; const float aces_shoulder = 0.9714f; const float aces_midIn = 0.18f; const float aces_midOut = 0.18f; const float aces_hdrMax = 11.0785f; a = max(getParam("contrast", aces_contrast), 0.0001f); d = clamp(getParam("shoulder", aces_shoulder), 0.0001f, 1.f); float m = clamp(getParam("midIn", aces_midIn), 0.0001f, 1.f); float n = clamp(getParam("midOut", aces_midOut), 0.0001f, 1.f); float w = max(getParam("hdrMax", aces_hdrMax), 1.f); acesColor = getParam("acesColor", true); // Solve b and c b = -((powf(m, -a * d) * (-powf(m, a) + (n * (powf(m, a * d) * n * powf(w, a) - powf(m, a) * powf(w, a * d))) / (powf(m, a * d) * n - n * powf(w, a * d)))) / n); // avoid discontinuous curve by clamping to 0 c = max((powf(m, a * d) * n * powf(w, a) - powf(m, a) * powf(w, a * d)) / (powf(m, a * d) * n - n * powf(w, a * d)), 0.f); } std::unique_ptr ToneMapperFrameOp::attach( FrameBufferView &fbView) { return rkcommon::make_unique( device, fbView, exposure, a, b, c, d, acesColor); } std::string ToneMapperFrameOp::toString() const { return "ospray::ToneMapperFrameOp"; } LiveToneMapperFrameOp::LiveToneMapperFrameOp(api::ISPCDevice &device, FrameBufferView &fbView, float exposure, float a, float b, float c, float d, bool acesColor) : AddStructShared(device.getIspcrtContext(), device, fbView) { // Pass tone mapping parameters getSh()->exposure = exposure; getSh()->a = a; getSh()->b = b; getSh()->c = c; getSh()->d = d; getSh()->acesColor = acesColor; } void LiveToneMapperFrameOp::process(void *waitEvent) { void *cmdQueue = nullptr; #ifdef OSPRAY_TARGET_SYCL cmdQueue = &device.getSyclQueue(); #endif ispc::ToneMapper_kernelLauncher(&getSh()->super, cmdQueue, waitEvent); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/ToneMapper.h000066400000000000000000000017671456566705700244060ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "fb/FrameOp.h" // ispc shared #include "ToneMapperShared.h" namespace ospray { /*! \brief Generic tone mapping operator approximating ACES by default. */ struct OSPRAY_SDK_INTERFACE ToneMapperFrameOp : public FrameOp { ToneMapperFrameOp(api::Device &device); void commit() override; std::unique_ptr attach( FrameBufferView &fbView) override; std::string toString() const override; private: // Params for the tone mapping curve float a, b, c, d; bool acesColor; float exposure; }; struct OSPRAY_SDK_INTERFACE LiveToneMapperFrameOp : public AddStructShared { LiveToneMapperFrameOp(api::ISPCDevice &device, FrameBufferView &fbView, float exposure, float a, float b, float c, float d, bool acesColor); // Execute FrameOp kernel void process(void *waitEvent) override; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/ToneMapper.ispc000066400000000000000000000031021456566705700250760ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "fb/FrameOpKernelLaunch.ih" #include "rkcommon/math/LinearSpace.ih" #include "rkcommon/math/vec.ih" // c++ shared #include "ToneMapperShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE inline void ToneMapper_kernel( const FrameBufferView *uniform fbvSelf, const vec2ui id) { // ACES input transform matrix = RRT_SAT_MAT * XYZ_2_AP1_MAT * D65_2_D60_CAT * // REC709_2_XYZ_PRI_MAT const uniform LinearSpace3f acesInputMat = { {0.5972782409f, 0.0760130499f, 0.0284085382f}, {0.3545713181f, 0.9083220973f, 0.1338243154f}, {0.0482176639f, 0.0156579968f, 0.8375684636f}}; // ACES output transform matrix = XYZ_2_REC709_PRI_MAT * D60_2_D65_CAT * // AP1_2_XYZ_MAT * ODT_SAT_MAT const uniform LinearSpace3f acesOutputMat = { {1.6047539945f, -0.1020831870f, -0.0032670420f}, {-0.5310794927f, 1.1081322801f, -0.0727552477f}, {-0.0736720338f, -0.0060518756f, 1.0760219533f}}; const LiveToneMapper *uniform self = (const LiveToneMapper *uniform)fbvSelf; uniform const vec2ui &dims = fbvSelf->viewDims; const uint32 i = id.y * dims.x + id.x; vec4f col = fbvSelf->colorBufferInput[i]; vec3f x = make_vec3f(col) * self->exposure; if (self->acesColor) x = acesInputMat * x; x = pow(x, self->a) / (pow(x, self->a * self->d) * self->b + self->c); if (self->acesColor) x = acesOutputMat * x; x = clamp(x, make_vec3f(0.f), make_vec3f(1.f)); fbvSelf->colorBufferOutput[i] = make_vec4f(x, col.w); } DEFINE_KERNEL_LAUNCHER(ToneMapper_kernel); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/ToneMapperShared.h000066400000000000000000000010141456566705700255160ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "fb/FrameBufferView.ih" #ifdef __cplusplus namespace ispc { #endif // Based on the generic filmic tone mapping operator from // [Lottes, 2016, "Advanced Techniques and Optimization of HDR Color Pipelines"] struct LiveToneMapper { FrameBufferView super; // linear exposure adjustment float exposure; // coefficients float a, b, c, d; // ACES color transform flag bool acesColor; }; #ifdef __cplusplus } #endif RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/Variance.cpp000066400000000000000000000030011456566705700243760ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Variance.h" #include "ISPCDevice.h" #include "fb/FrameBufferView.h" #ifndef OSPRAY_TARGET_SYCL extern "C" { #endif namespace ispc { void Variance_kernelLauncher(const FrameBufferView *, void *, void *); } // namespace ispc #ifndef OSPRAY_TARGET_SYCL } #endif namespace ospray { LiveVarianceFrameOp::LiveVarianceFrameOp(api::ISPCDevice &device, FrameBufferView &fbView, const vec4f *varianceBuffer) : AddStructShared(device.getIspcrtContext(), device, fbView), taskVariance(device.getIspcrtContext(), fbView.viewDims.product()) { // Prepare kernel constant variables getSh()->rtSize = divRoundUp(fbView.fbDims, fbView.viewDims); getSh()->varianceBuffer = varianceBuffer; getSh()->taskVarianceBuffer = taskVariance.data(); } void LiveVarianceFrameOp::process(void *waitEvent) { // Run kernel void *cmdQueue = nullptr; #ifdef OSPRAY_TARGET_SYCL cmdQueue = &device.getSyclQueue(); #endif ispc::Variance_kernelLauncher(&getSh()->super, cmdQueue, waitEvent); firstRun = false; } float LiveVarianceFrameOp::getAvgError(const float errorThreshold) const { float maxErr = 0.f; float sumActErr = 0.f; int activeTasks = 0; std::for_each(taskVariance.cbegin(), taskVariance.cend(), [&](const float &err) { maxErr = std::max(maxErr, err); if (err >= errorThreshold) { sumActErr += err; activeTasks++; } }); return activeTasks ? sumActErr / activeTasks : maxErr; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/Variance.h000066400000000000000000000017621456566705700240570ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/ISPCRTBuffers.h" #include "fb/FrameOp.h" // ispc shared #include "VarianceShared.h" namespace ospray { // The variance frame op calculates per-RenderTask variance struct OSPRAY_SDK_INTERFACE LiveVarianceFrameOp : public AddStructShared { LiveVarianceFrameOp(api::ISPCDevice &device, FrameBufferView &fbView, const vec4f *varianceBuffer); void process(void *) override; void restart(); bool validError() const; float getError(const uint32_t id) const; float getAvgError(const float errorThreshold) const; private: BufferShared taskVariance; bool firstRun{true}; }; inline void LiveVarianceFrameOp::restart() { firstRun = true; } inline bool LiveVarianceFrameOp::validError() const { return firstRun == false; } inline float LiveVarianceFrameOp::getError(const uint32_t id) const { return taskVariance[id]; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/Variance.ispc000066400000000000000000000035721456566705700245670ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "fb/FrameOpKernelLaunch.ih" #include "rkcommon/math/vec.ih" // c++ shared #include "VarianceShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE inline void Variance_kernel( const FrameBufferView *uniform fbvSelf, const vec2ui id) { uniform const vec2ui &rtDims = fbvSelf->viewDims; uniform const vec2ui &fbDims = fbvSelf->fbDims; const vec4f *uniform colorBuffer = fbvSelf->colorBufferInput; const LiveVariance *uniform self = (const LiveVariance *uniform)fbvSelf; uniform const vec2ui rtSize = self->rtSize; const vec4f *uniform varianceBuffer = self->varianceBuffer; const vec2ui rtLower = id * rtSize; // Iterate over all pixels within single render task and calculate maximum // variance over collected samples float v = 0.f; int cnt = 0; for (uniform uint32 rtY = 0; rtY < rtSize.y; rtY++) { // Skip if out of range const uint32 fbY = rtLower.y + rtY; if (fbY >= fbDims.y) continue; for (uniform uint32 rtX = 0; rtX < rtSize.x; rtX++) { // Skip if out of range const uint32 fbX = rtLower.x + rtX; if (fbX >= fbDims.x) continue; const uint32 linearId = fbY * fbDims.x + fbX; const vec4f color = colorBuffer[linearId]; const vec4f variance = varianceBuffer[linearId]; const float den2 = reduce_add(make_vec3f(color)) + (1.f - color.w); // invert alpha (bright alpha is more important) if (den2 > 0.f) { cnt++; const vec4f diff = absf(color - variance); v += reduce_add(diff) * rsqrtf(den2); } } } if (cnt) v *= rcp((float)cnt); // avg const uint32 lId = id.y * rtDims.x + id.x; // scale to be backwards compatible with the old default tile size of 64x64 self->taskVarianceBuffer[lId] = v * 64.f; } DEFINE_KERNEL_LAUNCHER(Variance_kernel); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/fb/frame_ops/VarianceShared.h000066400000000000000000000005031456566705700251760ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "fb/FrameBufferView.ih" #ifdef __cplusplus namespace ispc { #endif struct LiveVariance { FrameBufferView super; vec2ui rtSize; const vec4f *varianceBuffer; float *taskVarianceBuffer; }; #ifdef __cplusplus } #endif RenderKit-ospray-f2a61c2/modules/cpu/fb/registration.cpp000066400000000000000000000011731456566705700234150ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // We don't want an instance of ObjectFactory static table in this library // so we have to include it with import define so the table will be imported // from 'ospray' library #define OBJECTFACTORY_IMPORT #include "common/ObjectFactory.h" #include "frame_ops/Blur.h" #include "frame_ops/Debug.h" #include "frame_ops/ToneMapper.h" namespace ospray { void registerAllImageOps() { ImageOp::registerType("blur"); ImageOp::registerType("debug"); ImageOp::registerType("tonemapper"); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/fb/registration.h000066400000000000000000000002231456566705700230550ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 namespace ospray { void registerAllImageOps(); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/000077500000000000000000000000001456566705700214415ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/geometry/Boxes.cpp000066400000000000000000000020101456566705700232160ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Boxes.h" #include "common/Data.h" #ifndef OSPRAY_TARGET_SYCL // ispc-generated files #include "geometry/Boxes_ispc.h" #else namespace ispc { void Boxes_bounds(const RTCBoundsFunctionArguments *uniform args); } #endif namespace ospray { Boxes::Boxes(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFG_BOX) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.postIntersect = reinterpret_cast( ispc::Boxes_postIntersect_addr()); #endif } std::string Boxes::toString() const { return "ospray::Boxes"; } void Boxes::commit() { boxData = getParamDataT("box", true); createEmbreeUserGeometry((RTCBoundsFunction)&ispc::Boxes_bounds); getSh()->boxes = *ispc(boxData); getSh()->super.numPrimitives = numPrimitives(); postCreationInfo(); } size_t Boxes::numPrimitives() const { return boxData ? boxData->size() : 0; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/Boxes.h000066400000000000000000000010371456566705700226730ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Geometry.h" // ispc shared #include "BoxesShared.h" namespace ospray { struct OSPRAY_SDK_INTERFACE Boxes : public AddStructShared { Boxes(api::ISPCDevice &device); virtual ~Boxes() override = default; virtual std::string toString() const override; virtual void commit() override; virtual size_t numPrimitives() const override; protected: Ref> boxData; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/Boxes.ih000066400000000000000000000007351456566705700230500ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "geometry/Geometry.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL void Boxes_postIntersect(const Geometry *uniform _self, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags); SYCL_EXTERNAL unmasked void Boxes_intersect_kernel( const RTCIntersectFunctionNArguments *uniform args, const uniform bool isOcclusionTest); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/geometry/Boxes.ispc000066400000000000000000000037541456566705700234120ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "common/Data.ih" #include "common/DifferentialGeometry.ih" #include "common/FilterIntersect.ih" #include "common/Intersect.ih" #include "common/Ray.ih" #include "rkcommon/math/box.ih" #include "rkcommon/math/vec.ih" // c++ shared #include "BoxesShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE export void Boxes_bounds(const RTCBoundsFunctionArguments *uniform args) { Boxes *uniform self = (Boxes * uniform) args->geometryUserPtr; uniform int primID = args->primID; box3fa *uniform out = (box3fa * uniform) args->bounds_o; *out = make_box3fa(get_box3f(self->boxes, primID)); } SYCL_EXTERNAL unmasked void Boxes_intersect_kernel( const RTCIntersectFunctionNArguments *uniform args, const uniform bool isOcclusionTest) { // make sure to set the mask if (!args->valid[programIndex]) { return; } args->valid[programIndex] = 0; Boxes *uniform self = (Boxes * uniform) args->geometryUserPtr; varying Ray *uniform ray = (varying Ray * uniform) args->rayhit; uniform int primID = args->primID; uniform box3f box = get_box3f(self->boxes, primID); const Intersections isect = intersectBox(ray->org, ray->dir, box); // call intersection filtering callback and setup hit if accepted if (filterIntersectionBoth(args, isect, isOcclusionTest)) { args->valid[programIndex] = -1; } } export void Boxes_intersect( const struct RTCIntersectFunctionNArguments *uniform args) { Boxes_intersect_kernel(args, false); } export void Boxes_occluded( const struct RTCOccludedFunctionNArguments *uniform args) { Boxes_intersect_kernel((RTCIntersectFunctionNArguments * uniform) args, true); } SYCL_EXTERNAL void Boxes_postIntersect(const Geometry *uniform, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64) { dg.Ng = dg.Ns = ray.Ng; } export void *uniform Boxes_postIntersect_addr() { return (void *uniform)Boxes_postIntersect; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/geometry/BoxesShared.h000066400000000000000000000005661456566705700240300ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "GeometryShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Boxes { Geometry super; Data1D boxes; #ifdef __cplusplus Boxes() { super.type = GEOMETRY_TYPE_BOXES; } #endif }; #ifdef __cplusplus } // namespace ispc #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/geometry/Curves.cpp000066400000000000000000000165721456566705700234270ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Curves.h" #include "common/DGEnum.h" #ifndef OSPRAY_TARGET_SYCL // ispc-generated files #include "geometry/Curves_ispc.h" #endif // std #include namespace ospray { static std::map, RTCGeometryType> curveMap = {{{OSP_ROUND, OSP_LINEAR}, RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE}, {{OSP_FLAT, OSP_LINEAR}, RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE}, {{OSP_RIBBON, OSP_LINEAR}, (RTCGeometryType)-1}, {{OSP_DISJOINT, OSP_LINEAR}, RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE}, {{OSP_ROUND, OSP_BEZIER}, RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE}, {{OSP_FLAT, OSP_BEZIER}, RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE}, {{OSP_RIBBON, OSP_BEZIER}, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE}, {{OSP_DISJOINT, OSP_BEZIER}, (RTCGeometryType)-1}, {{OSP_ROUND, OSP_BSPLINE}, RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE}, {{OSP_FLAT, OSP_BSPLINE}, RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE}, {{OSP_RIBBON, OSP_BSPLINE}, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE}, {{OSP_DISJOINT, OSP_BSPLINE}, (RTCGeometryType)-1}, {{OSP_ROUND, OSP_HERMITE}, RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE}, {{OSP_FLAT, OSP_HERMITE}, RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE}, {{OSP_RIBBON, OSP_HERMITE}, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE}, {{OSP_DISJOINT, OSP_HERMITE}, (RTCGeometryType)-1}, {{OSP_ROUND, OSP_CATMULL_ROM}, RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE}, {{OSP_FLAT, OSP_CATMULL_ROM}, RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE}, {{OSP_RIBBON, OSP_CATMULL_ROM}, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE}, {{OSP_DISJOINT, OSP_CATMULL_ROM}, (RTCGeometryType)-1}}; static std::map curveFeatureFlags = { {RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE, FFG_CONE_LINEAR_CURVE}, {RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE, FFG_ROUND_LINEAR_CURVE}, {RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE, FFG_FLAT_LINEAR_CURVE}, {RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE, FFG_ROUND_BEZIER_CURVE}, {RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE, FFG_FLAT_BEZIER_CURVE}, {RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE, FFG_NORMAL_ORIENTED_BEZIER_CURVE}, {RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE, FFG_ROUND_BSPLINE_CURVE}, {RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE, FFG_FLAT_BSPLINE_CURVE}, {RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE, FFG_NORMAL_ORIENTED_BSPLINE_CURVE}, {RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE, FFG_ROUND_HERMITE_CURVE}, {RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE, FFG_FLAT_HERMITE_CURVE}, {RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE, FFG_NORMAL_ORIENTED_HERMITE_CURVE}, {RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE, FFG_ROUND_CATMULL_ROM_CURVE}, {RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE, FFG_FLAT_CATMULL_ROM_CURVE}, {RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE, FFG_NORMAL_ORIENTED_CATMULL_ROM_CURVE}}; // Curves definitions /////////////////////////////////////////////////////// Curves::Curves(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFG_NONE) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.postIntersect = reinterpret_cast( ispc::Curves_postIntersect_addr()); #endif // TODO implement area sampling of OldCurves for geometry lights } std::string Curves::toString() const { return "ospray::Curves"; } void Curves::commit() { indexData = getParamDataT("index", true); normalData = nullptr; tangentData = nullptr; texcoordData = getParamDataT("vertex.texcoord"); Ref> vertexNoRadiusData = getParamDataT("vertex.position"); if (vertexNoRadiusData) { // round, linear curves with constant radius float radius = getParam("radius", 0.01f); curveType = (OSPCurveType)getParam("type", OSP_ROUND); curveBasis = (OSPCurveBasis)getParam("basis", OSP_LINEAR); if (curveMap[std::make_pair(curveType, curveBasis)] != RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE) throw std::runtime_error( "constant-radius curves need to be of type OSP_ROUND and have " "basis OSP_LINEAR"); // To maintain OSPRay 2.x compatibility and keep support for // the global 'radius' parameter, a vec4f vertex buffer copy // has to be created. It specifies radius on per-vertex basis and // is required by Embree. TODO: Refactor for OSPRay 3.x DataT *dataT = (DataT *)new Data( getISPCDevice(), OSP_VEC4F, vertexNoRadiusData->numItems); for (size_t i = 0; i < dataT->size(); i++) { const vec3f &v = (*vertexNoRadiusData)[i]; (*dataT)[i] = vec4f(v.x, v.y, v.z, radius); } vertexData = dataT; dataT->refDec(); } else { // embree curves vertexData = getParamDataT("vertex.position_radius", true); curveType = (OSPCurveType)getParam("type", OSP_UNKNOWN_CURVE_TYPE); if (curveType == OSP_UNKNOWN_CURVE_TYPE) throw std::runtime_error("curves geometry has invalid 'type'"); curveBasis = (OSPCurveBasis)getParam("basis", OSP_UNKNOWN_CURVE_BASIS); if (curveBasis == OSP_UNKNOWN_CURVE_BASIS) throw std::runtime_error("curves geometry has invalid 'basis'"); if (curveType == OSP_RIBBON) normalData = getParamDataT("vertex.normal", true); if (curveBasis == OSP_HERMITE) tangentData = getParamDataT("vertex.tangent", true); } colorData = getParamDataT("vertex.color"); embreeCurveType = curveMap[std::make_pair(curveType, curveBasis)]; if (embreeCurveType == (RTCGeometryType)-1) throw std::runtime_error("unsupported combination of 'type' and 'basis'"); createEmbreeGeometry(); getSh()->geom = embreeGeometry; getSh()->flagMask = -1; getSh()->super.numPrimitives = numPrimitives(); getSh()->curveType = curveType; getSh()->curveBasis = curveBasis; getSh()->index = *ispc(indexData); if (!colorData) { getSh()->flagMask &= ispc::int64(~DG_COLOR); } else { getSh()->color = *ispc(colorData); } if (!texcoordData) { getSh()->flagMask &= ispc::int64(~DG_TEXCOORD); } else { getSh()->texcoord = *ispc(texcoordData); } postCreationInfo(vertexData->size()); featureFlagsGeometry = curveFeatureFlags[embreeCurveType]; } size_t Curves::numPrimitives() const { return indexData->size(); } void Curves::createEmbreeGeometry() { Geometry::createEmbreeGeometry(embreeCurveType); Ref> vertex4f(&vertexData->as()); setEmbreeGeometryBuffer(embreeGeometry, RTC_BUFFER_TYPE_VERTEX, vertex4f); setEmbreeGeometryBuffer(embreeGeometry, RTC_BUFFER_TYPE_INDEX, indexData); setEmbreeGeometryBuffer(embreeGeometry, RTC_BUFFER_TYPE_NORMAL, normalData); setEmbreeGeometryBuffer(embreeGeometry, RTC_BUFFER_TYPE_TANGENT, tangentData); if (colorData) { rtcSetGeometryVertexAttributeCount(embreeGeometry, 1); setEmbreeGeometryBuffer( embreeGeometry, RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE, colorData); } if (texcoordData) { rtcSetGeometryVertexAttributeCount(embreeGeometry, 2); setEmbreeGeometryBuffer( embreeGeometry, RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE, texcoordData, 1); } rtcCommitGeometry(embreeGeometry); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/Curves.h000066400000000000000000000017141456566705700230640ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Geometry.h" #include "common/Data.h" // ispc shared #include "CurvesShared.h" namespace ospray { struct OSPRAY_SDK_INTERFACE Curves : public AddStructShared { Curves(api::ISPCDevice &device); virtual ~Curves() override = default; virtual std::string toString() const override; virtual void commit() override; virtual size_t numPrimitives() const override; protected: Ref> vertexData; Ref> indexData; Ref> normalData; Ref> tangentData; Ref> colorData; Ref> texcoordData; RTCGeometryType embreeCurveType{(RTCGeometryType)-1}; OSPCurveType curveType{OSP_UNKNOWN_CURVE_TYPE}; OSPCurveBasis curveBasis{OSP_UNKNOWN_CURVE_BASIS}; private: void createEmbreeGeometry(); }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/Curves.ih000066400000000000000000000005101456566705700232260ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "geometry/Geometry.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL void Curves_postIntersect(const Geometry *uniform _self, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/geometry/Curves.ispc000066400000000000000000000056421456566705700235770ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Geometry.ih" #include "common/Data.ih" // c++ shared #include "CurvesShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE #ifdef OSPRAY_TARGET_SYCL using namespace ospray; #endif template inline T interpolate(const Curves *uniform self, const uniform Data1D &buffer, const varying Ray &ray) { T result = {0}; const uint32 index = get(self->index, ray.primID); const float u = ray.u; switch (self->curveBasis) { case OSP_LINEAR: case OSP_HERMITE: { const T v0 = get(buffer, index + 0); const T v1 = get(buffer, index + 1); result = lerp(u, v0, v1); } break; case OSP_BEZIER: { const T v0 = get(buffer, index + 0); const T v1 = get(buffer, index + 1); const T v2 = get(buffer, index + 2); const T v3 = get(buffer, index + 3); const float t1 = u; const float t0 = 1.0f - t1; const float b0 = t0 * t0 * t0; const float b1 = 3.0f * t1 * (t0 * t0); const float b2 = 3.0f * (t1 * t1) * t0; const float b3 = t1 * t1 * t1; result = b0 * v0 + b1 * v1 + b2 * v2 + b3 * v3; } break; case OSP_BSPLINE: { const T v0 = get(buffer, index + 0); const T v1 = get(buffer, index + 1); const T v2 = get(buffer, index + 2); const T v3 = get(buffer, index + 3); const float t = u; const float s = 1.0f - u; const float n0 = s * s * s; const float n1 = (4.0f * (s * s * s) + (t * t * t)) + (12.0f * ((s * t) * s) + 6.0f * ((t * s) * t)); const float n2 = (4.0f * (t * t * t) + (s * s * s)) + (12.0f * ((t * s) * t) + 6.0f * ((s * t) * s)); const float n3 = t * t * t; result = (1.0f / 6.0f) * (n0 * v0 + n1 * v1 + n2 * v2 + n3 * v3); } break; case OSP_CATMULL_ROM: { const T v0 = get(buffer, index + 0); const T v1 = get(buffer, index + 1); const T v2 = get(buffer, index + 2); const T v3 = get(buffer, index + 3); const float t = u; const float s = 1.0f - u; const float n0 = -t * s * s; const float n1 = 2.0f + t * t * (3.0f * t - 5.0f); const float n2 = 2.0f + s * s * (3.0f * s - 5.0f); const float n3 = -s * t * t; result = 0.5f * (n0 * v0 + n1 * v1 + n2 * v2 + n3 * v3); } break; case OSP_UNKNOWN_CURVE_BASIS: default: break; } return result; } SYCL_EXTERNAL void Curves_postIntersect(const Geometry *uniform _self, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags) { const Curves *uniform self = (const Curves *uniform)_self; dg.Ng = dg.Ns = ray.Ng; flags &= self->flagMask; if (flags & DG_COLOR) { dg.color = interpolate(self, self->color, ray); } if (flags & DG_TEXCOORD) { dg.st = interpolate(self, self->texcoord, ray); } } export void *uniform Curves_postIntersect_addr() { return (void *uniform)Curves_postIntersect; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/geometry/CurvesShared.h000066400000000000000000000012461456566705700242130ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "GeometryShared.h" #include "ospray/OSPEnums.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Curves { Geometry super; // inherited geometry fields RTCGeometry geom; int64 flagMask; OSPCurveType curveType; OSPCurveBasis curveBasis; Data1D index; Data1D color; Data1D texcoord; #ifdef __cplusplus Curves() : geom(nullptr), flagMask(-1), curveType(OSP_UNKNOWN_CURVE_TYPE), curveBasis(OSP_UNKNOWN_CURVE_BASIS) { super.type = GEOMETRY_TYPE_CURVES; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/geometry/GeometricModel.cpp000066400000000000000000000071131456566705700250460ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "GeometricModel.h" #include "render/Material.h" namespace ospray { GeometricModel::GeometricModel(api::ISPCDevice &device, Geometry *_geometry) : AddStructShared(device.getIspcrtContext(), device), geomAPI(_geometry) { managedObjectType = OSP_GEOMETRIC_MODEL; } std::string GeometricModel::toString() const { return "ospray::GeometricModel"; } void GeometricModel::commit() { geom = getParamObject("geometry", geomAPI.ptr); if (!geom) throw std::runtime_error(toString() + " received NULL 'geometry'"); materialData = getParamDataT("material", false, true); materialArray = nullptr; materialIDArray = nullptr; getSh()->material = nullptr; getSh()->materialID = nullptr; getSh()->numMaterials = 0; featureFlagsOther = FFO_NONE; if (materialData) { for (auto &&mat : materialData->as()) featureFlagsOther |= mat->getFeatureFlags().other; materialArray = make_buffer_shared_unique( getISPCDevice().getIspcrtContext(), createArrayOfSh(materialData->as())); getSh()->material = materialArray->sharedPtr(); getSh()->numMaterials = materialArray->size(); } else { materialData = getParamDataT("material", false, true); if (materialData) { materialIDArray = make_buffer_shared_unique( getISPCDevice().getIspcrtContext(), materialData->as().data(), materialData->size()); getSh()->materialID = materialIDArray->sharedPtr(); getSh()->numMaterials = materialIDArray->size(); } } colorData = getParamDataT("color", false, true); indexData = getParamDataT("index"); size_t maxItems = geom->numPrimitives(); if (indexData && indexData->size() < maxItems) { postStatusMsg(OSP_LOG_INFO) << toString() << " not enough 'index' elements for 'geometry', clamping"; } if (indexData) maxItems = 256; // conservative, should actually go over the index if (materialData && materialData->size() > 1 && materialData->size() < maxItems) { postStatusMsg(OSP_LOG_INFO) << toString() << " potentially not enough 'material' elements for " "'geometry', clamping"; } if (colorData && colorData->size() > 1 && colorData->size() < maxItems) { postStatusMsg(OSP_LOG_INFO) << toString() << " potentially not enough 'color' elements for 'geometry', clamping"; } getSh()->geom = geom->getSh(); getSh()->color = *ispc(colorData); getSh()->index = *ispc(indexData); getSh()->invertedNormals = getParam("invertNormals", false); getSh()->userID = getParam("id", RTC_INVALID_GEOMETRY_ID); } bool GeometricModel::hasEmissiveMaterials( Ref> rendererMaterials) const { // No materials used - nothing to check if (!materialData) return false; // Check geometry model materials bool hasEmissive = false; if (materialArray) { for (auto &&mat : materialData->as()) if (mat->isEmissive()) { hasEmissive = true; break; } } // Check renderer materials referenced from geometry model else if (materialIDArray) { for (auto matIdx : materialData->as()) if ((matIdx < rendererMaterials->size()) && ((*rendererMaterials)[matIdx]->isEmissive())) { hasEmissive = true; break; } } // Done return hasEmissive; } OSPTYPEFOR_DEFINITION(GeometricModel *); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/GeometricModel.h000066400000000000000000000032661456566705700245200ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Geometry.h" #include "common/Data.h" // ispc shared #include "GeometricModelShared.h" namespace ispc { struct Material; } namespace ospray { struct Material; struct OSPRAY_SDK_INTERFACE GeometricModel : public AddStructShared { GeometricModel(api::ISPCDevice &device, Geometry *geometry); ~GeometricModel() override = default; std::string toString() const override; void commit() override; Geometry &geometry(); RTCGeometry embreeGeometryHandle() const; bool invertedNormals() const; bool hasEmissiveMaterials( Ref> rendererMaterials) const; FeatureFlags getFeatureFlags() const; private: Ref geom; const Ref geomAPI; Ref materialData; Ref> colorData; Ref> indexData; std::unique_ptr> materialArray; std::unique_ptr> materialIDArray; FeatureFlagsOther featureFlagsOther{FFO_NONE}; }; OSPTYPEFOR_SPECIALIZATION(GeometricModel *, OSP_GEOMETRIC_MODEL); // Inlined members ////////////////////////////////////////////////////////// inline Geometry &GeometricModel::geometry() { return *geom; } inline RTCGeometry GeometricModel::embreeGeometryHandle() const { return geom->getEmbreeGeometry(); } inline bool GeometricModel::invertedNormals() const { return getSh()->invertedNormals; } inline FeatureFlags GeometricModel::getFeatureFlags() const { FeatureFlags ff = geom->getFeatureFlags(); ff.other |= featureFlagsOther; return ff; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/GeometricModel.ih000066400000000000000000000037561456566705700246750ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Geometry.ih" #include "GeometryDispatch.ih" #include "common/Data.ih" #include "common/FeatureFlagsEnum.h" #include "render/Renderer.ih" #include "rkcommon/math/AffineSpace.ih" // c++ shared #include "GeometricModelShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE #ifdef OSPRAY_TARGET_SYCL using namespace ospray; #endif inline Material *GeometricModel_getMaterial(const GeometricModel *uniform self, const Renderer *uniform renderer, const int32 primID) { if ((!self->material) && (!self->materialID)) return NULL; uint32 idx = primID; if (valid(self->index)) { idx = get_uint8(self->index, min(idx, self->index.numItems - 1)); } uniform uint32 lastMaterial = self->numMaterials - 1; Material **uniform mats = (Material * *uniform) self->material; if (!mats) { idx = self->materialID[min(idx, lastMaterial)]; mats = renderer->material; lastMaterial = renderer->numMaterials - 1; } if (mats) return mats[min(idx, lastMaterial)]; return NULL; } inline void GeometricModel_postIntersect(const GeometricModel *uniform self, const Renderer *uniform renderer, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags, const uniform FeatureFlagsHandler &ffh) { Geometry *uniform geom = self->geom; Geometry_dispatch_postIntersect(geom, dg, ray, flags, ffh); dg.areaPDF = self->areaPDF; dg.objID = (self->userID == RTC_INVALID_GEOMETRY_ID) ? ray.geomID : self->userID; if (flags & DG_COLOR && valid(self->color)) { uint32 idx = ray.primID; if (valid(self->index)) { idx = get_uint8(self->index, min(idx, self->index.numItems - 1)); } dg.color = get_vec4f(self->color, min(idx, self->color.numItems - 1)); } if (renderer) { dg.material = GeometricModel_getMaterial(self, renderer, ray.primID); } if (flags & DG_NS && self->invertedNormals) dg.Ns = neg(dg.Ns); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/geometry/GeometricModel.ispc000066400000000000000000000034071456566705700252240ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "GeometricModel.ih" #include "math/Distribution1D.ih" #include "render/Material.ih" // c++ shared #include "common/InstanceShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE export uniform int GeometricModel_gatherEmissivePrimIDs(void *uniform _model, void *uniform _renderer, void *uniform _instance, int *uniform primIDs, float *uniform distribution, uniform float &pdf) { GeometricModel *uniform model = (GeometricModel * uniform) _model; const Renderer *uniform renderer = (Renderer * uniform) _renderer; const Geometry *uniform geo = model->geom; const Instance *uniform instance = (Instance * uniform) _instance; // create the list of emissive primitive IDs uniform int32 numEmissivePrims = 0; #ifdef OSPRAY_TARGET_SYCL // SYCL execution in a thread is scalar for (int primID = 0; primID < geo->numPrimitives; ++primID) { #else foreach (primID = 0 ... geo->numPrimitives) { #endif Material *mat = (Material *)GeometricModel_getMaterial(model, renderer, primID); const vec3f emission = mat->emission; if (reduce_max(emission) > 0.f) { int offset = exclusive_scan_add(1); primIDs[numEmissivePrims + offset] = primID; numEmissivePrims += reduce_add(1); } } // create the sampling distribution // TODO: use emissive power instead of just area // TODO: motion blur can introduce scale, which means areas cannot // accurately be precomputed // Note: Can stay as a ptr call if not moved to GPU geo->getAreas(geo, primIDs, numEmissivePrims, instance->xfm, distribution); pdf = model->areaPDF = 1.f / Distribution1D_create(numEmissivePrims, distribution); return numEmissivePrims; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/geometry/GeometricModelShared.h000066400000000000000000000013371456566705700256440ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "GeometryShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Material; struct GeometricModel { Geometry *geom; Data1D color; Data1D index; // per-primitive property mapping Material **material; uint32 *materialID; uint32 numMaterials; bool invertedNormals; float areaPDF; unsigned int userID; #ifdef __cplusplus GeometricModel() : geom(nullptr), material(nullptr), materialID(nullptr), numMaterials(0), invertedNormals(false), areaPDF(0.f), userID(RTC_INVALID_GEOMETRY_ID) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/geometry/Geometry.cpp000066400000000000000000000032241456566705700237410ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Geometry.h" #include "common/Data.h" #ifndef OSPRAY_TARGET_SYCL #include "geometry/GeometryDispatch_ispc.h" #endif namespace ospray { // Geometry definitions /////////////////////////////////////////////////////// Geometry::Geometry(api::ISPCDevice &device, const FeatureFlagsGeometry ffg) : AddStructShared(device.getIspcrtContext(), device), featureFlagsGeometry(ffg) { managedObjectType = OSP_GEOMETRY; } Geometry::~Geometry() { if (embreeGeometry) rtcReleaseGeometry(embreeGeometry); } std::string Geometry::toString() const { return "ospray::Geometry"; } void Geometry::postCreationInfo(size_t numVerts) const { std::stringstream ss; ss << toString() << " created: #primitives=" << numPrimitives(); if (numVerts > 0) ss << ", #vertices=" << numVerts; postStatusMsg(OSP_LOG_INFO) << ss.str(); } void Geometry::createEmbreeGeometry(RTCGeometryType type) { if (embreeGeometry) rtcReleaseGeometry(embreeGeometry); if (!getISPCDevice().getEmbreeDevice()) { throw std::runtime_error("invalid Embree device"); } embreeGeometry = rtcNewGeometry(getISPCDevice().getEmbreeDevice(), type); } void Geometry::createEmbreeUserGeometry(RTCBoundsFunction boundsFn) { createEmbreeGeometry(RTC_GEOMETRY_TYPE_USER); // Setup Embree user-defined geometry rtcSetGeometryUserData(embreeGeometry, getSh()); rtcSetGeometryUserPrimitiveCount(embreeGeometry, numPrimitives()); rtcSetGeometryBoundsFunction(embreeGeometry, boundsFn, getSh()); rtcCommitGeometry(embreeGeometry); } OSPTYPEFOR_DEFINITION(Geometry *); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/Geometry.h000066400000000000000000000116331456566705700234110ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/Data.h" #include "common/FeatureFlagsEnum.h" #include "common/ObjectFactory.h" // embree #include "common/Embree.h" // ispc shared #include "GeometryShared.h" namespace ospray { struct OSPRAY_SDK_INTERFACE Geometry : public AddStructShared, public ObjectFactory { Geometry(api::ISPCDevice &device, const FeatureFlagsGeometry ffg); virtual ~Geometry() override; virtual std::string toString() const override; virtual size_t numPrimitives() const = 0; void postCreationInfo(size_t numVerts = 0) const; RTCGeometry getEmbreeGeometry() const; bool supportAreaLighting() const; virtual FeatureFlags getFeatureFlags() const; protected: RTCGeometry embreeGeometry{nullptr}; FeatureFlagsGeometry featureFlagsGeometry; void createEmbreeGeometry(RTCGeometryType type); // NOTE: We now pass intersection functions through Embree RTCIntersectionArgs // context parameter so that they can be inlined in SYCL void createEmbreeUserGeometry(RTCBoundsFunction boundsFn); }; OSPTYPEFOR_SPECIALIZATION(Geometry *, OSP_GEOMETRY); inline RTCGeometry Geometry::getEmbreeGeometry() const { return embreeGeometry; } inline bool Geometry::supportAreaLighting() const { return (getSh()->sampleArea != nullptr) && (getSh()->getAreas != nullptr); } inline FeatureFlags Geometry::getFeatureFlags() const { FeatureFlags ff; ff.geometry = featureFlagsGeometry; return ff; } // convenience wrappers to set Embree buffer ////////////////////////////////// template struct RTCFormatFor { static constexpr RTCFormat value = RTC_FORMAT_UNDEFINED; }; #define RTCFORMATFOR_SPECIALIZATION(type, rtc_format) \ template <> \ struct RTCFormatFor \ { \ static constexpr RTCFormat value = rtc_format; \ }; RTCFORMATFOR_SPECIALIZATION(char, RTC_FORMAT_CHAR); RTCFORMATFOR_SPECIALIZATION(unsigned char, RTC_FORMAT_UCHAR); RTCFORMATFOR_SPECIALIZATION(short, RTC_FORMAT_SHORT); RTCFORMATFOR_SPECIALIZATION(unsigned short, RTC_FORMAT_USHORT); RTCFORMATFOR_SPECIALIZATION(int32_t, RTC_FORMAT_INT); RTCFORMATFOR_SPECIALIZATION(vec2i, RTC_FORMAT_INT2); RTCFORMATFOR_SPECIALIZATION(vec3i, RTC_FORMAT_INT3); RTCFORMATFOR_SPECIALIZATION(vec4i, RTC_FORMAT_INT4); RTCFORMATFOR_SPECIALIZATION(uint32_t, RTC_FORMAT_UINT); RTCFORMATFOR_SPECIALIZATION(vec2ui, RTC_FORMAT_UINT2); RTCFORMATFOR_SPECIALIZATION(vec3ui, RTC_FORMAT_UINT3); RTCFORMATFOR_SPECIALIZATION(vec4ui, RTC_FORMAT_UINT4); RTCFORMATFOR_SPECIALIZATION(int64_t, RTC_FORMAT_LLONG); RTCFORMATFOR_SPECIALIZATION(vec2l, RTC_FORMAT_LLONG2); RTCFORMATFOR_SPECIALIZATION(vec3l, RTC_FORMAT_LLONG3); RTCFORMATFOR_SPECIALIZATION(vec4l, RTC_FORMAT_LLONG4); RTCFORMATFOR_SPECIALIZATION(uint64_t, RTC_FORMAT_ULLONG); RTCFORMATFOR_SPECIALIZATION(vec2ul, RTC_FORMAT_ULLONG2); RTCFORMATFOR_SPECIALIZATION(vec3ul, RTC_FORMAT_ULLONG3); RTCFORMATFOR_SPECIALIZATION(vec4ul, RTC_FORMAT_ULLONG4); RTCFORMATFOR_SPECIALIZATION(float, RTC_FORMAT_FLOAT); RTCFORMATFOR_SPECIALIZATION(vec2f, RTC_FORMAT_FLOAT2); RTCFORMATFOR_SPECIALIZATION(vec3f, RTC_FORMAT_FLOAT3); RTCFORMATFOR_SPECIALIZATION(vec4f, RTC_FORMAT_FLOAT4); RTCFORMATFOR_SPECIALIZATION(linear2f, RTC_FORMAT_FLOAT2X2_COLUMN_MAJOR); RTCFORMATFOR_SPECIALIZATION(linear3f, RTC_FORMAT_FLOAT3X3_COLUMN_MAJOR); RTCFORMATFOR_SPECIALIZATION(affine2f, RTC_FORMAT_FLOAT2X3_COLUMN_MAJOR); RTCFORMATFOR_SPECIALIZATION(affine3f, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR); #undef RTCFORMATFOR_SPECIALIZATION // ... via Ref, NoOp when data is invalid template void setEmbreeGeometryBuffer(RTCGeometry geom, enum RTCBufferType type, Ref> &dataRef, unsigned int slot = 0) { if (!dataRef) return; rtcSetSharedGeometryBuffer(geom, type, slot, RTCFormatFor::value, dataRef->data(), 0, dataRef->stride(), dataRef->size()); } // ... via *ospData, NoOp when data is invalid template void setEmbreeGeometryBuffer(RTCGeometry geom, enum RTCBufferType type, const DataT *dataPtr, unsigned int slot = 0) { if (!dataPtr) return; rtcSetSharedGeometryBuffer(geom, type, slot, RTCFormatFor::value, dataPtr->data(), 0, dataPtr->stride(), dataPtr->size()); } // ... via an std::vector template void setEmbreeGeometryBuffer(RTCGeometry geom, enum RTCBufferType type, std::vector &data, unsigned int slot = 0) { rtcSetSharedGeometryBuffer(geom, type, slot, RTCFormatFor::value, data.data(), 0, sizeof(T), data.size()); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/Geometry.ih000066400000000000000000000003661456566705700235630ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "../common/DifferentialGeometry.ih" #include "../common/Ray.ih" #include "rkcommon/math/AffineSpace.ih" // c++ shared #include "GeometryShared.h" RenderKit-ospray-f2a61c2/modules/cpu/geometry/GeometryDispatch.ih000066400000000000000000000035461456566705700252460ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/FeatureFlags.ih" #include "common/FeatureFlagsEnum.h" OSPRAY_BEGIN_ISPC_NAMESPACE // Geometries are supposed to fill certain members of DifferentialGeometry: // calculate Ng, Ns, st, color, and materialID if the respective bit DG_NG, // DG_NS, DG_TEXCOORD, DG_COLOR, and DG_MATERIALID, in flags is set. // Important with instancing: P and ray are in world-coordinates, whereas Ng // and Ns are in object-coordinates and transformed to world-space by // Instance_postIntersect. // World::postIntersect already set the hit point P, color, geometry, and // material before, and handles normalization/faceforwarding // (DG_NORMALIZE/DG_FACEFORWARD) after Geometry_postIntersectFct is called. // Thus the material pointer only needs to be set if different to // geometry->material, or the color when different to vec4f(1.0f). SYCL_EXTERNAL void Geometry_dispatch_postIntersect(const Geometry *uniform self, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags, const uniform FeatureFlagsHandler &ffh); // sample the given primitive uniformly wrt. area SYCL_EXTERNAL SampleAreaRes Geometry_dispatch_sampleArea( const Geometry *const uniform, const int32 primID, const uniform affine3f &xfm, // instance transformation (obj2world) const uniform affine3f &rcp_xfm, // inverse transformation (world2obj) const vec2f &s, // random numbers to generate the sample const float time, // for deformation motion blur const uniform FeatureFlagsHandler &ffh); RTC_SYCL_INDIRECTLY_CALLABLE unmasked void Geometry_dispatch_intersect( RTCIntersectFunctionNArguments *uniform args); RTC_SYCL_INDIRECTLY_CALLABLE unmasked void Geometry_dispatch_occluded( RTCOccludedFunctionNArguments *uniform args); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/geometry/GeometryDispatch.ispc000066400000000000000000000120201456566705700255670ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/DifferentialGeometry.ih" #include "common/FeatureFlagsEnum.h" #include "common/Ray.ih" #include "common/RayQueryContext.ih" #include "geometry/Boxes.ih" #include "geometry/Curves.ih" #include "geometry/GeometryDispatch.ih" #ifdef OSPRAY_ENABLE_VOLUMES #include "geometry/Isosurfaces.ih" #endif #include "geometry/Mesh.ih" #include "geometry/Planes.ih" #include "geometry/Spheres.ih" #include "geometry/Subdivision.ih" // c++ shared #include "geometry/GeometryShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL void Geometry_dispatch_postIntersect(const Geometry *uniform self, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlagsGeometry ffg = getFeatureFlagsGeometry(ffh); if ((self->type == GEOMETRY_TYPE_QUAD_MESH) && (ffg & FFG_QUAD)) { QuadMesh_postIntersect(self, dg, ray, flags); } else if ((self->type == GEOMETRY_TYPE_TRIANGLE_MESH) && (ffg & FFG_TRIANGLE)) { TriangleMesh_postIntersect(self, dg, ray, flags); } else if ((self->type == GEOMETRY_TYPE_BOXES) && (ffg & FFG_BOX)) { Boxes_postIntersect(self, dg, ray, flags); } else if ((self->type == GEOMETRY_TYPE_SPHERES) && (ffg & FFG_SPHERES)) { Spheres_postIntersect(self, dg, ray, flags); } else if ((self->type == GEOMETRY_TYPE_PLANES) && (ffg & FFG_PLANE)) { Planes_postIntersect(self, dg, ray, flags); } else if ((self->type == GEOMETRY_TYPE_CURVES) && (ffg & FFG_CURVES)) { Curves_postIntersect(self, dg, ray, flags); #ifdef OSPRAY_ENABLE_VOLUMES } else if ((self->type == GEOMETRY_TYPE_ISOSURFACES) && (ffg & FFG_ISOSURFACE)) { Isosurfaces_postIntersect(self, dg, ray, flags, ffh); #endif #ifndef OSPRAY_TARGET_SYCL } else if ((self->type == GEOMETRY_TYPE_SUBDIVISION) && (ffg & FFG_SUBDIVISION)) { Subdivision_postIntersect(self, dg, ray, flags); } else { self->postIntersect(self, dg, ray, flags); } #else } else { } #endif } SYCL_EXTERNAL SampleAreaRes Geometry_dispatch_sampleArea( const Geometry *const uniform self, const int32 primID, const uniform affine3f &xfm, const uniform affine3f &rcp_xfm, const vec2f &s, const float time, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlagsGeometry ffg = getFeatureFlagsGeometry(ffh); if (((self->type == GEOMETRY_TYPE_QUAD_MESH) && (ffg & FFG_QUAD)) || ((self->type == GEOMETRY_TYPE_TRIANGLE_MESH) && (ffg & FFG_TRIANGLE))) { return Mesh_sampleArea(self, primID, xfm, rcp_xfm, s, time); } else if ((self->type == GEOMETRY_TYPE_SPHERES) && (ffg & FFG_SPHERE)) { return Spheres_sampleArea(self, primID, xfm, rcp_xfm, s, time); } else { #ifdef OSPRAY_TARGET_SYCL SampleAreaRes res; res.pos = make_vec3f(0.f); res.normal = make_vec3f(0.f); res.st = make_vec2f(0.f); return res; #else return self->sampleArea(self, primID, xfm, rcp_xfm, s, time); #endif } } RTC_SYCL_INDIRECTLY_CALLABLE unmasked void Geometry_dispatch_intersect( RTCIntersectFunctionNArguments *uniform args) { RayQueryContextDefault *uniform ctx = (RayQueryContextDefault * uniform) args->context; const uniform FeatureFlagsHandler &ffh = *ctx->ffh; const uniform FeatureFlagsGeometry ffg = getFeatureFlagsGeometry(ffh); Geometry *uniform geom = (Geometry * uniform) args->geometryUserPtr; if ((geom->type == GEOMETRY_TYPE_BOXES) && (ffg & FFG_BOX)) { Boxes_intersect_kernel(args, false); } else if ((geom->type == GEOMETRY_TYPE_PLANES) && (ffg & FFG_PLANE)) { Planes_intersect_kernel(args, false); #ifdef OSPRAY_ENABLE_VOLUMES } else if ((geom->type == GEOMETRY_TYPE_ISOSURFACES) && (ffg & FFG_ISOSURFACE)) { Isosurfaces_intersect_kernel(args, false, ffh); #endif } else { #ifndef OSPRAY_TARGET_SYCL geom->intersect((RTCIntersectFunctionNArguments * uniform) args, false); #endif } } RTC_SYCL_INDIRECTLY_CALLABLE unmasked void Geometry_dispatch_occluded( RTCOccludedFunctionNArguments *uniform args) { RayQueryContextDefault *uniform ctx = (RayQueryContextDefault * uniform) args->context; const uniform FeatureFlagsHandler &ffh = *ctx->ffh; const uniform FeatureFlagsGeometry ffg = getFeatureFlagsGeometry(ffh); Geometry *uniform geom = (Geometry * uniform) args->geometryUserPtr; if ((geom->type == GEOMETRY_TYPE_BOXES) && (ffg & FFG_BOX)) { Boxes_intersect_kernel( (RTCIntersectFunctionNArguments * uniform) args, true); } else if ((geom->type == GEOMETRY_TYPE_PLANES) && (ffg & FFG_PLANE)) { Planes_intersect_kernel( (RTCIntersectFunctionNArguments * uniform) args, true); #ifdef OSPRAY_ENABLE_VOLUMES } else if ((geom->type == GEOMETRY_TYPE_ISOSURFACES) && (ffg & FFG_ISOSURFACE)) { Isosurfaces_intersect_kernel( (RTCIntersectFunctionNArguments * uniform) args, true, ffh); #endif } else { #ifndef OSPRAY_TARGET_SYCL geom->intersect((RTCIntersectFunctionNArguments * uniform) args, true); #endif } } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/geometry/GeometryShared.h000066400000000000000000000067371456566705700245510ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus #if defined(__cplusplus) && !defined(OSPRAY_TARGET_SYCL) typedef void *Geometry_postIntersectFct; typedef void *Geometry_GetAreasFct; typedef void *Geometry_SampleAreaFct; typedef void *Geometry_IntersectFct; #else struct Geometry; struct DifferentialGeometry; struct Ray; // Geometries are supposed to fill certain members of DifferentialGeometry: // calculate Ng, Ns, st, color, and materialID if the respective bit DG_NG, // DG_NS, DG_TEXCOORD, DG_COLOR, and DG_MATERIALID, in flags is set. // Important with instancing: P and ray are in world-coordinates, whereas Ng // and Ns are in object-coordinates and transformed to world-space by // Instance_postIntersect. // World::postIntersect already set the hit point P, color, geometry, and // material before, and handles normalization/faceforwarding // (DG_NORMALIZE/DG_FACEFORWARD) after Geometry_postIntersectFct is called. // Thus the material pointer only needs to be set if different to // geometry->material, or the color when different to vec4f(1.0f). typedef void (*Geometry_postIntersectFct)(const Geometry *uniform self, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags); typedef void (*Geometry_GetAreasFct)(const Geometry *const uniform, const int32 *const uniform primIDs, // primitive IDs const uniform int32 numPrims, // number of primitives const uniform affine3f &xfm, // instance transformation (obj2world) float *const uniform areas // array to return area per primitive in world-space ); struct SampleAreaRes // basically a reduced DifferentialGeometry { vec3f pos; // sampled point, in world-space vec3f normal; // geometry normal Ng at the sampled point vec2f st; // texture coordinates }; // sample the given primitive uniformly wrt. area typedef SampleAreaRes (*Geometry_SampleAreaFct)(const Geometry *const uniform, const int32 primID, const uniform affine3f &xfm, // instance transformation (obj2world) const uniform affine3f &rcp_xfm, // inverse transformation (world2obj) const vec2f &s, // random numbers to generate the sample const float time // for deformation motion blur ); typedef void unmasked (*Geometry_IntersectFct)( const struct RTCIntersectFunctionNArguments *uniform args, const uniform bool isOcclusionTest); #endif enum GeometryType { GEOMETRY_TYPE_TRIANGLE_MESH, GEOMETRY_TYPE_QUAD_MESH, GEOMETRY_TYPE_BOXES, GEOMETRY_TYPE_SPHERES, GEOMETRY_TYPE_PLANES, GEOMETRY_TYPE_CURVES, #ifdef OSPRAY_ENABLE_VOLUMES GEOMETRY_TYPE_ISOSURFACES, #endif GEOMETRY_TYPE_SUBDIVISION, GEOMETRY_TYPE_UNKNOWN, }; struct Geometry { GeometryType type; // 'virtual' post-intersect function that fills in a // DifferentialGeometry struct, see above prototype for details Geometry_postIntersectFct postIntersect; Geometry_GetAreasFct getAreas; Geometry_SampleAreaFct sampleArea; // TODO: Maybe behind a define? Custom user geometry w/ fcn ptr callbacks will // only be on the CPU for now for perf limitations #ifndef OSPRAY_TARGET_SYCL Geometry_IntersectFct intersect; #endif // number of primitives this geometry has int32 numPrimitives; #ifdef __cplusplus Geometry() : type(GEOMETRY_TYPE_UNKNOWN), postIntersect(nullptr), getAreas(nullptr), sampleArea(nullptr), numPrimitives(0) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/geometry/Isosurfaces.cpp000066400000000000000000000042721456566705700244400ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES // ospray #include "Isosurfaces.h" #include "common/Data.h" // openvkl #include "openvkl/openvkl.h" // comment break to prevent clang-format from reordering openvkl includes #include "openvkl/device/openvkl.h" #ifndef OSPRAY_TARGET_SYCL // ispc-generated files #include "geometry/Isosurfaces_ispc.h" #else namespace ispc { void Isosurfaces_bounds(const RTCBoundsFunctionArguments *uniform args); } #endif namespace ospray { Isosurfaces::Isosurfaces(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFG_ISOSURFACE) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.postIntersect = ispc::Isosurfaces_postIntersect_addr(); #endif } Isosurfaces::~Isosurfaces() { if (vklHitContext) { vklRelease(vklHitContext); } } std::string Isosurfaces::toString() const { return "ospray::Isosurfaces"; } void Isosurfaces::commit() { isovaluesData = getParamDataT("isovalue", true, true); volume = getParamObject("volume"); if (!volume) throw std::runtime_error(toString() + "must have 'volume'"); if (!isovaluesData->compact()) { // get rid of stride auto data = new Data( getISPCDevice(), OSP_FLOAT, vec3ui(isovaluesData->size(), 1, 1)); data->copy(*isovaluesData, vec3ui(0)); isovaluesData = &(data->as()); data->refDec(); } if (vklHitContext) { vklRelease(vklHitContext); } vklHitContext = vklNewHitIteratorContext(volume->vklSampler); if (isovaluesData->size() > 0) { VKLData valuesData = vklNewData(getISPCDevice().getVklDevice(), isovaluesData->size(), VKL_FLOAT, isovaluesData->data()); vklSetData(vklHitContext, "values", valuesData); vklRelease(valuesData); } vklCommit(vklHitContext); createEmbreeUserGeometry((RTCBoundsFunction)&ispc::Isosurfaces_bounds); getSh()->isovalues = isovaluesData->data(); getSh()->volume = volume->getSh(); getSh()->super.numPrimitives = numPrimitives(); getSh()->vklHitContext = vklHitContext; postCreationInfo(); } size_t Isosurfaces::numPrimitives() const { return isovaluesData->size(); } } // namespace ospray #endif RenderKit-ospray-f2a61c2/modules/cpu/geometry/Isosurfaces.h000066400000000000000000000017061456566705700241040ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/FeatureFlagsEnum.h" #ifdef OSPRAY_ENABLE_VOLUMES #pragma once #include "Geometry.h" #include "volume/Volume.h" // ispc shared #include "IsosurfacesShared.h" namespace ospray { struct OSPRAY_SDK_INTERFACE Isosurfaces : public AddStructShared { Isosurfaces(api::ISPCDevice &device); virtual ~Isosurfaces() override; virtual std::string toString() const override; virtual void commit() override; virtual size_t numPrimitives() const override; FeatureFlags getFeatureFlags() const override; protected: Ref> isovaluesData; Ref volume; VKLHitIteratorContext vklHitContext = VKLHitIteratorContext(); }; inline FeatureFlags Isosurfaces::getFeatureFlags() const { FeatureFlags ff = Geometry::getFeatureFlags(); ff |= volume->getFeatureFlags(); return ff; } } // namespace ospray #endif RenderKit-ospray-f2a61c2/modules/cpu/geometry/Isosurfaces.ih000066400000000000000000000013661456566705700242570ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #include "common/FeatureFlags.ih" #include "geometry/Geometry.ih" OSPRAY_BEGIN_ISPC_NAMESPACE #ifdef OSPRAY_TARGET_SYCL void Isosurfaces_bounds(const RTCBoundsFunctionArguments *uniform args); #endif SYCL_EXTERNAL void Isosurfaces_postIntersect(const Geometry *uniform geometry, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL void unmasked Isosurfaces_intersect_kernel( const RTCIntersectFunctionNArguments *uniform args, const uniform bool isOcclusionTest, const uniform FeatureFlagsHandler &ffh); OSPRAY_END_ISPC_NAMESPACE #endif RenderKit-ospray-f2a61c2/modules/cpu/geometry/Isosurfaces.ispc000066400000000000000000000073111456566705700246110ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/FeatureFlagsEnum.h" #ifdef OSPRAY_ENABLE_VOLUMES // ospray #include "common/FilterIntersect.ih" #include "common/Ray.ih" #include "common/World.ih" #include "geometry/Geometry.ih" #include "rkcommon/math/box.ih" #include "rkcommon/math/vec.ih" #include "volume/Volume.ih" // c++ shared #include "IsosurfacesShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE int Isosurfaces_primID(const Isosurfaces *uniform self, const float isovalue) { for (uniform int i = 0; i < self->super.numPrimitives; ++i) { if (isovalue == self->isovalues[i]) { return i; } } return -1; } export void Isosurfaces_bounds(const RTCBoundsFunctionArguments *uniform args) { uniform Isosurfaces *uniform self = (uniform Isosurfaces * uniform) args->geometryUserPtr; box3fa *uniform out = (box3fa * uniform) args->bounds_o; *out = make_box3fa(self->volume->boundingBox); } SYCL_EXTERNAL void Isosurfaces_postIntersect(const Geometry *uniform geometry, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags, const uniform FeatureFlagsHandler &ffh) { Isosurfaces *uniform self = (Isosurfaces * uniform) geometry; if (flags & (DG_NS | DG_NG)) dg.Ng = dg.Ns = Volume_getGradient(self->volume, ray.Ng /* actually local hit */, ffh); // convert ray-space epsilon (in ray.u) to object-/world-space using max(dir) // instead of costly length; the error is at most sqrt(3)~1.7, quite // acceptable for eps dg.epsilon = reduce_max(abs(ray.dir)) * ray.u; } SYCL_EXTERNAL void unmasked Isosurfaces_intersect_kernel( const RTCIntersectFunctionNArguments *uniform args, const uniform bool isOcclusionTest, const uniform FeatureFlagsHandler &ffh) { // make sure to set the mask if (!args->valid[programIndex]) { return; } const uniform FeatureFlags ff = getFeatureFlags(ffh); args->valid[programIndex] = 0; Isosurfaces *uniform self = (Isosurfaces * uniform) args->geometryUserPtr; // this assumes that the args->rayhit is actually a pointer to a varying ray! varying Ray *uniform ray = (varying Ray * uniform) args->rayhit; VKLHitIterator iterator; vkl_range1f tRange; tRange.lower = ray->t0; tRange.upper = ray->t; float time = 0.f; // do not use alloca: it prevents inlining and thus optimization // wrt. "template arg" isOcclusionTest, alloca also not supported on GPU uniform uint8 hitIteratorBuffer[VKL_MAX_HIT_ITERATOR_SIZE]; iterator = vklInitHitIteratorV(&self->vklHitContext, (varying vkl_vec3f *)&ray->org, (varying vkl_vec3f *)&ray->dir, &tRange, #ifndef OSPRAY_TARGET_SYCL & #endif time, hitIteratorBuffer #ifdef OSPRAY_TARGET_SYCL , ff.volume #endif ); VKLHit hit; bool gotHit = vklIterateHitV(iterator, &hit #ifdef OSPRAY_TARGET_SYCL , ff.volume #endif ); if (!gotHit) return; Hit hitFilter; hitFilter.hit = true; hitFilter.t = hit.t; // Transport hit point in *volume local coords* to postIntersect hitFilter.N = ray->org + ray->dir * hit.t; // Transport epsilon to postIntersect hitFilter.u = hit.epsilon; bool accept = filterIntersectionSingle(args, hitFilter, isOcclusionTest, false); if (!accept) return; args->valid[programIndex] = -1; if (isOcclusionTest) { ray->t = neg_inf; } else { ray->instID = args->context->instID[0]; ray->geomID = args->geomID; ray->primID = Isosurfaces_primID(self, hit.sample); ray->t = hitFilter.t; ray->u = hitFilter.u; ray->Ng = hitFilter.N; } } export void *uniform Isosurfaces_postIntersect_addr() { return (void *uniform)Isosurfaces_postIntersect; } OSPRAY_END_ISPC_NAMESPACE #endif RenderKit-ospray-f2a61c2/modules/cpu/geometry/IsosurfacesShared.h000066400000000000000000000011371456566705700252310ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #pragma once #include "GeometryShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Isosurfaces { Geometry super; // inherited geometry fields float *isovalues; Volume *volume; VKLHitIteratorContext vklHitContext; #ifdef __cplusplus Isosurfaces() : isovalues(nullptr), volume(nullptr), vklHitContext(VKLHitIteratorContext()) { super.type = ispc::GEOMETRY_TYPE_ISOSURFACES; } }; } // namespace ispc #else }; #endif // __cplusplus #endif RenderKit-ospray-f2a61c2/modules/cpu/geometry/Mesh.cpp000066400000000000000000000163011456566705700230420ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Mesh.h" #include "common/DGEnum.h" #ifndef OSPRAY_TARGET_SYCL // ispc exports #include "geometry/Mesh_ispc.h" #else namespace ispc { void *QuadMesh_postIntersect_addr(); void *TriangleMesh_postIntersect_addr(); void *Mesh_sampleArea_addr(); void *Mesh_getAreas_addr(); } // namespace ispc #endif // std #include namespace ospray { Mesh::Mesh(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFG_NONE), device(device) { getSh()->super.getAreas = reinterpret_cast(ispc::Mesh_getAreas_addr()); getSh()->super.sampleArea = reinterpret_cast( ispc::Mesh_sampleArea_addr()); } std::string Mesh::toString() const { return "ospray::Mesh"; } void Mesh::commit() { bool isNormalFaceVarying = true; motionVertexData = getParamDataT *>("motion.vertex.position"); if (motionVertexData) { const auto mKeys = motionVertexData->size(); motionBlur = mKeys > 1; if (!motionVertexAddr || motionVertexAddr->size() < mKeys) // reallocate? motionVertexAddr = make_buffer_shared_unique(device.getIspcrtContext(), mKeys); auto mVAddr = motionVertexAddr->begin(); // check types and strides vertexData = (*motionVertexData)[0]; // use 1st key as fallback const int64_t stride = vertexData->ispc.byteStride; const size_t size = vertexData->ispc.numItems; for (size_t i = 0; i < mKeys; i++) { auto &&vtxData = (*motionVertexData)[i]; if (vtxData->type != OSP_VEC3F || vtxData->ispc.numItems != size || vtxData->ispc.byteStride != stride) throw std::runtime_error( "Mesh 'motion.vertex.position' arrays need to be" " of same size and stride and have type vec3f"); mVAddr[i] = vtxData->data(); } motionNormalData = getParamDataT *>("motion.normal"); if (!motionNormalData) { motionNormalData = getParamDataT *>("motion.vertex.normal"); isNormalFaceVarying = false; } if (motionNormalData) { if (motionNormalData->size() < mKeys) throw std::runtime_error( "Mesh 'motion*.normal' array has less keys than" " 'motion.vertex.position'"); if (!motionNormalAddr || motionNormalAddr->size() < mKeys) // reallocate? motionNormalAddr = make_buffer_shared_unique( device.getIspcrtContext(), mKeys); auto mNAddr = motionNormalAddr->begin(); // check types and strides normalData = (*motionNormalData)[0]; // use 1st key as fallback const int64_t stride = normalData->ispc.byteStride; for (size_t i = 0; i < mKeys; i++) { auto &&norData = (*motionNormalData)[i]; if (norData->type != OSP_VEC3F || norData->ispc.numItems != size || norData->ispc.byteStride != stride) throw std::runtime_error( "Mesh 'motion*.normal' arrays need to be" " of same size and stride and have type vec3f"); mNAddr[i] = norData->data(); } } else normalData = nullptr; } else { motionBlur = false; vertexData = getParamDataT("vertex.position", true); normalData = getParamDataT("normal"); if (!normalData) { normalData = getParamDataT("vertex.normal"); isNormalFaceVarying = false; } } colorData = getParamObject("color"); bool isColorFaceVarying = true; if (!colorData) { colorData = getParamObject("vertex.color"); isColorFaceVarying = false; } bool isTexcoordFaceVarying = true; texcoordData = getParamDataT("texcoord"); if (!texcoordData) { texcoordData = getParamDataT("vertex.texcoord"); isTexcoordFaceVarying = false; } // get optional vec3i index, if successful, it's a triangle indexData = getParamDataT("index"); // optionally get vec4i index, if successful, it's a quad if (!indexData) indexData = getParamDataT("index"); // If no index data given, make tri or quad soup based on input parameter // Index order is 0,1,2,3,... if (!indexData) { const bool quadSoup = getParam("quadSoup", false); const int elements = quadSoup ? 4 : 3; indexData = new Data(getISPCDevice(), quadSoup ? OSP_VEC4UI : OSP_VEC3UI, vec3l(vertexData->size() / elements, 1, 1)); indexData->refDec(); auto begin = (unsigned int *)indexData->data(); std::iota(begin, begin + indexData->size() * elements, 0); } const bool isTri = indexData->type == OSP_VEC3UI; getSh()->super.type = isTri ? ispc::GEOMETRY_TYPE_TRIANGLE_MESH : ispc::GEOMETRY_TYPE_QUAD_MESH; createEmbreeGeometry( isTri ? RTC_GEOMETRY_TYPE_TRIANGLE : RTC_GEOMETRY_TYPE_QUAD); time = range1f(0.0f, 1.0f); if (motionBlur) { time = getParam("time", range1f(0.0f, 1.0f)); if (time.upper < time.lower) time.upper = time.lower; rtcSetGeometryTimeStepCount(embreeGeometry, motionVertexData->size()); size_t i = 0; for (auto &&vtx : *motionVertexData) setEmbreeGeometryBuffer(embreeGeometry, RTC_BUFFER_TYPE_VERTEX, vtx, i++); rtcSetGeometryTimeRange(embreeGeometry, time.lower, time.upper); } else { rtcSetGeometryTimeStepCount(embreeGeometry, 1); setEmbreeGeometryBuffer(embreeGeometry, RTC_BUFFER_TYPE_VERTEX, vertexData); } rtcSetSharedGeometryBuffer(embreeGeometry, RTC_BUFFER_TYPE_INDEX, 0, isTri ? RTC_FORMAT_UINT3 : RTC_FORMAT_UINT4, indexData->data(), 0, isTri ? sizeof(vec3ui) : sizeof(vec4ui), indexData->size()); rtcCommitGeometry(embreeGeometry); getSh()->isColorFaceVarying = isColorFaceVarying; getSh()->isTexcoordFaceVarying = isTexcoordFaceVarying; getSh()->isNormalFaceVarying = isNormalFaceVarying; getSh()->index = *ispc(indexData); getSh()->vertex = *ispc(vertexData); getSh()->normal = *ispc(normalData); getSh()->color = *ispc(colorData); getSh()->texcoord = *ispc(texcoordData); getSh()->motionVertex = motionVertexAddr ? (uint8_t **)motionVertexAddr->data() : nullptr; getSh()->motionNormal = motionNormalAddr ? (uint8_t **)motionNormalAddr->data() : nullptr; getSh()->motionKeys = motionBlur ? motionVertexData->size() : 0; getSh()->time = time; getSh()->has_alpha = colorData && colorData->type == OSP_VEC4F; getSh()->is_triangleMesh = isTri; getSh()->super.numPrimitives = numPrimitives(); getSh()->super.postIntersect = isTri ? reinterpret_cast( ispc::TriangleMesh_postIntersect_addr()) : reinterpret_cast( ispc::QuadMesh_postIntersect_addr()); getSh()->flagMask = -1; if (!normalData) getSh()->flagMask &= ispc::int64(~DG_NS); if (!colorData) getSh()->flagMask &= ispc::int64(~DG_COLOR); if (!texcoordData) getSh()->flagMask &= ispc::int64(~DG_TEXCOORD); postCreationInfo(vertexData->size()); featureFlagsGeometry = isTri ? FFG_TRIANGLE : FFG_QUAD; if (motionBlur) featureFlagsGeometry |= FFG_MOTION_BLUR; } size_t Mesh::numPrimitives() const { return indexData->size(); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/Mesh.h000066400000000000000000000017671456566705700225210ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Geometry.h" #include "common/Data.h" // ispc shared #include "MeshShared.h" namespace ospray { struct OSPRAY_SDK_INTERFACE Mesh : public AddStructShared { Mesh(api::ISPCDevice &device); virtual ~Mesh() override = default; virtual std::string toString() const override; virtual void commit() override; virtual size_t numPrimitives() const override; protected: Ref> vertexData; Ref> normalData; Ref colorData; Ref> texcoordData; Ref indexData; bool motionBlur{false}; Ref *>> motionVertexData; std::unique_ptr> motionVertexAddr; Ref *>> motionNormalData; std::unique_ptr> motionNormalAddr; range1f time{0.0f, 1.0f}; api::ISPCDevice &device; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/Mesh.ih000066400000000000000000000013101456566705700226520ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "geometry/Geometry.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL void QuadMesh_postIntersect(const Geometry *uniform _self, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags); SYCL_EXTERNAL void TriangleMesh_postIntersect(const Geometry *uniform _self, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags); SYCL_EXTERNAL SampleAreaRes Mesh_sampleArea(const Geometry *uniform const _self, const int32 primID, const uniform affine3f &xfm, const uniform affine3f &, const vec2f &s, const float time); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/geometry/Mesh.ispc000066400000000000000000000342531456566705700232240ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Mesh.ih" #include "common/Data.ih" #include "math/sampling.ih" #include "rkcommon/math/LinearSpace.ih" // c++ shared #include "MeshShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE #ifdef OSPRAY_TARGET_SYCL using namespace ospray; #endif // Create quad_interpolate for vec2f, vec3f, and vec4f types #define __define_quad_interpolate(T) \ static inline T quad_interpolate( \ const vec4f &uv, const T &t0, const T &t1, const T &t2, const T &t3) \ { \ return uv.x * t0 + uv.y * t1 + uv.z * t2 + uv.w * t3; \ } __define_quad_interpolate(vec2f); __define_quad_interpolate(vec3f); __define_quad_interpolate(vec4f); inline float Mesh_calcKey(const Mesh *uniform self, float time, int &idx) { // should only get hits within time interval, just to be sure... float t = clamp(time, self->time.lower, self->time.upper); t = (t - self->time.lower) * rcp(box_size(self->time)) * (self->motionKeys - 1); idx = clamp((int)t, (int)0, (int)(self->motionKeys - 2)); t = clamp(t - idx); return t; } inline vec3f interpolate_vec3f(const uniform int64 byteStride, const uint8 *a0, const uint8 *a1, const int index, const float t) { vec3f v0, v1; int64 offs = byteStride * index; v0 = *((const vec3f *)(a0 + offs)); v1 = *((const vec3f *)(a1 + offs)); return lerp(t, v0, v1); } SYCL_EXTERNAL void QuadMesh_postIntersect(const Geometry *uniform _self, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags) { Mesh *uniform self = (Mesh * uniform) _self; dg.Ng = dg.Ns = ray.Ng; const vec4ui index = get_vec4ui(self->index, ray.primID); const int iOffset = ray.primID * 4; const vec4ui findex = make_vec4ui( iOffset, iOffset + 1, iOffset + 2, iOffset + 3); // face indices const float u = ray.u; const float v = ray.v; vec4f uv; #define QUAD_BILINEAR #ifdef QUAD_BILINEAR if (index.z == index.w) uv = make_vec4f(1.f - u - v, u, v, 0.f); else uv = make_vec4f((1 - v) * (1 - u), (1 - v) * u, v * u, v * (1 - u)); #else // always as triangles if (u + v < 1.0f) uv = make_vec4f(1.f - u - v, u, 0.f, v); else uv = make_vec4f(0.f, 1.f - v, u + v - 1.f, 1.f - u); #endif flags &= self->flagMask; if (flags & DG_NS) { const vec4ui tindex = self->isNormalFaceVarying ? findex : index; if (self->motionKeys) { int idx; const float t = Mesh_calcKey(self, ray.time, idx); const uniform int64 byteStride = self->normal.byteStride; const uint8 *a0 = self->motionNormal[idx]; const uint8 *a1 = self->motionNormal[idx + 1]; const vec3f a = interpolate_vec3f(byteStride, a0, a1, tindex.x, t); const vec3f b = interpolate_vec3f(byteStride, a0, a1, tindex.y, t); const vec3f c = interpolate_vec3f(byteStride, a0, a1, tindex.z, t); const vec3f d = interpolate_vec3f(byteStride, a0, a1, tindex.w, t); dg.Ns = quad_interpolate(uv, a, b, c, d); } else { const vec3f a = get_vec3f(self->normal, tindex.x); const vec3f b = get_vec3f(self->normal, tindex.y); const vec3f c = get_vec3f(self->normal, tindex.z); const vec3f d = get_vec3f(self->normal, tindex.w); dg.Ns = quad_interpolate(uv, a, b, c, d); } } if (flags & DG_COLOR) { const vec4ui tindex = self->isColorFaceVarying ? findex : index; const vec4f a = get_vec4f(self->color, tindex.x); const vec4f b = get_vec4f(self->color, tindex.y); const vec4f c = get_vec4f(self->color, tindex.z); const vec4f d = get_vec4f(self->color, tindex.w); dg.color = quad_interpolate(uv, a, b, c, d); if (!self->has_alpha) dg.color.w = 1.f; } vec3f va, vb, vc, vd; if (self->motionKeys) { int idx; const float t = Mesh_calcKey(self, ray.time, idx); const uniform int64 byteStride = self->vertex.byteStride; const uint8 *a0 = self->motionVertex[idx]; const uint8 *a1 = self->motionVertex[idx + 1]; va = interpolate_vec3f(byteStride, a0, a1, index.x, t); vb = interpolate_vec3f(byteStride, a0, a1, index.y, t); vc = interpolate_vec3f(byteStride, a0, a1, index.z, t); vd = interpolate_vec3f(byteStride, a0, a1, index.w, t); } else { va = get_vec3f(self->vertex, index.x); vb = get_vec3f(self->vertex, index.y); vc = get_vec3f(self->vertex, index.z); vd = get_vec3f(self->vertex, index.w); } dg.epsilon = reduce_max(max(max(va, vb), max(vc, vd))) * ulpEpsilon; const uniform bool compute_texcoord = flags & DG_TEXCOORD; bool compute_tangents = flags & DG_TANGENTS; if ((compute_texcoord || compute_tangents) && valid(self->texcoord)) { const vec4ui tindex = self->isTexcoordFaceVarying ? findex : index; const vec2f a = get_vec2f(self->texcoord, tindex.x); const vec2f b = get_vec2f(self->texcoord, tindex.y); const vec2f d = get_vec2f(self->texcoord, tindex.w); if (compute_texcoord) { const vec2f c = get_vec2f(self->texcoord, tindex.z); dg.st = quad_interpolate(uv, a, b, c, d); } if (compute_tangents) { const vec2f dst02 = a - d; const vec2f dst12 = b - d; const float det = dst02.x * dst12.y - dst02.y * dst12.x; if (det != 0.f) { const float invDet = rcp(det); const vec3f dp02 = va - vd; const vec3f dp12 = vb - vd; dg.dPds = (dst12.y * dp02 - dst02.y * dp12) * invDet; dg.dPdt = (dst02.x * dp12 - dst12.x * dp02) * invDet; compute_tangents = false; } } } if (compute_tangents) { dg.dPds = vb - va; dg.dPdt = vd - va; } } SYCL_EXTERNAL void TriangleMesh_postIntersect(const Geometry *uniform _self, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags) { Mesh *uniform self = (Mesh * uniform) _self; dg.Ng = dg.Ns = ray.Ng; const vec3ui index = get_vec3ui(self->index, ray.primID); const int iOffset = ray.primID * 3; const vec3ui findex = make_vec3ui(iOffset, iOffset + 1, iOffset + 2); // face indices const vec3f uv = make_vec3f(1.0f - ray.u - ray.v, ray.u, ray.v); flags &= self->flagMask; if (flags & DG_NS) { const vec3ui tindex = self->isNormalFaceVarying ? findex : index; if (self->motionKeys) { int idx; const float t = Mesh_calcKey(self, ray.time, idx); const uniform int64 byteStride = self->normal.byteStride; const uint8 *a0 = self->motionNormal[idx]; const uint8 *a1 = self->motionNormal[idx + 1]; const vec3f a = interpolate_vec3f(byteStride, a0, a1, tindex.x, t); const vec3f b = interpolate_vec3f(byteStride, a0, a1, tindex.y, t); const vec3f c = interpolate_vec3f(byteStride, a0, a1, tindex.z, t); dg.Ns = interpolate(uv, a, b, c); } else { const vec3f a = get_vec3f(self->normal, tindex.x); const vec3f b = get_vec3f(self->normal, tindex.y); const vec3f c = get_vec3f(self->normal, tindex.z); dg.Ns = interpolate(uv, a, b, c); } } if (flags & DG_COLOR) { const vec3ui tindex = self->isColorFaceVarying ? findex : index; const vec4f a = get_vec4f(self->color, tindex.x); const vec4f b = get_vec4f(self->color, tindex.y); const vec4f c = get_vec4f(self->color, tindex.z); dg.color = interpolate(uv, a, b, c); if (!self->has_alpha) dg.color.w = 1.f; } vec3f va, vb, vc; if (self->motionKeys) { int idx; const float t = Mesh_calcKey(self, ray.time, idx); const uniform int64 byteStride = self->vertex.byteStride; const uint8 *a0 = self->motionVertex[idx]; const uint8 *a1 = self->motionVertex[idx + 1]; va = interpolate_vec3f(byteStride, a0, a1, index.x, t); vb = interpolate_vec3f(byteStride, a0, a1, index.y, t); vc = interpolate_vec3f(byteStride, a0, a1, index.z, t); } else { va = get_vec3f(self->vertex, index.x); vb = get_vec3f(self->vertex, index.y); vc = get_vec3f(self->vertex, index.z); } dg.epsilon = reduce_max(max(max(va, vb), vc)) * ulpEpsilon; const uniform bool compute_texcoord = flags & DG_TEXCOORD; bool compute_tangents = flags & DG_TANGENTS; if ((compute_texcoord || compute_tangents) && valid(self->texcoord)) { const vec3ui tindex = self->isTexcoordFaceVarying ? findex : index; const vec2f a = get_vec2f(self->texcoord, tindex.x); const vec2f b = get_vec2f(self->texcoord, tindex.y); const vec2f c = get_vec2f(self->texcoord, tindex.z); if (compute_texcoord) dg.st = interpolate(uv, a, b, c); if (compute_tangents) { const vec2f dst02 = a - c; const vec2f dst12 = b - c; const float det = dst02.x * dst12.y - dst02.y * dst12.x; if (det != 0.f) { const float invDet = rcp(det); const vec3f dp02 = va - vc; const vec3f dp12 = vb - vc; dg.dPds = (dst12.y * dp02 - dst02.y * dp12) * invDet; dg.dPdt = (dst02.x * dp12 - dst12.x * dp02) * invDet; compute_tangents = false; } } } if (compute_tangents) { dg.dPds = vb - va; dg.dPdt = vc - va; } } SYCL_EXTERNAL SampleAreaRes Mesh_sampleArea(const Geometry *uniform const _self, const int32 primID, const uniform affine3f &xfm, const uniform affine3f &, const vec2f &s, const float time) { const Mesh *const uniform self = (const Mesh *uniform)_self; SampleAreaRes res; vec4ui index4; bool quad = false; if (self->is_triangleMesh) { const vec3ui index3 = get_vec3ui(self->index, primID); index4 = make_vec4ui(index3.x, index3.y, index3.z, index3.z); } else { index4 = get_vec4ui(self->index, primID); quad = index4.z != index4.w; } const vec4ui index = index4; vec3f a, b, c, d; if (self->motionKeys) { int idx; const float t = Mesh_calcKey(self, time, idx); const uniform int64 byteStride = self->vertex.byteStride; const uint8 *a0 = self->motionVertex[idx]; const uint8 *a1 = self->motionVertex[idx + 1]; a = interpolate_vec3f(byteStride, a0, a1, index.x, t); b = interpolate_vec3f(byteStride, a0, a1, index.y, t); d = interpolate_vec3f(byteStride, a0, a1, index.w, t); if (quad) c = interpolate_vec3f(byteStride, a0, a1, index.z, t); } else { a = get_vec3f(self->vertex, index.x); b = get_vec3f(self->vertex, index.y); d = get_vec3f(self->vertex, index.w); if (quad) c = get_vec3f(self->vertex, index.z); } const vec3f e1 = xfmVector(xfm, a - d); const vec3f e2 = xfmVector(xfm, b - d); const vec3f m1 = cross(e1, e2); res.normal = m1; vec3f v0 = a; vec3f v1 = b; vec3f v2 = d; vec2f sp = s; bool invertUV = false; if (quad) { // painfully slow: re-calculate areas to decide which triangle to sample const vec3f e3 = xfmVector(xfm, c - d); const vec3f m2 = cross(e2, e3); const float a1 = length(m1); const float a2 = length(m2); const float p1 = a1 * rcp(a1 + a2); if (s.x < p1) { sp.x *= rcp(p1); // reproject } else { // sample second tri sp.x = (s.x - p1) * rcp(1.f - p1); // reproject // same split and parametrization as Embree invertUV = true; v0 = c; v1 = d; v2 = b; res.normal = m2; } } const vec2f uv = uniformSampleTriangleUV(sp); const vec3f localPos = v0 + uv.x * (v1 - v0) + uv.y * (v2 - v0); res.normal = normalize(res.normal); res.pos = xfmPoint(xfm, localPos); res.st = invertUV ? 1.0f - uv : uv; if (valid(self->texcoord)) { const float u = res.st.x; const float v = res.st.y; vec4f uv4; #ifdef QUAD_BILINEAR if (quad) uv4 = make_vec4f((1 - v) * (1 - u), (1 - v) * u, v * u, v * (1 - u)); else uv4 = make_vec4f(1.f - u - v, u, v, 0.f); #else // always as triangles if (invertUV) uv4 = make_vec4f(0.f, 1.f - v, u + v - 1.f, 1.f - u); else uv4 = make_vec4f(1.f - u - v, u, 0.f, v); #endif const int iOffs = primID * (self->is_triangleMesh ? 3 : 4); const vec4ui findex = make_vec4ui(iOffs, iOffs + 1, iOffs + 2, iOffs + 3); const vec4ui tindex = self->isTexcoordFaceVarying ? findex : index; const vec2f a = get_vec2f(self->texcoord, tindex.x); const vec2f b = get_vec2f(self->texcoord, tindex.y); const vec2f c = get_vec2f(self->texcoord, tindex.z); if (self->is_triangleMesh) { res.st = interpolate(make_vec3f(uv4), a, b, c); } else { const vec2f d = get_vec2f(self->texcoord, tindex.w); res.st = quad_interpolate(uv4, a, b, c, d); } } return res; } void Mesh_getAreas(const Geometry *const uniform _self, const int32 *const uniform primIDs, const uniform int32 numPrims, const uniform affine3f &xfm, float *const uniform areas) { const Mesh *const uniform self = (const Mesh *uniform)_self; // TODO vectorize this loop, with for each or ProgramCount & ProgramIndex // XXX for deformation motion blur the areas (i.e. selection probabilities) // are calculated using the first key only uniform vec4ui index; for (uniform int32 i = 0; i < numPrims; i++) { uniform bool quad = false; if (self->is_triangleMesh) { const uniform vec3ui index3 = get_vec3ui(self->index, primIDs[i]); index = make_vec4ui(index3.x, index3.y, index3.z, index3.z); } else { index = get_vec4ui(self->index, primIDs[i]); quad = index.z != index.w; } const uniform vec3f a = get_vec3f(self->vertex, index.x); const uniform vec3f b = get_vec3f(self->vertex, index.y); // use same splitting diagonal as Embree const uniform vec3f d = get_vec3f(self->vertex, index.w); const uniform vec3f e1 = xfmVector(xfm, a - d); const uniform vec3f e2 = xfmVector(xfm, b - d); areas[i] = length(cross(e1, e2)); if (quad) { const uniform vec3f c = get_vec3f(self->vertex, index.z); const uniform vec3f e3 = xfmVector(xfm, c - d); areas[i] += length(cross(e2, e3)); } areas[i] *= 0.5f; } } export void *uniform QuadMesh_postIntersect_addr() { return (void *uniform)QuadMesh_postIntersect; } export void *uniform TriangleMesh_postIntersect_addr() { return (void *uniform)TriangleMesh_postIntersect; } export void *uniform Mesh_sampleArea_addr() { return (void *uniform)Mesh_sampleArea; } export void *uniform Mesh_getAreas_addr() { return (void *uniform)Mesh_getAreas; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/geometry/MeshShared.h000066400000000000000000000017471456566705700236460ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "GeometryShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Mesh { Geometry super; Data1D index; Data1D vertex; Data1D normal; Data1D color; Data1D texcoord; uint8 **motionVertex; uint8 **motionNormal; uint32 motionKeys; box1f time; int64 flagMask; // which attributes are missing and cannot be interpolated bool has_alpha; // 4th color component is valid bool is_triangleMesh; bool isColorFaceVarying; bool isTexcoordFaceVarying; bool isNormalFaceVarying; #ifdef __cplusplus Mesh() : motionVertex(nullptr), motionNormal(nullptr), motionKeys(0), time(0.f, 1.f), flagMask(-1), has_alpha(false), is_triangleMesh(false), isColorFaceVarying(false), isTexcoordFaceVarying(false), isNormalFaceVarying(false) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/geometry/Planes.cpp000066400000000000000000000022051456566705700233660ustar00rootroot00000000000000// Copyright 2019 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Planes.h" #include "common/Data.h" #ifndef OSPRAY_TARGET_SYCL // ispc-generated files #include "geometry/Planes_ispc.h" #else namespace ispc { void Planes_bounds(const RTCBoundsFunctionArguments *args); } #endif namespace ospray { Planes::Planes(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFG_PLANE) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.postIntersect = reinterpret_cast( ispc::Planes_postIntersect_addr()); #endif } std::string Planes::toString() const { return "ospray::Planes"; } void Planes::commit() { coeffsData = getParamDataT("plane.coefficients", true); boundsData = getParamDataT("plane.bounds"); createEmbreeUserGeometry((RTCBoundsFunction)&ispc::Planes_bounds); getSh()->coeffs = *ispc(coeffsData); getSh()->bounds = *ispc(boundsData); getSh()->super.numPrimitives = numPrimitives(); postCreationInfo(); } size_t Planes::numPrimitives() const { return coeffsData ? coeffsData->size() : 0; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/Planes.h000066400000000000000000000011151456566705700230320ustar00rootroot00000000000000// Copyright 2019 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Geometry.h" // ispc shared #include "PlanesShared.h" namespace ospray { struct OSPRAY_SDK_INTERFACE Planes : public AddStructShared { Planes(api::ISPCDevice &device); virtual ~Planes() override = default; virtual std::string toString() const override; virtual void commit() override; virtual size_t numPrimitives() const override; protected: Ref> coeffsData; Ref> boundsData; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/Planes.ih000066400000000000000000000010761456566705700232110ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "geometry/Geometry.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // Only used on the host void Planes_bounds(const RTCBoundsFunctionArguments *uniform args); SYCL_EXTERNAL void Planes_postIntersect(const Geometry *uniform _self, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags); SYCL_EXTERNAL unmasked void Planes_intersect_kernel( const RTCIntersectFunctionNArguments *uniform args, const uniform bool isOcclusionTest); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/geometry/Planes.ispc000066400000000000000000000104311456566705700235420ustar00rootroot00000000000000// Copyright 2019 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "common/Data.ih" #include "common/DifferentialGeometry.ih" #include "common/FilterIntersect.ih" #include "common/Intersect.ih" #include "common/Ray.ih" #include "geometry/Geometry.ih" #include "rkcommon/math/box.ih" #include "rkcommon/math/vec.ih" // c++ shared #include "PlanesShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE // The plane can't be truly infinite because Embree has a limit on object size #define PLANE_MAX_SIZE 1e18f #define DUMMY_MAX_T 1e38f export void Planes_bounds(const RTCBoundsFunctionArguments *uniform args) { const uniform vec3f lo = make_vec3f(-PLANE_MAX_SIZE, -PLANE_MAX_SIZE, -PLANE_MAX_SIZE); const uniform vec3f hi = make_vec3f(PLANE_MAX_SIZE, PLANE_MAX_SIZE, PLANE_MAX_SIZE); // use maximum size planes if bounding boxes not provided Planes *uniform self = (Planes * uniform) args->geometryUserPtr; box3fa *uniform out = (box3fa * uniform) args->bounds_o; if (valid(self->bounds)) { uniform int primID = args->primID; uniform box3f bbox = get_box3f(self->bounds, primID); *out = make_box3fa(max(bbox.lower, lo), min(bbox.upper, hi)); } else { *out = make_box3fa(lo, hi); } } SYCL_EXTERNAL unmasked void Planes_intersect_kernel( const RTCIntersectFunctionNArguments *uniform args, const uniform bool isOcclusionTest) { // make sure to set the mask if (!args->valid[programIndex]) return; args->valid[programIndex] = 0; // get geometry pointers Planes *uniform self = (Planes * uniform) args->geometryUserPtr; uniform unsigned int primID = args->primID; // this assumes that the args->rayhit is actually a pointer to a varying // ray! varying Ray *uniform ray = (varying Ray * uniform) args->rayhit; // intersect plane with ray uniform vec4f coeffs = get_vec4f(self->coeffs, primID); const Hit hit = intersectPlane(ray->org, ray->dir, coeffs); // do bounding box check if defined if (valid(self->bounds)) { uniform box3f bbox = get_box3f(self->bounds, primID); const Intersections isect = intersectBox(ray->org, ray->dir, bbox); // discard the intersection if our ray misses bbox completely or // the intersection is not within bbox extents, // assumes that (isect.entry.hit == isect.exit.hit) if (!isect.entry.hit || (hit.t < isect.entry.t) || (hit.t > isect.exit.t)) return; } // we are done if first intersection accepted if (filterIntersectionSingle(args, hit, isOcclusionTest, false)) { args->valid[programIndex] = -1; return; } // handle plane parallel to ray, which breaks interval logic for clipping if (!hit.hit) { const uniform vec3f normal = make_vec3f(coeffs); if (coeffs.w > dot(ray->org, normal)) { // within clipping half-space? Hit hitExitDummy; hitExitDummy.hit = true; hitExitDummy.t = DUMMY_MAX_T; hitExitDummy.N = ray->dir; filterIntersectionSingle(args, hitExitDummy, isOcclusionTest, true); } return; } // The second implicit plane is needed just for infinite planes if (valid(self->bounds)) return; // clipping algorithm works on closed surfaces only, // so for infinite planes an implicit second plane is tested here, // it is positioned at the edge of bounding box and its // normal is oriented in opposite direction to mimic a closed surface const uniform vec4f coeffsImplicit = make_vec4f(-coeffs.x, -coeffs.y, -coeffs.z, PLANE_MAX_SIZE); const Hit hitImplicit = intersectPlane(ray->org, ray->dir, coeffsImplicit); // we don't want the second plane to be drawn so this intersection is never // accepted filterIntersectionSingle(args, hitImplicit, isOcclusionTest, true); } export void Planes_intersect( const struct RTCIntersectFunctionNArguments *uniform args) { Planes_intersect_kernel(args, false); } export void Planes_occluded( const struct RTCOccludedFunctionNArguments *uniform args) { Planes_intersect_kernel( (RTCIntersectFunctionNArguments * uniform) args, true); } SYCL_EXTERNAL void Planes_postIntersect(const Geometry *uniform, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64) { dg.Ng = dg.Ns = ray.Ng; } export void *uniform Planes_postIntersect_addr() { return (void *uniform)Planes_postIntersect; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/geometry/PlanesShared.h000066400000000000000000000006131456566705700241630ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "GeometryShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Planes { Geometry super; Data1D coeffs; Data1D bounds; #ifdef __cplusplus Planes() { super.type = GEOMETRY_TYPE_PLANES; } #endif }; #ifdef __cplusplus } // namespace ispc #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/geometry/Spheres.cpp000066400000000000000000000076021456566705700235630ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Spheres.h" #include "common/Data.h" #ifndef OSPRAY_TARGET_SYCL // ispc-generated files #include "geometry/Spheres_ispc.h" #else namespace ispc { void *Spheres_sampleArea_addr(); void *Spheres_getAreas_addr(); } // namespace ispc #endif namespace ospray { static std::map sphereFeatureFlags = { {OSP_SPHERE, FFG_SPHERE}, {OSP_DISC, FFG_DISC_POINT}, {OSP_ORIENTED_DISC, FFG_ORIENTED_DISC_POINT}}; Spheres::Spheres(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFG_NONE) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.postIntersect = reinterpret_cast( ispc::Spheres_postIntersect_addr()); #endif getSh()->super.getAreas = reinterpret_cast( ispc::Spheres_getAreas_addr()); // We also set the sampleArea function ptr so that // Geometry::supportAreaLighting will be true, but in SYCL we'll never call it // through the function pointer on the device getSh()->super.sampleArea = reinterpret_cast( ispc::Spheres_sampleArea_addr()); } std::string Spheres::toString() const { return "ospray::Spheres"; } void Spheres::commit() { sphereType = (OSPSphereType)getParam("type", OSP_SPHERE); radius = getParam("radius", 0.01f); vertexData = getParamDataT("sphere.position", true); radiusData = getParamDataT("sphere.radius"); texcoordData = getParamDataT("sphere.texcoord"); normalData = nullptr; if (sphereType == OSP_ORIENTED_DISC) { normalData = getParamDataT("sphere.normal", true); } // If the application's data is already interleaved and they just passed us // separate views into the interleaved data to make the sphere.position and // sphere.radius arrays we can detect this and use the interleaved array // directly to avoid copying it. If not, we need to make a new interleaved // data array for Embree if (radiusData && vertexData && reinterpret_cast(vertexData->data()) + sizeof(vec3f) == reinterpret_cast(radiusData->data()) && vertexData->stride() == radiusData->stride()) { auto interleaved = new Data(getISPCDevice(), vertexData->data(), OSP_VEC4F, vertexData->numItems, vec3l(sizeof(vec4f), 0, 0)); sphereData = &interleaved->as(); interleaved->refDec(); } else { // To maintain OSPRay 2.x compatibility we need to create the interleaved // position/radius array that Embree expects from the separate // position/radius (or global radius) that the OSPRay geometry takes auto interleaved = new Data(getISPCDevice(), OSP_VEC4F, vertexData->numItems); sphereData = &interleaved->as(); interleaved->refDec(); // For now default to always create the interleaved buffer since we // don't expose the interleaved data yet for (size_t i = 0; i < vertexData->size(); ++i) { float ptRadius = radius; if (radiusData) { ptRadius = (*radiusData)[i]; } interleaved->as()[i] = vec4f((*vertexData)[i], ptRadius); } } createEmbreeGeometry((RTCGeometryType)sphereType); featureFlagsGeometry = sphereFeatureFlags[sphereType]; setEmbreeGeometryBuffer(embreeGeometry, RTC_BUFFER_TYPE_VERTEX, sphereData); setEmbreeGeometryBuffer(embreeGeometry, RTC_BUFFER_TYPE_NORMAL, normalData); rtcCommitGeometry(embreeGeometry); getSh()->sphere = *ispc(sphereData); getSh()->texcoord = *ispc(texcoordData); getSh()->super.numPrimitives = numPrimitives(); getSh()->normalData = *ispc(normalData); getSh()->sphereType = sphereType; postCreationInfo(numPrimitives()); } size_t Spheres::numPrimitives() const { return sphereData ? sphereData->size() : 0; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/Spheres.h000066400000000000000000000022601456566705700232230ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Geometry.h" // ispc shared #include "SpheresShared.h" namespace ospray { struct OSPRAY_SDK_INTERFACE Spheres : public AddStructShared { Spheres(api::ISPCDevice &device); virtual ~Spheres() override = default; virtual std::string toString() const override; virtual void commit() override; virtual size_t numPrimitives() const override; protected: float radius{.01f}; // default radius, if no per-sphere radius Ref> vertexData; Ref> radiusData; Ref> texcoordData; // Embree's layout for sphere point uses interleaved position and // radius, each sphere is stored as x, y, z, r. OSPRay 2's format is not // interleaved, so we should deprecate the non-interleaved format. This array // is used to reference the interleaved data for the app or the interleaved // data the geometry creates when using the deprecated parameters Ref> sphereData; Ref> normalData; OSPSphereType sphereType{OSP_UNKNOWN_SPHERE_TYPE}; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/Spheres.ih000066400000000000000000000010451456566705700233740ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "geometry/Geometry.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL void Spheres_postIntersect(const Geometry *uniform _self, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags); SYCL_EXTERNAL SampleAreaRes Spheres_sampleArea( const Geometry *uniform const _self, const int32 primID, const uniform affine3f &xfm, const uniform affine3f &, const vec2f &s, const float time); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/geometry/Spheres.ispc000066400000000000000000000066201456566705700237360ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Spheres.ih" #include "common/Data.ih" #include "common/DifferentialGeometry.ih" #include "common/FilterIntersect.ih" #include "common/ISPCMessages.h" #include "common/Intersect.ih" #include "common/Ray.ih" #include "math/sampling.ih" #include "rkcommon/math/box.ih" #include "rkcommon/math/vec.ih" // c++ shared #include "SpheresShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE #ifdef OSPRAY_TARGET_SYCL using namespace ospray; #endif SYCL_EXTERNAL void Spheres_postIntersect(const Geometry *uniform geometry, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags) { Spheres *uniform self = (Spheres * uniform) geometry; dg.Ng = dg.Ns = ray.Ng; const vec4f vertex = get_vec4f(self->sphere, ray.primID); // make epsilon large enough to not get lost when computing // |CO| = |center-ray.org| ~ radius for 2ndary rays dg.epsilon = vertex.w * ulpEpsilon; if ((flags & DG_TEXCOORD) && valid(self->texcoord)) { dg.st = get_vec2f(self->texcoord, ray.primID); } } SYCL_EXTERNAL SampleAreaRes Spheres_sampleArea( const Geometry *uniform const _self, const int32 primID, const uniform affine3f &xfm, const uniform affine3f &rcp_xfm, const vec2f &s, const float) { const Spheres *const uniform self = (const Spheres *uniform)_self; const vec4f vertex = get_vec4f(self->sphere, primID); vec3f localNormal; vec3f localPos; if (self->sphereType == OSP_ORIENTED_DISC) { localNormal = normalize(get_vec3f(self->normalData, primID)); localPos = frame(localNormal) * uniformSampleDisk(vertex.w, s); } else { localNormal = uniformSampleSphere(vertex.w, s); localPos = localNormal; } SampleAreaRes res; res.pos = xfmPoint(xfm, make_vec3f(vertex) + localPos); res.normal = normalize(xfmVector(transposed(rcp_xfm.l), localNormal)); res.st = valid(self->texcoord) ? get_vec2f(self->texcoord, primID) : make_vec2f(0.f); return res; } void Spheres_getAreas(const Geometry *const uniform _self, const int32 *const uniform, const uniform int32 numPrims, const uniform affine3f &xfm, float *const uniform areas) { Spheres *uniform self = (Spheres * uniform) _self; // detect (non-uniform) scaling; get length of transformed unit-vectors const uniform vec3f scaling3 = make_vec3f(length(xfm.l.vx), length(xfm.l.vy), length(xfm.l.vz)); #if 0 const uniform float min_scaling = reduce_min(scaling3); const uniform float max_scaling = reduce_max(scaling3); if ((max_scaling - min_scaling) > 1e-4f * min_scaling) { postStatusMsg(ISPC_MSG_SPHERES, OSP_LOG_WARNING); } #endif // use average as approximation to closest uniform scaling const uniform float scale = ((self->sphereType == OSP_SPHERE) ? 4.0f : 1.0f) * (float)pi * sqr(reduce_add(scaling3) / 3.f); // TODO vectorize this loop, with foreach or ProgramCount & ProgramIndex for (uniform int32 i = 0; i < numPrims; i++) { const uniform vec4f vertex = get_vec4f(self->sphere, i); areas[i] = scale * sqr(vertex.w); } } export void *uniform Spheres_postIntersect_addr() { return (void *uniform)Spheres_postIntersect; } export void *uniform Spheres_sampleArea_addr() { return (void *uniform)Spheres_sampleArea; } export void *uniform Spheres_getAreas_addr() { return (void *uniform)Spheres_getAreas; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/geometry/SpheresShared.h000066400000000000000000000007351456566705700243570ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "GeometryShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Spheres { Geometry super; Data1D sphere; Data1D texcoord; Data1D normalData; float global_radius; OSPSphereType sphereType; #ifdef __cplusplus Spheres() : global_radius(.01f) { super.type = GEOMETRY_TYPE_SPHERES; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/geometry/Subdivision.cpp000066400000000000000000000134211456566705700244440ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Subdivision.h" #include "common/DGEnum.h" #include #ifndef OSPRAY_TARGET_SYCL // ispc exports #include "geometry/Subdivision_ispc.h" #else void *Subdivision_postIntersect_addr(); #endif namespace ospray { Subdivision::Subdivision(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFG_SUBDIVISION) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.postIntersect = reinterpret_cast( ispc::Subdivision_postIntersect_addr()); #endif } std::string Subdivision::toString() const { return "ospray::Subdivision"; } void Subdivision::commit() { createEmbreeGeometry(RTC_GEOMETRY_TYPE_SUBDIVISION); vertexData = getParamDataT("vertex.position", true); colorsData = getParamDataT("color"); bool isColorsFaceVarying = true; if (!colorsData) { colorsData = getParamDataT("vertex.color"); isColorsFaceVarying = false; } texcoordData = getParamDataT("texcoord"); bool isTexcoordFaceVarying = true; if (!texcoordData) { texcoordData = getParamDataT("vertex.texcoord"); isTexcoordFaceVarying = false; } level = getParam("level", 5.f); indexData = getParamDataT("index", true); indexLevelData = getParamDataT("index.level"); facesData = getParamDataT("face"); edge_crease_indicesData = getParamDataT("edgeCrease.index"); edge_crease_weightsData = getParamDataT("edgeCrease.weight"); vertex_crease_indicesData = getParamDataT("vertexCrease.index"); vertex_crease_weightsData = getParamDataT("vertexCrease.weight"); mode = (OSPSubdivisionMode)getParam( "mode", OSP_SUBDIVISION_SMOOTH_BOUNDARY); if (!facesData) { if (indexData->size() % 4 != 0) throw std::runtime_error( toString() + ": if no 'face' array is present then a pure quad mesh is assumed " "(the number of indices must be a multiple of 4)"); auto data = new Data( getISPCDevice(), OSP_UINT, vec3ui(indexData->size() / 4, 1, 1)); facesData = &(data->as()); data->refDec(); for (auto &&face : *facesData) face = 4; } setEmbreeGeometryBuffer(embreeGeometry, RTC_BUFFER_TYPE_VERTEX, vertexData); setEmbreeGeometryBuffer(embreeGeometry, RTC_BUFFER_TYPE_INDEX, indexData); setEmbreeGeometryBuffer(embreeGeometry, RTC_BUFFER_TYPE_FACE, facesData); rtcSetGeometrySubdivisionMode(embreeGeometry, 0, (RTCSubdivisionMode)mode); if (edge_crease_indicesData && edge_crease_weightsData) { if (edge_crease_indicesData->size() != edge_crease_weightsData->size()) postStatusMsg(OSP_LOG_DEBUG) << toString() + " ignoring edge creases, because size of arrays " "'edgeCrease.index' and 'edgeCrease.weight' does not match"; else { setEmbreeGeometryBuffer(embreeGeometry, RTC_BUFFER_TYPE_EDGE_CREASE_INDEX, edge_crease_indicesData); setEmbreeGeometryBuffer(embreeGeometry, RTC_BUFFER_TYPE_EDGE_CREASE_WEIGHT, edge_crease_weightsData); } } if (vertex_crease_indicesData && vertex_crease_weightsData) { if (vertex_crease_indicesData->size() != vertex_crease_weightsData->size()) { postStatusMsg(OSP_LOG_DEBUG) << toString() + " ignoring vertex creases, because size of " "arrays 'vertexCrease.index' and " "'vertexCrease.weight' does not match"; } else { setEmbreeGeometryBuffer(embreeGeometry, RTC_BUFFER_TYPE_VERTEX_CREASE_INDEX, vertex_crease_indicesData); setEmbreeGeometryBuffer(embreeGeometry, RTC_BUFFER_TYPE_VERTEX_CREASE_WEIGHT, vertex_crease_weightsData); } } if ((colorsData && isColorsFaceVarying) || (texcoordData && isTexcoordFaceVarying)) { if (generatedIndicesSize != indexData->size()) { auto data = new Data(getISPCDevice(), OSP_UINT, vec3ui(indexData->size(), 1, 1)); generatedIndicesData = &(data->as()); data->refDec(); uint32_t *dataptr = static_cast(generatedIndicesData->data()); for (unsigned int i = 0; i < indexData->size(); i++) *(dataptr++) = i; generatedIndicesSize = indexData->size(); } rtcSetGeometryTopologyCount(embreeGeometry, 2); setEmbreeGeometryBuffer( embreeGeometry, RTC_BUFFER_TYPE_INDEX, generatedIndicesData, 1); rtcSetGeometrySubdivisionMode(embreeGeometry, 1, (RTCSubdivisionMode)mode); } if (colorsData) { rtcSetGeometryVertexAttributeCount(embreeGeometry, 1); setEmbreeGeometryBuffer( embreeGeometry, RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE, colorsData, 0); if (isColorsFaceVarying) rtcSetGeometryVertexAttributeTopology(embreeGeometry, 0, 1); } if (texcoordData) { rtcSetGeometryVertexAttributeCount(embreeGeometry, 2); setEmbreeGeometryBuffer( embreeGeometry, RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE, texcoordData, 1); if (isTexcoordFaceVarying) rtcSetGeometryVertexAttributeTopology(embreeGeometry, 1, 1); } if (!indexLevelData) rtcSetGeometryTessellationRate(embreeGeometry, level); else { setEmbreeGeometryBuffer( embreeGeometry, RTC_BUFFER_TYPE_LEVEL, indexLevelData); } rtcCommitGeometry(embreeGeometry); getSh()->geom = embreeGeometry; getSh()->flagMask = -1; if (!colorsData) getSh()->flagMask &= ispc::int64(~DG_COLOR); if (!texcoordData) getSh()->flagMask &= ispc::int64(~DG_TEXCOORD); getSh()->super.numPrimitives = numPrimitives(); postCreationInfo(vertexData->size()); } size_t Subdivision::numPrimitives() const { return facesData->size(); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/Subdivision.h000066400000000000000000000023541456566705700241140ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Geometry.h" #include "common/Data.h" // ispc shared #include "SubdivisionShared.h" namespace ospray { struct OSPRAY_SDK_INTERFACE Subdivision : public AddStructShared { Subdivision(api::ISPCDevice &device); virtual ~Subdivision() override = default; virtual std::string toString() const override; virtual void commit() override; virtual size_t numPrimitives() const override; protected: float level{0.f}; Ref> vertexData; Ref> colorsData; size_t generatedIndicesSize{0}; // indices for face varying params Ref> generatedIndicesData; Ref> texcoordData; Ref> indexData; Ref> colorIndexData; Ref> indexLevelData; Ref> facesData; Ref> edge_crease_indicesData; Ref> edge_crease_weightsData; Ref> vertex_crease_indicesData; Ref> vertex_crease_weightsData; OSPSubdivisionMode mode{OSP_SUBDIVISION_SMOOTH_BOUNDARY}; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/Subdivision.ih000066400000000000000000000005421456566705700242620ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "geometry/Geometry.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // Not supported/used in SYCL/GPU void Subdivision_postIntersect(const Geometry *uniform _self, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/geometry/Subdivision.ispc000066400000000000000000000024061456566705700246210ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Geometry.ih" #include "common/Data.ih" // c++ shared #include "SubdivisionShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE void Subdivision_postIntersect(const Geometry *uniform _self, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags) { Subdivision *uniform self = (Subdivision * uniform) _self; dg.Ng = dg.Ns = ray.Ng; flags &= self->flagMask; if (flags & DG_NS) { vec3f dPdu, dPdv; rtcInterpolateV1(self->geom, ray.primID, ray.u, ray.v, RTC_BUFFER_TYPE_VERTEX, 0, NULL, &dPdu.x, &dPdv.x, 3); dg.Ns = cross(dPdu, dPdv); } if (flags & DG_COLOR) { rtcInterpolateV0(self->geom, ray.primID, ray.u, ray.v, RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE, 0, &dg.color.x, 4); } if (flags & DG_TEXCOORD) { rtcInterpolateV0(self->geom, ray.primID, ray.u, ray.v, RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE, 1, &dg.st.x, 2); } } export void *uniform Subdivision_postIntersect_addr() { return (void *uniform)Subdivision_postIntersect; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/geometry/SubdivisionShared.h000066400000000000000000000007461456566705700252460ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "GeometryShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Subdivision { Geometry super; RTCGeometry geom; int64 flagMask; // which attributes are missing and cannot be interpolated #ifdef __cplusplus Subdivision() : geom(nullptr), flagMask(-1) { super.type = GEOMETRY_TYPE_SUBDIVISION; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/geometry/registration.cpp000066400000000000000000000014521456566705700246610ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Boxes.h" #include "Curves.h" #ifdef OSPRAY_ENABLE_VOLUMES #include "Isosurfaces.h" #endif #include "Mesh.h" #include "Planes.h" #include "Spheres.h" #ifndef OSPRAY_TARGET_SYCL #include "Subdivision.h" #endif namespace ospray { void registerAllGeometries() { Geometry::registerType("box"); Geometry::registerType("curve"); #ifdef OSPRAY_ENABLE_VOLUMES Geometry::registerType("isosurface"); #endif Geometry::registerType("mesh"); Geometry::registerType("sphere"); #ifndef OSPRAY_TARGET_SYCL // Subdivision surfaces not supported on the GPU Geometry::registerType("subdivision"); #endif Geometry::registerType("plane"); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/geometry/registration.h000066400000000000000000000002251456566705700243230ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 namespace ospray { void registerAllGeometries(); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/ispc_symbols.txt000066400000000000000000000031171456566705700230570ustar00rootroot00000000000000Distribution2D_pdf___un_3C_s_5B__c_unDistribution2D_5D__3E_REFs_5B__c_vyvec2f_5D__, Distribution2D_sample___un_3C_s_5B__c_unDistribution2D_5D__3E_REFs_5B__c_vyvec2f_5D__, Light_eval___un_3C_s_5B__c_unLight_5D__3E_REFs_5B__c_vyDifferentialGeometry_5D_REFs_5B__c_vyvec3f_5D_CvyfCvyfCvyf_, Renderer_getBackground___un_3C_s_5B__c_unRenderer_5D__3E_REFs_5B__c_vyvec2f_5D_REFs_5B__c_unFeatureFlagsHandler_5D__, Renderer_getMaxDepth___un_3C_s_5B__c_unRenderer_5D__3E_REFs_5B__c_vyvec2f_5D_REFs_5B__c_unFeatureFlagsHandler_5D__, clippingIntersectionFilterV___UM_un_3C_s_5B__c_unRTCFilterFunctionNArguments_5D__3E__, get_zorder____, Geometry_dispatch_intersect___UM_un_3C_s_5B_unRTCIntersectFunctionNArguments_5D__3E__, Geometry_dispatch_occluded___UM_un_3C_s_5B_unRTCOccludedFunctionNArguments_5D__3E__, Geometry_dispatch_postIntersect___un_3C_s_5B__c_unGeometry_5D__3E_REFs_5B_vyDifferentialGeometry_5D_REFs_5B__c_vyRay_5D_unIREFs_5B__c_unFeatureFlagsHandler_5D__, Texture_dispatch_get___un_3C_s_5B__c_unTexture_5D__3E_REFs_5B__c_vyDifferentialGeometry_5D__, FrameBuffer_dispatch_getRenderTaskDesc___un_3C_s_5B_unFrameBuffer_5D__3E_CunuREFs_5B__c_unFeatureFlagsHandler_5D__, FrameBuffer_dispatch_accumulateSample___un_3C_s_5B_unFrameBuffer_5D__3E_REFs_5B__c_vyScreenSample_5D_REFs_5B_unRenderTaskDesc_5D_REFs_5B__c_unFeatureFlagsHandler_5D__, FrameBuffer_dispatch_completeTask___un_3C_s_5B_unFrameBuffer_5D__3E_REFs_5B__c_unRenderTaskDesc_5D_REFs_5B__c_unFeatureFlagsHandler_5D__, Camera_dispatch_initRay___un_3C_s_5B__c_unCamera_5D__3E_REFs_5B_vyRay_5D_REFs_5B__c_vyCameraSample_5D_REFs_5B__c_unFeatureFlagsHandler_5D__, RenderKit-ospray-f2a61c2/modules/cpu/ispc_symbols_volume.txt000066400000000000000000000003541456566705700244460ustar00rootroot00000000000000LinearTransferFunction_get___un_3C_s_5B__c_unTransferFunction_5D__3E_vyf_, TransferFunction_dispatch_get___un_3C_s_5B__c_unTransferFunction_5D__3E_vyf_, Volume_intersect_kernel___UM_un_3C_s_5B_unRTCIntersectFunctionNArguments_5D__3E__, RenderKit-ospray-f2a61c2/modules/cpu/ispc_tasksys.cpp000066400000000000000000000034601456566705700230340ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include #include #include "common/OSPCommon.h" #include "ispcrt.h" #include "rkcommon/memory/malloc.h" #include "rkcommon/tasking/parallel_for.h" namespace ospray { /* Signature of ispc-generated 'task' functions */ using ISPCTaskFunc = void (*)(void *data, int threadIndex, int threadCount, int taskIndex, int taskCount, int taskIndex0, int taskIndex1, int taskIndex2, int taskCount0, int taskCount1, int taskCount2); void *ospISPCAlloc(void **taskPtr, int64_t size, int32_t alignment) { if (*taskPtr == nullptr) *taskPtr = new std::vector; std::vector *lst = (std::vector *)(*taskPtr); void *ptr = memory::alignedMalloc((size_t)size, alignment); lst->push_back(ptr); return ptr; } void ospISPCSync(void *task) { std::vector *lst = (std::vector *)task; for (size_t i = 0; i < lst->size(); i++) memory::alignedFree((*lst)[i]); delete lst; } void ospISPCLaunch(void ** /*taskPtr*/, void *func, void *data, int taskCount0, int taskCount1, int taskCount2) { const size_t nTasks = size_t(taskCount0) * size_t(taskCount1) * size_t(taskCount2); tasking::parallel_for(nTasks, [&](const size_t i) { const int taskIndex0 = i % taskCount0; const int taskIndex1 = (i / taskCount0) % taskCount1; const int taskIndex2 = i / (size_t(taskCount0) * taskCount1); ((ISPCTaskFunc)func)(data, i, nTasks, i, nTasks, taskIndex0, taskIndex1, taskIndex2, taskCount0, taskCount1, taskCount2); }); } void setIspcrtTaskingCallbacks() { ispcrtSetTaskingCallbacks(ospISPCLaunch, ospISPCAlloc, ospISPCSync); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/ispc_tasksys.h000066400000000000000000000002211456566705700224710ustar00rootroot00000000000000// Copyright 2023 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once namespace ospray { void setIspcrtTaskingCallbacks(); } RenderKit-ospray-f2a61c2/modules/cpu/lights/000077500000000000000000000000001456566705700211005ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/lights/AmbientLight.cpp000066400000000000000000000033011456566705700241500ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "AmbientLight.h" #include "common/StructShared.h" #ifndef OSPRAY_TARGET_SYCL #include "lights/AmbientLight_ispc.h" #else namespace ispc { void *AmbientLight_sample_addr(); void *AmbientLight_eval_addr(); } // namespace ispc #endif // ispc shared #include "AmbientLightShared.h" namespace ospray { ISPCRTMemoryView AmbientLight::createSh( uint32_t, const ispc::Instance *instance) const { ISPCRTMemoryView view = StructSharedCreate( getISPCDevice().getIspcrtContext().handle()); ispc::AmbientLight *sh = (ispc::AmbientLight *)ispcrtSharedPtr(view); #ifndef OSPRAY_TARGET_SYCL sh->super.sample = reinterpret_cast( ispc::AmbientLight_sample_addr()); sh->super.eval = reinterpret_cast(ispc::AmbientLight_eval_addr()); #endif sh->super.isVisible = visible; sh->super.instance = instance; sh->radiance = radiance; return view; } std::string AmbientLight::toString() const { return "ospray::AmbientLight"; } void AmbientLight::commit() { Light::commit(); queryIntensityQuantityType(OSP_INTENSITY_QUANTITY_RADIANCE); processIntensityQuantityType(); } void AmbientLight::processIntensityQuantityType() { // validate the correctness of the light quantity type if (intensityQuantity == OSP_INTENSITY_QUANTITY_IRRADIANCE) { radiance = coloredIntensity / M_PI; } else if (intensityQuantity == OSP_INTENSITY_QUANTITY_RADIANCE) { radiance = coloredIntensity; } else { postStatusMsg(OSP_LOG_WARNING) << toString() << " unsupported 'intensityQuantity' value"; radiance = vec3f(0.0f); } } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/AmbientLight.h000066400000000000000000000013131456566705700236160ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Light.h" namespace ospray { //! an AmbientLight is a constant light that is present everywhere struct OSPRAY_SDK_INTERFACE AmbientLight : public Light { AmbientLight(api::ISPCDevice &device) : Light(device, FFO_LIGHT_AMBIENT) {} virtual ~AmbientLight() override = default; virtual ISPCRTMemoryView createSh( uint32_t, const ispc::Instance *instance = nullptr) const override; virtual std::string toString() const override; virtual void commit() override; vec3f radiance{1.f}; //!< emitted radiance of the AmbientLight private: void processIntensityQuantityType(); }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/AmbientLight.ih000066400000000000000000000010601456566705700237660ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "lights/LightShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL Light_SampleRes AmbientLight_sample(const Light *uniform super, const DifferentialGeometry &dg, const vec2f &sp, const float, const uniform FeatureFlagsHandler &); SYCL_EXTERNAL Light_EvalRes AmbientLight_eval(const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/AmbientLight.ispc000066400000000000000000000037211456566705700243320ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/DifferentialGeometry.ih" #include "math/sampling.ih" #include "rkcommon/math/LinearSpace.ih" // c++ shared #include "AmbientLightShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE // Implementation ////////////////////////////////////////////////////////////////////////////// // XXX importance sampling is only done into the positive hemisphere // ==> poor support for translucent materials SYCL_EXTERNAL Light_SampleRes AmbientLight_sample(const Light *uniform super, const DifferentialGeometry &dg, const vec2f &s, const float, const uniform FeatureFlagsHandler &) { uniform AmbientLight *uniform self = (uniform AmbientLight * uniform) super; Light_SampleRes res; if (reduce_max(abs(dg.Ns)) > 0) { const vec3f localDir = cosineSampleHemisphere(s); res.dir = frame(dg.Ns) * localDir; res.pdf = cosineSampleHemispherePDF(localDir); } else { res.dir = uniformSampleSphere(1.f, s); res.pdf = uniformSampleSpherePDF(1.f); } res.dist = inf; res.weight = self->radiance * rcp(res.pdf); return res; } SYCL_EXTERNAL Light_EvalRes AmbientLight_eval(const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float, const float maxDist, const float) { uniform AmbientLight *uniform self = (uniform AmbientLight * uniform) super; Light_EvalRes res; res.radiance = (float)inf <= maxDist ? self->radiance : make_vec3f(0.f); if (reduce_max(abs(dg.Ns)) > 0) res.pdf = cosineSampleHemispherePDF(max(dot(dg.Ns, dir), 0.f)); else res.pdf = uniformSampleSpherePDF(1.f); return res; } // Exports (called from C++) ////////////////////////////////////////////////////////////////////////////// export void *uniform AmbientLight_sample_addr() { return (void *uniform)AmbientLight_sample; } export void *uniform AmbientLight_eval_addr() { return (void *uniform)AmbientLight_eval; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/AmbientLightShared.h000066400000000000000000000006601456566705700247510ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "LightShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct AmbientLight { Light super; // inherited light fields vec3f radiance; // emitted RGB radiance #ifdef __cplusplus AmbientLight() : radiance(1.f) { super.type = LIGHT_TYPE_AMBIENT; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/lights/CylinderCapSolidAngleTable.ih000066400000000000000000001232431456566705700265360ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/math.ih" OSPRAY_BEGIN_ISPC_NAMESPACE const uniform float CylCapSolidAngleTable[] = {0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 1.324344735105687941e-04f, 1.522660324370707656e-04f, 1.573041622823640709e-04f, 1.592206333250290138e-04f, 1.601378902436257539e-04f, 1.606445666452721154e-04f, 1.609530122796813971e-04f, 1.611544049267169627e-04f, 1.612930298554018850e-04f, 1.613924640850384403e-04f, 0.000000000000000000e+00f, 2.079389560425832215e-04f, 2.418569419427302593e-04f, 2.505750744399992008e-04f, 2.539021985766657676e-04f, 2.554967263084124691e-04f, 2.563780999808024769e-04f, 2.569148511271038141e-04f, 2.572653939717546990e-04f, 2.575067219119174088e-04f, 2.576798431415581146e-04f, 0.000000000000000000e+00f, 2.353557656252160569e-04f, 2.747346643900388640e-04f, 2.848935470945746515e-04f, 2.887745253091539743e-04f, 2.906352752629875590e-04f, 2.916640219201449709e-04f, 2.922905986733082559e-04f, 2.926998362668255336e-04f, 2.929815863886020013e-04f, 2.931837124451351423e-04f, 0.000000000000000000e+00f, 2.471449816382869638e-04f, 2.889245245841044274e-04f, 2.997188457314994055e-04f, 3.038443349008019688e-04f, 3.058226611542990336e-04f, 3.069165077355631341e-04f, 3.075827682434436705e-04f, 3.080179382636986712e-04f, 3.083175485132807580e-04f, 3.085324904882438043e-04f, 0.000000000000000000e+00f, 2.530989951023317479e-04f, 2.961026955154546559e-04f, 3.072215014833809088e-04f, 3.114719015023532499e-04f, 3.135103031200374511e-04f, 3.146374152658422646e-04f, 3.153239548826361808e-04f, 3.157723772518377043e-04f, 3.160811148227334185e-04f, 3.163026063990813071e-04f, 0.000000000000000000e+00f, 2.564809353247177529e-04f, 3.001834485672567800e-04f, 3.114876213887419424e-04f, 3.158093939369322942e-04f, 3.178821249299264469e-04f, 3.190282471529652577e-04f, 3.197263758519848921e-04f, 3.201823717808763401e-04f, 3.204963255635058170e-04f, 3.207215602277217921e-04f, 0.000000000000000000e+00f, 2.585734616717737873e-04f, 3.027096121304737692e-04f, 3.141288595804324390e-04f, 3.184949452806097050e-04f, 3.205889914938048245e-04f, 3.217469174426753568e-04f, 3.224522421353280457e-04f, 3.229129407487705650e-04f, 3.232301334775221466e-04f, 3.234576923788846708e-04f, 0.000000000000000000e+00f, 2.599538312189582433e-04f, 3.043765623677294522e-04f, 3.158718799923146523e-04f, 3.202672612340357614e-04f, 3.223753994528717292e-04f, 3.235411292573714057e-04f, 3.242512115177207201e-04f, 3.247150192879226017e-04f, 3.250343534384156656e-04f, 3.252634490080406069e-04f, 0.000000000000000000e+00f, 2.609105553783080608e-04f, 3.055321579139339515e-04f, 3.170802734117933344e-04f, 3.214959888194799482e-04f, 3.236139085749938256e-04f, 3.247850552478668976e-04f, 3.254984398861687973e-04f, 3.259644058287874437e-04f, 3.262852264175356508e-04f, 3.265153886461359851e-04f, 0.000000000000000000e+00f, 2.616001385399520417e-04f, 3.063652066180995947e-04f, 3.179514151471859074e-04f, 3.223818019526446471e-04f, 3.245067793375723542e-04f, 3.256818344500071673e-04f, 3.263976018676227695e-04f, 3.268651250102232240e-04f, 3.271870181202876562e-04f, 3.274179499846075663e-04f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 3.518709244702191308e-04f, 4.683165637320721247e-04f, 5.112354179907870229e-04f, 5.303183442801986426e-04f, 5.401600925084595840e-04f, 5.458213572572553993e-04f, 5.493521299147061847e-04f, 5.516935337888750988e-04f, 5.533222474443736652e-04f, 5.544992454144986914e-04f, 0.000000000000000000e+00f, 7.564274540073267963e-04f, 1.047422775041331137e-03f, 1.157895188902293045e-03f, 1.207568980015362057e-03f, 1.233320234019417332e-03f, 1.248173894431466383e-03f, 1.257452756424457408e-03f, 1.263612327455216049e-03f, 1.267900004232375925e-03f, 1.271000042202091859e-03f, 0.000000000000000000e+00f, 1.003462835547388327e-03f, 1.419131877800553724e-03f, 1.579135209145570828e-03f, 1.651485122984807079e-03f, 1.689091300932595669e-03f, 1.710813997450975378e-03f, 1.724395352762325738e-03f, 1.733415930831165271e-03f, 1.739697458797044528e-03f, 1.744240251854955927e-03f, 0.000000000000000000e+00f, 1.143834031312154515e-03f, 1.636939564350985447e-03f, 1.828099798065667934e-03f, 1.914790679706731419e-03f, 1.959913807652678436e-03f, 1.985998222441378788e-03f, 2.002313918709211060e-03f, 2.013153735013494244e-03f, 2.020703571863047363e-03f, 2.026164358059563773e-03f, 0.000000000000000000e+00f, 1.226309947336103739e-03f, 1.767333086735097024e-03f, 1.977908109642293084e-03f, 2.073560818586137576e-03f, 2.123387906682048902e-03f, 2.152203878442562283e-03f, 2.170232757489803758e-03f, 2.182212740185190698e-03f, 2.190557619589210761e-03f, 2.196593933475704443e-03f, 0.000000000000000000e+00f, 1.277461271335418244e-03f, 1.849154837636200191e-03f, 2.072208855142282369e-03f, 2.173631403692885631e-03f, 2.226489455102349368e-03f, 2.257066262878798871e-03f, 2.276199798626163916e-03f, 2.288915083509291803e-03f, 2.297772751394711651e-03f, 2.304180300992577507e-03f, 0.000000000000000000e+00f, 1.310886684522754274e-03f, 1.903030842774131731e-03f, 2.134428080685532754e-03f, 2.239712232707347355e-03f, 2.294599846438157443e-03f, 2.326356050655218645e-03f, 2.346229600079902024e-03f, 2.359437518863661924e-03f, 2.368638766816207920e-03f, 2.375295065567726085e-03f, 0.000000000000000000e+00f, 1.333742658498826388e-03f, 1.940061354761947118e-03f, 2.177251861166239286e-03f, 2.285219226091063632e-03f, 2.341517535968261950e-03f, 2.374093656364981327e-03f, 2.394481718982423898e-03f, 2.408032177838734678e-03f, 2.417472336517638778e-03f, 2.424301610494127707e-03f, 0.000000000000000000e+00f, 1.349981060688657973e-03f, 1.966465991084871863e-03f, 2.207816820003138340e-03f, 2.317711996277340217e-03f, 2.375024082451204169e-03f, 2.408189497312768039e-03f, 2.428947381262678857e-03f, 2.442744062634739140e-03f, 2.452355959253100376e-03f, 2.459309577158362136e-03f, 0.000000000000000000e+00f, 1.361894711241359206e-03f, 1.985889500491258477e-03f, 2.230316422217705225e-03f, 2.341637485555428909e-03f, 2.399699524599541254e-03f, 2.433300916004638680e-03f, 2.454332418834928586e-03f, 2.468311278606549232e-03f, 2.478050245966633217e-03f, 2.485095868809059950e-03f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 5.148143079474772456e-04f, 7.466963702743565669e-04f, 8.540924768223674864e-04f, 9.090308884320854026e-04f, 9.398167374470985059e-04f, 9.584482807966543567e-04f, 9.704531768272830951e-04f, 9.785903359863293554e-04f, 9.843379804579401558e-04f, 9.885378125159579969e-04f, 0.000000000000000000e+00f, 1.253514637562834185e-03f, 1.937381211125926810e-03f, 2.264953477267791799e-03f, 2.435076592709123963e-03f, 2.531146721947160651e-03f, 2.589542084462958128e-03f, 2.627268588474988235e-03f, 2.652884902384841648e-03f, 2.671000464765789419e-03f, 2.684248870354409826e-03f, 0.000000000000000000e+00f, 1.805645740500164045e-03f, 2.923239499370571155e-03f, 3.469880912448602625e-03f, 3.756492839361498873e-03f, 3.919162270565094107e-03f, 4.018327199393406657e-03f, 4.082508604594513660e-03f, 4.126139500491008902e-03f, 4.157019994337727252e-03f, 4.179616969615533410e-03f, 0.000000000000000000e+00f, 2.166031051752110529e-03f, 3.623367960760648290e-03f, 4.346786328097372240e-03f, 4.728425004110046147e-03f, 4.945730130634628727e-03f, 5.078450242993188049e-03f, 5.164449556490857511e-03f, 5.222957424495248274e-03f, 5.264389371789464193e-03f, 5.294719002811903302e-03f, 0.000000000000000000e+00f, 2.397429617633945256e-03f, 4.102067843197306288e-03f, 4.957450923063252100e-03f, 5.410593565507399588e-03f, 5.669169656332504782e-03f, 5.827292658623370661e-03f, 5.929831656028333210e-03f, 5.999627523881404835e-03f, 6.049070396274724981e-03f, 6.085273449131553547e-03f, 0.000000000000000000e+00f, 2.549368937648944372e-03f, 4.430824716323404980e-03f, 5.382479625796733787e-03f, 5.888099668579335061e-03f, 6.177049414622892871e-03f, 6.353896803602655276e-03f, 6.468638692124228234e-03f, 6.546767941194820209e-03f, 6.602127406276578521e-03f, 6.642669686120350990e-03f, 0.000000000000000000e+00f, 2.652478153375369910e-03f, 4.661169684101590209e-03f, 5.683180157940269719e-03f, 6.227324667582475638e-03f, 6.538617837456350834e-03f, 6.729254639632639874e-03f, 6.852989337057374501e-03f, 6.937262504145540881e-03f, 6.996985390082748058e-03f, 7.040728491883075507e-03f, 0.000000000000000000e+00f, 2.724833704580410364e-03f, 4.826576642897440102e-03f, 5.900647986915204257e-03f, 6.473397323717751048e-03f, 6.801306029919003925e-03f, 7.002205690658911200e-03f, 7.132636668749612469e-03f, 7.221486230823217362e-03f, 7.284459995566929316e-03f, 7.330588179434545208e-03f, 0.000000000000000000e+00f, 2.777193121512918500e-03f, 4.948313722212235519e-03f, 6.061549571150137879e-03f, 6.655874317352564358e-03f, 6.996329873173594109e-03f, 7.204984098087410804e-03f, 7.340476631155143199e-03f, 7.432786208671369500e-03f, 7.498218225694946310e-03f, 7.546150173259567884e-03f, 0.000000000000000000e+00f, 2.816127041162471301e-03f, 5.039991504078758511e-03f, 6.183207539771379095e-03f, 6.794081629995274256e-03f, 7.144169726016271968e-03f, 7.358780144991966012e-03f, 7.498161501484510751e-03f, 7.593129914869260755e-03f, 7.660451201529748164e-03f, 7.709769539512028799e-03f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 6.330630758403497406e-04f, 9.689183242194677158e-04f, 1.147393727860851259e-03f, 1.248824337567151690e-03f, 1.310016946721651813e-03f, 1.348979419893589016e-03f, 1.374985660749956928e-03f, 1.393060169151647334e-03f, 1.406061569536036938e-03f, 1.415691385285003075e-03f, 0.000000000000000000e+00f, 1.622982320300010717e-03f, 2.701938518079526844e-03f, 3.294702983947319502e-03f, 3.636918114345742345e-03f, 3.845154685284924660e-03f, 3.978419795121803000e-03f, 4.067657530720846307e-03f, 4.129812091727653317e-03f, 4.174588465907964896e-03f, 4.207789226664360865e-03f, 0.000000000000000000e+00f, 2.414795568233982399e-03f, 4.318654218803607940e-03f, 5.395581270951582339e-03f, 6.024765956700464144e-03f, 6.410139085803693605e-03f, 6.657744753022374652e-03f, 6.823970299633269967e-03f, 6.939946223429980035e-03f, 7.023596514313117274e-03f, 7.085675836419507052e-03f, 0.000000000000000000e+00f, 2.954155122638248490e-03f, 5.585884539816199715e-03f, 7.117112432957192758e-03f, 8.020644828942680507e-03f, 8.576903781303987090e-03f, 8.935395883314885268e-03f, 9.176532167816170080e-03f, 9.344994335701675356e-03f, 9.466613516980450227e-03f, 9.556931087201311556e-03f, 0.000000000000000000e+00f, 3.309622812366178578e-03f, 6.519673311726707082e-03f, 8.434770609219766069e-03f, 9.574480857880865101e-03f, 1.027907845340537626e-02f, 1.073426714901062028e-02f, 1.104091172683628087e-02f, 1.125535734483322503e-02f, 1.141028395754554135e-02f, 1.152539586104889095e-02f, 0.000000000000000000e+00f, 3.546872447411592976e-03f, 7.197122743859855031e-03f, 9.420419469569327187e-03f, 1.075305604061065762e-02f, 1.157974188162016853e-02f, 1.211483561693207055e-02f, 1.247574371943477312e-02f, 1.272833935428445591e-02f, 1.291092914697953946e-02f, 1.304664963401448372e-02f, 0.000000000000000000e+00f, 3.709598889376596823e-03f, 7.691126070511996801e-03f, 1.015658152587857292e-02f, 1.164308907444725101e-02f, 1.256778608267826794e-02f, 1.316724812456793008e-02f, 1.357195842639335667e-02f, 1.385538992174475091e-02f, 1.406035943214321848e-02f, 1.421276311649024952e-02f, 0.000000000000000000e+00f, 3.824618653025676183e-03f, 8.056429142161470464e-03f, 1.071114747813457953e-02f, 1.231942132085871340e-02f, 1.332210697903568782e-02f, 1.397293583788518541e-02f, 1.441266073211551826e-02f, 1.472076883805627061e-02f, 1.494366122753849543e-02f, 1.510943278865536921e-02f, 0.000000000000000000e+00f, 3.908276579859369312e-03f, 8.331238865437462504e-03f, 1.113438477823026213e-02f, 1.283912775213246968e-02f, 1.390388080150351847e-02f, 1.459568779448104647e-02f, 1.506338519389619802e-02f, 1.539122479106847657e-02f, 1.562845714833507524e-02f, 1.580492889957122241e-02f, 0.000000000000000000e+00f, 3.970714592225201359e-03f, 8.541660185314235709e-03f, 1.146212511353233467e-02f, 1.324374946206734009e-02f, 1.435815175165684396e-02f, 1.508280258434187455e-02f, 1.557294585420195346e-02f, 1.591663025057328193e-02f, 1.616538368357876149e-02f, 1.635045528411100887e-02f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 7.212811140121224915e-04f, 1.145742417107076683e-03f, 1.391883272944551518e-03f, 1.542798871459532314e-03f, 1.639473665637473324e-03f, 1.703890684308947186e-03f, 1.748374322168447757e-03f, 1.780089635894296744e-03f, 1.803348655089967922e-03f, 1.820833937754083587e-03f, 0.000000000000000000e+00f, 1.887340452230905439e-03f, 3.320212172265470454e-03f, 4.179485837867540250e-03f, 4.714296490400989546e-03f, 5.059805189507511798e-03f, 5.291228737426888033e-03f, 5.451582859600462815e-03f, 5.566174678315898364e-03f, 5.650350614937620086e-03f, 5.713706941678609041e-03f, 0.000000000000000000e+00f, 2.834448186751709845e-03f, 5.468555396175245331e-03f, 7.113650880673496810e-03f, 8.152108432206669683e-03f, 8.828034936984537062e-03f, 9.282851385270190700e-03f, 9.598942269980353242e-03f, 9.825292590586972782e-03f, 9.991807914818658445e-03f, 1.011727386957128084e-02f, 0.000000000000000000e+00f, 3.482562777897965905e-03f, 7.230836955609326079e-03f, 9.680161174012684097e-03f, 1.124972903795233570e-02f, 1.227878066863242502e-02f, 1.297412787946376073e-02f, 1.345868672328128825e-02f, 1.380631017143750527e-02f, 1.406237157233477565e-02f, 1.425549161837616485e-02f, 0.000000000000000000e+00f, 3.910125450455917764e-03f, 8.573986045328902544e-03f, 1.175344402795287270e-02f, 1.382224323503398154e-02f, 1.518830623356486054e-02f, 1.611506977648453215e-02f, 1.676250277269603420e-02f, 1.722774511293859862e-02f, 1.757084466358614303e-02f, 1.782982762043219122e-02f, 0.000000000000000000e+00f, 4.195478113700949578e-03f, 9.572553801176924421e-03f, 1.337208257744917743e-02f, 1.587981542579631339e-02f, 1.754687578908758691e-02f, 1.868205174785504685e-02f, 1.947689490705743071e-02f, 2.004892814257227054e-02f, 2.047122494349440380e-02f, 2.079023041572572797e-02f, 0.000000000000000000e+00f, 4.391139168102254839e-03f, 1.031374719492394315e-02f, 1.462190656340965102e-02f, 1.750115447916205519e-02f, 1.942679519129223223e-02f, 2.074244707635598123e-02f, 2.166554766725809281e-02f, 2.233078004469190095e-02f, 2.282233761806777214e-02f, 2.319391222302685795e-02f, 0.000000000000000000e+00f, 4.529394042038001507e-03f, 1.086901209427927791e-02f, 1.558799715383739869e-02f, 1.877549102780820545e-02f, 2.091854264573917224e-02f, 2.238703945070888088e-02f, 2.341923306400309213e-02f, 2.416396003589227695e-02f, 2.471470604294914372e-02f, 2.513126542062316809e-02f, 0.000000000000000000e+00f, 4.629923660528266829e-03f, 1.129079130639894755e-02f, 1.634022180551901460e-02f, 1.978126845756981306e-02f, 2.210521617926395482e-02f, 2.370169823405501863e-02f, 2.482559216036049274e-02f, 2.563730547928672401e-02f, 2.623801094619798019e-02f, 2.669258636203961088e-02f, 0.000000000000000000e+00f, 4.704936553889154868e-03f, 1.161612790425591360e-02f, 1.693193703735837441e-02f, 2.058118757044315530e-02f, 2.305512780417269536e-02f, 2.475831255654708379e-02f, 2.595891243272585233e-02f, 2.682677959716530183e-02f, 2.746942706560224698e-02f, 2.795595112510076627e-02f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 7.886277541261281585e-04f, 1.288083776318236454e-03f, 1.595231749729407802e-03f, 1.794205293561702830e-03f, 1.927825702307663612e-03f, 2.020359060251305031e-03f, 2.086251153426085976e-03f, 2.134382573814292295e-03f, 2.170362532143429047e-03f, 2.197824765211205296e-03f, 0.000000000000000000e+00f, 2.075871817031091186e-03f, 3.813224858676668438e-03f, 4.920759008805931922e-03f, 5.648430922382662728e-03f, 6.140991888636010421e-03f, 6.483794346710756648e-03f, 6.728708363724023034e-03f, 6.908018590856198314e-03f, 7.042280562632280763e-03f, 7.144883080190312166e-03f, 0.000000000000000000e+00f, 3.117381304854234102e-03f, 6.375259184681209869e-03f, 8.566777219774319649e-03f, 1.003128508041885303e-02f, 1.103089239346197181e-02f, 1.173004494238572525e-02f, 1.223118215498218871e-02f, 1.259891109331477341e-02f, 1.287470254726895934e-02f, 1.308571527942264771e-02f, 0.000000000000000000e+00f, 3.825717120065501992e-03f, 8.514634789312950161e-03f, 1.186896531448872714e-02f, 1.415911630965160581e-02f, 1.573767876663084361e-02f, 1.684782962166546383e-02f, 1.764629906813101543e-02f, 1.823356497228816389e-02f, 1.867472804716201196e-02f, 1.901267522803663790e-02f, 0.000000000000000000e+00f, 4.290824483525533355e-03f, 1.016390003634775122e-02f, 1.461213065387898837e-02f, 1.772098796640041857e-02f, 1.988756547327948099e-02f, 2.142046605735105358e-02f, 2.252707718259811323e-02f, 2.334296722288513662e-02f, 2.395691971003124227e-02f, 2.442781050823393529e-02f, 0.000000000000000000e+00f, 4.600251514432151904e-03f, 1.139909612452231005e-02f, 1.680079008919013392e-02f, 2.066199309645985402e-02f, 2.338320775886965769e-02f, 2.532056302592006203e-02f, 2.672449224496529011e-02f, 2.776218338397702309e-02f, 2.854439294144339029e-02f, 2.914508316732965232e-02f, 0.000000000000000000e+00f, 4.811966833600228761e-03f, 1.232039591725546043e-02f, 1.851919219488658980e-02f, 2.304017738419015388e-02f, 2.626031209934483884e-02f, 2.856675316168256346e-02f, 3.024437998247574491e-02f, 3.148741075694074659e-02f, 3.242599367838468888e-02f, 3.314764878185472857e-02f, 0.000000000000000000e+00f, 4.961345092670534258e-03f, 1.301288388128898389e-02f, 1.986461845266174545e-02f, 2.494866092839396338e-02f, 2.860454189137067935e-02f, 3.123772859020323631e-02f, 3.315969831138976254e-02f, 3.458705750859270012e-02f, 3.566654530130984602e-02f, 3.649749476986991620e-02f, 0.000000000000000000e+00f, 5.069848982399235808e-03f, 1.354013275348193990e-02f, 2.092263441641366295e-02f, 2.648029178931736449e-02f, 3.051020421836446103e-02f, 3.342730774392779075e-02f, 3.556323727608656782e-02f, 3.715283217135611354e-02f, 3.835677661573724112e-02f, 3.928450805609219609e-02f, 0.000000000000000000e+00f, 5.150749986807798275e-03f, 1.394751711739385114e-02f, 2.176135386663251986e-02f, 2.771490302859902846e-02f, 3.206294610534261846e-02f, 3.522414215931390230e-02f, 3.754529218616584757e-02f, 3.927598085625663704e-02f, 4.058851195179079274e-02f, 4.160088044039742666e-02f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 8.409049105883540254e-04f, 1.404128719459686852e-03f, 1.765188368639016882e-03f, 2.008796995337924253e-03f, 2.178544808847337338e-03f, 2.299906117061264327e-03f, 2.388668553265759636e-03f, 2.454952271330086699e-03f, 2.505405544133496552e-03f, 2.544488663735909248e-03f, 0.000000000000000000e+00f, 2.211276794768384218e-03f, 4.205942891278083295e-03f, 5.537393703907753963e-03f, 6.447998830919157189e-03f, 7.087164739749489059e-03f, 7.546231432481296901e-03f, 7.883021429449974318e-03f, 8.135064537221082734e-03f, 8.327214095147432785e-03f, 8.476235642834154330e-03f, 0.000000000000000000e+00f, 3.309415263687501968e-03f, 7.078555395920566561e-03f, 9.768119993488632094e-03f, 1.164596828840228429e-02f, 1.297644774436901641e-02f, 1.393714345522122089e-02f, 1.464436793760017820e-02f, 1.517488254254313260e-02f, 1.558001732315511534e-02f, 1.589461677611720899e-02f, 0.000000000000000000e+00f, 4.050730286239253436e-03f, 9.487235508271726903e-03f, 1.366709854910849904e-02f, 1.666953051899764879e-02f, 1.882431979081320220e-02f, 2.039106305104328165e-02f, 2.154933675325849257e-02f, 2.242064567410862255e-02f, 2.308734523799175001e-02f, 2.360580292793293400e-02f, 0.000000000000000000e+00f, 4.535286937466600360e-03f, 1.134611476159541089e-02f, 1.694721425714761781e-02f, 2.109867955125385372e-02f, 2.412438914252086272e-02f, 2.634309090146036078e-02f, 2.799179615553328698e-02f, 2.923620194935939651e-02f, 3.019059610352927900e-02f, 3.093402180179632283e-02f, 0.000000000000000000e+00f, 4.856764952963409966e-03f, 1.273813200608200392e-02f, 1.958802920526525604e-02f, 2.481999190609950404e-02f, 2.869531045468254674e-02f, 3.156345647461759885e-02f, 3.370696880367917564e-02f, 3.533092542090644078e-02f, 3.657964832387837484e-02f, 3.755415734009321521e-02f, 0.000000000000000000e+00f, 5.076341487001670601e-03f, 1.377588337266780205e-02f, 2.167490906914956716e-02f, 2.787110986356607437e-02f, 3.253221801062159552e-02f, 3.601408854351095812e-02f, 3.863157383647888854e-02f, 4.062237364604340262e-02f, 4.215733831870509957e-02f, 4.335758190036979182e-02f, 0.000000000000000000e+00f, 5.231086483603165568e-03f, 1.455546358066520454e-02f, 2.331654516634287452e-02f, 3.034659890518537698e-02f, 3.570968046632597148e-02f, 3.975117471924284607e-02f, 4.280664993000107138e-02f, 4.513950503188909891e-02f, 4.694305546941619778e-02f, 4.835607691153816223e-02f, 0.000000000000000000e+00f, 5.343398176252857866e-03f, 1.514871634855200627e-02f, 2.461199808645184520e-02f, 3.235060518899594145e-02f, 3.832736202473158160e-02f, 4.286730310131266902e-02f, 4.631777880203825914e-02f, 4.896176865226951197e-02f, 5.101111340104958619e-02f, 5.261972191992605324e-02f, 0.000000000000000000e+00f, 5.427089881340583372e-03f, 1.560689566768099813e-02f, 2.564164045356884594e-02f, 3.397721033727196110e-02f, 4.048372286997169167e-02f, 4.546111243969969823e-02f, 4.926218276911005500e-02f, 5.218451437880067267e-02f, 5.445499338070784040e-02f, 5.624029962279188805e-02f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 8.819928697035788563e-04f, 1.499808675898415189e-03f, 1.908225105418749840e-03f, 2.192393595377619547e-03f, 2.396239154598805640e-03f, 2.545843228278368321e-03f, 2.657792261706820678e-03f, 2.743043405345950078e-03f, 2.809018628625797181e-03f, 2.860843823986314143e-03f, 0.000000000000000000e+00f, 2.309604703834023005e-03f, 4.519723640833095586e-03f, 6.050185724869521636e-03f, 7.129594126592466927e-03f, 7.909145032571158682e-03f, 8.483635400819646358e-03f, 8.914722305197662205e-03f, 9.243647113839898247e-03f, 9.498565711386340940e-03f, 9.699027573244036263e-03f, 0.000000000000000000e+00f, 3.441993626605958489e-03f, 7.621663068032521332e-03f, 1.075187088001746533e-02f, 1.301549353337524799e-02f, 1.466792515089303424e-02f, 1.589275460458437761e-02f, 1.681515189784345277e-02f, 1.752066328498773709e-02f, 1.806838645729005530e-02f, 1.849965608010141135e-02f, 0.000000000000000000e+00f, 4.201738591611474220e-03f, 1.021713787947973323e-02f, 1.511696034060911083e-02f, 1.878711774109946553e-02f, 2.151020004638156888e-02f, 2.354613908580450304e-02f, 2.508729736790969028e-02f, 2.627003716202713779e-02f, 2.719038558162066924e-02f, 2.791626932314798457e-02f, 0.000000000000000000e+00f, 4.696687057928286904e-03f, 1.221429317381030229e-02f, 1.880444680860411319e-02f, 2.393282904286624796e-02f, 2.781434330205767233e-02f, 3.074895459913826179e-02f, 3.298548417575247749e-02f, 3.470945032645365858e-02f, 3.605501455116834342e-02f, 3.711856949032635994e-02f, 0.000000000000000000e+00f, 5.024435445393716539e-03f, 1.370594897871207744e-02f, 2.177985357316791770e-02f, 2.829246297011497879e-02f, 3.332552982113546475e-02f, 3.717851557333125279e-02f, 4.013808584602007734e-02f, 4.243127373289958676e-02f, 4.422757557670908835e-02f, 4.565108540542069104e-02f, 0.000000000000000000e+00f, 5.248035000733364611e-03f, 1.481567994456567047e-02f, 2.413389556736813407e-02f, 3.188929233515737371e-02f, 3.800301313475547976e-02f, 4.274262540563071588e-02f, 4.641334665795533027e-02f, 4.927350398863060421e-02f, 5.152275429342469820e-02f, 5.331031390248602841e-02f, 0.000000000000000000e+00f, 5.405496525820404664e-03f, 1.564801264267183870e-02f, 2.598681309218115604e-02f, 3.482120856979355195e-02f, 4.191118616424213683e-02f, 4.747363860785879658e-02f, 5.181659128966996375e-02f, 5.521960355379183089e-02f, 5.790653639116814105e-02f, 6.004825723819562366e-02f, 0.000000000000000000e+00f, 5.519721114539997281e-03f, 1.628064506019030397e-02f, 2.744943573409894255e-02f, 3.720313374981960158e-02f, 4.515400169935586405e-02f, 5.145999443455393646e-02f, 5.642095558640027736e-02f, 6.032922389709499678e-02f, 6.342720140861805855e-02f, 6.590376215915122460e-02f, 0.000000000000000000e+00f, 5.604807172925481938e-03f, 1.676878494454391022e-02f, 2.861211162654109935e-02f, 3.914175575307056454e-02f, 4.784084480994308525e-02f, 5.480714130841123771e-02f, 6.032558356131666188e-02f, 6.469486252637586532e-02f, 6.817107846412569228e-02f, 7.095772783148365792e-02f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 9.146083830287583642e-04f, 1.579466856061922161e-03f, 2.029488185763906292e-03f, 2.350141314220413613e-03f, 2.585532485783417593e-03f, 2.762039714184235176e-03f, 2.896705517765219007e-03f, 3.001026726814950626e-03f, 3.082973043715643222e-03f, 3.148178209924899686e-03f, 0.000000000000000000e+00f, 2.381923649558957169e-03f, 4.771564976138984587e-03f, 6.477660849154662052e-03f, 7.710637905019568188e-03f, 8.621560397996115566e-03f, 9.307164465156857192e-03f, 9.831533372309179952e-03f, 1.023844968121729107e-02f, 1.055849739339442817e-02f, 1.081340653973560974e-02f, 0.000000000000000000e+00f, 3.535394475345355822e-03f, 8.041696433516517042e-03f, 1.155489757345273122e-02f, 1.417049695167621123e-02f, 1.612711144661847784e-02f, 1.760921674056959568e-02f, 1.874710505678665179e-02f, 1.963233381291838026e-02f, 2.032980615371487304e-02f, 2.088603811178604483e-02f, 0.000000000000000000e+00f, 4.305761889290633283e-03f, 1.076538989099030258e-02f, 1.627663864269695074e-02f, 2.055251087807164270e-02f, 2.381497047720437799e-02f, 2.631238608553041619e-02f, 2.824170594523811931e-02f, 2.974859390027098302e-02f, 3.093907698776395335e-02f, 3.189031186244749294e-02f, 0.000000000000000000e+00f, 4.806493448779084431e-03f, 1.285280603117577684e-02f, 2.026429933233919040e-02f, 2.626995208535578760e-02f, 3.096391948219001308e-02f, 3.460749201784794199e-02f, 3.744638174270890907e-02f, 3.967603736834866834e-02f, 4.144423551014510959e-02f, 4.286092010174952921e-02f, 0.000000000000000000e+00f, 5.137662194585928405e-03f, 1.440720060696200518e-02f, 2.347862141063761232e-02f, 3.112856878432999561e-02f, 3.725816810538268992e-02f, 4.209069272126627487e-02f, 4.589397915749048040e-02f, 4.890130600633454949e-02f, 5.129749328254108037e-02f, 5.322387085040267835e-02f, 0.000000000000000000e+00f, 5.363429462624667160e-03f, 1.556110912888218796e-02f, 2.601869761382172297e-02f, 3.514450605321959437e-02f, 4.262920439588310795e-02f, 4.862302407365758777e-02f, 5.339053744130816542e-02f, 5.718817021170410214e-02f, 6.023003236992537784e-02f, 6.268496109512571024e-02f, 0.000000000000000000e+00f, 5.522343068669122342e-03f, 1.642522820790207408e-02f, 2.801586174906607260e-02f, 3.842179910921796060e-02f, 4.713538023233512786e-02f, 5.421668062745129552e-02f, 5.990809922566721346e-02f, 6.447563789424214098e-02f, 6.815420154092251270e-02f, 7.113509806267460933e-02f, 0.000000000000000000e+00f, 5.637584583779466779e-03f, 1.708127107996294802e-02f, 2.959086256581842239e-02f, 4.108621225472355171e-02f, 5.088622500212632016e-02f, 5.895706762814859753e-02f, 6.550738910549069871e-02f, 7.080215473675173510e-02f, 7.508935702281148428e-02f, 7.857763544664297939e-02f, 0.000000000000000000e+00f, 5.723409014370593739e-03f, 1.758704298274597899e-02f, 3.084188567563100197e-02f, 4.325572603690309298e-02f, 5.400162213255688126e-02f, 6.295602341423879589e-02f, 7.028825445802376615e-02f, 7.625490487763730840e-02f, 8.111082141276432234e-02f, 8.507736160994681940e-02f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 0.000000000000000000e+00f, 9.407175649717369140e-04f, 1.646344177610784259e-03f, 2.133022545851611784e-03f, 2.486368129260723737e-03f, 2.750626368692035174e-03f, 2.952322151141739161e-03f, 3.108750693981697597e-03f, 3.231745439960234754e-03f, 3.329650157514978896e-03f, 3.408471310692032588e-03f, 0.000000000000000000e+00f, 2.435828950196621163e-03f, 4.974727915303407688e-03f, 6.835291369405445752e-03f, 8.206972502698303001e-03f, 9.239229846344653926e-03f, 1.002978347962796626e-02f, 1.064423803298986983e-02f, 1.112808885472833624e-02f, 1.151365936870699970e-02f, 1.182433136920202181e-02f, 0.000000000000000000e+00f, 3.602555256674739963e-03f, 8.368077737178299114e-03f, 1.221054718799924679e-02f, 1.514283600888060091e-02f, 1.738166808092690349e-02f, 1.910867140094551359e-02f, 2.045652908204030271e-02f, 2.152068013770556260e-02f, 2.237019693720150235e-02f, 2.305557241678675082e-02f, 0.000000000000000000e+00f, 4.379251827572607468e-03f, 1.117978193107454360e-02f, 1.720234016040313521e-02f, 2.201620195010858469e-02f, 2.577798151457473541e-02f, 2.871637658705877144e-02f, 3.102661519549590463e-02f, 3.285907988714027728e-02f, 3.432651952566168757e-02f, 3.551303224345320891e-02f, 0.000000000000000000e+00f, 4.883336402690426417e-03f, 1.332632627032051542e-02f, 2.140812375876842075e-02f, 2.818059142001937828e-02f, 3.362163715849737083e-02f, 3.794276055337758580e-02f, 4.137547846997025047e-02f, 4.411681001711743877e-02f, 4.632228985032173924e-02f, 4.811145835127387388e-02f, 0.000000000000000000e+00f, 5.216458452347733261e-03f, 1.492052170740058165e-02f, 2.479039304084246567e-02f, 3.341922235530064150e-02f, 4.054846000436074238e-02f, 4.631490055836424286e-02f, 5.095191227795443922e-02f, 5.468596768919504331e-02f, 5.770784088044408899e-02f, 6.016979812822989548e-02f, 0.000000000000000000e+00f, 5.443452390953965048e-03f, 1.610184242266437388e-02f, 2.745791860035587395e-02f, 3.774735773987216575e-02f, 4.647087682887238863e-02f, 5.365611441928514608e-02f, 5.950828411399150530e-02f, 6.426398211234400637e-02f, 6.813822608265847347e-02f, 7.131020298760183673e-02f, 0.000000000000000000e+00f, 5.603182869318606638e-03f, 1.698537988167880472e-02f, 2.955196761958390692e-02f, 4.127727827674304573e-02f, 5.144592380528976300e-02f, 5.996410190786041067e-02f, 6.698880813872078177e-02f, 7.275015724326128197e-02f, 7.747610674357763294e-02f, 8.136570783515832683e-02f, 0.000000000000000000e+00f, 5.718994165839363757e-03f, 1.765556418075154080e-02f, 3.120130665078258217e-02f, 4.414527445525694149e-02f, 5.559042754703297923e-02f, 6.532404806963165722e-02f, 7.344467067117703418e-02f, 8.016402447511272733e-02f, 8.571334926782668562e-02f, 9.030469447376583692e-02f, 0.000000000000000000e+00f, 5.805231126591313059e-03f, 1.817189858907889560e-02f, 3.251008336421949002e-02f, 4.647919386144636761e-02f, 5.903462270333981188e-02f, 6.985498102082771110e-02f, 7.897742990674293251e-02f, 8.658805699566379799e-02f, 9.291411037656233107e-02f, 9.817477042468102100e-02f}; float sampleCylSolidAngleTable(float u, float v, float w) { if (u > 1.f) u = 1.f; if (v > 1.f) v = 1.f; if (w > 1.f) w = 1.f; if (u <= 0.f || v <= 0.f || w <= 0.f) return 0.f; u *= 10.f; v *= 10.f; w *= 10.f; const int U0 = (int)u; const int V0 = (int)v; const int W0 = (int)w; const int U1 = U0 == 10 ? 10 : U0 + 1; const int V1 = V0 == 10 ? 10 : V0 + 1; const int W1 = W0 == 10 ? 10 : W0 + 1; u -= (float)U0; v -= (float)V0; w -= (float)W0; const float p00 = lerp(u, CylCapSolidAngleTable[121 * U0 + 11 * V0 + W0], CylCapSolidAngleTable[121 * U1 + 11 * V0 + W0]); const float p10 = lerp(u, CylCapSolidAngleTable[121 * U0 + 11 * V0 + W1], CylCapSolidAngleTable[121 * U1 + 11 * V0 + W1]); const float p0 = (1.f - w) * p00 + w * p10; const float p01 = lerp(u, CylCapSolidAngleTable[121 * U0 + 11 * V1 + W0], CylCapSolidAngleTable[121 * U1 + 11 * V1 + W0]); const float p11 = lerp(u, CylCapSolidAngleTable[121 * U0 + 11 * V1 + W1], CylCapSolidAngleTable[121 * U1 + 11 * V1 + W1]); const float p1 = (1.f - w) * p01 + w * p11; return (1.f - v) * p0 + v * p1; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/CylinderLight.cpp000066400000000000000000000060131456566705700243450ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "CylinderLight.h" #include "common/StructShared.h" #ifndef OSPRAY_TARGET_SYCL #include "lights/CylinderLight_ispc.h" #else namespace ispc { void CylinderLight_Transform(const void *self, const void *xfm, void *dyn); void *CylinderLight_sample_addr(); void *CylinderLight_sample_instanced_addr(); void *CylinderLight_eval_addr(); void *CylinderLight_eval_instanced_addr(); } // namespace ispc #endif #include "CylinderLightShared.h" #include "common/InstanceShared.h" namespace ospray { ISPCRTMemoryView CylinderLight::createSh( uint32_t, const ispc::Instance *instance) const { ISPCRTMemoryView view = StructSharedCreate( getISPCDevice().getIspcrtContext().handle()); ispc::CylinderLight *sh = (ispc::CylinderLight *)ispcrtSharedPtr(view); #ifndef OSPRAY_TARGET_SYCL sh->super.sample = reinterpret_cast( ispc::CylinderLight_sample_addr()); sh->super.eval = reinterpret_cast(ispc::CylinderLight_eval_addr()); #endif sh->super.isVisible = visible; sh->super.instance = instance; const float zMax = length(position1 - position0); if (zMax <= 0.f || radius <= 0.f) { sh->radiance = 0.f; return view; } sh->radiance = radiance; sh->radius = radius; sh->pre.position0 = position0; sh->pre.position1 = position1; // Enable dynamic runtime instancing or apply static transformation if (instance) { if (instance->motionBlur) { #ifndef OSPRAY_TARGET_SYCL sh->super.sample = reinterpret_cast( ispc::CylinderLight_sample_instanced_addr()); sh->super.eval = reinterpret_cast( ispc::CylinderLight_eval_instanced_addr()); #endif } else ispc::CylinderLight_Transform(sh, instance->xfm, &sh->pre); } return view; } std::string CylinderLight::toString() const { return "ospray::CylinderLight"; } void CylinderLight::commit() { Light::commit(); position0 = getParam("position0", vec3f(0.f)); position1 = getParam("position1", vec3f(0.f, 0.f, 1.f)); radius = getParam("radius", 1.f); queryIntensityQuantityType(OSP_INTENSITY_QUANTITY_RADIANCE); processIntensityQuantityType(); } void CylinderLight::processIntensityQuantityType() { float cylinderArea = 2.f * M_PI * length(position1 - position0) * radius; radiance = vec3f(0.0f); /// converting from the chosen intensity quantity type to radiance if (intensityQuantity == OSP_INTENSITY_QUANTITY_POWER) { if (cylinderArea > 0.f) radiance = coloredIntensity / (M_PI * cylinderArea); } else if (intensityQuantity == OSP_INTENSITY_QUANTITY_INTENSITY) { if (cylinderArea > 0.f) radiance = M_PI * coloredIntensity / cylinderArea; } else if (intensityQuantity == OSP_INTENSITY_QUANTITY_RADIANCE) { radiance = coloredIntensity; } else { postStatusMsg(OSP_LOG_WARNING) << toString() << " unsupported 'intensityQuantity' value"; } } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/CylinderLight.h000066400000000000000000000015361456566705700240170ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Light.h" namespace ospray { /*! a CylinderLight is a virtual area light uniformly emitting from a * cylindrical area into outward space */ struct OSPRAY_SDK_INTERFACE CylinderLight : public Light { CylinderLight(api::ISPCDevice &device) : Light(device, FFO_LIGHT_CYLINDER) {} virtual ~CylinderLight() override = default; virtual ISPCRTMemoryView createSh( uint32_t, const ispc::Instance *instance = nullptr) const override; virtual std::string toString() const override; virtual void commit() override; private: void processIntensityQuantityType(); vec3f position0{0.f}; // start of the cylinder vec3f position1{0.f, 0.f, 1.f}; // end of the cylinder vec3f radiance{1.0f, 1.0f, 1.0f}; float radius{1.f}; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/CylinderLight.ih000066400000000000000000000017501456566705700241660ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "lights/LightShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL Light_SampleRes CylinderLight_sample(const Light *uniform super, const DifferentialGeometry &dg, const vec2f &sp, const float, const uniform FeatureFlagsHandler &); SYCL_EXTERNAL Light_SampleRes CylinderLight_sample_instanced( const Light *uniform super, const DifferentialGeometry &dg, const vec2f &sp, const float time, const uniform FeatureFlagsHandler &); SYCL_EXTERNAL Light_EvalRes CylinderLight_eval(const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float); SYCL_EXTERNAL Light_EvalRes CylinderLight_eval_instanced( const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float time); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/CylinderLight.ispc000066400000000000000000000200521456566705700245200ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "CylinderCapSolidAngleTable.ih" #include "SphericalQuadSampling.ih" #include "common/DifferentialGeometry.ih" #include "common/Instance.ih" #include "common/Intersect.ih" #include "rkcommon/math/AffineSpace.ih" // c++ shared #include "CylinderLightShared.h" // Implementation ////////////////////////////////////////////////////////////////////////////// OSPRAY_BEGIN_ISPC_NAMESPACE inline void Transform(const CylinderLight *uniform self, const uniform affine3f &xfm, uniform CylinderLightDynamic &dyn) { dyn.position0 = xfmPoint(xfm, self->pre.position0); dyn.position1 = xfmPoint(xfm, self->pre.position1); } export void CylinderLight_Transform( const void *uniform self, const void *uniform xfm, void *uniform dyn) { Transform((CylinderLight * uniform) self, *((affine3f * uniform) xfm), *((CylinderLightDynamic * uniform) dyn)); } inline float cylinderAxialSolidAngle( float c, float b, float h0, float h1, float b2c2) { return 2.f * atan(c * h1 / (b * sqrt(b2c2 + sqr(h1)))) - 2.f * atan(c * h0 / (b * sqrt(b2c2 + sqr(h0)))); } inline float cylinderCapSolidAngle(float d, float R, float h) { const float dmR = d - R; const float dpR = d + R; const float dmR2 = dmR * dmR; const float R2 = R * R; const float h2 = h * h; const float u = sqrt(dmR / dpR); const float v = sqrt((dmR2 + h2) / (d * d - R2 + h2)); const float w = sqrt((dmR2 + h2) / (dpR * dpR + h2)); const float integral = sampleCylSolidAngleTable(u, v, w); const float recip = sqrt(dmR2 + h2); return (16.f * R2 * h / (recip * recip * recip)) * integral; } inline void cylinderComputeRectBounds(const uniform vec3f &position0, const uniform vec3f &position1, const uniform float radius, const vec3f &P, vec3f &q0, vec3f &e0, vec3f &e1, float &S) { // construct geometry of cylinder from sample point vec3f O = position0; vec3f Z = position1 - position0; const float H = length(Z); Z = Z / H; vec3f Dp = P - O; float h0 = -dot(Dp, Z); // flip origin if end of cylinder is closer to sample point if (h0 < -H) { O = position1; Z = -1.f * Z; Dp = P - O; h0 = -dot(Dp, Z); } const vec3f D = -h0 * Z - Dp; const float d = length(D); const float srad = min(radius / d, 1.f); const float q = max(1.f - sqr(srad), 4.e-6f); const float b = d * q; const float c = radius * sqrt(q); const float b2c2 = sqr(b) + sqr(c); const vec3f X = normalize(cross(D, Z)); const float h1 = (1.f + srad) * (h0 + H); // compute the bounding rectangle of the cylinder const float hO = h0 < 0.f ? (1.f + srad) * h0 : h0; q0 = P + D * q - c * X + hO * Z; e0 = 2.f * c * X; e1 = (h1 - hO) * Z; // compute solid angle of cylinder at sample point S = cylinderAxialSolidAngle(c, b, hO, h1, b2c2); } inline void cylinderSampleSolidAngle(const DifferentialGeometry &dg, const vec2f &sp, const uniform vec3f &position0, const uniform vec3f &position1, const uniform float radius, vec3f &dir, float &pdf, float &S) { // compute spherical quad bounding cylinder vec3f q0, e0, e1; cylinderComputeRectBounds(position0, position1, radius, dg.P, q0, e0, e1, S); const vec3f n = normalize(cross(e0, e1)); SphericalQuad quad = SphericalQuad_create(q0, e0, e1, n, dg.P); // warped samples in solid angle space const vec3f cosW = computeCosineWeightedRNG(q0, e0, e1, dg.P, dg.Ng, sp); // sample spherical quad bounding cylinder dir = sampleSphericalQuad(quad, make_vec2f(cosW.x, cosW.y)); pdf = cosW.z; } inline Light_SampleRes Sample(const CylinderLight *uniform self, const uniform CylinderLightDynamic &dyn, const DifferentialGeometry &dg, const vec2f &sp) { Light_SampleRes res; res.weight = make_vec3f(0.f); res.pdf = 0.f; float S = 0.f; float pdf = 0.f; vec3f dir; if (sp.x == 0.0f && sp.y == 0.0f) { // XXX SciVis dir = 0.5f * (dyn.position0 + dyn.position1) - dg.P; // to center vec3f q0, e0, e1; cylinderComputeRectBounds( dyn.position0, dyn.position1, self->radius, dg.P, q0, e0, e1, S); if (S > 0.f) { pdf = 1.f; } } else { cylinderSampleSolidAngle( dg, sp, dyn.position0, dyn.position1, self->radius, dir, pdf, S); } if (S <= 0.f || pdf == 0.f) { return res; } res.dir = normalize(dir); // rejection sampling of the cylinder sample direction (through out cap hits // and rare misses) Intersections isect = intersectCylinder( dg.P, res.dir, dyn.position0, dyn.position1, self->radius); if (isect.entry.hit) { res.pdf = pdf / S; res.weight = self->radiance * rcp(res.pdf); res.dist = isect.entry.t; } return res; } SYCL_EXTERNAL Light_SampleRes CylinderLight_sample( const uniform Light *uniform super, const DifferentialGeometry &dg, const vec2f &s, const float, const uniform FeatureFlagsHandler &) { const CylinderLight *uniform self = (CylinderLight * uniform) super; assert(self); return Sample(self, self->pre, dg, s); } SYCL_EXTERNAL Light_SampleRes CylinderLight_sample_instanced( const Light *uniform super, const DifferentialGeometry &dg, const vec2f &s, const float time, const uniform FeatureFlagsHandler &) { const CylinderLight *uniform self = (CylinderLight * uniform) super; assert(self); const Instance *uniform instance = self->super.instance; assert(instance); Light_SampleRes res; foreach_unique (utime in time) { const uniform affine3f xfm = Instance_getTransform(instance, utime); uniform CylinderLightDynamic dyn; Transform(self, xfm, dyn); res = Sample(self, dyn, dg, s); } return res; } inline Light_EvalRes Eval(const CylinderLight *uniform self, const uniform CylinderLightDynamic &dyn, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist) { Light_EvalRes res; res.radiance = make_vec3f(0.f); // check if intersecting cylinder Intersections isect = intersectCylinder(dg.P, dir, dyn.position0, dyn.position1, self->radius); if (isect.entry.hit) { if ((minDist < isect.entry.t && isect.entry.t <= maxDist)) { // compute bounding rectangle solid angle vec3f q0, e0, e1; float S; cylinderComputeRectBounds( dyn.position0, dyn.position1, self->radius, dg.P, q0, e0, e1, S); if (S > 0.f) { res.radiance = self->radiance; res.pdf = rcp(S); } } } return res; } SYCL_EXTERNAL Light_EvalRes CylinderLight_eval( const uniform Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float) { CylinderLight *uniform self = (CylinderLight * uniform) super; assert(self); return Eval(self, self->pre, dg, dir, minDist, maxDist); } SYCL_EXTERNAL Light_EvalRes CylinderLight_eval_instanced( const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float time) { const CylinderLight *uniform self = (CylinderLight * uniform) super; assert(self); const Instance *uniform instance = self->super.instance; assert(instance); Light_EvalRes res; foreach_unique (utime in time) { const uniform affine3f xfm = Instance_getTransform(instance, utime); uniform CylinderLightDynamic dyn; Transform(self, xfm, dyn); res = Eval(self, dyn, dg, dir, minDist, maxDist); } return res; } // Exports (called from C++) ////////////////////////////////////////////////////////////////////////////// export void *uniform CylinderLight_sample_addr() { return (void *uniform)CylinderLight_sample; } #ifndef OSPRAY_TARGET_SYCL export void *uniform CylinderLight_sample_instanced_addr() { return (void *uniform)CylinderLight_sample_instanced; } #endif export void *uniform CylinderLight_eval_addr() { return (void *uniform)CylinderLight_eval; } #ifndef OSPRAY_TARGET_SYCL export void *uniform CylinderLight_eval_instanced_addr() { return (void *uniform)CylinderLight_eval_instanced; } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/CylinderLightShared.h000066400000000000000000000012601456566705700251400ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "LightShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus // state that changes under transformations struct CylinderLightDynamic { vec3f position0; vec3f position1; #ifdef __cplusplus CylinderLightDynamic() : position0(0.f), position1(0.f, 0.f, 1.f) {} #endif }; struct CylinderLight { Light super; vec3f radiance; float radius; CylinderLightDynamic pre; // un- or pre-transformed state #ifdef __cplusplus CylinderLight() : radiance(1.f), radius(1.f) { super.type = LIGHT_TYPE_CYLINDER; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/lights/DirectionalLight.cpp000066400000000000000000000063311456566705700250340ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "DirectionalLight.h" #include "common/StructShared.h" #include "math/sampling.h" #ifndef OSPRAY_TARGET_SYCL // ispc exports #include "lights/DirectionalLight_ispc.h" #else namespace ispc { void *DirectionalLight_sample_addr(); void *DirectionalLight_sample_instanced_addr(); void *DirectionalLight_eval_addr(); void *DirectionalLight_eval_instanced_addr(); } // namespace ispc #endif // ispc shared #include "DirectionalLightShared.h" #include "common/InstanceShared.h" namespace ispc { void DirectionalLight::set(bool isVisible, const Instance *instance, const vec3f &direction, const vec3f &irradiance, float cosAngle) { super.isVisible = isVisible; super.instance = instance; #ifndef OSPRAY_TARGET_SYCL super.sample = reinterpret_cast( ispc::DirectionalLight_sample_addr()); super.eval = reinterpret_cast( ispc::DirectionalLight_eval_addr()); #endif frame = rkcommon::math::frame(direction); this->irradiance = irradiance; this->cosAngle = cosAngle; pdf = cosAngle < COS_ANGLE_MAX ? ospray::uniformSampleConePDF(cosAngle) : inf; // Enable dynamic runtime instancing or apply static transformation if (instance) { if (instance->motionBlur) { #ifndef OSPRAY_TARGET_SYCL super.sample = reinterpret_cast( ispc::DirectionalLight_sample_instanced_addr()); super.eval = reinterpret_cast( ispc::DirectionalLight_eval_instanced_addr()); #endif } else { frame = instance->xfm.l * frame; } } } } // namespace ispc namespace ospray { ISPCRTMemoryView DirectionalLight::createSh( uint32_t, const ispc::Instance *instance) const { ISPCRTMemoryView view = StructSharedCreate( getISPCDevice().getIspcrtContext().handle()); ispc::DirectionalLight *sh = (ispc::DirectionalLight *)ispcrtSharedPtr(view); sh->set(visible, instance, direction, irradiance, cosAngle); return view; } std::string DirectionalLight::toString() const { return "ospray::DirectionalLight"; } void DirectionalLight::commit() { Light::commit(); direction = getParam("direction", vec3f(0.f, 0.f, 1.f)); angularDiameter = getParam("angularDiameter", .0f); // the ispc::DirLight expects direction towards light source direction = -normalize(direction); angularDiameter = clamp(angularDiameter, 0.f, 180.f); cosAngle = std::cos(deg2rad(0.5f * angularDiameter)); queryIntensityQuantityType(OSP_INTENSITY_QUANTITY_IRRADIANCE); processIntensityQuantityType(); } void DirectionalLight::processIntensityQuantityType() { // validate the correctness of the light quantity type if (intensityQuantity == OSP_INTENSITY_QUANTITY_RADIANCE) { // convert from radiance to irradiance float cosineCapIntegral = 2.0f * M_PI * (1.0f - cosAngle); irradiance = cosineCapIntegral * coloredIntensity; } else if (intensityQuantity == OSP_INTENSITY_QUANTITY_IRRADIANCE) { irradiance = coloredIntensity; } else { postStatusMsg(OSP_LOG_WARNING) << toString() << " unsupported 'intensityQuantity' value"; irradiance = vec3f(0.0f); } } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/DirectionalLight.h000066400000000000000000000017571456566705700245100ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Light.h" namespace ospray { /*! a DirectionalLight is a singular light which is infinitely distant and * thus projects parallel rays of light across the entire scene */ struct OSPRAY_SDK_INTERFACE DirectionalLight : public Light { DirectionalLight(api::ISPCDevice &device) : Light(device, FFO_LIGHT_DIRECTIONAL) {} virtual ~DirectionalLight() override = default; virtual ISPCRTMemoryView createSh( uint32_t, const ispc::Instance *instance = nullptr) const override; virtual std::string toString() const override; virtual void commit() override; private: void processIntensityQuantityType(); vec3f irradiance{1.f}; vec3f direction{0.f, 0.f, 1.f}; //!< Direction of the emitted rays float angularDiameter{0.f}; //!< Apparent size of the distant light, in degree //!< (e.g. 0.53 for the sun) float cosAngle{1.f}; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/DirectionalLight.ih000066400000000000000000000017711456566705700246550ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "lights/LightShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL Light_SampleRes DirectionalLight_sample( const Light *uniform super, const DifferentialGeometry &dg, const vec2f &sp, const float, const uniform FeatureFlagsHandler &); SYCL_EXTERNAL Light_SampleRes DirectionalLight_sample_instanced( const Light *uniform super, const DifferentialGeometry &dg, const vec2f &sp, const float time, const uniform FeatureFlagsHandler &); SYCL_EXTERNAL Light_EvalRes DirectionalLight_eval(const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float); SYCL_EXTERNAL Light_EvalRes DirectionalLight_eval_instanced( const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float time); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/DirectionalLight.ispc000066400000000000000000000071321456566705700252100ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/Instance.ih" #include "math/sampling.ih" #include "rkcommon/math/LinearSpace.ih" // c++ shared #include "DirectionalLightShared.h" // Implementation ////////////////////////////////////////////////////////////////////////////// OSPRAY_BEGIN_ISPC_NAMESPACE inline Light_SampleRes Sample(const DirectionalLight *uniform self, const uniform linear3f &frame, const vec2f &s) { Light_SampleRes res; res.dir = frame.vz; res.dist = inf; res.pdf = self->pdf; if (self->cosAngle < COS_ANGLE_MAX) res.dir = frame * uniformSampleCone(self->cosAngle, s); res.weight = self->irradiance; // *pdf/pdf cancel return res; } SYCL_EXTERNAL Light_SampleRes DirectionalLight_sample( const Light *uniform super, const DifferentialGeometry &, const vec2f &s, const float, const uniform FeatureFlagsHandler &) { const DirectionalLight *uniform self = (DirectionalLight * uniform) super; assert(self); return Sample(self, self->frame, s); } SYCL_EXTERNAL Light_SampleRes DirectionalLight_sample_instanced( const Light *uniform super, const DifferentialGeometry &dg, const vec2f &s, const float time, const uniform FeatureFlagsHandler &) { const DirectionalLight *uniform self = (DirectionalLight * uniform) super; assert(self); const Instance *uniform instance = self->super.instance; assert(instance); Light_SampleRes res; foreach_unique (utime in time) { const uniform affine3f xfm = Instance_getTransform(instance, utime); res = Sample(self, xfm.l * self->frame, s); } return res; } inline Light_EvalRes Eval(const DirectionalLight *uniform self, const uniform linear3f &frame, const vec3f &dir, const float maxDist) { Light_EvalRes res; res.radiance = make_vec3f(0.f); if ((float)inf <= maxDist && self->cosAngle < COS_ANGLE_MAX && dot(frame.vz, dir) > self->cosAngle) { res.radiance = self->irradiance * self->pdf; res.pdf = self->pdf; } return res; } SYCL_EXTERNAL Light_EvalRes DirectionalLight_eval(const Light *uniform super, const DifferentialGeometry &, const vec3f &dir, const float, const float maxDist, const float) { const DirectionalLight *uniform self = (DirectionalLight * uniform) super; assert(self); return Eval(self, self->frame, dir, maxDist); } SYCL_EXTERNAL Light_EvalRes DirectionalLight_eval_instanced( const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float time) { const DirectionalLight *uniform self = (DirectionalLight * uniform) super; assert(self); const Instance *uniform instance = self->super.instance; assert(instance); Light_EvalRes res; foreach_unique (utime in time) { const uniform affine3f xfm = Instance_getTransform(instance, utime); res = Eval(self, xfm.l * self->frame, dir, maxDist); } return res; } // Exports (called from C++) ////////////////////////////////////////////////////////////////////////////// export void *uniform DirectionalLight_sample_addr() { return (void *uniform)DirectionalLight_sample; } #ifndef OSPRAY_TARGET_SYCL export void *uniform DirectionalLight_sample_instanced_addr() { return (void *uniform)DirectionalLight_sample_instanced; } #endif export void *uniform DirectionalLight_eval_addr() { return (void *uniform)DirectionalLight_eval; } #ifndef OSPRAY_TARGET_SYCL export void *uniform DirectionalLight_eval_instanced_addr() { return (void *uniform)DirectionalLight_eval_instanced; } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/DirectionalLightShared.h000066400000000000000000000020761456566705700256320ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "LightShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus // for very small cones treat as singular light, because float precision is not // good enough #define COS_ANGLE_MAX 0.99999988f struct DirectionalLight { Light super; // inherited light fields linear3f frame; // coordinate frame, with vz == direction *towards* the // light source vec3f irradiance; // RGB irradiance contribution of the light float cosAngle; // Angular limit of the cone light in an easier to use form: // cosine of the half angle in radians float pdf; // Probability to sample a direction to the light #ifdef __cplusplus DirectionalLight() : frame(one), irradiance(0.f), cosAngle(1.f), pdf(inf) { super.type = LIGHT_TYPE_DIRECTIONAL; } void set(bool isVisible, const Instance *instance, const vec3f &direction, const vec3f &irradiance, float cosAngle); }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/lights/HDRILight.cpp000066400000000000000000000062031456566705700233230ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "HDRILight.h" #include "common/StructShared.h" #ifndef OSPRAY_TARGET_SYCL // ispc exports #include "lights/HDRILight_ispc.h" #include "lights/Light_ispc.h" #else namespace ispc { void HDRILight_initDistribution(const void *map, void *distribution); } #endif // ispc shared #include "HDRILightShared.h" #include "common/InstanceShared.h" namespace ispc { void HDRILight::set(bool isVisible, const Instance *instance, const vec3f &radianceScale, const linear3f &light2world, const Texture2D *map, const Distribution2D *distribution) { super.isVisible = isVisible; super.instance = instance; #ifndef OSPRAY_TARGET_SYCL super.sample = reinterpret_cast(ispc::HDRILight_sample_addr()); super.eval = reinterpret_cast(ispc::HDRILight_eval_addr()); #endif this->radianceScale = radianceScale; this->map = map; this->distribution = distribution; this->rcpSize = 1.f / this->map->sizef; this->light2world = light2world; // Enable dynamic runtime instancing or apply static transformation if (instance) { if (instance->motionBlur) { #ifndef OSPRAY_TARGET_SYCL super.sample = reinterpret_cast( ispc::HDRILight_sample_instanced_addr()); super.eval = reinterpret_cast( ispc::HDRILight_eval_instanced_addr()); #endif } else { this->light2world = instance->xfm.l * this->light2world; } } world2light = rcp(this->light2world); } } // namespace ispc namespace ospray { ISPCRTMemoryView HDRILight::createSh( uint32_t, const ispc::Instance *instance) const { ISPCRTMemoryView view = StructSharedCreate( getISPCDevice().getIspcrtContext().handle()); ispc::HDRILight *sh = (ispc::HDRILight *)ispcrtSharedPtr(view); sh->set(visible, instance, coloredIntensity, frame, map->getSh(), distribution->getSh()); return view; } std::string HDRILight::toString() const { return "ospray::HDRILight"; } void HDRILight::commit() { Light::commit(); const vec3f up = getParam("up", vec3f(0.f, 1.f, 0.f)); const vec3f dir = getParam("direction", vec3f(0.f, 0.f, 1.f)); map = getParamObject("map"); if (!map) throw std::runtime_error(toString() + " must have 'map'"); // recreate distribution distribution = new Distribution2D(map->getSh()->size, getISPCDevice()); distribution->refDec(); // Release extra local ref ispc::HDRILight_initDistribution(map->getSh(), distribution->getSh()); frame.vx = normalize(-dir); frame.vy = normalize(cross(frame.vx, up)); frame.vz = cross(frame.vx, frame.vy); queryIntensityQuantityType(OSP_INTENSITY_QUANTITY_SCALE); processIntensityQuantityType(); } void HDRILight::processIntensityQuantityType() { // validate the correctness of the light quantity type if (intensityQuantity != OSP_INTENSITY_QUANTITY_SCALE) { postStatusMsg(OSP_LOG_WARNING) << toString() << " unsupported 'intensityQuantity' value"; coloredIntensity = vec3f(0.0f); } } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/HDRILight.h000066400000000000000000000012661456566705700227740ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Light.h" #include "math/Distribution2D.h" #include "texture/Texture2D.h" namespace ospray { struct OSPRAY_SDK_INTERFACE HDRILight : public Light { HDRILight(api::ISPCDevice &device) : Light(device, FFO_LIGHT_HDRI) {} virtual ISPCRTMemoryView createSh( uint32_t, const ispc::Instance *instance = nullptr) const override; virtual std::string toString() const override; virtual void commit() override; private: void processIntensityQuantityType(); linear3f frame{one}; // light orientation Ref map; Ref distribution; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/HDRILight.ih000066400000000000000000000017231456566705700231430ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "lights/LightShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL Light_SampleRes HDRILight_sample(const Light *uniform super, const DifferentialGeometry &dg, const vec2f &sp, const float, const uniform FeatureFlagsHandler &); SYCL_EXTERNAL Light_SampleRes HDRILight_sample_instanced( const Light *uniform super, const DifferentialGeometry &dg, const vec2f &sp, const float time, const uniform FeatureFlagsHandler &); SYCL_EXTERNAL Light_EvalRes HDRILight_eval(const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float); SYCL_EXTERNAL Light_EvalRes HDRILight_eval_instanced(const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float time); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/HDRILight.ispc000066400000000000000000000160701456566705700235020ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/Instance.ih" #include "math/Distribution1D.ih" #include "math/Distribution2D.ih" #include "math/sampling.ih" #include "rkcommon/math/LinearSpace.ih" #include "texture/Texture2D.ih" // c++ shared #include "HDRILightShared.h" // Implementation ////////////////////////////////////////////////////////////////////////////// OSPRAY_BEGIN_ISPC_NAMESPACE inline Light_SampleRes Sample(const HDRILight *uniform self, const uniform linear3f &light2world, const vec2f &s) { Light_SampleRes res; Sample2D sample2d = Distribution2D_sample(self->distribution, s); // Distribution2D samples within bin i as (i, i+1), whereas we provided // average importance for (i-0.5, i+0.5), thus shift by 0.5 sample2d.uv = sample2d.uv - self->map->halfTexel; const float phi = (float)two_pi * sample2d.uv.x; const float theta = (float)pi * sample2d.uv.y; float sinTheta, cosTheta; sincos(theta, &sinTheta, &cosTheta); const vec3f localDir = cartesian(phi, sinTheta, cosTheta); res.dir = light2world * localDir; res.pdf = sample2d.pdf * (float)one_over_two_pi_sqr * rcp(sinTheta); res.dist = inf; // clamp2edge for theta for tex lookup, to prevent light leaks at the poles sample2d.uv.y = clamp( sample2d.uv.y, self->map->halfTexel.y, 1.0f - self->map->halfTexel.y); DifferentialGeometry lookup; initDgFromTexCoord(lookup, sample2d.uv); res.weight = get3f(self->map, lookup) * self->radianceScale / res.pdf; return res; } SYCL_EXTERNAL Light_SampleRes HDRILight_sample(const Light *uniform super, const DifferentialGeometry &, const vec2f &s, const float, const uniform FeatureFlagsHandler &) { const HDRILight *uniform self = (HDRILight * uniform) super; assert(self); return Sample(self, self->light2world, s); } SYCL_EXTERNAL Light_SampleRes HDRILight_sample_instanced( const Light *uniform super, const DifferentialGeometry &, const vec2f &s, const float time, const uniform FeatureFlagsHandler &) { const HDRILight *uniform self = (HDRILight * uniform) super; assert(self); const Instance *uniform instance = self->super.instance; assert(instance); Light_SampleRes res; foreach_unique (utime in time) { const uniform affine3f xfm = Instance_getTransform(instance, utime); res = Sample(self, xfm.l * self->light2world, s); } return res; } inline Light_EvalRes Eval(const HDRILight *uniform self, const uniform linear3f &world2light, const vec3f &dir, const float maxDist) { Light_EvalRes res; res.radiance = make_vec3f(0.f); if ((float)inf > maxDist) return res; const vec3f localDir = world2light * dir; const float u = atan2(localDir.y, localDir.x) * (float)one_over_two_pi; const float v = acos(clamp(localDir.z, -1.f, 1.f)) * (float)one_over_pi; // clamp2edge for theta for tex lookup, to prevent light leaks at the poles const vec2f uvc = make_vec2f( u, clamp(v, self->map->halfTexel.y, 1.0f - self->map->halfTexel.y)); DifferentialGeometry lookup; initDgFromTexCoord(lookup, uvc); res.radiance = get3f(self->map, lookup) * self->radianceScale; // domain of Distribution2D is shifted by half a texel compared to texture vec2f uv = uvc + self->map->halfTexel; // atan2 can get negative, shift can lead to values > 1.f: reproject to [0..1) uv.x = frac(uv.x); res.pdf = Distribution2D_pdf(self->distribution, uv); res.pdf *= (float)one_over_two_pi_sqr * rsqrt(1.f - sqr(localDir.z)); return res; } SYCL_EXTERNAL Light_EvalRes HDRILight_eval(const Light *uniform super, const DifferentialGeometry &, const vec3f &dir, const float, const float maxDist, const float) { const HDRILight *uniform self = (HDRILight * uniform) super; assert(self); return Eval(self, self->world2light, dir, maxDist); } SYCL_EXTERNAL Light_EvalRes HDRILight_eval_instanced(const Light *uniform super, const DifferentialGeometry &, const vec3f &dir, const float, const float maxDist, const float time) { const HDRILight *uniform self = (HDRILight * uniform) super; assert(self); const Instance *uniform instance = self->super.instance; assert(instance); Light_EvalRes res; foreach_unique (utime in time) { const uniform affine3f xfm = Instance_getTransform(instance, utime); res = Eval(self, self->world2light * rcp(xfm.l), dir, maxDist); } return res; } // bin i represents the average contribution of (i-0.5, i+0.5) when we sample // the texture bilinearly at i // for i==0 we have a wrap-around, which is wanted for x (phi), but actually // not for y (theta), because then light (importance) from the south-pole is // leaking to the north-pole // however, sin(theta) is zero then, thus we will never sample there #ifndef OSPRAY_TARGET_SYCL task #endif unmasked void HDRILight_calcRowImportance(const Texture2D *uniform const map, float *uniform const importance, float *uniform const row_importance #ifdef OSPRAY_TARGET_SYCL , const int taskIndex #endif ) { const uniform int y = taskIndex; const uniform vec2f rcpSize = 1.f / map->sizef; const uniform float fy = y * rcpSize.y; const uniform int width = map->size.x; const uniform float sinTheta = sin(fy * M_PI); #ifdef OSPRAY_TARGET_SYCL for (int x = 0; x < width; ++x) { #else foreach (x = 0 ... width) { #endif const vec2f coord = make_vec2f(x * rcpSize.x, fy); // using bilinear filtering is indeed what we want DifferentialGeometry lookup; initDgFromTexCoord(lookup, coord); const vec3f col = get3f(map, lookup); importance[y * width + x] = sinTheta * luminance(col); } row_importance[y] = Distribution1D_create(width, importance + y * width); } // Exports (called from C++) ////////////////////////////////////////////////////////////////////////////// export void *uniform HDRILight_sample_addr() { return (void *uniform)HDRILight_sample; } #ifndef OSPRAY_TARGET_SYCL export void *uniform HDRILight_sample_instanced_addr() { return (void *uniform)HDRILight_sample_instanced; } #endif export void *uniform HDRILight_eval_addr() { return (void *uniform)HDRILight_eval; } #ifndef OSPRAY_TARGET_SYCL export void *uniform HDRILight_eval_instanced_addr() { return (void *uniform)HDRILight_eval_instanced; } #endif export void HDRILight_initDistribution( const void *uniform _map, void *uniform _distribution) { // calculate importance in parallel const Texture2D *uniform m = (const Texture2D *uniform)_map; Distribution2D *uniform distribution = (Distribution2D * uniform) _distribution; const uniform int height = m->size.y; float *uniform cdf_x = distribution->cdf_x; float *uniform row_importance = distribution->cdf_y; #ifdef OSPRAY_TARGET_SYCL // TODO: Should become a kernel launch in SYCL for (int i = 0; i < height; ++i) { HDRILight_calcRowImportance(m, cdf_x, row_importance, i); } #else launch[height] HDRILight_calcRowImportance(m, cdf_x, row_importance); sync; #endif // Initialize the distribution with the computed cdf/f values Distribution2D_init(distribution); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/HDRILightShared.h000066400000000000000000000020421456566705700241140ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "LightShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Texture2D; struct Distribution2D; struct HDRILight { Light super; linear3f light2world; linear3f world2light; const Texture2D *map; // Environment map in latitude / longitude format const Distribution2D *distribution; // The 2D distribution used to importance sample vec2f rcpSize; // precomputed 1/map.size vec3f radianceScale; // scaling factor of emitted RGB radiance #ifdef __cplusplus HDRILight() : light2world(one), world2light(one), map(nullptr), distribution(nullptr), rcpSize(0.f), radianceScale(1.f) { super.type = LIGHT_TYPE_HDRI; } void set(bool isVisible, const Instance *instance, const vec3f &radianceScale, const linear3f &light2world, const Texture2D *map, const Distribution2D *distribution); }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/lights/IntensityDistribution.cpp000066400000000000000000000026041456566705700261740ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "IntensityDistribution.h" #include "IntensityDistributionShared.h" namespace ospray { void IntensityDistribution::readParams(ISPCDeviceObject &obj) { c0 = obj.getParam("c0", c0); lid = obj.getParamDataT("intensityDistribution"); if (lid) { if (lid->numItems.z > 1) throw std::runtime_error(obj.toString() + " must have (at most 2D) 'intensityDistribution' array using the first two dimensions."); size = vec2i(lid->numItems.x, lid->numItems.y); if (size.x < 2) throw std::runtime_error(obj.toString() + " 'intensityDistribution' must have data for at least two gamma angles."); if (!lid->compact()) { postStatusMsg(OSP_LOG_WARNING) << obj.toString() << " does currently not support strides for 'intensityDistribution', copying data."; const auto data = new Data(obj.getISPCDevice(), OSP_FLOAT, lid->numItems); data->copy(*lid, vec3ui(0)); lid = &(data->as()); data->refDec(); } } } void IntensityDistribution::setSh(ispc::IntensityDistribution &sh) const { sh.lid = lid ? lid->data() : nullptr; sh.size = size; sh.scale.x = nextafter(float(size.x - 1) * float(one_over_pi), -1.0f); sh.scale.y = nextafter(float(size.y) * float(one_over_two_pi), -1.0f); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/IntensityDistribution.h000066400000000000000000000010211456566705700256310ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/Data.h" namespace ispc { struct IntensityDistribution; } namespace ospray { struct OSPRAY_SDK_INTERFACE IntensityDistribution { void readParams(ISPCDeviceObject &); operator bool() const { return lid; } void setSh(ispc::IntensityDistribution &sh) const; vec2i size{0}; vec3f c0{1.f, 0.f, 0.f}; private: Ref> lid; // luminous intensity distribution }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/IntensityDistribution.ih000066400000000000000000000023571456566705700260170ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/vec.ih" // c++ shared #include "IntensityDistributionShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE inline float IntensityDistribution_eval( const IntensityDistribution *uniform self, const uniform vec3f &c0, const uniform vec3f &c90, float cosAngle, const vec3f &dir /*normalized*/) { const float u = acos(clamp(cosAngle, -1.f, 1.f)) * self->scale.x; const float u_frac = frac(u); const int u0 = u; const int u1 = (u0 + 2 >= self->size.x) ? self->size.x - 1 : u0 + 1; float intensity; if (self->size.y == 1) { // 1D intensity = lerp(u_frac, self->lid[u0], self->lid[u1]); } else { // 2D const float v = (atan2(dot(dir, c90), dot(dir, c0)) + (float)pi) * self->scale.y; const float v_frac = frac(v); const int v0 = v; const int v1 = (v0 + 1 >= self->size.y) ? 0 : v0 + 1; const int r0 = v0 * self->size.x; const int r1 = v1 * self->size.x; const float li0 = lerp(u_frac, self->lid[r0 + u0], self->lid[r0 + u1]); const float li1 = lerp(u_frac, self->lid[r1 + u0], self->lid[r1 + u1]); intensity = lerp(v_frac, li0, li1); } return intensity; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/IntensityDistributionShared.h000066400000000000000000000006161456566705700267710ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct IntensityDistribution { float *lid; // luminance intensity distribution vec2i size; vec2f scale; #ifdef __cplusplus IntensityDistribution() : lid{nullptr}, size(0), scale(1.f) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/lights/Light.cpp000066400000000000000000000016121456566705700226530ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Light.h" #ifndef OSPRAY_TARGET_SYCL #include "lights/Light_ispc.h" #endif namespace ospray { // Light definitions ////////////////////////////////////////////////////////// Light::Light(api::ISPCDevice &device, const FeatureFlagsOther ffo) : ISPCDeviceObject(device), featureFlags(ffo) { managedObjectType = OSP_LIGHT; } void Light::commit() { visible = getParam("visible", true); coloredIntensity = getParam("color", vec3f(1.f)) * getParam("intensity", 1.f); } std::string Light::toString() const { return "ospray::Light"; } void Light::queryIntensityQuantityType(const OSPIntensityQuantity &defaultIQ) { intensityQuantity = (OSPIntensityQuantity)getParam("intensityQuantity", defaultIQ); } OSPTYPEFOR_DEFINITION(Light *); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/Light.h000066400000000000000000000026221456566705700223220ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ISPCDeviceObject.h" #include "common/FeatureFlagsEnum.h" #include "common/ObjectFactory.h" #include "ispcrt.h" namespace ispc { struct Light; struct Instance; } // namespace ispc namespace ospray { //! Base class for Light objects struct OSPRAY_SDK_INTERFACE Light : public ISPCDeviceObject, public ObjectFactory { Light(api::ISPCDevice &device, const FeatureFlagsOther ffo); virtual ~Light() override = default; virtual uint32_t getShCount() const; virtual ISPCRTMemoryView createSh( uint32_t index, const ispc::Instance *instance = nullptr) const = 0; virtual void commit() override; virtual std::string toString() const override; bool visible{true}; vec3f coloredIntensity{1.0f, 1.0f, 1.0f}; OSPIntensityQuantity intensityQuantity = OSP_INTENSITY_QUANTITY_UNKNOWN; FeatureFlags getFeatureFlags() const; protected: FeatureFlagsOther featureFlags; void queryIntensityQuantityType(const OSPIntensityQuantity &defaultIQ); }; OSPTYPEFOR_SPECIALIZATION(Light *, OSP_LIGHT); // Inlined definitions ///////////////////////////////////////////////////////// inline uint32_t Light::getShCount() const { return 1; } inline FeatureFlags Light::getFeatureFlags() const { FeatureFlags ff; ff.other = featureFlags; return ff; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/Light.ispc000066400000000000000000000011631456566705700230300ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/DifferentialGeometry.ih" // c++ shared #include "LightShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE Light_EvalRes Light_eval(const Light *uniform, const DifferentialGeometry &, const vec3f &, const float, const float, const float) { Light_EvalRes res; res.radiance = make_vec3f(0.f); return res; } // Exports (called from C++) ////////////////////////////////////////////////////////////////////////////// export void *uniform Light_eval_addr() { return (void *uniform)Light_eval; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/LightDispatch.ih000066400000000000000000000027001456566705700241500ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/FeatureFlags.ih" #include "rkcommon/math/vec.ih" // c++ shared #include "LightShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE struct Light; struct DifferentialGeometry; // compute the weighted radiance at a point caused by a sample on the light // source // by convention, giving (0, 0) as "random" numbers should sample the "center" // of the light source (used by the raytracing renderers such as the SciVis // renderer) SYCL_EXTERNAL Light_SampleRes Light_dispatch_sample(const Light *uniform self, const DifferentialGeometry &dg, // point (&normal) to generate the sample const vec2f &s, // random numbers to generate the sample const float time, // generate the sample at time (motion blur) const uniform FeatureFlagsHandler &ffh); //! compute the radiance and pdf caused by the light source (pointed to by the //! given direction up until maxDist) SYCL_EXTERNAL Light_EvalRes Light_dispatch_eval(const Light *uniform self, const DifferentialGeometry &dg, // point to evaluate illumination for const vec3f &dir, // direction towards the light source, normalized const float minDist, // minimum distance to look for light contribution const float maxDist, // maximum distance to look for light contribution const float time, // evaluate at time (motion blur) const uniform FeatureFlagsHandler &ffh); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/LightDispatch.ispc000066400000000000000000000130731456566705700245130ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/DifferentialGeometry.ih" #include "common/FeatureFlagsEnum.h" #include "common/Instance.ih" #include "lights/LightDispatch.ih" #include "lights/LightShared.h" #include "lights/AmbientLight.ih" #include "lights/CylinderLight.ih" #include "lights/DirectionalLight.ih" #include "lights/HDRILight.ih" #include "lights/PointLight.ih" #include "lights/QuadLight.ih" #include "lights/SpotLight.ih" #include "render/pathtracer/GeometryLight.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL Light_SampleRes Light_dispatch_sample(const Light *uniform self, const DifferentialGeometry &dg, const vec2f &s, const float time, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlagsGeometry ffg = getFeatureFlagsGeometry(ffh); const uniform FeatureFlagsOther ffo = getFeatureFlagsOther(ffh); #ifndef OSPRAY_TARGET_SYCL return self->sample(self, dg, s, time, ffh); #else if ((self->type == LIGHT_TYPE_AMBIENT) && (ffo & FFO_LIGHT_AMBIENT)) { return AmbientLight_sample(self, dg, s, time, ffh); } else if ((self->type == LIGHT_TYPE_DIRECTIONAL) && (ffo & FFO_LIGHT_DIRECTIONAL)) { if (self->instance->motionBlur && (ffg & FFG_MOTION_BLUR)) return DirectionalLight_sample_instanced(self, dg, s, time, ffh); else return DirectionalLight_sample(self, dg, s, time, ffh); } else if ((self->type == LIGHT_TYPE_POINT) && (ffo & FFO_LIGHT_POINT)) { if (self->instance->motionBlur && (ffg & FFG_MOTION_BLUR)) return PointLight_sample_instanced(self, dg, s, time, ffh); else return PointLight_sample(self, dg, s, time, ffh); } else if ((self->type == LIGHT_TYPE_SPOT) && (ffo & FFO_LIGHT_SPOT)) { if (self->instance->motionBlur && (ffg & FFG_MOTION_BLUR)) return SpotLight_sample_instanced(self, dg, s, time, ffh); else return SpotLight_sample(self, dg, s, time, ffh); } else if ((self->type == LIGHT_TYPE_HDRI) && (ffo & FFO_LIGHT_HDRI)) { if (self->instance->motionBlur && (ffg & FFG_MOTION_BLUR)) return HDRILight_sample_instanced(self, dg, s, time, ffh); else return HDRILight_sample(self, dg, s, time, ffh); } else if ((self->type == LIGHT_TYPE_QUAD) && (ffo & FFO_LIGHT_QUAD)) { if (self->instance->motionBlur && (ffg & FFG_MOTION_BLUR)) return QuadLight_sample_instanced(self, dg, s, time, ffh); else return QuadLight_sample(self, dg, s, time, ffh); } else if ((self->type == LIGHT_TYPE_CYLINDER) && (ffo & FFO_LIGHT_CYLINDER)) { if (self->instance->motionBlur && (ffg & FFG_MOTION_BLUR)) return CylinderLight_sample_instanced(self, dg, s, time, ffh); else return CylinderLight_sample(self, dg, s, time, ffh); } else if ((self->type == LIGHT_TYPE_GEOMETRY) && (ffo & FFO_LIGHT_GEOMETRY)) { return GeometryLight_sample(self, dg, s, time, ffh); } else { Light_SampleRes res; res.weight = make_vec3f(0.f); res.dir = make_vec3f(0.f); res.dist = inf; res.pdf = 0.f; return res; } #endif } SYCL_EXTERNAL Light_EvalRes Light_dispatch_eval(const Light *uniform self, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float time, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlagsGeometry ffg = getFeatureFlagsGeometry(ffh); const uniform FeatureFlagsOther ffo = getFeatureFlagsOther(ffh); #ifndef OSPRAY_TARGET_SYCL return self->eval(self, dg, dir, minDist, maxDist, time); #else if ((self->type == LIGHT_TYPE_AMBIENT) && (ffo & FFO_LIGHT_AMBIENT)) { return AmbientLight_eval(self, dg, dir, minDist, maxDist, time); } else if ((self->type == LIGHT_TYPE_DIRECTIONAL) && (ffo & FFO_LIGHT_DIRECTIONAL)) { if (self->instance->motionBlur && (ffg & FFG_MOTION_BLUR)) return DirectionalLight_eval_instanced( self, dg, dir, minDist, maxDist, time); else return DirectionalLight_eval(self, dg, dir, minDist, maxDist, time); } else if ((self->type == LIGHT_TYPE_POINT) && (ffo & FFO_LIGHT_POINT)) { if (self->instance->motionBlur && (ffg & FFG_MOTION_BLUR)) return PointLight_eval_instanced(self, dg, dir, minDist, maxDist, time); else return PointLight_eval(self, dg, dir, minDist, maxDist, time); } else if ((self->type == LIGHT_TYPE_SPOT) && (ffo & FFO_LIGHT_SPOT)) { if (self->instance->motionBlur && (ffg & FFG_MOTION_BLUR)) return SpotLight_eval_instanced(self, dg, dir, minDist, maxDist, time); else return SpotLight_eval(self, dg, dir, minDist, maxDist, time); } else if ((self->type == LIGHT_TYPE_HDRI) && (ffo & FFO_LIGHT_HDRI)) { if (self->instance->motionBlur && (ffg & FFG_MOTION_BLUR)) return HDRILight_eval_instanced(self, dg, dir, minDist, maxDist, time); else return HDRILight_eval(self, dg, dir, minDist, maxDist, time); } else if ((self->type == LIGHT_TYPE_QUAD) && (ffo & FFO_LIGHT_QUAD)) { if (self->instance->motionBlur && (ffg & FFG_MOTION_BLUR)) return QuadLight_eval_instanced(self, dg, dir, minDist, maxDist, time); else return QuadLight_eval(self, dg, dir, minDist, maxDist, time); } else if ((self->type == LIGHT_TYPE_CYLINDER) && (ffo & FFO_LIGHT_CYLINDER)) { if (self->instance->motionBlur && (ffg & FFG_MOTION_BLUR)) return CylinderLight_eval_instanced( self, dg, dir, minDist, maxDist, time); else return CylinderLight_eval(self, dg, dir, minDist, maxDist, time); } else { Light_EvalRes res; res.radiance = make_vec3f(0.f); res.pdf = 0.f; return res; } #endif } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/LightShared.h000066400000000000000000000053331456566705700234530ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #if defined(ISPC) || defined(OSPRAY_TARGET_SYCL) #include "common/FeatureFlags.ih" #endif #ifdef __cplusplus namespace ispc { #endif // __cplusplus #if defined(__cplusplus) && !defined(OSPRAY_TARGET_SYCL) typedef void *Light_SampleFunc; typedef void *Light_EvalFunc; #else struct Light; struct DifferentialGeometry; struct Light_SampleRes { vec3f weight; // radiance that arrives at the given point divided by pdf vec3f dir; // direction towards the light source, normalized float dist; // largest valid t_far value for a shadow ray, including epsilon // to avoid self-intersection float pdf; // probability density that this sample was taken }; // compute the weighted radiance at a point caused by a sample on the light // source // by convention, giving (0, 0) as "random" numbers should sample the "center" // of the light source (used by the raytracing renderers such as the SciVis // renderer) typedef Light_SampleRes (*Light_SampleFunc)(const Light *uniform self, const DifferentialGeometry &dg, // point (&normal) to generate the sample const vec2f &s, // random numbers to generate the sample const float time, // generate the sample at time (motion blur) const uniform FeatureFlagsHandler &ffh); struct Light_EvalRes { vec3f radiance; // radiance that arrives at the given point (not weighted by // pdf) float pdf; // probability density that the direction would have been sampled }; //! compute the radiance and pdf caused by the light source (pointed to by the //! given direction up until maxDist) typedef Light_EvalRes (*Light_EvalFunc)(const Light *uniform self, const DifferentialGeometry &dg, // point to evaluate illumination for const vec3f &dir, // direction towards the light source, normalized const float minDist, // minimum distance to look for light contribution const float maxDist, // maximum distance to look for light contribution const float time); // evaluate at time (motion blur) #endif struct Instance; enum LightType { LIGHT_TYPE_AMBIENT, LIGHT_TYPE_CYLINDER, LIGHT_TYPE_DIRECTIONAL, LIGHT_TYPE_HDRI, LIGHT_TYPE_POINT, LIGHT_TYPE_QUAD, LIGHT_TYPE_SPOT, LIGHT_TYPE_GEOMETRY, LIGHT_TYPE_UNKNOWN, }; struct Light { LightType type; Light_SampleFunc sample; Light_EvalFunc eval; bool isVisible; // either directly in camera, or via a straight path (i.e. // through ThinGlass) const Instance *instance; #ifdef __cplusplus Light() : type(LIGHT_TYPE_UNKNOWN), sample(nullptr), eval(nullptr), isVisible(true), instance(nullptr) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/lights/PointLight.cpp000066400000000000000000000076741456566705700237030ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "PointLight.h" #ifndef OSPRAY_TARGET_SYCL #include "lights/PointLight_ispc.h" #else namespace ispc { void PointLight_Transform(const void *self, const void *xfm, void *dyn); void *PointLight_sample_addr(); void *PointLight_sample_instanced_addr(); void *PointLight_eval_addr(); void *PointLight_eval_instanced_addr(); } // namespace ispc #endif #include "PointLightShared.h" #include "common/InstanceShared.h" namespace ospray { ISPCRTMemoryView PointLight::createSh( uint32_t, const ispc::Instance *instance) const { ISPCRTMemoryView view = StructSharedCreate( getISPCDevice().getIspcrtContext().handle()); ispc::PointLight *sh = (ispc::PointLight *)ispcrtSharedPtr(view); sh->super.isVisible = visible; sh->super.instance = instance; #ifndef OSPRAY_TARGET_SYCL sh->super.sample = reinterpret_cast(ispc::PointLight_sample_addr()); sh->super.eval = reinterpret_cast(ispc::PointLight_eval_addr()); #endif sh->radiance = radiance; sh->intensity = radIntensity; sh->radius = radius; sh->pre.position = position; sh->pre.direction = normalize(direction); intensityDistribution.setSh(sh->intensityDistribution); // Enable dynamic runtime instancing or apply static transformation if (instance) { sh->pre.c0 = intensityDistribution.c0; if (instance->motionBlur) { #ifndef OSPRAY_TARGET_SYCL sh->super.sample = reinterpret_cast( ispc::PointLight_sample_instanced_addr()); sh->super.eval = reinterpret_cast( ispc::PointLight_eval_instanced_addr()); #endif } else ispc::PointLight_Transform(sh, instance->xfm, &sh->pre); } else { sh->pre.c90 = normalize(cross(intensityDistribution.c0, sh->pre.direction)); sh->pre.c0 = cross(sh->pre.direction, sh->pre.c90); } return view; } std::string PointLight::toString() const { return "ospray::PointLight"; } void PointLight::commit() { Light::commit(); position = getParam("position", vec3f(0.f)); radius = getParam("radius", 0.f); // per default perpendicular to direction direction = getParam("direction", vec3f(0.f, 0.f, 1.f)); intensityDistribution.c0 = std::abs(direction.x) < std::abs(direction.y) ? vec3f(0.0f, direction.z, direction.y) : vec3f(direction.z, 0.0f, direction.x); intensityDistribution.readParams(*this); queryIntensityQuantityType(intensityDistribution ? OSP_INTENSITY_QUANTITY_SCALE : OSP_INTENSITY_QUANTITY_INTENSITY); processIntensityQuantityType(); } void PointLight::processIntensityQuantityType() { radIntensity = 0.0f; radiance = 0.0f; const float sphereArea = 4.0f * M_PI * radius * radius; // converting from the chosen intensity quantity type to radiance // (for r > 0) or radiative intensity (r = 0) if (intensityDistribution ? intensityQuantity == OSP_INTENSITY_QUANTITY_SCALE : intensityQuantity == OSP_INTENSITY_QUANTITY_INTENSITY) { radIntensity = coloredIntensity; if (radius > 0.0f) { // the visible surface are of a sphere in one direction is equal // to the surface area of a disk oriented to this direction radiance = coloredIntensity / (sphereArea / 4.0f); } return; } if (!intensityDistribution) { if (intensityQuantity == OSP_INTENSITY_QUANTITY_POWER) { radIntensity = coloredIntensity / (4.0f * M_PI); if (radius > 0.0f) radiance = coloredIntensity / (M_PI * sphereArea); return; } if (intensityQuantity == OSP_INTENSITY_QUANTITY_RADIANCE) { // a virtual point light has no surface area therefore // radIntensity stays zero if (radius > 0.0f) radiance = coloredIntensity; return; } } postStatusMsg(OSP_LOG_WARNING) << toString() << " unsupported 'intensityQuantity' value"; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/PointLight.h000066400000000000000000000017311456566705700233340ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "IntensityDistribution.h" #include "Light.h" namespace ospray { //! a PointLight is a singular light emitting from a point uniformly into all //! directions struct OSPRAY_SDK_INTERFACE PointLight : public Light { PointLight(api::ISPCDevice &device) : Light(device, FFO_LIGHT_POINT) {} virtual ~PointLight() override = default; virtual ISPCRTMemoryView createSh( uint32_t, const ispc::Instance *instance = nullptr) const override; virtual std::string toString() const override; virtual void commit() override; private: void processIntensityQuantityType(); vec3f position{0.f}; //!< world-space position of the light float radius{0.f}; //!< Radius of SphereLight vec3f radiance{1.f}; //!< emitted radiance of the SphereLight vec3f radIntensity{0.f}; IntensityDistribution intensityDistribution; vec3f direction{0.f, 0.f, 1.f}; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/PointLight.ih000066400000000000000000000017341456566705700235100ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "lights/LightShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL Light_SampleRes PointLight_sample(const Light *uniform super, const DifferentialGeometry &dg, const vec2f &sp, const float, const uniform FeatureFlagsHandler &); SYCL_EXTERNAL Light_SampleRes PointLight_sample_instanced( const Light *uniform super, const DifferentialGeometry &dg, const vec2f &sp, const float time, const uniform FeatureFlagsHandler &); SYCL_EXTERNAL Light_EvalRes PointLight_eval(const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float); SYCL_EXTERNAL Light_EvalRes PointLight_eval_instanced( const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float time); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/PointLight.ispc000066400000000000000000000145721456566705700240520ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "IntensityDistribution.ih" #include "common/Instance.ih" #include "common/Intersect.ih" #include "common/Ray.ih" #include "math/sampling.ih" #include "rkcommon/math/LinearSpace.ih" // c++ shared #include "PointLightShared.h" // Implementation ////////////////////////////////////////////////////////////////////////////// OSPRAY_BEGIN_ISPC_NAMESPACE inline void Transform(const PointLight *uniform self, const uniform affine3f &xfm, uniform PointLightDynamic &dyn) { dyn.position = xfmPoint(xfm, self->pre.position); if (self->intensityDistribution.lid) { dyn.direction = normalize(xfmVector(xfm, self->pre.direction)); dyn.c90 = normalize(cross(xfmVector(xfm, self->pre.c0), dyn.direction)); dyn.c0 = cross(dyn.direction, dyn.c90); } } export void PointLight_Transform( const void *uniform self, const void *uniform xfm, void *uniform dyn) { Transform((PointLight * uniform) self, *((affine3f * uniform) xfm), *((PointLightDynamic * uniform) dyn)); } inline Light_SampleRes Sample(const PointLight *uniform self, const uniform PointLightDynamic &dyn, const DifferentialGeometry &dg, const vec2f &s) { Light_SampleRes res; // extant light vector from the hit point const vec3f dir = dyn.position - dg.P; const float dist2 = dot(dir, dir); const float invdist = rsqrt(dist2); // normalized light vector res.dir = dir * invdist; res.dist = dist2 * invdist; res.pdf = inf; // per default we always take this sample const float sinTheta = self->radius * invdist; if ((self->radius > 0.f) & (sinTheta > 0.005f)) { // sample surface of sphere as seen by hit point -> cone of directions // for very small cones treat as point light, because float precision is not // good enough if (sinTheta < 1.f) { const float cosTheta = sqrt(1.f - sinTheta * sinTheta); const vec3f localDir = uniformSampleCone(cosTheta, s); res.dir = frame(res.dir) * localDir; res.pdf = uniformSampleConePDF(cosTheta); const float c = localDir.z; res.dist = c * res.dist - sqrt_safe(sqr(self->radius) - (1.f - c * c) * dist2); // note the sampling PDF is already in solid angle therefore, we do not // need to divide it by the squared distance res.weight = self->radiance / res.pdf; } else { // emit only from the surface to the outside res.weight = make_vec3f(0.f); } } else { // convert from intensity to radiance by attenuating by distance^2 res.weight = self->intensity * sqr(invdist); } if (self->intensityDistribution.lid) { const float cosd = -dot(dyn.direction, res.dir); res.weight = res.weight * IntensityDistribution_eval( &self->intensityDistribution, dyn.c0, dyn.c90, cosd, res.dir); } return res; } SYCL_EXTERNAL Light_SampleRes PointLight_sample(const Light *uniform super, const DifferentialGeometry &dg, const vec2f &s, const float, const uniform FeatureFlagsHandler &) { const PointLight *uniform self = (PointLight * uniform) super; assert(self); return Sample(self, self->pre, dg, s); } SYCL_EXTERNAL Light_SampleRes PointLight_sample_instanced( const Light *uniform super, const DifferentialGeometry &dg, const vec2f &s, const float time, const uniform FeatureFlagsHandler &) { const PointLight *uniform self = (PointLight * uniform) super; assert(self); const Instance *uniform instance = self->super.instance; assert(instance); Light_SampleRes res; foreach_unique (utime in time) { const uniform affine3f xfm = Instance_getTransform(instance, utime); uniform PointLightDynamic dyn; Transform(self, xfm, dyn); res = Sample(self, dyn, dg, s); } return res; } inline Light_EvalRes Eval(const PointLight *uniform self, const uniform PointLightDynamic &dyn, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist) { Light_EvalRes res; res.radiance = make_vec3f(0.f); const vec3f A = dyn.position - dg.P; const float centerDist2 = dot(A, A); const float sinTheta2 = sqr(self->radius) * rcp(centerDist2); if (self->radius > 0.f && sqrt(sinTheta2) > 0.005f) { const Intersections isect = intersectSphere(dg.P, dir, dyn.position, self->radius); if (isect.entry.hit && isect.entry.t > minDist && isect.entry.t < maxDist) { const float cosTheta = sqrt(1.f - sinTheta2); res.pdf = uniformSampleConePDF(cosTheta); res.radiance = self->radiance; if (self->intensityDistribution.lid) { const float cosAngle = -dot(dyn.direction, dir); res.radiance = res.radiance * IntensityDistribution_eval( &self->intensityDistribution, dyn.c0, dyn.c90, cosAngle, dir); } } } return res; } SYCL_EXTERNAL Light_EvalRes PointLight_eval(const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float) { const PointLight *uniform self = (PointLight * uniform) super; assert(self); return Eval(self, self->pre, dg, dir, minDist, maxDist); } SYCL_EXTERNAL Light_EvalRes PointLight_eval_instanced( const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float time) { const PointLight *uniform self = (PointLight * uniform) super; assert(self); const Instance *uniform instance = self->super.instance; assert(instance); Light_EvalRes res; foreach_unique (utime in time) { const uniform affine3f xfm = Instance_getTransform(instance, utime); uniform PointLightDynamic dyn; Transform(self, xfm, dyn); res = Eval(self, dyn, dg, dir, minDist, maxDist); } return res; } // Exports (called from C++) ////////////////////////////////////////////////////////////////////////////// export void *uniform PointLight_sample_addr() { return (void *uniform)PointLight_sample; } #ifndef OSPRAY_TARGET_SYCL export void *uniform PointLight_sample_instanced_addr() { return (void *uniform)PointLight_sample_instanced; } #endif export void *uniform PointLight_eval_addr() { return (void *uniform)PointLight_eval; } #ifndef OSPRAY_TARGET_SYCL export void *uniform PointLight_eval_instanced_addr() { return (void *uniform)PointLight_eval_instanced; } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/PointLightShared.h000066400000000000000000000020631456566705700244620ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "IntensityDistributionShared.h" #include "LightShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus // state that changes under transformations struct PointLightDynamic { vec3f position; vec3f direction; vec3f c0; // orientation for intensityDistribution: direction of the C0- vec3f c90; // and the C90-(half)plane #ifdef __cplusplus PointLightDynamic() : position(0.f), direction(0.f, 0.f, 1.f), c0(1.f, 0.f, 0.f), c90(0.f, 1.f, 0.f) {} #endif }; struct PointLight { Light super; vec3f intensity; // RGB color and intensity of light vec3f radiance; // emitted RGB radiance float radius; // defines the size of the SphereLight IntensityDistribution intensityDistribution; PointLightDynamic pre; // un- or pre-transformed state #ifdef __cplusplus PointLight() : intensity(1.f), radiance(1.f), radius(0.f) { super.type = LIGHT_TYPE_POINT; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/lights/QuadLight.cpp000066400000000000000000000064611456566705700234750ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "QuadLight.h" #ifndef OSPRAY_TARGET_SYCL #include "lights/QuadLight_ispc.h" #else namespace ispc { void QuadLight_Transform(const void *self, const void *xfm, void *dyn); } #endif #include "QuadLightShared.h" #include "common/InstanceShared.h" namespace ospray { ISPCRTMemoryView QuadLight::createSh( uint32_t, const ispc::Instance *instance) const { ISPCRTMemoryView view = StructSharedCreate( getISPCDevice().getIspcrtContext().handle()); ispc::QuadLight *sh = (ispc::QuadLight *)ispcrtSharedPtr(view); #ifndef OSPRAY_TARGET_SYCL sh->super.sample = reinterpret_cast(ispc::QuadLight_sample_addr()); sh->super.eval = reinterpret_cast(ispc::QuadLight_eval_addr()); #endif sh->super.isVisible = visible; sh->super.instance = instance; sh->radiance = radiance; sh->pre.position = position; sh->pre.edge1 = edge1; sh->pre.edge2 = edge2; intensityDistribution.setSh(sh->intensityDistribution); // Enable dynamic runtime instancing or apply static transformation if (instance) { sh->pre.c0 = intensityDistribution.c0; if (instance->motionBlur) { #ifndef OSPRAY_TARGET_SYCL // TODO: QuadLight sample/eval dispatch needs to handle this case now sh->super.sample = reinterpret_cast( ispc::QuadLight_sample_instanced_addr()); sh->super.eval = reinterpret_cast( ispc::QuadLight_eval_instanced_addr()); #endif } else ispc::QuadLight_Transform(sh, instance->xfm, &sh->pre); } else { const vec3f ndirection = cross(edge2, edge1); sh->pre.ppdf = rcp(length(ndirection)); // 1/area sh->pre.nnormal = ndirection * sh->pre.ppdf; // normalize sh->pre.c90 = normalize(cross(sh->pre.nnormal, intensityDistribution.c0)); sh->pre.c0 = cross(sh->pre.c90, sh->pre.nnormal); } return view; } std::string QuadLight::toString() const { return "ospray::QuadLight"; } void QuadLight::commit() { Light::commit(); position = getParam("position", vec3f(0.f)); edge1 = getParam("edge1", vec3f(1.f, 0.f, 0.f)); edge2 = getParam("edge2", vec3f(0.f, 1.f, 0.f)); intensityDistribution.c0 = edge2; intensityDistribution.readParams(*this); queryIntensityQuantityType(intensityDistribution ? OSP_INTENSITY_QUANTITY_SCALE : OSP_INTENSITY_QUANTITY_RADIANCE); processIntensityQuantityType(); } void QuadLight::processIntensityQuantityType() { const float quadArea = length(cross(edge1, edge2)); // converting from the chosen intensity quantity type to radiance if (intensityDistribution ? intensityQuantity == OSP_INTENSITY_QUANTITY_SCALE : intensityQuantity == OSP_INTENSITY_QUANTITY_INTENSITY) { radiance = coloredIntensity / quadArea; return; } if (!intensityDistribution) { if (intensityQuantity == OSP_INTENSITY_QUANTITY_POWER) { radiance = coloredIntensity / (M_PI * quadArea); return; } if (intensityQuantity == OSP_INTENSITY_QUANTITY_RADIANCE) { radiance = coloredIntensity; return; } } postStatusMsg(OSP_LOG_WARNING) << toString() << " unsupported 'intensityQuantity' value"; radiance = vec3f(0.0f); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/QuadLight.h000066400000000000000000000020041456566705700231270ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "IntensityDistribution.h" #include "Light.h" namespace ospray { /*! a QuadLight is a virtual area light uniformly emitting from a rectangular * area into the positive half space */ struct OSPRAY_SDK_INTERFACE QuadLight : public Light { QuadLight(api::ISPCDevice &device) : Light(device, FFO_LIGHT_QUAD) {} virtual ~QuadLight() override = default; virtual ISPCRTMemoryView createSh( uint32_t, const ispc::Instance *instance = nullptr) const override; virtual std::string toString() const override; virtual void commit() override; private: void processIntensityQuantityType(); vec3f position{0.f}; //!< world-space corner position of the light vec3f edge1{1.f, 0.f, 0.f}; //!< vectors to adjacent corners vec3f edge2{0.f, 1.f, 0.f}; //!< vectors to adjacent corners vec3f radiance{1.f}; //!< emitted radiance of the QuadLight IntensityDistribution intensityDistribution; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/QuadLight.ih000066400000000000000000000017231456566705700233070ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "lights/LightShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL Light_SampleRes QuadLight_sample(const Light *uniform super, const DifferentialGeometry &dg, const vec2f &sp, const float, const uniform FeatureFlagsHandler &); SYCL_EXTERNAL Light_SampleRes QuadLight_sample_instanced( const Light *uniform super, const DifferentialGeometry &dg, const vec2f &sp, const float time, const uniform FeatureFlagsHandler &); SYCL_EXTERNAL Light_EvalRes QuadLight_eval(const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float); SYCL_EXTERNAL Light_EvalRes QuadLight_eval_instanced(const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float time); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/QuadLight.ispc000066400000000000000000000177711456566705700236570ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "IntensityDistribution.ih" #include "SphericalQuadSampling.ih" #include "common/DifferentialGeometry.ih" #include "common/Instance.ih" // c++ shared #include "QuadLightShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE // Implementation ////////////////////////////////////////////////////////////////////////////// inline void Transform(const QuadLight *uniform self, const uniform affine3f &xfm, uniform QuadLightDynamic &dyn) { // transform light into the world space dyn.position = xfmPoint(xfm, self->pre.position); dyn.edge1 = xfmVector(xfm, self->pre.edge1); dyn.edge2 = xfmVector(xfm, self->pre.edge2); // calculate quad normal vector const uniform vec3f ndirection = cross(dyn.edge2, dyn.edge1); dyn.ppdf = rcp(length(ndirection)); // 1/area dyn.nnormal = ndirection * dyn.ppdf; // normalize if (self->intensityDistribution.lid) { dyn.c90 = normalize(cross(dyn.nnormal, xfmVector(xfm, self->pre.c0))); dyn.c0 = cross(dyn.c90, dyn.nnormal); } } export void QuadLight_Transform( const void *uniform self, const void *uniform xfm, void *uniform dyn) { Transform((QuadLight * uniform) self, *((affine3f * uniform) xfm), *((QuadLightDynamic * uniform) dyn)); } inline Light_SampleRes SampleArea(const QuadLight *uniform self, const uniform QuadLightDynamic &dyn, const DifferentialGeometry &dg, const vec2f &s) { Light_SampleRes res; const vec3f p = dyn.position + dyn.edge1 * s.x + dyn.edge2 * s.y; // extant light vector from the hit point const vec3f dir = p - dg.P; const float dist = length(dir); // normalized light vector res.dir = dir / dist; res.dist = dist; // convert to pdf wrt. solid angle const float cosd = dot(dyn.nnormal, res.dir); res.pdf = dyn.ppdf * sqr(dist) / abs(cosd); float weight; if (self->intensityDistribution.lid) { weight = IntensityDistribution_eval( &self->intensityDistribution, dyn.c0, dyn.c90, cosd, res.dir); // when an light distribution function is used we want to // remove the cosine term. To avoid numerical issues // at cosineAngle = 0 we use the fact that the division // of radiance with the cosine cancels out. weight /= dyn.ppdf * sqr(dist); } else { // emit only to one side weight = cosd > 0.f ? rcp(res.pdf) : 0.f; } res.weight = self->radiance * weight; return res; } inline Light_SampleRes Sample(const QuadLight *uniform self, const uniform QuadLightDynamic &dyn, const DifferentialGeometry &dg, const vec2f &s) { Light_SampleRes res; if (s.x == 0.0f && s.y == 0.0f) { // XXX SciVis vec2f ss = make_vec2f(0.5f); return SampleArea(self, dyn, dg, ss); } // create spherical quad for solid angle sampling SphericalQuad quad = SphericalQuad_create( dyn.position, dyn.edge1, dyn.edge2, neg(dyn.nnormal), dg.P); // bilinear warped cosine weight approximation const vec3f cosW = computeCosineWeightedRNG( dyn.position, dyn.edge1, dyn.edge2, dg.P, dg.Ng, s); // sample quad const vec3f dir = sampleSphericalQuad(quad, make_vec2f(cosW.x, cosW.y)); const float dist = length(dir); // normalized light vector res.dir = dir / dist; res.dist = dist; // convert to pdf wrt. solid angle const float cosd = dot(dyn.nnormal, res.dir); res.pdf = quad.S == 0.f ? 0.f : cosW.z / quad.S; if (self->intensityDistribution.lid) { if (abs(cosd) < 0.005f) // handle numerical edge case return SampleArea(self, dyn, dg, s); else { float weight = IntensityDistribution_eval( &self->intensityDistribution, dyn.c0, dyn.c90, cosd, res.dir); // when an light distribution function is used we want to // remove the cosine term. To avoid numerical issues // at cosineAngle = 0 we use the fact that the division // of radiance with the cosine cancels out. weight /= abs(cosd) * res.pdf; res.weight = res.pdf != 0.f ? self->radiance * weight : make_vec3f(0.f); } } else { // emit only to one side res.weight = (cosd > 0.f) && (res.pdf != 0.f) ? self->radiance * rcp(res.pdf) : make_vec3f(0.f); } return res; } SYCL_EXTERNAL Light_SampleRes QuadLight_sample(const Light *uniform super, const DifferentialGeometry &dg, const vec2f &sp, const float, const uniform FeatureFlagsHandler &) { const QuadLight *uniform self = (QuadLight * uniform) super; assert(self); return Sample(self, self->pre, dg, sp); } SYCL_EXTERNAL Light_SampleRes QuadLight_sample_instanced( const Light *uniform super, const DifferentialGeometry &dg, const vec2f &sp, const float time, const uniform FeatureFlagsHandler &) { const QuadLight *uniform self = (QuadLight * uniform) super; assert(self); const Instance *uniform instance = self->super.instance; assert(instance); Light_SampleRes res; foreach_unique (utime in time) { const uniform affine3f xfm = Instance_getTransform(instance, utime); uniform QuadLightDynamic dyn; Transform(self, xfm, dyn); res = Sample(self, dyn, dg, sp); } return res; } inline Light_EvalRes Eval(const QuadLight *uniform self, const uniform QuadLightDynamic &dyn, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist) { Light_EvalRes res; res.radiance = make_vec3f(0.f); // backfacing? const float cosd = dot(dyn.nnormal, dir); // denominator = dot(cross(edge1, edge2), dir) == cosd/ppdf if (cosd <= 0.f && !self->intensityDistribution.lid) return res; const vec3f c = dyn.position - dg.P; const vec3f r = cross(c, dir); const float rcosd = rcp(cosd); const float u = dot(r, dyn.edge1) * rcosd; const float v = -dot(r, dyn.edge2) * rcosd; // u/denominator > 1? if (min(u, v) < 0.f || max(u, v) * dyn.ppdf > 1.0f) return res; const float dist = dot(dyn.nnormal, c) * rcosd; if (dist <= minDist || dist > maxDist) return res; SphericalQuad quad = SphericalQuad_create( dyn.position, dyn.edge1, dyn.edge2, neg(dyn.nnormal), dg.P); if (quad.S > 0.f) { res.radiance = self->radiance; if (self->intensityDistribution.lid) { // convert from intensity to radiance by canceling the the cosine // term introduced by the Lambertian area light res.radiance = res.radiance * (IntensityDistribution_eval( &self->intensityDistribution, dyn.c0, dyn.c90, cosd, dir) / abs(cosd)); } res.pdf = rcp(quad.S); } return res; } SYCL_EXTERNAL Light_EvalRes QuadLight_eval(const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float) { const QuadLight *uniform self = (QuadLight * uniform) super; assert(self); return Eval(self, self->pre, dg, dir, minDist, maxDist); } SYCL_EXTERNAL Light_EvalRes QuadLight_eval_instanced(const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float time) { const QuadLight *uniform self = (QuadLight * uniform) super; assert(self); const Instance *uniform instance = self->super.instance; assert(instance); Light_EvalRes res; foreach_unique (utime in time) { const uniform affine3f xfm = Instance_getTransform(instance, utime); uniform QuadLightDynamic dyn; Transform(self, xfm, dyn); res = Eval(self, dyn, dg, dir, minDist, maxDist); } return res; } // Exports (called from C++) ////////////////////////////////////////////////////////////////////////////// export void *uniform QuadLight_sample_addr() { return (void *uniform)QuadLight_sample; } #ifndef OSPRAY_TARGET_SYCL export void *uniform QuadLight_sample_instanced_addr() { return (void *uniform)QuadLight_sample_instanced; } #endif export void *uniform QuadLight_eval_addr() { return (void *uniform)QuadLight_eval; } #ifndef OSPRAY_TARGET_SYCL export void *uniform QuadLight_eval_instanced_addr() { return (void *uniform)QuadLight_eval_instanced; } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/QuadLightShared.h000066400000000000000000000022571456566705700242700ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "IntensityDistributionShared.h" #include "LightShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus // state that changes under transformations struct QuadLightDynamic { vec3f position; vec3f edge1; vec3f edge2; vec3f nnormal; // negated normal, the direction that the QuadLight is not // emitting; normalized float ppdf; // probability to sample point on light = 1/area vec3f c0; // orientation for intensityDistribution: direction of the C0- vec3f c90; // and the C90-(half)plane #ifdef __cplusplus QuadLightDynamic() : position(0.f), edge1(1.f, 0.f, 0.f), edge2(0.f, 1.f, 0.f), nnormal(0.f, 0.f, 1.f), ppdf(1.f), c0(0.f, 1.f, 0.f), c90(1.f, 0.f, 0.f) {} #endif }; struct QuadLight { Light super; vec3f radiance; // emitted RGB radiance IntensityDistribution intensityDistribution; QuadLightDynamic pre; // un- or pre-transformed state #ifdef __cplusplus QuadLight() : radiance(0.f) { super.type = LIGHT_TYPE_QUAD; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/lights/SphericalQuadSampling.ih000066400000000000000000000247701456566705700256540ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct SphericalQuad { vec3f e0, e1, z; float S, k, n0z, n0z2, n2z, x0, x1, y0, y02, y1, y12, z0, z02; }; #define template_SphericalQuad_create(univary) \ inline SphericalQuad SphericalQuad_create(const univary vec3f &q0, \ const univary vec3f &e0, \ const univary vec3f &e1, \ const univary vec3f &n, \ const vec3f &P) \ { \ const univary float e0l = length(e0); \ const univary float e1l = length(e1); \ SphericalQuad quad; \ quad.e0 = e0 / e0l; \ quad.e1 = e1 / e1l; \ quad.z = n; \ \ /* compute rectangle coords in local reference system */ \ vec3f d = q0 - P; \ quad.z0 = dot(d, quad.z); \ \ /* flip z to make it point against Q */ \ quad.z = quad.z0 > 0.f ? neg(quad.z) : quad.z; \ quad.z0 = -abs(quad.z0); \ \ quad.z02 = sqr(quad.z0); \ \ quad.x0 = dot(d, quad.e0); \ quad.y0 = dot(d, quad.e1); \ quad.y02 = sqr(quad.y0); \ quad.x1 = quad.x0 + e0l; \ quad.y1 = quad.y0 + e1l; \ quad.y12 = sqr(quad.y1) * quad.y1; \ \ /* create vectors to four vertices */ \ vec3f v00 = make_vec3f(quad.x0, quad.y0, quad.z0); \ vec3f v01 = make_vec3f(quad.x0, quad.y1, quad.z0); \ vec3f v10 = make_vec3f(quad.x1, quad.y0, quad.z0); \ vec3f v11 = make_vec3f(quad.x1, quad.y1, quad.z0); \ \ /* compute normals to edges */ \ vec3f n0 = normalize(cross(v00, v10)); \ quad.n0z = n0.z; \ quad.n0z2 = n0.z * n0.z; \ vec3f n1 = normalize(cross(v10, v11)); \ vec3f n2 = normalize(cross(v11, v01)); \ quad.n2z = n2.z; \ vec3f n3 = normalize(cross(v01, v00)); \ \ /* compute internal angles (gamma_i) */ \ float g0 = acos(clamp(-dot(n0, n1), -1.f, 1.f)); \ float g1 = acos(clamp(-dot(n1, n2), -1.f, 1.f)); \ float g2 = acos(clamp(-dot(n2, n3), -1.f, 1.f)); \ float g3 = acos(clamp(-dot(n3, n0), -1.f, 1.f)); \ \ /* compute predefined constants */ \ quad.k = (float)two_pi - g2 - g3; \ \ /* compute solid angle from internal angles */ \ quad.S = max(0.f, g0 + g1 - quad.k); \ \ return quad; \ } #ifndef OSPRAY_TARGET_SYCL template_SphericalQuad_create(varying); #endif template_SphericalQuad_create(uniform); #undef template_SphericalQuad_create inline float sign(float x) { return ((float)(0.f < x) - (float)(x < 0.f)); } inline vec3f sampleSphericalQuad(const SphericalQuad &quad, const vec2f &s) { // 1. compute cu const float au = s.x * quad.S + quad.k; float cosau, sinau; sincos(au, &sinau, &cosau); const float fu = (cosau * quad.n0z - quad.n2z) * rcp(sinau); const float cu = clamp(rsqrt(fu * fu + sqr(quad.n0z)) * sign(fu), -1.f, 1.f); // 2. compute xu const float x0 = -(cu * quad.z0) * rsqrt(1.f - cu * cu); const float xu = clamp(x0, quad.x0, quad.x1); // 3. compute yv const float ds = sqrt(sqr(xu) + sqr(quad.z0)); const float ds2 = sqr(ds); const float h0 = quad.y0 * rsqrt(ds2 + sqr(quad.y0)); const float h1 = quad.y1 * rsqrt(ds2 + sqr(quad.y1)); const float hv = s.y * (h1 - h0) + h0; const float hv2 = sqr(hv); const float yv = (hv2 < 1.f - 1e-4f) ? (hv * ds) * rsqrt(1.f - hv2) : quad.y1; // 4. transform (xu,yv,z0) to world coords return (xu * quad.e0 + yv * quad.e1 + quad.z0 * quad.z); } inline float solve_quadratic(float A, float B, float C) { // see https://people.csail.mit.edu/bkph/articles/Quadratics.pdf if (A == 0.f) return -C / B; float rad = B * B - 4.f * A * C; if (rad < 0.f) return 0.f; rad = sqrt(rad); float root; if (B >= 0.f) { root = (-B - rad) / (2.f * A); if (root < 0.f || root > 1.f) root = 2.f * C / (-B - rad); } else { root = 2.f * C / (-B + rad); if (root < 0.f || root > 1.f) root = (-B + rad) / (2.f * A); } return root; } // These functions correspond to the bilinear row of table 3 in the paper // https://diglib.eg.org/bitstream/handle/10.1111/cgf14060/v39i4pp149-158.pdf inline float fu(float r, float W00, float W01, float W10, float W11) { const float A = W10 + W11 - W01 - W00; const float B = 2.f * (W01 + W00); if (A + B == 0.f) return r; const float C = -(W00 + W01 + W10 + W11) * r; return solve_quadratic(A, B, C); } inline float fv(float r, float u, float W00, float W01, float W10, float W11) { const float A = (1.f - u) * W01 + u * W11 - (1.f - u) * W00 - u * W10; const float B = 2.f * (1.f - u) * W00 + 2.f * u * W10; if (A + B == 0.f) return r; const float C = -((1.f - u) * W01 + u * W11 + (1.f - u) * W00 + u * W10) * r; return solve_quadratic(A, B, C); } #define template_computeCosineWeightedRNG(univary) \ inline vec3f computeCosineWeightedRNG(const univary vec3f &q0, \ const univary vec3f &e0, \ const univary vec3f &e1, \ const vec3f &P, \ const vec3f &Ng, \ const vec2f &s) \ { \ /*code from \ https://casual-effects.com/research/Hart2020Sampling/Hart2020Sampling.pdf*/ \ vec3f wpn[4]; \ univary vec3f wp[4]; \ float prob[4]; \ wp[0] = q0; \ wp[1] = q0 + e0; \ wp[2] = q0 + e1; \ wp[3] = wp[1] + e1; \ for (int i = 0; i < 4; i++) { \ wpn[i] = normalize(wp[i] - P); \ /* cosine term of ray with illuminated surface */ \ prob[i] = max(0.f, dot(wpn[i], Ng)); \ } \ \ if ((prob[0] + prob[2]) == 0.f) { \ return make_vec3f(s.x, s.y, 1.f); \ } \ \ const float totProb = prob[0] + prob[2] + prob[1] + prob[3]; \ const float u = fu(s.x, prob[0], prob[2], prob[1], prob[3]); \ const float v = fv(s.y, u, prob[0], prob[2], prob[1], prob[3]); \ \ const float pdf = 4.f \ * ((1.f - u) * (1.f - v) * prob[0] + u * (1.f - v) * prob[1] \ + u * v * prob[3] + (1.f - u) * v * prob[2]) \ / totProb; \ \ return make_vec3f(u, v, pdf); \ } #ifndef OSPRAY_TARGET_SYCL template_computeCosineWeightedRNG(varying); #endif template_computeCosineWeightedRNG(uniform); #undef template_computeCosineWeightedRNG OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/SpotLight.cpp000066400000000000000000000117611456566705700235270ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "SpotLight.h" #include "math/sampling.h" #ifndef OSPRAY_TARGET_SYCL #include "lights/SpotLight_ispc.h" #else namespace ispc { void SpotLight_Transform(const void *self, const void *xfm, void *dyn); void *SpotLight_sample_addr(); void *SpotLight_sample_instanced_addr(); void *SpotLight_eval_addr(); void *SpotLight_eval_instanced_addr(); } // namespace ispc #endif // ispc shared #include "SpotLightShared.h" #include "common/InstanceShared.h" namespace ospray { ISPCRTMemoryView SpotLight::createSh( uint32_t, const ispc::Instance *instance) const { ISPCRTMemoryView view = StructSharedCreate( getISPCDevice().getIspcrtContext().handle()); ispc::SpotLight *sh = (ispc::SpotLight *)ispcrtSharedPtr(view); #ifndef OSPRAY_TARGET_SYCL sh->super.sample = reinterpret_cast(ispc::SpotLight_sample_addr()); sh->super.eval = reinterpret_cast(ispc::SpotLight_eval_addr()); #endif sh->super.isVisible = visible; sh->super.instance = instance; sh->pre.position = position; sh->pre.direction = normalize(direction); intensityDistribution.setSh(sh->intensityDistribution); // Enable dynamic runtime instancing or apply static transformation if (instance) { sh->pre.c0 = intensityDistribution.c0; if (instance->motionBlur) { #ifndef OSPRAY_TARGET_SYCL sh->super.sample = reinterpret_cast( ispc::SpotLight_sample_instanced_addr()); sh->super.eval = reinterpret_cast( ispc::SpotLight_eval_instanced_addr()); #endif } else ispc::SpotLight_Transform(&sh->pre, instance->xfm, &sh->pre); } else { sh->pre.c90 = normalize(cross(intensityDistribution.c0, sh->pre.direction)); sh->pre.c0 = cross(sh->pre.direction, sh->pre.c90); } sh->radiance = radiance; sh->intensity = radIntensity; sh->cosAngleMax = cosAngleMax; sh->cosAngleScale = cosAngleScale; sh->radius = radius; sh->innerRadius = innerRadius; sh->areaPdf = uniformSampleRingPDF(radius, innerRadius); return view; } std::string SpotLight::toString() const { return "ospray::SpotLight"; } void SpotLight::commit() { Light::commit(); position = getParam("position", vec3f(0.f)); direction = getParam("direction", vec3f(0.f, 0.f, 1.f)); float openingAngle = getParam("openingAngle", 180.f); float penumbraAngle = getParam("penumbraAngle", 5.f); radius = max(0.0f, getParam("radius", 0.f)); innerRadius = clamp(getParam("innerRadius", 0.f), 0.0f, 0.999f * radius); // per default perpendicular to direction intensityDistribution.c0 = std::abs(direction.x) < std::abs(direction.y) ? vec3f(0.0f, direction.z, direction.y) : vec3f(direction.z, 0.0f, direction.x); intensityDistribution.readParams(*this); // check ranges and pre-compute parameters openingAngle = clamp(openingAngle, 0.f, 360.f); penumbraAngle = clamp(penumbraAngle, 0.f, 0.5f * openingAngle); cosAngleMax = std::cos(deg2rad(0.5f * openingAngle)); const float cosAngleMin = std::cos(deg2rad(0.5f * openingAngle - penumbraAngle)); cosAngleScale = 1.0f / (cosAngleMin - cosAngleMax); queryIntensityQuantityType(intensityDistribution ? OSP_INTENSITY_QUANTITY_SCALE : OSP_INTENSITY_QUANTITY_INTENSITY); processIntensityQuantityType(openingAngle); } void SpotLight::processIntensityQuantityType(const float openingAngle) { radIntensity = 0.0f; radiance = 0.0f; const float halfOpeningAngleRad = M_PI * (openingAngle * 0.5f) / 180.0f; const float cosHalfOpeningAngle = cos(halfOpeningAngleRad); const auto sqr = [](const float f) { return f * f; }; const float ringDiskArea = M_PI * (sqr(radius) - sqr(innerRadius)); const float sphericalCapCosInt = M_PI * (1.0f - sqr(cosHalfOpeningAngle)); // converting from the chosen intensity quantity type to radiance if (intensityDistribution ? intensityQuantity == OSP_INTENSITY_QUANTITY_SCALE : intensityQuantity == OSP_INTENSITY_QUANTITY_INTENSITY) { radIntensity = coloredIntensity; if (radius > 0.0f) radiance = radIntensity / ringDiskArea; return; } if (!intensityDistribution) { if (intensityQuantity == OSP_INTENSITY_QUANTITY_POWER) { // since our spot light implementation includes the cosine term we need // to consider the integrated cosine cap instead of the usually used // integrated cap radIntensity = coloredIntensity / sphericalCapCosInt; if (radius > 0.0f) radiance = coloredIntensity / (sphericalCapCosInt * ringDiskArea); return; } if (intensityQuantity == OSP_INTENSITY_QUANTITY_RADIANCE) { // a virtual spot light has no surface area therefore radIntensity stays 0 if (radius > 0.0f) radiance = coloredIntensity; return; } } postStatusMsg(OSP_LOG_WARNING) << toString() << " unsupported 'intensityQuantity' value"; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/SpotLight.h000066400000000000000000000017571456566705700232000ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "IntensityDistribution.h" #include "Light.h" namespace ospray { /*! a SpotLight is a singular light emitting from a point uniformly into a * cone of directions bounded by halfAngle */ struct OSPRAY_SDK_INTERFACE SpotLight : public Light { SpotLight(api::ISPCDevice &device) : Light(device, FFO_LIGHT_SPOT) {} virtual ~SpotLight() override = default; virtual ISPCRTMemoryView createSh( uint32_t, const ispc::Instance *instance = nullptr) const override; virtual std::string toString() const override; virtual void commit() override; private: void processIntensityQuantityType(const float openingAngle); vec3f position{0.f}; vec3f direction{0.f, 0.f, 1.f}; vec3f radiance{1.f}; vec3f radIntensity{0.f}; float radius{0.f}; float innerRadius{0.f}; float cosAngleMax{1.f}; float cosAngleScale{1.f}; IntensityDistribution intensityDistribution; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/SpotLight.ih000066400000000000000000000017231456566705700233420ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "lights/LightShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL Light_SampleRes SpotLight_sample(const Light *uniform super, const DifferentialGeometry &dg, const vec2f &sp, const float, const uniform FeatureFlagsHandler &); SYCL_EXTERNAL Light_SampleRes SpotLight_sample_instanced( const Light *uniform super, const DifferentialGeometry &dg, const vec2f &sp, const float time, const uniform FeatureFlagsHandler &); SYCL_EXTERNAL Light_EvalRes SpotLight_eval(const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float); SYCL_EXTERNAL Light_EvalRes SpotLight_eval_instanced(const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float time); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/SpotLight.ispc000066400000000000000000000156061456566705700237050ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "IntensityDistribution.ih" #include "common/Instance.ih" #include "math/sampling.ih" // c++ shared #include "SpotLightShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE // Implementation ////////////////////////////////////////////////////////////////////////////// inline void Transform(const uniform SpotLightDynamic &pre, const uniform affine3f &xfm, uniform SpotLightDynamic &dyn) { dyn.position = xfmPoint(xfm, pre.position); dyn.direction = normalize(xfmVector(xfm, pre.direction)); dyn.c90 = normalize(cross(xfmVector(xfm, pre.c0), dyn.direction)); dyn.c0 = cross(dyn.direction, dyn.c90); } export void SpotLight_Transform( const void *uniform self, const void *uniform xfm, void *uniform dyn) { Transform(*((const SpotLightDynamic *uniform)self), *((affine3f * uniform) xfm), *((SpotLightDynamic * uniform) dyn)); } inline float AngularAttenuation(const SpotLight *uniform self, float cosAngle) { return clamp((cosAngle - self->cosAngleMax) * self->cosAngleScale); } inline Light_SampleRes Sample(const SpotLight *uniform self, const uniform SpotLightDynamic &dyn, const DifferentialGeometry &dg, const vec2f &s) { Light_SampleRes res; // extant light vector from the hit point res.dir = dyn.position - dg.P; if (self->radius > 0.0f) { uniform linear3f l2w; l2w.vx = dyn.c0; l2w.vy = dyn.c90; l2w.vz = dyn.direction; res.dir = l2w * uniformSampleRing(self->radius, self->innerRadius, s) + res.dir; } const float dist2 = dot(res.dir, res.dir); const float invdist = rsqrt(dist2); // normalized light vector res.dir = res.dir * invdist; res.dist = dist2 * invdist; // cosine of the negated light direction and light vector. const float cosAngle = -dot(dyn.direction, res.dir); float weight = AngularAttenuation(self, cosAngle); if (self->intensityDistribution.lid) weight *= IntensityDistribution_eval( &self->intensityDistribution, dyn.c0, dyn.c90, cosAngle, res.dir); if (self->radius > 0.0f) { // convert area PDF to solid angle PDF res.pdf = self->areaPdf * (dist2 / abs(cosAngle)); if (self->intensityDistribution.lid) { // when an light distribution function is used we want to // remove the cosine term. To avoid numerical issues // at cosineAngle = 0 we use the fact that the division // of radiance with the cosine cancels out. weight /= self->areaPdf * dist2; } else { weight /= res.pdf; } res.weight = self->radiance * weight; } else { res.pdf = inf; // we always take this sample if (!self->intensityDistribution.lid) { // if the spotlight does not use a measured LDF we // simulate Lambertian behavior by multiplication with cosineAngle weight *= abs(cosAngle); } // convert from intensity to radiance by attenuating by distance^2; // attenuate by angle res.weight = self->intensity * (sqr(invdist) * weight); } return res; } SYCL_EXTERNAL Light_SampleRes SpotLight_sample(const Light *uniform super, const DifferentialGeometry &dg, const vec2f &s, const float, const uniform FeatureFlagsHandler &) { const SpotLight *uniform self = (SpotLight * uniform) super; assert(self); return Sample(self, self->pre, dg, s); } SYCL_EXTERNAL Light_SampleRes SpotLight_sample_instanced( const Light *uniform super, const DifferentialGeometry &dg, const vec2f &s, const float time, const uniform FeatureFlagsHandler &) { const SpotLight *uniform self = (SpotLight * uniform) super; assert(self); const Instance *uniform instance = self->super.instance; assert(instance); Light_SampleRes res; foreach_unique (utime in time) { const uniform affine3f xfm = Instance_getTransform(instance, utime); uniform SpotLightDynamic dyn; Transform(self->pre, xfm, dyn); res = Sample(self, dyn, dg, s); } return res; } inline Light_EvalRes Eval(const SpotLight *uniform self, const uniform SpotLightDynamic &dyn, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist) { Light_EvalRes res; res.radiance = make_vec3f(0.f); if (self->radius > 0.f) { // intersect ring const float cosAngle = -dot(dyn.direction, dir); if (cosAngle > self->cosAngleMax) { // inside illuminated cone? const vec3f vp = dg.P - dyn.position; const float t = dot(vp, dyn.direction) * rcp(cosAngle); if (t > minDist & t <= maxDist) { const vec3f vd = vp + t * dir; const float d2 = dot(vd, vd); // inside ring? if (d2 < sqr(self->radius) && d2 > sqr(self->innerRadius)) { float attenuation = AngularAttenuation(self, cosAngle); if (self->intensityDistribution.lid) { attenuation *= IntensityDistribution_eval( &self->intensityDistribution, dyn.c0, dyn.c90, cosAngle, dir); // convert from intensity to radiance by canceling the the cosine // term introduced by the Lambertian area light attenuation /= abs(cosAngle); } // calculate the attenuated emitted radiance res.radiance = self->radiance * attenuation; // convert area PDF to solid angle PDF res.pdf = self->areaPdf * (sqr(t) / abs(cosAngle)); } } } } return res; } SYCL_EXTERNAL Light_EvalRes SpotLight_eval(const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float) { const SpotLight *uniform self = (SpotLight * uniform) super; assert(self); return Eval(self, self->pre, dg, dir, minDist, maxDist); } SYCL_EXTERNAL Light_EvalRes SpotLight_eval_instanced(const Light *uniform super, const DifferentialGeometry &dg, const vec3f &dir, const float minDist, const float maxDist, const float time) { const SpotLight *uniform self = (SpotLight * uniform) super; assert(self); const Instance *uniform instance = self->super.instance; assert(instance); Light_EvalRes res; foreach_unique (utime in time) { const uniform affine3f xfm = Instance_getTransform(instance, utime); uniform SpotLightDynamic dyn; Transform(self->pre, xfm, dyn); res = Eval(self, dyn, dg, dir, minDist, maxDist); } return res; } // Exports (called from C++) ////////////////////////////////////////////////////////////////////////////// export void *uniform SpotLight_sample_addr() { return (void *uniform)SpotLight_sample; } #ifndef OSPRAY_TARGET_SYCL export void *uniform SpotLight_sample_instanced_addr() { return (void *uniform)SpotLight_sample_instanced; } #endif export void *uniform SpotLight_eval_addr() { return (void *uniform)SpotLight_eval; } #ifndef OSPRAY_TARGET_SYCL export void *uniform SpotLight_eval_instanced_addr() { return (void *uniform)SpotLight_eval_instanced; } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/lights/SpotLightShared.h000066400000000000000000000031311456566705700243130ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "IntensityDistributionShared.h" #include "LightShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus // state that changes under transformations struct SpotLightDynamic { vec3f position; vec3f direction; vec3f c0; vec3f c90; #ifdef __cplusplus SpotLightDynamic() : position(0.f), direction(0.f, 0.f, 1.f), c0(1.f, 0.f, 0.f), c90(0.f, 1.f, 0.f) {} #endif // __cplusplus }; struct SpotLight { Light super; vec3f intensity; // RGB radiative intensity of the SpotLight vec3f radiance; // emitted RGB radiance float cosAngleMax; // Angular limit of the spot in an easier to use form: // cosine of the half angle in radians float cosAngleScale; // 1/(cos(border of the penumbra area) - cosAngleMax); // positive float radius; // defines the size of the DiskLight represented using // the (extended) SpotLight float innerRadius; // defines the size of the inner cut out of the DiskLight // to represent a RingLight float areaPdf; // pdf of disk/ring with radius/innerRadius IntensityDistribution intensityDistribution; SpotLightDynamic pre; // un- or pre-transformed state #ifdef __cplusplus SpotLight() : intensity(0.f), radiance(1.f), cosAngleMax(1.f), cosAngleScale(1.f), radius(0.f), innerRadius(0.f), areaPdf(inf) { super.type = LIGHT_TYPE_SPOT; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/lights/SunSkyLight.cpp000066400000000000000000000145161456566705700240370ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "SunSkyLight.h" #include "texture/Texture2D.h" #ifndef OSPRAY_TARGET_SYCL // ispc exports #include "lights/HDRILight_ispc.h" #else namespace ispc { void HDRILight_initDistribution(const void *map, void *distribution); } #endif // ispc shared #include "DirectionalLightShared.h" #include "HDRILightShared.h" namespace ospray { SunSkyLight::SunSkyLight(api::ISPCDevice &device) : Light(device, FFO_LIGHT_HDRI | FFO_LIGHT_DIRECTIONAL) { static const int skyResolution = 512; this->skySize = vec2i(skyResolution, skyResolution / 2); this->skyImage = make_buffer_shared_unique( getISPCDevice().getIspcrtContext(), skySize.product()); static auto format = static_cast(OSP_TEXTURE_RGB32F); static auto filter = static_cast(OSP_TEXTURE_FILTER_LINEAR); map = new Texture2D(getISPCDevice()); map->refDec(); map->getSh()->set( skySize, (ispc::vec3f *)this->skyImage->data(), format, filter); } ISPCRTMemoryView SunSkyLight::createSh( uint32_t index, const ispc::Instance *instance) const { switch (index) { case 0: { ISPCRTMemoryView view = StructSharedCreate( getISPCDevice().getIspcrtContext().handle()); ispc::HDRILight *sh = (ispc::HDRILight *)ispcrtSharedPtr(view); sh->set(visible, instance, coloredIntensity, frame, map->getSh(), distribution->getSh()); return view; } case 1: { ISPCRTMemoryView view = StructSharedCreate( getISPCDevice().getIspcrtContext().handle()); ispc::DirectionalLight *sh = (ispc::DirectionalLight *)ispcrtSharedPtr(view); sh->set(visible, instance, direction, solarIrradiance, cosAngle); return view; } default: assert(false && "Incorrect SunSky sublight index"); } return nullptr; } std::string SunSkyLight::toString() const { return "ospray::SunSkyLight"; } void SunSkyLight::commit() { Light::commit(); const float lambdaMin = 320.0f; const float lambdaMax = 720.0f; const vec3f up = normalize(getParam("up", vec3f(0.f, 1.f, 0.f))); direction = -normalize(getParam("direction", vec3f(0.f, -1.f, 0.f))); const float albedo = clamp(getParam("albedo", 0.3f), 0.1f, 1.f); const float turbidity = clamp(getParam("turbidity", 3.f), 1.f, 10.f); const float horizon = clamp(getParam("horizonExtension", 0.01f), 0.0f, 1.f); const float sunTheta = dot(up, direction); queryIntensityQuantityType(OSP_INTENSITY_QUANTITY_SCALE); processIntensityQuantityType(); frame.vz = up; if (std::abs(sunTheta) > 0.99f) { const vec3f dx0 = vec3f(0.0f, up.z, -up.y); const vec3f dx1 = vec3f(-up.z, 0.0f, up.x); frame.vx = normalize(std::abs(up.x) < std::abs(up.y) ? dx0 : dx1); frame.vy = cross(up, frame.vx); } else { frame.vy = normalize(cross(-direction, frame.vz)); frame.vx = cross(frame.vy, frame.vz); } // clamp sun to horizon if (sunTheta < 0) direction = frame.vx; // sun doesn't go beneath the horizon as theta clamped to pi/2 const float sunThetaMax = min(std::acos(sunTheta), (float)pi * 0.999f / 2.0f); const float sunPhi = pi; const float sunElevation = (float)pi / 2.0f - sunThetaMax; ArHosekSkyModelState *spectralModel = arhosekskymodelstate_alloc_init(sunElevation, turbidity, albedo); // angular diameter of the sun in degrees // using this value produces matching solar irradiance results from the model // and directional light const float angularDiameter = 0.53; solarIrradiance = zero; // calculate solar radiance for (int i = 0; i < cieSize; ++i) { if (cieLambda[i] >= lambdaMin && cieLambda[i] <= lambdaMax) { float r = arhosekskymodel_solar_radiance_internal2( spectralModel, cieLambda[i], sunElevation, 1); solarIrradiance += r * cieXyz(i); } } arhosekskymodelstate_free(spectralModel); cosAngle = std::cos(deg2rad(0.5f * angularDiameter)); const float rcpPdf = 2 * (float)pi * (1 - cosAngle); // convert solar radiance to solar irradiance solarIrradiance = xyzToRgb(solarIrradiance) * rcpPdf * intensityScale * coloredIntensity; ArHosekSkyModelState *rgbModel = arhosek_rgb_skymodelstate_alloc_init(turbidity, albedo, sunElevation); tasking::parallel_for(skySize.y, [&](int y) { for (int x = 0; x < skySize.x; x++) { float theta = (y + 0.5) / skySize.y * float(pi); const size_t index = skySize.x * y + x; // const size_t index = skySize.x * y + x * 3; vec3f skyRadiance = zero; const float maxTheta = 0.999 * float(pi) / 2.0; const float maxThetaHorizon = (horizon + 1.0) * float(pi) / 2.0; if (theta <= maxThetaHorizon) { float shadow = (horizon > 0.f) ? float( clamp((maxThetaHorizon - theta) / (maxThetaHorizon - maxTheta), 0.f, 1.f)) : 1.f; theta = min(theta, maxTheta); float phi = ((x + 0.5) / skySize.x - 0.5) * (2.0 * (float)pi); float cosGamma = cos(theta) * cos(sunThetaMax) + sin(theta) * sin(sunThetaMax) * cos(phi - sunPhi); float gamma = std::acos(clamp(cosGamma, -1.f, 1.f)); float rgbData[3]; for (int i = 0; i < 3; ++i) { rgbData[i] = arhosek_tristim_skymodel_radiance(rgbModel, theta, gamma, i); } skyRadiance = vec3f(rgbData[0], rgbData[1], rgbData[2]); skyRadiance = skyRadiance * shadow; skyRadiance *= intensityScale; } skyImage->data()[index] = max(skyRadiance, vec3f(0.0f)); } }); arhosekskymodelstate_free(rgbModel); // recreate distribution distribution = new Distribution2D(skySize, getISPCDevice()); // Release extra local ref distribution->refDec(); ispc::HDRILight_initDistribution(map->getSh(), distribution->getSh()); } void SunSkyLight::processIntensityQuantityType() { // validate the correctness of the light quantity type if (intensityQuantity == OSP_INTENSITY_QUANTITY_SCALE) { coloredIntensity = getParam("color", vec3f(1.f)); intensityScale = getParam("intensity", 0.025f); } else { postStatusMsg(OSP_LOG_WARNING) << toString() << " unsupported 'intensityQuantity' value"; coloredIntensity = vec3f(0.0f); } } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/SunSkyLight.h000066400000000000000000000035671456566705700235100ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Light.h" #include "math/Distribution2D.h" #include "math/spectrum.h" #include "rkcommon/tasking/parallel_for.h" #include "sky_model/color_info.h" #include "sky_model/sky_model.h" // ispc shared #include "texture/Texture2D.h" // Sun and sky environment lights // [Hosek and Wilkie 2012, "An Analytic Model for Full Spectral Sky-Dome // Radiance"] [Hosek and Wilkie 2013, "Adding a Solar Radiance Function to the // Hosek Skylight Model"] namespace ospray { // // CIE XYZ color matching functions // // -------------------------------- inline vec3f cieXyz(int i) { return vec3f(cieX[i], cieY[i], cieZ[i]); } inline vec3f xyzToRgb(const vec3f &c) { float r = 3.240479f * c.x - 1.537150f * c.y - 0.498535f * c.z; float g = -0.969256f * c.x + 1.875991f * c.y + 0.041556f * c.z; float b = 0.055648f * c.x - 0.204043f * c.y + 1.057311f * c.z; return vec3f(r, g, b); } struct OSPRAY_SDK_INTERFACE SunSkyLight : public Light { SunSkyLight(api::ISPCDevice &device); virtual uint32_t getShCount() const override; virtual ISPCRTMemoryView createSh( uint32_t index, const ispc::Instance *instance = nullptr) const override; virtual std::string toString() const override; virtual void commit() override; private: void processIntensityQuantityType(); std::unique_ptr> skyImage; Ref map; Ref distribution; vec2i skySize; linear3f frame{one}; // sky orientation vec3f direction{0.f, 0.f, 1.f}; vec3f solarIrradiance{0.f}; float cosAngle{1.f}; // scaling factor for values provided from model for both sun and sky to be <1 float intensityScale{0.025f}; }; // Inlined defintions ///////////////////////////////////////////////////////// inline uint32_t SunSkyLight::getShCount() const { return 2; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/registration.cpp000066400000000000000000000013151456566705700243160ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "AmbientLight.h" #include "CylinderLight.h" #include "DirectionalLight.h" #include "HDRILight.h" #include "PointLight.h" #include "QuadLight.h" #include "SpotLight.h" #include "SunSkyLight.h" namespace ospray { void registerAllLights() { Light::registerType("ambient"); Light::registerType("cylinder"); Light::registerType("distant"); Light::registerType("hdri"); Light::registerType("sphere"); Light::registerType("quad"); Light::registerType("spot"); Light::registerType("sunSky"); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/registration.h000066400000000000000000000002211456566705700237560ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 namespace ospray { void registerAllLights(); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/sky_model/000077500000000000000000000000001456566705700230665ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/lights/sky_model/color_info.h000066400000000000000000000664621456566705700254060ustar00rootroot00000000000000// Copyright 2010-2020 Attila T. Afra // Copyright 2015 Intel Corporation // SPDX-License-Identifier: Apache-2.0 namespace ospray { static const int cieSize = 471; const float cieX[cieSize] = {0.0001299000f, 0.0001458470f, 0.0001638021f, 0.0001840037f, 0.0002066902f, 0.0002321000f, 0.0002607280f, 0.0002930750f, 0.0003293880f, 0.0003699140f, 0.0004149000f, 0.0004641587f, 0.0005189860f, 0.0005818540f, 0.0006552347f, 0.0007416000f, 0.0008450296f, 0.0009645268f, 0.001094949f, 0.001231154f, 0.001368000f, 0.001502050f, 0.001642328f, 0.001802382f, 0.001995757f, 0.002236000f, 0.002535385f, 0.002892603f, 0.003300829f, 0.003753236f, 0.004243000f, 0.004762389f, 0.005330048f, 0.005978712f, 0.006741117f, 0.007650000f, 0.008751373f, 0.01002888f, 0.01142170f, 0.01286901f, 0.01431000f, 0.01570443f, 0.01714744f, 0.01878122f, 0.02074801f, 0.02319000f, 0.02620736f, 0.02978248f, 0.03388092f, 0.03846824f, 0.04351000f, 0.04899560f, 0.05502260f, 0.06171880f, 0.06921200f, 0.07763000f, 0.08695811f, 0.09717672f, 0.1084063f, 0.1207672f, 0.1343800f, 0.1493582f, 0.1653957f, 0.1819831f, 0.1986110f, 0.2147700f, 0.2301868f, 0.2448797f, 0.2587773f, 0.2718079f, 0.2839000f, 0.2949438f, 0.3048965f, 0.3137873f, 0.3216454f, 0.3285000f, 0.3343513f, 0.3392101f, 0.3431213f, 0.3461296f, 0.3482800f, 0.3495999f, 0.3501474f, 0.3500130f, 0.3492870f, 0.3480600f, 0.3463733f, 0.3442624f, 0.3418088f, 0.3390941f, 0.3362000f, 0.3331977f, 0.3300411f, 0.3266357f, 0.3228868f, 0.3187000f, 0.3140251f, 0.3088840f, 0.3032904f, 0.2972579f, 0.2908000f, 0.2839701f, 0.2767214f, 0.2689178f, 0.2604227f, 0.2511000f, 0.2408475f, 0.2298512f, 0.2184072f, 0.2068115f, 0.1953600f, 0.1842136f, 0.1733273f, 0.1626881f, 0.1522833f, 0.1421000f, 0.1321786f, 0.1225696f, 0.1132752f, 0.1042979f, 0.09564000f, 0.08729955f, 0.07930804f, 0.07171776f, 0.06458099f, 0.05795001f, 0.05186211f, 0.04628152f, 0.04115088f, 0.03641283f, 0.03201000f, 0.02791720f, 0.02414440f, 0.02068700f, 0.01754040f, 0.01470000f, 0.01216179f, 0.009919960f, 0.007967240f, 0.006296346f, 0.004900000f, 0.003777173f, 0.002945320f, 0.002424880f, 0.002236293f, 0.002400000f, 0.002925520f, 0.003836560f, 0.005174840f, 0.006982080f, 0.009300000f, 0.01214949f, 0.01553588f, 0.01947752f, 0.02399277f, 0.02910000f, 0.03481485f, 0.04112016f, 0.04798504f, 0.05537861f, 0.06327000f, 0.07163501f, 0.08046224f, 0.08973996f, 0.09945645f, 0.1096000f, 0.1201674f, 0.1311145f, 0.1423679f, 0.1538542f, 0.1655000f, 0.1772571f, 0.1891400f, 0.2011694f, 0.2133658f, 0.2257499f, 0.2383209f, 0.2510668f, 0.2639922f, 0.2771017f, 0.2904000f, 0.3038912f, 0.3175726f, 0.3314384f, 0.3454828f, 0.3597000f, 0.3740839f, 0.3886396f, 0.4033784f, 0.4183115f, 0.4334499f, 0.4487953f, 0.4643360f, 0.4800640f, 0.4959713f, 0.5120501f, 0.5282959f, 0.5446916f, 0.5612094f, 0.5778215f, 0.5945000f, 0.6112209f, 0.6279758f, 0.6447602f, 0.6615697f, 0.6784000f, 0.6952392f, 0.7120586f, 0.7288284f, 0.7455188f, 0.7621000f, 0.7785432f, 0.7948256f, 0.8109264f, 0.8268248f, 0.8425000f, 0.8579325f, 0.8730816f, 0.8878944f, 0.9023181f, 0.9163000f, 0.9297995f, 0.9427984f, 0.9552776f, 0.9672179f, 0.9786000f, 0.9893856f, 0.9995488f, 1.0090892f, 1.0180064f, 1.0263000f, 1.0339827f, 1.0409860f, 1.0471880f, 1.0524667f, 1.0567000f, 1.0597944f, 1.0617992f, 1.0628068f, 1.0629096f, 1.0622000f, 1.0607352f, 1.0584436f, 1.0552244f, 1.0509768f, 1.0456000f, 1.0390369f, 1.0313608f, 1.0226662f, 1.0130477f, 1.0026000f, 0.9913675f, 0.9793314f, 0.9664916f, 0.9528479f, 0.9384000f, 0.9231940f, 0.9072440f, 0.8905020f, 0.8729200f, 0.8544499f, 0.8350840f, 0.8149460f, 0.7941860f, 0.7729540f, 0.7514000f, 0.7295836f, 0.7075888f, 0.6856022f, 0.6638104f, 0.6424000f, 0.6215149f, 0.6011138f, 0.5811052f, 0.5613977f, 0.5419000f, 0.5225995f, 0.5035464f, 0.4847436f, 0.4661939f, 0.4479000f, 0.4298613f, 0.4120980f, 0.3946440f, 0.3775333f, 0.3608000f, 0.3444563f, 0.3285168f, 0.3130192f, 0.2980011f, 0.2835000f, 0.2695448f, 0.2561184f, 0.2431896f, 0.2307272f, 0.2187000f, 0.2070971f, 0.1959232f, 0.1851708f, 0.1748323f, 0.1649000f, 0.1553667f, 0.1462300f, 0.1374900f, 0.1291467f, 0.1212000f, 0.1136397f, 0.1064650f, 0.09969044f, 0.09333061f, 0.08740000f, 0.08190096f, 0.07680428f, 0.07207712f, 0.06768664f, 0.06360000f, 0.05980685f, 0.05628216f, 0.05297104f, 0.04981861f, 0.04677000f, 0.04378405f, 0.04087536f, 0.03807264f, 0.03540461f, 0.03290000f, 0.03056419f, 0.02838056f, 0.02634484f, 0.02445275f, 0.02270000f, 0.02108429f, 0.01959988f, 0.01823732f, 0.01698717f, 0.01584000f, 0.01479064f, 0.01383132f, 0.01294868f, 0.01212920f, 0.01135916f, 0.01062935f, 0.009938846f, 0.009288422f, 0.008678854f, 0.008110916f, 0.007582388f, 0.007088746f, 0.006627313f, 0.006195408f, 0.005790346f, 0.005409826f, 0.005052583f, 0.004717512f, 0.004403507f, 0.004109457f, 0.003833913f, 0.003575748f, 0.003334342f, 0.003109075f, 0.002899327f, 0.002704348f, 0.002523020f, 0.002354168f, 0.002196616f, 0.002049190f, 0.001910960f, 0.001781438f, 0.001660110f, 0.001546459f, 0.001439971f, 0.001340042f, 0.001246275f, 0.001158471f, 0.001076430f, 0.0009999493f, 0.0009287358f, 0.0008624332f, 0.0008007503f, 0.0007433960f, 0.0006900786f, 0.0006405156f, 0.0005945021f, 0.0005518646f, 0.0005124290f, 0.0004760213f, 0.0004424536f, 0.0004115117f, 0.0003829814f, 0.0003566491f, 0.0003323011f, 0.0003097586f, 0.0002888871f, 0.0002695394f, 0.0002515682f, 0.0002348261f, 0.0002191710f, 0.0002045258f, 0.0001908405f, 0.0001780654f, 0.0001661505f, 0.0001550236f, 0.0001446219f, 0.0001349098f, 0.0001258520f, 0.0001174130f, 0.0001095515f, 0.0001022245f, 0.00009539445f, 0.00008902390f, 0.00008307527f, 0.00007751269f, 0.00007231304f, 0.00006745778f, 0.00006292844f, 0.00005870652f, 0.00005477028f, 0.00005109918f, 0.00004767654f, 0.00004448567f, 0.00004150994f, 0.00003873324f, 0.00003614203f, 0.00003372352f, 0.00003146487f, 0.00002935326f, 0.00002737573f, 0.00002552433f, 0.00002379376f, 0.00002217870f, 0.00002067383f, 0.00001927226f, 0.00001796640f, 0.00001674991f, 0.00001561648f, 0.00001455977f, 0.00001357387f, 0.00001265436f, 0.00001179723f, 0.00001099844f, 0.00001025398f, 0.000009559646f, 0.000008912044f, 0.000008308358f, 0.000007745769f, 0.000007221456f, 0.000006732475f, 0.000006276423f, 0.000005851304f, 0.000005455118f, 0.000005085868f, 0.000004741466f, 0.000004420236f, 0.000004120783f, 0.000003841716f, 0.000003581652f, 0.000003339127f, 0.000003112949f, 0.000002902121f, 0.000002705645f, 0.000002522525f, 0.000002351726f, 0.000002192415f, 0.000002043902f, 0.000001905497f, 0.000001776509f, 0.000001656215f, 0.000001544022f, 0.000001439440f, 0.000001341977f, 0.000001251141f}; const float cieY[cieSize] = {0.000003917000f, 0.000004393581f, 0.000004929604f, 0.000005532136f, 0.000006208245f, 0.000006965000f, 0.000007813219f, 0.000008767336f, 0.000009839844f, 0.00001104323f, 0.00001239000f, 0.00001388641f, 0.00001555728f, 0.00001744296f, 0.00001958375f, 0.00002202000f, 0.00002483965f, 0.00002804126f, 0.00003153104f, 0.00003521521f, 0.00003900000f, 0.00004282640f, 0.00004691460f, 0.00005158960f, 0.00005717640f, 0.00006400000f, 0.00007234421f, 0.00008221224f, 0.00009350816f, 0.0001061361f, 0.0001200000f, 0.0001349840f, 0.0001514920f, 0.0001702080f, 0.0001918160f, 0.0002170000f, 0.0002469067f, 0.0002812400f, 0.0003185200f, 0.0003572667f, 0.0003960000f, 0.0004337147f, 0.0004730240f, 0.0005178760f, 0.0005722187f, 0.0006400000f, 0.0007245600f, 0.0008255000f, 0.0009411600f, 0.001069880f, 0.001210000f, 0.001362091f, 0.001530752f, 0.001720368f, 0.001935323f, 0.002180000f, 0.002454800f, 0.002764000f, 0.003117800f, 0.003526400f, 0.004000000f, 0.004546240f, 0.005159320f, 0.005829280f, 0.006546160f, 0.007300000f, 0.008086507f, 0.008908720f, 0.009767680f, 0.01066443f, 0.01160000f, 0.01257317f, 0.01358272f, 0.01462968f, 0.01571509f, 0.01684000f, 0.01800736f, 0.01921448f, 0.02045392f, 0.02171824f, 0.02300000f, 0.02429461f, 0.02561024f, 0.02695857f, 0.02835125f, 0.02980000f, 0.03131083f, 0.03288368f, 0.03452112f, 0.03622571f, 0.03800000f, 0.03984667f, 0.04176800f, 0.04376600f, 0.04584267f, 0.04800000f, 0.05024368f, 0.05257304f, 0.05498056f, 0.05745872f, 0.06000000f, 0.06260197f, 0.06527752f, 0.06804208f, 0.07091109f, 0.07390000f, 0.07701600f, 0.08026640f, 0.08366680f, 0.08723280f, 0.09098000f, 0.09491755f, 0.09904584f, 0.1033674f, 0.1078846f, 0.1126000f, 0.1175320f, 0.1226744f, 0.1279928f, 0.1334528f, 0.1390200f, 0.1446764f, 0.1504693f, 0.1564619f, 0.1627177f, 0.1693000f, 0.1762431f, 0.1835581f, 0.1912735f, 0.1994180f, 0.2080200f, 0.2171199f, 0.2267345f, 0.2368571f, 0.2474812f, 0.2586000f, 0.2701849f, 0.2822939f, 0.2950505f, 0.3085780f, 0.3230000f, 0.3384021f, 0.3546858f, 0.3716986f, 0.3892875f, 0.4073000f, 0.4256299f, 0.4443096f, 0.4633944f, 0.4829395f, 0.5030000f, 0.5235693f, 0.5445120f, 0.5656900f, 0.5869653f, 0.6082000f, 0.6293456f, 0.6503068f, 0.6708752f, 0.6908424f, 0.7100000f, 0.7281852f, 0.7454636f, 0.7619694f, 0.7778368f, 0.7932000f, 0.8081104f, 0.8224962f, 0.8363068f, 0.8494916f, 0.8620000f, 0.8738108f, 0.8849624f, 0.8954936f, 0.9054432f, 0.9148501f, 0.9237348f, 0.9320924f, 0.9399226f, 0.9472252f, 0.9540000f, 0.9602561f, 0.9660074f, 0.9712606f, 0.9760225f, 0.9803000f, 0.9840924f, 0.9874812f, 0.9903128f, 0.9928116f, 0.9949501f, 0.9967108f, 0.9980983f, 0.9991120f, 0.9997482f, 1.0000000f, 0.9998567f, 0.9993046f, 0.9983255f, 0.9968987f, 0.9950000f, 0.9926005f, 0.9897426f, 0.9864444f, 0.9827241f, 0.9786000f, 0.9740837f, 0.9691712f, 0.9638568f, 0.9581349f, 0.9520000f, 0.9454504f, 0.9384992f, 0.9311628f, 0.9234576f, 0.9154000f, 0.9070064f, 0.8982772f, 0.8892048f, 0.8797816f, 0.8700000f, 0.8598613f, 0.8493920f, 0.8386220f, 0.8275813f, 0.8163000f, 0.8047947f, 0.7930820f, 0.7811920f, 0.7691547f, 0.7570000f, 0.7447541f, 0.7324224f, 0.7200036f, 0.7074965f, 0.6949000f, 0.6822192f, 0.6694716f, 0.6566744f, 0.6438448f, 0.6310000f, 0.6181555f, 0.6053144f, 0.5924756f, 0.5796379f, 0.5668000f, 0.5539611f, 0.5411372f, 0.5283528f, 0.5156323f, 0.5030000f, 0.4904688f, 0.4780304f, 0.4656776f, 0.4534032f, 0.4412000f, 0.4290800f, 0.4170360f, 0.4050320f, 0.3930320f, 0.3810000f, 0.3689184f, 0.3568272f, 0.3447768f, 0.3328176f, 0.3210000f, 0.3093381f, 0.2978504f, 0.2865936f, 0.2756245f, 0.2650000f, 0.2547632f, 0.2448896f, 0.2353344f, 0.2260528f, 0.2170000f, 0.2081616f, 0.1995488f, 0.1911552f, 0.1829744f, 0.1750000f, 0.1672235f, 0.1596464f, 0.1522776f, 0.1451259f, 0.1382000f, 0.1315003f, 0.1250248f, 0.1187792f, 0.1127691f, 0.1070000f, 0.1014762f, 0.09618864f, 0.09112296f, 0.08626485f, 0.08160000f, 0.07712064f, 0.07282552f, 0.06871008f, 0.06476976f, 0.06100000f, 0.05739621f, 0.05395504f, 0.05067376f, 0.04754965f, 0.04458000f, 0.04175872f, 0.03908496f, 0.03656384f, 0.03420048f, 0.03200000f, 0.02996261f, 0.02807664f, 0.02632936f, 0.02470805f, 0.02320000f, 0.02180077f, 0.02050112f, 0.01928108f, 0.01812069f, 0.01700000f, 0.01590379f, 0.01483718f, 0.01381068f, 0.01283478f, 0.01192000f, 0.01106831f, 0.01027339f, 0.009533311f, 0.008846157f, 0.008210000f, 0.007623781f, 0.007085424f, 0.006591476f, 0.006138485f, 0.005723000f, 0.005343059f, 0.004995796f, 0.004676404f, 0.004380075f, 0.004102000f, 0.003838453f, 0.003589099f, 0.003354219f, 0.003134093f, 0.002929000f, 0.002738139f, 0.002559876f, 0.002393244f, 0.002237275f, 0.002091000f, 0.001953587f, 0.001824580f, 0.001703580f, 0.001590187f, 0.001484000f, 0.001384496f, 0.001291268f, 0.001204092f, 0.001122744f, 0.001047000f, 0.0009765896f, 0.0009111088f, 0.0008501332f, 0.0007932384f, 0.0007400000f, 0.0006900827f, 0.0006433100f, 0.0005994960f, 0.0005584547f, 0.0005200000f, 0.0004839136f, 0.0004500528f, 0.0004183452f, 0.0003887184f, 0.0003611000f, 0.0003353835f, 0.0003114404f, 0.0002891656f, 0.0002684539f, 0.0002492000f, 0.0002313019f, 0.0002146856f, 0.0001992884f, 0.0001850475f, 0.0001719000f, 0.0001597781f, 0.0001486044f, 0.0001383016f, 0.0001287925f, 0.0001200000f, 0.0001118595f, 0.0001043224f, 0.00009733560f, 0.00009084587f, 0.00008480000f, 0.00007914667f, 0.00007385800f, 0.00006891600f, 0.00006430267f, 0.00006000000f, 0.00005598187f, 0.00005222560f, 0.00004871840f, 0.00004544747f, 0.00004240000f, 0.00003956104f, 0.00003691512f, 0.00003444868f, 0.00003214816f, 0.00003000000f, 0.00002799125f, 0.00002611356f, 0.00002436024f, 0.00002272461f, 0.00002120000f, 0.00001977855f, 0.00001845285f, 0.00001721687f, 0.00001606459f, 0.00001499000f, 0.00001398728f, 0.00001305155f, 0.00001217818f, 0.00001136254f, 0.00001060000f, 0.000009885877f, 0.000009217304f, 0.000008592362f, 0.000008009133f, 0.000007465700f, 0.000006959567f, 0.000006487995f, 0.000006048699f, 0.000005639396f, 0.000005257800f, 0.000004901771f, 0.000004569720f, 0.000004260194f, 0.000003971739f, 0.000003702900f, 0.000003452163f, 0.000003218302f, 0.000003000300f, 0.000002797139f, 0.000002607800f, 0.000002431220f, 0.000002266531f, 0.000002113013f, 0.000001969943f, 0.000001836600f, 0.000001712230f, 0.000001596228f, 0.000001488090f, 0.000001387314f, 0.000001293400f, 0.000001205820f, 0.000001124143f, 0.000001048009f, 0.0000009770578f, 0.0000009109300f, 0.0000008492513f, 0.0000007917212f, 0.0000007380904f, 0.0000006881098f, 0.0000006415300f, 0.0000005980895f, 0.0000005575746f, 0.0000005198080f, 0.0000004846123f, 0.0000004518100f}; const float cieZ[cieSize] = {0.0006061000f, 0.0006808792f, 0.0007651456f, 0.0008600124f, 0.0009665928f, 0.001086000f, 0.001220586f, 0.001372729f, 0.001543579f, 0.001734286f, 0.001946000f, 0.002177777f, 0.002435809f, 0.002731953f, 0.003078064f, 0.003486000f, 0.003975227f, 0.004540880f, 0.005158320f, 0.005802907f, 0.006450001f, 0.007083216f, 0.007745488f, 0.008501152f, 0.009414544f, 0.01054999f, 0.01196580f, 0.01365587f, 0.01558805f, 0.01773015f, 0.02005001f, 0.02251136f, 0.02520288f, 0.02827972f, 0.03189704f, 0.03621000f, 0.04143771f, 0.04750372f, 0.05411988f, 0.06099803f, 0.06785001f, 0.07448632f, 0.08136156f, 0.08915364f, 0.09854048f, 0.1102000f, 0.1246133f, 0.1417017f, 0.1613035f, 0.1832568f, 0.2074000f, 0.2336921f, 0.2626114f, 0.2947746f, 0.3307985f, 0.3713000f, 0.4162091f, 0.4654642f, 0.5196948f, 0.5795303f, 0.6456000f, 0.7184838f, 0.7967133f, 0.8778459f, 0.9594390f, 1.0390501f, 1.1153673f, 1.1884971f, 1.2581233f, 1.3239296f, 1.3856000f, 1.4426352f, 1.4948035f, 1.5421903f, 1.5848807f, 1.6229600f, 1.6564048f, 1.6852959f, 1.7098745f, 1.7303821f, 1.7470600f, 1.7600446f, 1.7696233f, 1.7762637f, 1.7804334f, 1.7826000f, 1.7829682f, 1.7816998f, 1.7791982f, 1.7758671f, 1.7721100f, 1.7682589f, 1.7640390f, 1.7589438f, 1.7524663f, 1.7441000f, 1.7335595f, 1.7208581f, 1.7059369f, 1.6887372f, 1.6692000f, 1.6475287f, 1.6234127f, 1.5960223f, 1.5645280f, 1.5281000f, 1.4861114f, 1.4395215f, 1.3898799f, 1.3387362f, 1.2876400f, 1.2374223f, 1.1878243f, 1.1387611f, 1.0901480f, 1.0419000f, 0.9941976f, 0.9473473f, 0.9014531f, 0.8566193f, 0.8129501f, 0.7705173f, 0.7294448f, 0.6899136f, 0.6521049f, 0.6162000f, 0.5823286f, 0.5504162f, 0.5203376f, 0.4919673f, 0.4651800f, 0.4399246f, 0.4161836f, 0.3938822f, 0.3729459f, 0.3533000f, 0.3348578f, 0.3175521f, 0.3013375f, 0.2861686f, 0.2720000f, 0.2588171f, 0.2464838f, 0.2347718f, 0.2234533f, 0.2123000f, 0.2011692f, 0.1901196f, 0.1792254f, 0.1685608f, 0.1582000f, 0.1481383f, 0.1383758f, 0.1289942f, 0.1200751f, 0.1117000f, 0.1039048f, 0.09666748f, 0.08998272f, 0.08384531f, 0.07824999f, 0.07320899f, 0.06867816f, 0.06456784f, 0.06078835f, 0.05725001f, 0.05390435f, 0.05074664f, 0.04775276f, 0.04489859f, 0.04216000f, 0.03950728f, 0.03693564f, 0.03445836f, 0.03208872f, 0.02984000f, 0.02771181f, 0.02569444f, 0.02378716f, 0.02198925f, 0.02030000f, 0.01871805f, 0.01724036f, 0.01586364f, 0.01458461f, 0.01340000f, 0.01230723f, 0.01130188f, 0.01037792f, 0.009529306f, 0.008749999f, 0.008035200f, 0.007381600f, 0.006785400f, 0.006242800f, 0.005749999f, 0.005303600f, 0.004899800f, 0.004534200f, 0.004202400f, 0.003900000f, 0.003623200f, 0.003370600f, 0.003141400f, 0.002934800f, 0.002749999f, 0.002585200f, 0.002438600f, 0.002309400f, 0.002196800f, 0.002100000f, 0.002017733f, 0.001948200f, 0.001889800f, 0.001840933f, 0.001800000f, 0.001766267f, 0.001737800f, 0.001711200f, 0.001683067f, 0.001650001f, 0.001610133f, 0.001564400f, 0.001513600f, 0.001458533f, 0.001400000f, 0.001336667f, 0.001270000f, 0.001205000f, 0.001146667f, 0.001100000f, 0.001068800f, 0.001049400f, 0.001035600f, 0.001021200f, 0.001000000f, 0.0009686400f, 0.0009299200f, 0.0008868800f, 0.0008425600f, 0.0008000000f, 0.0007609600f, 0.0007236800f, 0.0006859200f, 0.0006454400f, 0.0006000000f, 0.0005478667f, 0.0004916000f, 0.0004354000f, 0.0003834667f, 0.0003400000f, 0.0003072533f, 0.0002831600f, 0.0002654400f, 0.0002518133f, 0.0002400000f, 0.0002295467f, 0.0002206400f, 0.0002119600f, 0.0002021867f, 0.0001900000f, 0.0001742133f, 0.0001556400f, 0.0001359600f, 0.0001168533f, 0.0001000000f, 0.00008613333f, 0.00007460000f, 0.00006500000f, 0.00005693333f, 0.00004999999f, 0.00004416000f, 0.00003948000f, 0.00003572000f, 0.00003264000f, 0.00003000000f, 0.00002765333f, 0.00002556000f, 0.00002364000f, 0.00002181333f, 0.00002000000f, 0.00001813333f, 0.00001620000f, 0.00001420000f, 0.00001213333f, 0.00001000000f, 0.000007733333f, 0.000005400000f, 0.000003200000f, 0.000001333333f, 0.000000000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; const float cieLambda[cieSize] = {360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830}; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/lights/sky_model/sky_model.cpp000066400000000000000000000607001456566705700255630ustar00rootroot00000000000000/* This source is published under the following 3-clause BSD license. Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * None of the names of the contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // with slight modifications // Copyright 2020 Intel Corporation /* ============================================================================ This file is part of a sample implementation of the analytical skylight and solar radiance models presented in the SIGGRAPH 2012 paper "An Analytic Model for Full Spectral Sky-Dome Radiance" and the 2013 IEEE CG&A paper "Adding a Solar Radiance Function to the Hosek Skylight Model" both by Lukas Hosek and Alexander Wilkie Charles University in Prague, Czech Republic Version: 1.4a, February 22nd, 2013 Version history: 1.4a February 22nd, 2013 Removed unnecessary and counter-intuitive solar radius parameters from the interface of the colourspace sky dome initialisation functions. 1.4 February 11th, 2013 Fixed a bug which caused the relative brightness of the solar disc and the sky dome to be off by a factor of about 6. The sun was too bright: this affected both normal and alien sun scenarios. The coefficients of the solar radiance function were changed to fix this. 1.3 January 21st, 2013 (not released to the public) Added support for solar discs that are not exactly the same size as the terrestrial sun. Also added support for suns with a different emission spectrum ("Alien World" functionality). 1.2a December 18th, 2012 Fixed a mistake and some inaccuracies in the solar radiance function explanations found in ArHosekSkyModel.h. The actual source code is unchanged compared to version 1.2. 1.2 December 17th, 2012 Native RGB data and a solar radiance function that matches the turbidity conditions were added. 1.1 September 2012 The coefficients of the spectral model are now scaled so that the output is given in physical units: W / (m^-2 * sr * nm). Also, the output of the XYZ model is now no longer scaled to the range [0...1]. Instead, it is the result of a simple conversion from spectral data via the CIE 2 degree standard observer matching functions. Therefore, after multiplication with 683 lm / W, the Y channel now corresponds to luminance in lm. 1.0 May 11th, 2012 Initial release. Please visit http://cgg.mff.cuni.cz/projects/SkylightModelling/ to check if an updated version of this code has been published! ============================================================================ */ /* All instructions on how to use this code are in the accompanying header file. */ #include "sky_model.h" #include #include #include #include #include "sky_model_data_ciexyz.h" #include "sky_model_data_rgb.h" #include "sky_model_data_spectral.h" // Some macro definitions that occur elsewhere in ART, and that have to be // replicated to make this a stand-alone module. #ifndef MATH_PI #define MATH_PI 3.141592653589793 #endif #ifndef MATH_DEG_TO_RAD #define MATH_DEG_TO_RAD (MATH_PI / 180.0) #endif #ifndef DEGREES #define DEGREES *MATH_DEG_TO_RAD #endif #ifndef TERRESTRIAL_SOLAR_RADIUS #define TERRESTRIAL_SOLAR_RADIUS ((0.51 DEGREES) / 2.0) #endif #ifndef ALLOC #define ALLOC(_struct) (new (_struct)) #endif // internal definitions typedef float *ArHosekSkyModel_Dataset; typedef float *ArHosekSkyModel_Radiance_Dataset; // internal functions void ArHosekSkyModel_CookConfiguration(ArHosekSkyModel_Dataset dataset, ArHosekSkyModelConfiguration config, float turbidity, float albedo, float solar_elevation) { float *elev_matrix; int int_turbidity = (int)turbidity; float turbidity_rem = turbidity - (float)int_turbidity; solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0)); // alb 0 low turb elev_matrix = dataset + (9 * 6 * (int_turbidity - 1)); for (unsigned int i = 0; i < 9; ++i) { //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; config[i] = (1.0 - albedo) * (1.0 - turbidity_rem) * (pow(1.0 - solar_elevation, 5.0) * elev_matrix[i] + 5.0 * pow(1.0 - solar_elevation, 4.0) * solar_elevation * elev_matrix[i + 9] + 10.0 * pow(1.0 - solar_elevation, 3.0) * pow(solar_elevation, 2.0) * elev_matrix[i + 18] + 10.0 * pow(1.0 - solar_elevation, 2.0) * pow(solar_elevation, 3.0) * elev_matrix[i + 27] + 5.0 * (1.0 - solar_elevation) * pow(solar_elevation, 4.0) * elev_matrix[i + 36] + pow(solar_elevation, 5.0) * elev_matrix[i + 45]); } // alb 1 low turb elev_matrix = dataset + (9 * 6 * 10 + 9 * 6 * (int_turbidity - 1)); for (unsigned int i = 0; i < 9; ++i) { //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; config[i] += (albedo) * (1.0 - turbidity_rem) * (pow(1.0 - solar_elevation, 5.0) * elev_matrix[i] + 5.0 * pow(1.0 - solar_elevation, 4.0) * solar_elevation * elev_matrix[i + 9] + 10.0 * pow(1.0 - solar_elevation, 3.0) * pow(solar_elevation, 2.0) * elev_matrix[i + 18] + 10.0 * pow(1.0 - solar_elevation, 2.0) * pow(solar_elevation, 3.0) * elev_matrix[i + 27] + 5.0 * (1.0 - solar_elevation) * pow(solar_elevation, 4.0) * elev_matrix[i + 36] + pow(solar_elevation, 5.0) * elev_matrix[i + 45]); } if (int_turbidity == 10) return; // alb 0 high turb elev_matrix = dataset + (9 * 6 * (int_turbidity)); for (unsigned int i = 0; i < 9; ++i) { //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; config[i] += (1.0 - albedo) * (turbidity_rem) * (pow(1.0 - solar_elevation, 5.0) * elev_matrix[i] + 5.0 * pow(1.0 - solar_elevation, 4.0) * solar_elevation * elev_matrix[i + 9] + 10.0 * pow(1.0 - solar_elevation, 3.0) * pow(solar_elevation, 2.0) * elev_matrix[i + 18] + 10.0 * pow(1.0 - solar_elevation, 2.0) * pow(solar_elevation, 3.0) * elev_matrix[i + 27] + 5.0 * (1.0 - solar_elevation) * pow(solar_elevation, 4.0) * elev_matrix[i + 36] + pow(solar_elevation, 5.0) * elev_matrix[i + 45]); } // alb 1 high turb elev_matrix = dataset + (9 * 6 * 10 + 9 * 6 * (int_turbidity)); for (unsigned int i = 0; i < 9; ++i) { //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; config[i] += (albedo) * (turbidity_rem) * (pow(1.0 - solar_elevation, 5.0) * elev_matrix[i] + 5.0 * pow(1.0 - solar_elevation, 4.0) * solar_elevation * elev_matrix[i + 9] + 10.0 * pow(1.0 - solar_elevation, 3.0) * pow(solar_elevation, 2.0) * elev_matrix[i + 18] + 10.0 * pow(1.0 - solar_elevation, 2.0) * pow(solar_elevation, 3.0) * elev_matrix[i + 27] + 5.0 * (1.0 - solar_elevation) * pow(solar_elevation, 4.0) * elev_matrix[i + 36] + pow(solar_elevation, 5.0) * elev_matrix[i + 45]); } } float ArHosekSkyModel_CookRadianceConfiguration( ArHosekSkyModel_Radiance_Dataset dataset, float turbidity, float albedo, float solar_elevation) { float *elev_matrix; int int_turbidity = (int)turbidity; float turbidity_rem = turbidity - (float)int_turbidity; float res; solar_elevation = pow(solar_elevation / (MATH_PI / 2.0), (1.0 / 3.0)); // alb 0 low turb elev_matrix = dataset + (6 * (int_turbidity - 1)); //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; res = (1.0 - albedo) * (1.0 - turbidity_rem) * (pow(1.0 - solar_elevation, 5.0) * elev_matrix[0] + 5.0 * pow(1.0 - solar_elevation, 4.0) * solar_elevation * elev_matrix[1] + 10.0 * pow(1.0 - solar_elevation, 3.0) * pow(solar_elevation, 2.0) * elev_matrix[2] + 10.0 * pow(1.0 - solar_elevation, 2.0) * pow(solar_elevation, 3.0) * elev_matrix[3] + 5.0 * (1.0 - solar_elevation) * pow(solar_elevation, 4.0) * elev_matrix[4] + pow(solar_elevation, 5.0) * elev_matrix[5]); // alb 1 low turb elev_matrix = dataset + (6 * 10 + 6 * (int_turbidity - 1)); //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; res += (albedo) * (1.0 - turbidity_rem) * (pow(1.0 - solar_elevation, 5.0) * elev_matrix[0] + 5.0 * pow(1.0 - solar_elevation, 4.0) * solar_elevation * elev_matrix[1] + 10.0 * pow(1.0 - solar_elevation, 3.0) * pow(solar_elevation, 2.0) * elev_matrix[2] + 10.0 * pow(1.0 - solar_elevation, 2.0) * pow(solar_elevation, 3.0) * elev_matrix[3] + 5.0 * (1.0 - solar_elevation) * pow(solar_elevation, 4.0) * elev_matrix[4] + pow(solar_elevation, 5.0) * elev_matrix[5]); if (int_turbidity == 10) return res; // alb 0 high turb elev_matrix = dataset + (6 * (int_turbidity)); //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; res += (1.0 - albedo) * (turbidity_rem) * (pow(1.0 - solar_elevation, 5.0) * elev_matrix[0] + 5.0 * pow(1.0 - solar_elevation, 4.0) * solar_elevation * elev_matrix[1] + 10.0 * pow(1.0 - solar_elevation, 3.0) * pow(solar_elevation, 2.0) * elev_matrix[2] + 10.0 * pow(1.0 - solar_elevation, 2.0) * pow(solar_elevation, 3.0) * elev_matrix[3] + 5.0 * (1.0 - solar_elevation) * pow(solar_elevation, 4.0) * elev_matrix[4] + pow(solar_elevation, 5.0) * elev_matrix[5]); // alb 1 high turb elev_matrix = dataset + (6 * 10 + 6 * (int_turbidity)); //(1-t).^3* A1 + 3*(1-t).^2.*t * A2 + 3*(1-t) .* t .^ 2 * A3 + t.^3 * A4; res += (albedo) * (turbidity_rem) * (pow(1.0 - solar_elevation, 5.0) * elev_matrix[0] + 5.0 * pow(1.0 - solar_elevation, 4.0) * solar_elevation * elev_matrix[1] + 10.0 * pow(1.0 - solar_elevation, 3.0) * pow(solar_elevation, 2.0) * elev_matrix[2] + 10.0 * pow(1.0 - solar_elevation, 2.0) * pow(solar_elevation, 3.0) * elev_matrix[3] + 5.0 * (1.0 - solar_elevation) * pow(solar_elevation, 4.0) * elev_matrix[4] + pow(solar_elevation, 5.0) * elev_matrix[5]); return res; } float ArHosekSkyModel_GetRadianceInternal( ArHosekSkyModelConfiguration configuration, float theta, float gamma) { const float expM = exp(configuration[4] * gamma); const float rayM = cos(gamma) * cos(gamma); const float mieM = (1.0 + cos(gamma) * cos(gamma)) / pow((1.0 + configuration[8] * configuration[8] - 2.0 * configuration[8] * cos(gamma)), 1.5); const float zenith = sqrt(cos(theta)); return (1.0 + configuration[0] * exp(configuration[1] / (cos(theta) + 0.01))) * (configuration[2] + configuration[3] * expM + configuration[5] * rayM + configuration[6] * mieM + configuration[7] * zenith); } // spectral version ArHosekSkyModelState *arhosekskymodelstate_alloc_init( const float solar_elevation, const float atmospheric_turbidity, const float ground_albedo) { ArHosekSkyModelState *state = ALLOC(ArHosekSkyModelState); state->solar_radius = (0.51 DEGREES) / 2.0; state->turbidity = atmospheric_turbidity; state->albedo = ground_albedo; state->elevation = solar_elevation; for (unsigned int wl = 0; wl < 11; ++wl) { ArHosekSkyModel_CookConfiguration(datasets[wl], state->configs[wl], atmospheric_turbidity, ground_albedo, solar_elevation); state->radiances[wl] = ArHosekSkyModel_CookRadianceConfiguration( datasetsRad[wl], atmospheric_turbidity, ground_albedo, solar_elevation); state->emission_correction_factor_sun[wl] = 1.0; state->emission_correction_factor_sky[wl] = 1.0; } return state; } // 'blackbody_scaling_factor' // // Fudge factor, computed in Mathematica, to scale the results of the // following function to match the solar radiance spectrum used in the // original simulation. The scaling is done so their integrals over the // range from 380.0 to 720.0 nanometers match for a blackbody temperature // of 5800 K. // Which leaves the original spectrum being less bright overall than the 5.8k // blackbody radiation curve if the ultra-violet part of the spectrum is // also considered. But the visible brightness should be very similar. const float blackbody_scaling_factor = 3.19992 * 10E-11; // 'art_blackbody_dd_value()' function // // Blackbody radiance, Planck's formula float art_blackbody_dd_value(const float temperature, const float lambda) { float c1 = 3.74177 * 10E-17; float c2 = 0.0143878; float value; value = (c1 / (pow(lambda, 5.0))) * (1.0 / (exp(c2 / (lambda * temperature)) - 1.0)); return value; } // 'originalSolarRadianceTable[]' // // The solar spectrum incident at the top of the atmosphere, as it was used // in the brute force path tracer that generated the reference results the // model was fitted to. We need this as the yardstick to compare any altered // Blackbody emission spectra for alien world stars to. // This is just the data from the Preetham paper, extended into the UV range. const float originalSolarRadianceTable[] = {7500.0, 12500.0, 21127.5, 26760.5, 30663.7, 27825.0, 25503.8, 25134.2, 23212.1, 21526.7, 19870.8}; ArHosekSkyModelState *arhosekskymodelstate_alienworld_alloc_init( const float solar_elevation, const float solar_intensity, const float solar_surface_temperature_kelvin, const float atmospheric_turbidity, const float ground_albedo) { ArHosekSkyModelState *state = ALLOC(ArHosekSkyModelState); state->turbidity = atmospheric_turbidity; state->albedo = ground_albedo; state->elevation = solar_elevation; for (unsigned int wl = 0; wl < 11; ++wl) { // Basic init as for the normal scenario ArHosekSkyModel_CookConfiguration(datasets[wl], state->configs[wl], atmospheric_turbidity, ground_albedo, solar_elevation); state->radiances[wl] = ArHosekSkyModel_CookRadianceConfiguration( datasetsRad[wl], atmospheric_turbidity, ground_albedo, solar_elevation); // The wavelength of this band in nanometers float owl = (320.0 + 40.0 * wl) * 10E-10; // The original intensity we just computed float osr = originalSolarRadianceTable[wl]; // The intensity of a blackbody with the desired temperature // The fudge factor described above is used to make sure the BB // function matches the used radiance data reasonably well // in magnitude. float nsr = art_blackbody_dd_value(solar_surface_temperature_kelvin, owl) * blackbody_scaling_factor; // Correction factor for this waveband is simply the ratio of // the two. state->emission_correction_factor_sun[wl] = nsr / osr; } // We then compute the average correction factor of all wavebands. // Theoretically, some weighting to favour wavelengths human vision is // more sensitive to could be introduced here - think V(lambda). But // given that the whole effort is not *that* accurate to begin with (we // are talking about the appearance of alien worlds, after all), simple // averaging over the visible wavelengths (! - this is why we start at // WL #2, and only use 2-11) seems like a sane first approximation. float correctionFactor = 0.0; for (unsigned int i = 2; i < 11; i++) { correctionFactor += state->emission_correction_factor_sun[i]; } // This is the average ratio in emitted energy between our sun, and an // equally large sun with the blackbody spectrum we requested. // Division by 9 because we only used 9 of the 11 wavelengths for this // (see above). float ratio = correctionFactor / 9.0; // This ratio is then used to determine the radius of the alien sun // on the sky dome. The additional factor 'solar_intensity' can be used // to make the alien sun brighter or dimmer compared to our sun. state->solar_radius = (sqrt(solar_intensity) * TERRESTRIAL_SOLAR_RADIUS) / sqrt(ratio); // Finally, we have to reduce the scaling factor of the sky by the // ratio used to scale the solar disc size. The rationale behind this is // that the scaling factors apply to the new blackbody spectrum, which // can be more or less bright than the one our sun emits. However, we // just scaled the size of the alien solar disc so it is roughly as // bright (in terms of energy emitted) as the terrestrial sun. So the sky // dome has to be reduced in brightness appropriately - but not in an // uniform fashion across wavebands. If we did that, the sky colour would // be wrong. for (unsigned int i = 0; i < 11; i++) { state->emission_correction_factor_sky[i] = solar_intensity * state->emission_correction_factor_sun[i] / ratio; } return state; } void arhosekskymodelstate_free(ArHosekSkyModelState *state) { delete state; } float arhosekskymodel_radiance( ArHosekSkyModelState *state, float theta, float gamma, float wavelength) { int low_wl = (wavelength - 320.0) / 40.0; if (low_wl < 0 || low_wl >= 11) return 0.0f; float interp = fmod((wavelength - 320.0) / 40.0, 1.0); float val_low = ArHosekSkyModel_GetRadianceInternal(state->configs[low_wl], theta, gamma) * state->radiances[low_wl] * state->emission_correction_factor_sky[low_wl]; if (interp < 1e-6) return val_low; float result = (1.0 - interp) * val_low; if (low_wl + 1 < 11) { result += interp * ArHosekSkyModel_GetRadianceInternal( state->configs[low_wl + 1], theta, gamma) * state->radiances[low_wl + 1] * state->emission_correction_factor_sky[low_wl + 1]; } return result; } // xyz and rgb versions ArHosekSkyModelState *arhosek_xyz_skymodelstate_alloc_init( const float turbidity, const float albedo, const float elevation) { ArHosekSkyModelState *state = ALLOC(ArHosekSkyModelState); state->solar_radius = TERRESTRIAL_SOLAR_RADIUS; state->turbidity = turbidity; state->albedo = albedo; state->elevation = elevation; for (unsigned int channel = 0; channel < 3; ++channel) { ArHosekSkyModel_CookConfiguration(datasetsXYZ[channel], state->configs[channel], turbidity, albedo, elevation); state->radiances[channel] = ArHosekSkyModel_CookRadianceConfiguration( datasetsXYZRad[channel], turbidity, albedo, elevation); } return state; } ArHosekSkyModelState *arhosek_rgb_skymodelstate_alloc_init( const float turbidity, const float albedo, const float elevation) { ArHosekSkyModelState *state = ALLOC(ArHosekSkyModelState); state->solar_radius = TERRESTRIAL_SOLAR_RADIUS; state->turbidity = turbidity; state->albedo = albedo; state->elevation = elevation; for (unsigned int channel = 0; channel < 3; ++channel) { ArHosekSkyModel_CookConfiguration(datasetsRGB[channel], state->configs[channel], turbidity, albedo, elevation); state->radiances[channel] = ArHosekSkyModel_CookRadianceConfiguration( datasetsRGBRad[channel], turbidity, albedo, elevation); } return state; } float arhosek_tristim_skymodel_radiance( ArHosekSkyModelState *state, float theta, float gamma, int channel) { return ArHosekSkyModel_GetRadianceInternal( state->configs[channel], theta, gamma) * state->radiances[channel]; } const int pieces = 45; const int order = 4; float arhosekskymodel_sr_internal( ArHosekSkyModelState *state, int turbidity, int wl, float elevation) { int pos = (int)(pow(2.0 * elevation / MATH_PI, 1.0 / 3.0) * pieces); // floor if (pos > 44) pos = 44; const float break_x = pow(((float)pos / (float)pieces), 3.0) * (MATH_PI * 0.5); const float *coefs = solarDatasets[wl] + (order * pieces * turbidity + order * (pos + 1) - 1); float res = 0.0; const float x = elevation - break_x; float x_exp = 1.0; for (int i = 0; i < order; ++i) { res += x_exp * *coefs--; x_exp *= x; } return res * state->emission_correction_factor_sun[wl]; } float arhosekskymodel_solar_radiance_internal2(ArHosekSkyModelState *state, float wavelength, float elevation, float gamma) { assert(wavelength >= 320.0 && wavelength <= 720.0 && state->turbidity >= 1.0 && state->turbidity <= 10.0); int turb_low = (int)state->turbidity - 1; float turb_frac = state->turbidity - (float)(turb_low + 1); if (turb_low == 9) { turb_low = 8; turb_frac = 1.0; } int wl_low = (int)((wavelength - 320.0) / 40.0); float wl_frac = fmod(wavelength, 40.0) / 40.0; if (wl_low == 10) { wl_low = 9; wl_frac = 1.0; } float direct_radiance = (1.0 - turb_frac) * ((1.0 - wl_frac) * arhosekskymodel_sr_internal( state, turb_low, wl_low, elevation) + wl_frac * arhosekskymodel_sr_internal( state, turb_low, wl_low + 1, elevation)) + turb_frac * ((1.0 - wl_frac) * arhosekskymodel_sr_internal( state, turb_low + 1, wl_low, elevation) + wl_frac * arhosekskymodel_sr_internal( state, turb_low + 1, wl_low + 1, elevation)); float ldCoefficient[6]; for (int i = 0; i < 6; i++) ldCoefficient[i] = (1.0 - wl_frac) * limbDarkeningDatasets[wl_low][i] + wl_frac * limbDarkeningDatasets[wl_low + 1][i]; // sun distance to diameter ratio, squared const float sol_rad_sin = sin(state->solar_radius); const float ar2 = 1 / (sol_rad_sin * sol_rad_sin); const float singamma = sin(gamma); float sc2 = 1.0 - ar2 * singamma * singamma; if (sc2 < 0.0) sc2 = 0.0; float sampleCosine = sqrt(sc2); // The following will be improved in future versions of the model: // here, we directly use fitted 5th order polynomials provided by the // astronomical community for the limb darkening effect. Astronomers need // such accurate fittings for their predictions. However, this sort of // accuracy is not really needed for CG purposes, so an approximated // dataset based on quadratic polynomials will be provided in a future // release. float darkeningFactor = ldCoefficient[0] + ldCoefficient[1] * sampleCosine + ldCoefficient[2] * pow(sampleCosine, 2.0) + ldCoefficient[3] * pow(sampleCosine, 3.0) + ldCoefficient[4] * pow(sampleCosine, 4.0) + ldCoefficient[5] * pow(sampleCosine, 5.0); direct_radiance *= darkeningFactor; return direct_radiance; } float arhosekskymodel_solar_radiance( ArHosekSkyModelState *state, float theta, float gamma, float wavelength) { float direct_radiance = arhosekskymodel_solar_radiance_internal2( state, wavelength, ((MATH_PI / 2.0) - theta), gamma); float inscattered_radiance = arhosekskymodel_radiance(state, theta, gamma, wavelength); return direct_radiance + inscattered_radiance; } RenderKit-ospray-f2a61c2/modules/cpu/lights/sky_model/sky_model.h000066400000000000000000000454531456566705700252400ustar00rootroot00000000000000/* This source is published under the following 3-clause BSD license. Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * None of the names of the contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // with slight modifications // Copyright 2020 Intel Corporation /* ============================================================================ This file is part of a sample implementation of the analytical skylight and solar radiance models presented in the SIGGRAPH 2012 paper "An Analytic Model for Full Spectral Sky-Dome Radiance" and the 2013 IEEE CG&A paper "Adding a Solar Radiance Function to the Hosek Skylight Model" both by Lukas Hosek and Alexander Wilkie Charles University in Prague, Czech Republic Version: 1.4a, February 22nd, 2013 Version history: 1.4a February 22nd, 2013 Removed unnecessary and counter-intuitive solar radius parameters from the interface of the colourspace sky dome initialisation functions. 1.4 February 11th, 2013 Fixed a bug which caused the relative brightness of the solar disc and the sky dome to be off by a factor of about 6. The sun was too bright: this affected both normal and alien sun scenarios. The coefficients of the solar radiance function were changed to fix this. 1.3 January 21st, 2013 (not released to the public) Added support for solar discs that are not exactly the same size as the terrestrial sun. Also added support for suns with a different emission spectrum ("Alien World" functionality). 1.2a December 18th, 2012 Fixed a mistake and some inaccuracies in the solar radiance function explanations found in ArHosekSkyModel.h. The actual source code is unchanged compared to version 1.2. 1.2 December 17th, 2012 Native RGB data and a solar radiance function that matches the turbidity conditions were added. 1.1 September 2012 The coefficients of the spectral model are now scaled so that the output is given in physical units: W / (m^-2 * sr * nm). Also, the output of the XYZ model is now no longer scaled to the range [0...1]. Instead, it is the result of a simple conversion from spectral data via the CIE 2 degree standard observer matching functions. Therefore, after multiplication with 683 lm / W, the Y channel now corresponds to luminance in lm. 1.0 May 11th, 2012 Initial release. Please visit http://cgg.mff.cuni.cz/projects/SkylightModelling/ to check if an updated version of this code has been published! ============================================================================ */ /* This code is taken from ART, a rendering research system written in a mix of C99 / Objective C. Since ART is not a small system and is intended to be inter-operable with other libraries, and since C does not have namespaces, the structures and functions in ART all have to have somewhat wordy canonical names that begin with Ar.../ar..., like those seen in this example. Usage information: ================== Model initialisation -------------------- A separate ArHosekSkyModelState has to be maintained for each spectral band you want to use the model for. So in a renderer with 'num_channels' bands, you would need something like ArHosekSkyModelState * skymodel_state[num_channels]; You then have to allocate and initialise these states. In the following code snippet, we assume that 'albedo' is defined as float albedo[num_channels]; with a ground albedo value between [0,1] for each channel. The solar elevation is given in radians. for ( unsigned int i = 0; i < num_channels; i++ ) skymodel_state[i] = arhosekskymodelstate_alloc_init( turbidity, albedo[i], solarElevation ); Note that starting with version 1.3, there is also a second initialisation function which generates skydome states for different solar emission spectra and solar radii: 'arhosekskymodelstate_alienworld_alloc_init()'. See the notes about the "Alien World" functionality provided further down for a discussion of the usefulness and limits of that second initialisation function. Sky model states that have been initialised with either function behave in a completely identical fashion during use and cleanup. Using the model to generate skydome samples ------------------------------------------- Generating a skydome radiance spectrum "skydome_result" for a given location on the skydome determined via the angles theta and gamma works as follows: float skydome_result[num_channels]; for ( unsigned int i = 0; i < num_channels; i++ ) skydome_result[i] = arhosekskymodel_radiance( skymodel_state[i], theta, gamma, channel_center[i] ); The variable "channel_center" is assumed to hold the channel center wavelengths for each of the num_channels samples of the spectrum we are building. Cleanup after use ----------------- After rendering is complete, the content of the sky model states should be disposed of via for ( unsigned int i = 0; i < num_channels; i++ ) arhosekskymodelstate_free( skymodel_state[i] ); CIE XYZ Version of the Model ---------------------------- Usage of the CIE XYZ version of the model is exactly the same, except that num_channels is of course always 3, and that ArHosekTristimSkyModelState and arhosek_tristim_skymodel_radiance() have to be used instead of their spectral counterparts. RGB Version of the Model ------------------------ The RGB version uses sRGB primaries with a linear gamma ramp. The same set of functions as with the XYZ data is used, except the model is initialized by calling arhosek_rgb_skymodelstate_alloc_init. Solar Radiance Function ----------------------- For each position on the solar disc, this function returns the entire radiance one sees - direct emission, as well as in-scattered light in the area of the solar disc. The latter is important for low solar elevations - nice images of the setting sun would not be possible without this. This is also the reason why this function, just like the regular sky dome model evaluation function, needs access to the sky dome data structures, as these provide information on in-scattered radiance. CAVEAT #1: in this release, this function is only provided in spectral form! RGB/XYZ versions to follow at a later date. CAVEAT #2: (fixed from release 1.3 onwards) CAVEAT #3: limb darkening renders the brightness of the solar disc inhomogeneous even for high solar elevations - only taking a single sample at the centre of the sun will yield an incorrect power estimate for the solar disc! Always take multiple random samples across the entire solar disc to estimate its power! CAVEAT #4: in this version, the limb darkening calculations still use a fairly computationally expensive 5th order polynomial that was directly taken from astronomical literature. For the purposes of Computer Graphics, this is needlessly accurate, though, and will be replaced by a cheaper approximation in a future release. "Alien World" functionality --------------------------- The Hosek sky model can be used to roughly (!) predict the appearance of outdoor scenes on earth-like planets, i.e. planets of a similar size and atmospheric make-up. Since the spectral version of our model predicts sky dome luminance patterns and solar radiance independently for each waveband, and since the intensity of each waveband is solely dependent on the input radiance from the star that the world in question is orbiting, it is trivial to re-scale the wavebands to match a different star radiance. At least in theory, the spectral version of the model has always been capable of this sort of thing, and the actual sky dome and solar radiance models were actually not altered at all in this release. All we did was to add some support functionality for doing this more easily with the existing data and functions, and to add some explanations. Just use 'arhosekskymodelstate_alienworld_alloc_init()' to initialise the sky model states (you will have to provide values for star temperature and solar intensity compared to the terrestrial sun), and do everything else as you did before. CAVEAT #1: we assume the emission of the star that illuminates the alien world to be a perfect blackbody emission spectrum. This is never entirely realistic - real star emission spectra are considerably more complex than this, mainly due to absorption effects in the outer layers of stars. However, blackbody spectra are a reasonable first assumption in a usage scenario like this, where 100% accuracy is simply not necessary: for rendering purposes, there are likely no visible differences between a highly accurate solution based on a more involved simulation, and this approximation. CAVEAT #2: we always use limb darkening data from our own sun to provide this "appearance feature", even for suns of strongly different temperature. Which is presumably not very realistic, but (as with the unaltered blackbody spectrum from caveat #1) probably not a bad first guess, either. If you need more accuracy than we provide here, please make inquiries with a friendly astro-physicst of your choice. CAVEAT #3: you have to provide a value for the solar intensity of the star which illuminates the alien world. For this, please bear in mind that there is very likely a comparatively tight range of absolute solar irradiance values for which an earth-like planet with an atmosphere like the one we assume in our model can exist in the first place! Too much irradiance, and the atmosphere probably boils off into space, too little, it freezes. Which means that stars of considerably different emission colour than our sun will have to be fairly different in size from it, to still provide a reasonable and inhabitable amount of irradiance. Red stars will need to be much larger than our sun, while white or blue stars will have to be comparatively tiny. The initialisation function handles this and computes a plausible solar radius for a given emission spectrum. In terms of absolute radiometric values, you should probably not stray all too far from a solar intensity value of 1.0. CAVEAT #4: although we now support different solar radii for the actual solar disc, the sky dome luminance patterns are *not* parameterised by this value - i.e. the patterns stay exactly the same for different solar radii! Which is of course not correct. But in our experience, solar discs up to several degrees in diameter (! - our own sun is half a degree across) do not cause the luminance patterns on the sky to change perceptibly. The reason we know this is that we initially used unrealistically large suns in our brute force path tracer, in order to improve convergence speeds (which in the beginning were abysmal). Later, we managed to do the reference renderings much faster even with realistically small suns, and found that there was no real difference in skydome appearance anyway. Conclusion: changing the solar radius should not be over-done, so close orbits around red supergiants are a no-no. But for the purposes of getting a fairly credible first impression of what an alien world with a reasonably sized sun would look like, what we are doing here is probably still o.k. HINT #1: if you want to model the sky of an earth-like planet that orbits a binary star, just super-impose two of these models with solar intensity of ~0.5 each, and closely spaced solar positions. Light is additive, after all. Tattooine, here we come... :-) P.S. according to Star Wars canon, Tattooine orbits a binary that is made up of a G and K class star, respectively. So ~5500K and ~4200K should be good first guesses for their temperature. Just in case you were wondering, after reading the previous paragraph. */ #ifndef _ARHOSEK_SKYMODEL_H_ #define _ARHOSEK_SKYMODEL_H_ typedef float ArHosekSkyModelConfiguration[9]; // Spectral version of the model /* ---------------------------------------------------------------------------- ArHosekSkyModelState struct --------------------------- This struct holds the pre-computation data for one particular albedo value. Most fields are self-explanatory, but users should never directly manipulate any of them anyway. The only consistent way to manipulate such structs is via the functions 'arhosekskymodelstate_alloc_init' and 'arhosekskymodelstate_free'. 'emission_correction_factor_sky' 'emission_correction_factor_sun' The original model coefficients were fitted against the emission of our local sun. If a different solar emission is desired (i.e. if the model is being used to predict skydome appearance for an earth-like planet that orbits a different star), these correction factors, which are determined during the alloc_init step, are applied to each waveband separately (they default to 1.0 in normal usage). This is the simplest way to retrofit this sort of capability to the existing model. The different factors for sky and sun are needed since the solar disc may be of a different size compared to the terrestrial sun. ---------------------------------------------------------------------------- */ typedef struct ArHosekSkyModelState { ArHosekSkyModelConfiguration configs[11]; float radiances[11]; float turbidity; float solar_radius; float emission_correction_factor_sky[11]; float emission_correction_factor_sun[11]; float albedo; float elevation; } ArHosekSkyModelState; /* ---------------------------------------------------------------------------- arhosekskymodelstate_alloc_init() function ------------------------------------------ Initialises an ArHosekSkyModelState struct for a terrestrial setting. ---------------------------------------------------------------------------- */ ArHosekSkyModelState *arhosekskymodelstate_alloc_init( const float solar_elevation, const float atmospheric_turbidity, const float ground_albedo); /* ---------------------------------------------------------------------------- arhosekskymodelstate_alienworld_alloc_init() function ----------------------------------------------------- Initialises an ArHosekSkyModelState struct for an "alien world" setting with a sun of a surface temperature given in 'kelvin'. The parameter 'solar_intensity' controls the overall brightness of the sky, relative to the solar irradiance on Earth. A value of 1.0 yields a sky dome that is, on average over the wavelengths covered in the model (!), as bright as the terrestrial sky in radiometric terms. Which means that the solar radius has to be adjusted, since the emissivity of a solar surface with a given temperature is more or less fixed. So hotter suns have to be smaller to be equally bright as the terrestrial sun, while cooler suns have to be larger. Note that there are limits to the validity of the luminance patterns of the underlying model: see the discussion above for more on this. In particular, an alien sun with a surface temperature of only 2000 Kelvin has to be very large if it is to be as bright as the terrestrial sun - so large that the luminance patterns are no longer a really good fit in that case. If you need information about the solar radius that the model computes for a given temperature (say, for light source sampling purposes), you have to query the 'solar_radius' variable of the sky model state returned *after* running this function. ---------------------------------------------------------------------------- */ ArHosekSkyModelState *arhosekskymodelstate_alienworld_alloc_init( const float solar_elevation, const float solar_intensity, const float solar_surface_temperature_kelvin, const float atmospheric_turbidity, const float ground_albedo); void arhosekskymodelstate_free(ArHosekSkyModelState *state); float arhosekskymodel_radiance( ArHosekSkyModelState *state, float theta, float gamma, float wavelength); // CIE XYZ and RGB versions ArHosekSkyModelState *arhosek_xyz_skymodelstate_alloc_init( const float turbidity, const float albedo, const float elevation); ArHosekSkyModelState *arhosek_rgb_skymodelstate_alloc_init( const float turbidity, const float albedo, const float elevation); float arhosek_tristim_skymodel_radiance( ArHosekSkyModelState *state, float theta, float gamma, int channel); // Delivers the complete function: sky + sun, including limb darkening. // Please read the above description before using this - there are several // caveats! float arhosekskymodel_solar_radiance( ArHosekSkyModelState *state, float theta, float gamma, float wavelength); float arhosekskymodel_solar_radiance_internal2(ArHosekSkyModelState *state, float wavelength, float elevation, float gamma); #endif // _ARHOSEK_SKYMODEL_H_ RenderKit-ospray-f2a61c2/modules/cpu/lights/sky_model/sky_model_data_ciexyz.h000066400000000000000000002303761456566705700276240ustar00rootroot00000000000000/* This source is published under the following 3-clause BSD license. Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * None of the names of the contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // with slight modifications // Copyright 2020 Intel Corporation /* ============================================================================ This file is part of a sample implementation of the analytical skylight and solar radiance models presented in the SIGGRAPH 2012 paper "An Analytic Model for Full Spectral Sky-Dome Radiance" and the 2013 IEEE CG&A paper "Adding a Solar Radiance Function to the Hosek Skylight Model" both by Lukas Hosek and Alexander Wilkie Charles University in Prague, Czech Republic Version: 1.4a, February 22nd, 2013 Version history: 1.4a February 22nd, 2013 Removed unnecessary and counter-intuitive solar radius parameters from the interface of the colourspace sky dome initialisation functions. 1.4 February 11th, 2013 Fixed a bug which caused the relative brightness of the solar disc and the sky dome to be off by a factor of about 6. The sun was too bright: this affected both normal and alien sun scenarios. The coefficients of the solar radiance function were changed to fix this. 1.3 January 21st, 2013 (not released to the public) Added support for solar discs that are not exactly the same size as the terrestrial sun. Also added support for suns with a different emission spectrum ("Alien World" functionality). 1.2a December 18th, 2012 Fixed a mistake and some inaccuracies in the solar radiance function explanations found in ArHosekSkyModel.h. The actual source code is unchanged compared to version 1.2. 1.2 December 17th, 2012 Native RGB data and a solar radiance function that matches the turbidity conditions were added. 1.1 September 2012 The coefficients of the spectral model are now scaled so that the output is given in physical units: W / (m^-2 * sr * nm). Also, the output of the XYZ model is now no longer scaled to the range [0...1]. Instead, it is the result of a simple conversion from spectral data via the CIE 2 degree standard observer matching functions. Therefore, after multiplication with 683 lm / W, the Y channel now corresponds to luminance in lm. 1.0 May 11th, 2012 Initial release. Please visit http://cgg.mff.cuni.cz/projects/SkylightModelling/ to check if an updated version of this code has been published! ============================================================================ */ /* This file contains the coefficient data for the XYZ colour space version of the model. */ // Uses Sep 9 pattern / Aug 23 mean dataset static float datasetXYZ1[] = { // albedo 0, turbidity 1 -1.117001e+000, -1.867262e-001, -1.113505e+001, 1.259865e+001, -3.937339e-002, 1.167571e+000, 7.100686e-003, 3.592678e+000, 6.083296e-001, -1.152006e+000, -1.926669e-001, 6.152049e+000, -4.770802e+000, -8.704701e-002, 7.483626e-001, 3.372718e-002, 4.464592e+000, 4.036546e-001, -1.072371e+000, -2.696632e-001, 2.816168e-001, 1.820571e+000, -3.742666e-001, 2.080607e+000, -7.675295e-002, -2.835366e+000, 1.129329e+000, -1.109935e+000, -1.532764e-001, 1.198787e+000, -9.015183e-001, 5.173015e-003, 5.749178e-001, 1.075633e-001, 4.387949e+000, 2.650413e-001, -1.052297e+000, -2.229452e-001, 1.952347e+000, 5.727205e-001, -4.885070e+000, 1.984016e+000, -1.106197e-001, -4.898361e-001, 8.907873e-001, -1.070108e+000, -1.600465e-001, 1.593886e+000, -4.479251e-005, -3.306541e+000, 9.390193e-001, 9.513168e-002, 2.343583e+000, 5.335404e-001, // albedo 0, turbidity 2 -1.113253e+000, -1.699600e-001, -1.038822e+001, 1.137513e+001, -4.040911e-002, 1.037455e+000, 4.991792e-002, 4.801919e+000, 6.302710e-001, -1.135747e+000, -1.678594e-001, 4.970755e+000, -4.430230e+000, -6.657408e-002, 3.636161e-001, 1.558009e-001, 6.013370e+000, 3.959601e-001, -1.095892e+000, -2.732595e-001, 7.666496e-001, 1.350731e+000, -4.401401e-001, 2.470135e+000, -1.707929e-001, -3.260793e+000, 1.170337e+000, -1.073668e+000, -2.603929e-002, -1.944589e-001, 4.575207e-001, 6.878164e-001, -1.390770e-001, 3.690299e-001, 7.885781e+000, 1.877694e-001, -1.070091e+000, -2.798957e-001, 2.338478e+000, -2.647221e+000, -7.387808e+000, 2.329210e+000, -1.644639e-001, -2.003710e+000, 9.874527e-001, -1.067120e+000, -1.418866e-001, 1.254090e+000, 6.053048e+000, -2.918892e+000, 5.322812e-001, 1.613053e-001, 3.018161e+000, 5.274090e-001, // albedo 0, turbidity 3 -1.129483e+000, -1.890619e-001, -9.065101e+000, 9.659923e+000, -3.607819e-002, 8.314359e-001, 8.181661e-002, 4.768868e+000, 6.339777e-001, -1.146420e+000, -1.883579e-001, 3.309173e+000, -3.127882e+000, -6.938176e-002, 3.987113e-001, 1.400581e-001, 6.283042e+000, 5.267076e-001, -1.128348e+000, -2.641305e-001, 1.223176e+000, 5.514952e-002, -3.490649e-001, 1.997784e+000, -4.123709e-002, -2.251251e+000, 9.483466e-001, -1.025820e+000, 1.404690e-002, -1.187406e+000, 2.729900e+000, 5.877588e-001, -2.761140e-001, 4.602633e-001, 8.305125e+000, 3.945001e-001, -1.083957e+000, -2.606679e-001, 2.207108e+000, -7.202803e+000, -5.968103e+000, 2.129455e+000, -7.789512e-002, -1.137688e+000, 8.871769e-001, -1.062465e+000, -1.512189e-001, 1.042881e+000, 1.427839e+001, -4.242214e+000, 4.038100e-001, 1.997780e-001, 2.814449e+000, 5.803196e-001, // albedo 0, turbidity 4 -1.175099e+000, -2.410789e-001, -1.108587e+001, 1.133404e+001, -1.819300e-002, 6.772942e-001, 9.605043e-002, 4.231166e+000, 6.239972e-001, -1.224207e+000, -2.883527e-001, 3.002206e+000, -2.649612e+000, -4.795418e-002, 4.984398e-001, 3.251434e-002, 4.851611e+000, 6.551019e-001, -1.136955e+000, -2.423048e-001, 1.058823e+000, -2.489236e-001, -2.462179e-001, 1.933140e+000, 9.106828e-002, -1.905869e-001, 8.171065e-001, -1.014535e+000, -8.262500e-003, -1.448017e+000, 2.295788e+000, 3.510334e-001, -1.477418e+000, 5.432449e-001, 5.762796e+000, 4.908751e-001, -1.070666e+000, -2.379780e-001, 1.844589e+000, -5.442448e+000, -4.012768e+000, 2.945275e+000, 9.854725e-003, 8.455959e-002, 8.145030e-001, -1.071525e+000, -1.777132e-001, 8.076590e-001, 9.925865e+000, -3.324623e+000, -6.367437e-001, 2.844581e-001, 2.248384e+000, 6.544022e-001, // albedo 0, turbidity 5 -1.218818e+000, -2.952382e-001, -1.345975e+001, 1.347153e+001, -6.814585e-003, 5.079068e-001, 1.197230e-001, 3.776949e+000, 5.836961e-001, -1.409868e+000, -5.114330e-001, 2.776539e+000, -2.039001e+000, -2.673769e-002, 4.145288e-001, 7.829342e-004, 2.275883e+000, 6.629691e-001, -1.069151e+000, -9.434247e-002, 7.293972e-001, -1.222473e+000, -1.533461e-001, 2.160357e+000, 4.626837e-002, 3.852415e+000, 8.593570e-001, -1.021306e+000, -1.149551e-001, -1.108414e+000, 4.178343e+000, 4.013665e-001, -2.222814e+000, 6.929462e-001, 1.392652e+000, 4.401662e-001, -1.074251e+000, -2.224002e-001, 1.372356e+000, -8.858704e+000, -3.922660e+000, 3.020018e+000, -1.458724e-002, 1.511186e+000, 8.288064e-001, -1.062048e+000, -1.526582e-001, 4.921067e-001, 1.485522e+001, -3.229936e+000, -8.426604e-001, 3.916243e-001, 2.678994e+000, 6.689264e-001, // albedo 0, turbidity 6 -1.257023e+000, -3.364700e-001, -1.527795e+001, 1.504223e+001, 2.717715e-003, 3.029910e-001, 1.636851e-001, 3.561663e+000, 5.283161e-001, -1.635124e+000, -7.329993e-001, 3.523939e+000, -2.566337e+000, -1.902543e-002, 5.505483e-001, -6.242176e-002, 1.065992e+000, 6.654236e-001, -9.295823e-001, 4.845834e-002, -2.992990e-001, -2.001327e-001, -8.019339e-002, 1.807806e+000, 9.020277e-002, 5.095372e+000, 8.639936e-001, -1.093740e+000, -2.148608e-001, -5.216240e-001, 2.119777e+000, 9.506454e-002, -1.831439e+000, 6.961204e-001, 1.102084e-001, 4.384319e-001, -1.044181e+000, -1.849257e-001, 9.071246e-001, -4.648901e+000, -2.279385e+000, 2.356502e+000, -4.169147e-002, 1.932557e+000, 8.296550e-001, -1.061451e+000, -1.458745e-001, 2.952267e-001, 8.967214e+000, -3.726228e+000, -5.022316e-001, 5.684877e-001, 3.102347e+000, 6.658443e-001, // albedo 0, turbidity 7 -1.332391e+000, -4.127769e-001, -9.328643e+000, 9.046194e+000, 3.457775e-003, 3.377425e-001, 1.530909e-001, 3.301209e+000, 4.997917e-001, -1.932002e+000, -9.947777e-001, -2.042329e+000, 3.586940e+000, -5.642182e-002, 8.130478e-001, -8.195988e-002, 1.118294e-001, 5.617231e-001, -8.707374e-001, 1.286999e-001, 1.820054e+000, -4.674706e+000, 3.317471e-003, 5.919018e-001, 1.975278e-001, 6.686519e+000, 9.631727e-001, -1.070378e+000, -3.030579e-001, -9.041938e-001, 6.200201e+000, 1.232207e-001, -3.650628e-001, 5.029403e-001, -2.903162e+000, 3.811408e-001, -1.063035e+000, -1.637545e-001, 5.853072e-001, -7.889906e+000, -1.200641e+000, 1.035018e+000, 1.192093e-001, 3.267054e+000, 8.416151e-001, -1.053655e+000, -1.562286e-001, 2.423683e-001, 1.128575e+001, -4.363262e+000, -7.314160e-002, 5.642088e-001, 2.514023e+000, 6.670457e-001, // albedo 0, turbidity 8 -1.366112e+000, -4.718287e-001, -7.876222e+000, 7.746900e+000, -9.182309e-003, 4.716076e-001, 8.320252e-002, 3.165603e+000, 5.392334e-001, -2.468204e+000, -1.336340e+000, -5.386723e+000, 7.072672e+000, -8.329266e-002, 8.636876e-001, -1.978177e-002, -1.326218e-001, 2.979222e-001, -9.653522e-001, -2.373416e-002, 1.810250e+000, -6.467262e+000, 1.410706e-001, -4.753717e-001, 3.003095e-001, 6.551163e+000, 1.151083e+000, -8.943186e-001, -2.487152e-001, -2.308960e-001, 8.512648e+000, 1.298402e-001, 1.034705e+000, 2.303509e-001, -3.924095e+000, 2.982717e-001, -1.146999e+000, -2.318784e-001, 8.992419e-002, -9.933614e+000, -8.860920e-001, -3.071656e-002, 2.852012e-001, 3.046199e+000, 8.599001e-001, -1.032399e+000, -1.645145e-001, 2.683599e-001, 1.327701e+001, -4.407670e+000, 7.709869e-002, 4.951727e-001, 1.957277e+000, 6.630943e-001, // albedo 0, turbidity 9 -1.469070e+000, -6.135092e-001, -6.506263e+000, 6.661315e+000, -3.835383e-002, 7.150413e-001, 7.784318e-003, 2.820577e+000, 6.756784e-001, -2.501583e+000, -1.247404e+000, -1.523462e+001, 1.633191e+001, -1.204803e-002, 5.896471e-001, -2.002023e-002, 1.144647e+000, 6.177874e-002, -2.438672e+000, -1.127291e+000, 5.731172e+000, -1.021350e+001, 6.165610e-002, -7.752641e-001, 4.708254e-001, 4.176847e+000, 1.200881e+000, -1.513427e-001, 9.792731e-002, -1.612349e+000, 9.814289e+000, 5.188921e-002, 1.716403e+000, -7.039255e-002, -2.815115e+000, 3.291874e-001, -1.318511e+000, -3.650554e-001, 4.221268e-001, -9.294529e+000, -4.397520e-002, -8.100625e-001, 3.742719e-001, 1.834166e+000, 8.223450e-001, -1.016009e+000, -1.820264e-001, 1.278426e-001, 1.182696e+001, -4.801528e+000, 4.947899e-001, 4.660378e-001, 1.601254e+000, 6.702359e-001, // albedo 0, turbidity 10 -1.841310e+000, -9.781779e-001, -4.610903e+000, 4.824662e+000, -5.100806e-002, 6.463776e-001, -6.377724e-006, 2.216875e+000, 8.618530e-001, -2.376373e+000, -1.108657e+000, -1.489799e+001, 1.546458e+001, 4.091025e-002, 9.761780e-002, -1.048958e-002, 2.165834e+000, -1.609171e-001, -4.710318e+000, -2.261963e+000, 6.947327e+000, -1.034828e+001, -1.325542e-001, 7.508674e-001, 2.247553e-001, 2.873142e+000, 1.297100e+000, 2.163750e-001, -1.944345e-001, -2.437860e+000, 1.011314e+001, 4.450500e-001, 3.111492e-001, 2.751323e-001, -1.627906e+000, 2.531213e-001, -1.258794e+000, -3.524641e-001, 8.425444e-001, -1.085313e+001, -1.154381e+000, -4.638014e-001, -2.781115e-003, 4.344498e-001, 8.507091e-001, -1.018938e+000, -1.804153e-001, -6.354054e-002, 1.573150e+001, -4.386999e+000, 6.211115e-001, 5.294648e-001, 1.580749e+000, 6.586655e-001, // albedo 1, turbidity 1 -1.116416e+000, -1.917524e-001, -1.068233e+001, 1.222221e+001, -3.668978e-002, 1.054022e+000, 1.592132e-002, 3.180583e+000, 5.627370e-001, -1.132341e+000, -1.671286e-001, 5.976499e+000, -4.227366e+000, -9.542489e-002, 8.664938e-001, 8.351793e-003, 4.876068e+000, 4.492779e-001, -1.087635e+000, -3.173679e-001, 4.314407e-001, 1.100555e+000, -4.410057e-001, 1.677253e+000, -3.005925e-002, -4.201249e+000, 1.070902e+000, -1.083031e+000, -8.847705e-002, 1.291773e+000, 4.546776e-001, 3.091894e-001, 7.261760e-001, 4.203659e-002, 5.990615e+000, 3.704756e-001, -1.057899e+000, -2.246706e-001, 2.329563e+000, -1.219656e+000, -5.335260e+000, 8.545378e-001, -3.906209e-002, -9.025499e-001, 7.797348e-001, -1.073305e+000, -1.522553e-001, 1.767063e+000, 1.904280e+000, -3.101673e+000, 3.995856e-001, 2.905192e-002, 2.563977e+000, 5.753067e-001, // albedo 1, turbidity 2 -1.113674e+000, -1.759694e-001, -9.754125e+000, 1.087391e+001, -3.841093e-002, 9.524272e-001, 5.680219e-002, 4.227034e+000, 6.029571e-001, -1.126496e+000, -1.680281e-001, 5.332352e+000, -4.575579e+000, -6.761755e-002, 3.295335e-001, 1.194896e-001, 5.570901e+000, 4.536185e-001, -1.103074e+000, -2.681801e-001, 6.571479e-002, 2.396522e+000, -4.551280e-001, 2.466331e+000, -1.232022e-001, -3.023201e+000, 1.086379e+000, -1.053299e+000, -2.697173e-002, 8.379121e-001, -9.681458e-001, 5.890692e-001, -4.872027e-001, 2.936929e-001, 7.510139e+000, 3.079122e-001, -1.079553e+000, -2.710448e-001, 2.462379e+000, -3.713554e-001, -8.534512e+000, 1.828242e+000, -1.686398e-001, -1.961340e+000, 8.941077e-001, -1.069741e+000, -1.396394e-001, 1.657868e+000, 3.236313e+000, -2.706344e+000, -2.948122e-001, 1.314816e-001, 2.868457e+000, 5.413403e-001, // albedo 1, turbidity 3 -1.131649e+000, -1.954455e-001, -7.751595e+000, 8.685861e+000, -4.910871e-002, 8.992952e-001, 4.710143e-002, 4.254818e+000, 6.821116e-001, -1.156689e+000, -1.884324e-001, 3.163519e+000, -3.091522e+000, -6.613927e-002, -2.575883e-002, 1.640065e-001, 6.073643e+000, 4.453468e-001, -1.079224e+000, -2.621389e-001, 9.446437e-001, 1.448479e+000, -3.969384e-001, 2.626638e+000, -8.101186e-002, -3.016355e+000, 1.076295e+000, -1.080832e+000, 1.033057e-002, -3.500156e-001, -3.281419e-002, 5.655512e-001, -1.156742e+000, 4.534710e-001, 8.774122e+000, 2.772869e-001, -1.051202e+000, -2.679975e-001, 2.719109e+000, -2.190316e+000, -6.878798e+000, 2.250481e+000, -2.030252e-001, -2.026527e+000, 9.701096e-001, -1.089849e+000, -1.598589e-001, 1.564748e+000, 6.869187e+000, -3.053670e+000, -6.110435e-001, 1.644472e-001, 2.370452e+000, 5.511770e-001, // albedo 1, turbidity 4 -1.171419e+000, -2.429746e-001, -8.991334e+000, 9.571216e+000, -2.772861e-002, 6.688262e-001, 7.683478e-002, 3.785611e+000, 6.347635e-001, -1.228554e+000, -2.917562e-001, 2.753986e+000, -2.491780e+000, -4.663434e-002, 3.118303e-001, 7.546506e-002, 4.463096e+000, 5.955071e-001, -1.093124e+000, -2.447767e-001, 9.097406e-001, 5.448296e-001, -2.957824e-001, 2.024167e+000, -5.152333e-004, -1.069081e+000, 9.369565e-001, -1.056994e+000, 1.569507e-002, -8.217491e-001, 1.870818e+000, 7.061930e-001, -1.483928e+000, 5.978206e-001, 6.864902e+000, 3.673332e-001, -1.054871e+000, -2.758129e-001, 2.712807e+000, -5.950110e+000, -6.554039e+000, 2.447523e+000, -1.895171e-001, -1.454292e+000, 9.131738e-001, -1.100218e+000, -1.746241e-001, 1.438505e+000, 1.115481e+001, -3.266076e+000, -8.837357e-001, 1.970100e-001, 1.991595e+000, 5.907821e-001, // albedo 1, turbidity 5 -1.207267e+000, -2.913610e-001, -1.103767e+001, 1.140724e+001, -1.416800e-002, 5.564047e-001, 8.476262e-002, 3.371255e+000, 6.221335e-001, -1.429698e+000, -5.374218e-001, 2.837524e+000, -2.221936e+000, -2.422337e-002, 9.313758e-002, 7.190250e-002, 1.869022e+000, 5.609035e-001, -1.002274e+000, -6.972810e-002, 4.031308e-001, -3.932997e-001, -1.521923e-001, 2.390646e+000, -6.893990e-002, 2.999661e+000, 1.017843e+000, -1.081168e+000, -1.178666e-001, -4.968080e-001, 3.919299e+000, 6.046866e-001, -2.440615e+000, 7.891538e-001, 2.140835e+000, 2.740470e-001, -1.050727e+000, -2.307688e-001, 2.276396e+000, -9.454407e+000, -5.505176e+000, 2.992620e+000, -2.450942e-001, 6.078372e-001, 9.606765e-001, -1.103752e+000, -1.810202e-001, 1.375044e+000, 1.589095e+001, -3.438954e+000, -1.265669e+000, 2.475172e-001, 1.680768e+000, 5.978056e-001, // albedo 1, turbidity 6 -1.244324e+000, -3.378542e-001, -1.111001e+001, 1.137784e+001, -7.896794e-003, 4.808023e-001, 9.249904e-002, 3.025816e+000, 5.880239e-001, -1.593165e+000, -7.027621e-001, 2.220896e+000, -1.437709e+000, -1.534738e-002, 6.286958e-002, 6.644555e-002, 1.091727e+000, 5.470080e-001, -9.136506e-001, 1.344874e-002, 7.772636e-001, -1.209396e+000, -1.408978e-001, 2.433718e+000, -1.041938e-001, 3.791244e+000, 1.037916e+000, -1.134968e+000, -1.803315e-001, -9.267335e-001, 4.576670e+000, 6.851928e-001, -2.805000e+000, 8.687208e-001, 1.161483e+000, 2.571688e-001, -1.017037e+000, -2.053943e-001, 2.361640e+000, -9.887818e+000, -5.122889e+000, 3.287088e+000, -2.594102e-001, 8.578927e-001, 9.592340e-001, -1.118723e+000, -1.934942e-001, 1.226023e+000, 1.674140e+001, -3.277335e+000, -1.629809e+000, 2.765232e-001, 1.637713e+000, 6.113963e-001, // albedo 1, turbidity 7 -1.314779e+000, -4.119915e-001, -1.241150e+001, 1.241578e+001, 2.344284e-003, 2.980837e-001, 1.414613e-001, 2.781731e+000, 4.998556e-001, -1.926199e+000, -1.020038e+000, 2.569200e+000, -1.081159e+000, -2.266833e-002, 3.588668e-001, 8.750078e-003, -2.452171e-001, 4.796758e-001, -7.780002e-001, 1.850647e-001, 4.445456e-002, -2.409297e+000, -7.816346e-002, 1.546790e+000, -2.807227e-002, 5.998176e+000, 1.132396e+000, -1.179326e+000, -3.578330e-001, -2.392933e-001, 6.467883e+000, 5.904596e-001, -1.869975e+000, 8.045839e-001, -2.498121e+000, 1.610633e-001, -1.009956e+000, -1.311896e-001, 1.726577e+000, -1.219356e+001, -3.466239e+000, 2.343602e+000, -2.252205e-001, 2.573681e+000, 1.027109e+000, -1.112460e+000, -2.063093e-001, 1.233051e+000, 2.058946e+001, -4.578074e+000, -1.145643e+000, 3.160192e-001, 1.420159e+000, 5.860212e-001, // albedo 1, turbidity 8 -1.371689e+000, -4.914196e-001, -1.076610e+001, 1.107405e+001, -1.485077e-002, 5.936218e-001, 3.685482e-002, 2.599968e+000, 6.002204e-001, -2.436997e+000, -1.377939e+000, 2.130141e-002, 1.079593e+000, -1.796232e-002, -3.933248e-002, 1.610711e-001, -6.901181e-001, 1.206416e-001, -8.743368e-001, 7.331370e-002, 8.734259e-001, -3.743126e+000, -3.151167e-002, 1.297596e+000, -7.634926e-002, 6.532873e+000, 1.435737e+000, -9.810197e-001, -3.521634e-001, -2.855205e-001, 7.134674e+000, 6.839748e-001, -1.394841e+000, 6.952036e-001, -4.633104e+000, -2.173401e-002, -1.122958e+000, -1.691536e-001, 1.382360e+000, -1.102913e+001, -2.608171e+000, 1.865111e+000, -1.345154e-001, 3.112342e+000, 1.094134e+000, -1.075586e+000, -2.077415e-001, 1.171477e+000, 1.793270e+001, -4.656858e+000, -1.036839e+000, 3.338295e-001, 1.042793e+000, 5.739374e-001, // albedo 1, turbidity 9 -1.465871e+000, -6.364486e-001, -8.833718e+000, 9.343650e+000, -3.223600e-002, 7.552848e-001, -3.121341e-006, 2.249164e+000, 8.094662e-001, -2.448924e+000, -1.270878e+000, -4.823703e+000, 5.853058e+000, -2.149127e-002, 3.581132e-002, -1.230276e-003, 4.892553e-001, -1.597657e-001, -2.419809e+000, -1.071337e+000, 1.575648e+000, -4.983580e+000, 9.545185e-003, 5.032615e-001, 4.186266e-001, 4.634147e+000, 1.433517e+000, -1.383278e-001, -2.797095e-002, -1.943067e-001, 6.679623e+000, 4.118280e-001, -2.744289e-001, -2.118722e-002, -4.337025e+000, 1.505072e-001, -1.341872e+000, -2.518572e-001, 1.027009e+000, -6.527103e+000, -1.081271e+000, 1.015465e+000, 2.845789e-001, 2.470371e+000, 9.278120e-001, -1.040640e+000, -2.367454e-001, 1.100744e+000, 8.827253e+000, -4.560794e+000, -7.287017e-001, 2.842503e-001, 6.336593e-001, 6.327335e-001, // albedo 1, turbidity 10 -1.877993e+000, -1.025135e+000, -4.311037e+000, 4.715016e+000, -4.711631e-002, 6.335844e-001, -7.665398e-006, 1.788017e+000, 9.001409e-001, -2.281540e+000, -1.137668e+000, -1.036869e+001, 1.136254e+001, 1.961739e-002, -9.836174e-002, -6.734567e-003, 1.320918e+000, -2.400807e-001, -4.904054e+000, -2.315781e+000, 5.735999e+000, -8.626257e+000, -1.255643e-001, 1.545446e+000, 1.396860e-001, 2.972897e+000, 1.429934e+000, 4.077067e-001, -1.833688e-001, -2.450939e+000, 9.119433e+000, 4.505361e-001, -1.340828e+000, 3.973690e-001, -1.785370e+000, 9.628711e-002, -1.296052e+000, -3.250526e-001, 1.813294e+000, -1.031485e+001, -1.388690e+000, 1.239733e+000, -8.989196e-002, -3.389637e-001, 9.639560e-001, -1.062181e+000, -2.423444e-001, 7.577592e-001, 1.566938e+001, -4.462264e+000, -5.742810e-001, 3.262259e-001, 9.461672e-001, 6.232887e-001, }; static float datasetXYZRad1[] = { // albedo 0, turbidity 1 1.560219e+000, 1.417388e+000, 1.206927e+000, 1.091949e+001, 5.931416e+000, 7.304788e+000, // albedo 0, turbidity 2 1.533049e+000, 1.560532e+000, 3.685059e-001, 1.355040e+001, 5.543711e+000, 7.792189e+000, // albedo 0, turbidity 3 1.471043e+000, 1.746088e+000, -9.299697e-001, 1.720362e+001, 5.473384e+000, 8.336416e+000, // albedo 0, turbidity 4 1.355991e+000, 2.109348e+000, -3.295855e+000, 2.264843e+001, 5.454607e+000, 9.304656e+000, // albedo 0, turbidity 5 1.244963e+000, 2.547533e+000, -5.841485e+000, 2.756879e+001, 5.576104e+000, 1.043287e+001, // albedo 0, turbidity 6 1.175532e+000, 2.784634e+000, -7.212225e+000, 2.975347e+001, 6.472980e+000, 1.092331e+001, // albedo 0, turbidity 7 1.082973e+000, 3.118094e+000, -8.934293e+000, 3.186879e+001, 8.473885e+000, 1.174019e+001, // albedo 0, turbidity 8 9.692500e-001, 3.349574e+000, -1.003810e+001, 3.147654e+001, 1.338931e+001, 1.272547e+001, // albedo 0, turbidity 9 8.547044e-001, 3.151538e+000, -9.095567e+000, 2.554995e+001, 2.273219e+001, 1.410398e+001, // albedo 0, turbidity 10 7.580340e-001, 2.311153e+000, -5.170814e+000, 1.229669e+001, 3.686529e+001, 1.598882e+001, // albedo 1, turbidity 1 1.664273e+000, 1.574468e+000, 1.422078e+000, 9.768247e+000, 1.447338e+001, 1.644988e+001, // albedo 1, turbidity 2 1.638295e+000, 1.719586e+000, 5.786675e-001, 1.239846e+001, 1.415419e+001, 1.728605e+001, // albedo 1, turbidity 3 1.572623e+000, 1.921559e+000, -7.714802e-001, 1.609246e+001, 1.420954e+001, 1.825908e+001, // albedo 1, turbidity 4 1.468395e+000, 2.211970e+000, -2.845869e+000, 2.075027e+001, 1.524822e+001, 1.937622e+001, // albedo 1, turbidity 5 1.355047e+000, 2.556469e+000, -4.960920e+000, 2.460237e+001, 1.648360e+001, 2.065648e+001, // albedo 1, turbidity 6 1.291642e+000, 2.742036e+000, -6.061967e+000, 2.602002e+001, 1.819144e+001, 2.116712e+001, // albedo 1, turbidity 7 1.194565e+000, 2.972120e+000, -7.295779e+000, 2.691805e+001, 2.124880e+001, 2.201819e+001, // albedo 1, turbidity 8 1.083631e+000, 3.047021e+000, -7.766096e+000, 2.496261e+001, 2.744264e+001, 2.291875e+001, // albedo 1, turbidity 9 9.707994e-001, 2.736459e+000, -6.308284e+000, 1.760860e+001, 3.776291e+001, 2.392150e+001, // albedo 1, turbidity 10 8.574294e-001, 1.865155e+000, -2.364707e+000, 4.337793e+000, 5.092831e+001, 2.523432e+001, }; static float datasetXYZ2[] = { // albedo 0, turbidity 1 -1.127942e+000, -1.905548e-001, -1.252356e+001, 1.375799e+001, -3.624732e-002, 1.055453e+000, 1.385036e-002, 4.176970e+000, 5.928345e-001, -1.155260e+000, -1.778135e-001, 6.216056e+000, -5.254116e+000, -8.787445e-002, 8.434621e-001, 4.025734e-002, 6.195322e+000, 3.111856e-001, -1.125624e+000, -3.217593e-001, 5.043919e-001, 1.686284e+000, -3.536071e-001, 1.476321e+000, -7.899019e-002, -4.522531e+000, 1.271691e+000, -1.081801e+000, -1.033234e-001, 9.995550e-001, 7.482946e-003, -6.776018e-002, 1.463141e+000, 9.492021e-002, 5.612723e+000, 1.298846e-001, -1.075320e+000, -2.402711e-001, 2.141284e+000, -1.203359e+000, -4.945188e+000, 1.437221e+000, -8.096750e-002, -1.028378e+000, 1.004164e+000, -1.073337e+000, -1.516517e-001, 1.639379e+000, 2.304669e+000, -3.214244e+000, 1.286245e+000, 5.613957e-002, 2.480902e+000, 4.999363e-001, // albedo 0, turbidity 2 -1.128399e+000, -1.857793e-001, -1.089863e+001, 1.172984e+001, -3.768099e-002, 9.439285e-001, 4.869335e-002, 4.845114e+000, 6.119211e-001, -1.114002e+000, -1.399280e-001, 4.963800e+000, -4.685500e+000, -7.780879e-002, 4.049736e-001, 1.586297e-001, 7.770264e+000, 3.449006e-001, -1.185472e+000, -3.403543e-001, 6.588322e-001, 1.133713e+000, -4.118674e-001, 2.061191e+000, -1.882768e-001, -4.372586e+000, 1.223530e+000, -1.002272e+000, 2.000703e-002, 7.073269e-002, 1.485075e+000, 5.005589e-001, 4.301494e-001, 3.626541e-001, 7.921098e+000, 1.574766e-001, -1.121006e+000, -3.007777e-001, 2.242051e+000, -4.571561e+000, -7.761071e+000, 2.053404e+000, -1.524018e-001, -1.886162e+000, 1.018208e+000, -1.058864e+000, -1.358673e-001, 1.389667e+000, 8.633409e+000, -3.437249e+000, 7.295429e-001, 1.514700e-001, 2.842513e+000, 5.014325e-001, // albedo 0, turbidity 3 -1.144464e+000, -2.043799e-001, -1.020188e+001, 1.071247e+001, -3.256693e-002, 7.860205e-001, 6.872719e-002, 4.824771e+000, 6.259836e-001, -1.170104e+000, -2.118626e-001, 4.391405e+000, -4.198900e+000, -7.111559e-002, 3.890442e-001, 1.024831e-001, 6.282535e+000, 5.365688e-001, -1.129171e+000, -2.552880e-001, 2.238298e-001, 7.314295e-001, -3.562730e-001, 1.881931e+000, -3.078716e-002, -1.039120e+000, 9.096301e-001, -1.042294e+000, 4.450203e-003, -5.116033e-001, 2.627589e+000, 6.098996e-001, -1.264638e-001, 4.325281e-001, 7.080503e+000, 4.583646e-001, -1.082293e+000, -2.723056e-001, 2.065076e+000, -8.143133e+000, -7.892212e+000, 2.142231e+000, -7.106240e-002, -1.122398e+000, 8.338505e-001, -1.071715e+000, -1.426568e-001, 1.095351e+000, 1.729783e+001, -3.851931e+000, 4.360514e-001, 2.114440e-001, 2.970832e+000, 5.944389e-001, // albedo 0, turbidity 4 -1.195909e+000, -2.590449e-001, -1.191037e+001, 1.207947e+001, -1.589842e-002, 6.297846e-001, 9.054772e-002, 4.285959e+000, 5.933752e-001, -1.245763e+000, -3.316637e-001, 4.293660e+000, -3.694011e+000, -4.699947e-002, 4.843684e-001, 2.130425e-002, 4.097549e+000, 6.530809e-001, -1.148742e+000, -1.902509e-001, -2.393233e-001, -2.441254e-001, -2.610918e-001, 1.846988e+000, 3.532866e-002, 2.660106e+000, 8.358294e-001, -1.016080e+000, -7.444960e-002, -5.053436e-001, 4.388855e+000, 6.054987e-001, -1.208300e+000, 5.817215e-001, 2.543570e+000, 4.726568e-001, -1.072027e+000, -2.101440e-001, 1.518378e+000, -1.060119e+001, -6.016546e+000, 2.649475e+000, -5.166992e-002, 1.571269e+000, 8.344622e-001, -1.072365e+000, -1.511201e-001, 7.478010e-001, 1.900732e+001, -3.950387e+000, -3.473907e-001, 3.797211e-001, 2.782949e+000, 6.296808e-001, // albedo 0, turbidity 5 -1.239423e+000, -3.136289e-001, -1.351100e+001, 1.349468e+001, -7.070423e-003, 5.012315e-001, 1.106008e-001, 3.803619e+000, 5.577948e-001, -1.452524e+000, -5.676944e-001, 2.993153e+000, -2.277288e+000, -2.168954e-002, 3.056720e-001, 1.152338e-002, 1.852697e+000, 6.427228e-001, -1.061421e+000, -4.590521e-002, 6.057022e-001, -1.096835e+000, -1.504952e-001, 2.344921e+000, -5.491832e-002, 5.268322e+000, 9.082253e-001, -1.042373e+000, -1.769498e-001, -1.075388e+000, 3.831712e+000, 3.154140e-001, -2.416458e+000, 7.909032e-001, -1.492892e-002, 3.854049e-001, -1.064159e+000, -1.892684e-001, 1.438685e+000, -8.166362e+000, -3.616364e+000, 3.275206e+000, -1.203825e-001, 2.039491e+000, 8.688057e-001, -1.070120e+000, -1.569508e-001, 4.124760e-001, 1.399683e+001, -3.547085e+000, -1.046326e+000, 4.973825e-001, 2.791231e+000, 6.503286e-001, // albedo 0, turbidity 6 -1.283579e+000, -3.609518e-001, -1.335397e+001, 1.315248e+001, -4.431938e-004, 3.769526e-001, 1.429824e-001, 3.573613e+000, 4.998696e-001, -1.657952e+000, -7.627948e-001, 1.958222e+000, -7.949816e-001, -2.882837e-002, 5.356149e-001, -5.191946e-002, 8.869955e-001, 6.263320e-001, -9.527600e-001, 6.494189e-002, 5.361303e-001, -2.129590e+000, -9.258630e-002, 1.604776e+000, 5.067770e-002, 6.376055e+000, 9.138052e-001, -1.080827e+000, -2.523120e-001, -7.154262e-001, 4.120085e+000, 1.878228e-001, -1.492158e+000, 6.881655e-001, -1.446611e+000, 4.040631e-001, -1.054075e+000, -1.665498e-001, 9.191052e-001, -6.636943e+000, -1.894826e+000, 2.107810e+000, -3.680499e-002, 2.655452e+000, 8.413840e-001, -1.061127e+000, -1.448849e-001, 2.667493e-001, 1.034103e+001, -4.285769e+000, -3.874504e-001, 5.998752e-001, 3.132426e+000, 6.652753e-001, // albedo 0, turbidity 7 -1.347345e+000, -4.287832e-001, -9.305553e+000, 9.133813e+000, -3.173527e-003, 3.977564e-001, 1.151420e-001, 3.320564e+000, 4.998134e-001, -1.927296e+000, -9.901372e-001, -2.593499e+000, 4.087421e+000, -5.833993e-002, 8.158929e-001, -4.681279e-002, 2.423716e-001, 4.938052e-001, -9.470092e-001, 7.325237e-002, 2.064735e+000, -5.167540e+000, -1.313751e-002, 4.832169e-001, 1.126295e-001, 6.970522e+000, 1.035022e+000, -1.022557e+000, -2.762616e-001, -9.375748e-001, 6.696739e+000, 2.200765e-001, -1.133253e-001, 5.492505e-001, -3.109391e+000, 3.321914e-001, -1.087444e+000, -1.836263e-001, 6.225024e-001, -8.576765e+000, -1.107637e+000, 7.859427e-001, 9.910909e-002, 3.112938e+000, 8.596261e-001, -1.051544e+000, -1.546262e-001, 2.371731e-001, 1.200502e+001, -4.527291e+000, 7.268862e-002, 5.571478e-001, 2.532873e+000, 6.662000e-001, // albedo 0, turbidity 8 -1.375576e+000, -4.840019e-001, -8.121290e+000, 8.058140e+000, -1.445661e-002, 5.123314e-001, 5.813321e-002, 3.203219e+000, 5.442318e-001, -2.325221e+000, -1.241463e+000, -7.063430e+000, 8.741369e+000, -7.829950e-002, 8.844273e-001, -3.471106e-002, 1.740583e-001, 2.814079e-001, -1.228700e+000, -2.013412e-001, 2.949042e+000, -7.371945e+000, 1.071753e-001, -2.491970e-001, 2.265223e-001, 6.391504e+000, 1.172389e+000, -7.601786e-001, -1.680631e-001, -7.584444e-001, 8.541356e+000, 8.222291e-002, 6.729633e-001, 3.206615e-001, -3.700940e+000, 2.710054e-001, -1.191166e+000, -2.672347e-001, 2.927498e-001, -9.713613e+000, -4.783721e-001, 2.352803e-001, 2.161949e-001, 2.691481e+000, 8.745447e-001, -1.030135e+000, -1.653301e-001, 2.263443e-001, 1.296157e+001, -4.650644e+000, 7.055709e-003, 5.091975e-001, 2.000370e+000, 6.603839e-001, // albedo 0, turbidity 9 -1.508018e+000, -6.460933e-001, -6.402745e+000, 6.545995e+000, -3.750320e-002, 6.921803e-001, 3.309819e-003, 2.797527e+000, 6.978446e-001, -2.333308e+000, -1.167837e+000, -1.746787e+001, 1.868630e+001, -8.948229e-003, 5.621946e-001, -3.402626e-002, 1.217943e+000, 1.149865e-002, -2.665953e+000, -1.226307e+000, 7.169725e+000, -1.159434e+001, 3.583420e-002, -3.074378e-001, 3.412248e-001, 4.422122e+000, 1.283791e+000, -9.705116e-002, 8.312991e-002, -2.160462e+000, 1.028235e+001, 3.543357e-002, 1.032049e+000, 1.058310e-001, -2.972898e+000, 2.418628e-001, -1.329617e+000, -3.699557e-001, 5.560117e-001, -9.730113e+000, 9.938865e-002, -3.071488e-001, 2.510691e-001, 1.777111e+000, 8.705142e-001, -1.019387e+000, -1.893247e-001, 1.194079e-001, 1.239436e+001, -4.799224e+000, 2.940213e-001, 4.841268e-001, 1.529724e+000, 6.582615e-001, // albedo 0, turbidity 10 -1.896737e+000, -1.005442e+000, -6.411032e+000, 6.548220e+000, -3.227596e-002, 5.717262e-001, -8.115192e-006, 2.296704e+000, 9.000749e-001, -2.411116e+000, -1.225587e+000, -1.753629e+001, 1.829393e+001, 1.247555e-002, 2.364616e-001, -5.114637e-003, 1.603778e+000, -2.224156e-001, -4.707121e+000, -2.074977e+000, 7.942300e+000, -1.132407e+001, -5.415654e-002, 5.446811e-001, 1.032493e-001, 4.010235e+000, 1.369802e+000, 1.010482e-001, -4.013305e-001, -2.674579e+000, 9.779409e+000, 1.782506e-001, 7.053045e-001, 4.200002e-001, -2.400671e+000, 1.953165e-001, -1.243526e+000, -3.391255e-001, 8.848882e-001, -9.789025e+000, -3.997324e-001, -9.546227e-001, -1.044017e-001, 6.010593e-001, 8.714462e-001, -1.014633e+000, -1.730009e-001, -7.738934e-002, 1.390903e+001, -4.847307e+000, 1.076059e+000, 5.685743e-001, 1.572992e+000, 6.561432e-001, // albedo 1, turbidity 1 -1.122998e+000, -1.881183e-001, -1.030709e+001, 1.158932e+001, -4.079495e-002, 9.603774e-001, 3.079436e-002, 4.009235e+000, 5.060745e-001, -1.134790e+000, -1.539688e-001, 5.478405e+000, -4.217270e+000, -1.043858e-001, 7.165008e-001, 1.524765e-002, 6.473623e+000, 4.207882e-001, -1.134957e+000, -3.513318e-001, 7.393837e-001, 1.354415e+000, -4.764078e-001, 1.690441e+000, -5.492640e-002, -5.563523e+000, 1.145743e+000, -1.058344e+000, -5.758503e-002, 1.168230e+000, 3.269824e-001, 1.795193e-001, 7.849011e-001, 7.441853e-002, 6.904804e+000, 2.818790e-001, -1.075194e+000, -2.355813e-001, 2.463685e+000, -1.536505e+000, -7.505771e+000, 9.619712e-001, -6.465851e-002, -1.355492e+000, 8.489847e-001, -1.079030e+000, -1.465328e-001, 1.773838e+000, 2.310131e+000, -3.136065e+000, 3.507952e-001, 4.435014e-002, 2.819225e+000, 5.689008e-001, // albedo 1, turbidity 2 -1.125833e+000, -1.870849e-001, -9.555833e+000, 1.059713e+001, -4.225402e-002, 9.164663e-001, 4.338796e-002, 4.400980e+000, 6.056119e-001, -1.127440e+000, -1.551891e-001, 4.755621e+000, -4.408806e+000, -7.851763e-002, 2.268284e-001, 1.460070e-001, 7.048003e+000, 3.525997e-001, -1.143788e+000, -3.170178e-001, 5.480669e-001, 2.041830e+000, -4.532139e-001, 2.302233e+000, -1.887419e-001, -4.489221e+000, 1.250967e+000, -1.032849e+000, 7.376031e-003, 5.666073e-001, -2.312203e-001, 4.862894e-001, -1.748294e-001, 3.572870e-001, 8.380522e+000, 1.302333e-001, -1.093728e+000, -2.786977e-001, 2.641272e+000, -1.507494e+000, -8.731243e+000, 1.684055e+000, -2.023377e-001, -2.176398e+000, 1.013249e+000, -1.076578e+000, -1.456205e-001, 1.693935e+000, 2.945003e+000, -2.822673e+000, -2.520033e-001, 1.517034e-001, 2.649109e+000, 5.179094e-001, // albedo 1, turbidity 3 -1.146417e+000, -2.119353e-001, -7.187525e+000, 8.058599e+000, -5.256438e-002, 8.375733e-001, 3.887093e-002, 4.222111e+000, 6.695347e-001, -1.173674e+000, -2.067025e-001, 2.899359e+000, -2.804918e+000, -8.473899e-002, 3.944225e-003, 1.340641e-001, 6.160887e+000, 4.527141e-001, -1.090098e+000, -2.599633e-001, 9.180856e-001, 1.092710e+000, -4.215019e-001, 2.427660e+000, -9.277667e-002, -2.123523e+000, 1.058159e+000, -1.084460e+000, 8.056181e-003, -2.453510e-001, 6.619567e-001, 4.668118e-001, -9.526719e-001, 4.648454e-001, 8.001572e+000, 3.054194e-001, -1.053728e+000, -2.765784e-001, 2.792388e+000, -3.489517e+000, -8.150535e+000, 2.195757e+000, -2.017234e-001, -2.128017e+000, 9.326589e-001, -1.099348e+000, -1.593939e-001, 1.568292e+000, 7.247853e+000, -2.933000e+000, -5.890481e-001, 1.724440e-001, 2.433484e+000, 5.736558e-001, // albedo 1, turbidity 4 -1.185983e+000, -2.581184e-001, -7.761056e+000, 8.317053e+000, -3.351773e-002, 6.676667e-001, 5.941733e-002, 3.820727e+000, 6.324032e-001, -1.268591e+000, -3.398067e-001, 2.348503e+000, -2.023779e+000, -5.368458e-002, 1.083282e-001, 8.402858e-002, 3.910254e+000, 5.577481e-001, -1.071353e+000, -1.992459e-001, 7.878387e-001, 1.974702e-001, -3.033058e-001, 2.335298e+000, -8.205259e-002, 7.954454e-001, 9.972312e-001, -1.089513e+000, -3.104364e-002, -5.995746e-001, 2.330281e+000, 6.581939e-001, -1.821467e+000, 6.679973e-001, 5.090195e+000, 3.125161e-001, -1.040214e+000, -2.570934e-001, 2.660489e+000, -6.506045e+000, -7.053586e+000, 2.763153e+000, -2.433632e-001, -7.648176e-001, 9.452937e-001, -1.116052e+000, -1.831993e-001, 1.457694e+000, 1.163608e+001, -3.216426e+000, -1.045594e+000, 2.285002e-001, 1.817407e+000, 5.810396e-001, // albedo 1, turbidity 5 -1.230134e+000, -3.136264e-001, -8.909301e+000, 9.145006e+000, -1.055387e-002, 4.467317e-001, 1.016826e-001, 3.342964e+000, 5.633840e-001, -1.442907e+000, -5.593147e-001, 2.156447e+000, -1.241657e+000, -3.512130e-002, 3.050274e-001, 1.797175e-002, 1.742358e+000, 5.977153e-001, -1.027627e+000, -6.481539e-002, 4.351975e-001, -1.051677e+000, -2.030672e-001, 1.942684e+000, -3.615993e-002, 4.050266e+000, 9.801624e-001, -1.082110e+000, -1.578209e-001, -3.397511e-001, 4.163851e+000, 6.650368e-001, -1.841730e+000, 7.062544e-001, 6.789881e-001, 3.172623e-001, -1.047447e+000, -1.977560e-001, 2.183364e+000, -8.805249e+000, -5.483962e+000, 2.551309e+000, -1.779640e-001, 1.519501e+000, 9.212536e-001, -1.111853e+000, -1.935736e-001, 1.394408e+000, 1.392405e+001, -3.465430e+000, -1.068432e+000, 2.388671e-001, 1.455336e+000, 6.233425e-001, // albedo 1, turbidity 6 -1.262238e+000, -3.546341e-001, -1.008703e+001, 1.020084e+001, -1.852187e-003, 3.537580e-001, 1.239199e-001, 3.056093e+000, 5.132052e-001, -1.613810e+000, -7.355585e-001, 2.760123e+000, -1.685253e+000, -2.517552e-002, 2.914258e-001, 4.743448e-003, 8.689596e-001, 5.674192e-001, -9.462336e-001, 2.950767e-002, -2.613816e-001, -7.398653e-001, -1.315558e-001, 1.901042e+000, -6.447844e-002, 4.969341e+000, 1.027342e+000, -1.111481e+000, -2.194054e-001, -9.004538e-002, 3.983442e+000, 4.871278e-001, -1.965315e+000, 7.956121e-001, -2.363225e-001, 2.718037e-001, -1.036397e+000, -1.827106e-001, 1.964747e+000, -8.870759e+000, -4.208011e+000, 2.461215e+000, -2.158905e-001, 1.561676e+000, 9.436866e-001, -1.113769e+000, -1.947819e-001, 1.300720e+000, 1.516476e+001, -4.088732e+000, -1.069384e+000, 2.836434e-001, 1.671451e+000, 6.229612e-001, // albedo 1, turbidity 7 -1.328069e+000, -4.244047e-001, -8.417040e+000, 8.552244e+000, -6.813504e-003, 4.127422e-001, 9.619897e-002, 2.854227e+000, 5.059880e-001, -1.927552e+000, -1.025290e+000, 9.529576e-001, 4.255950e-001, -3.738779e-002, 2.584586e-001, 4.911004e-002, -2.640913e-001, 4.138626e-001, -8.488094e-001, 1.435988e-001, 6.356807e-001, -2.895732e+000, -8.473961e-002, 1.701305e+000, -1.323908e-001, 6.499338e+000, 1.210928e+000, -1.128313e+000, -3.397048e-001, -4.043140e-001, 6.265097e+000, 5.482395e-001, -2.057614e+000, 8.884087e-001, -2.943879e+000, 9.760301e-002, -1.039764e+000, -1.494772e-001, 1.781915e+000, -1.153012e+001, -3.379232e+000, 2.517231e+000, -2.764393e-001, 2.588849e+000, 1.052120e+000, -1.108447e+000, -2.012251e-001, 1.198640e+000, 1.925331e+001, -4.423892e+000, -1.257122e+000, 3.395690e-001, 1.481220e+000, 5.880175e-001, // albedo 1, turbidity 8 -1.374185e+000, -4.967434e-001, -7.401318e+000, 7.724021e+000, -2.345723e-002, 5.979653e-001, 2.436346e-002, 2.658970e+000, 6.014891e-001, -2.310933e+000, -1.290290e+000, -1.301909e+000, 2.557806e+000, -3.744449e-002, 8.982861e-002, 1.090613e-001, -4.398363e-001, 1.184329e-001, -1.124730e+000, -9.921830e-002, 1.366902e+000, -4.172489e+000, -5.078016e-002, 1.393597e+000, -9.323843e-002, 6.452721e+000, 1.435913e+000, -8.468477e-001, -2.744819e-001, -4.347200e-001, 6.713362e+000, 6.127133e-001, -1.685634e+000, 7.360941e-001, -4.535502e+000, -2.920866e-002, -1.165242e+000, -2.008697e-001, 1.438778e+000, -1.008936e+001, -2.214771e+000, 2.102909e+000, -1.763085e-001, 2.859075e+000, 1.093470e+000, -1.074614e+000, -2.066374e-001, 1.131891e+000, 1.630063e+001, -4.801441e+000, -1.112590e+000, 3.595785e-001, 1.122227e+000, 5.794610e-001, // albedo 1, turbidity 9 -1.521515e+000, -6.835604e-001, -5.571044e+000, 6.028774e+000, -4.253715e-002, 6.875746e-001, -5.279456e-006, 2.180150e+000, 8.487705e-001, -2.240415e+000, -1.171166e+000, -7.182771e+000, 8.417068e+000, -1.932866e-002, 1.101887e-001, -1.098862e-002, 6.242195e-001, -2.393875e-001, -2.712354e+000, -1.198830e+000, 3.180200e+000, -6.768130e+000, -2.563386e-003, 7.984607e-001, 2.764376e-001, 4.695358e+000, 1.557045e+000, -3.655172e-002, -2.142321e-002, -9.138120e-001, 7.932786e+000, 3.516542e-001, -7.994343e-001, 1.786761e-001, -4.208399e+000, 1.820576e-002, -1.368610e+000, -2.656212e-001, 1.249397e+000, -8.317818e+000, -8.962772e-001, 1.423249e+000, 1.478381e-001, 2.191660e+000, 1.007748e+000, -1.041753e+000, -2.453366e-001, 1.061102e+000, 1.130172e+001, -4.739312e+000, -9.223334e-001, 2.982776e-001, 6.162931e-001, 6.080302e-001, // albedo 1, turbidity 10 -1.989159e+000, -1.095160e+000, -2.915550e+000, 3.275339e+000, -5.735765e-002, 5.742174e-001, -7.683288e-006, 1.763400e+000, 9.001342e-001, -2.070020e+000, -1.086338e+000, -1.095898e+001, 1.206960e+001, 3.780123e-002, -1.774699e-002, -5.881348e-004, 1.333819e+000, -2.605423e-001, -5.249653e+000, -2.383040e+000, 6.160406e+000, -9.097138e+000, -1.955319e-001, 1.651785e+000, 6.016463e-004, 3.021824e+000, 1.493574e+000, 4.685432e-001, -2.358662e-001, -2.666433e+000, 9.685763e+000, 5.804928e-001, -1.521875e+000, 5.668989e-001, -1.548136e+000, 1.688642e-002, -1.296891e+000, -3.449031e-001, 1.928548e+000, -1.167560e+001, -1.627615e+000, 1.355603e+000, -1.929074e-001, -6.568952e-001, 1.009774e+000, -1.067288e+000, -2.410392e-001, 7.147961e-001, 1.783840e+001, -4.374399e+000, -6.588777e-001, 3.329831e-001, 1.012066e+000, 6.118645e-001, }; static float datasetXYZRad2[] = { // albedo 0, turbidity 1 1.632341e+000, 1.395230e+000, 1.375634e+000, 1.238193e+001, 5.921102e+000, 7.766508e+000, // albedo 0, turbidity 2 1.597115e+000, 1.554617e+000, 3.932382e-001, 1.505284e+001, 5.725234e+000, 8.158155e+000, // albedo 0, turbidity 3 1.522034e+000, 1.844545e+000, -1.322862e+000, 1.918382e+001, 5.440769e+000, 8.837119e+000, // albedo 0, turbidity 4 1.403048e+000, 2.290852e+000, -4.013792e+000, 2.485100e+001, 5.521888e+000, 9.845547e+000, // albedo 0, turbidity 5 1.286364e+000, 2.774498e+000, -6.648221e+000, 2.964151e+001, 5.923777e+000, 1.097075e+001, // albedo 0, turbidity 6 1.213544e+000, 3.040195e+000, -8.092676e+000, 3.186082e+001, 6.789782e+000, 1.158899e+001, // albedo 0, turbidity 7 1.122622e+000, 3.347465e+000, -9.649016e+000, 3.343824e+001, 9.347715e+000, 1.231374e+001, // albedo 0, turbidity 8 1.007356e+000, 3.543858e+000, -1.053520e+001, 3.239842e+001, 1.483962e+001, 1.331718e+001, // albedo 0, turbidity 9 8.956642e-001, 3.278700e+000, -9.254933e+000, 2.557923e+001, 2.489677e+001, 1.476166e+001, // albedo 0, turbidity 10 7.985143e-001, 2.340404e+000, -4.928274e+000, 1.141787e+001, 3.961501e+001, 1.682448e+001, // albedo 1, turbidity 1 1.745162e+000, 1.639467e+000, 1.342721e+000, 1.166033e+001, 1.490124e+001, 1.774031e+001, // albedo 1, turbidity 2 1.708439e+000, 1.819144e+000, 2.834399e-001, 1.448066e+001, 1.459214e+001, 1.858679e+001, // albedo 1, turbidity 3 1.631720e+000, 2.094799e+000, -1.378825e+000, 1.843198e+001, 1.463173e+001, 1.962881e+001, // albedo 1, turbidity 4 1.516536e+000, 2.438729e+000, -3.624121e+000, 2.298621e+001, 1.599782e+001, 2.070027e+001, // albedo 1, turbidity 5 1.405863e+000, 2.785191e+000, -5.705236e+000, 2.645121e+001, 1.768330e+001, 2.191903e+001, // albedo 1, turbidity 6 1.344052e+000, 2.951807e+000, -6.683851e+000, 2.744271e+001, 1.985706e+001, 2.229452e+001, // albedo 1, turbidity 7 1.245827e+000, 3.182923e+000, -7.822960e+000, 2.791395e+001, 2.327254e+001, 2.315910e+001, // albedo 1, turbidity 8 1.132305e+000, 3.202593e+000, -8.008429e+000, 2.521093e+001, 3.000014e+001, 2.405306e+001, // albedo 1, turbidity 9 1.020330e+000, 2.820556e+000, -6.238704e+000, 1.709276e+001, 4.077916e+001, 2.509949e+001, // albedo 1, turbidity 10 9.031570e-001, 1.863917e+000, -1.955738e+000, 3.032665e+000, 5.434290e+001, 2.641780e+001, }; static float datasetXYZ3[] = { // albedo 0, turbidity 1 -1.310023e+000, -4.407658e-001, -3.640340e+001, 3.683292e+001, -8.124762e-003, 5.297961e-001, 1.188633e-002, 3.138320e+000, 5.134778e-001, -1.424100e+000, -5.501606e-001, -1.753510e+001, 1.822769e+001, -1.539272e-002, 6.366826e-001, 2.661996e-003, 2.659915e+000, 4.071138e-001, -1.103436e+000, -1.884105e-001, 6.425322e+000, -6.910579e+000, -2.019861e-002, 3.553271e-001, -1.589061e-002, 5.345985e+000, 8.790218e-001, -1.186200e+000, -4.307514e-001, -3.957947e+000, 5.979352e+000, -5.348869e-002, 1.736117e+000, 3.491346e-002, -2.692261e+000, 5.610506e-001, -1.006038e+000, -1.305995e-001, 4.473513e+000, -3.806719e+000, 1.419407e-001, -2.148238e-002, -5.081185e-002, 3.735362e+000, 5.358280e-001, -1.078507e+000, -1.633754e-001, -3.812368e+000, 4.381700e+000, 2.988122e-002, 1.754224e+000, 1.472376e-001, 3.722798e+000, 4.999157e-001, // albedo 0, turbidity 2 -1.333582e+000, -4.649908e-001, -3.359528e+001, 3.404375e+001, -9.384242e-003, 5.587511e-001, 5.726310e-003, 3.073145e+000, 5.425529e-001, -1.562624e+000, -7.107068e-001, -1.478170e+001, 1.559839e+001, -1.462375e-002, 5.050133e-001, 2.516017e-002, 1.604696e+000, 2.902403e-001, -8.930158e-001, 4.068077e-002, 1.373481e+000, -2.342752e+000, -2.098058e-002, 6.248686e-001, -5.258363e-002, 7.058214e+000, 1.150373e+000, -1.262823e+000, -4.818353e-001, 8.892610e-004, 1.923120e+000, -4.979718e-002, 1.040693e+000, 1.558103e-001, -2.852480e+000, 2.420691e-001, -9.968383e-001, -1.200648e-001, 1.324342e+000, -9.430889e-001, 1.931098e-001, 4.436916e-001, -7.320456e-002, 4.215931e+000, 7.898019e-001, -1.078185e+000, -1.718192e-001, -1.720191e+000, 2.358918e+000, 2.765637e-002, 1.260245e+000, 2.021941e-001, 3.395483e+000, 5.173628e-001, // albedo 0, turbidity 3 -1.353023e+000, -4.813523e-001, -3.104920e+001, 3.140156e+001, -9.510741e-003, 5.542030e-001, 8.135471e-003, 3.136646e+000, 5.215989e-001, -1.624704e+000, -7.990201e-001, -2.167125e+001, 2.246341e+001, -1.163533e-002, 5.415746e-001, 2.618378e-002, 1.139214e+000, 3.444357e-001, -7.983610e-001, 1.417476e-001, 9.914841e+000, -1.081503e+001, -1.218845e-002, 3.411392e-001, -6.137698e-002, 7.445848e+000, 1.180080e+000, -1.266679e+000, -4.288977e-001, -5.818701e+000, 6.986437e+000, -8.180711e-002, 1.397403e+000, 2.016916e-001, -1.275731e+000, 2.592773e-001, -1.009707e+000, -1.537754e-001, 3.496378e+000, -3.013726e+000, 2.421150e-001, -2.831925e-001, 3.003395e-002, 3.702862e+000, 7.746320e-001, -1.075646e+000, -1.768747e-001, -1.347762e+000, 1.989004e+000, 1.375836e-002, 1.764810e+000, 1.330018e-001, 3.230864e+000, 6.626210e-001, // albedo 0, turbidity 4 -1.375269e+000, -5.103569e-001, -3.442661e+001, 3.478703e+001, -8.460009e-003, 5.408643e-001, 4.813323e-003, 3.016078e+000, 5.062069e-001, -1.821679e+000, -9.766461e-001, -1.926488e+001, 1.997912e+001, -9.822567e-003, 3.649556e-001, 4.316092e-002, 8.930190e-001, 4.166527e-001, -6.633542e-001, 1.997841e-001, 2.395592e+000, -3.117175e+000, -1.080884e-002, 8.983814e-001, -1.375825e-001, 6.673463e+000, 1.115663e+000, -1.303240e+000, -3.612712e-001, 8.292959e-002, 3.381364e-001, -6.078648e-002, 3.229247e-001, 3.680987e-001, 7.046755e-001, 3.144924e-001, -9.952598e-001, -2.039076e-001, 4.026851e-001, 2.686684e-001, 1.640712e-001, 5.186341e-001, -1.205520e-002, 2.659613e+000, 8.030394e-001, -1.098579e+000, -2.151992e-001, 6.558198e-001, -7.436900e-004, -1.421817e-003, 1.073701e+000, 1.886875e-001, 2.536857e+000, 6.673923e-001, // albedo 0, turbidity 5 -1.457986e+000, -5.906842e-001, -3.812464e+001, 3.838539e+001, -6.024357e-003, 4.741484e-001, 1.209223e-002, 2.818432e+000, 5.012433e-001, -1.835728e+000, -1.003405e+000, -6.848129e+000, 7.601943e+000, -1.277375e-002, 4.785598e-001, 3.366853e-002, 1.097701e+000, 4.636635e-001, -8.491348e-001, 9.466365e-003, -2.685226e+000, 2.004060e+000, -1.168708e-002, 6.752316e-001, -1.543371e-001, 5.674759e+000, 1.039534e+000, -1.083379e+000, -1.506790e-001, 7.328236e-001, -5.095568e-001, -8.609153e-002, 4.448820e-001, 4.174662e-001, 1.481556e+000, 3.942551e-001, -1.117089e+000, -3.337605e-001, 2.502281e-001, 4.036323e-001, 2.673899e-001, 2.829817e-001, 2.242450e-002, 2.043207e+000, 7.706902e-001, -1.071648e+000, -2.126200e-001, 6.069466e-001, -1.456290e-003, -5.515960e-001, 1.046755e+000, 1.985021e-001, 2.290245e+000, 6.876058e-001, // albedo 0, turbidity 6 -1.483903e+000, -6.309647e-001, -4.380213e+001, 4.410537e+001, -5.712161e-003, 5.195992e-001, 2.028428e-003, 2.687114e+000, 5.098321e-001, -2.053976e+000, -1.141473e+000, 5.109183e-001, 8.060391e-002, -1.033983e-002, 4.066532e-001, 4.869627e-002, 1.161722e+000, 4.039525e-001, -6.348185e-001, 7.651292e-002, -1.031327e+001, 1.007598e+001, -2.083688e-002, 7.359516e-001, -2.029459e-001, 5.013257e+000, 1.077649e+000, -1.228630e+000, -1.650496e-001, 4.077157e-002, -7.189167e-001, -5.092220e-002, 2.959814e-001, 5.111496e-001, 2.540433e+000, 3.615330e-001, -1.041883e+000, -3.278413e-001, -6.691911e-002, 1.307364e+000, 2.166663e-001, 3.000595e-001, -3.157136e-003, 1.389208e+000, 7.999026e-001, -1.103556e+000, -2.443602e-001, 4.705347e-001, -9.296482e-004, -5.309920e-001, 9.654511e-001, 2.142587e-001, 2.244723e+000, 6.839976e-001, // albedo 0, turbidity 7 -1.555684e+000, -6.962113e-001, -4.647983e+001, 4.674270e+001, -5.034895e-003, 4.755090e-001, -9.502561e-007, 2.626569e+000, 5.056194e-001, -1.998288e+000, -1.124720e+000, -1.629586e+000, 2.187993e+000, -8.284384e-003, 3.845258e-001, 5.726240e-002, 1.185644e+000, 4.255812e-001, -1.032570e+000, -2.513850e-001, -3.721112e+000, 3.506967e+000, -2.186561e-002, 9.436049e-001, -2.451412e-001, 4.725724e+000, 1.039256e+000, -8.597532e-001, 9.073332e-002, -2.553741e+000, 1.993237e+000, -4.390891e-002, -2.046928e-001, 5.515623e-001, 1.909127e+000, 3.948212e-001, -1.210482e+000, -4.477622e-001, -2.267805e-001, 1.219488e+000, 1.336186e-001, 6.866897e-001, 2.808997e-002, 1.600403e+000, 7.816409e-001, -1.078168e+000, -2.699261e-001, 2.537282e-001, 3.820684e-001, -4.425103e-001, 5.298235e-001, 2.185217e-001, 1.728679e+000, 6.882743e-001, // albedo 0, turbidity 8 -1.697968e+000, -8.391488e-001, -5.790105e+001, 5.814120e+001, -3.404760e-003, 4.265140e-001, -1.796301e-006, 2.368442e+000, 5.324429e-001, -2.141552e+000, -1.172230e+000, 1.677872e+001, -1.641470e+001, -5.732425e-003, 2.002199e-001, 6.841834e-002, 1.485338e+000, 3.215763e-001, -1.442946e+000, -7.264245e-001, -9.503706e+000, 9.650462e+000, -2.120995e-002, 1.419263e+000, -2.893098e-001, 3.860731e+000, 1.120857e+000, -5.696752e-001, 3.411279e-001, -2.931035e-001, -6.512552e-001, -1.068437e-001, -1.085661e+000, 6.107549e-001, 1.459503e+000, 3.210336e-001, -1.313839e+000, -5.921371e-001, -2.332222e-001, 1.648196e+000, 2.492787e-001, 1.381033e+000, -1.993392e-002, 9.812560e-001, 8.316329e-001, -1.087464e+000, -3.195534e-001, 2.902095e-001, 3.383709e-001, -8.798482e-001, 1.494668e-002, 2.529703e-001, 1.452644e+000, 6.693870e-001, // albedo 0, turbidity 9 -2.068582e+000, -1.118605e+000, -5.081598e+001, 5.097486e+001, -3.280669e-003, 4.067371e-001, -2.544951e-006, 2.179497e+000, 5.778017e-001, -1.744693e+000, -8.537207e-001, 2.234361e+001, -2.208318e+001, -5.932616e-003, 1.035049e-001, 5.742772e-002, 1.977880e+000, 2.124846e-001, -3.287515e+000, -2.140268e+000, -1.249566e+001, 1.240091e+001, -2.409349e-002, 1.397821e+000, -2.371627e-001, 2.771192e+000, 1.170496e+000, 5.502311e-001, 1.046630e+000, 2.193517e+000, -2.220400e+000, -1.064394e-001, -1.017926e+000, 4.795457e-001, 1.030644e+000, 3.177516e-001, -1.719734e+000, -9.536198e-001, -6.586821e-001, 1.386361e+000, -2.513065e-002, 1.187011e+000, 6.542539e-002, 5.296055e-001, 8.082660e-001, -1.005700e+000, -3.028096e-001, 4.470957e-002, 1.007760e+000, -8.119016e-001, 3.153338e-002, 2.311321e-001, 1.182208e+000, 6.824758e-001, // albedo 0, turbidity 10 -2.728867e+000, -1.580388e+000, -3.079627e+001, 3.092586e+001, -4.197673e-003, 3.154759e-001, -3.897675e-006, 1.920567e+000, 6.664791e-001, -1.322495e+000, -7.249275e-001, 1.477660e+001, -1.468154e+001, -9.044857e-003, 5.624314e-002, 6.498392e-002, 2.047389e+000, 6.367540e-002, -6.102376e+000, -3.473018e+000, -9.926071e+000, 9.637797e+000, -1.097909e-002, 1.103498e+000, -2.424521e-001, 2.520748e+000, 1.240260e+000, 1.351796e+000, 1.018588e+000, 2.009081e+000, -1.333394e+000, -1.979125e-001, -3.318292e-001, 4.476624e-001, 9.095235e-001, 2.955611e-001, -1.774467e+000, -1.079880e+000, -8.084680e-002, 2.577697e-001, -1.149295e-001, 4.975303e-001, 2.931611e-003, -3.803171e-001, 8.002794e-001, -9.898401e-001, -2.542513e-001, -7.530911e-002, 1.870355e+000, -1.521918e+000, 2.405164e-001, 2.964615e-001, 1.334800e+000, 6.789053e-001, // albedo 1, turbidity 1 -1.279730e+000, -4.290674e-001, -4.277972e+001, 4.343305e+001, -6.541826e-003, 4.945086e-001, 1.425338e-002, 2.685244e+000, 5.011313e-001, -1.449506e+000, -5.766374e-001, -1.688496e+001, 1.781118e+001, -1.121649e-002, 3.545020e-001, 2.287338e-002, 1.904281e+000, 4.936998e-001, -1.021980e+000, -1.897574e-001, 2.482462e+000, -2.941725e+000, -1.570448e-002, 7.532578e-001, -4.256800e-002, 5.239660e+000, 4.983116e-001, -1.162608e+000, -3.428049e-001, 3.974358e+000, -1.527935e+000, -3.919201e-002, 8.758593e-001, 7.291363e-002, -3.455257e+000, 8.007426e-001, -9.929985e-001, -8.712006e-002, -7.397313e-001, 1.348372e+000, 9.511685e-002, 3.233584e-001, -7.549148e-002, 5.806452e+000, 4.990042e-001, -1.084996e+000, -1.739767e-001, 1.580475e-001, 9.088180e-001, 6.871433e-002, 5.933079e-001, 1.188921e-001, 3.074079e+000, 4.999327e-001, // albedo 1, turbidity 2 -1.317009e+000, -4.661946e-001, -4.255347e+001, 4.312782e+001, -5.727235e-003, 4.285447e-001, 2.189854e-002, 2.608310e+000, 5.190700e-001, -1.469236e+000, -6.282139e-001, -1.241404e+001, 1.348765e+001, -1.204770e-002, 5.070285e-001, -7.280216e-004, 1.491533e+000, 3.635064e-001, -9.713808e-001, -8.138038e-002, 3.709854e-001, -1.041174e+000, -1.814075e-002, 5.060860e-001, -2.053756e-002, 6.161431e+000, 1.093736e+000, -1.159057e+000, -3.698074e-001, 2.711209e+000, -6.006479e-001, -4.896926e-002, 9.273957e-001, 1.137712e-001, -3.496828e+000, 2.867109e-001, -1.011601e+000, -8.201890e-002, 2.105725e-001, 4.597520e-001, 1.478925e-001, 2.138940e-001, -5.660670e-002, 6.057755e+000, 7.859121e-001, -1.078020e+000, -1.811580e-001, 1.646622e-001, 8.348426e-001, 1.149064e-001, 4.985738e-001, 1.376605e-001, 2.746607e+000, 4.999626e-001, // albedo 1, turbidity 3 -1.325672e+000, -4.769313e-001, -4.111215e+001, 4.168293e+001, -6.274997e-003, 4.649469e-001, 1.119411e-002, 2.631267e+000, 5.234546e-001, -1.619391e+000, -8.000253e-001, -1.534098e+001, 1.632706e+001, -1.012023e-002, 4.242255e-001, 2.931597e-002, 8.925807e-001, 3.314765e-001, -7.356979e-001, 1.368406e-001, 2.972579e+000, -3.535359e+000, -1.318948e-002, 4.607620e-001, -7.182778e-002, 6.254100e+000, 1.236299e+000, -1.316217e+000, -4.194427e-001, 3.489902e-002, 1.289849e+000, -4.755960e-002, 1.138222e+000, 1.975992e-001, -8.991542e-001, 2.290572e-001, -9.502188e-001, -1.172703e-001, 1.405202e+000, -3.061919e-001, 1.058772e-001, -3.760592e-001, -1.983179e-002, 3.562353e+000, 7.895959e-001, -1.100117e+000, -1.900567e-001, 4.925030e-001, 5.250225e-001, 1.576804e-001, 1.042701e+000, 7.330743e-002, 2.796064e+000, 6.749783e-001, // albedo 1, turbidity 4 -1.354183e+000, -5.130625e-001, -4.219268e+001, 4.271772e+001, -5.365373e-003, 4.136743e-001, 1.235172e-002, 2.520122e+000, 5.187269e-001, -1.741434e+000, -9.589761e-001, -8.230339e+000, 9.296799e+000, -9.600162e-003, 4.994969e-001, 2.955452e-002, 3.667099e-001, 3.526999e-001, -6.917347e-001, 2.154887e-001, -8.760264e-001, 2.334121e-001, -1.909621e-002, 4.748033e-001, -1.138514e-001, 6.515360e+000, 1.225097e+000, -1.293189e+000, -4.218700e-001, 1.620952e+000, -7.858597e-001, -3.769410e-002, 6.636786e-001, 3.364945e-001, -5.341017e-001, 2.128347e-001, -9.735521e-001, -1.325495e-001, 1.007517e+000, 2.598258e-001, 6.762169e-002, 1.421018e-003, -6.915987e-002, 3.185897e+000, 8.641956e-001, -1.094800e+000, -1.962062e-001, 5.755591e-001, 2.906259e-001, 2.625748e-001, 7.644049e-001, 1.347492e-001, 2.677126e+000, 6.465460e-001, // albedo 1, turbidity 5 -1.393063e+000, -5.578338e-001, -4.185249e+001, 4.233504e+001, -5.435640e-003, 4.743765e-001, 7.422477e-003, 2.442801e+000, 5.211707e-001, -1.939487e+000, -1.128509e+000, -8.974257e+000, 9.978383e+000, -7.965597e-003, 2.948830e-001, 4.436763e-002, 2.839868e-001, 3.440424e-001, -6.011562e-001, 2.354877e-001, -3.079820e+000, 2.585094e+000, -2.002701e-002, 7.793909e-001, -1.598414e-001, 5.834678e+000, 1.202856e+000, -1.315676e+000, -3.903446e-001, 1.701900e+000, -1.304609e+000, -1.045121e-002, 2.747707e-001, 4.143967e-001, 3.197102e-001, 2.637580e-001, -9.618628e-001, -1.625841e-001, 1.187138e+000, 1.497802e-001, -5.590954e-006, 3.178475e-002, -4.153145e-002, 2.496096e+000, 8.195082e-001, -1.111554e+000, -2.365546e-001, 7.831875e-001, 2.018684e-001, 2.074369e-001, 7.395978e-001, 1.225730e-001, 1.876478e+000, 6.821167e-001, // albedo 1, turbidity 6 -1.427879e+000, -5.994879e-001, -3.531016e+001, 3.581581e+001, -6.431497e-003, 4.554192e-001, 7.348731e-004, 2.334619e+000, 5.233377e-001, -1.998177e+000, -1.206633e+000, -2.146510e+001, 2.242237e+001, -5.857596e-003, 2.755663e-001, 6.384795e-002, 1.358244e-001, 3.328437e-001, -6.440630e-001, 2.058571e-001, 2.155499e+000, -2.587968e+000, -1.840023e-002, 8.826555e-001, -2.222452e-001, 5.847073e+000, 1.228387e+000, -1.229071e+000, -3.360441e-001, -3.429599e-001, 6.179469e-001, 2.029610e-003, 8.899319e-002, 5.041624e-001, 1.882964e-001, 2.252040e-001, -1.022905e+000, -2.101621e-001, 1.915689e+000, -6.498794e-001, -3.463651e-002, 8.954605e-002, -6.797854e-002, 2.417705e+000, 8.568618e-001, -1.082538e+000, -2.007723e-001, 4.731009e-001, 4.077267e-001, 1.324289e-001, 6.514880e-001, 1.702912e-001, 2.309383e+000, 6.600895e-001, // albedo 1, turbidity 7 -1.472139e+000, -6.499815e-001, -3.428465e+001, 3.469659e+001, -5.747023e-003, 4.174167e-001, 1.688597e-003, 2.323046e+000, 5.395191e-001, -2.161176e+000, -1.353089e+000, -2.226827e+001, 2.329138e+001, -5.583808e-003, 2.364793e-001, 6.096656e-002, 1.944666e-003, 2.861624e-001, -6.593044e-001, 1.393558e-001, 4.698373e+000, -5.193883e+000, -1.998390e-002, 1.095635e+000, -2.391254e-001, 5.598103e+000, 1.236193e+000, -1.195717e+000, -2.972715e-001, 4.648953e-002, 3.024588e-001, 5.003313e-003, -3.754741e-001, 5.247265e-001, -1.381312e-001, 2.493896e-001, -1.020139e+000, -2.253524e-001, 3.548437e-001, 7.030485e-001, -2.107076e-002, 4.581395e-001, -3.243757e-002, 2.453259e+000, 8.323623e-001, -1.098770e+000, -2.435780e-001, 8.761614e-001, 1.941613e-001, -1.990692e-001, 3.761139e-001, 1.657412e-001, 1.590503e+000, 6.741417e-001, // albedo 1, turbidity 8 -1.648007e+000, -8.205121e-001, -4.435106e+001, 4.479801e+001, -4.181353e-003, 3.854830e-001, -1.842385e-006, 2.000281e+000, 5.518363e-001, -2.140986e+000, -1.282239e+000, -3.979213e+000, 4.672459e+000, -5.008582e-003, 2.421920e-001, 6.253602e-002, 6.612713e-001, 2.555851e-001, -1.300502e+000, -5.137898e-001, 5.179821e-001, -4.032341e-001, -2.066785e-002, 1.087929e+000, -2.615309e-001, 4.225887e+000, 1.229237e+000, -6.963340e-001, 9.241060e-002, 6.936356e-002, -3.588571e-001, -5.461843e-002, -5.616643e-001, 5.484166e-001, -4.776267e-002, 2.414935e-001, -1.233179e+000, -4.325498e-001, 6.479813e-001, 8.368356e-001, 2.458875e-001, 6.464752e-001, -2.897097e-002, 1.561773e+000, 8.518598e-001, -1.051023e+000, -2.533690e-001, 1.004294e+000, 3.028083e-001, -1.520108e+000, 1.607013e-001, 1.619975e-001, 1.131094e+000, 6.706655e-001, // albedo 1, turbidity 9 -1.948249e+000, -1.097383e+000, -4.453697e+001, 4.494902e+001, -3.579939e-003, 3.491605e-001, -2.500253e-006, 1.740442e+000, 6.188022e-001, -2.154253e+000, -1.209559e+000, 4.144894e+000, -3.562411e+000, -5.638843e-003, 1.067169e-001, 7.594858e-002, 1.005280e+000, 1.072543e-001, -2.513259e+000, -1.507208e+000, -1.602979e+000, 1.404154e+000, -5.560750e-003, 1.240490e+000, -2.852117e-001, 3.485252e+000, 1.349321e+000, -7.832214e-002, 3.655626e-001, 3.856288e-001, 6.867894e-001, -1.609523e-001, -6.704306e-001, 5.357301e-001, -6.457935e-001, 1.479503e-001, -1.354784e+000, -5.454375e-001, 8.797469e-001, -1.466514e+000, 7.134420e-001, 5.934903e-001, -2.911178e-002, 8.643737e-001, 9.030724e-001, -1.048324e+000, -2.738736e-001, 8.783074e-001, 3.246188e+000, -4.435369e+000, 1.251791e-001, 1.783486e-001, 1.064657e+000, 6.522878e-001, // albedo 1, turbidity 10 -2.770408e+000, -1.618911e+000, -2.504031e+001, 2.531674e+001, -4.239279e-003, 3.241013e-001, -3.764484e-006, 1.586843e+000, 7.035906e-001, -1.913500e+000, -1.144014e+000, -1.080587e+001, 1.153677e+001, -1.003197e-002, 1.577515e-001, 5.217789e-002, 1.225278e+000, 5.172771e-003, -5.293208e+000, -2.876463e+000, 2.087053e+000, -3.201552e+000, 3.892964e-003, 5.323930e-001, -2.034512e-001, 2.617760e+000, 1.273597e+000, 9.060340e-001, 3.773409e-001, -6.399945e-001, 3.213979e+000, -9.112172e-002, 6.494055e-001, 3.953280e-001, 5.047796e-001, 2.998695e-001, -1.482179e+000, -6.778310e-001, 1.161775e+000, -3.004872e+000, 4.774797e-001, -4.969248e-001, -3.512074e-003, -1.307190e+000, 7.927378e-001, -9.863181e-001, -1.803364e-001, 5.810824e-001, 4.580570e+000, -3.863454e+000, 5.328174e-001, 2.272821e-001, 1.771114e+000, 6.791814e-001, }; static float datasetXYZRad3[] = { // albedo 0, turbidity 1 1.168084e+000, 2.156455e+000, -3.980314e+000, 1.989302e+001, 1.328335e+001, 1.435621e+001, // albedo 0, turbidity 2 1.135488e+000, 2.294701e+000, -4.585886e+000, 2.090208e+001, 1.347840e+001, 1.467658e+001, // albedo 0, turbidity 3 1.107408e+000, 2.382765e+000, -5.112357e+000, 2.147823e+001, 1.493128e+001, 1.460882e+001, // albedo 0, turbidity 4 1.054193e+000, 2.592891e+000, -6.115000e+000, 2.268967e+001, 1.635672e+001, 1.518999e+001, // albedo 0, turbidity 5 1.006946e+000, 2.705420e+000, -6.698930e+000, 2.291830e+001, 1.834324e+001, 1.570651e+001, // albedo 0, turbidity 6 9.794044e-001, 2.742440e+000, -6.805283e+000, 2.225271e+001, 2.050797e+001, 1.563130e+001, // albedo 0, turbidity 7 9.413577e-001, 2.722009e+000, -6.760707e+000, 2.098242e+001, 2.342588e+001, 1.605011e+001, // albedo 0, turbidity 8 8.917923e-001, 2.592780e+000, -6.152635e+000, 1.774141e+001, 2.858324e+001, 1.657910e+001, // albedo 0, turbidity 9 8.288391e-001, 2.153434e+000, -4.118327e+000, 1.078118e+001, 3.681710e+001, 1.738139e+001, // albedo 0, turbidity 10 7.623528e-001, 1.418187e+000, -8.845235e-001, 7.590129e-001, 4.629859e+001, 1.921657e+001, // albedo 1, turbidity 1 1.352858e+000, 2.048862e+000, -2.053393e+000, 1.405874e+001, 3.045344e+001, 3.044430e+001, // albedo 1, turbidity 2 1.330497e+000, 2.126497e+000, -2.466296e+000, 1.467559e+001, 3.090738e+001, 3.069707e+001, // albedo 1, turbidity 3 1.286344e+000, 2.200436e+000, -2.877228e+000, 1.492701e+001, 3.236288e+001, 3.077223e+001, // albedo 1, turbidity 4 1.234428e+000, 2.289628e+000, -3.404699e+000, 1.499436e+001, 3.468390e+001, 3.084842e+001, // albedo 1, turbidity 5 1.178660e+000, 2.306071e+000, -3.549159e+000, 1.411006e+001, 3.754188e+001, 3.079730e+001, // albedo 1, turbidity 6 1.151366e+000, 2.333005e+000, -3.728627e+000, 1.363374e+001, 3.905894e+001, 3.092599e+001, // albedo 1, turbidity 7 1.101593e+000, 2.299422e+000, -3.565787e+000, 1.196745e+001, 4.188472e+001, 3.102755e+001, // albedo 1, turbidity 8 1.038322e+000, 2.083539e+000, -2.649585e+000, 8.037389e+000, 4.700869e+001, 3.065948e+001, // albedo 1, turbidity 9 9.596146e-001, 1.671470e+000, -8.751538e-001, 1.679772e+000, 5.345784e+001, 3.054520e+001, // albedo 1, turbidity 10 8.640731e-001, 9.858301e-001, 1.854956e+000, -6.798097e+000, 5.936468e+001, 3.110255e+001, }; static float *datasetsXYZ[] = {datasetXYZ1, datasetXYZ2, datasetXYZ3}; static float *datasetsXYZRad[] = {datasetXYZRad1, datasetXYZRad2, datasetXYZRad3}; RenderKit-ospray-f2a61c2/modules/cpu/lights/sky_model/sky_model_data_rgb.h000066400000000000000000002303631456566705700270570ustar00rootroot00000000000000/* This source is published under the following 3-clause BSD license. Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * None of the names of the contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // with slight modifications // Copyright 2020 Intel Corporation /* ============================================================================ This file is part of a sample implementation of the analytical skylight and solar radiance models presented in the SIGGRAPH 2012 paper "An Analytic Model for Full Spectral Sky-Dome Radiance" and the 2013 IEEE CG&A paper "Adding a Solar Radiance Function to the Hosek Skylight Model" both by Lukas Hosek and Alexander Wilkie Charles University in Prague, Czech Republic Version: 1.4a, February 22nd, 2013 Version history: 1.4a February 22nd, 2013 Removed unnecessary and counter-intuitive solar radius parameters from the interface of the colourspace sky dome initialisation functions. 1.4 February 11th, 2013 Fixed a bug which caused the relative brightness of the solar disc and the sky dome to be off by a factor of about 6. The sun was too bright: this affected both normal and alien sun scenarios. The coefficients of the solar radiance function were changed to fix this. 1.3 January 21st, 2013 (not released to the public) Added support for solar discs that are not exactly the same size as the terrestrial sun. Also added support for suns with a different emission spectrum ("Alien World" functionality). 1.2a December 18th, 2012 Fixed a mistake and some inaccuracies in the solar radiance function explanations found in ArHosekSkyModel.h. The actual source code is unchanged compared to version 1.2. 1.2 December 17th, 2012 Native RGB data and a solar radiance function that matches the turbidity conditions were added. 1.1 September 2012 The coefficients of the spectral model are now scaled so that the output is given in physical units: W / (m^-2 * sr * nm). Also, the output of the XYZ model is now no longer scaled to the range [0...1]. Instead, it is the result of a simple conversion from spectral data via the CIE 2 degree standard observer matching functions. Therefore, after multiplication with 683 lm / W, the Y channel now corresponds to luminance in lm. 1.0 May 11th, 2012 Initial release. Please visit http://cgg.mff.cuni.cz/projects/SkylightModelling/ to check if an updated version of this code has been published! ============================================================================ */ /* This file contains the coefficient data for the RGB colour space version of the model. */ // uses Aug 23 dataset static float datasetRGB1[] = { // albedo 0, turbidity 1 -1.099459e+000, -1.335146e-001, -4.083223e+000, 5.919603e+000, -1.104166e-001, 1.600158e+000, -1.326538e-006, 4.917807e+000, 5.127716e-001, -1.169858e+000, -1.832793e-001, 9.694744e-001, 9.495762e-002, -4.738918e-002, 2.194171e-001, 1.095749e-001, 3.603604e+000, 3.815119e-001, -9.665225e-001, -1.403888e-001, 5.194457e+000, -1.107607e+000, -8.135181e-001, 4.969661e+000, -2.300508e-001, -2.489350e+000, 1.279158e+000, -1.292508e+000, -1.299552e-001, -2.071404e+000, -4.752482e-002, 1.215598e+000, -1.904179e+000, 3.027985e-001, 8.707768e+000, 6.332446e-002, -9.264666e-001, -1.696780e-001, 4.574070e+000, -4.232936e-001, -7.575833e+000, 5.079755e+000, -2.576343e-001, -4.506805e+000, 6.908129e-001, -1.139072e+000, -1.796056e-001, 1.923311e+000, 6.788529e+000, -2.364389e+000, -1.064041e+000, 1.717010e-001, 1.534681e+000, 5.015810e-001, // albedo 0, turbidity 2 -1.107257e+000, -1.384411e-001, -4.285744e+000, 5.713157e+000, -1.015992e-001, 1.372638e+000, 6.555893e-002, 5.127514e+000, 6.550471e-001, -1.187337e+000, -1.969013e-001, 8.551048e-001, 5.289708e-002, -7.626406e-002, 1.733153e-002, 1.779454e-001, 3.801038e+000, 4.742709e-001, -9.685321e-001, -1.553308e-001, 4.732492e+000, -1.178935e+000, -7.852791e-001, 4.604492e+000, -2.666518e-001, -2.367663e+000, 1.177527e+000, -1.252817e+000, -5.129949e-002, -2.800433e+000, -1.295992e-002, 1.308964e+000, -2.204331e+000, 7.276011e-001, 8.699265e+000, 1.188388e-001, -9.459509e-001, -2.322133e-001, 4.375041e+000, -1.712018e-001, -7.451681e+000, 5.078019e+000, -4.223538e-001, -4.595561e+000, 1.074719e+000, -1.125092e+000, -1.796750e-001, 1.626399e+000, 6.989743e+000, -2.406382e+000, -9.060383e-001, 2.961611e-001, 1.337715e+000, 5.438140e-001, // albedo 0, turbidity 3 -1.135338e+000, -1.716160e-001, -1.499253e+000, 2.373491e+000, -1.654023e-001, 9.566404e-001, 1.113453e-001, 4.528473e+000, 6.579439e-001, -1.132780e+000, -1.456214e-001, -1.736672e+000, 1.756589e+000, -1.087003e-001, 3.757927e-001, 2.525070e-001, 7.178513e+000, 5.003814e-001, -1.167176e+000, -2.927225e-001, 5.727667e+000, -3.139244e+000, -6.425204e-001, 2.822634e+000, -1.457812e-001, -6.787080e+000, 1.017072e+000, -1.042529e+000, 4.110823e-002, -4.000629e+000, 4.362364e+000, 1.090540e+000, -1.338674e+000, 8.246964e-001, 1.095249e+001, 2.912211e-001, -1.061598e+000, -2.096143e-001, 3.803155e+000, -7.977069e+000, -3.637880e+000, 3.707671e+000, -1.903128e-001, -3.397953e+000, 9.971500e-001, -1.073560e+000, -2.077964e-001, 1.492052e+000, 1.626322e+001, -5.015304e+000, -4.059889e-001, 2.659782e-001, 6.395380e-001, 5.634436e-001, // albedo 0, turbidity 4 -1.172794e+000, -2.111186e-001, -1.360013e+000, 1.604080e+000, -8.473723e-002, 7.217312e-001, 1.548030e-001, 4.257010e+000, 6.328974e-001, -1.238374e+000, -2.670827e-001, 3.247678e-001, 5.466311e-001, -7.425952e-001, 5.276440e-001, 2.678026e-002, 5.484169e+000, 6.814734e-001, -1.176923e+000, -2.574586e-001, 2.304045e+000, -2.797678e+000, 1.464405e+000, 1.998552e+000, 2.550559e-001, -4.199772e+000, 7.544892e-001, -1.003284e+000, 1.943984e-002, -2.145066e+000, 1.030924e+001, -1.525413e+001, -2.023010e+000, 5.448699e-001, 8.159497e+000, 5.539148e-001, -1.060017e+000, -2.037206e-001, 2.483018e+000, -4.595459e+000, 6.526991e+000, 4.031804e+000, 1.206513e-001, -2.586527e+000, 7.875752e-001, -1.081141e+000, -2.123302e-001, 1.092275e+000, 2.683841e+000, -4.166938e+000, -1.396582e+000, 4.371205e-001, 1.030233e+000, 6.664862e-001, // albedo 0, turbidity 5 -1.222392e+000, -2.651924e-001, -4.625037e-001, 3.521964e-001, 2.148855e-002, 5.078494e-001, 1.791590e-001, 3.852516e+000, 5.998216e-001, -1.424610e+000, -4.710155e-001, -1.826815e-001, 1.786277e+000, -1.952442e+000, 5.277612e-001, -1.773629e-002, 2.415874e+000, 6.701272e-001, -1.130655e+000, -1.358609e-001, 9.171203e-001, -4.660394e+000, 6.251162e+000, 1.904529e+000, 2.639668e-001, 1.856130e+000, 8.228440e-001, -9.739015e-001, -6.674749e-002, -4.768897e-001, 1.248589e+001, -1.994688e+001, -2.353043e+000, 5.885575e-001, 1.287251e+000, 4.830135e-001, -1.082178e+000, -1.974495e-001, 1.050245e+000, -4.792855e+000, 8.663406e+000, 3.246969e+000, 1.556731e-001, 8.117442e-001, 8.050376e-001, -1.063354e+000, -1.727108e-001, 9.681592e-001, 2.736077e+000, -4.969269e+000, -8.360570e-001, 5.994612e-001, 1.024039e+000, 6.786935e-001, // albedo 0, turbidity 6 -1.261936e+000, -3.053676e-001, -4.262222e-001, 4.000196e-001, -2.059388e-002, 4.721802e-001, 1.480028e-001, 3.505343e+000, 6.121337e-001, -1.681088e+000, -6.971919e-001, -1.105652e-001, 7.437426e-001, -6.594399e-001, 2.254221e-001, 8.710195e-002, 1.263913e+000, 5.681865e-001, -9.453001e-001, 3.460388e-002, 6.067038e-001, -1.985128e+000, 3.457236e+000, 2.655483e+000, -1.162354e-002, 3.304716e+000, 1.001950e+000, -1.086609e+000, -2.029011e-001, -6.399170e-001, 6.926885e+000, -1.512189e+001, -3.793051e+000, 9.456120e-001, 2.222222e-001, 2.893725e-001, -1.041259e+000, -1.388790e-001, 1.147331e+000, 6.282086e+000, 3.679836e+000, 4.398314e+000, -1.355232e-001, 1.031134e+000, 9.273509e-001, -1.063473e+000, -1.916051e-001, 6.556979e-001, -3.371891e-003, -3.699664e+000, -1.926783e+000, 7.371154e-001, 1.179975e+000, 6.367068e-001, // albedo 0, turbidity 7 -1.336390e+000, -3.778927e-001, -7.259477e-001, 2.270247e-001, 4.627513e-001, 1.366459e-001, 2.637347e-001, 3.292059e+000, 4.998211e-001, -2.119878e+000, -1.055472e+000, 5.422052e-001, 7.826648e-001, -1.286065e+000, 9.517905e-001, -1.432358e-001, -2.379816e-001, 5.910513e-001, -7.761432e-001, 2.124336e-001, -6.845184e-001, -9.812342e-001, 4.347257e+000, 9.671980e-001, 3.773150e-001, 5.789529e+000, 9.646598e-001, -1.118734e+000, -3.513815e-001, 5.500918e-001, 9.449627e-001, -1.262070e+001, -1.825280e+000, 4.731260e-001, -3.326892e+000, 3.568768e-001, -1.026437e+000, -8.257946e-002, 3.221701e-001, 1.198372e+001, 1.555130e+000, 2.560304e+000, 1.406465e-001, 2.912858e+000, 8.643181e-001, -1.069949e+000, -2.029607e-001, 5.825042e-001, -2.398595e-003, -3.278335e+000, -1.349882e+000, 7.208433e-001, 8.505164e-001, 6.625391e-001, // albedo 0, turbidity 8 -1.392309e+000, -4.454945e-001, -5.664000e-001, 6.283393e-001, -3.761727e-001, 6.949802e-001, 7.748178e-002, 3.192797e+000, 5.968661e-001, -2.713405e+000, -1.395112e+000, 2.029230e-001, 1.877272e-001, -3.715859e-001, -1.652929e-001, 2.385861e-001, -4.150768e-001, 1.375467e-001, -9.588644e-001, 2.433900e-002, -1.527493e+000, -9.632874e-001, 5.496269e+000, 1.094931e+000, 2.004044e-001, 6.084554e+000, 1.369604e+000, -8.028546e-001, -2.473563e-001, 1.617898e+000, 2.073591e+000, -1.149446e+001, -8.394131e-001, 2.726847e-001, -4.634538e+000, 1.367293e-001, -1.198326e+000, -1.804865e-001, -3.565414e-001, 4.073200e+000, 1.662086e+000, 1.239770e+000, 3.367978e-001, 2.997402e+000, 9.360383e-001, -1.013531e+000, -1.859060e-001, 5.799857e-001, 1.331883e+001, -4.346873e+000, -1.113820e+000, 5.275714e-001, 8.045177e-001, 6.496373e-001, // albedo 0, turbidity 9 -1.530103e+000, -6.107468e-001, -3.841771e-001, 1.881508e+000, -1.464807e+000, 6.654690e-001, -5.950797e-006, 2.738912e+000, 8.101012e-001, -2.415469e+000, -1.057499e+000, -4.161968e-001, -2.357548e+000, 6.300296e-001, 6.224915e-001, 1.545048e-002, 2.038561e+000, -1.339415e-001, -3.096796e+000, -1.465688e+000, -1.199232e+000, 4.567061e+000, 3.260980e+000, -9.794907e-001, 8.950491e-001, 2.049235e+000, 1.331015e+000, 2.713904e-001, 2.852852e-001, 1.202090e+000, -8.206784e+000, -5.805762e+000, 1.804431e+000, -6.090648e-001, -1.990902e+000, 3.288858e-001, -1.456580e+000, -3.455960e-001, -6.409257e-002, 1.667697e+001, -2.311094e+000, -9.771104e-001, 6.759863e-001, 1.245136e+000, 7.911932e-001, -9.860389e-001, -2.099564e-001, 2.946650e-001, -3.547800e-003, -2.268313e+000, -6.205647e-002, 4.705185e-001, 8.657995e-001, 6.856284e-001, // albedo 0, turbidity 10 -1.971736e+000, -9.414047e-001, -3.400557e-001, 1.468763e+000, -1.474284e+000, 5.501062e-001, -1.109750e-005, 2.356370e+000, 9.001702e-001, -1.589845e+000, -7.797079e-001, -5.582240e-001, -8.137376e-001, 5.846617e-001, 1.129459e-001, -2.658005e-002, 2.707248e+000, -2.112486e-001, -6.940173e+000, -2.823963e+000, -1.620848e+000, 1.090696e+000, 2.391730e+000, 1.370047e+000, 5.890462e-001, 1.728400e+000, 1.331253e+000, 1.293144e+000, -1.919778e-003, 1.644206e+000, -8.666967e-001, -7.161953e+000, -1.385018e+000, -1.505374e-001, -1.388643e+000, 2.530122e-001, -1.488880e+000, -2.495496e-001, -2.377137e-001, 1.167714e+001, -8.617124e-001, 1.053828e+000, 1.992744e-001, 3.633564e-001, 8.553304e-001, -1.060891e+000, -4.035829e-001, 2.823207e-001, -2.369798e-003, -1.876577e+000, -5.950265e-001, 4.241017e-001, 3.140802e-001, 6.631669e-001, // albedo 1, turbidity 1 -1.101204e+000, -1.351353e-001, -4.030882e+000, 6.096353e+000, -1.148599e-001, 1.606507e+000, -1.555474e-006, 4.436084e+000, 5.973715e-001, -1.154597e+000, -1.923378e-001, 8.512132e-001, 2.934895e-001, -6.522777e-002, 1.389077e-001, 9.091469e-002, 3.133307e+000, 2.108541e-001, -1.031588e+000, -1.546804e-001, 5.266214e+000, -9.491390e-001, -7.184867e-001, 4.875626e+000, -1.911907e-001, -2.865642e+000, 1.087895e+000, -1.159454e+000, -9.546699e-002, -1.508146e+000, -2.031411e-002, 1.040653e+000, -2.333508e+000, 2.540592e-001, 8.594981e+000, 9.316770e-002, -1.035940e+000, -2.021151e-001, 4.719343e+000, -9.019318e-001, -7.858046e+000, 3.901234e+000, -2.233137e-001, -4.344739e+000, 6.550733e-001, -1.096669e+000, -1.558196e-001, 2.057553e+000, 6.274495e+000, -2.678352e+000, -1.814927e+000, 1.550676e-001, 1.903276e+000, 4.998989e-001, // albedo 1, turbidity 2 -1.114209e+000, -1.473531e-001, -7.602914e+000, 8.973685e+000, -4.980074e-002, 1.289198e+000, 8.366906e-002, 4.557987e+000, 6.118757e-001, -1.149397e+000, -1.981628e-001, 4.914096e+000, -3.498986e+000, -6.257090e-002, 1.667401e-001, 1.048980e-001, 2.284689e+000, 5.935965e-001, -1.056121e+000, -1.456172e-001, 4.272656e-001, 2.912649e+000, -5.501745e-001, 4.406542e+000, -1.387680e-001, 1.245555e+000, 9.733011e-001, -1.125047e+000, -4.003662e-002, 1.058457e+000, -3.462236e+000, 4.395278e-001, -2.395805e+000, 5.177589e-001, 4.866247e+000, 4.253189e-001, -1.051444e+000, -2.804541e-001, 3.364668e+000, 3.293787e+000, -1.015741e+001, 3.807407e+000, -3.592377e-001, -3.367415e+000, 7.900825e-001, -1.093847e+000, -1.436965e-001, 2.384780e+000, 5.787070e+000, -2.445987e+000, -1.311171e+000, 2.326563e-001, 1.158439e+000, 5.555416e-001, // albedo 1, turbidity 3 -1.134824e+000, -1.680468e-001, -3.325620e+000, 4.458596e+000, -1.135063e-001, 1.104500e+000, 7.794544e-002, 4.609952e+000, 6.854854e-001, -1.143017e+000, -1.565926e-001, 3.014687e-001, -1.763027e-001, -3.557925e-002, -2.342406e-001, 2.528705e-001, 5.884085e+000, 4.750602e-001, -1.136801e+000, -2.907502e-001, 3.682423e+000, -4.061202e-001, -8.728159e-001, 4.001510e+000, -1.522202e-001, -5.528713e+000, 1.044847e+000, -1.063652e+000, 7.808107e-002, -1.983678e+000, 3.648078e-001, 2.102276e+000, -3.065050e+000, 8.431951e-001, 1.038830e+001, 2.662834e-001, -1.061015e+000, -2.859814e-001, 4.223615e+000, -2.290138e+000, -8.314010e+000, 4.405718e+000, -4.613627e-001, -4.502910e+000, 1.008383e+000, -1.106302e+000, -1.697123e-001, 2.087196e+000, 8.238929e+000, -2.992416e+000, -1.821776e+000, 3.434859e-001, 7.755179e-001, 5.341190e-001, // albedo 1, turbidity 4 -1.171110e+000, -2.106304e-001, -1.614361e+000, 2.378103e+000, -1.625969e-001, 8.504483e-001, 1.059312e-001, 4.046256e+000, 6.618227e-001, -1.200480e+000, -2.235733e-001, 1.014390e+000, -1.174074e+000, -4.440180e-001, 2.262406e-001, 1.665868e-001, 5.461829e+000, 5.676310e-001, -1.223587e+000, -3.502622e-001, 1.699106e+000, 6.724266e-001, 1.268567e+000, 2.135102e+000, 8.039374e-004, -5.221111e+000, 9.445690e-001, -9.452673e-001, 1.468459e-001, -1.335034e+000, 4.346628e+000, -1.285652e+001, -1.807046e+000, 8.175243e-001, 9.301065e+000, 3.656798e-001, -1.134681e+000, -3.310951e-001, 3.571244e+000, -2.208948e+000, 6.041580e+000, 3.107577e+000, -3.112127e-001, -4.186351e+000, 9.188333e-001, -1.083237e+000, -1.831394e-001, 2.062654e+000, 1.385424e+000, -5.004950e+000, -1.332669e+000, 3.627352e-001, 3.323150e-001, 6.191181e-001, // albedo 1, turbidity 5 -1.211527e+000, -2.590617e-001, -1.660874e-001, 3.627905e-001, -1.039258e-001, 4.697924e-001, 1.671653e-001, 3.507497e+000, 6.022506e-001, -1.433017e+000, -4.733592e-001, 1.724445e-001, 9.953236e-001, -1.874457e+000, 4.432099e-001, 1.715810e-002, 2.339272e+000, 6.441470e-001, -1.084920e+000, -1.587903e-001, 8.999585e-001, -2.537516e+000, 5.877859e+000, 2.014554e+000, 9.689141e-002, 3.177242e-001, 9.030399e-001, -1.008242e+000, 2.793030e-003, -3.507469e-001, 1.028300e+001, -2.080454e+001, -2.781026e+000, 8.995090e-001, 3.366951e+000, 3.473867e-001, -1.103151e+000, -2.799598e-001, 2.525791e+000, -4.255704e+000, 9.903388e+000, 3.722668e+000, -3.603941e-001, -1.303292e+000, 9.369454e-001, -1.102235e+000, -2.025061e-001, 2.085660e+000, 1.686787e+000, -5.010957e+000, -1.656458e+000, 4.584029e-001, -2.751759e-001, 6.184162e-001, // albedo 1, turbidity 6 -1.256130e+000, -3.104904e-001, 1.639350e-001, 1.315502e-001, -7.297583e-001, 4.778480e-001, 1.259265e-001, 3.012108e+000, 6.202728e-001, -1.620114e+000, -6.552670e-001, -2.877157e-001, 1.094371e+000, 2.818914e-001, 3.696830e-001, 9.428521e-002, 1.450951e+000, 5.681308e-001, -9.686204e-001, -3.755647e-002, 1.469980e+000, -3.103414e+000, 2.856583e+000, 1.883209e+000, -5.746099e-002, 1.286383e+000, 1.001751e+000, -1.089377e+000, -1.023062e-001, -1.498891e+000, 1.066455e+001, -1.720184e+001, -2.759314e+000, 1.061258e+000, 2.910211e+000, 2.624701e-001, -1.044681e+000, -2.156857e-001, 3.230136e+000, -5.863862e-001, 6.096640e+000, 3.550019e+000, -4.255773e-001, -1.500033e+000, 9.687696e-001, -1.133658e+000, -2.505101e-001, 1.717840e+000, 8.480428e-003, -5.011789e+000, -1.740989e+000, 4.983430e-001, -2.081829e-001, 6.088641e-001, // albedo 1, turbidity 7 -1.335366e+000, -3.863319e-001, -5.279971e-001, 3.638324e-001, 3.230699e-001, 8.339707e-002, 2.483293e-001, 2.678646e+000, 4.998346e-001, -2.004511e+000, -9.957121e-001, 1.250807e+000, 1.625025e-002, -3.410754e-001, 7.858244e-001, -9.506757e-002, 2.651876e-002, 5.788643e-001, -8.714157e-001, 1.192051e-001, -8.486879e-001, -3.702497e-001, 1.818277e+000, 1.103427e+000, 2.454866e-001, 3.841575e+000, 9.847350e-001, -1.042618e+000, -2.285793e-001, 3.620175e-001, 2.983368e+000, -9.776844e+000, -1.971587e+000, 6.691674e-001, -7.901947e-001, 3.213200e-001, -1.099112e+000, -1.869868e-001, 2.044065e+000, 2.062964e+000, 1.265668e+000, 2.710130e+000, -1.099443e-001, 2.179353e-001, 9.024108e-001, -1.106985e+000, -2.396881e-001, 1.809807e+000, 8.523319e+000, -5.011788e+000, -1.590086e+000, 3.248449e-001, -1.003187e-001, 6.550606e-001, // albedo 1, turbidity 8 -1.421285e+000, -4.767024e-001, -3.885004e-001, 8.274590e-001, -3.644229e-001, 6.999513e-001, 5.196710e-002, 2.578431e+000, 6.246310e-001, -2.611217e+000, -1.398846e+000, 4.527425e-001, -5.932142e-001, 2.224617e-001, -5.593581e-001, 3.389633e-001, -7.767112e-001, 6.536004e-002, -9.881543e-001, 4.684782e-002, -8.616613e-001, 8.799807e-001, 4.003130e+000, 1.739543e+000, -8.098378e-002, 5.524802e+000, 1.499673e+000, -7.544759e-001, -2.314808e-001, 8.125770e-001, -7.724135e-001, -9.577645e+000, -1.629433e+000, 6.790832e-001, -4.193895e+000, -2.526624e-002, -1.273719e+000, -2.187030e-001, 1.401798e+000, 5.231832e+000, 7.405093e-001, 1.775166e+000, -7.269476e-002, 1.996087e+000, 1.057450e+000, -1.046864e+000, -2.247559e-001, 1.679449e+000, 1.140057e+001, -4.948829e+000, -1.182664e+000, 3.241038e-001, -2.470012e-001, 6.115900e-001, // albedo 1, turbidity 9 -1.514607e+000, -5.985430e-001, -1.877610e-001, 1.756930e+000, -1.314206e+000, 6.115810e-001, -5.970460e-006, 2.412975e+000, 8.124304e-001, -2.308414e+000, -1.083797e+000, -1.179959e-001, -1.728246e+000, 7.784742e-001, 5.494505e-001, 6.203168e-003, 9.326251e-001, -1.419518e-001, -3.230837e+000, -1.438670e+000, -9.868286e-001, 2.974393e+000, 1.949339e+000, -6.337857e-001, 8.160271e-001, 3.278606e+000, 1.354373e+000, 5.149378e-001, 2.754789e-001, 1.040965e+000, -4.501186e+000, -3.399057e+000, 9.661861e-001, -4.736173e-001, -4.037574e+000, 2.794847e-001, -1.621870e+000, -3.192763e-001, 8.786242e-001, 9.785565e+000, -2.727652e+000, 1.903691e-002, 5.521261e-001, 2.138764e+000, 8.419871e-001, -9.951701e-001, -2.550607e-001, 1.498952e+000, -2.737197e-003, -3.101832e+000, -5.921329e-001, 2.864422e-001, -4.405218e-001, 6.631410e-001, // albedo 1, turbidity 10 -1.902954e+000, -9.056918e-001, -2.069570e-001, 1.191499e+000, -1.092577e+000, 5.849556e-001, -9.649602e-006, 2.048407e+000, 9.001527e-001, -1.271627e+000, -7.193923e-001, -1.136606e-002, -1.167951e-001, 3.286175e-003, -5.262827e-002, -2.473874e-002, 1.716125e+000, -2.187133e-001, -7.647175e+000, -3.114129e+000, -1.490128e+000, -5.266488e-001, 3.063090e+000, 1.474262e+000, 5.481458e-001, 2.052174e+000, 1.353089e+000, 2.191403e+000, 3.421120e-001, 1.446510e+000, 2.170943e+000, -7.768187e+000, -1.471207e+000, -1.456708e-001, -1.753574e+000, 2.310576e-001, -1.932296e+000, -3.814739e-001, 6.245422e-001, 6.748294e+000, -3.060171e-001, 1.067747e+000, 2.500671e-001, -1.252596e-001, 8.614611e-001, -9.471101e-001, -4.052640e-001, 1.300174e+000, -3.951536e-003, -1.908284e+000, -5.385721e-001, 2.133578e-001, -6.250292e-001, 6.658012e-001, }; static float datasetRGBRad1[] = { // albedo 0, turbidity 1 1.962684e+000, 1.159831e+000, 4.450588e+000, 5.079633e+000, 4.437388e+000, 4.324573e+000, // albedo 0, turbidity 2 1.946487e+000, 1.287515e+000, 3.703696e+000, 8.782833e+000, 3.440437e+000, 5.160333e+000, // albedo 0, turbidity 3 1.882170e+000, 1.335878e+000, 2.648641e+000, 1.358368e+001, 3.105473e+000, 5.907387e+000, // albedo 0, turbidity 4 1.738159e+000, 1.624289e+000, -8.786695e-003, 2.118253e+001, 2.770255e+000, 7.055672e+000, // albedo 0, turbidity 5 1.571896e+000, 2.301786e+000, -4.028545e+000, 2.966806e+001, 1.630876e+000, 8.711031e+000, // albedo 0, turbidity 6 1.475048e+000, 2.679086e+000, -6.311315e+000, 3.377896e+001, 2.140975e+000, 9.385283e+000, // albedo 0, turbidity 7 1.326174e+000, 3.378759e+000, -9.831444e+000, 3.942061e+001, 2.852702e+000, 1.082542e+001, // albedo 0, turbidity 8 1.153344e+000, 3.967771e+000, -1.265181e+001, 4.195016e+001, 7.468239e+000, 1.221350e+001, // albedo 0, turbidity 9 9.746081e-001, 4.051626e+000, -1.298454e+001, 3.754964e+001, 1.749232e+001, 1.420619e+001, // albedo 0, turbidity 10 8.448016e-001, 3.181809e+000, -8.757338e+000, 2.197962e+001, 3.524033e+001, 1.639549e+001, // albedo 1, turbidity 1 2.029623e+000, 1.364434e+000, 4.201529e+000, 5.415099e+000, 9.825839e+000, 1.063328e+001, // albedo 1, turbidity 2 2.023126e+000, 1.494728e+000, 3.420413e+000, 9.072178e+000, 9.205157e+000, 1.186639e+001, // albedo 1, turbidity 3 1.956307e+000, 1.648665e+000, 2.039712e+000, 1.430239e+001, 9.039526e+000, 1.330453e+001, // albedo 1, turbidity 4 1.825053e+000, 1.985022e+000, -8.036307e-001, 2.202493e+001, 9.415361e+000, 1.517659e+001, // albedo 1, turbidity 5 1.650367e+000, 2.593201e+000, -4.469328e+000, 2.969817e+001, 9.410977e+000, 1.744850e+001, // albedo 1, turbidity 6 1.555202e+000, 2.962925e+000, -6.608170e+000, 3.329887e+001, 1.064559e+001, 1.850816e+001, // albedo 1, turbidity 7 1.412478e+000, 3.439403e+000, -9.196616e+000, 3.685077e+001, 1.345341e+001, 2.003128e+001, // albedo 1, turbidity 8 1.252990e+000, 3.820805e+000, -1.115338e+001, 3.721593e+001, 2.014916e+001, 2.182320e+001, // albedo 1, turbidity 9 1.091952e+000, 3.663027e+000, -1.031330e+001, 2.978985e+001, 3.296835e+001, 2.375450e+001, // albedo 1, turbidity 10 9.501691e-001, 2.664579e+000, -5.545167e+000, 1.281159e+001, 5.154768e+001, 2.574284e+001, }; static float datasetRGB2[] = { // albedo 0, turbidity 1 -1.140530e+000, -1.982747e-001, -7.512730e+000, 8.403899e+000, -5.699038e-002, 9.015907e-001, 3.392161e-002, 4.772522e+000, 5.111184e-001, -1.165117e+000, -1.852955e-001, 2.963684e+000, -2.262274e+000, -1.571683e-001, 6.339974e-001, 4.977879e-002, 7.243307e+000, 4.220053e-001, -1.169936e+000, -3.357429e-001, 1.911291e+000, -2.391074e-001, -4.791643e-001, 1.446113e+000, -9.178108e-002, -4.700239e+000, 8.096219e-001, -1.060246e+000, -1.051633e-001, 5.013829e-001, 2.832309e+000, -3.707855e-001, 1.523131e+000, 9.163749e-002, 5.604183e+000, 7.208566e-001, -1.089753e+000, -2.382167e-001, 2.360312e+000, -5.902562e+000, -8.799894e+000, 1.377692e+000, -6.131633e-002, -1.415472e+000, 6.124057e-001, -1.075481e+000, -1.242391e-001, 1.425781e+000, 8.810319e+000, -2.922646e+000, 1.486520e+000, 3.270580e-002, 3.889783e+000, 4.999482e-001, // albedo 0, turbidity 2 -1.149342e+000, -2.076337e-001, -7.446587e+000, 8.014559e+000, -4.866227e-002, 8.203043e-001, 6.386483e-002, 4.894198e+000, 5.452051e-001, -1.120531e+000, -1.513311e-001, 2.735504e+000, -2.417591e+000, -1.361114e-001, 4.296342e-001, 9.427488e-002, 8.171403e+000, 4.102448e-001, -1.226964e+000, -3.516378e-001, 1.308298e+000, -5.097487e-002, -4.846783e-001, 1.654619e+000, -1.134940e-001, -3.347854e+000, 1.131147e+000, -9.664377e-001, 2.767589e-002, 1.658235e-001, 2.407439e+000, -1.300304e-001, 9.170958e-001, 2.742895e-001, 6.642633e+000, 2.550064e-001, -1.153358e+000, -3.126223e-001, 2.078934e+000, -5.857733e+000, -8.659848e+000, 1.758505e+000, -9.616094e-002, -1.230863e+000, 9.663832e-001, -1.053850e+000, -1.330743e-001, 1.481738e+000, 1.049485e+001, -3.528854e+000, 9.142363e-001, 1.244880e-001, 2.644615e+000, 5.001048e-001, // albedo 0, turbidity 3 -1.173687e+000, -2.360362e-001, -3.741454e+000, 4.088507e+000, -7.528205e-002, 6.645237e-001, 7.718265e-002, 4.651220e+000, 5.586318e-001, -1.213757e+000, -2.589561e-001, 7.132551e-001, -4.259327e-001, -1.980821e-001, 3.627815e-001, 4.666560e-002, 5.807984e+000, 5.847377e-001, -1.108794e+000, -2.259870e-001, 1.574179e+000, -3.753731e-001, -5.984743e-001, 1.659414e+000, -1.681021e-002, 6.785219e-001, 8.647325e-001, -1.060896e+000, -1.346690e-002, -7.529656e-001, 1.711319e+000, -9.792435e-001, 2.022433e-001, 3.826487e-001, 5.725157e+000, 5.290714e-001, -1.085145e+000, -2.840715e-001, 2.088029e+000, -4.935097e+000, -9.056542e+000, 1.976149e+000, -3.912485e-002, -8.636064e-001, 7.452125e-001, -1.077983e+000, -1.416633e-001, 1.100848e+000, 1.015875e+001, -2.943712e+000, 5.255135e-001, 2.164224e-001, 2.941143e+000, 6.699937e-001, // albedo 0, turbidity 4 -1.223293e+000, -2.867444e-001, -1.624136e+000, 1.668299e+000, -9.537589e-002, 5.015947e-001, 1.130741e-001, 4.244812e+000, 5.082152e-001, -1.325342e+000, -4.280991e-001, 4.705490e-001, 6.926592e-002, -4.572587e-001, 5.344144e-001, -2.554192e-002, 3.093939e+000, 6.639401e-001, -1.113581e+000, -1.192133e-001, 4.011536e-001, 7.011889e-001, 2.052842e-001, 9.880724e-001, 1.807533e-002, 4.690160e+000, 8.576240e-001, -1.016063e+000, -1.038138e-001, -2.280391e-001, 7.898918e-001, -1.127333e+001, 2.074545e-001, 5.388182e-001, 1.364263e+000, 4.660455e-001, -1.099582e+000, -2.228607e-001, 1.332648e+000, 5.135188e+000, 1.653152e+000, 1.417020e+000, -1.087532e-001, 1.809275e+000, 8.080874e-001, -1.064357e+000, -1.520775e-001, 8.207368e-001, -1.323565e-003, -5.009523e+000, 3.946298e-001, 4.337902e-001, 2.593198e+000, 6.719172e-001, // albedo 0, turbidity 5 -1.278702e+000, -3.512866e-001, -4.511055e-001, 3.895760e-001, -2.429672e-001, 4.270577e-001, 1.135348e-001, 3.719130e+000, 4.998867e-001, -1.580069e+000, -7.095475e-001, -3.198904e-001, 1.715748e+000, -1.185915e+000, 4.523161e-001, -1.026159e-002, 7.927188e-001, 5.538350e-001, -9.474023e-001, 1.173703e-001, 4.881381e-001, -2.618684e+000, 3.251661e+000, 1.213931e+000, -1.736274e-002, 8.000768e+000, 1.025998e+000, -1.129091e+000, -3.287694e-001, -3.524077e-001, 3.352892e+000, -1.416073e+001, -8.485617e-001, 6.560766e-001, -2.820937e+000, 3.111303e-001, -1.030884e+000, -1.137581e-001, 1.109855e+000, 8.082276e+000, 1.519214e+000, 2.112433e+000, -1.592299e-001, 3.675905e+000, 8.703367e-001, -1.075192e+000, -1.627166e-001, 3.514910e-001, 1.168164e+000, -4.255822e+000, -6.015348e-001, 6.265776e-001, 2.884818e+000, 6.548384e-001, // albedo 0, turbidity 6 -1.316017e+000, -3.889652e-001, -5.030854e-001, 4.488704e-001, -3.186800e-001, 4.570763e-001, 8.909201e-002, 3.659274e+000, 5.011746e-001, -1.731876e+000, -8.493806e-001, 1.194871e-001, 2.002781e+000, -2.006547e+000, 4.872233e-001, -2.854606e-002, 2.662137e-001, 4.611629e-001, -9.273680e-001, 1.380954e-001, -3.302179e-001, -3.553265e+000, 4.633345e+000, 9.696729e-001, 8.799775e-002, 8.291129e+000, 1.094451e+000, -1.099377e+000, -3.325392e-001, 2.501063e-001, 2.613712e+000, -1.328142e+001, -5.579527e-001, 4.992081e-001, -3.504402e+000, 3.022924e-001, -1.048420e+000, -1.227773e-001, 5.845373e-001, 1.105869e+001, 3.813151e-002, 1.330409e+000, 1.978131e-002, 3.959430e+000, 8.396439e-001, -1.063233e+000, -1.560639e-001, 2.840033e-001, 8.751565e-001, -3.411820e+000, -1.436564e-001, 5.846580e-001, 2.899292e+000, 6.799095e-001, // albedo 0, turbidity 7 -1.376715e+000, -4.541567e-001, -1.445491e+000, 1.569898e+000, -1.390627e-001, 5.558270e-001, 4.109877e-002, 3.349451e+000, 5.516123e-001, -1.953391e+000, -1.035869e+000, 1.690563e+000, -1.964690e-001, -7.787096e-001, 5.799605e-001, 2.945626e-002, 4.217906e-002, 2.451373e-001, -1.012422e+000, 7.136451e-002, -1.862534e+000, -7.228653e-001, 1.947997e-001, 2.091805e-001, 6.399233e-002, 7.928994e+000, 1.290733e+000, -9.706708e-001, -2.880950e-001, 1.107797e+000, -2.731734e+000, -8.445995e+000, 4.296774e-001, 5.117648e-001, -3.824277e+000, 1.761207e-001, -1.110611e+000, -1.789409e-001, 2.108488e-001, 2.071430e+001, -1.763174e+000, 9.554695e-002, -2.943103e-002, 3.422079e+000, 8.815496e-001, -1.048334e+000, -1.614087e-001, 2.475184e-001, 2.146938e-002, -2.983901e+000, 2.538224e-001, 5.601370e-001, 2.461925e+000, 6.777394e-001, // albedo 0, turbidity 8 -1.393719e+000, -5.002724e-001, -2.408940e+000, 2.680983e+000, -1.362825e-001, 7.395067e-001, -3.300343e-006, 3.260889e+000, 8.132057e-001, -2.128663e+000, -1.151182e+000, 2.923026e+000, -1.931838e+000, -4.426170e-001, 2.309983e-001, -5.485890e-003, 3.279529e-001, -2.229467e-001, -1.618022e+000, -3.766490e-001, -3.163544e+000, 1.611608e+000, -3.967476e-001, 3.933680e-001, 3.006742e-001, 6.835177e+000, 1.613765e+000, -5.669064e-001, -1.481749e-001, 2.071817e+000, -8.157422e+000, -5.988088e+000, 2.387202e-001, 1.447191e-001, -4.296385e+000, 5.011258e-002, -1.241724e+000, -2.519348e-001, -1.908609e-001, 2.952235e+001, -3.333660e+000, -1.837651e-002, 1.022249e-001, 2.929320e+000, 8.867262e-001, -1.021670e+000, -1.667327e-001, 1.789771e-001, -2.178108e-003, -2.641572e+000, -5.641484e-002, 5.303758e-001, 2.138196e+000, 6.780350e-001, // albedo 0, turbidity 9 -1.669332e+000, -7.588708e-001, -2.993557e+000, 3.178760e+000, -8.066442e-002, 6.544672e-001, -8.089880e-006, 2.628924e+000, 9.001272e-001, -1.755806e+000, -8.735348e-001, 3.258881e+000, -2.504785e+000, -3.300791e-001, 1.180565e-001, -9.315982e-003, 1.785154e+000, -3.205824e-001, -3.720277e+000, -1.733350e+000, -3.332272e+000, 1.515869e+000, 1.734218e-001, 8.011956e-001, 1.995440e-001, 3.817666e+000, 1.638502e+000, 4.724641e-001, 3.209828e-001, 2.051443e+000, -5.105574e+000, -6.509139e+000, -4.232041e-001, 2.598931e-001, -2.151756e+000, -3.493910e-003, -1.525600e+000, -4.897606e-001, -9.891121e-002, 2.346818e+001, -2.278152e+000, 1.681219e-001, -4.469389e-002, 1.051000e+000, 9.294666e-001, -9.908649e-001, -2.008182e-001, 1.605143e-001, -2.463113e-003, -2.477349e+000, -1.218647e-001, 4.750121e-001, 1.460813e+000, 6.661364e-001, // albedo 0, turbidity 10 -2.122119e+000, -1.125475e+000, -3.066599e+000, 3.145078e+000, -5.411593e-002, 5.133628e-001, -7.823408e-006, 2.268448e+000, 9.001416e-001, -1.528158e+000, -9.370249e-001, 2.567559e+000, -1.591439e+000, -3.634460e-001, 1.763256e-001, 1.119624e-003, 1.811848e+000, -2.637929e-001, -6.524387e+000, -2.673507e+000, -2.940472e+000, -6.025609e-001, 7.852067e-001, 1.073499e+000, -3.540435e-002, 3.517416e+000, 1.490466e+000, 8.886026e-001, -9.681828e-002, 1.430554e+000, 4.993717e+000, -6.071355e+000, -6.053986e-001, 5.092997e-001, -1.273010e+000, 7.491329e-002, -1.481997e+000, -5.897282e-001, 2.659264e-001, 1.267239e+000, -5.741291e-001, 5.983011e-002, -2.217312e-001, -3.016452e-001, 9.260830e-001, -1.010943e+000, -2.075134e-001, 5.066749e-002, 1.470708e+001, -3.780501e+000, 7.253223e-002, 4.045458e-001, 1.320164e+000, 6.559925e-001, // albedo 1, turbidity 1 -1.129907e+000, -1.884011e-001, -8.047670e+000, 9.035776e+000, -5.539419e-002, 8.823349e-001, 3.197135e-002, 4.839388e+000, 5.042822e-001, -1.133821e+000, -1.510781e-001, 3.362822e+000, -2.453381e+000, -1.463925e-001, 4.728708e-001, 5.958140e-002, 7.636300e+000, 4.805162e-001, -1.176518e+000, -3.549902e-001, 1.729044e+000, -2.160966e-001, -5.075865e-001, 1.675584e+000, -8.906902e-002, -5.386842e+000, 5.452218e-001, -1.043563e+000, -7.520975e-002, 8.750644e-001, 2.510518e+000, 7.584882e-003, 9.361250e-001, 7.889083e-002, 6.066644e+000, 5.813108e-001, -1.081304e+000, -2.222253e-001, 2.517638e+000, -4.453820e+000, -8.663691e+000, 8.662558e-001, -4.802657e-002, -8.965449e-001, 4.886656e-001, -1.083774e+000, -1.375469e-001, 1.685818e+000, 5.631120e+000, -3.100752e+000, 4.045941e-001, 2.346895e-002, 3.390321e+000, 5.008309e-001, // albedo 1, turbidity 2 -1.143158e+000, -2.058334e-001, -9.660198e+000, 1.062394e+001, -4.434119e-002, 8.607615e-001, 3.177325e-002, 4.416481e+000, 5.918162e-001, -1.146773e+000, -1.727385e-001, 4.626048e+000, -4.684602e+000, -8.307137e-002, 1.619616e-001, 1.484866e-001, 7.572868e+000, 2.681126e-001, -1.151324e+000, -3.099303e-001, 4.125596e-001, 2.340752e+000, -4.214444e-001, 1.987375e+000, -1.913410e-001, -3.845978e+000, 1.337311e+000, -1.034258e+000, -7.778759e-003, 7.050094e-001, -8.036369e-001, 3.138570e-001, 2.469452e-001, 3.559970e-001, 7.485917e+000, 4.790329e-002, -1.096568e+000, -2.673169e-001, 2.575654e+000, -8.057121e-001, -8.884928e+000, 1.416170e+000, -2.091315e-001, -1.543494e+000, 1.065445e+000, -1.083304e+000, -1.528265e-001, 1.697727e+000, 2.503702e+000, -2.885296e+000, -1.298500e-001, 1.548870e-001, 2.479652e+000, 5.066496e-001, // albedo 1, turbidity 3 -1.165736e+000, -2.329945e-001, -5.967964e+000, 6.705959e+000, -5.931355e-002, 7.485638e-001, 3.913878e-002, 4.221591e+000, 6.183926e-001, -1.212422e+000, -2.545910e-001, 2.418626e+000, -2.266104e+000, -1.102014e-001, 1.363887e-002, 1.055411e-001, 5.648062e+000, 4.557412e-001, -1.070436e+000, -2.163341e-001, 7.098718e-001, 7.843075e-001, -4.323930e-001, 2.109823e+000, -9.589700e-002, -1.985193e-001, 1.060428e+000, -1.104879e+000, -3.013622e-002, 2.976276e-002, 1.069707e+000, 1.410000e-001, -4.880020e-001, 4.452288e-001, 6.418590e+000, 3.195986e-001, -1.048969e+000, -2.655317e-001, 2.689426e+000, -3.941038e+000, -9.506461e+000, 1.837119e+000, -1.892124e-001, -1.562146e+000, 9.043414e-001, -1.106145e+000, -1.601642e-001, 1.544544e+000, 7.388492e+000, -2.924600e+000, -4.328453e-001, 1.763161e-001, 2.523111e+000, 5.851902e-001, // albedo 1, turbidity 4 -1.203666e+000, -2.776587e-001, -2.084286e+000, 2.450840e+000, -8.746613e-002, 5.258507e-001, 7.983316e-002, 3.860055e+000, 5.486167e-001, -1.340448e+000, -4.230590e-001, 3.462849e-001, 4.707607e-001, -2.512626e-001, 1.530746e-001, 2.724218e-002, 3.035216e+000, 5.876133e-001, -1.014554e+000, -1.168790e-001, 9.477794e-001, -1.061218e+000, -4.196730e-001, 2.058832e+000, -5.989624e-002, 3.058168e+000, 9.763861e-001, -1.137388e+000, -9.854030e-002, -2.984893e-001, 3.647820e+000, -6.585571e-001, -1.479180e+000, 6.102932e-001, 3.265914e+000, 3.480333e-001, -1.021816e+000, -2.344957e-001, 2.463671e+000, -7.240685e+000, -8.862697e+000, 2.514058e+000, -2.122768e-001, -3.313968e-002, 9.028136e-001, -1.126581e+000, -1.874347e-001, 1.454154e+000, 1.034398e+001, -3.237393e+000, -8.654927e-001, 2.457248e-001, 1.845769e+000, 6.002482e-001, // albedo 1, turbidity 5 -1.263727e+000, -3.439354e-001, -1.786388e-001, 3.980166e-001, -3.349517e-001, 3.825166e-001, 1.029225e-001, 3.331096e+000, 4.998955e-001, -1.530010e+000, -6.879698e-001, 2.380415e-001, 1.608216e+000, -1.682679e+000, 3.546360e-001, -3.915220e-003, 4.517655e-001, 5.128605e-001, -9.685659e-001, 9.480403e-002, 6.076844e-002, -3.217561e+000, 4.568074e+000, 1.069299e+000, 2.083638e-002, 7.301088e+000, 1.072165e+000, -1.113925e+000, -3.112382e-001, 3.954133e-001, 5.105907e+000, -1.456866e+001, -4.917378e-001, 5.289909e-001, -2.678374e+000, 3.014709e-001, -1.046864e+000, -1.215754e-001, 1.778308e+000, 4.661489e+000, 2.565583e-001, 1.353680e+000, -1.175767e-001, 3.415972e+000, 8.457746e-001, -1.104480e+000, -1.940913e-001, 1.343668e+000, -1.759206e-003, -5.009204e+000, -4.186951e-001, 3.125710e-001, 1.628183e+000, 6.720408e-001, // albedo 1, turbidity 6 -1.286902e+000, -3.781238e-001, -8.977253e-002, 3.545393e-001, -4.866515e-001, 3.843664e-001, 8.281675e-002, 3.122231e+000, 5.046991e-001, -1.712597e+000, -8.549112e-001, 4.809286e-001, 1.515398e+000, -2.212211e+000, 2.539029e-001, 2.335997e-002, -6.089466e-002, 4.268444e-001, -8.807283e-001, 1.646097e-001, -4.437898e-001, -3.188247e+000, 5.984417e+000, 1.334779e+000, -4.026975e-002, 7.546431e+000, 1.175751e+000, -1.147253e+000, -3.538199e-001, 6.101836e-001, 4.437780e+000, -1.559813e+001, -1.103222e+000, 6.242039e-001, -3.091472e+000, 2.174290e-001, -1.038230e+000, -1.213475e-001, 1.547505e+000, 5.893176e+000, 1.368738e+000, 1.663127e+000, -1.377130e-001, 3.185279e+000, 8.736453e-001, -1.101026e+000, -1.874907e-001, 1.272667e+000, 3.596524e+000, -5.007243e+000, -6.352483e-001, 3.048985e-001, 1.931613e+000, 6.788844e-001, // albedo 1, turbidity 7 -1.342753e+000, -4.384971e-001, -1.213491e+000, 1.621399e+000, -1.551441e-001, 5.614218e-001, 2.591739e-002, 2.958967e+000, 5.782132e-001, -1.937684e+000, -1.066019e+000, 1.913336e+000, -7.347719e-001, -5.916167e-001, 1.587590e-001, 1.092568e-001, -6.275002e-001, 1.599071e-001, -9.302391e-001, 1.486187e-001, -1.603835e+000, 1.783713e-001, 1.100461e+000, 1.174181e+000, -1.602361e-001, 7.868331e+000, 1.468971e+000, -1.053631e+000, -3.727050e-001, 1.114117e+000, -9.603286e-001, -1.062469e+001, -1.162140e+000, 7.952797e-001, -4.478765e+000, -4.440862e-002, -1.083629e+000, -1.261405e-001, 1.229344e+000, 1.127825e+001, 1.319010e-001, 1.624729e+000, -2.825898e-001, 3.661082e+000, 1.036911e+000, -1.093950e+000, -2.067455e-001, 1.258035e+000, 7.548645e+000, -4.598387e+000, -8.944932e-001, 3.292634e-001, 1.311304e+000, 6.291871e-001, // albedo 1, turbidity 8 -1.385867e+000, -5.068139e-001, -1.486490e+000, 1.969049e+000, -1.698025e-001, 6.629167e-001, -5.289365e-006, 2.760315e+000, 8.644368e-001, -2.107367e+000, -1.175639e+000, 2.313241e+000, -1.001653e+000, -4.843139e-001, 1.124485e-001, 3.901494e-005, -3.502469e-001, -3.204780e-001, -1.475244e+000, -2.833055e-001, -2.085824e+000, 1.192563e+000, -7.645200e-001, 8.380081e-001, 2.203580e-001, 7.157885e+000, 1.753702e+000, -6.644372e-001, -2.549735e-001, 1.600273e+000, -8.589034e+000, -6.144718e+000, -7.599731e-001, 2.898370e-001, -5.770923e+000, -9.656242e-002, -1.211687e+000, -1.653494e-001, 8.393400e-001, 2.792988e+001, -3.395461e+000, 9.933752e-001, -3.976877e-002, 3.776659e+000, 9.546526e-001, -1.063757e+000, -2.037563e-001, 1.117207e+000, -1.252806e-003, -3.332330e+000, -6.971409e-001, 3.388719e-001, 1.311398e+000, 6.635171e-001, // albedo 1, turbidity 9 -1.678889e+000, -7.992295e-001, -2.421687e+000, 2.871029e+000, -7.662842e-002, 6.046208e-001, -7.598099e-006, 2.002314e+000, 9.001307e-001, -1.692144e+000, -8.804250e-001, 3.060895e+000, -2.000009e+000, -3.183563e-001, 8.385862e-002, -6.326713e-003, 1.206639e+000, -3.369967e-001, -3.676795e+000, -1.719207e+000, -2.534697e+000, 1.005285e+000, 1.550407e-001, 1.072910e+000, 1.318094e-001, 3.717018e+000, 1.689191e+000, 5.424542e-001, 3.263528e-001, 1.551055e+000, -3.841058e+000, -6.598996e+000, -1.201779e+000, 3.530669e-001, -2.542945e+000, -6.482523e-002, -1.553849e+000, -4.576860e-001, 9.324676e-001, 1.950982e+001, -2.344516e+000, 1.121020e+000, -1.221537e-001, 7.285496e-001, 9.582816e-001, -1.020650e+000, -2.215797e-001, 1.009774e+000, -2.056855e-003, -2.740338e+000, -8.122355e-001, 3.328967e-001, 8.982766e-001, 6.594676e-001, // albedo 1, turbidity 10 -2.247360e+000, -1.221267e+000, -3.072346e+000, 3.385139e+000, -4.387559e-002, 5.084887e-001, -7.418833e-006, 1.750107e+000, 9.001401e-001, -1.248499e+000, -8.442718e-001, 3.062611e+000, -2.020314e+000, -2.815341e-001, 5.254745e-002, 3.345008e-003, 1.433225e+000, -2.835911e-001, -7.004119e+000, -2.927978e+000, -2.649852e+000, 7.971894e-001, 5.466893e-001, 1.442667e+000, -6.063912e-002, 2.806194e+000, 1.547429e+000, 1.434882e+000, 9.114639e-002, 1.170089e+000, 3.512808e-002, -5.861915e+000, -1.411843e+000, 5.400486e-001, -7.746522e-001, 2.386984e-002, -1.559053e+000, -5.502302e-001, 1.200396e+000, 1.347741e+001, -2.344397e+000, 8.868907e-001, -3.292661e-001, -1.362105e+000, 9.217826e-001, -1.044436e+000, -2.360719e-001, 7.054471e-001, -2.904518e-003, -2.092829e+000, -5.119668e-001, 4.174861e-001, 9.687435e-001, 6.588427e-001, }; static float datasetRGBRad2[] = { // albedo 0, turbidity 1 1.590330e+000, 1.355401e+000, 1.151412e+000, 1.359116e+001, 5.857714e+000, 8.090833e+000, // albedo 0, turbidity 2 1.552540e+000, 1.510040e+000, 1.276413e-001, 1.604643e+001, 5.912162e+000, 8.350009e+000, // albedo 0, turbidity 3 1.470871e+000, 1.880464e+000, -1.865398e+000, 2.030808e+001, 5.471461e+000, 9.109834e+000, // albedo 0, turbidity 4 1.356563e+000, 2.373866e+000, -4.653245e+000, 2.570922e+001, 5.686009e+000, 1.009480e+001, // albedo 0, turbidity 5 1.244232e+000, 2.851519e+000, -7.130942e+000, 2.993449e+001, 6.382120e+000, 1.114578e+001, // albedo 0, turbidity 6 1.173693e+000, 3.120604e+000, -8.491886e+000, 3.187393e+001, 7.290615e+000, 1.180066e+001, // albedo 0, turbidity 7 1.091845e+000, 3.368888e+000, -9.722083e+000, 3.268508e+001, 1.032424e+001, 1.236508e+001, // albedo 0, turbidity 8 9.858985e-001, 3.500541e+000, -1.026328e+001, 3.092956e+001, 1.610881e+001, 1.331222e+001, // albedo 0, turbidity 9 8.864993e-001, 3.172888e+000, -8.687550e+000, 2.362161e+001, 2.621851e+001, 1.474967e+001, // albedo 0, turbidity 10 7.946973e-001, 2.189355e+000, -4.207953e+000, 9.399091e+000, 4.062849e+001, 1.681753e+001, // albedo 1, turbidity 1 1.711696e+000, 1.657311e+000, 9.328021e-001, 1.317880e+001, 1.506751e+001, 1.863556e+001, // albedo 1, turbidity 2 1.666968e+000, 1.849993e+000, -2.088601e-001, 1.586653e+001, 1.486880e+001, 1.940719e+001, // albedo 1, turbidity 3 1.584846e+000, 2.170022e+000, -2.019597e+000, 1.970826e+001, 1.490684e+001, 2.045055e+001, // albedo 1, turbidity 4 1.469412e+000, 2.524017e+000, -4.197267e+000, 2.365249e+001, 1.664588e+001, 2.134477e+001, // albedo 1, turbidity 5 1.369714e+000, 2.843548e+000, -6.059031e+000, 2.634993e+001, 1.881361e+001, 2.232186e+001, // albedo 1, turbidity 6 1.310477e+000, 2.984444e+000, -6.831686e+000, 2.682340e+001, 2.123267e+001, 2.259755e+001, // albedo 1, turbidity 7 1.222552e+000, 3.176523e+000, -7.731496e+000, 2.671760e+001, 2.484358e+001, 2.336863e+001, // albedo 1, turbidity 8 1.115781e+000, 3.130635e+000, -7.581744e+000, 2.336531e+001, 3.171048e+001, 2.413859e+001, // albedo 1, turbidity 9 1.013181e+000, 2.699342e+000, -5.602709e+000, 1.500158e+001, 4.217613e+001, 2.515957e+001, // albedo 1, turbidity 10 8.976323e-001, 1.726948e+000, -1.296120e+000, 1.183675e+000, 5.503215e+001, 2.643066e+001, }; static float datasetRGB3[] = { // albedo 0, turbidity 1 -1.372629e+000, -4.905585e-001, -4.100789e+001, 4.122169e+001, -7.389360e-003, 4.839359e-001, 6.474757e-003, 3.471755e+000, 5.092936e-001, -1.523025e+000, -6.497084e-001, 6.249857e+000, -5.662543e+000, -1.908402e-002, 5.512810e-001, -2.181049e-005, 2.507663e+000, 4.339598e-001, -1.035567e+000, -7.478740e-002, 9.221030e-001, -2.140047e+000, -2.374146e-002, 3.795517e-001, -1.769134e-002, 7.479831e+000, 7.729303e-001, -1.271086e+000, -5.588190e-001, 6.908023e-001, 2.096832e+000, -2.453967e-001, 1.410648e+000, 4.475036e-002, -4.719115e+000, 5.741186e-001, -9.712598e-001, -7.033926e-002, 9.167274e-001, -9.502097e-001, 3.004684e-001, 4.547054e-001, -5.929017e-002, 5.266196e+000, 7.204135e-001, -1.087457e+000, -1.888896e-001, 8.156686e-001, 3.101712e-001, -2.155419e+000, 1.422205e+000, 9.692261e-002, 3.122404e+000, 4.999430e-001, // albedo 0, turbidity 2 -1.425280e+000, -5.413508e-001, -3.454883e+001, 3.481142e+001, -8.686975e-003, 4.914268e-001, -2.479243e-006, 3.239879e+000, 6.094201e-001, -1.688557e+000, -8.070865e-001, 7.018459e+000, -6.244574e+000, -2.149341e-002, 3.993971e-001, 1.252502e-002, 1.630662e+000, 1.097860e-001, -8.664152e-001, 7.869125e-002, -5.236535e-001, -1.218960e+000, -2.059093e-002, 6.684898e-001, -5.584112e-002, 8.602299e+000, 1.410496e+000, -1.319763e+000, -5.985323e-001, 1.253918e+000, 1.914706e+000, -3.216739e-001, 9.011213e-001, 1.324845e-001, -5.252749e+000, 6.231252e-002, -9.706008e-001, -5.914059e-002, 5.693150e-001, -1.175362e+000, 5.221644e-001, 7.518213e-001, -8.247655e-002, 5.875635e+000, 9.850863e-001, -1.085330e+000, -1.956105e-001, 8.019605e-001, 5.338101e-001, -3.423464e+000, 1.110444e+000, 1.507923e-001, 2.864942e+000, 4.999481e-001, // albedo 0, turbidity 3 -1.431967e+000, -5.478935e-001, -3.286288e+001, 3.305288e+001, -8.380797e-003, 4.772050e-001, -3.044274e-006, 3.289973e+000, 5.976303e-001, -1.801361e+000, -9.315889e-001, 5.391756e+000, -4.588592e+000, -2.040076e-002, 4.144684e-001, 1.814534e-002, 1.051795e+000, 1.145651e-001, -7.905357e-001, 1.451332e-001, -1.605661e-001, -1.592174e+000, 4.561348e-004, 3.380323e-001, -7.770275e-002, 8.775384e+000, 1.489512e+000, -1.308575e+000, -5.539232e-001, 9.184133e-001, 2.011479e+000, -3.842472e-001, 1.432274e+000, 1.637153e-001, -4.408856e+000, 5.272957e-002, -9.829872e-001, -8.183048e-002, 4.464556e-001, -1.442716e+000, 1.029641e+000, -6.991617e-002, 8.702356e-003, 5.706417e+000, 9.116452e-001, -1.087130e+000, -2.038013e-001, 7.260801e-001, 9.164376e-001, -5.006183e+000, 1.511271e+000, 1.257134e-001, 2.715439e+000, 6.201652e-001, // albedo 0, turbidity 4 -1.448662e+000, -5.799075e-001, -2.833268e+001, 2.858023e+001, -9.134061e-003, 4.404783e-001, -2.709026e-006, 3.029357e+000, 5.540071e-001, -2.061772e+000, -1.145190e+000, 7.918478e+000, -7.212525e+000, -2.020760e-002, 2.962715e-001, 4.689670e-002, 8.517209e-001, 2.334587e-001, -6.413755e-001, 1.780425e-001, -2.412919e+000, 1.064484e+000, -1.949986e-002, 6.769741e-001, -1.752760e-001, 7.262714e+000, 1.325869e+000, -1.304871e+000, -3.975581e-001, 1.219002e+000, 7.285178e-001, -2.710105e-001, 7.779727e-001, 3.247139e-001, -8.818168e-001, 1.839517e-001, -1.001104e+000, -1.994801e-001, 3.676742e-001, -1.409737e+000, 2.901555e-001, 2.506940e-001, 2.468899e-003, 3.398923e+000, 8.584645e-001, -1.111552e+000, -2.487204e-001, 7.410842e-001, 1.703749e+000, -5.007855e+000, 1.057763e+000, 1.354511e-001, 2.088715e+000, 6.600013e-001, // albedo 0, turbidity 5 -1.547227e+000, -6.679466e-001, -1.861465e+001, 1.884045e+001, -1.242210e-002, 4.157339e-001, -2.432805e-006, 2.812423e+000, 5.446957e-001, -2.043890e+000, -1.149081e+000, 2.304118e+000, -1.715757e+000, -2.433628e-002, 2.816836e-001, 7.185458e-002, 1.064860e+000, 2.706789e-001, -9.040720e-001, -8.274472e-002, -2.555676e-001, -6.326215e-001, -2.770880e-002, 6.676024e-001, -2.513532e-001, 5.903839e+000, 1.241452e+000, -1.000013e+000, -1.010774e-001, 3.699166e-001, 8.774526e-001, -3.042007e-001, 6.951053e-001, 4.361813e-001, 6.793421e-001, 2.573892e-001, -1.171332e+000, -3.768188e-001, 3.701377e-001, -1.470757e+000, 5.525942e-001, 2.991456e-002, 1.581823e-002, 2.365233e+000, 8.214514e-001, -1.068667e+000, -2.326330e-001, 6.725059e-001, 2.243733e+000, -4.614370e+000, 1.033677e+000, 1.376291e-001, 2.013334e+000, 6.865304e-001, // albedo 0, turbidity 6 -1.592991e+000, -7.246948e-001, -2.598204e+001, 2.621960e+001, -8.365176e-003, 4.207571e-001, -2.742772e-006, 2.623735e+000, 5.873190e-001, -2.271349e+000, -1.280884e+000, 6.308739e+000, -5.758350e+000, -1.977049e-002, 3.671835e-001, 6.698038e-002, 1.150597e+000, 1.759218e-001, -6.368620e-001, -7.436052e-003, -2.230026e+000, 1.640997e+000, -1.548497e-002, 3.145331e-001, -2.492644e-001, 5.083843e+000, 1.260215e+000, -1.177925e+000, -9.628114e-002, 3.051152e-001, -3.749544e-002, -2.713209e-001, 1.164226e+000, 4.559969e-001, 2.175429e+000, 2.874284e-001, -1.078500e+000, -3.801779e-001, 4.788906e-001, -4.795969e-001, 5.977621e-001, -4.488535e-001, 3.386874e-002, 1.538143e+000, 8.062054e-001, -1.108028e+000, -2.596892e-001, 5.162202e-001, 1.557081e+000, -4.265039e+000, 1.182535e+000, 1.563762e-001, 2.095084e+000, 6.883383e-001, // albedo 0, turbidity 7 -1.668427e+000, -7.908511e-001, -2.779690e+001, 2.799746e+001, -7.186935e-003, 3.757766e-001, -3.326858e-006, 2.563421e+000, 5.439687e-001, -2.156175e+000, -1.220004e+000, 3.585732e+000, -3.235988e+000, -1.086239e-002, 1.846143e-001, 1.046017e-001, 1.234427e+000, 2.842191e-001, -1.117051e+000, -4.101627e-001, -8.463730e-001, 7.671472e-001, -2.226609e-002, 8.574943e-001, -3.434124e-001, 4.475715e+000, 1.154824e+000, -7.444840e-001, 2.312078e-001, -5.393724e-001, 1.574213e-001, -1.763914e-001, 2.751692e-001, 5.564200e-001, 2.217672e+000, 3.483932e-001, -1.273036e+000, -5.275562e-001, 4.902512e-001, -4.498436e-002, 4.339366e-001, 2.386682e-001, 2.380879e-002, 1.413444e+000, 7.855923e-001, -1.084192e+000, -2.936753e-001, 4.719432e-001, 1.384436e+000, -3.257789e+000, 6.119543e-001, 1.681884e-001, 1.650441e+000, 6.936631e-001, // albedo 0, turbidity 8 -1.848490e+000, -9.512670e-001, -3.005251e+001, 3.024315e+001, -5.635304e-003, 3.447780e-001, -2.782999e-006, 2.309422e+000, 5.643559e-001, -2.300008e+000, -1.252335e+000, -1.218876e+000, 1.493730e+000, -6.107100e-003, 7.974860e-002, 1.023449e-001, 1.505934e+000, 2.360948e-001, -1.483705e+000, -8.547575e-001, -7.797146e-001, 6.447971e-001, -2.678052e-002, 1.091263e+000, -3.344889e-001, 3.830416e+000, 1.189425e+000, -5.348005e-001, 3.982733e-001, -4.071573e-001, 3.265569e-001, -8.658789e-002, -2.370892e-001, 5.369097e-001, 1.478279e+000, 3.143303e-001, -1.320401e+000, -6.043247e-001, 3.019196e-001, -7.732911e-002, 4.768381e-001, 6.745764e-001, 3.694098e-002, 1.158234e+000, 8.169056e-001, -1.101040e+000, -3.420019e-001, 3.775661e-001, 1.769338e+000, -2.990515e+000, 1.649529e-001, 1.970125e-001, 1.453355e+000, 6.759757e-001, // albedo 0, turbidity 9 -2.251946e+000, -1.229349e+000, -3.271808e+001, 3.283114e+001, -4.252027e-003, 3.372289e-001, -3.001937e-006, 2.154046e+000, 5.842674e-001, -1.867834e+000, -9.531252e-001, -1.229365e+001, 1.269149e+001, -6.844772e-003, 1.185107e-001, 7.539587e-002, 1.846381e+000, 1.899412e-001, -3.398629e+000, -2.180862e+000, 2.335213e+000, -3.382823e+000, -8.613985e-003, 8.431602e-001, -2.393567e-001, 3.112460e+000, 1.218556e+000, 5.708381e-001, 9.406030e-001, -6.890113e-001, 2.746233e+000, -5.772068e-002, 1.096005e-001, 3.491978e-001, 7.281453e-001, 3.212049e-001, -1.705909e+000, -8.517224e-001, 1.131160e-001, -2.141434e+000, 4.274043e-001, 3.397600e-001, 1.786490e-001, 9.026101e-001, 7.882800e-001, -1.012865e+000, -3.495551e-001, 3.369038e-001, 3.724205e+000, -3.089586e+000, 1.266964e-001, 1.461790e-001, 1.170199e+000, 6.931052e-001, // albedo 0, turbidity 10 -2.890318e+000, -1.665573e+000, -3.493756e+001, 3.500369e+001, -2.984251e-003, 2.622419e-001, -4.259360e-006, 1.947681e+000, 6.905752e-001, -1.956022e+000, -1.062900e+000, -1.919714e+001, 1.975164e+001, -8.865396e-003, 2.165540e-001, 5.475637e-002, 1.761134e+000, 3.164249e-003, -5.612198e+000, -3.101371e+000, 4.098034e+000, -6.144001e+000, 9.944958e-003, 2.905472e-001, -1.707110e-001, 3.199107e+000, 1.337660e+000, 8.353756e-001, 4.855943e-001, -1.243589e+000, 5.147385e+000, -7.013963e-002, 9.380410e-001, 2.335714e-001, 1.727744e-001, 2.802696e-001, -1.524329e+000, -7.388547e-001, 3.259025e-001, -4.050634e+000, 4.058549e-001, -2.591384e-001, 1.898299e-001, 3.556071e-001, 7.884126e-001, -1.070371e+000, -4.207858e-001, 1.739862e-001, 5.293410e+000, -3.136757e+000, 2.323856e-001, 1.673706e-001, 1.007227e+000, 6.844287e-001, // albedo 1, turbidity 1 -1.341720e+000, -4.834889e-001, -4.633447e+001, 4.682148e+001, -6.137296e-003, 4.599216e-001, 7.047323e-003, 2.895798e+000, 4.999398e-001, -1.529104e+000, -6.498631e-001, 1.534103e+001, -1.450675e+001, -1.531439e-002, 3.280082e-001, 1.682926e-002, 1.901587e+000, 5.013227e-001, -1.014776e+000, -1.454495e-001, -4.071085e+000, 2.954982e+000, -2.630348e-002, 5.681531e-001, -3.016505e-002, 6.773854e+000, 5.003504e-001, -1.172413e+000, -4.026320e-001, 2.960428e+000, 2.020710e-001, -2.004947e-001, 9.375572e-001, 5.998168e-002, -4.945934e+000, 4.502898e-001, -9.898161e-001, -5.772814e-002, 4.470024e-001, -5.786656e-001, 1.158168e-001, 3.468040e-001, -5.043360e-002, 6.867947e+000, 8.012363e-001, -1.085111e+000, -1.882675e-001, 1.223748e+000, 3.565495e-001, -3.688357e+000, 5.653723e-001, 6.727646e-002, 2.690130e+000, 4.999400e-001, // albedo 1, turbidity 2 -1.389119e+000, -5.290250e-001, -4.055774e+001, 4.105972e+001, -7.062577e-003, 4.560060e-001, -1.736334e-006, 2.775512e+000, 6.671455e-001, -1.584641e+000, -7.200619e-001, 1.248067e+001, -1.156028e+001, -1.659568e-002, 3.050029e-001, 1.099895e-002, 1.438927e+000, -2.138015e-002, -9.826068e-001, -8.887254e-002, -2.960031e+000, 1.808816e+000, -2.478159e-002, 6.035733e-001, -4.868441e-002, 7.347705e+000, 1.584739e+000, -1.150423e+000, -4.073793e-001, 2.412991e+000, 4.870840e-001, -2.337902e-001, 8.295114e-001, 1.129914e-001, -5.150045e+000, -9.016643e-002, -1.016933e+000, -6.311501e-002, 5.218937e-001, -5.716430e-001, 1.250993e-001, 3.601524e-001, -5.497586e-002, 7.060139e+000, 1.018333e+000, -1.073151e+000, -1.845444e-001, 1.155394e+000, 3.004486e-001, -3.431711e+000, 4.657031e-001, 9.401223e-002, 2.688620e+000, 4.999544e-001, // albedo 1, turbidity 3 -1.391257e+000, -5.365815e-001, -4.255881e+001, 4.299132e+001, -5.838466e-003, 4.229134e-001, -2.760038e-006, 2.775531e+000, 6.234597e-001, -1.780062e+000, -9.228880e-001, 1.376172e+001, -1.260946e+001, -1.507526e-002, 3.117435e-001, 2.205045e-002, 6.093731e-001, 3.463446e-002, -7.388169e-001, 1.275670e-001, -3.999528e+000, 2.223993e+000, -1.856853e-002, 5.439310e-001, -8.834054e-002, 8.037139e+000, 1.645951e+000, -1.322387e+000, -5.320143e-001, 2.659359e+000, 1.086712e+000, -2.129712e-001, 8.704649e-001, 1.800315e-001, -4.967241e+000, -1.383720e-001, -9.378288e-001, -1.599895e-002, 3.607555e-001, -1.980561e+000, 3.791456e-001, 1.212268e-001, -2.845992e-002, 6.825542e+000, 1.059139e+000, -1.100832e+000, -2.172313e-001, 1.211561e+000, 2.002721e+000, -5.010011e+000, 5.717583e-001, 6.777702e-002, 2.160006e+000, 5.676392e-001, // albedo 1, turbidity 4 -1.409373e+000, -5.708751e-001, -3.034974e+001, 3.079809e+001, -7.280715e-003, 3.723304e-001, -2.436279e-006, 2.577348e+000, 5.913377e-001, -1.954312e+000, -1.116510e+000, 5.399148e+000, -4.299553e+000, -1.724739e-002, 3.742824e-001, 4.187077e-002, 1.044883e-001, 1.232727e-001, -6.772215e-001, 2.001396e-001, -3.670523e-001, -1.014628e+000, -3.497152e-003, 4.099858e-001, -1.584633e-001, 7.750400e+000, 1.514559e+000, -1.291600e+000, -4.977437e-001, 9.641914e-001, 1.562420e+000, -3.227782e-001, 9.055427e-001, 3.046444e-001, -3.385619e+000, 9.546291e-003, -9.750857e-001, -8.770560e-002, 9.054256e-001, -1.429236e+000, 8.974777e-001, -1.217961e-001, -5.194608e-002, 4.909409e+000, 9.589153e-001, -1.088007e+000, -1.959301e-001, 9.745799e-001, 1.260761e+000, -5.008864e+000, 7.271248e-001, 1.096661e-001, 2.717295e+000, 6.340731e-001, // albedo 1, turbidity 5 -1.456050e+000, -6.223072e-001, -2.228088e+001, 2.269604e+001, -9.340812e-003, 4.118308e-001, -2.418083e-006, 2.442117e+000, 5.589638e-001, -2.176449e+000, -1.302416e+000, 2.222836e+000, -1.222730e+000, -1.728051e-002, 1.323513e-001, 7.027731e-002, 4.835745e-002, 2.093351e-001, -5.789641e-001, 2.215407e-001, 2.142291e-001, -1.201725e+000, -1.185728e-002, 8.122982e-001, -2.380420e-001, 6.706841e+000, 1.404146e+000, -1.307463e+000, -4.515174e-001, 6.447827e-001, 1.223841e+000, -2.902391e-001, 4.986588e-001, 4.073652e-001, -1.706696e+000, 1.060885e-001, -9.698678e-001, -1.307094e-001, 9.389347e-001, -1.522852e+000, 7.768797e-001, -1.368595e-001, -3.857426e-002, 3.676935e+000, 8.980966e-001, -1.104349e+000, -2.380323e-001, 1.047043e+000, 1.865421e+000, -5.011664e+000, 7.014954e-001, 9.622701e-002, 1.891360e+000, 6.687354e-001, // albedo 1, turbidity 6 -1.502249e+000, -6.724523e-001, -2.888092e+001, 2.930360e+001, -6.685766e-003, 3.685464e-001, -2.469442e-006, 2.310797e+000, 5.566754e-001, -2.217125e+000, -1.364924e+000, 4.048243e+000, -3.111333e+000, -1.317747e-002, 1.921948e-001, 8.627702e-002, 1.981769e-003, 2.213689e-001, -6.215757e-001, 1.687995e-001, -5.949131e-001, -1.551293e-001, 3.356129e-004, 6.897657e-001, -2.855053e-001, 6.271042e+000, 1.363084e+000, -1.216317e+000, -3.489429e-001, 7.566226e-001, 5.409809e-001, -2.830843e-001, 6.191825e-001, 4.755163e-001, -9.131387e-001, 1.383909e-001, -1.030437e+000, -2.034064e-001, 8.335995e-001, -1.050947e+000, 8.689093e-001, -3.672310e-001, -4.056183e-002, 3.111269e+000, 8.856842e-001, -1.078984e+000, -2.070549e-001, 9.683145e-001, 1.497022e+000, -5.007653e+000, 7.702541e-001, 1.285822e-001, 2.225188e+000, 6.587911e-001, // albedo 1, turbidity 7 -1.559291e+000, -7.374039e-001, -3.596311e+001, 3.634470e+001, -4.667132e-003, 3.277964e-001, -2.487945e-006, 2.215652e+000, 5.764681e-001, -2.356929e+000, -1.444755e+000, 6.244526e+000, -5.540162e+000, -8.794510e-003, 1.792100e-001, 9.578517e-002, 3.737676e-001, 1.922194e-001, -6.589752e-001, -2.926910e-002, -1.831779e+000, 1.869962e+000, -2.030095e-003, 7.552089e-001, -3.168157e-001, 4.632196e+000, 1.294054e+000, -1.161046e+000, -1.472506e-001, 6.494138e-001, -8.327174e-001, -2.320724e-001, 3.391212e-001, 5.269637e-001, 9.376341e-001, 2.458573e-001, -1.034427e+000, -3.062504e-001, 8.975634e-001, 3.203531e-001, 8.565142e-001, -1.250162e-001, -4.094017e-002, 1.861304e+000, 8.223468e-001, -1.109954e+000, -2.740277e-001, 1.063811e+000, 7.077398e-001, -4.695734e+000, 5.621696e-001, 1.248956e-001, 1.297723e+000, 6.789720e-001, // albedo 1, turbidity 8 -1.788293e+000, -9.368751e-001, -4.382980e+001, 4.424963e+001, -3.652530e-003, 3.094331e-001, -2.810503e-006, 1.904402e+000, 5.861599e-001, -2.268206e+000, -1.312676e+000, 2.863082e+000, -2.373727e+000, -5.144980e-003, 1.711072e-001, 9.316041e-002, 9.309598e-001, 1.791683e-001, -1.376966e+000, -7.418582e-001, -1.349589e+000, 1.563419e+000, -3.124219e-003, 6.967139e-001, -3.061887e-001, 3.602731e+000, 1.255669e+000, -6.017540e-001, 2.815928e-001, 5.424052e-001, -6.885450e-001, -1.620001e-001, 2.980046e-001, 4.995571e-001, 7.371203e-001, 2.812466e-001, -1.278853e+000, -5.245326e-001, 7.870520e-001, 3.125067e-001, 7.748105e-001, -7.788581e-002, 3.490956e-003, 1.283748e+000, 8.130190e-001, -1.050930e+000, -2.786331e-001, 1.056344e+000, 1.053002e+000, -4.047789e+000, 4.432174e-001, 1.169077e-001, 9.532621e-001, 6.806764e-001, // albedo 1, turbidity 9 -2.084927e+000, -1.203954e+000, -4.881638e+001, 4.920160e+001, -2.896045e-003, 2.882977e-001, -3.073517e-006, 1.702211e+000, 6.374180e-001, -2.328567e+000, -1.238023e+000, -1.891019e+000, 2.451520e+000, -5.847581e-003, 2.084702e-001, 7.848130e-002, 1.211048e+000, 8.095008e-002, -2.634632e+000, -1.789460e+000, -1.370558e-001, -3.326435e-001, 2.783737e-003, 5.239451e-001, -2.548881e-001, 2.896327e+000, 1.324116e+000, 6.882616e-002, 5.997821e-001, 1.535398e-001, 1.375209e+000, -1.267285e-001, 4.239743e-001, 4.013122e-001, 1.794675e-001, 2.395382e-001, -1.430918e+000, -6.439041e-001, 8.325980e-001, -1.705612e+000, 7.236426e-001, -5.567593e-002, 6.408718e-002, 6.836524e-001, 8.388887e-001, -1.037956e+000, -3.215402e-001, 9.457349e-001, 3.178114e+000, -4.152156e+000, 2.230992e-001, 1.156198e-001, 7.606223e-001, 6.656923e-001, // albedo 1, turbidity 10 -2.967314e+000, -1.728778e+000, -3.730988e+001, 3.755578e+001, -2.588835e-003, 2.927966e-001, -3.935038e-006, 1.592161e+000, 6.868694e-001, -2.123311e+000, -1.175148e+000, -1.314988e+001, 1.386882e+001, -7.828537e-003, 1.852026e-001, 5.481038e-002, 1.294309e+000, 2.428177e-002, -5.443597e+000, -3.156344e+000, 2.110838e+000, -3.421556e+000, 1.181890e-002, 1.196951e-001, -1.742902e-001, 2.404353e+000, 1.272805e+000, 1.029898e+000, 5.912521e-001, -3.983531e-001, 3.286069e+000, -9.252065e-002, 1.331381e+000, 2.560642e-001, 8.001754e-001, 3.624178e-001, -1.547574e+000, -7.881604e-001, 1.020902e+000, -2.897069e+000, 5.213470e-001, -9.242315e-001, 1.185594e-001, -1.150721e+000, 7.317211e-001, -9.621043e-001, -1.991406e-001, 6.531287e-001, 3.925839e+000, -3.596904e+000, 6.317332e-001, 1.531334e-001, 1.457846e+000, 6.966285e-001, }; static float datasetRGBRad3[] = { // albedo 0, turbidity 1 9.926518e-001, 1.999494e+000, -4.136109e+000, 1.856270e+001, 1.351028e+001, 1.390238e+001, // albedo 0, turbidity 2 9.634366e-001, 2.119694e+000, -4.614523e+000, 1.919701e+001, 1.376644e+001, 1.418731e+001, // albedo 0, turbidity 3 9.446537e-001, 2.171610e+000, -4.915556e+000, 1.918240e+001, 1.537135e+001, 1.400530e+001, // albedo 0, turbidity 4 9.073074e-001, 2.330536e+000, -5.577596e+000, 1.961615e+001, 1.688365e+001, 1.446955e+001, // albedo 0, turbidity 5 8.739124e-001, 2.388682e+000, -5.842995e+000, 1.923265e+001, 1.887735e+001, 1.485698e+001, // albedo 0, turbidity 6 8.563688e-001, 2.391534e+000, -5.769133e+000, 1.828709e+001, 2.097209e+001, 1.469587e+001, // albedo 0, turbidity 7 8.270533e-001, 2.342790e+000, -5.558071e+000, 1.684993e+001, 2.356498e+001, 1.505975e+001, // albedo 0, turbidity 8 7.908339e-001, 2.190341e+000, -4.852571e+000, 1.374862e+001, 2.806846e+001, 1.548444e+001, // albedo 0, turbidity 9 7.403619e-001, 1.783998e+000, -2.983854e+000, 7.622563e+000, 3.507610e+001, 1.615805e+001, // albedo 0, turbidity 10 6.840111e-001, 1.154457e+000, -2.393830e-001, -7.896893e-001, 4.282765e+001, 1.779469e+001, // albedo 1, turbidity 1 1.168300e+000, 1.860993e+000, -2.129074e+000, 1.251952e+001, 3.032499e+001, 2.938716e+001, // albedo 1, turbidity 2 1.150338e+000, 1.918813e+000, -2.413527e+000, 1.274862e+001, 3.087134e+001, 2.951432e+001, // albedo 1, turbidity 3 1.114719e+000, 1.964689e+000, -2.625423e+000, 1.247837e+001, 3.237949e+001, 2.943596e+001, // albedo 1, turbidity 4 1.077948e+000, 2.006292e+000, -2.846934e+000, 1.190195e+001, 3.459293e+001, 2.937492e+001, // albedo 1, turbidity 5 1.035143e+000, 1.986681e+000, -2.752584e+000, 1.060972e+001, 3.722185e+001, 2.918594e+001, // albedo 1, turbidity 6 1.015992e+000, 1.992054e+000, -2.812626e+000, 1.001416e+001, 3.847300e+001, 2.924624e+001, // albedo 1, turbidity 7 9.756887e-001, 1.939897e+000, -2.533281e+000, 8.319176e+000, 4.083907e+001, 2.925586e+001, // albedo 1, turbidity 8 9.264164e-001, 1.716454e+000, -1.597044e+000, 4.739725e+000, 4.507683e+001, 2.878915e+001, // albedo 1, turbidity 9 8.595191e-001, 1.346034e+000, -2.801895e-002, -6.582906e-001, 5.017523e+001, 2.852953e+001, // albedo 1, turbidity 10 7.754116e-001, 7.709245e-001, 2.200201e+000, -7.487661e+000, 5.436622e+001, 2.893432e+001, }; static float *datasetsRGB[] = {datasetRGB1, datasetRGB2, datasetRGB3}; static float *datasetsRGBRad[] = {datasetRGBRad1, datasetRGBRad2, datasetRGBRad3}; RenderKit-ospray-f2a61c2/modules/cpu/lights/sky_model/sky_model_data_spectral.h000066400000000000000000022600451456566705700301240ustar00rootroot00000000000000/* This source is published under the following 3-clause BSD license. Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * None of the names of the contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ // with slight modifications // Copyright 2020 Intel Corporation /* ============================================================================ This file is part of a sample implementation of the analytical skylight and solar radiance models presented in the SIGGRAPH 2012 paper "An Analytic Model for Full Spectral Sky-Dome Radiance" and the 2013 IEEE CG&A paper "Adding a Solar Radiance Function to the Hosek Skylight Model" both by Lukas Hosek and Alexander Wilkie Charles University in Prague, Czech Republic Version: 1.4a, February 22nd, 2013 Version history: 1.4a February 22nd, 2013 Removed unnecessary and counter-intuitive solar radius parameters from the interface of the colourspace sky dome initialisation functions. 1.4 February 11th, 2013 Fixed a bug which caused the relative brightness of the solar disc and the sky dome to be off by a factor of about 6. The sun was too bright: this affected both normal and alien sun scenarios. The coefficients of the solar radiance function were changed to fix this. 1.3 January 21st, 2013 (not released to the public) Added support for solar discs that are not exactly the same size as the terrestrial sun. Also added support for suns with a different emission spectrum ("Alien World" functionality). 1.2a December 18th, 2012 Fixed a mistake and some inaccuracies in the solar radiance function explanations found in ArHosekSkyModel.h. The actual source code is unchanged compared to version 1.2. 1.2 December 17th, 2012 Native RGB data and a solar radiance function that matches the turbidity conditions were added. 1.1 September 2012 The coefficients of the spectral model are now scaled so that the output is given in physical units: W / (m^-2 * sr * nm). Also, the output of the XYZ model is now no longer scaled to the range [0...1]. Instead, it is the result of a simple conversion from spectral data via the CIE 2 degree standard observer matching functions. Therefore, after multiplication with 683 lm / W, the Y channel now corresponds to luminance in lm. 1.0 May 11th, 2012 Initial release. Please visit http://cgg.mff.cuni.cz/projects/SkylightModelling/ to check if an updated version of this code has been published! ============================================================================ */ /* This file contains the coefficient data for the spectral version of the model. */ // uses Apr 26 dataset static float dataset320[] = { // albedo 0, turbidity 1 -1.341049e+001, -3.742293e+000, -5.229614e+000, 5.307180e+000, -2.182658e-002, 1.497676e-001, -8.561730e-006, 1.733480e+000, 8.826913e-001, -1.426825e+001, -3.550926e+000, 5.719350e-002, 3.165753e-001, -5.870693e-002, 1.333896e-001, 1.779338e-005, 1.504276e+000, 9.750357e-001, -2.239068e+000, -4.290407e+000, -7.494879e-001, 2.864989e-001, -6.017855e-002, 1.325901e-001, -1.661674e-004, 1.732120e+000, 6.513374e-001, -1.336194e+000, -2.467808e-001, 3.961139e-001, -6.723820e-002, -1.817268e-001, 1.017581e-002, 6.096079e-004, 1.986859e+000, 1.415296e+000, -1.554271e+000, -1.811527e+000, 7.309756e-001, 1.766793e-003, 5.779090e-001, 6.186216e-001, -1.755338e-003, -2.701090e-002, 2.699530e-001, -8.449639e-001, -5.665198e-001, 5.525823e-001, -2.838870e-003, -4.555228e+000, 2.824945e-001, 4.002014e-003, 1.114208e+000, 6.637074e-001, // albedo 0, turbidity 2 -1.298333e+001, -3.775577e+000, -5.173531e+000, 5.316518e+000, -2.572615e-002, 1.516601e-001, -8.297168e-006, 1.669649e+000, 9.000495e-001, -1.402639e+001, -3.787558e+000, 7.611941e-002, 2.521881e-001, -5.859973e-002, 1.753711e-001, 4.670097e-005, 1.459275e+000, 8.998629e-001, -2.190256e+000, -3.575495e+000, -4.930996e-001, 4.826321e-002, -6.797145e-002, 3.425922e-002, -3.512550e-004, 1.978419e+000, 8.866517e-001, -2.415991e+000, -1.453294e+000, 2.170671e-001, 1.341284e-001, -1.926330e-001, 1.059103e-001, 1.360739e-003, 1.587725e+000, 9.821154e-001, -5.254592e-001, -8.181026e-001, 7.535702e-001, -3.323364e-002, 4.503149e-001, 5.778285e-001, -4.089673e-003, 3.335089e-001, 6.827164e-001, -1.280108e+000, -1.013716e+000, 5.577676e-001, 9.539205e-004, -4.934956e+000, 2.642883e-001, 1.005169e-002, 9.265844e-001, 4.999698e-001, // albedo 0, turbidity 3 -1.292247e+001, -3.819777e+000, -4.478733e+000, 4.582924e+000, -2.364370e-002, 1.619828e-001, -3.053548e-006, 1.646629e+000, 5.103371e-001, -1.433099e+001, -3.766213e+000, 4.930150e-001, -3.081235e-002, -6.522199e-002, 1.564198e-001, 3.455657e-004, 1.428507e+000, 4.312273e-001, -2.539220e+000, -3.459074e+000, -3.774393e-001, -3.628419e-001, -2.124451e-001, -1.358132e-002, -1.812805e-003, 2.245152e+000, 7.247429e-001, -2.393246e+000, -1.937898e+000, 1.005834e-001, 5.867890e-001, 2.645044e-001, 1.413695e-001, 6.378716e-003, 1.140715e+000, 1.263014e+000, -1.185583e-001, -1.960943e-001, 7.212723e-001, -1.763978e-001, -1.000190e+000, 6.259726e-001, -1.783726e-002, 7.790644e-001, 3.244710e-001, -1.550325e+000, -1.333575e+000, 5.618137e-001, 2.563595e-002, -5.007716e+000, 6.522985e-002, 4.262830e-002, 7.371930e-001, 5.239972e-001, // albedo 0, turbidity 4 -1.234358e+001, -3.851875e+000, -3.911206e+000, 4.011324e+000, -2.734425e-002, 1.272306e-001, -7.628210e-006, 1.661843e+000, 8.993903e-001, -1.349727e+001, -3.592681e+000, 1.335192e+000, -9.426446e-001, -5.741127e-002, 9.765267e-002, 5.518099e-005, 1.428554e+000, -4.278471e-001, -3.399618e+000, -3.818725e+000, -8.698171e-001, 2.723930e-001, -3.644369e-001, 1.238759e-001, -5.189179e-004, 2.279175e+000, 1.841076e+000, -1.925152e+000, -1.539333e+000, 2.757771e-001, -6.435980e-002, 6.466700e-001, 3.084382e-002, 3.114730e-003, 1.259818e+000, 5.121617e-001, -5.706832e-001, -6.696186e-001, 6.798158e-001, 6.920162e-001, -3.898854e+000, 5.954021e-001, -1.196667e-002, 5.714991e-001, 6.528481e-001, -1.371907e+000, -1.142330e+000, 5.207805e-001, -4.480298e-003, -5.008950e+000, 1.251549e-001, 3.531514e-002, 8.776759e-001, 4.999465e-001, // albedo 0, turbidity 5 -1.459738e+001, -3.833562e+000, -4.148717e+000, 4.203270e+000, -2.484405e-002, 1.189704e-001, 4.166397e-004, 1.748850e+000, 4.999721e-001, -1.223022e+001, -3.942049e+000, 1.183072e+000, -9.018678e-001, -4.644071e-002, 1.237476e-001, -2.359994e-003, 1.471013e+000, 5.298845e-001, -4.078262e+000, -3.261096e+000, -5.520001e-001, 2.174261e-001, -3.582576e-001, 2.000597e-002, 9.890182e-003, 2.199274e+000, 2.756320e-001, -2.499065e+000, -2.408391e+000, 3.391663e-002, -6.167543e-002, 7.555424e-001, 2.349252e-001, -2.443140e-002, 1.328540e+000, 1.348906e+000, 5.456648e-002, -9.221401e-002, 7.403428e-001, 5.565324e-001, -5.134970e+000, 3.021763e-001, 3.638500e-002, 5.560149e-001, 1.818210e-001, -1.590269e+000, -1.344330e+000, 4.805789e-001, 5.038509e-001, -3.370644e+000, 3.040357e-001, 2.418483e-003, 8.979818e-001, 7.477974e-001, // albedo 0, turbidity 6 -6.775680e+000, -3.436745e+000, -2.696730e+000, 2.740681e+000, -4.032382e-002, 1.036486e-001, 8.133034e-005, 1.767160e+000, 5.401354e-001, -7.800595e+000, -2.867058e+000, 1.478909e+000, -1.380160e+000, -1.658909e-001, 1.962673e-001, -6.512798e-004, 1.634359e+000, 4.300704e-001, -4.392403e+000, -3.857979e+000, -1.022020e+000, 1.449394e+000, 2.769695e-001, -3.331834e-001, 3.513950e-003, 1.942113e+000, 3.970742e-001, -2.469701e+000, -1.357319e+000, 2.132600e-001, -1.918729e+000, -4.193060e+000, 8.101579e-001, -9.605279e-003, 1.844443e+000, 1.582310e+000, -7.759612e-001, -1.298076e+000, 7.162377e-001, 2.906682e+000, -8.261148e-001, -2.892123e-001, 1.491449e-002, 6.529387e-002, -4.180287e-002, -9.962340e-001, -6.488730e-001, 3.933344e-001, -4.752111e-003, -4.721793e+000, 6.053196e-001, 3.453563e-003, 1.247655e+000, 8.673379e-001, // albedo 0, turbidity 7 -7.552689e+000, -3.219112e+000, -2.730242e+000, 2.755929e+000, -3.925138e-002, 8.394617e-002, 1.514980e-004, 1.844410e+000, 5.389194e-001, -8.494732e+000, -3.138528e+000, 1.424739e+000, -1.269326e+000, -1.561580e-001, 1.767060e-001, -1.175921e-003, 1.659123e+000, 3.746132e-001, -4.672972e+000, -4.049529e+000, -1.027600e+000, 1.072252e+000, 7.908165e-002, -2.243835e-001, 6.190595e-003, 1.988822e+000, 6.684758e-001, -2.256117e+000, -1.258356e+000, 2.198377e-001, -1.296239e+000, -3.200970e+000, 6.407291e-001, -1.527762e-002, 1.735209e+000, 1.170530e+000, -7.790059e-001, -1.269213e+000, 6.315194e-001, 2.368850e+000, -1.199163e+000, -1.504024e-001, 1.733299e-002, 2.544016e-001, 2.756763e-001, -1.046916e+000, -6.991719e-001, 3.620624e-001, 7.364236e-002, -5.012491e+000, 4.240417e-001, 3.580425e-002, 1.202329e+000, 6.255804e-001, // albedo 0, turbidity 8 -1.886851e+001, -4.491136e+000, -3.660440e+000, 3.704226e+000, -3.158478e-002, 1.229909e-001, 9.233613e-004, 1.745459e+000, 5.011929e-001, -1.986322e+001, -3.528401e+000, 1.401749e+000, -1.191377e+000, -7.474944e-002, -2.193835e-002, -5.138968e-003, 1.710181e+000, 5.473672e-001, 5.355660e-001, -5.459304e+000, -8.809226e-001, 5.959028e-001, -3.311339e-001, 3.876731e-001, 2.126070e-002, 1.929868e+000, 1.883429e-001, -3.136053e+000, -2.856938e-001, 1.048390e-001, -7.708877e-001, 2.106630e-001, -1.488471e-001, -5.172733e-002, 1.769302e+000, 1.526253e+000, 1.496752e-001, -9.170428e-001, 5.628226e-001, 1.733601e+000, -4.784033e+000, 3.570330e-001, 7.396580e-002, 3.954993e-001, 1.397727e-003, -1.839740e+000, -1.279260e+000, 3.173503e-001, 1.096266e+000, -4.168649e+000, 2.121881e-001, 2.150917e-002, 1.151497e+000, 7.233585e-001, // albedo 0, turbidity 9 -1.841090e+001, -4.803089e+000, -4.883823e+000, 4.962235e+000, -2.693216e-002, 1.089917e-001, -6.338015e-006, 1.725865e+000, 8.890717e-001, -1.947081e+001, -2.961260e+000, 1.963002e+000, -1.942423e+000, -5.550118e-002, 7.036456e-002, -5.990592e-004, 1.807097e+000, -8.871814e-003, 9.588307e-001, -6.379803e+000, -1.021090e+000, 9.560589e-001, -2.175500e-001, 8.613517e-002, 1.362268e-002, 1.953529e+000, 7.422482e-001, -3.609766e+000, -1.823498e-003, 2.516424e-002, -8.909855e-001, 2.207805e-001, 1.783064e-001, -4.293958e-002, 1.607901e+000, 1.131559e+000, 6.087707e-001, -6.744295e-001, 4.236310e-001, 1.505925e+000, -4.197126e+000, 2.046561e-001, 6.445824e-002, 7.793118e-001, 3.262213e-001, -2.148492e+000, -1.597890e+000, 3.166858e-001, 2.414329e+000, -4.201339e+000, 1.005902e-001, 4.687865e-002, 9.335376e-001, 5.289661e-001, // albedo 0, turbidity 10 -1.787767e+001, -4.873485e+000, -5.861224e+000, 5.866336e+000, -1.564202e-002, 6.967640e-002, 7.574926e-004, 1.768065e+000, 5.856596e-001, -1.932995e+001, -4.092647e+000, 2.679531e+000, -2.555671e+000, -4.181418e-002, 1.023654e-001, -5.964172e-003, 1.625691e+000, 4.036808e-001, 1.788482e+000, -5.652582e+000, -1.517519e+000, 1.251535e+000, -2.225912e-001, -1.084716e-001, 3.272584e-002, 2.139078e+000, 3.876645e-001, -3.363801e+000, -3.266475e-001, 1.313912e-001, -6.889075e-001, 4.356523e-001, 3.120297e-001, -8.700131e-002, 1.750122e+000, 1.223546e+000, 4.668756e-004, -9.612337e-001, 3.082344e-001, 1.298938e+000, -4.371395e+000, 8.845524e-002, 1.303481e-001, 5.843720e-001, 2.718863e-001, -1.759172e+000, -1.386072e+000, 2.349661e-001, 1.592185e+000, -3.063267e+000, 1.529736e-001, 3.429185e-002, 1.030294e+000, 6.917018e-001, // albedo 1, turbidity 1 -1.341051e+001, -3.742047e+000, -5.229556e+000, 5.307222e+000, -2.094796e-002, 1.499787e-001, -7.023116e-006, 1.732898e+000, 8.826861e-001, -1.426829e+001, -3.550660e+000, 5.731266e-002, 3.166575e-001, -5.821080e-002, 1.335860e-001, 2.003178e-004, 1.503788e+000, 9.750310e-001, -2.239143e+000, -4.290084e+000, -7.493158e-001, 2.865753e-001, -5.993923e-002, 1.327393e-001, -5.399344e-004, 1.731677e+000, 6.513329e-001, -1.336350e+000, -2.463606e-001, 3.963632e-001, -6.721398e-002, -1.816244e-001, 1.021503e-002, 8.081470e-004, 1.986453e+000, 1.415292e+000, -1.554584e+000, -1.810948e+000, 7.313475e-001, 1.703307e-003, 5.779436e-001, 6.184790e-001, -6.832621e-004, -2.739619e-002, 2.699443e-001, -8.456234e-001, -5.656772e-001, 5.531782e-001, -2.975361e-003, -4.555221e+000, 2.821035e-001, 4.007713e-004, 1.113850e+000, 6.636719e-001, // albedo 1, turbidity 2 -1.263311e+001, -4.099112e+000, -5.130792e+000, 5.526406e+000, -2.122841e-002, 1.202556e-001, -8.060670e-006, 1.209196e+000, 8.997967e-001, -1.361400e+001, -3.538236e+000, 1.570583e-001, 3.445259e-001, -5.306874e-002, 2.322893e-001, 1.572516e-005, 1.152750e+000, 9.026902e-001, -1.477014e+000, -3.664310e+000, -1.442116e-001, -4.293554e-002, -3.768326e-002, -1.388530e-001, -1.687893e-004, 1.592625e+000, 8.804841e-001, -2.050884e+000, -1.470536e+000, 3.327590e-001, 1.976143e-001, -1.930369e-001, 2.831960e-001, 6.940849e-004, 1.271203e+000, 9.790242e-001, -3.704793e-001, -5.829841e-001, 1.168589e+000, -1.387973e-001, 5.998426e-001, 3.825096e-001, -2.188637e-003, -2.273264e-001, 7.393514e-001, -9.877542e-001, -7.646946e-001, 8.859003e-001, 5.263145e-002, -4.849410e+000, 1.301905e-001, 5.464872e-003, 5.270984e-001, 5.001226e-001, // albedo 1, turbidity 3 -1.294452e+001, -3.858933e+000, -4.362969e+000, 4.657159e+000, -2.281956e-002, 1.371565e-001, 3.552610e-006, 1.354369e+000, 5.222053e-001, -1.425646e+001, -3.745266e+000, 6.901454e-001, -5.345642e-002, -5.238708e-002, 1.157055e-001, -1.961110e-005, 1.030408e+000, 4.036292e-001, -2.236186e+000, -3.560196e+000, -1.053059e-001, -3.002269e-001, -1.702750e-001, 3.290753e-002, -7.253274e-005, 1.846963e+000, 6.828000e-001, -1.991088e+000, -2.028027e+000, 2.747056e-001, 5.076456e-001, 2.056096e-001, 1.537040e-001, 1.010611e-003, 8.439763e-001, 1.286657e+000, -2.733597e-001, -1.938590e-001, 1.108079e+000, -1.668080e-001, -8.136300e-001, 3.962292e-001, -4.757393e-003, 1.536882e-001, 4.595467e-001, -9.782447e-001, -8.452104e-001, 9.149995e-001, 2.750126e-002, -4.996263e+000, 1.226836e-001, 1.533731e-002, 3.686265e-001, 5.004484e-001, // albedo 1, turbidity 4 -1.234416e+001, -3.818503e+000, -3.804408e+000, 4.093838e+000, -2.505623e-002, 1.149315e-001, -7.610563e-006, 1.361584e+000, 8.981571e-001, -1.349621e+001, -3.551853e+000, 1.469377e+000, -8.971164e-001, -5.623731e-002, 1.078524e-001, 1.491378e-003, 1.113040e+000, -4.279059e-001, -3.391950e+000, -3.791028e+000, -6.935352e-001, 2.998175e-001, -3.155309e-001, 1.196041e-001, -4.708048e-003, 2.001973e+000, 1.840166e+000, -1.915114e+000, -1.493080e+000, 4.567342e-001, -7.334296e-002, 6.767060e-001, -4.562689e-003, 1.016838e-002, 1.003272e+000, 5.102018e-001, -5.674128e-001, -5.568719e-001, 9.084369e-001, 6.684870e-001, -3.892720e+000, 5.312866e-001, -1.768715e-002, 3.252051e-001, 6.541029e-001, -1.343751e+000, -9.647458e-001, 7.945561e-001, 5.127485e-004, -5.009873e+000, 6.165389e-002, 2.642926e-002, 6.213595e-001, 5.327376e-001, // albedo 1, turbidity 5 -1.450562e+001, -4.021778e+000, -4.181517e+000, 4.509518e+000, -2.369519e-002, 6.955582e-002, 1.149882e-004, 1.329583e+000, 5.260857e-001, -1.297772e+001, -3.655039e+000, 2.030636e+000, -1.537436e+000, -4.915490e-002, 1.511047e-001, -9.053517e-004, 1.156980e+000, 4.831690e-001, -1.991837e+000, -3.919397e+000, -8.466357e-001, 5.319508e-001, -3.165811e-001, 1.056172e-001, 4.836036e-003, 1.843574e+000, 3.084513e-001, -2.052725e+000, -1.606839e+000, 5.876624e-001, -7.464148e-002, 7.525473e-001, 1.590947e-003, -1.261084e-002, 8.587516e-001, 1.404076e+000, -3.737447e-001, -4.061843e-001, 8.985804e-001, 5.700187e-001, -5.422882e+000, 4.334301e-001, 1.759754e-002, 2.613056e-001, 2.062463e-001, -1.002263e+000, -1.006484e+000, 9.629219e-001, 8.528366e-002, -4.220831e+000, 7.848806e-002, 1.254937e-002, 2.140208e-001, 6.187813e-001, // albedo 1, turbidity 6 -7.175451e+000, -3.313094e+000, -2.396914e+000, 2.657177e+000, -3.936959e-002, 1.123476e-001, 7.315860e-005, 1.431209e+000, 5.107145e-001, -8.058121e+000, -3.119458e+000, 1.729776e+000, -1.435370e+000, -1.414745e-001, 2.338787e-001, -5.865288e-004, 1.247225e+000, 5.037743e-001, -4.387785e+000, -3.851081e+000, -7.774273e-001, 1.405520e+000, 1.743075e-001, -4.108912e-001, 3.058571e-003, 1.519803e+000, 2.636805e-001, -1.807473e+000, -1.498491e+000, 3.237723e-001, -1.626737e+000, -3.741656e+000, 8.444519e-001, -8.297013e-003, 1.624861e+000, 1.753817e+000, -6.242455e-001, -1.063850e+000, 1.166897e+000, 2.283807e+000, -1.150947e+000, -3.242997e-001, 1.279340e-002, -5.448139e-001, -8.653106e-002, -8.143405e-001, -5.251732e-001, 7.822692e-001, -3.764280e-003, -5.011112e+000, 3.985065e-001, 3.652394e-003, 7.140115e-001, 7.004910e-001, // albedo 1, turbidity 7 -7.579673e+000, -3.495594e+000, -2.498830e+000, 2.771470e+000, -3.451351e-002, 8.186886e-002, 1.272079e-004, 1.390420e+000, 5.545117e-001, -8.524117e+000, -3.121778e+000, 1.680395e+000, -1.329455e+000, -1.395912e-001, 1.911589e-001, -1.027988e-003, 1.259267e+000, 3.356989e-001, -4.579718e+000, -4.086739e+000, -8.030175e-001, 1.103390e+000, 1.429699e-001, -2.211841e-001, 5.620349e-003, 1.693702e+000, 7.084432e-001, -1.946704e+000, -1.512415e+000, 3.559506e-001, -1.318829e+000, -3.063409e+000, 6.250046e-001, -1.490672e-002, 1.414520e+000, 1.317647e+000, -7.123367e-001, -1.133848e+000, 1.064800e+000, 2.217543e+000, -1.247373e+000, -2.105594e-001, 2.261048e-002, -3.648618e-001, 1.147223e-001, -7.979833e-001, -5.546030e-001, 7.765850e-001, -4.676928e-003, -5.014372e+000, 3.694816e-001, 2.373221e-003, 6.783145e-001, 7.862971e-001, // albedo 1, turbidity 8 -1.886599e+001, -4.523457e+000, -3.559445e+000, 3.748747e+000, -2.082711e-002, 1.120505e-001, 4.908827e-005, 1.430333e+000, 4.999603e-001, -1.985552e+001, -3.530040e+000, 1.578922e+000, -1.170838e+000, -6.347814e-002, 2.032158e-003, -7.291357e-004, 1.399338e+000, 5.515394e-001, 5.631541e-001, -5.483754e+000, -6.832337e-001, 6.170499e-001, -2.824393e-001, 3.546810e-001, 6.248420e-003, 1.638520e+000, 2.300717e-001, -3.083195e+000, -3.071409e-001, 2.822360e-001, -7.871125e-001, 2.420642e-001, -1.716096e-001, -1.936307e-002, 1.450902e+000, 1.590291e+000, 2.003824e-001, -8.374106e-001, 8.800366e-001, 1.702679e+000, -4.785357e+000, 3.194078e-001, 3.028099e-002, 6.649245e-002, -4.459174e-003, -1.738851e+000, -1.144728e+000, 6.950894e-001, 1.073870e+000, -4.176611e+000, 9.901497e-002, 2.719362e-002, 6.579628e-001, 6.542088e-001, // albedo 1, turbidity 9 -1.842858e+001, -4.464894e+000, -4.876181e+000, 4.999894e+000, -1.680473e-002, 9.284371e-002, 8.631599e-005, 1.551671e+000, 8.637202e-001, -1.946220e+001, -2.928492e+000, 1.932796e+000, -2.009963e+000, -2.067172e-002, 2.760643e-001, -1.316034e-003, 1.910005e+000, -2.057018e-002, 1.012726e+000, -6.397245e+000, -8.570688e-001, 9.466942e-001, -2.428074e-001, 4.505376e-002, 1.159119e-002, 1.686356e+000, 7.885028e-001, -3.502022e+000, -9.795202e-002, 3.286657e-001, -8.318684e-001, 1.254695e-001, 9.600123e-002, -3.501772e-002, 1.161309e+000, 1.205342e+000, 7.024550e-001, -6.903001e-001, 7.519618e-001, 1.501909e+000, -4.224528e+000, 1.253867e-001, 5.829515e-002, 2.671626e-001, 3.030079e-001, -2.056576e+000, -1.583471e+000, 7.947031e-001, 2.224097e+000, -4.127138e+000, 1.885249e-001, 1.729132e-005, 3.336881e-001, 5.332061e-001, // albedo 1, turbidity 10 -1.825745e+001, -5.122861e+000, -5.876715e+000, 5.970876e+000, -1.788919e-002, 1.063934e-001, 4.770037e-004, 1.612403e+000, 5.156506e-001, -1.981828e+001, -3.746331e+000, 2.729783e+000, -2.477317e+000, -2.797536e-002, -5.281985e-002, -3.739083e-003, 1.378246e+000, 5.904024e-001, 1.346751e+000, -6.486837e+000, -1.082622e+000, 1.125524e+000, -2.228944e-001, 3.975587e-001, 2.035973e-002, 1.884664e+000, 1.086023e-003, -3.996320e+000, -4.646476e-001, 3.008639e-002, -1.193861e+000, 4.443960e-001, -2.593178e-001, -5.378377e-002, 1.528777e+000, 1.734923e+000, 4.789259e-001, -8.952042e-001, 8.595191e-001, 2.353988e+000, -4.885398e+000, 4.438339e-001, 7.931163e-002, -8.144393e-002, 1.663921e-002, -1.772626e+000, -1.783205e+000, 7.322534e-001, 1.529827e+000, -2.789303e+000, -1.817210e-001, 2.737502e-002, 2.620216e-001, 6.227585e-001, }; static float datasetRad320[] = { // albedo 0, turbidity 1 9.282016e-004, 3.169257e-004, 5.255138e-003, -1.465200e-002, 7.187172e-002, 5.400860e-002, // albedo 0, turbidity 2 9.160628e-004, 2.599956e-004, 5.466998e-003, -1.503537e-002, 7.200167e-002, 5.387713e-002, // albedo 0, turbidity 3 9.148749e-004, 2.164768e-004, 5.576667e-003, -1.537254e-002, 7.215609e-002, 5.380753e-002, // albedo 0, turbidity 4 9.090685e-004, 1.467840e-004, 5.775870e-003, -1.598491e-002, 7.252530e-002, 5.329870e-002, // albedo 0, turbidity 5 8.902830e-004, 1.126529e-004, 5.945913e-003, -1.648173e-002, 7.220217e-002, 5.391054e-002, // albedo 0, turbidity 6 8.885423e-004, 1.142350e-004, 5.938903e-003, -1.668800e-002, 7.231405e-002, 5.331532e-002, // albedo 0, turbidity 7 8.674766e-004, 3.506619e-005, 6.176212e-003, -1.732036e-002, 7.223472e-002, 5.318228e-002, // albedo 0, turbidity 8 8.525095e-004, -1.752028e-005, 6.286417e-003, -1.779286e-002, 7.150222e-002, 5.334072e-002, // albedo 0, turbidity 9 8.232652e-004, -1.292152e-004, 6.645270e-003, -1.886566e-002, 7.052974e-002, 5.331726e-002, // albedo 0, turbidity 10 7.670001e-004, -1.885989e-004, 6.484739e-003, -1.852036e-002, 6.610758e-002, 5.484068e-002, // albedo 1, turbidity 1 1.105405e-003, 2.555979e-005, 7.984713e-003, -2.152422e-002, 8.452836e-002, 9.622688e-002, // albedo 1, turbidity 2 1.111427e-003, -6.046059e-005, 8.035207e-003, -2.134768e-002, 8.363698e-002, 9.641842e-002, // albedo 1, turbidity 3 1.103552e-003, -8.229160e-005, 8.170699e-003, -2.189940e-002, 8.404871e-002, 9.504912e-002, // albedo 1, turbidity 4 1.075129e-003, -1.473970e-004, 8.391094e-003, -2.255482e-002, 8.415497e-002, 9.338994e-002, // albedo 1, turbidity 5 1.036467e-003, -1.328992e-004, 8.348236e-003, -2.256138e-002, 8.304671e-002, 9.263679e-002, // albedo 1, turbidity 6 1.042383e-003, -2.016636e-004, 8.479624e-003, -2.296524e-002, 8.303746e-002, 9.082494e-002, // albedo 1, turbidity 7 1.014293e-003, -2.355927e-004, 8.551010e-003, -2.333261e-002, 8.258160e-002, 8.873588e-002, // albedo 1, turbidity 8 9.683336e-004, -2.120256e-004, 8.172046e-003, -2.223973e-002, 7.852279e-002, 8.864017e-002, // albedo 1, turbidity 9 9.139571e-004, -2.688667e-004, 8.068793e-003, -2.224390e-002, 7.590320e-002, 8.464876e-002, // albedo 1, turbidity 10 8.457855e-004, -3.459869e-004, 7.626953e-003, -2.067614e-002, 6.841363e-002, 8.244103e-002, }; static float dataset360[] = { // albedo 0, turbidity 1 -2.974290e+000, -1.670904e+000, -5.183199e+000, 5.377376e+000, -2.904124e-002, 2.486720e-001, 8.045624e-005, 1.889212e+000, 5.188203e-001, -2.638402e+000, -1.651876e+000, -1.229939e+000, 1.776358e+000, -6.372414e-002, 3.767834e-001, -6.475530e-004, 1.373589e+000, 4.349252e-001, -2.449142e+000, -1.541788e+000, 4.629358e-001, -1.149742e+000, -7.317185e-002, -2.422158e-001, 3.667113e-003, 3.146429e+000, 6.725657e-001, -8.559357e-001, -5.054959e-001, 4.334205e-001, 4.254155e-001, -2.920605e-001, 9.303230e-001, -1.212609e-002, 4.498482e-001, 2.117838e-001, -1.098145e+000, -5.123514e-001, 7.773196e-001, -1.325175e-001, 4.648396e-001, 1.386648e-001, 2.427679e-002, 1.199386e+000, 7.988611e-001, -1.124849e+000, -5.693597e-001, 7.315125e-001, 2.986435e-002, -4.536788e+000, 6.650081e-001, -9.004215e-007, 1.006380e+000, 4.999682e-001, // albedo 0, turbidity 2 -2.709497e+000, -1.635812e+000, -4.594177e+000, 4.809336e+000, -3.672907e-002, 2.383111e-001, 3.241989e-005, 1.885505e+000, 6.619619e-001, -2.590279e+000, -1.525236e+000, -6.846073e-001, 1.216080e+000, -8.022814e-002, 3.040074e-001, -4.984576e-004, 1.521429e+000, 1.746040e-001, -2.988403e+000, -1.938687e+000, 4.954649e-002, -8.992325e-001, -7.157111e-002, -4.370068e-002, 4.336645e-003, 2.849496e+000, 8.892788e-001, -2.932084e-001, -1.323910e-001, 5.535910e-001, 7.456284e-001, -2.713400e-001, 6.989175e-001, -1.513162e-002, 6.926848e-001, 5.719944e-001, -1.379400e+000, -6.876864e-001, 7.224534e-001, -6.172704e-001, 1.217500e-001, 3.074795e-001, 2.905167e-002, 1.123563e+000, 6.837510e-001, -1.042446e+000, -5.201193e-001, 7.107656e-001, 4.182566e-001, -4.956238e+000, 5.315425e-001, 6.232999e-003, 1.059015e+000, 5.116427e-001, // albedo 0, turbidity 3 -2.686687e+000, -1.615137e+000, -3.811956e+000, 4.018597e+000, -3.953418e-002, 2.171778e-001, -7.374887e-006, 1.875745e+000, 8.996180e-001, -3.049670e+000, -1.775802e+000, 2.577719e-002, 5.331200e-001, -9.424429e-002, 3.852753e-001, -8.678326e-005, 1.347053e+000, -1.078327e-001, -2.414334e+000, -1.637863e+000, -3.948523e-001, -4.867989e-001, -1.545516e-001, -2.045592e-001, 2.308206e-003, 3.257409e+000, 1.029606e+000, -6.821703e-001, -3.665215e-001, 7.496076e-001, 5.391760e-001, -2.903450e-001, 8.498544e-001, -1.388990e-002, 2.126622e-001, 6.857005e-001, -1.227285e+000, -5.958479e-001, 5.828611e-001, -4.050489e-001, -2.935835e-001, 1.410603e-001, 4.352812e-002, 1.406076e+000, 4.955059e-001, -1.080553e+000, -5.308084e-001, 6.980027e-001, 2.193524e-001, -5.007206e+000, 5.895807e-001, 1.122391e-002, 1.052433e+000, 6.643198e-001, // albedo 0, turbidity 4 -2.983088e+000, -1.746025e+000, -4.564198e+000, 4.776145e+000, -3.208607e-002, 2.008358e-001, -6.578048e-006, 1.829880e+000, 9.001069e-001, -2.858023e+000, -1.624623e+000, 1.859497e+000, -1.348577e+000, -7.427284e-002, 2.943068e-001, -1.961205e-004, 1.502334e+000, -3.183648e-001, -2.858102e+000, -2.072804e+000, -1.205584e+000, 5.674135e-001, -3.934144e-001, -3.736288e-002, 4.780332e-003, 2.831298e+000, 1.553942e+000, -3.305766e-001, -8.277591e-003, 8.561917e-001, -2.239172e-001, 5.896697e-001, 6.229823e-001, -2.242577e-002, 7.216263e-001, 4.295956e-001, -1.322728e+000, -7.101315e-001, 5.645563e-001, 9.897384e-001, -6.756374e+000, 2.491515e-001, 5.308124e-002, 1.166258e+000, 5.472501e-001, -1.117086e+000, -5.760006e-001, 6.388217e-001, 1.659290e-001, -4.687099e+000, 4.544540e-001, 2.672063e-002, 1.067777e+000, 6.419825e-001, // albedo 0, turbidity 5 -2.943340e+000, -1.779161e+000, -3.715839e+000, 3.949049e+000, -4.499824e-002, 2.234466e-001, -8.091518e-006, 1.825217e+000, 9.000118e-001, -3.717358e+000, -1.850324e+000, 2.277659e+000, -2.027790e+000, -1.240730e-001, 3.029522e-001, -2.176255e-004, 1.585933e+000, -2.794001e-001, -2.439542e+000, -2.277701e+000, -1.702329e+000, 2.025885e+000, -1.142291e-001, -2.011641e-001, 5.563891e-003, 2.424957e+000, 1.399542e+000, -1.562453e-001, 5.099893e-001, 1.026847e+000, -2.516874e+000, -2.212969e+000, 9.252660e-001, -2.696795e-002, 1.443711e+000, 7.450372e-001, -1.579698e+000, -1.110703e+000, 4.743061e-001, 4.160187e+000, -4.597085e+000, -2.112156e-001, 6.791770e-002, 6.131169e-001, 2.291635e-001, -9.959610e-001, -4.119588e-001, 5.707529e-001, -3.505536e-003, -4.253949e+000, 7.498003e-001, 8.246945e-003, 1.397857e+000, 8.021253e-001, // albedo 0, turbidity 6 -2.304734e+000, -1.483605e+000, -1.531059e+000, 1.707306e+000, -1.150367e-001, 2.153063e-001, -3.351533e-006, 2.021261e+000, 5.742842e-001, -3.130477e+000, -1.966839e+000, 6.058600e-001, -9.209976e-001, -1.932901e-001, 3.242645e-001, 3.361262e-002, 1.529938e+000, 2.851152e-001, -1.110129e+000, -1.306323e+000, -3.235833e-001, 2.998748e+000, -1.535927e-002, -4.001906e-001, -9.430492e-002, 2.211086e+000, 8.632200e-001, -1.174540e+000, 7.550161e-002, -1.849588e-001, -6.281432e+000, -6.186665e+000, 1.173048e+000, 1.481656e-001, 2.668578e+000, 6.145923e-001, -1.104583e+000, -8.430389e-001, 8.668416e-001, 9.153752e+000, -7.289540e-001, -4.346537e-001, -9.065784e-002, 2.866983e-001, 6.920973e-001, -1.105893e+000, -4.500399e-001, 4.286451e-001, 1.207864e+000, -5.018291e+000, 6.988292e-001, 3.891745e-002, 1.602324e+000, 6.269169e-001, // albedo 0, turbidity 7 -3.709341e+000, -2.038242e+000, -3.127214e+000, 3.287030e+000, -4.565671e-002, 2.427627e-001, -7.503980e-006, 1.817881e+000, 9.000389e-001, -3.393374e+000, -1.710497e+000, 1.661275e+000, -1.388896e+000, -1.012293e-001, 1.676172e-001, -5.719846e-004, 1.694199e+000, -3.140071e-001, -2.812820e+000, -2.678401e+000, -1.170428e+000, 1.560988e+000, -4.488218e-001, 1.088693e-001, 1.391966e-002, 2.144426e+000, 1.525731e+000, 2.547360e-001, 8.840167e-001, 5.469168e-001, -2.615530e+000, -1.048663e+000, 4.823171e-001, -5.958515e-002, 1.842479e+000, 5.322138e-001, -1.612173e+000, -1.055541e+000, 4.733463e-001, 5.083504e+000, -5.558403e+000, 8.029584e-002, 1.294180e-001, 7.807964e-001, 3.949822e-001, -1.098367e+000, -5.550631e-001, 4.221569e-001, -1.661587e-003, -4.970027e+000, 3.479325e-001, 4.503648e-002, 1.369224e+000, 6.753984e-001, // albedo 0, turbidity 8 -4.292777e+000, -2.231300e+000, -4.359252e+000, 4.562131e+000, -3.759725e-002, 2.170783e-001, -6.945269e-006, 1.791630e+000, 8.996451e-001, -4.016595e+000, -1.761175e+000, 2.616213e+000, -2.658657e+000, -8.209207e-002, 2.736152e-001, -6.864170e-004, 1.820262e+000, -2.712707e-001, -2.942646e+000, -3.350329e+000, -1.645817e+000, 2.957424e+000, -1.073783e-001, -1.920050e-001, 1.665992e-002, 1.723144e+000, 1.394962e+000, 9.793627e-001, 1.743715e+000, 5.396545e-001, -4.618273e+000, -2.186669e+000, 1.012973e+000, -7.213786e-002, 2.388103e+000, 6.712519e-001, -2.085434e+000, -1.445755e+000, 3.384806e-001, 7.702938e+000, -3.897179e+000, -5.947697e-001, 1.614194e-001, 7.854754e-001, 3.291034e-001, -9.660466e-001, -5.247410e-001, 4.199048e-001, -3.304707e-003, -5.014144e+000, 6.733599e-001, 2.345161e-002, 1.225739e+000, 7.256834e-001, // albedo 0, turbidity 9 -3.950771e+000, -2.192673e+000, -7.263653e+000, 7.343312e+000, -1.840332e-002, 1.893809e-001, -3.583629e-006, 1.901172e+000, 5.902387e-001, -6.384690e+000, -2.515788e+000, 3.874778e+000, -3.776079e+000, -3.484710e-002, 3.311078e-001, 8.248395e-003, 1.612712e+000, 3.123684e-001, -6.207616e-001, -2.681061e+000, -2.005212e+000, 2.445498e+000, -1.935675e-001, -1.988856e-001, -1.553754e-002, 2.210740e+000, 6.507040e-001, -1.241493e+000, 5.908170e-001, 3.899777e-001, -2.344038e+000, -1.820327e-001, 7.889592e-001, -1.468064e-002, 1.586758e+000, 1.007885e+000, -4.395130e-001, -3.700611e-001, 2.452754e-001, 3.602006e+000, -4.692896e+000, -8.620746e-002, 1.418548e-001, 1.521301e+000, 3.989756e-001, -1.794977e+000, -1.190586e+000, 3.928989e-001, 1.946953e+000, -1.874118e+000, -3.292602e-002, 2.983309e-002, 6.737092e-001, 7.322706e-001, // albedo 0, turbidity 10 -8.896186e+000, -3.278330e+000, -7.998349e+000, 8.023312e+000, -1.357555e-002, 1.947910e-001, -5.390226e-006, 1.798414e+000, 7.881395e-001, -8.040403e+000, -2.528514e+000, 3.774303e+000, -3.590457e+000, -3.551313e-002, 3.650761e-001, -4.401382e-004, 1.701545e+000, -6.992899e-003, -4.150010e-001, -3.539507e+000, -1.527733e+000, 1.415242e+000, -1.831476e-001, -3.009746e-001, 1.211955e-002, 2.365976e+000, 9.928240e-001, -2.090923e+000, 1.673638e-001, -2.183495e-001, -8.374584e-001, 2.774184e-002, 7.912769e-001, -6.650609e-002, 1.154446e+000, 7.863979e-001, 5.115239e-001, 2.415831e-001, 4.022318e-001, 2.292950e+000, -4.061496e+000, 7.453182e-002, 1.902451e-001, 1.587339e+000, 5.207620e-001, -2.334879e+000, -1.642495e+000, 2.384458e-001, 3.068363e+000, -1.699588e+000, -3.936924e-001, 3.028660e-002, 4.715374e-001, 7.091893e-001, // albedo 1, turbidity 1 -2.375941e+000, -1.508643e+000, -5.070151e+000, 5.509378e+000, -2.915769e-002, 2.122471e-001, 8.584007e-005, 1.517285e+000, 5.163253e-001, -2.605398e+000, -1.589160e+000, -1.137560e+000, 1.827729e+000, -4.939637e-002, 3.243952e-001, -6.464612e-004, 1.008816e+000, 4.568463e-001, -2.176260e+000, -1.601522e+000, 7.060324e-001, -1.060717e+000, -5.144614e-002, -1.938031e-001, 3.449257e-003, 2.641594e+000, 5.976852e-001, -7.365744e-001, -3.720296e-001, 7.315328e-001, 3.156067e-001, -2.739385e-001, 8.252942e-001, -1.055013e-002, 7.327610e-002, 3.218251e-001, -1.017537e+000, -4.631811e-001, 1.093174e+000, -7.215941e-002, 5.408457e-001, -1.848322e-002, 1.942990e-002, 6.882763e-001, 7.268524e-001, -1.025215e+000, -3.712574e-001, 9.661278e-001, 7.791398e-003, -4.508617e+000, 4.371074e-001, -1.241898e-006, 1.152655e+000, 5.008240e-001, // albedo 1, turbidity 2 -2.621793e+000, -1.611544e+000, -4.494730e+000, 4.902741e+000, -2.935751e-002, 1.930048e-001, 1.821579e-005, 1.522018e+000, 6.563013e-001, -2.473330e+000, -1.495083e+000, -5.536781e-001, 1.305457e+000, -7.261347e-002, 2.967738e-001, -2.858526e-004, 1.132650e+000, 1.737068e-001, -2.843519e+000, -1.913751e+000, 2.006296e-001, -8.580922e-001, -5.273753e-002, -7.800250e-002, 2.395781e-003, 2.505017e+000, 9.023934e-001, -1.805184e-001, -3.670063e-002, 7.583717e-001, 7.594739e-001, -2.092951e-001, 6.278666e-001, -8.086828e-003, 4.136002e-001, 6.026937e-001, -1.274753e+000, -5.831501e-001, 9.711756e-001, -6.209175e-001, 1.488633e-001, 2.117108e-001, 1.531499e-002, 9.306008e-001, 7.201852e-001, -9.224434e-001, -3.344822e-001, 9.964647e-001, 3.991735e-001, -4.951439e+000, 4.332347e-001, -1.082832e-005, 9.570977e-001, 5.221054e-001, // albedo 1, turbidity 3 -2.648100e+000, -1.587720e+000, -3.738681e+000, 4.084015e+000, -3.301163e-002, 1.736140e-001, -5.598265e-006, 1.628176e+000, 8.967917e-001, -3.004556e+000, -1.702983e+000, 1.060112e-001, 5.816666e-001, -8.140777e-002, 3.584557e-001, -7.793874e-005, 1.090228e+000, -1.079451e-001, -2.337937e+000, -1.584523e+000, -2.912486e-001, -4.467895e-001, -9.195281e-002, -2.355753e-001, 1.887118e-003, 3.053238e+000, 1.043382e+000, -5.985994e-001, -2.846782e-001, 8.903642e-001, 5.578845e-001, -2.510042e-001, 8.033778e-001, -9.920460e-003, 7.388584e-002, 7.097127e-001, -1.155357e+000, -4.638306e-001, 8.041892e-001, -4.051351e-001, -2.819435e-001, 8.505708e-002, 2.749222e-002, 1.334820e+000, 5.216620e-001, -1.010658e+000, -3.816787e-001, 9.644918e-001, 2.144477e-001, -5.005667e+000, 5.475125e-001, 3.758162e-005, 1.033427e+000, 6.866266e-001, // albedo 1, turbidity 4 -2.686681e+000, -1.694114e+000, -4.346908e+000, 4.745876e+000, -2.879846e-002, 2.237339e-001, -6.438656e-006, 1.456353e+000, 9.000340e-001, -2.684912e+000, -1.616888e+000, 2.447798e+000, -1.626883e+000, -7.346183e-002, 2.641722e-001, -1.001518e-004, 1.045501e+000, -2.314856e-001, -2.587652e+000, -1.999748e+000, -1.325810e+000, 7.561102e-001, -4.182131e-001, -4.285017e-002, 2.719759e-003, 2.420598e+000, 1.281981e+000, -2.679506e-001, 5.139740e-002, 1.276587e+000, -2.286956e-001, 7.388924e-001, 5.606395e-001, -1.472508e-002, 5.105614e-001, 7.670396e-001, -1.267160e+000, -7.441021e-001, 9.154665e-001, 8.190436e-001, -6.805266e+000, 1.013064e-001, 4.140297e-002, 3.378301e-001, 3.128860e-001, -9.570978e-001, -3.478847e-001, 9.709923e-001, -3.444499e-003, -4.677921e+000, 3.551546e-001, 6.241534e-003, 1.052060e+000, 7.543152e-001, // albedo 1, turbidity 5 -3.093830e+000, -1.859478e+000, -4.003711e+000, 4.391665e+000, -3.051581e-002, 2.180265e-001, -7.401285e-006, 1.448366e+000, 9.000549e-001, -3.121106e+000, -1.664385e+000, 2.868256e+000, -2.280292e+000, -8.456847e-002, 2.227469e-001, -1.681252e-004, 1.176332e+000, -2.605895e-001, -2.166025e+000, -2.172663e+000, -1.705862e+000, 1.960864e+000, -2.185020e-001, 1.891067e-002, 4.423413e-003, 2.071931e+000, 1.297661e+000, -5.263078e-001, 2.296403e-001, 1.342025e+000, -2.034590e+000, -1.024013e+000, 4.873264e-001, -1.982506e-002, 9.818474e-001, 1.040041e+000, -1.138361e+000, -8.186096e-001, 8.845700e-001, 3.291911e+000, -5.915866e+000, 1.125846e-001, 4.477952e-002, 9.195132e-002, -1.138939e-002, -1.013651e+000, -3.811416e-001, 9.420266e-001, -3.599378e-003, -4.895655e+000, 2.864445e-001, 1.940262e-002, 1.026648e+000, 7.421204e-001, // albedo 1, turbidity 6 -2.379373e+000, -1.540348e+000, -1.318467e+000, 1.724703e+000, -1.017147e-001, 1.811106e-001, -3.047951e-006, 1.598808e+000, 5.796580e-001, -3.200327e+000, -2.016985e+000, 9.935187e-001, -9.970906e-001, -2.159523e-001, 3.183812e-001, 1.575987e-002, 1.180131e+000, 2.839510e-001, -1.107956e+000, -1.330969e+000, -1.627216e-001, 2.985435e+000, -2.198633e-002, -4.401148e-001, -5.433064e-002, 1.701087e+000, 8.289746e-001, -9.423359e-001, 4.619106e-002, 3.116348e-002, -6.353122e+000, -6.192769e+000, 1.175886e+000, 1.020452e-001, 2.180417e+000, 7.076018e-001, -1.037343e+000, -5.711080e-001, 1.282899e+000, 8.808032e+000, -8.741903e-001, -6.097972e-001, -5.996612e-002, 1.533313e-001, 5.842877e-001, -1.002208e+000, -3.271512e-001, 7.288675e-001, 7.950560e-001, -5.029931e+000, 4.493639e-001, 2.389923e-002, 1.568465e+000, 5.653910e-001, // albedo 1, turbidity 7 -3.584221e+000, -2.140498e+000, -5.324613e+000, 5.753381e+000, -2.662581e-002, 2.099272e-001, -6.879519e-006, 1.362229e+000, 9.000467e-001, -3.579609e+000, -1.804420e+000, 3.448490e+000, -2.929179e+000, -6.009529e-002, 2.821561e-001, -6.203809e-004, 1.312035e+000, -3.013934e-001, -2.053811e+000, -2.420850e+000, -1.795999e+000, 1.835004e+000, -3.451800e-001, -1.042135e-001, 1.511574e-002, 1.751304e+000, 1.491704e+000, -2.602659e-001, 5.963320e-001, 1.059632e+000, -1.214076e+000, 6.424455e-001, 6.890202e-001, -6.544341e-002, 1.457883e+000, 5.321707e-001, -1.266632e+000, -8.504227e-001, 8.680693e-001, 1.899473e+000, -8.680238e+000, -1.798563e-001, 1.477665e-001, 2.430031e-001, 4.229871e-001, -1.021321e+000, -5.129049e-001, 9.006232e-001, 1.534018e+000, -3.672948e+000, 2.301115e-001, 5.151145e-003, 7.460819e-001, 5.418252e-001, // albedo 1, turbidity 8 -4.095186e+000, -2.274183e+000, -4.115160e+000, 4.514741e+000, -3.131440e-002, 1.475658e-001, -5.329133e-006, 1.411833e+000, 8.893477e-001, -3.691554e+000, -1.654418e+000, 3.158573e+000, -2.961366e+000, -7.834161e-002, 3.035141e-001, -4.241191e-004, 1.485200e+000, -1.689443e-001, -2.697067e+000, -3.473351e+000, -1.707297e+000, 3.138823e+000, -8.323430e-002, -1.605972e-001, 1.025052e-002, 1.132282e+000, 1.093318e+000, 7.049827e-001, 1.769870e+000, 8.659868e-001, -4.445404e+000, -2.256134e+000, 7.768538e-001, -4.741793e-002, 2.212406e+000, 1.109562e+000, -1.771411e+000, -1.358270e+000, 7.604506e-001, 7.191590e+000, -4.358366e+000, -3.375251e-001, 1.136852e-001, 1.844576e-001, -1.208189e-003, -9.623648e-001, -5.518470e-001, 9.623684e-001, -5.697517e-003, -5.015884e+000, 2.811964e-001, 2.100168e-002, 4.434131e-001, 7.212648e-001, // albedo 1, turbidity 9 -5.131552e+000, -2.558716e+000, -8.066753e+000, 8.403192e+000, -1.450692e-002, 1.494495e-001, -2.898774e-006, 1.427512e+000, 5.020826e-001, -6.192910e+000, -2.261479e+000, 5.059205e+000, -4.892079e+000, -2.703716e-002, 3.381259e-001, 2.231257e-002, 1.490697e+000, 5.441761e-001, -6.741018e-001, -3.356237e+000, -2.207329e+000, 3.300094e+000, -1.801120e-001, -2.560242e-001, -6.216731e-002, 1.180699e+000, 2.241782e-001, -8.312435e-001, 1.325391e+000, 5.324159e-001, -2.912438e+000, -8.384977e-002, 7.600872e-001, 7.749519e-002, 2.129188e+000, 1.328287e+000, -7.455272e-001, -8.504579e-001, 9.021474e-001, 3.426594e+000, -4.607412e+000, -1.706127e-001, 4.792024e-002, 2.354077e-001, 2.718195e-001, -1.448374e+000, -9.739004e-001, 8.801628e-001, 1.705262e+000, -2.420298e+000, -1.077392e-002, 2.691713e-002, 1.854876e-001, 7.097466e-001, // albedo 1, turbidity 10 -8.672396e+000, -3.339107e+000, -7.666257e+000, 7.916291e+000, -1.396976e-002, 1.676538e-001, -5.816416e-006, 1.448247e+000, 8.178892e-001, -7.852799e+000, -2.606120e+000, 4.231840e+000, -3.774406e+000, -3.540722e-002, 2.178494e-001, 6.198617e-005, 1.295236e+000, 1.130678e-001, -1.374103e-001, -3.570476e+000, -1.588768e+000, 1.538806e+000, -1.923629e-001, -1.793545e-002, 3.373950e-003, 2.008581e+000, 6.041668e-001, -2.211224e+000, 1.190704e-001, 6.700025e-002, -8.972445e-001, 2.133056e-001, 4.471730e-001, -3.148150e-002, 9.759721e-001, 1.166537e+000, 5.932825e-001, 2.482606e-001, 9.239617e-001, 2.382787e+000, -4.611846e+000, 1.608983e-001, 1.385590e-001, 7.641781e-001, 3.076032e-001, -2.098394e+000, -1.561705e+000, 7.602298e-001, 1.783879e+000, -1.486238e+000, -4.025919e-001, 2.965074e-002, -8.717180e-002, 7.279518e-001, }; static float datasetRad360[] = { // albedo 0, turbidity 1 2.494129e-003, 3.556297e-003, 2.965923e-004, 2.713084e-003, 1.335823e-001, 8.293879e-002, // albedo 0, turbidity 2 2.473622e-003, 3.518055e-003, 4.432438e-004, 1.754027e-003, 1.352516e-001, 8.253805e-002, // albedo 0, turbidity 3 2.485307e-003, 3.507686e-003, 4.235269e-004, 1.120748e-003, 1.360769e-001, 8.328522e-002, // albedo 0, turbidity 4 2.421491e-003, 3.278595e-003, 1.395344e-003, -1.953245e-003, 1.392978e-001, 8.376885e-002, // albedo 0, turbidity 5 2.403587e-003, 3.114517e-003, 2.224702e-003, -5.305220e-003, 1.435766e-001, 8.315234e-002, // albedo 0, turbidity 6 2.351950e-003, 2.915308e-003, 3.179213e-003, -8.297787e-003, 1.471589e-001, 8.200387e-002, // albedo 0, turbidity 7 2.347797e-003, 2.761449e-003, 3.671854e-003, -1.012039e-002, 1.480091e-001, 8.399335e-002, // albedo 0, turbidity 8 2.296250e-003, 2.420416e-003, 5.106803e-003, -1.515460e-002, 1.526421e-001, 8.454641e-002, // albedo 0, turbidity 9 2.193368e-003, 1.826966e-003, 7.606333e-003, -2.312584e-002, 1.588488e-001, 8.547295e-002, // albedo 0, turbidity 10 2.037533e-003, 9.415569e-004, 1.104382e-002, -3.348390e-002, 1.637893e-001, 8.792408e-002, // albedo 1, turbidity 1 3.061048e-003, 2.126839e-003, 1.132767e-002, -2.788848e-002, 1.948610e-001, 1.618476e-001, // albedo 1, turbidity 2 3.047180e-003, 2.153513e-003, 1.116935e-002, -2.810228e-002, 1.949994e-001, 1.614103e-001, // albedo 1, turbidity 3 3.038920e-003, 2.051613e-003, 1.130934e-002, -2.861029e-002, 1.941964e-001, 1.617911e-001, // albedo 1, turbidity 4 2.963024e-003, 1.869150e-003, 1.189063e-002, -3.088695e-002, 1.962576e-001, 1.593205e-001, // albedo 1, turbidity 5 2.918936e-003, 1.726267e-003, 1.250792e-002, -3.337994e-002, 1.973927e-001, 1.577752e-001, // albedo 1, turbidity 6 2.855489e-003, 1.647214e-003, 1.256484e-002, -3.387525e-002, 1.965371e-001, 1.571482e-001, // albedo 1, turbidity 7 2.825443e-003, 1.406555e-003, 1.336433e-002, -3.675617e-002, 1.982073e-001, 1.535780e-001, // albedo 1, turbidity 8 2.678428e-003, 1.109106e-003, 1.431453e-002, -4.011878e-002, 1.979278e-001, 1.510186e-001, // albedo 1, turbidity 9 2.555750e-003, 6.244779e-004, 1.562522e-002, -4.466841e-002, 1.968517e-001, 1.462399e-001, // albedo 1, turbidity 10 2.323920e-003, 1.300657e-004, 1.663828e-002, -4.826021e-002, 1.889056e-001, 1.427310e-001, }; static float dataset400[] = { // albedo 0, turbidity 1 -1.869600e+000, -9.575785e-001, -6.993871e+000, 7.306207e+000, -3.240320e-002, 3.834949e-001, 4.369976e-005, 2.254773e+000, 5.025988e-001, -1.746138e+000, -1.001117e+000, -1.758295e+000, 2.492931e+000, -6.202861e-002, 4.442043e-001, -3.779550e-004, 1.411622e+000, 4.890101e-001, -1.536453e+000, -5.330479e-001, 1.126830e+000, -2.452367e+000, -6.694842e-002, -2.983825e-002, 2.320196e-003, 5.488905e+000, 5.403856e-001, -1.069780e+000, -5.815078e-001, 8.612956e-001, 1.301347e+000, -4.089489e-001, 1.269432e+000, -9.018004e-003, -2.283572e+000, 3.760374e-001, -1.060384e+000, -2.207518e-001, 6.362691e-001, -5.757237e-001, 4.275177e-001, 8.443714e-002, 2.082596e-002, 3.125040e+000, 7.891611e-001, -1.077246e+000, -2.993040e-001, 8.167430e-001, 2.203982e-001, -3.984213e+000, 1.123699e+000, 1.313138e-002, 1.750491e+000, 4.999653e-001, // albedo 0, turbidity 2 -1.752499e+000, -9.053927e-001, -1.080943e+001, 1.110516e+001, -2.092090e-002, 3.348109e-001, -8.432141e-006, 2.326824e+000, 9.000500e-001, -1.888565e+000, -1.067725e+000, 1.491851e+000, -7.934014e-001, -4.853718e-002, 5.346693e-001, 9.170370e-005, 1.397595e+000, -3.635730e-001, -1.471013e+000, -5.497976e-001, -4.310423e-001, -8.787275e-001, -9.206447e-002, -1.490862e-001, -4.078054e-005, 5.442983e+000, 1.757010e+000, -1.061905e+000, -5.429222e-001, 1.412232e+000, 8.460977e-001, -2.973654e-001, 1.357299e+000, -5.347332e-003, -2.444304e+000, -3.363016e-002, -1.071200e+000, -2.263246e-001, 3.639469e-001, -6.109244e-001, -2.484665e-001, -7.097027e-002, 4.735641e-002, 3.445733e+000, 8.486491e-001, -1.081645e+000, -3.128264e-001, 8.436471e-001, 3.884148e-001, -5.004662e+000, 1.137000e+000, 1.500838e-002, 1.585647e+000, 5.832608e-001, // albedo 0, turbidity 3 -1.774187e+000, -9.327599e-001, -9.130103e+000, 9.413272e+000, -2.448089e-002, 3.487996e-001, -3.033497e-006, 2.291071e+000, 6.408360e-001, -1.849342e+000, -1.038735e+000, 2.863013e+000, -2.260302e+000, -5.040252e-002, 4.583723e-001, 1.008690e-002, 1.502617e+000, 7.223351e-002, -1.624679e+000, -7.257060e-001, -1.493033e+000, 5.658415e-001, -2.079847e-001, -4.651180e-002, -3.701743e-002, 4.858534e+000, 1.342775e+000, -8.692395e-001, -3.025565e-001, 1.630221e+000, -4.624355e-002, 8.408669e-002, 1.091981e+000, 6.506253e-002, -1.403006e+000, 2.076066e-001, -1.169258e+000, -3.711802e-001, 3.440155e-001, -1.044556e-001, -3.304858e+000, 1.185883e-001, 1.489352e-002, 2.642598e+000, 8.151882e-001, -1.058391e+000, -2.657785e-001, 6.984363e-001, 9.737578e-002, -1.903943e+000, 8.963329e-001, 6.480860e-002, 2.034024e+000, 5.870424e-001, // albedo 0, turbidity 4 -1.898858e+000, -1.031814e+000, -9.726056e+000, 1.000989e+001, -2.125268e-002, 3.569897e-001, -2.706653e-006, 2.147646e+000, 5.982401e-001, -2.136007e+000, -1.206456e+000, 3.801172e+000, -3.254852e+000, -4.516490e-002, 4.001123e-001, 2.151890e-002, 1.481457e+000, 1.444904e-001, -1.355343e+000, -6.736369e-001, -2.052620e+000, 1.298239e+000, -1.986869e-001, 6.321488e-002, -6.792635e-002, 4.482593e+000, 1.322565e+000, -9.063816e-001, -1.873797e-001, 1.559544e+000, -2.631298e-001, 5.988684e-002, 9.375378e-001, 9.681349e-002, -6.480890e-001, 2.362949e-001, -1.170470e+000, -3.968082e-001, 2.266604e-001, -2.018118e-001, -3.768512e+000, 9.706445e-002, 6.046660e-002, 2.723200e+000, 7.968878e-001, -1.085813e+000, -3.519543e-001, 7.537557e-001, 3.003522e-001, -1.811803e+000, 7.945754e-001, 5.293207e-002, 1.335214e+000, 6.385980e-001, // albedo 0, turbidity 5 -1.743240e+000, -9.391727e-001, -8.905876e+000, 9.139326e+000, -2.333803e-002, 3.093783e-001, -2.051734e-006, 2.320564e+000, 5.474845e-001, -2.624196e+000, -1.516703e+000, 5.053093e+000, -4.599198e+000, -4.248730e-002, 4.820250e-001, 1.829762e-002, 1.216991e+000, 2.739806e-001, -1.040612e+000, -6.103044e-001, -3.190021e+000, 3.216574e+000, -3.285978e-001, -1.982489e-001, -5.367025e-002, 3.984414e+000, 1.158312e+000, -9.537244e-001, -6.895800e-003, 1.788307e+000, -2.659655e+000, 6.473584e-001, 1.333544e+000, 5.529579e-002, 8.049825e-001, 4.930209e-001, -1.163791e+000, -5.095388e-001, 1.215079e-001, 3.427998e+000, -9.243257e+000, -5.059496e-001, 1.412681e-001, 1.829389e+000, 5.544610e-001, -1.118058e+000, -3.706501e-001, 6.885180e-001, -1.596776e-003, -3.279613e+000, 1.068229e+000, 3.010797e-002, 1.479756e+000, 7.483765e-001, // albedo 0, turbidity 6 -1.811701e+000, -1.002650e+000, -9.194183e+000, 9.469966e+000, -2.224886e-002, 3.237441e-001, -2.632967e-006, 2.168879e+000, 5.952956e-001, -2.746180e+000, -1.592055e+000, 4.225172e+000, -3.929912e+000, -3.866297e-002, 3.982440e-001, 3.812089e-002, 1.390284e+000, 1.922369e-001, -9.558770e-001, -6.401790e-001, -2.117905e+000, 2.293799e+000, -2.226591e-001, 6.151477e-002, -1.223358e-001, 3.475975e+000, 1.124575e+000, -9.065351e-001, 1.443765e-001, 7.871576e-001, -1.631026e+000, 1.537369e-001, 8.353048e-001, 1.849704e-001, 1.650615e+000, 4.473559e-001, -1.180081e+000, -5.441674e-001, 3.963103e-001, 1.375519e+000, -4.882926e+000, -9.391794e-004, 6.455569e-002, 1.774670e+000, 6.989373e-001, -1.128755e+000, -3.892532e-001, 5.327884e-001, 1.825253e+000, -2.335719e+000, 5.863162e-001, 5.535626e-002, 1.452293e+000, 6.920090e-001, // albedo 0, turbidity 7 -2.042064e+000, -1.144943e+000, -5.152625e+000, 5.384535e+000, -3.519943e-002, 3.025845e-001, -2.994849e-006, 2.113418e+000, 6.000255e-001, -2.700541e+000, -1.485611e+000, 2.159154e+000, -2.188608e+000, -5.879735e-002, 3.921779e-001, 5.020849e-002, 1.869923e+000, 2.118398e-001, -1.187417e+000, -1.102630e+000, -9.404690e-001, 2.427532e+000, -2.948903e-001, -3.437257e-002, -1.636446e-001, 1.894926e+000, 1.001327e+000, -5.639857e-001, 7.170770e-001, -1.146502e-001, -3.487513e+000, -7.711076e-001, 1.046031e+000, 2.606854e-001, 3.873520e+000, 5.637980e-001, -1.363103e+000, -8.396317e-001, 5.750351e-001, 4.317766e+000, -2.364722e+000, -4.135433e-001, 2.669162e-002, 5.768700e-001, 6.649078e-001, -1.102449e+000, -3.685043e-001, 4.622549e-001, -2.018634e-003, -3.947538e+000, 8.449276e-001, 8.837036e-002, 1.601304e+000, 7.026980e-001, // albedo 0, turbidity 8 -2.314053e+000, -1.314766e+000, -7.125646e+000, 7.357344e+000, -2.585710e-002, 2.863908e-001, -2.425744e-006, 2.039404e+000, 5.594003e-001, -2.630411e+000, -1.404258e+000, 3.675058e+000, -3.804226e+000, -4.249037e-002, 3.486414e-001, 5.675141e-002, 1.944935e+000, 2.880711e-001, -1.884599e+000, -1.657069e+000, -1.731916e+000, 3.034605e+000, -1.746846e-001, -1.559184e-002, -1.600465e-001, 1.915108e+000, 9.460232e-001, 6.351036e-002, 1.061776e+000, 1.195544e-002, -3.018584e+000, -5.618808e-001, 1.008146e+000, 2.013783e-001, 3.212273e+000, 6.523624e-001, -1.672505e+000, -9.752710e-001, 5.282860e-001, 3.776331e+000, -4.325128e+000, -4.384279e-001, 1.352387e-001, 8.847662e-001, 5.717158e-001, -1.007695e+000, -3.840375e-001, 3.463543e-001, 2.848366e+000, -2.105699e+000, 4.636429e-001, 2.800131e-002, 1.306056e+000, 7.618236e-001, // albedo 0, turbidity 9 -2.865406e+000, -1.637174e+000, -7.429613e+000, 7.592861e+000, -2.196505e-002, 2.800873e-001, -3.908530e-006, 1.962505e+000, 5.891464e-001, -3.196334e+000, -1.512711e+000, 3.947880e+000, -4.029796e+000, -3.699620e-002, 1.461452e-001, 5.921432e-002, 1.806132e+000, 2.331816e-001, -2.335492e+000, -2.353032e+000, -1.764665e+000, 2.841986e+000, -7.331326e-002, 4.537047e-001, -1.668000e-001, 2.156269e+000, 9.812486e-001, 3.278911e-001, 1.315177e+000, -1.438189e-001, -2.859630e+000, -8.436262e-001, 2.645711e-001, 2.154409e-001, 2.264493e+000, 5.975203e-001, -1.738015e+000, -1.091057e+000, 5.425696e-001, 4.650166e+000, -3.975190e+000, 2.066035e-001, 1.017332e-001, 9.321625e-001, 6.517783e-001, -1.006457e+000, -4.243112e-001, 1.934952e-001, 2.795030e+000, -1.680697e+000, -9.428375e-002, 7.158314e-002, 1.082383e+000, 7.234775e-001, // albedo 0, turbidity 10 -4.195701e+000, -2.171135e+000, -5.278016e+000, 5.393085e+000, -2.419182e-002, 2.050075e-001, -3.797795e-006, 1.853402e+000, 6.912927e-001, -4.119053e+000, -1.648023e+000, 2.332552e+000, -2.173813e+000, -6.442977e-002, 2.188945e-001, 3.548565e-002, 1.792598e+000, 4.162082e-002, -4.016823e+000, -3.599323e+000, -6.179057e-001, 6.454998e-001, -9.913704e-002, 2.770986e-001, -9.265471e-002, 2.227501e+000, 1.179216e+000, 1.066227e+000, 1.392783e+000, -9.653695e-001, -5.471637e-001, -8.500569e-001, 4.678476e-001, 8.760324e-002, 1.564314e+000, 4.885251e-001, -1.855594e+000, -1.029300e+000, 8.521013e-001, 3.975027e+000, -3.806819e+000, -2.044703e-002, 1.757298e-001, 7.790123e-001, 6.918921e-001, -1.014961e+000, -6.014045e-001, 1.926619e-002, 2.357335e+000, -1.312911e+000, -8.783609e-002, 7.739369e-002, 7.356770e-001, 7.042591e-001, // albedo 1, turbidity 1 -1.467874e+000, -7.636581e-001, -7.251111e+000, 7.726558e+000, -2.759341e-002, 3.527534e-001, 5.340629e-005, 2.007747e+000, 5.447487e-001, -1.863242e+000, -1.048209e+000, -1.580541e+000, 2.558030e+000, -5.622126e-002, 3.053960e-001, -4.657733e-004, 9.956390e-001, 3.409087e-001, -1.384101e+000, -5.553588e-001, 1.191974e+000, -2.157512e+000, -3.567589e-002, 1.020018e-001, 2.940191e-003, 4.555372e+000, 8.736043e-001, -9.828878e-001, -4.220161e-001, 1.184916e+000, 9.230716e-001, -4.062756e-001, 1.064980e+000, -1.060088e-002, -1.764815e+000, 2.932808e-001, -1.057001e+000, -2.727017e-001, 1.000018e+000, -3.108668e-001, 6.848382e-001, -1.682596e-001, 2.301218e-002, 2.075821e+000, 7.647327e-001, -1.058165e+000, -2.436130e-001, 1.074414e+000, 8.554434e-002, -3.846431e+000, 7.595465e-001, 9.729528e-006, 1.915942e+000, 4.999612e-001, // albedo 1, turbidity 2 -1.610179e+000, -8.336019e-001, -1.443356e+001, 1.492556e+001, -1.381931e-002, 2.902743e-001, -7.665717e-006, 1.981513e+000, 9.000423e-001, -2.004083e+000, -1.148388e+000, 3.747156e+000, -2.808560e+000, -3.298677e-002, 4.224754e-001, 4.166438e-004, 8.792110e-001, -2.321793e-001, -1.178554e+000, -5.064839e-001, -1.117126e+000, 2.815740e-001, -7.068438e-002, -3.031589e-002, -3.468069e-003, 4.539093e+000, 1.385612e+000, -1.091191e+000, -4.200919e-001, 1.826508e+000, 7.131992e-002, -1.883417e-001, 1.061437e+000, 1.311913e-002, -1.972550e+000, 2.511246e-001, -9.987232e-001, -2.073656e-001, 7.443384e-001, -7.245157e-002, -5.588818e-001, -1.364188e-001, 2.023795e-002, 2.829822e+000, 7.230021e-001, -1.075477e+000, -2.556973e-001, 1.051690e+000, 3.075960e-002, -1.895492e+000, 6.408333e-001, 2.109454e-002, 1.891240e+000, 5.652527e-001, // albedo 1, turbidity 3 -1.531711e+000, -8.266123e-001, -9.324763e+000, 9.811491e+000, -1.988560e-002, 3.404598e-001, -2.068369e-006, 1.869307e+000, 5.860842e-001, -2.113444e+000, -1.209106e+000, 3.526508e+000, -2.628730e+000, -4.634065e-002, 3.182739e-001, 9.500212e-003, 1.004871e+000, 2.109968e-001, -1.196720e+000, -5.485073e-001, -1.667136e+000, 9.920197e-001, -1.622954e-001, 6.951315e-002, -3.482877e-002, 4.214632e+000, 1.108967e+000, -1.003096e+000, -3.200944e-001, 2.042427e+000, -4.417822e-001, -1.404599e-001, 9.288535e-001, 6.077264e-002, -1.386737e+000, 4.557129e-001, -1.061048e+000, -2.908451e-001, 6.390633e-001, 1.406786e-001, -1.834706e+000, -1.432145e-001, 1.914080e-002, 2.284516e+000, 5.965839e-001, -1.054623e+000, -2.267971e-001, 1.028491e+000, -3.197518e-003, -1.705329e+000, 6.747358e-001, 2.072713e-002, 2.140509e+000, 7.205824e-001, // albedo 1, turbidity 4 -1.610001e+000, -8.622601e-001, -1.060181e+001, 1.106133e+001, -1.648296e-002, 2.590559e-001, -1.904522e-006, 1.930415e+000, 6.006964e-001, -2.308577e+000, -1.440194e+000, 2.937335e+000, -2.093599e+000, -3.430217e-002, 3.427774e-001, 2.590705e-002, 5.673750e-001, 1.250422e-001, -9.441254e-001, -3.064812e-001, -8.895068e-001, 2.815271e-001, -8.036228e-002, 1.867017e-001, -7.809247e-002, 4.774631e+000, 1.391904e+000, -1.214397e+000, -5.423074e-001, 1.361001e+000, 1.782273e-001, -3.648675e-001, 7.181838e-001, 1.135547e-001, -1.935982e+000, 1.820361e-001, -9.377631e-001, -1.533211e-001, 8.439993e-001, -3.893771e-001, -2.564779e-001, -6.742272e-002, 2.255856e-002, 2.780601e+000, 7.972008e-001, -1.101428e+000, -3.069552e-001, 9.687591e-001, 4.500576e-001, -4.912444e+000, 5.398387e-001, 3.638172e-002, 1.582999e+000, 6.425950e-001, // albedo 1, turbidity 5 -1.687541e+000, -9.378170e-001, -8.475686e+000, 8.929279e+000, -2.132746e-002, 2.917650e-001, -2.177239e-006, 1.863407e+000, 5.908179e-001, -2.278432e+000, -1.387936e+000, 5.425292e+000, -4.725025e+000, -3.892912e-002, 4.084727e-001, 1.842665e-002, 8.461986e-001, 1.673366e-001, -1.302702e+000, -7.200083e-001, -3.084331e+000, 3.191487e+000, -3.222828e-001, -1.493849e-001, -5.641672e-002, 3.624218e+000, 1.256086e+000, -7.886965e-001, -3.966453e-002, 2.110076e+000, -2.232935e+000, 7.269719e-001, 1.163410e+000, 7.133744e-002, -1.660119e-001, 4.329084e-001, -1.157760e+000, -4.084596e-001, 5.689088e-001, 2.379590e+000, -9.687743e+000, -5.598487e-001, 9.191895e-002, 1.923047e+000, 5.802927e-001, -1.047250e+000, -2.873072e-001, 1.046858e+000, 6.890046e-001, -2.947892e+000, 7.245997e-001, 1.125227e-002, 1.352625e+000, 7.193979e-001, // albedo 1, turbidity 6 -1.643764e+000, -9.086683e-001, -8.750078e+000, 9.165653e+000, -2.025728e-002, 2.737848e-001, -2.240987e-006, 1.943471e+000, 5.731722e-001, -2.473069e+000, -1.505194e+000, 5.448737e+000, -4.863726e+000, -3.662439e-002, 1.938729e-001, 4.741355e-002, 8.586572e-001, 2.284408e-001, -1.232599e+000, -7.896777e-001, -3.056911e+000, 3.546334e+000, -1.948820e-001, 3.344216e-001, -1.376967e-001, 3.029469e+000, 1.120573e+000, -6.095289e-001, 2.745468e-001, 1.809782e+000, -2.593032e+000, -1.710009e-002, 5.537278e-001, 1.935506e-001, 1.259882e+000, 4.970103e-001, -1.324655e+000, -6.255071e-001, 6.240868e-001, 2.021182e+000, -5.876050e+000, -1.507819e-001, 3.301250e-002, 1.142019e+000, 5.986671e-001, -9.888131e-001, -2.584852e-001, 1.052160e+000, 7.264224e-001, -2.563426e+000, 5.494058e-001, 1.821983e-002, 1.277896e+000, 7.557967e-001, // albedo 1, turbidity 7 -2.100689e+000, -1.204431e+000, -7.573121e+000, 8.039632e+000, -2.300526e-002, 2.839214e-001, -2.346958e-006, 1.678847e+000, 5.536303e-001, -2.610610e+000, -1.587799e+000, 5.460928e+000, -5.158708e+000, -4.505650e-002, 3.876929e-001, 3.852459e-002, 1.172854e+000, 3.104745e-001, -8.340903e-001, -7.487965e-001, -3.154774e+000, 4.600448e+000, -1.818975e-001, -1.871764e-001, -1.222094e-001, 2.067197e+000, 8.802127e-001, -9.180308e-001, 3.752197e-001, 1.471125e+000, -4.691789e+000, -5.128294e-001, 1.164707e+000, 1.831224e-001, 2.900937e+000, 7.718397e-001, -1.126819e+000, -6.652330e-001, 7.386065e-001, 5.362044e+000, -6.196453e+000, -7.280092e-001, 6.312604e-002, 2.874666e-001, 4.225580e-001, -1.091610e+000, -3.433417e-001, 1.042206e+000, 1.075776e-001, -4.443940e+000, 7.469895e-001, 3.166247e-002, 1.019495e+000, 7.523771e-001, // albedo 1, turbidity 8 -2.234623e+000, -1.310221e+000, -8.525764e+000, 8.932373e+000, -1.814945e-002, 2.615153e-001, -2.992344e-006, 1.672403e+000, 5.897681e-001, -2.566352e+000, -1.472664e+000, 5.894182e+000, -5.619094e+000, -3.204346e-002, 2.993298e-001, 4.281047e-002, 1.303481e+000, 2.453403e-001, -1.577477e+000, -1.491725e+000, -3.065840e+000, 4.446634e+000, -1.689128e-001, 9.559287e-002, -1.384724e-001, 1.778589e+000, 9.159045e-001, -2.747774e-001, 8.787060e-001, 1.071723e+000, -4.169230e+000, -3.029966e-001, 6.326611e-001, 2.145395e-001, 2.611218e+000, 7.082708e-001, -1.433045e+000, -8.939972e-001, 8.538090e-001, 4.481475e+000, -5.978961e+000, -1.608369e-001, 5.335732e-002, 3.510751e-001, 5.421327e-001, -9.961738e-001, -3.023960e-001, 9.152994e-001, 2.936173e+000, -2.311060e+000, 1.216642e-001, 2.844950e-002, 9.492671e-001, 6.929460e-001, // albedo 1, turbidity 9 -2.428587e+000, -1.538689e+000, -9.076712e+000, 9.464050e+000, -1.503392e-002, 2.373401e-001, -2.770103e-006, 1.537508e+000, 5.959289e-001, -3.240872e+000, -1.646067e+000, 6.091797e+000, -5.738481e+000, -3.098072e-002, 2.698026e-001, 3.864212e-002, 1.286514e+000, 2.461153e-001, -1.970987e+000, -2.124015e+000, -2.894000e+000, 3.858260e+000, -1.449222e-001, 1.903898e-001, -1.194017e-001, 1.882566e+000, 8.764452e-001, 3.562238e-002, 1.092427e+000, 6.291668e-001, -3.337396e+000, -2.817141e-001, 4.799828e-001, 1.674350e-001, 1.943489e+000, 7.728749e-001, -1.501790e+000, -9.408520e-001, 1.000954e+000, 4.599103e+000, -5.295662e+000, -1.111397e-001, 1.040124e-001, 3.185557e-001, 4.959400e-001, -9.859417e-001, -3.827367e-001, 8.040930e-001, 2.980678e+000, -2.015582e+000, -8.947514e-003, 1.696367e-002, 6.489501e-001, 7.555598e-001, // albedo 1, turbidity 10 -3.758956e+000, -2.159015e+000, -7.207163e+000, 7.516659e+000, -1.643521e-002, 2.465725e-001, -4.045068e-006, 1.471688e+000, 6.687943e-001, -4.635664e+000, -1.766046e+000, 4.282669e+000, -4.058908e+000, -2.908998e-002, 1.202684e-001, 3.167305e-002, 1.450927e+000, 8.171815e-002, -3.458011e+000, -3.657280e+000, -1.484743e+000, 2.264533e+000, -1.033120e-001, 4.282323e-001, -8.387881e-002, 1.687334e+000, 1.130604e+000, 9.673527e-001, 1.500425e+000, -3.604932e-001, -2.050346e+000, -3.778381e-001, 2.416298e-001, 8.439313e-002, 1.458583e+000, 5.816071e-001, -1.808078e+000, -1.089975e+000, 1.291838e+000, 5.144631e+000, -5.047822e+000, 4.301183e-002, 1.426941e-001, 1.187472e-001, 6.145551e-001, -8.399253e-001, -3.832885e-001, 6.306417e-001, 2.179775e+000, -1.492762e+000, -1.682763e-001, 4.109851e-002, 4.221724e-001, 7.086504e-001, }; static float datasetRad400[] = { // albedo 0, turbidity 1 5.767645e-003, 1.219302e-002, -2.188467e-002, 8.262275e-002, 1.719839e-001, 1.233791e-001, // albedo 0, turbidity 2 5.661981e-003, 1.258489e-002, -2.324339e-002, 8.372421e-002, 1.730981e-001, 1.255797e-001, // albedo 0, turbidity 3 5.644031e-003, 1.248986e-002, -2.287316e-002, 7.999388e-002, 1.815345e-001, 1.252983e-001, // albedo 0, turbidity 4 5.479152e-003, 1.215496e-002, -2.122586e-002, 7.189527e-002, 1.962517e-001, 1.245648e-001, // albedo 0, turbidity 5 5.385972e-003, 1.187505e-002, -2.025911e-002, 6.602510e-002, 2.067312e-001, 1.264910e-001, // albedo 0, turbidity 6 5.319970e-003, 1.160513e-002, -1.904232e-002, 6.030292e-002, 2.158311e-001, 1.261204e-001, // albedo 0, turbidity 7 5.179289e-003, 1.125842e-002, -1.708641e-002, 5.111365e-002, 2.285030e-001, 1.278260e-001, // albedo 0, turbidity 8 4.994685e-003, 1.025385e-002, -1.254777e-002, 3.429945e-002, 2.490310e-001, 1.302691e-001, // albedo 0, turbidity 9 4.759538e-003, 8.205142e-003, -3.246300e-003, 3.909938e-003, 2.819549e-001, 1.322430e-001, // albedo 0, turbidity 10 4.412341e-003, 4.910210e-003, 1.040886e-002, -3.627125e-002, 3.147182e-001, 1.409331e-001, // albedo 1, turbidity 1 7.016633e-003, 9.796846e-003, -9.823849e-004, 2.324224e-002, 3.035010e-001, 2.573850e-001, // albedo 1, turbidity 2 6.984411e-003, 9.584282e-003, -5.945671e-004, 2.061312e-002, 3.090019e-001, 2.547364e-001, // albedo 1, turbidity 3 6.865141e-003, 9.540856e-003, -3.311701e-004, 1.726495e-002, 3.147099e-001, 2.539552e-001, // albedo 1, turbidity 4 6.701191e-003, 9.352606e-003, 3.392916e-004, 1.159886e-002, 3.228446e-001, 2.530111e-001, // albedo 1, turbidity 5 6.513679e-003, 8.873317e-003, 2.339520e-003, 2.817964e-003, 3.341256e-001, 2.496316e-001, // albedo 1, turbidity 6 6.405833e-003, 8.466409e-003, 3.661909e-003, -3.045984e-003, 3.414328e-001, 2.464327e-001, // albedo 1, turbidity 7 6.220899e-003, 7.997469e-003, 5.957591e-003, -1.302863e-002, 3.523355e-001, 2.418785e-001, // albedo 1, turbidity 8 5.912801e-003, 6.826679e-003, 1.008544e-002, -2.771812e-002, 3.640405e-001, 2.386599e-001, // albedo 1, turbidity 9 5.550967e-003, 5.157051e-003, 1.661696e-002, -5.072656e-002, 3.807009e-001, 2.315489e-001, // albedo 1, turbidity 10 5.011118e-003, 2.636752e-003, 2.499879e-002, -7.576617e-002, 3.828189e-001, 2.328116e-001, }; static float dataset440[] = { // albedo 0, turbidity 1 -1.397312e+000, -5.327311e-001, -5.456059e+000, 5.777674e+000, -5.111575e-002, 4.730804e-001, 7.375500e-003, 3.032806e+000, 5.181890e-001, -1.561639e+000, -7.024946e-001, -2.140322e+000, 2.841761e+000, -8.846023e-002, 5.529005e-001, 6.219344e-003, 2.004212e+000, 3.701256e-001, -1.047473e+000, -1.152734e-001, 2.275873e+000, -3.020347e+000, -1.739218e-001, 2.250142e-001, -2.731776e-002, 6.659723e+000, 1.067495e+000, -1.298483e+000, -5.788209e-001, 4.906412e-001, 1.522576e+000, -5.650061e-001, 1.544707e+000, 4.638003e-002, -3.742019e+000, 2.485397e-001, -9.485899e-001, -7.383610e-002, 1.039247e+000, -4.744931e-001, -1.822357e-001, 2.284415e-001, -4.796962e-002, 4.363935e+000, 8.217971e-001, -1.099082e+000, -2.001688e-001, 7.365077e-001, 1.068489e-001, -5.005434e+000, 1.508145e+000, 8.181497e-002, 3.226865e+000, 4.999418e-001, // albedo 0, turbidity 2 -1.416143e+000, -5.515006e-001, -7.045898e+000, 7.448161e+000, -4.504075e-002, 5.055437e-001, -1.378949e-006, 2.955475e+000, 6.184716e-001, -1.698183e+000, -8.272914e-001, 9.984388e-001, -2.511235e-001, -9.262675e-002, 5.681534e-001, 5.377123e-003, 1.631048e+000, 1.137691e-001, -9.234085e-001, -2.165404e-002, 6.483039e-002, -8.535145e-001, -2.497457e-001, 1.695057e-001, -3.410225e-002, 6.726925e+000, 1.331197e+000, -1.265077e+000, -5.034231e-001, 1.196547e+000, 3.666463e-001, -3.960044e-001, 1.404008e+000, 1.129300e-001, -2.644439e+000, 1.103356e-001, -1.008210e+000, -1.455232e-001, 7.347739e-001, 2.462433e-002, -2.534587e+000, 3.088590e-001, -6.687136e-002, 3.786007e+000, 9.578369e-001, -1.076840e+000, -1.851501e-001, 7.341818e-001, -2.658571e-003, -5.001762e+000, 1.275390e+000, 1.277410e-001, 3.223315e+000, 5.147659e-001, // albedo 0, turbidity 3 -1.449526e+000, -5.738159e-001, -8.976383e+000, 9.275142e+000, -3.157845e-002, 5.011970e-001, -1.218363e-006, 3.001006e+000, 5.662190e-001, -1.748840e+000, -9.338946e-001, 5.557460e-002, 9.451626e-001, -6.929558e-002, 5.458365e-001, 5.505399e-003, 8.818793e-001, 2.135274e-001, -8.369988e-001, 1.127967e-001, 8.846958e-001, -2.467908e+000, -8.394011e-002, 1.684067e-001, -3.352743e-002, 7.957386e+000, 1.297777e+000, -1.284515e+000, -5.332365e-001, 5.511261e-001, 1.702784e+000, -6.616281e-001, 1.349449e+000, 1.269152e-001, -3.247373e+000, 2.115827e-001, -9.889637e-001, -9.962819e-002, 6.096776e-001, -8.472749e-001, 7.672924e-001, 7.425160e-002, 2.113714e-002, 4.990637e+000, 8.274585e-001, -1.093910e+000, -2.211349e-001, 6.959659e-001, 3.423174e-001, -5.004213e+000, 1.347201e+000, 1.198192e-001, 2.547517e+000, 6.329489e-001, // albedo 0, turbidity 4 -1.394462e+000, -5.287733e-001, -8.095187e+000, 8.076613e+000, -1.275227e-002, 1.916790e-001, 4.741296e-002, 3.145140e+000, 5.071760e-001, -2.234192e+000, -1.437079e+000, -5.734544e-001, 1.248687e+000, -4.136344e-002, 7.671749e-001, -1.273584e-002, 4.751894e-001, 4.116995e-001, -4.063889e-001, 4.920785e-001, 3.865520e-001, 2.254008e-001, -1.618861e-001, 1.950875e-001, -8.622479e-002, 3.836900e+000, 1.108189e+000, -1.366924e+000, -4.557853e-001, -6.731417e-001, -3.011452e-001, 2.413069e-001, 1.404821e+000, 1.920278e-001, 6.394529e+000, 4.219713e-001, -9.128947e-001, 1.980978e-002, 5.119874e-001, 8.027541e-002, -3.680159e+000, 6.597416e-001, 3.853339e-002, 3.969131e+000, 8.351942e-001, -1.162856e+000, -3.606511e-001, 7.055795e-001, -2.702137e-003, 4.777294e-001, -7.722331e-001, 3.446509e-001, 1.186834e+000, 5.118539e-001, // albedo 0, turbidity 5 -1.563353e+000, -6.916347e-001, -4.154766e+001, 4.181703e+001, -5.673370e-003, 4.344900e-001, 1.839829e-003, 2.669278e+000, 5.021266e-001, -1.948172e+000, -1.080669e+000, 1.082552e+001, -1.034262e+001, -1.196421e-002, 3.895739e-001, 5.621831e-002, 1.347130e+000, 4.561106e-001, -9.155219e-001, -1.456265e-001, -2.177275e+000, 2.079788e+000, -2.154465e-002, 7.743816e-001, -2.181642e-001, 4.897704e+000, 1.035464e+000, -1.010898e+000, -4.425431e-002, 3.067880e-001, -6.899235e-001, -1.891895e-001, 3.015686e-001, 4.236422e-001, 1.901582e+000, 3.916662e-001, -1.159005e+000, -4.048136e-001, 5.385745e-001, 3.423651e-001, 1.474365e-001, 3.516065e-001, 2.564260e-003, 1.815518e+000, 7.634079e-001, -1.081675e+000, -2.556981e-001, 6.544471e-001, 4.093649e-001, -3.215201e+000, 9.116400e-001, 1.406660e-001, 1.869407e+000, 6.968119e-001, // albedo 0, turbidity 6 -1.561484e+000, -7.153039e-001, -1.623772e+001, 1.650713e+001, -1.394913e-002, 4.467465e-001, 9.613464e-004, 2.564429e+000, 5.363746e-001, -2.308050e+000, -1.314851e+000, -1.484346e+000, 1.928705e+000, -2.164130e-002, 2.817711e-001, 7.177671e-002, 1.146387e+000, 3.025595e-001, -4.886429e-001, 8.279799e-002, 2.432876e+000, -2.276257e+000, -4.799742e-002, 9.362010e-001, -2.753669e-001, 4.784291e+000, 1.180593e+000, -1.306115e+000, -1.759650e-001, -1.392008e+000, 3.119302e-001, -2.268673e-001, 8.336951e-002, 5.250725e-001, 2.534962e+000, 2.800244e-001, -1.016608e+000, -3.429911e-001, 5.659470e-001, 9.044333e-001, 7.387499e-002, 4.267609e-001, -4.165623e-002, 1.452779e+000, 8.409560e-001, -1.127637e+000, -2.854231e-001, 4.933964e-001, -3.379287e-003, -1.181893e+000, 8.164171e-001, 1.910509e-001, 1.979338e+000, 6.658885e-001, // albedo 0, turbidity 7 -1.675310e+000, -8.020443e-001, -1.136130e+001, 1.159861e+001, -1.871156e-002, 4.151400e-001, -1.940992e-006, 2.486322e+000, 5.256426e-001, -2.071301e+000, -1.175325e+000, 1.789426e+000, -1.455233e+000, -2.855906e-002, 3.218745e-001, 7.776969e-002, 1.431615e+000, 3.478887e-001, -1.093503e+000, -4.120496e-001, -8.598647e-002, 4.564844e-001, -1.231980e-001, 7.992132e-001, -2.910745e-001, 3.881502e+000, 1.064658e+000, -7.736128e-001, 2.385498e-001, -7.867818e-001, -6.009723e-001, -1.808566e-001, -8.796429e-003, 5.412620e-001, 2.991552e+000, 4.008143e-001, -1.259083e+000, -5.300975e-001, 5.418031e-001, 1.150966e+000, -7.553821e-001, 5.991000e-001, -2.344718e-003, 1.097939e+000, 7.756612e-001, -1.094148e+000, -3.178958e-001, 4.126954e-001, 3.591106e-001, -1.415744e+000, 3.908399e-001, 1.806147e-001, 1.584959e+000, 6.862009e-001, // albedo 0, turbidity 8 -1.815485e+000, -9.306778e-001, -1.249527e+001, 1.271288e+001, -1.497209e-002, 3.576353e-001, -2.464284e-006, 2.326460e+000, 5.655414e-001, -2.225570e+000, -1.213627e+000, 6.082472e+000, -5.907562e+000, -2.446452e-002, 2.113558e-001, 7.708802e-002, 1.647556e+000, 2.416155e-001, -1.439532e+000, -8.666475e-001, -2.734807e+000, 3.355265e+000, -1.311068e-001, 1.048703e+000, -2.887025e-001, 3.419973e+000, 1.146322e+000, -5.599890e-001, 4.437236e-001, 1.582320e-001, -2.000110e+000, -2.859304e-001, -5.600631e-001, 5.382793e-001, 1.986387e+000, 3.455121e-001, -1.319304e+000, -6.466246e-001, 5.684685e-001, 2.050330e+000, -2.796053e+000, 1.001659e+000, -1.161356e-002, 9.737235e-001, 8.101246e-001, -1.097281e+000, -3.336023e-001, 1.781708e-001, 1.733079e+000, -1.378806e+000, -1.870394e-001, 1.997578e-001, 1.456148e+000, 6.791796e-001, // albedo 0, turbidity 9 -2.208666e+000, -1.219745e+000, -7.548669e+000, 7.680830e+000, -2.012473e-002, 3.627866e-001, -2.906182e-006, 2.147138e+000, 6.340095e-001, -1.967348e+000, -9.528057e-001, 4.171590e+000, -4.002838e+000, -5.074552e-002, 1.581866e-001, 5.920106e-002, 1.981564e+000, 1.023257e-001, -3.150304e+000, -2.193706e+000, -2.016165e+000, 2.374337e+000, -6.793058e-002, 9.623811e-001, -2.195022e-001, 2.736885e+000, 1.252161e+000, 4.737094e-001, 1.067875e+000, -1.003861e-001, -1.566752e+000, -1.217264e+000, -4.270598e-001, 3.968055e-001, 1.234108e+000, 3.105789e-001, -1.706975e+000, -9.607442e-001, 7.140098e-001, 3.981202e+000, -3.521433e+000, 6.308820e-001, 5.140937e-002, 7.435120e-001, 8.074305e-001, -1.012042e+000, -3.372525e-001, 2.589450e-002, 1.768224e+000, -1.059990e+000, -1.299077e-001, 1.790337e-001, 1.091012e+000, 6.873854e-001, // albedo 0, turbidity 10 -2.912541e+000, -1.677524e+000, -3.843452e+000, 3.954207e+000, -3.414327e-002, 2.945890e-001, -4.245832e-006, 1.934337e+000, 7.258748e-001, -1.567383e+000, -8.279686e-001, 1.690940e+000, -1.413268e+000, -1.216792e-001, 7.332798e-002, 4.862765e-002, 2.034766e+000, -5.041561e-002, -6.058613e+000, -3.509207e+000, -6.312870e-001, -4.558316e-002, 6.168891e-002, 8.153413e-001, -1.686845e-001, 2.670227e+000, 1.362906e+000, 1.347177e+000, 9.821888e-001, -9.242155e-001, 5.851576e-001, -1.897421e+000, -2.729487e-002, 2.866724e-001, 7.306238e-001, 2.792136e-001, -1.810783e+000, -1.027512e+000, 1.216071e+000, 5.270108e+000, -3.887149e+000, 6.193256e-002, 2.774610e-002, 1.484756e-001, 8.033249e-001, -9.801965e-001, -3.375841e-001, -3.004804e-001, 1.385754e+000, -6.834540e-001, 5.827734e-002, 2.268309e-001, 1.028696e+000, 6.797371e-001, // albedo 1, turbidity 1 -1.345260e+000, -5.085528e-001, -6.052009e+000, 6.604590e+000, -4.300752e-002, 4.745234e-001, 6.591457e-003, 2.595142e+000, 5.013653e-001, -1.573525e+000, -7.133524e-001, -1.671346e+000, 2.693205e+000, -7.828763e-002, 2.915699e-001, 1.795879e-002, 1.469445e+000, 4.927472e-001, -1.013665e+000, -1.731419e-001, 2.043423e+000, -2.919634e+000, -1.020807e-001, 5.467619e-001, -4.041481e-002, 5.853992e+000, 5.272064e-001, -1.173191e+000, -3.964683e-001, 1.097258e+000, 1.509973e+000, -5.675641e-001, 9.815927e-001, 6.962319e-002, -3.358210e+000, 4.263117e-001, -1.003507e+000, -1.124908e-001, 1.030642e+000, -5.357088e-001, 6.114201e-001, 1.628414e-001, -5.701497e-002, 4.541126e+000, 8.084996e-001, -1.071959e+000, -1.567262e-001, 9.923029e-001, 1.457160e-001, -4.742907e+000, 7.280970e-001, 6.770360e-002, 3.919300e+000, 4.999529e-001, // albedo 1, turbidity 2 -1.399982e+000, -5.538549e-001, -6.983148e+000, 7.513966e+000, -3.358417e-002, 3.667027e-001, 1.158837e-002, 2.499680e+000, 5.598537e-001, -1.602839e+000, -7.835806e-001, 1.200264e+000, -1.454290e-001, -7.431927e-002, 5.374263e-001, 9.505505e-004, 1.096167e+000, 2.185838e-001, -9.587294e-001, -6.134134e-002, 2.234030e-001, -8.115395e-001, -2.344054e-001, 2.018782e-001, -4.192332e-002, 6.331499e+000, 1.353587e+000, -1.166832e+000, -4.057833e-001, 1.461335e+000, 3.165401e-001, -3.245858e-001, 1.199323e+000, 1.100274e-001, -2.727373e+000, 5.329788e-002, -1.023178e+000, -1.351631e-001, 9.944251e-001, 2.103341e-002, -2.460318e+000, 5.136074e-003, -5.267951e-002, 4.097235e+000, 9.388837e-001, -1.071426e+000, -1.726491e-001, 1.048949e+000, -2.624840e-003, -4.993124e+000, 6.621513e-001, 7.801931e-002, 3.227750e+000, 5.363265e-001, // albedo 1, turbidity 3 -1.362723e+000, -5.257224e-001, -1.325130e+001, 1.374641e+001, -1.971887e-002, 4.480379e-001, -9.588735e-007, 2.679516e+000, 5.628531e-001, -1.824466e+000, -9.877790e-001, 4.631069e+000, -3.630521e+000, -4.340325e-002, 3.913450e-001, 3.415899e-002, 4.746800e-001, 2.022772e-001, -6.435267e-001, 1.629762e-001, -1.452097e+000, 8.028761e-001, -9.611017e-002, 4.267105e-001, -1.023573e-001, 6.652106e+000, 1.406057e+000, -1.400277e+000, -5.150235e-001, 1.752017e+000, -1.699743e-001, -3.411643e-001, 8.465596e-001, 2.127075e-001, -2.235971e+000, 4.728189e-002, -9.044866e-001, -7.979493e-002, 8.298122e-001, -5.604698e-002, -1.433761e+000, 1.011757e-001, -7.175544e-002, 4.243075e+000, 9.588179e-001, -1.115618e+000, -2.148000e-001, 1.109081e+000, 2.661209e-001, -5.008111e+000, 6.333048e-001, 9.274718e-002, 2.494529e+000, 5.890657e-001, // albedo 1, turbidity 4 -1.389611e+000, -5.579886e-001, -1.045229e+001, 1.092342e+001, -2.282772e-002, 4.054079e-001, 2.781558e-003, 2.578484e+000, 5.372706e-001, -1.893851e+000, -1.116122e+000, 2.111553e+000, -8.775468e-001, -5.640158e-002, 5.399894e-001, 1.929352e-002, -5.585557e-002, 2.870402e-001, -7.015617e-001, 1.884526e-001, -1.660273e-001, -8.785899e-001, -5.471987e-002, 1.787856e-001, -9.958870e-002, 7.207213e+000, 1.277933e+000, -1.279075e+000, -4.794032e-001, 9.037342e-001, 6.225399e-001, -6.592270e-001, 9.474313e-001, 2.524811e-001, -2.485658e+000, 2.050401e-001, -9.744212e-001, -9.899254e-002, 9.474600e-001, -2.536639e-001, 5.390432e-001, -8.465488e-002, -3.140532e-002, 4.512343e+000, 8.530654e-001, -1.093264e+000, -2.115594e-001, 9.876876e-001, 7.531309e-002, -5.003648e+000, 6.719560e-001, 1.111699e-001, 2.412349e+000, 6.482966e-001, // albedo 1, turbidity 5 -1.410458e+000, -5.905263e-001, -4.146328e+001, 4.190254e+001, -5.607421e-003, 4.437719e-001, -1.948391e-006, 2.496743e+000, 5.031933e-001, -1.817258e+000, -9.848495e-001, 1.089217e+001, -1.028029e+001, -1.221684e-002, 3.317008e-001, 5.060062e-002, 1.198443e+000, 4.449482e-001, -8.920534e-001, -8.835804e-002, -2.111594e+000, 2.083599e+000, -1.507800e-002, 6.993567e-001, -1.987686e-001, 4.793539e+000, 1.072586e+000, -1.048633e+000, -1.110825e-001, 5.438710e-001, -6.707296e-001, -1.825365e-001, 2.307221e-001, 4.056218e-001, 1.886912e+000, 3.579576e-001, -1.094223e+000, -3.084727e-001, 9.739595e-001, 3.972140e-001, 1.511647e-001, 2.788218e-001, -6.279180e-002, 1.866444e+000, 7.995203e-001, -1.078162e+000, -2.176197e-001, 1.088756e+000, 4.329413e-001, -3.209490e+000, 8.364785e-001, 7.689785e-002, 1.943182e+000, 7.150615e-001, // albedo 1, turbidity 6 -1.455846e+000, -6.322333e-001, -1.618289e+001, 1.656258e+001, -1.280603e-002, 4.130359e-001, -9.061644e-007, 2.461391e+000, 5.315915e-001, -2.222251e+000, -1.233356e+000, -1.454954e+000, 1.957432e+000, -1.730555e-002, 2.418496e-001, 7.240262e-002, 1.061939e+000, 3.148474e-001, -4.536196e-001, 1.457295e-001, 2.483934e+000, -2.244550e+000, -4.593767e-002, 8.967621e-001, -2.712877e-001, 4.732142e+000, 1.188839e+000, -1.277343e+000, -2.046024e-001, -1.229720e+000, 3.977256e-001, -2.209195e-001, 6.033235e-002, 5.267707e-001, 2.536445e+000, 2.759606e-001, -1.029833e+000, -2.979843e-001, 8.742883e-001, 1.037710e+000, 1.350257e-001, 4.066094e-001, -1.376375e-001, 1.500753e+000, 8.676699e-001, -1.095935e+000, -2.211775e-001, 9.320585e-001, 8.955212e-002, -1.113388e+000, 7.909911e-001, 1.393848e-001, 2.057146e+000, 6.699739e-001, // albedo 1, turbidity 7 -1.571831e+000, -7.466353e-001, -1.226063e+001, 1.265995e+001, -1.514083e-002, 3.639653e-001, -2.504287e-006, 2.204454e+000, 5.468861e-001, -2.235398e+000, -1.371434e+000, 1.787996e+000, -1.073965e+000, -2.503530e-002, 2.143584e-001, 7.703453e-002, 5.207181e-001, 2.714312e-001, -6.944677e-001, -7.243136e-002, -6.193104e-001, 9.567440e-001, -6.317194e-002, 8.881508e-001, -2.783301e-001, 4.224532e+000, 1.192802e+000, -1.133391e+000, -9.811942e-002, 2.312721e-001, -1.100585e+000, -3.655097e-001, 2.268787e-003, 5.074358e-001, 1.512457e+000, 3.165593e-001, -1.057051e+000, -3.424797e-001, 9.536822e-001, 1.034064e+000, 6.413292e-001, 1.165363e-001, -4.248128e-002, 1.592803e+000, 7.875911e-001, -1.096695e+000, -2.745143e-001, 1.077920e+000, -8.435082e-004, -3.715956e+000, 5.197900e-001, 1.171467e-001, 1.236912e+000, 6.915287e-001, // albedo 1, turbidity 8 -1.711623e+000, -9.023881e-001, -9.799257e+000, 1.022040e+001, -1.708447e-002, 3.309925e-001, -3.241111e-006, 1.932295e+000, 5.844205e-001, -2.351937e+000, -1.340391e+000, 6.329976e+000, -6.054139e+000, -2.843868e-002, 2.298301e-001, 7.698142e-002, 1.109800e+000, 1.863187e-001, -1.141314e+000, -6.670322e-001, -3.262632e+000, 4.551521e+000, -8.614941e-002, 8.058038e-001, -2.791051e-001, 3.084281e+000, 1.236638e+000, -7.950557e-001, 2.489854e-001, 9.966347e-001, -3.391737e+000, -7.235716e-001, -2.155609e-001, 5.126659e-001, 1.452322e+000, 2.882812e-001, -1.182289e+000, -5.192524e-001, 9.672941e-001, 3.091448e+000, -4.193043e+000, 4.051469e-001, -5.708309e-002, 9.386723e-001, 8.208828e-001, -1.080579e+000, -2.918654e-001, 9.499317e-001, 2.856082e+000, -2.256007e+000, 1.377750e-002, 1.012914e-001, 9.716489e-001, 6.832750e-001, // albedo 1, turbidity 9 -1.964781e+000, -1.162652e+000, -6.074737e+000, 6.497797e+000, -2.595660e-002, 3.222936e-001, -3.220871e-006, 1.685891e+000, 6.501551e-001, -2.352213e+000, -1.199539e+000, 4.248376e+000, -3.876965e+000, -6.837923e-002, 1.764412e-001, 5.514810e-002, 1.442736e+000, 6.979575e-002, -2.560247e+000, -1.883591e+000, -1.916723e+000, 2.598994e+000, -2.372381e-002, 8.442578e-001, -2.063113e-001, 2.359942e+000, 1.287838e+000, 7.281064e-002, 7.835433e-001, 1.380748e-001, -2.065580e+000, -1.696648e+000, -4.575316e-001, 3.840004e-001, 9.397056e-001, 3.103904e-001, -1.444446e+000, -7.662151e-001, 1.364103e+000, 4.930232e+000, -4.455564e+000, 6.735458e-001, -4.052978e-003, 3.194173e-001, 7.842959e-001, -1.039666e+000, -3.171617e-001, 7.295920e-001, 2.813846e+000, -1.561230e+000, -4.128303e-001, 1.004149e-001, 6.653613e-001, 6.980277e-001, // albedo 1, turbidity 10 -2.999915e+000, -1.721740e+000, -4.796494e+000, 5.021888e+000, -2.163250e-002, 3.309183e-001, -4.051804e-006, 1.645464e+000, 7.145890e-001, -1.673162e+000, -1.056666e+000, 3.209766e+000, -2.559187e+000, -7.456364e-002, 6.215063e-002, 4.469425e-002, 1.242757e+000, -1.580590e-002, -5.775475e+000, -3.239700e+000, -1.356432e+000, 1.099950e+000, -9.497509e-002, 7.121875e-001, -1.656838e-001, 2.553396e+000, 1.286227e+000, 1.241869e+000, 6.671222e-001, -4.156007e-001, -8.167921e-001, -1.037816e+000, 5.950065e-002, 3.114868e-001, 6.414114e-001, 3.677503e-001, -1.580126e+000, -7.852349e-001, 1.749569e+000, 5.987990e+000, -5.075133e+000, -4.693815e-002, -5.106759e-002, -9.755925e-001, 7.440092e-001, -9.732917e-001, -1.939297e-001, 2.709367e-001, 1.352990e+000, -9.040352e-001, 5.181217e-003, 2.302437e-001, 1.506500e+000, 6.840186e-001, }; static float datasetRad440[] = { // albedo 0, turbidity 1 9.406889e-003, 1.954373e-002, -4.018205e-002, 1.740051e-001, 1.351020e-001, 1.365376e-001, // albedo 0, turbidity 2 9.206049e-003, 2.042313e-002, -4.377380e-002, 1.787089e-001, 1.388614e-001, 1.384128e-001, // albedo 0, turbidity 3 9.050889e-003, 2.086396e-002, -4.652916e-002, 1.794829e-001, 1.524222e-001, 1.376563e-001, // albedo 0, turbidity 4 8.656343e-003, 2.210653e-002, -5.212791e-002, 1.836315e-001, 1.663040e-001, 1.419649e-001, // albedo 0, turbidity 5 8.355466e-003, 2.244975e-002, -5.393078e-002, 1.788056e-001, 1.868417e-001, 1.445069e-001, // albedo 0, turbidity 6 8.187585e-003, 2.235434e-002, -5.291187e-002, 1.693688e-001, 2.073941e-001, 1.424517e-001, // albedo 0, turbidity 7 7.909229e-003, 2.199365e-002, -5.165975e-002, 1.577725e-001, 2.297489e-001, 1.468516e-001, // albedo 0, turbidity 8 7.580566e-003, 2.048421e-002, -4.471863e-002, 1.277026e-001, 2.737620e-001, 1.497600e-001, // albedo 0, turbidity 9 7.101943e-003, 1.675094e-002, -2.761544e-002, 7.078506e-002, 3.397147e-001, 1.557184e-001, // albedo 0, turbidity 10 6.525444e-003, 1.090411e-002, -1.995302e-003, -8.176097e-003, 4.124321e-001, 1.714881e-001, // albedo 1, turbidity 1 1.111702e-002, 1.783998e-002, -1.949635e-002, 1.124970e-001, 2.993330e-001, 2.864943e-001, // albedo 1, turbidity 2 1.099681e-002, 1.809609e-002, -2.099087e-002, 1.131858e-001, 3.057413e-001, 2.866962e-001, // albedo 1, turbidity 3 1.070017e-002, 1.818573e-002, -2.159895e-002, 1.084494e-001, 3.229180e-001, 2.835407e-001, // albedo 1, turbidity 4 1.032234e-002, 1.871074e-002, -2.469404e-002, 1.069731e-001, 3.380450e-001, 2.864479e-001, // albedo 1, turbidity 5 9.893912e-003, 1.844953e-002, -2.358500e-002, 9.439551e-002, 3.642566e-001, 2.829554e-001, // albedo 1, turbidity 6 9.650400e-003, 1.877062e-002, -2.542361e-002, 9.189004e-002, 3.720610e-001, 2.856265e-001, // albedo 1, turbidity 7 9.322628e-003, 1.810055e-002, -2.246559e-002, 7.543314e-002, 3.958251e-001, 2.842134e-001, // albedo 1, turbidity 8 8.842659e-003, 1.604245e-002, -1.397353e-002, 4.233011e-002, 4.358270e-001, 2.789888e-001, // albedo 1, turbidity 9 8.169168e-003, 1.265551e-002, 4.076399e-004, -7.877623e-003, 4.830048e-001, 2.768485e-001, // albedo 1, turbidity 10 7.383449e-003, 7.340131e-003, 2.094279e-002, -7.138907e-002, 5.217098e-001, 2.803810e-001, }; static float dataset480[] = { // albedo 0, turbidity 1 -1.255072e+000, -3.501170e-001, -5.952795e+000, 6.529723e+000, -6.362962e-002, 6.436422e-001, 7.745270e-003, 3.657426e+000, 5.329375e-001, -1.344988e+000, -4.365880e-001, -1.750961e+000, 2.262943e+000, -1.049983e-001, 3.754288e-001, 5.298712e-002, 3.402851e+000, 3.874229e-001, -1.073402e+000, -1.395260e-001, 2.839003e+000, -2.827315e+000, -1.882090e-001, 1.054349e+000, -8.976330e-002, 5.604794e+000, 6.740510e-001, -1.183711e+000, -4.011868e-001, 7.358740e-001, 1.479436e+000, -7.268596e-001, 1.133998e+000, 1.205942e-001, -4.232970e+000, 1.060586e+000, -1.018668e+000, -8.561816e-002, 1.030241e+000, -4.461392e-001, 3.940284e-001, 1.220382e+000, -1.391238e-001, 5.771847e+000, 5.627180e-001, -1.080081e+000, -1.746769e-001, 1.174843e+000, 9.389450e-002, -4.893194e+000, 1.162505e+000, 1.563406e-001, 2.606800e+000, 4.999990e-001, // albedo 0, turbidity 2 -1.268430e+000, -3.752425e-001, -8.504068e+000, 9.021017e+000, -4.092613e-002, 6.553965e-001, 8.607147e-003, 3.444138e+000, 5.600385e-001, -1.459780e+000, -5.882818e-001, 1.800729e+000, -9.674514e-001, -8.308819e-002, 4.453337e-001, 4.086836e-002, 1.853978e+000, 2.818975e-001, -8.680288e-001, 1.148721e-001, 3.161508e-001, -1.524870e+000, -1.921031e-001, 6.496299e-001, 4.422347e-004, 8.241268e+000, 9.821338e-001, -1.277439e+000, -4.550135e-001, 1.088681e+000, 1.552370e+000, -6.184442e-001, 1.386667e+000, 1.035135e-001, -3.331179e+000, 5.236122e-001, -9.964896e-001, -9.832891e-002, 9.746026e-001, -9.125638e-001, -7.457170e-001, 9.111352e-001, -7.027011e-002, 4.669829e+000, 7.455938e-001, -1.083449e+000, -1.686372e-001, 1.003727e+000, 4.085513e-001, -4.725304e+000, 1.112591e+000, 1.855240e-001, 3.038195e+000, 5.969305e-001, // albedo 0, turbidity 3 -1.290677e+000, -3.901158e-001, -9.520695e+000, 9.828711e+000, -3.154131e-002, 5.939314e-001, 2.686840e-002, 3.612397e+000, 5.140176e-001, -1.535002e+000, -6.667464e-001, 2.735758e-002, 9.423936e-001, -8.287240e-002, 6.775029e-001, 4.575744e-003, 1.432097e+000, 3.872415e-001, -7.903104e-001, 1.563438e-001, -2.022567e-001, -1.026670e+000, 9.063977e-003, 3.942033e-001, -1.241980e-002, 7.980026e+000, 1.066191e+000, -1.278947e+000, -3.694875e-001, 8.111792e-001, 4.993027e-001, -1.096772e+000, 1.008837e+000, 2.920972e-001, -7.314209e-001, 3.179440e-001, -1.006667e+000, -1.519095e-001, 8.774664e-001, -1.909283e-001, 3.756189e+000, 9.311862e-001, -9.327427e-002, 3.499747e+000, 8.574583e-001, -1.086931e+000, -1.774734e-001, 8.989024e-001, 5.536469e-002, -3.474034e+000, 9.736834e-001, 2.325787e-001, 2.809427e+000, 6.246481e-001, // albedo 0, turbidity 4 -1.346571e+000, -4.451276e-001, -2.373159e+001, 2.408962e+001, -1.225268e-002, 5.720568e-001, 1.636363e-002, 3.288957e+000, 5.104502e-001, -1.607315e+000, -7.416360e-001, -5.233286e-001, 1.169215e+000, -2.350907e-002, 4.942922e-001, 3.544231e-002, 1.659598e+000, 3.959771e-001, -8.259129e-001, 9.305732e-002, 4.864320e+000, -5.585537e+000, -4.428624e-002, 7.540493e-001, -1.060506e-001, 6.548781e+000, 1.138009e+000, -1.204471e+000, -2.620580e-001, -2.637261e+000, 3.057335e+000, -1.226916e-001, 5.657925e-001, 4.446409e-001, 1.136957e+000, 2.881385e-001, -1.035718e+000, -2.116415e-001, 1.288642e+000, -3.834162e-001, -9.488050e-002, 7.404996e-001, -6.538922e-002, 2.336877e+000, 8.612030e-001, -1.087946e+000, -1.841898e-001, 4.491757e-001, 1.691479e-001, 1.022577e-001, 9.202996e-001, 2.926112e-001, 2.844475e+000, 6.452620e-001, // albedo 0, turbidity 5 -1.381782e+000, -4.914069e-001, -4.813999e+001, 4.837634e+001, -5.296025e-003, 5.571609e-001, 1.649034e-002, 3.203385e+000, 5.048069e-001, -1.776157e+000, -9.226583e-001, 1.389662e+001, -1.292490e+001, -1.480095e-002, 5.073308e-001, 4.585849e-002, 7.385206e-001, 4.280887e-001, -8.381948e-001, 1.229315e-001, -3.370527e+000, 1.825510e+000, -9.728251e-003, 8.572929e-001, -1.855299e-001, 7.471741e+000, 1.133190e+000, -1.125194e+000, -2.647028e-001, 6.942391e-001, 1.389102e+000, -2.216447e-001, 1.356485e-001, 5.812792e-001, -5.073865e-001, 2.675490e-001, -1.095144e+000, -2.442208e-001, 4.787687e-001, -2.707940e+000, 6.129627e-001, 7.213058e-001, -6.034254e-002, 2.798703e+000, 8.787214e-001, -1.062019e+000, -1.765309e-001, 5.423897e-001, 3.783099e+000, -5.007038e+000, 7.376299e-001, 3.034085e-001, 2.733411e+000, 6.555070e-001, // albedo 0, turbidity 6 -1.390263e+000, -5.185474e-001, -1.630741e+001, 1.654109e+001, -1.499201e-002, 5.661787e-001, 1.452544e-002, 3.046179e+000, 5.026700e-001, -1.935801e+000, -9.953289e-001, -1.483271e+000, 1.913745e+000, -2.518160e-002, 4.593343e-001, 4.285617e-002, 1.448437e+000, 4.509310e-001, -7.547378e-001, 2.590987e-002, 2.480507e+000, -2.271835e+000, -5.259620e-002, 9.001709e-001, -2.024986e-001, 4.958191e+000, 1.036940e+000, -1.157324e+000, -1.198742e-001, -1.440574e+000, 3.070751e-001, -1.807577e-001, 4.059237e-002, 6.210184e-001, 2.425946e+000, 3.828327e-001, -1.065566e+000, -3.139616e-001, 5.715306e-001, 8.053761e-001, 1.396364e-001, 4.009778e-001, 5.681033e-003, 1.354013e+000, 7.861375e-001, -1.095972e+000, -2.178745e-001, 4.681537e-001, 1.235458e-001, -1.084613e+000, 1.006455e+000, 2.754677e-001, 2.239616e+000, 6.954839e-001, // albedo 0, turbidity 7 -1.453150e+000, -5.790574e-001, -1.243832e+001, 1.263425e+001, -1.892784e-002, 4.979177e-001, 1.035899e-002, 2.982682e+000, 5.056256e-001, -1.925518e+000, -1.010928e+000, 1.513827e+000, -9.219873e-001, -3.776925e-002, 4.692652e-001, 4.083023e-002, 1.303495e+000, 4.245150e-001, -1.134311e+000, -2.754710e-001, -2.443212e-001, 3.845396e-002, -1.074645e-001, 1.066657e+000, -2.324557e-001, 4.996897e+000, 1.052268e+000, -8.094396e-001, 1.096826e-001, -5.117072e-001, -1.915992e-001, -1.991693e-001, -5.943341e-001, 6.791986e-001, 1.332014e+000, 3.606306e-001, -1.227889e+000, -4.522793e-001, 5.338266e-002, 1.074118e+000, 8.733709e-002, 1.005448e+000, -1.725176e-002, 1.326110e+000, 8.063751e-001, -1.065450e+000, -2.160134e-001, 3.413994e-001, 4.950303e-001, -1.077199e+000, 3.654185e-001, 3.125819e-001, 1.998536e+000, 6.865917e-001, // albedo 0, turbidity 8 -1.594869e+000, -7.366760e-001, -1.252117e+001, 1.275030e+001, -1.697659e-002, 4.892543e-001, 2.831848e-003, 2.542039e+000, 5.457358e-001, -1.980952e+000, -9.910920e-001, 6.178699e+000, -5.888582e+000, -3.099336e-002, 3.859266e-001, 4.511764e-002, 1.839601e+000, 2.791527e-001, -1.766081e+000, -8.995150e-001, -2.712687e+000, 3.263201e+000, -1.840688e-001, 1.305410e+000, -2.675879e-001, 3.647246e+000, 1.168203e+000, -3.742071e-001, 4.678023e-001, 6.371403e-002, -2.016941e+000, -2.723239e-001, -1.446876e+000, 7.533604e-001, 1.131760e+000, 2.537537e-001, -1.380378e+000, -6.406403e-001, 7.018678e-001, 2.032023e+000, -2.393487e+000, 1.930827e+000, -1.260608e-001, 7.634327e-001, 8.870918e-001, -1.088465e+000, -2.971190e-001, 1.411657e-001, 1.879601e+000, -1.310304e+000, -7.045740e-001, 3.313185e-001, 1.264266e+000, 6.534482e-001, // albedo 0, turbidity 9 -2.229949e+000, -1.153733e+000, -7.505783e+000, 7.718722e+000, -2.407129e-002, 4.175820e-001, 4.559186e-005, 2.157318e+000, 6.337774e-001, -1.995509e+000, -8.778717e-001, 4.191031e+000, -3.968507e+000, -5.176872e-002, 1.960357e-001, 3.755797e-002, 1.975436e+000, 1.077053e-001, -3.174785e+000, -2.105130e+000, -2.062230e+000, 2.391786e+000, -4.217147e-002, 9.727297e-001, -1.540078e-001, 2.691773e+000, 1.235189e+000, 4.882832e-001, 1.097365e+000, -1.866214e-001, -1.567231e+000, -1.216396e+000, -4.391280e-001, 4.541998e-001, 1.167636e+000, 3.003642e-001, -1.709118e+000, -9.374505e-001, 6.559000e-001, 3.977860e+000, -3.525762e+000, 6.202828e-001, 7.863257e-002, 6.882512e-001, 8.161696e-001, -9.999977e-001, -2.777886e-001, 9.586687e-003, 1.766813e+000, -1.065121e+000, -1.325963e-001, 2.512239e-001, 1.055043e+000, 6.874661e-001, // albedo 0, turbidity 10 -2.932652e+000, -1.609416e+000, -3.825171e+000, 3.969752e+000, -3.638195e-002, 3.557402e-001, -4.379735e-006, 1.927804e+000, 7.278380e-001, -1.591732e+000, -7.579896e-001, 1.711976e+000, -1.369988e+000, -1.107557e-001, 1.237841e-001, 1.548121e-002, 2.024749e+000, -4.315379e-002, -6.085760e+000, -3.429651e+000, -6.780006e-001, -1.902709e-002, 6.566034e-002, 8.329946e-001, -1.012845e-001, 2.617589e+000, 1.342663e+000, 1.335204e+000, 1.035931e+000, -1.008915e+000, 5.915758e-001, -1.907371e+000, -3.568938e-002, 3.295382e-001, 6.546480e-001, 2.435447e-001, -1.800155e+000, -1.010684e+000, 1.160290e+000, 5.269190e+000, -3.895543e+000, 5.274946e-002, 3.971324e-002, 8.769492e-002, 8.252336e-001, -9.843476e-001, -3.014031e-001, -3.167912e-001, 1.384556e+000, -6.881572e-001, 5.617519e-002, 2.805263e-001, 9.930291e-001, 6.783964e-001, // albedo 1, turbidity 1 -1.257325e+000, -3.441598e-001, -5.951667e+000, 6.530618e+000, -5.773033e-002, 6.437990e-001, 8.453838e-003, 3.657343e+000, 5.329715e-001, -1.346061e+000, -4.331978e-001, -1.749638e+000, 2.263845e+000, -1.013807e-001, 3.755084e-001, 5.287214e-002, 3.402954e+000, 3.874047e-001, -1.073983e+000, -1.372222e-001, 2.840388e+000, -2.826616e+000, -1.866609e-001, 1.054193e+000, -8.989038e-002, 5.604984e+000, 6.739811e-001, -1.184707e+000, -3.992543e-001, 7.374377e-001, 1.479838e+000, -7.263903e-001, 1.133619e+000, 1.199206e-001, -4.232702e+000, 1.060412e+000, -1.021623e+000, -8.422241e-002, 1.032293e+000, -4.460168e-001, 3.941239e-001, 1.219939e+000, -1.420884e-001, 5.772239e+000, 5.623142e-001, -1.087791e+000, -1.754873e-001, 1.178006e+000, 9.386850e-002, -4.893184e+000, 1.162164e+000, 1.535543e-001, 2.607460e+000, 4.997706e-001, // albedo 1, turbidity 2 -1.251295e+000, -3.651612e-001, -9.950987e+000, 1.058444e+001, -3.065334e-002, 5.979560e-001, 1.817303e-002, 3.132460e+000, 5.458738e-001, -1.374134e+000, -5.079738e-001, 2.333109e+000, -1.251359e+000, -7.802080e-002, 3.182768e-001, 3.746599e-002, 1.963940e+000, 2.733180e-001, -9.862389e-001, -2.441831e-002, 2.657376e-001, -1.054016e+000, -8.576871e-002, 7.356127e-001, -4.711349e-002, 6.677884e+000, 1.206629e+000, -1.140461e+000, -3.212487e-001, 1.547332e+000, 9.031281e-001, -8.421239e-001, 1.166595e+000, 1.643076e-001, -2.534096e+000, 1.884034e-001, -1.049493e+000, -1.256523e-001, 1.205849e+000, -3.649526e-001, 8.075413e-001, 3.421308e-001, -1.173508e-001, 4.535809e+000, 9.497555e-001, -1.063961e+000, -1.336751e-001, 1.173271e+000, 1.016777e-001, -4.093576e+000, 4.559998e-001, 1.519017e-001, 4.153208e+000, 5.324846e-001, // albedo 1, turbidity 3 -1.271751e+000, -3.837936e-001, -1.052025e+001, 1.102826e+001, -2.411879e-002, 5.019991e-001, 3.094786e-002, 3.138107e+000, 5.059631e-001, -1.472034e+000, -6.259760e-001, -5.356154e-001, 1.713500e+000, -6.089970e-002, 4.750716e-001, 6.622428e-003, 1.224931e+000, 4.198087e-001, -8.587401e-001, 1.099859e-001, 3.258521e-001, -1.301658e+000, -4.452458e-002, 6.461336e-001, -2.947489e-002, 7.603712e+000, 1.091511e+000, -1.221875e+000, -3.659269e-001, 9.953072e-001, 8.481237e-001, -5.952235e-001, 1.016442e+000, 2.259940e-001, -1.925411e+000, 3.654292e-001, -1.008105e+000, -1.136472e-001, 1.248935e+000, -3.865165e-001, 1.714619e+000, -1.216223e-001, -2.436842e-002, 4.227455e+000, 7.030495e-001, -1.082262e+000, -1.513279e-001, 1.052383e+000, 2.125686e-001, -5.028093e-001, 8.694047e-001, 1.099128e-001, 3.634467e+000, 7.206727e-001, // albedo 1, turbidity 4 -1.310438e+000, -4.332417e-001, -2.812457e+001, 2.859054e+001, -7.241887e-003, 4.123186e-001, 2.839263e-002, 2.866138e+000, 5.063521e-001, -1.598864e+000, -7.787419e-001, 4.189377e+000, -3.122921e+000, -1.896105e-002, 6.071985e-001, 1.999660e-002, 7.039076e-001, 4.125456e-001, -7.834866e-001, 1.890740e-001, 1.102853e+000, -1.842558e+000, -3.985000e-002, 6.423282e-001, -1.131231e-001, 7.222493e+000, 1.177285e+000, -1.244910e+000, -3.668018e-001, -2.083168e-001, 1.051092e+000, -1.483362e-001, 4.066210e-001, 4.623360e-001, -1.971682e-001, 2.178890e-001, -1.010078e+000, -1.593623e-001, 1.747411e+000, -6.961852e-002, -1.503091e-001, 5.439839e-001, -1.874287e-001, 2.074758e+000, 9.133302e-001, -1.086611e+000, -1.529597e-001, 4.548984e-001, 2.836062e-001, 4.168066e-001, 3.953841e-001, 2.451427e-001, 3.799065e+000, 6.288711e-001, // albedo 1, turbidity 5 -1.338369e+000, -4.683873e-001, -3.858110e+001, 3.898823e+001, -5.111812e-003, 4.638476e-001, 2.389163e-002, 2.774207e+000, 5.242274e-001, -1.785780e+000, -9.773633e-001, 6.470331e+000, -5.147348e+000, -1.593592e-002, 4.175720e-001, 2.497956e-002, 7.090702e-002, 3.252744e-001, -6.972735e-001, 2.786524e-001, 4.011350e-003, -1.686706e+000, -4.966516e-003, 8.368703e-001, -1.225606e-001, 7.731542e+000, 1.267577e+000, -1.307129e+000, -4.728119e-001, 2.639424e-002, 2.633155e+000, -2.357439e-001, 1.263362e-001, 4.765765e-001, -2.025027e+000, 1.705113e-001, -9.583414e-001, -7.928834e-002, 1.447497e+000, -2.797571e+000, 8.553597e-001, 4.842942e-001, -7.727878e-002, 3.765006e+000, 9.191738e-001, -1.114040e+000, -2.132678e-001, 1.030931e+000, 2.871507e+000, -5.013319e+000, 2.699945e-001, 1.819978e-001, 2.239642e+000, 6.539653e-001, // albedo 1, turbidity 6 -1.393024e+000, -5.200008e-001, -1.941271e+001, 1.986171e+001, -1.212818e-002, 5.019138e-001, 7.897163e-003, 2.696459e+000, 5.258316e-001, -1.831466e+000, -1.018106e+000, 3.204932e+000, -2.139369e+000, -2.441969e-002, 3.191029e-001, 5.563321e-002, 1.320760e-001, 3.265220e-001, -7.994553e-001, 1.337239e-001, -1.563712e+000, 7.392042e-001, -3.136373e-002, 1.008208e+000, -1.988762e-001, 6.626579e+000, 1.223213e+000, -1.159543e+000, -2.836180e-001, 1.057464e+000, -3.647533e-001, -2.513115e-001, -1.995636e-001, 5.943224e-001, -4.865436e-001, 2.279895e-001, -1.044528e+000, -2.152538e-001, 1.023157e+000, 5.599579e-002, 6.321805e-001, 5.155639e-001, -1.111252e-001, 2.282270e+000, 8.647371e-001, -1.092518e+000, -1.865821e-001, 1.057856e+000, 3.491427e-001, -2.631526e+000, 3.584288e-001, 2.191649e-001, 2.389704e+000, 6.765946e-001, // albedo 1, turbidity 7 -1.384989e+000, -5.305700e-001, -1.459855e+001, 1.497673e+001, -1.471976e-002, 4.569028e-001, 5.419006e-003, 2.735360e+000, 5.389891e-001, -2.086660e+000, -1.234696e+000, 2.053196e+000, -1.257012e+000, -2.129117e-002, 1.990309e-001, 8.511032e-002, -1.312659e-001, 2.800139e-001, -7.309069e-001, 1.413931e-001, -1.773938e-001, 2.938820e-001, -4.933601e-002, 1.496853e+000, -3.213358e-001, 6.305852e+000, 1.298086e+000, -1.203529e+000, -3.216432e-001, -1.458970e-001, -5.598789e-001, -2.934068e-001, -1.206192e+000, 7.793654e-001, -9.223710e-001, 1.229360e-001, -1.002538e+000, -1.984480e-001, 1.233954e+000, 8.779171e-001, 3.133737e-001, 1.311239e+000, -2.132532e-001, 2.223702e+000, 9.461065e-001, -1.123572e+000, -2.342682e-001, 9.679089e-001, -1.017991e-003, -1.960819e+000, -1.153680e-001, 2.843114e-001, 1.779831e+000, 6.400916e-001, // albedo 1, turbidity 8 -1.537393e+000, -6.924151e-001, -1.239252e+001, 1.285585e+001, -1.666284e-002, 4.429862e-001, 2.398230e-003, 2.210714e+000, 5.509453e-001, -1.817841e+000, -9.662082e-001, 6.281905e+000, -5.778709e+000, -3.131226e-002, 3.074609e-001, 4.530074e-002, 1.409838e+000, 2.538213e-001, -1.790530e+000, -8.332867e-001, -2.605975e+000, 3.383959e+000, -1.685493e-001, 1.307568e+000, -2.569465e-001, 3.272862e+000, 1.247743e+000, -3.808658e-001, 3.525732e-001, 3.897535e-001, -2.085715e+000, -1.845614e-001, -1.470598e+000, 7.033938e-001, 8.475130e-001, 1.758974e-001, -1.374360e+000, -5.517879e-001, 1.276626e+000, 1.821209e+000, -2.480880e+000, 1.866494e+000, -1.649246e-001, 6.333864e-001, 9.339444e-001, -1.024167e+000, -2.097189e-001, 8.424991e-001, 1.767689e+000, -1.312031e+000, -8.191386e-001, 2.156968e-001, 1.201032e+000, 6.593457e-001, // albedo 1, turbidity 9 -2.190652e+000, -1.106580e+000, -7.466636e+000, 7.752518e+000, -2.263662e-002, 4.154878e-001, -1.646586e-006, 2.076563e+000, 6.322611e-001, -1.972368e+000, -8.108244e-001, 4.233742e+000, -3.927321e+000, -5.152609e-002, 2.005285e-001, 2.985984e-002, 1.903602e+000, 1.099985e-001, -3.148093e+000, -2.033135e+000, -2.019650e+000, 2.409779e+000, -1.255187e-002, 9.697956e-001, -1.538080e-001, 2.617071e+000, 1.234755e+000, 5.592882e-001, 1.073057e+000, -2.763735e-002, -1.563728e+000, -1.191791e+000, -4.331798e-001, 4.622361e-001, 1.142664e+000, 2.988891e-001, -1.706427e+000, -8.516236e-001, 1.014996e+000, 3.980336e+000, -3.487485e+000, 6.331985e-001, -1.818380e-002, 7.352340e-001, 8.452629e-001, -1.006197e+000, -1.932306e-001, 5.337019e-001, 1.797637e+000, -9.474717e-001, -1.353274e-001, 2.049954e-001, 1.156100e+000, 6.894153e-001, // albedo 1, turbidity 10 -2.473813e+000, -1.478132e+000, -3.492210e+000, 3.805303e+000, -3.251673e-002, 3.621052e-001, -6.447770e-006, 1.596383e+000, 8.551930e-001, -1.494464e+000, -7.635918e-001, 2.071212e+000, -1.536108e+000, -1.369345e-001, 1.287259e-001, 2.147844e-002, 1.753080e+000, -2.246103e-001, -6.305007e+000, -3.323156e+000, -7.099379e-001, 1.686111e-001, 1.080881e-001, 8.729732e-001, -1.291207e-001, 2.282989e+000, 1.475588e+000, 1.325532e+000, 5.765517e-001, -7.011257e-001, 7.720216e-001, -2.013560e+000, -1.990572e-001, 3.922685e-001, 9.898769e-003, 1.789360e-001, -1.590406e+000, -7.529646e-001, 1.930414e+000, 5.169169e+000, -4.221403e+000, 4.614858e-002, -9.527005e-002, -7.894472e-001, 8.458063e-001, -1.005785e+000, -2.286223e-001, 3.330253e-001, 1.438452e+000, -7.701349e-001, 2.780764e-002, 2.630698e-001, 8.329894e-001, 6.747408e-001, }; static float datasetRad480[] = { // albedo 0, turbidity 1 1.367487e-002, 1.998477e-002, -2.747378e-002, 2.012913e-001, 1.065803e-001, 1.249226e-001, // albedo 0, turbidity 2 1.319623e-002, 2.233282e-002, -3.838862e-002, 2.216885e-001, 1.032539e-001, 1.308019e-001, // albedo 0, turbidity 3 1.265118e-002, 2.391819e-002, -4.721677e-002, 2.352182e-001, 1.174476e-001, 1.303906e-001, // albedo 0, turbidity 4 1.204726e-002, 2.745130e-002, -6.437791e-002, 2.605947e-001, 1.298129e-001, 1.378516e-001, // albedo 0, turbidity 5 1.125691e-002, 3.031033e-002, -7.856070e-002, 2.797308e-001, 1.411425e-001, 1.486601e-001, // albedo 0, turbidity 6 1.087451e-002, 3.134174e-002, -8.308676e-002, 2.793109e-001, 1.610134e-001, 1.502290e-001, // albedo 0, turbidity 7 1.035757e-002, 3.176437e-002, -8.486370e-002, 2.674373e-001, 1.974534e-001, 1.533206e-001, // albedo 0, turbidity 8 9.649434e-003, 3.087937e-002, -8.067259e-002, 2.353243e-001, 2.553337e-001, 1.608814e-001, // albedo 0, turbidity 9 8.869346e-003, 2.627497e-002, -5.891488e-002, 1.570602e-001, 3.504762e-001, 1.724148e-001, // albedo 0, turbidity 10 8.105360e-003, 1.756907e-002, -2.001928e-002, 3.536541e-002, 4.692392e-001, 1.926373e-001, // albedo 1, turbidity 1 1.531497e-002, 2.090118e-002, -1.665041e-002, 1.626765e-001, 2.602854e-001, 2.739350e-001, // albedo 1, turbidity 2 1.500055e-002, 2.258405e-002, -2.517423e-002, 1.780058e-001, 2.604774e-001, 2.803331e-001, // albedo 1, turbidity 3 1.435727e-002, 2.473634e-002, -3.651251e-002, 1.966627e-001, 2.645889e-001, 2.894029e-001, // albedo 1, turbidity 4 1.368791e-002, 2.602874e-002, -4.462666e-002, 2.008996e-001, 2.978971e-001, 2.872899e-001, // albedo 1, turbidity 5 1.298035e-002, 2.709110e-002, -5.084570e-002, 2.010066e-001, 3.257828e-001, 2.917322e-001, // albedo 1, turbidity 6 1.267531e-002, 2.752851e-002, -5.364450e-002, 1.962715e-001, 3.472458e-001, 2.928354e-001, // albedo 1, turbidity 7 1.200196e-002, 2.782022e-002, -5.449978e-002, 1.818445e-001, 3.795420e-001, 2.974612e-001, // albedo 1, turbidity 8 1.115769e-002, 2.603247e-002, -4.606362e-002, 1.383509e-001, 4.427481e-001, 2.969281e-001, // albedo 1, turbidity 9 1.034375e-002, 2.111036e-002, -2.502615e-002, 6.215948e-002, 5.253192e-001, 2.999927e-001, // albedo 1, turbidity 10 9.270257e-003, 1.252950e-002, 1.085115e-002, -5.004679e-002, 6.169243e-001, 3.053035e-001, }; static float dataset520[] = { // albedo 0, turbidity 1 -1.171338e+000, -2.379456e-001, -6.515446e+000, 7.133235e+000, -5.382867e-002, 6.889982e-001, 4.250983e-002, 4.471437e+000, 5.087463e-001, -1.193029e+000, -2.445141e-001, -4.311723e-001, 1.019354e+000, -1.281643e-001, 7.837279e-001, 2.609613e-002, 5.965800e+000, 4.381607e-001, -1.165299e+000, -2.503239e-001, 3.829843e+000, -2.234083e+000, -4.693988e-001, 1.045109e+000, -6.241707e-002, 2.623310e-001, 7.500398e-001, -1.077288e+000, -2.659342e-001, -7.565678e-002, 1.145086e+000, -2.316655e-002, 1.564941e+000, 9.375322e-002, -7.476929e-001, 6.076913e-001, -1.075530e+000, -1.232648e-001, 1.877081e+000, -1.186427e-001, -2.748628e+000, 1.249377e+000, -1.085780e-001, 3.838331e+000, 8.601227e-001, -1.067002e+000, -1.572453e-001, 1.350156e+000, 3.140948e-003, -3.277283e+000, 1.488404e+000, 1.127058e-001, 2.655730e+000, 4.999138e-001, // albedo 0, turbidity 2 -1.175145e+000, -2.454528e-001, -8.173280e+000, 8.622722e+000, -3.895019e-002, 6.739096e-001, 6.622835e-002, 4.450872e+000, 5.061382e-001, -1.226543e+000, -2.979950e-001, 3.102814e+000, -2.662701e+000, -1.012309e-001, 5.142095e-001, 4.939276e-002, 5.007851e+000, 4.179865e-001, -1.075743e+000, -1.267529e-001, 1.017884e-001, 4.839556e-001, -4.025119e-001, 1.120466e+000, -5.059103e-002, 3.601070e+000, 1.104232e+000, -1.104008e+000, -2.079352e-001, 1.094572e+000, 1.147058e+000, -1.516726e-001, 1.526097e+000, 1.922554e-001, 4.060614e-001, 2.975787e-001, -1.080135e+000, -1.942481e-001, 1.409056e+000, -3.800384e+000, -7.125701e+000, 9.731220e-001, -7.312793e-002, 2.377810e+000, 9.223131e-001, -1.066280e+000, -1.421591e-001, 1.272936e+000, 7.891881e+000, -3.626975e+000, 1.294678e+000, 1.331475e-001, 2.986127e+000, 5.316962e-001, // albedo 0, turbidity 3 -1.210057e+000, -2.827640e-001, -5.179186e+000, 5.514430e+000, -5.638504e-002, 6.656727e-001, 5.417868e-002, 4.216550e+000, 5.495231e-001, -1.311087e+000, -3.921139e-001, 1.436554e+000, -7.051260e-001, -1.462714e-001, 2.604620e-001, 5.771570e-002, 3.493766e+000, 5.041164e-001, -9.705912e-001, -4.316197e-002, 5.357225e-001, -1.399982e+000, -3.407923e-001, 1.585242e+000, -6.423039e-002, 5.338193e+000, 9.835385e-001, -1.177697e+000, -1.893604e-001, -5.207247e-002, 4.572666e+000, -5.523178e-001, 2.677765e-001, 3.872768e-001, 1.978123e+000, 4.095974e-001, -1.029420e+000, -2.105096e-001, 1.657176e+000, -1.028655e+001, -7.725428e+000, 1.707122e+000, -7.681108e-002, 1.074660e+000, 8.312794e-001, -1.082084e+000, -1.321893e-001, 8.487219e-001, 1.858290e+001, -3.172656e+000, 6.915801e-001, 1.905927e-001, 3.901473e+000, 6.144141e-001, // albedo 0, turbidity 4 -1.259854e+000, -3.329630e-001, -2.270176e+000, 2.357599e+000, -9.019414e-002, 5.779792e-001, 7.706039e-002, 3.971905e+000, 4.999172e-001, -1.413220e+000, -5.430979e-001, -1.715627e-001, 1.151561e+000, -2.318489e-001, 2.791441e-001, 1.306646e-002, 1.794583e+000, 6.167457e-001, -9.926840e-001, 2.303697e-002, 7.306051e-001, -2.124879e+000, -2.221853e-001, 1.635982e+000, -8.684297e-002, 7.621636e+000, 9.443863e-001, -1.113409e+000, -2.409045e-001, -1.979662e-001, 5.089736e+000, -2.071840e+000, -6.954891e-001, 5.966469e-001, -1.346819e+000, 3.752080e-001, -1.055595e+000, -1.703680e-001, 1.089771e+000, -1.041463e+001, -4.687545e+000, 2.149733e+000, -1.118987e-001, 3.558810e+000, 8.741214e-001, -1.070779e+000, -1.445161e-001, 6.385947e-001, 1.695445e+001, -3.724275e+000, -3.465499e-002, 3.645376e-001, 3.232410e+000, 6.285788e-001, // albedo 0, turbidity 5 -1.297812e+000, -3.805039e-001, -1.474455e+000, 1.558382e+000, -1.292485e-001, 5.206238e-001, 7.166147e-002, 3.651150e+000, 4.998781e-001, -1.680599e+000, -8.036751e-001, 8.267015e-001, -2.109200e-001, -4.326451e-001, 3.843930e-001, 5.207142e-002, 6.938520e-001, 4.752346e-001, -8.467684e-001, 1.620743e-001, -5.520307e-001, 8.293798e-001, 8.728132e-001, 9.075147e-001, -1.734859e-001, 7.815672e+000, 1.126843e+000, -1.182658e+000, -3.290773e-001, 1.442907e-001, -1.705529e+000, -1.186174e+001, -1.903040e-001, 7.826049e-001, -1.497409e+000, 2.238945e-001, -1.032316e+000, -1.590425e-001, 9.289968e-001, 1.217091e+001, 1.274690e+000, 1.400296e+000, -3.047612e-001, 2.805729e+000, 9.198989e-001, -1.073060e+000, -1.623303e-001, 3.798836e-001, 2.223272e+000, -4.660805e+000, -1.172357e-001, 5.306455e-001, 3.105520e+000, 6.420864e-001, // albedo 0, turbidity 6 -1.374072e+000, -4.453408e-001, -1.081601e+000, 1.104314e+000, -1.730612e-001, 5.074812e-001, 5.784588e-002, 3.488150e+000, 5.037112e-001, -1.704606e+000, -8.629255e-001, -3.905040e-001, 2.152742e+000, -6.716606e-001, 5.638527e-001, -5.967161e-003, 4.886292e-001, 4.385432e-001, -9.651511e-001, 1.186522e-001, 3.421397e-001, -4.626814e+000, 9.716770e-001, 7.579588e-001, -1.064476e-002, 8.154392e+000, 1.103676e+000, -1.067172e+000, -3.214506e-001, -3.934660e-001, 9.254630e+000, -3.599603e+000, -1.624031e-001, 5.478446e-001, -2.781628e+000, 2.905848e-001, -1.063218e+000, -1.412572e-001, 8.153795e-001, -1.467486e+001, -2.020170e+000, 1.094685e+000, 7.786265e-002, 3.719129e+000, 8.826899e-001, -1.070058e+000, -1.684172e-001, 2.225147e-001, 2.345795e+001, -4.342429e+000, -4.661816e-002, 3.545794e-001, 3.051769e+000, 6.567686e-001, // albedo 0, turbidity 7 -1.397244e+000, -4.874379e-001, -2.217129e+000, 2.415780e+000, -1.039290e-001, 5.444596e-001, 2.296795e-002, 3.242776e+000, 5.575920e-001, -1.943117e+000, -1.042293e+000, 1.936194e+000, -7.807718e-001, -4.753317e-001, 6.351817e-001, 3.357824e-002, 3.221570e-001, 2.277390e-001, -1.007469e+000, 4.283560e-002, -1.830583e+000, -1.613949e-001, 5.103059e-001, 1.830881e-001, -6.111472e-002, 7.698471e+000, 1.322151e+000, -9.885823e-001, -2.796329e-001, 9.017585e-001, 9.500529e-001, -8.751757e+000, 5.198673e-001, 6.111910e-001, -3.165369e+000, 1.193651e-001, -1.105054e+000, -1.835801e-001, 2.099263e-001, 3.626436e+000, 4.241807e-001, 2.861915e-002, -3.245808e-002, 3.560209e+000, 9.581069e-001, -1.061783e+000, -1.955111e-001, 3.405765e-001, 1.682185e+001, -4.868111e+000, 3.591669e-001, 3.518670e-001, 2.163473e+000, 6.425305e-001, // albedo 0, turbidity 8 -1.452178e+000, -5.662818e-001, -1.492883e+000, 1.742373e+000, -1.894966e-001, 6.129524e-001, 2.370115e-006, 3.042560e+000, 7.988979e-001, -2.146318e+000, -1.176122e+000, 1.480664e+000, 1.846814e-001, -9.003192e-001, 2.819986e-001, -6.858291e-003, 5.447940e-001, -2.109028e-001, -1.465359e+000, -3.055025e-001, -1.747423e+000, -2.538335e+000, 6.082904e-001, 6.523133e-001, 1.426957e-001, 6.921276e+000, 1.637843e+000, -7.135462e-001, -2.351046e-001, 1.111445e+000, 2.259275e+000, -7.853810e+000, -3.006083e-001, 3.100486e-001, -4.047366e+000, -3.732308e-002, -1.188030e+000, -2.177467e-001, 8.022451e-002, 8.746107e+000, -6.824017e-001, 5.968181e-001, 7.024883e-002, 3.164998e+000, 9.909158e-001, -1.038065e+000, -1.989059e-001, 1.630845e-001, 1.261969e+001, -4.006594e+000, -3.213161e-001, 3.948313e-001, 2.040063e+000, 6.364874e-001, // albedo 0, turbidity 9 -1.789980e+000, -8.450140e-001, -2.591234e+000, 2.769295e+000, -8.338896e-002, 5.620741e-001, -8.271253e-006, 2.531602e+000, 9.001159e-001, -1.468080e+000, -7.426812e-001, 2.369441e+000, -1.635443e+000, -3.560365e-001, 2.130482e-001, -2.124886e-003, 1.863478e+000, -3.426455e-001, -3.911974e+000, -1.873182e+000, -2.428294e+000, 1.019786e+000, 2.178584e-001, 9.599962e-001, 3.763471e-002, 4.121844e+000, 1.708236e+000, 5.986629e-001, 4.160930e-001, 1.499968e+000, -4.234635e+000, -7.153272e+000, -8.777277e-001, 4.276508e-001, -2.268730e+000, -9.278595e-002, -1.581111e+000, -5.414559e-001, 3.449756e-002, 2.095624e+001, -1.717086e+000, 6.913385e-001, -1.227380e-001, 1.401315e+000, 9.723511e-001, -9.931334e-001, -2.191364e-001, 1.647201e-001, 2.954460e+000, -2.889774e+000, -4.261816e-001, 4.166838e-001, 1.370273e+000, 6.561021e-001, // albedo 0, turbidity 10 -2.368520e+000, -1.245557e+000, -3.473878e+000, 3.511922e+000, -4.076311e-002, 4.228576e-001, -8.136079e-006, 2.268992e+000, 9.001266e-001, -1.498984e+000, -9.483364e-001, 2.970418e+000, -2.003511e+000, -3.005171e-001, 3.242320e-001, 6.724107e-003, 1.693927e+000, -2.648941e-001, -6.258071e+000, -2.616781e+000, -3.186408e+000, -3.570416e-002, 5.972101e-001, 5.638927e-001, -8.227073e-002, 3.805214e+000, 1.486701e+000, 7.183470e-001, -1.332710e-001, 1.495243e+000, 3.859652e+000, -5.605361e+000, 3.808435e-001, 4.998100e-001, -1.207866e+000, 1.082917e-001, -1.422091e+000, -5.984032e-001, 2.297508e-001, 1.726780e+000, -6.684454e-001, -1.024912e+000, -1.967199e-001, -3.214571e-001, 8.922300e-001, -1.018798e+000, -2.003211e-001, 5.344788e-002, 1.474717e+001, -4.025558e+000, 9.010150e-001, 3.605184e-001, 1.504726e+000, 6.720300e-001, // albedo 1, turbidity 1 -1.150179e+000, -2.233430e-001, -6.725138e+000, 7.601675e+000, -6.176639e-002, 7.963802e-001, 2.476816e-002, 4.311811e+000, 5.070506e-001, -1.184017e+000, -2.330060e-001, 1.903877e-001, 4.425206e-001, -1.173330e-001, 2.459899e-001, 6.799957e-002, 5.710763e+000, 4.639162e-001, -1.129855e+000, -2.313999e-001, 3.299978e+000, -1.861830e+000, -3.626476e-001, 1.858194e+000, -9.845844e-002, 6.523143e-001, 6.278178e-001, -1.090030e+000, -2.445577e-001, 4.546659e-001, 9.848860e-001, -4.044981e-001, 3.532740e-001, 1.409977e-001, -7.724273e-001, 2.901711e-001, -1.048192e+000, -1.048720e-001, 2.079951e+000, -7.519850e-002, -1.451911e+000, 1.354243e+000, -1.508252e-001, 4.159135e+000, 8.685415e-001, -1.081709e+000, -1.496534e-001, 1.433416e+000, -8.415186e-005, -3.147387e+000, 6.964893e-002, 1.345400e-001, 3.372381e+000, 5.369835e-001, // albedo 1, turbidity 2 -1.163329e+000, -2.341078e-001, -8.084459e+000, 8.765664e+000, -4.227908e-002, 6.476384e-001, 5.575993e-002, 4.291594e+000, 5.023286e-001, -1.234281e+000, -3.038288e-001, 3.304120e+000, -2.565467e+000, -1.080261e-001, 5.183037e-001, 2.633070e-002, 4.459108e+000, 4.526356e-001, -1.015235e+000, -1.003890e-001, 2.834337e-001, 4.230399e-001, -4.060874e-001, 1.119918e+000, -2.357803e-002, 3.215664e+000, 1.089777e+000, -1.171497e+000, -2.465867e-001, 1.219344e+000, 1.184120e+000, -6.451707e-002, 1.087554e+000, 1.687897e-001, 4.111776e-001, 2.471485e-001, -1.010262e+000, -1.337460e-001, 1.953577e+000, -3.761183e+000, -7.089300e+000, 5.963565e-001, -8.297304e-002, 2.741114e+000, 9.771003e-001, -1.102719e+000, -1.647974e-001, 1.510508e+000, 7.573412e+000, -3.431528e+000, 3.953995e-001, 6.793657e-002, 2.744717e+000, 5.018037e-001, // albedo 1, turbidity 3 -1.186728e+000, -2.648685e-001, -7.540497e+000, 8.152868e+000, -4.363040e-002, 6.836829e-001, 3.221451e-002, 4.013046e+000, 6.004295e-001, -1.302626e+000, -3.904258e-001, 3.431819e+000, -2.975541e+000, -7.666020e-002, 2.464561e-002, 1.054528e-001, 3.161765e+000, 3.544185e-001, -9.615438e-001, -4.842098e-002, -4.756207e-001, 9.408081e-001, -3.108222e-001, 1.708814e+000, -1.241215e-001, 4.416567e+000, 1.207369e+000, -1.178731e+000, -1.824314e-001, 8.266664e-001, 1.001614e+000, 3.024332e-001, 3.291998e-002, 4.178949e-001, 2.532397e+000, 2.014902e-001, -1.018913e+000, -2.016682e-001, 2.132865e+000, -3.323938e+000, -8.751654e+000, 1.240780e+000, -1.801214e-001, 6.145479e-001, 9.457932e-001, -1.101603e+000, -1.521834e-001, 1.348807e+000, 5.640453e+000, -2.695953e+000, -7.496627e-002, 1.719606e-001, 3.175091e+000, 5.968939e-001, // albedo 1, turbidity 4 -1.229694e+000, -3.167126e-001, -3.548352e+000, 3.846155e+000, -5.028022e-002, 5.061677e-001, 7.498335e-002, 3.626295e+000, 4.999424e-001, -1.436439e+000, -5.562909e-001, 8.010070e-001, 3.290243e-001, -1.385772e-001, 4.556269e-002, 2.571935e-002, 1.623385e+000, 5.222220e-001, -8.876360e-001, 5.717281e-002, 4.713905e-001, -1.668970e+000, -3.199243e-001, 2.050582e+000, -7.783980e-002, 6.117601e+000, 1.070445e+000, -1.235363e+000, -2.778190e-001, 1.577638e-001, 3.982457e+000, -2.266885e-002, -1.411004e+000, 5.570462e-001, 1.740426e-001, 2.747952e-001, -9.785264e-001, -1.458813e-001, 1.996989e+000, -7.517409e+000, -6.602487e+000, 2.387711e+000, -1.996484e-001, 2.112759e+000, 9.289256e-001, -1.117781e+000, -1.699302e-001, 1.214480e+000, 1.141083e+001, -3.253445e+000, -8.156284e-001, 2.248021e-001, 2.860500e+000, 6.151694e-001, // albedo 1, turbidity 5 -1.290523e+000, -3.813116e-001, -6.728796e-001, 1.007366e+000, -2.068030e-001, 4.422499e-001, 6.016254e-002, 3.218056e+000, 5.068822e-001, -1.614452e+000, -7.953309e-001, 5.977485e-001, 1.056365e+000, -8.402403e-001, 3.713919e-001, 3.164720e-002, -2.526630e-001, 4.072481e-001, -8.377211e-001, 2.276878e-001, -3.232539e-001, -2.390300e+000, 2.127070e+000, 7.169058e-001, -4.032313e-002, 9.072383e+000, 1.188019e+000, -1.226600e+000, -4.426177e-001, 6.370202e-001, 3.846913e+000, -1.128719e+001, 3.667721e-002, 5.000027e-001, -4.192432e+000, 2.376054e-001, -9.852235e-001, -5.890324e-002, 1.529937e+000, 4.301220e+000, -1.839775e+000, 8.993504e-001, -1.040866e-001, 4.636528e+000, 8.466710e-001, -1.118112e+000, -2.040213e-001, 1.203227e+000, 7.252102e+000, -4.515955e+000, -2.398231e-001, 2.375855e-001, 1.923160e+000, 6.645269e-001, // albedo 1, turbidity 6 -1.330626e+000, -4.272516e-001, -1.317682e+000, 1.650847e+000, -1.192771e-001, 4.904191e-001, 4.074827e-002, 3.015846e+000, 5.271835e-001, -1.711989e+000, -8.644776e-001, 4.057135e-001, 9.037139e-001, -3.100084e-001, 6.317697e-002, 1.065625e-001, 9.226240e-002, 3.022474e-001, -8.465894e-001, 1.652715e-001, -2.532361e-001, -2.422693e+000, 3.144841e-001, 1.839347e+000, -2.818162e-001, 7.856667e+000, 1.387977e+000, -1.192114e+000, -3.830569e-001, 5.124751e-001, 7.280034e+000, -2.610477e+000, -1.832768e+000, 9.101904e-001, -3.349116e+000, -7.313079e-002, -1.011026e+000, -1.061217e-001, 1.357854e+000, -1.496195e+001, -2.180975e+000, 2.484329e+000, -3.239225e-001, 3.899425e+000, 1.179264e+000, -1.106228e+000, -1.927917e-001, 1.179701e+000, 2.379834e+001, -4.870211e+000, -1.290713e+000, 2.854422e-001, 2.078973e+000, 5.128625e-001, // albedo 1, turbidity 7 -1.342815e+000, -4.571984e-001, -1.803521e+000, 2.229578e+000, -1.196587e-001, 5.694038e-001, 1.194687e-002, 2.950110e+000, 5.961719e-001, -1.937297e+000, -1.078823e+000, 2.178495e+000, -1.251900e+000, -3.577875e-001, 2.553915e-001, 8.081142e-002, -4.723152e-001, 1.174551e-001, -9.292675e-001, 1.125551e-001, -1.708569e+000, 1.832840e+000, 5.150525e-001, 9.287322e-001, -1.746780e-001, 7.793815e+000, 1.498832e+000, -1.058850e+000, -3.495292e-001, 1.135259e+000, -4.069374e+000, -9.727412e+000, -7.670653e-001, 7.550431e-001, -4.105064e+000, -5.149354e-002, -1.079472e+000, -1.399984e-001, 1.058148e+000, 1.392667e+001, -6.245343e-001, 1.192083e+000, -2.578858e-001, 4.030723e+000, 1.025069e+000, -1.093159e+000, -2.150433e-001, 1.210946e+000, 3.349246e+000, -4.030345e+000, -5.362971e-001, 2.886842e-001, 1.192375e+000, 6.363049e-001, // albedo 1, turbidity 8 -1.408172e+000, -5.491538e-001, -1.360219e+000, 1.738150e+000, -1.505117e-001, 6.030014e-001, -6.866289e-006, 2.656101e+000, 9.001849e-001, -2.171702e+000, -1.231851e+000, 1.860400e+000, 3.613146e-002, -7.300078e-001, 1.974371e-001, -5.351202e-003, -1.443434e-001, -3.779605e-001, -1.284657e+000, -1.935945e-001, -1.494185e+000, -2.070689e+000, 2.974020e-001, 8.048383e-001, 1.097715e-001, 6.907960e+000, 1.819367e+000, -8.288598e-001, -3.374917e-001, 1.029011e+000, 1.347088e+000, -7.655126e+000, -8.232335e-001, 3.722934e-001, -4.847675e+000, -1.864913e-001, -1.146031e+000, -1.480097e-001, 1.051391e+000, 8.396865e+000, -1.407010e+000, 1.240651e+000, -3.942068e-002, 3.291458e+000, 1.060212e+000, -1.069599e+000, -2.047532e-001, 9.437765e-001, 1.189879e+001, -4.026750e+000, -9.372092e-001, 2.463501e-001, 1.782902e+000, 6.235027e-001, // albedo 1, turbidity 9 -1.793508e+000, -8.986075e-001, -2.346395e+000, 2.775625e+000, -7.052213e-002, 5.349215e-001, -7.457456e-006, 1.901248e+000, 9.001358e-001, -1.629402e+000, -8.273410e-001, 2.270930e+000, -1.125114e+000, -3.562854e-001, 1.948044e-001, 1.703882e-003, 1.426305e+000, -3.737234e-001, -3.443431e+000, -1.686429e+000, -1.515036e+000, -6.941862e-001, 4.976814e-001, 1.144483e+000, -4.277285e-002, 3.662107e+000, 1.819972e+000, 3.138150e-001, 2.426714e-001, 7.717995e-001, 2.759520e+000, -7.216077e+000, -1.389093e+000, 5.332838e-001, -2.316313e+000, -2.636593e-001, -1.449802e+000, -4.017798e-001, 1.133688e+000, 2.114337e+000, 6.227965e-002, 1.378688e+000, -1.759313e-001, 9.446579e-001, 1.165017e+000, -1.049420e+000, -2.614006e-001, 9.473363e-001, 1.531288e+001, -4.714989e+000, -8.992715e-001, 2.423509e-001, 9.148027e-001, 5.650972e-001, // albedo 1, turbidity 10 -2.382332e+000, -1.290760e+000, -3.316114e+000, 3.587059e+000, -3.748522e-002, 4.468493e-001, -7.212198e-006, 1.789208e+000, 9.001267e-001, -1.333339e+000, -9.355999e-001, 3.281313e+000, -2.263103e+000, -2.499164e-001, 1.591742e-001, 8.117981e-003, 1.345396e+000, -2.689053e-001, -6.612658e+000, -2.809230e+000, -2.744061e+000, 1.005261e+000, 4.216309e-001, 1.055067e+000, -9.021558e-002, 2.940833e+000, 1.495270e+000, 1.251113e+000, 5.915517e-002, 1.142846e+000, -2.807371e-001, -5.335452e+000, -6.967012e-001, 5.129558e-001, -5.264483e-001, 1.137786e-001, -1.517768e+000, -5.807447e-001, 1.179477e+000, 1.252252e+001, -2.305973e+000, 2.184822e-001, -3.092917e-001, -1.524373e+000, 8.724218e-001, -1.037889e+000, -2.065780e-001, 6.479897e-001, 4.786848e-002, -2.348244e+000, -3.053490e-002, 4.059549e-001, 1.313102e+000, 6.713422e-001, }; static float datasetRad520[] = { // albedo 0, turbidity 1 1.459826e-002, 1.539451e-002, -1.848659e-003, 1.563602e-001, 6.773320e-002, 9.272923e-002, // albedo 0, turbidity 2 1.433599e-002, 1.641988e-002, -1.010719e-002, 1.752844e-001, 7.101618e-002, 9.423920e-002, // albedo 0, turbidity 3 1.361165e-002, 2.045058e-002, -3.003054e-002, 2.142268e-001, 6.624853e-002, 1.021088e-001, // albedo 0, turbidity 4 1.263245e-002, 2.450953e-002, -5.278634e-002, 2.554090e-001, 7.442617e-002, 1.093243e-001, // albedo 0, turbidity 5 1.161553e-002, 2.837614e-002, -7.218472e-002, 2.860706e-001, 8.559036e-002, 1.183292e-001, // albedo 0, turbidity 6 1.106384e-002, 3.079241e-002, -8.377247e-002, 3.007502e-001, 9.584072e-002, 1.242989e-001, // albedo 0, turbidity 7 1.036501e-002, 3.253539e-002, -9.274680e-002, 3.036297e-001, 1.249370e-001, 1.307019e-001, // albedo 0, turbidity 8 9.469294e-003, 3.287197e-002, -9.329500e-002, 2.773078e-001, 1.866053e-001, 1.366498e-001, // albedo 0, turbidity 9 8.599754e-003, 2.901873e-002, -7.532574e-002, 2.032418e-001, 2.837623e-001, 1.499765e-001, // albedo 0, turbidity 10 7.760808e-003, 1.977285e-002, -3.328752e-002, 7.084295e-002, 4.155148e-001, 1.708600e-001, // albedo 1, turbidity 1 1.597952e-002, 1.790201e-002, -1.839686e-003, 1.470389e-001, 1.698205e-001, 2.119268e-001, // albedo 1, turbidity 2 1.553599e-002, 1.969270e-002, -1.173079e-002, 1.677871e-001, 1.714108e-001, 2.173300e-001, // albedo 1, turbidity 3 1.489601e-002, 2.206336e-002, -2.576017e-002, 1.949160e-001, 1.781909e-001, 2.236776e-001, // albedo 1, turbidity 4 1.384558e-002, 2.528945e-002, -4.419483e-002, 2.249469e-001, 1.968802e-001, 2.312108e-001, // albedo 1, turbidity 5 1.299228e-002, 2.767429e-002, -5.793193e-002, 2.409692e-001, 2.215448e-001, 2.384850e-001, // albedo 1, turbidity 6 1.245635e-002, 2.874175e-002, -6.384005e-002, 2.429023e-001, 2.428387e-001, 2.418906e-001, // albedo 1, turbidity 7 1.170787e-002, 3.001101e-002, -6.977107e-002, 2.368382e-001, 2.775809e-001, 2.482129e-001, // albedo 1, turbidity 8 1.081211e-002, 2.854760e-002, -6.360294e-002, 1.948047e-001, 3.501631e-001, 2.490269e-001, // albedo 1, turbidity 9 9.903541e-003, 2.416012e-002, -4.342521e-002, 1.140965e-001, 4.468771e-001, 2.561579e-001, // albedo 1, turbidity 10 8.793464e-003, 1.518177e-002, -4.699154e-003, -9.107614e-003, 5.554550e-001, 2.692918e-001, }; static float dataset560[] = { // albedo 0, turbidity 1 -1.121223e+000, -1.710187e-001, -1.383038e+001, 1.475343e+001, -3.137953e-002, 1.035662e+000, 4.060064e-002, 5.222551e+000, 5.001051e-001, -1.172565e+000, -1.880874e-001, 7.283594e+000, -5.774643e+000, -9.051333e-002, 9.108126e-001, -1.565410e-002, 6.194404e+000, 4.688599e-001, -1.124108e+000, -3.082835e-001, -2.179926e-001, 1.330167e+000, -4.502254e-001, 1.470140e+000, 4.202392e-004, -4.724308e+000, 1.134678e+000, -1.079809e+000, -9.226814e-002, 1.465364e+000, 1.348856e+000, 4.357794e-001, 1.771543e+000, 8.121383e-003, 6.057395e+000, 2.462141e-001, -1.086667e+000, -2.709889e-001, 2.249152e+000, -3.177505e+000, -7.138130e+000, 1.112553e+000, -9.718434e-003, -2.392239e+000, 9.352768e-001, -1.071154e+000, -1.272150e-001, 1.644374e+000, 4.326598e+000, -2.244682e+000, 1.611051e+000, 7.835546e-003, 3.213282e+000, 6.580432e-001, // albedo 0, turbidity 2 -1.133883e+000, -1.835049e-001, -1.232301e+001, 1.307796e+001, -3.760123e-002, 1.051162e+000, 3.392954e-002, 5.319376e+000, 6.501601e-001, -1.116119e+000, -1.457114e-001, 5.436576e+000, -5.114276e+000, -7.178414e-002, 2.658168e-001, 1.603756e-001, 7.619379e+000, 3.112698e-001, -1.215552e+000, -3.391607e-001, 4.502377e-001, 1.281602e+000, -4.095778e-001, 2.374058e+000, -1.988430e-001, -3.809377e+000, 1.254846e+000, -9.657094e-001, 3.858547e-002, 3.324554e-001, 1.541740e+000, 6.029572e-001, 2.346414e-001, 3.902458e-001, 7.263050e+000, 1.353991e-001, -1.152042e+000, -3.155103e-001, 2.163244e+000, -5.230832e+000, -7.443608e+000, 2.247834e+000, -1.632216e-001, -1.725315e+000, 1.034709e+000, -1.051862e+000, -1.310458e-001, 1.554942e+000, 1.063510e+001, -3.558989e+000, 6.764257e-001, 1.428912e-001, 2.541641e+000, 5.000389e-001, // albedo 0, turbidity 3 -1.156925e+000, -2.104634e-001, -1.793090e+001, 1.817524e+001, -1.225514e-002, 6.518753e-001, 1.085708e-001, 4.947239e+000, 5.635117e-001, -1.183783e+000, -2.187288e-001, 5.860654e+000, -5.643960e+000, -4.453459e-002, 6.724995e-001, 1.698133e-002, 6.742131e+000, 6.353553e-001, -1.143101e+000, -2.644541e-001, 9.354577e-001, 9.256854e-001, -1.074845e-001, 1.663131e+000, 4.998918e-002, -2.049721e+000, 8.150826e-001, -1.021102e+000, 2.478746e-002, -1.367363e+000, -9.011684e-002, -5.001730e-001, 4.316685e-002, 3.952231e-001, 8.084754e+000, 5.380131e-001, -1.101145e+000, -2.731481e-001, 2.483816e+000, 3.581780e-001, 4.249615e-001, 2.284087e+000, -5.836688e-002, -1.651434e+000, 7.685430e-001, -1.073863e+000, -1.705854e-001, 1.169673e+000, -2.183705e-003, -5.007439e+000, 2.318154e-001, 2.738714e-001, 2.187327e+000, 6.676882e-001, // albedo 0, turbidity 4 -1.207581e+000, -2.653224e-001, -9.004497e+000, 8.985720e+000, -9.024461e-003, 4.273132e-001, 1.378091e-001, 4.307648e+000, 5.309421e-001, -1.278614e+000, -3.516334e-001, 2.489304e+000, -1.840089e+000, -6.293646e-002, 8.426903e-001, -7.266949e-002, 4.434869e+000, 7.077739e-001, -1.150333e+000, -2.033123e-001, 8.150312e-001, -7.926382e-001, -3.230951e-001, 1.291679e+000, 1.822329e-001, 1.619133e+000, 7.522432e-001, -1.002248e+000, -3.092969e-002, -1.092273e+000, 2.820671e+000, 4.504455e-001, -5.121048e-001, 4.229688e-001, 4.037073e+000, 5.843543e-001, -1.087962e+000, -2.434172e-001, 1.817322e+000, -6.031774e+000, -4.873903e+000, 2.094606e+000, 1.184743e-001, 2.293346e-001, 7.283940e-001, -1.072272e+000, -1.614715e-001, 8.337136e-001, 1.086866e+001, -3.373042e+000, 2.260332e-002, 2.622468e-001, 2.470766e+000, 7.078601e-001, // albedo 0, turbidity 5 -1.263850e+000, -3.278851e-001, -5.336400e+000, 5.102832e+000, 2.070020e-003, 3.605369e-001, 1.633426e-001, 3.790121e+000, 4.999503e-001, -1.507623e+000, -6.465694e-001, -2.983753e+000, 4.212027e+000, -5.868795e-002, 3.852488e-001, -7.222995e-002, 1.042808e+000, 6.632120e-001, -1.041397e+000, 6.326589e-002, 3.860471e+000, -5.579882e+000, -1.730201e-001, 2.303753e+000, 6.102393e-002, 7.287763e+000, 8.916057e-001, -1.049861e+000, -2.836044e-001, -2.302537e+000, 6.724969e+000, 4.373598e-001, -2.422514e+000, 6.952438e-001, -2.633600e+000, 4.070954e-001, -1.054117e+000, -1.206625e-001, 1.764625e+000, -9.467716e+000, -3.436987e+000, 3.394707e+000, -8.149683e-002, 3.485918e+000, 8.515716e-001, -1.072517e+000, -1.574135e-001, 2.214599e-001, 1.331766e+001, -3.915381e+000, -1.229973e+000, 6.267275e-001, 2.923262e+000, 6.516824e-001, // albedo 0, turbidity 6 -1.293503e+000, -3.676147e-001, -1.323095e+001, 1.301713e+001, -3.471894e-004, 3.957986e-001, 1.317480e-001, 3.616827e+000, 4.998510e-001, -1.757697e+000, -8.202513e-001, 2.560133e+000, -1.337734e+000, -3.413795e-002, 5.633043e-001, -4.355758e-002, 7.324869e-001, 5.728008e-001, -8.814599e-001, 9.828960e-002, -2.701428e-001, -1.298657e+000, -6.721423e-002, 1.581675e+000, 4.095024e-002, 6.548913e+000, 9.726866e-001, -1.125663e+000, -2.625873e-001, -2.797592e-001, 2.848739e+000, -3.363778e-002, -1.672768e+000, 7.349952e-001, -1.708628e+000, 3.557813e-001, -1.044841e+000, -1.712889e-001, 7.091708e-001, -4.275119e+000, -7.565130e-001, 2.483873e+000, -7.781321e-002, 2.667776e+000, 8.709126e-001, -1.067360e+000, -1.543712e-001, 3.884866e-001, 6.915851e+000, -4.250734e+000, -6.525729e-001, 6.368377e-001, 2.671865e+000, 6.566986e-001, // albedo 0, turbidity 7 -1.360356e+000, -4.336026e-001, -1.442967e+001, 1.428579e+001, -3.990325e-003, 4.600126e-001, 1.023159e-001, 3.367805e+000, 4.999150e-001, -2.054147e+000, -1.064745e+000, -7.857491e-001, 2.214734e+000, -3.764113e-002, 8.504761e-001, -4.222958e-002, 1.091377e-001, 4.732161e-001, -8.953952e-001, 1.048085e-001, 1.481293e+000, -4.223012e+000, -4.164160e-002, 5.999023e-001, 6.310005e-002, 7.156883e+000, 1.066682e+000, -1.030251e+000, -2.777709e-001, -8.361086e-001, 5.611154e+000, 1.861240e-001, -5.823197e-001, 6.716210e-001, -3.269717e+000, 2.922029e-001, -1.095631e+000, -1.966849e-001, 6.300566e-001, -7.129591e+000, -7.351951e-001, 1.400340e+000, -6.997516e-003, 2.879018e+000, 8.879337e-001, -1.052935e+000, -1.551958e-001, 2.334578e-001, 1.040948e+001, -4.426381e+000, -3.477323e-001, 6.257070e-001, 2.451148e+000, 6.570737e-001, // albedo 0, turbidity 8 -1.382656e+000, -4.830539e-001, -1.107403e+001, 1.127854e+001, -2.723641e-002, 8.478005e-001, 2.907652e-003, 3.290364e+000, 7.398950e-001, -2.230895e+000, -1.163446e+000, -1.001991e+001, 1.125340e+001, -3.233871e-002, 3.041577e-001, 3.870458e-003, 3.463879e-001, -8.829082e-002, -1.489234e+000, -3.402035e-001, 2.948409e+000, -8.098077e+000, 9.078299e-002, -3.179835e-001, 4.730321e-001, 6.765707e+000, 1.440217e+000, -6.206234e-001, -1.701007e-001, -7.346357e-002, 9.350033e+000, 1.548964e-001, 1.313206e+000, -1.479143e-001, -5.119165e+000, 1.854277e-001, -1.226372e+000, -2.128299e-001, -1.643093e-001, -9.382334e+000, -4.857784e-001, -1.374948e-001, 5.877245e-001, 3.862307e+000, 8.700125e-001, -1.030598e+000, -1.931668e-001, 3.691403e-001, 1.066393e+001, -4.244968e+000, -5.872571e-002, 4.193140e-001, 1.461878e+000, 6.699478e-001, // albedo 0, turbidity 9 -1.606656e+000, -7.140209e-001, -1.149565e+001, 1.168427e+001, -2.245577e-002, 7.718953e-001, -8.349882e-006, 2.654449e+000, 9.001224e-001, -2.100494e+000, -1.013602e+000, -1.638934e+001, 1.729185e+001, -1.580924e-002, 5.038208e-002, -1.628735e-002, 1.762584e+000, -3.121794e-001, -3.228292e+000, -1.459508e+000, 7.424519e+000, -1.194272e+001, 4.931054e-002, 6.493074e-001, 3.590561e-001, 4.068321e+000, 1.613039e+000, 1.278814e-001, 4.010913e-002, -2.185675e+000, 1.164548e+001, 2.706306e-002, 1.632886e-001, -1.090111e-002, -3.342580e+000, 1.916992e-002, -1.400278e+000, -2.825658e-001, 4.168149e-001, -1.195909e+001, -1.122968e-002, 1.863328e-001, 4.263033e-001, 2.270053e+000, 9.748449e-001, -1.017511e+000, -2.884028e-001, 3.544996e-001, 1.535118e+001, -5.009184e+000, 1.511064e-001, 2.916578e-001, 7.889658e-001, 6.294910e-001, // albedo 0, turbidity 10 -2.031136e+000, -1.076357e+000, -8.660773e+000, 8.800317e+000, -2.370842e-002, 5.736027e-001, -8.441313e-006, 2.248669e+000, 9.001280e-001, -1.270967e+000, -7.828844e-001, -1.198232e+001, 1.262753e+001, -1.509989e-002, 1.663438e-001, 2.440939e-004, 2.068640e+000, -2.521574e-001, -6.600872e+000, -2.689874e+000, 6.453928e+000, -9.592747e+000, -3.551170e-002, 1.325662e+000, -1.894375e-002, 3.506163e+000, 1.469724e+000, 7.961323e-001, -1.989144e-001, -2.685238e+000, 1.034230e+001, 2.076702e-001, -7.692350e-001, 6.184894e-001, -1.969413e+000, 3.842922e-002, -1.459073e+000, -4.964034e-001, 1.060127e+000, -1.277712e+001, -9.634553e-001, 5.610879e-001, -2.034286e-001, 3.525910e-001, 1.003048e+000, -1.021565e+000, -2.553022e-001, 6.367571e-002, 2.028825e+001, -4.623219e+000, -2.400428e-002, 4.251423e-001, 9.640897e-001, 6.080298e-001, // albedo 1, turbidity 1 -1.121224e+000, -1.710171e-001, -1.383038e+001, 1.475343e+001, -3.137812e-002, 1.035662e+000, 4.060006e-002, 5.222551e+000, 5.001051e-001, -1.172565e+000, -1.880857e-001, 7.283595e+000, -5.774643e+000, -9.051285e-002, 9.108124e-001, -1.565627e-002, 6.194404e+000, 4.688599e-001, -1.124109e+000, -3.082816e-001, -2.179926e-001, 1.330167e+000, -4.502252e-001, 1.470140e+000, 4.158616e-004, -4.724308e+000, 1.134678e+000, -1.079810e+000, -9.226583e-002, 1.465364e+000, 1.348856e+000, 4.357794e-001, 1.771543e+000, 8.115381e-003, 6.057395e+000, 2.462140e-001, -1.086668e+000, -2.709863e-001, 2.249153e+000, -3.177505e+000, -7.138130e+000, 1.112553e+000, -9.724210e-003, -2.392239e+000, 9.352768e-001, -1.071158e+000, -1.272123e-001, 1.644374e+000, 4.326598e+000, -2.244682e+000, 1.611051e+000, 7.831866e-003, 3.213282e+000, 6.580432e-001, // albedo 1, turbidity 2 -1.125449e+000, -1.733403e-001, -1.228038e+001, 1.311695e+001, -3.541409e-002, 1.005494e+000, 4.147852e-002, 5.316886e+000, 6.051699e-001, -1.101273e+000, -1.422106e-001, 5.484715e+000, -5.089835e+000, -6.655928e-002, 2.076815e-001, 1.633101e-001, 7.624535e+000, 3.044941e-001, -1.213425e+000, -3.085010e-001, 5.550585e-001, 1.302798e+000, -3.946488e-001, 2.285152e+000, -1.925101e-001, -3.790065e+000, 1.263207e+000, -9.610579e-001, 9.458093e-003, 5.293256e-001, 1.553214e+000, 6.053752e-001, 1.172267e-001, 3.674690e-001, 7.305350e+000, 1.509544e-001, -1.119731e+000, -2.765693e-001, 2.433951e+000, -5.229810e+000, -7.449777e+000, 2.123304e+000, -2.242917e-001, -1.669115e+000, 1.041008e+000, -1.094324e+000, -1.418743e-001, 1.836224e+000, 1.063054e+001, -3.561209e+000, 5.916534e-001, 9.296571e-002, 2.600060e+000, 4.999316e-001, // albedo 1, turbidity 3 -1.155818e+000, -2.162981e-001, -2.560068e+001, 2.636088e+001, -1.382944e-002, 8.101983e-001, 4.709210e-002, 4.301909e+000, 6.416958e-001, -1.171460e+000, -1.866443e-001, 8.497645e+000, -8.396229e+000, -3.345417e-002, 2.960022e-001, 7.985279e-002, 7.420544e+000, 5.552152e-001, -1.114385e+000, -2.963805e-001, 5.955009e-002, 2.320529e+000, -7.649266e-002, 2.277940e+000, -5.942479e-002, -4.040964e+000, 9.588558e-001, -1.070647e+000, 4.194546e-002, -5.701942e-001, -1.001278e+000, -3.389615e-001, -8.559533e-001, 5.070784e-001, 9.805560e+000, 3.529747e-001, -1.057912e+000, -2.733753e-001, 3.080618e+000, 7.477366e-001, 3.484876e-001, 2.214994e+000, -2.597625e-001, -2.842961e+000, 9.178917e-001, -1.105636e+000, -1.815423e-001, 1.651373e+000, -2.553941e-003, -5.008441e+000, -6.378055e-001, 2.370503e-001, 1.890656e+000, 6.018255e-001, // albedo 1, turbidity 4 -1.194221e+000, -2.570801e-001, -8.919095e+000, 9.380192e+000, -2.650470e-002, 6.233645e-001, 6.663964e-002, 4.027438e+000, 6.125383e-001, -1.308216e+000, -3.781794e-001, 2.369107e+000, -1.977066e+000, -4.079773e-002, 1.443960e-001, 8.206719e-002, 3.465933e+000, 5.442867e-001, -1.048459e+000, -1.617720e-001, 1.015136e+000, -2.989579e-001, -2.764989e-001, 2.427990e+000, -1.147612e-001, 1.522921e+000, 1.041410e+000, -1.105796e+000, -4.826962e-002, -8.419705e-001, 3.285981e+000, 7.975109e-001, -1.954456e+000, 7.424696e-001, 4.604902e+000, 2.602059e-001, -1.033856e+000, -2.507382e-001, 2.882633e+000, -8.250912e+000, -6.878129e+000, 2.948966e+000, -2.850302e-001, -8.253849e-001, 9.844934e-001, -1.125219e+000, -1.879003e-001, 1.474838e+000, 1.453266e+001, -3.271910e+000, -1.231579e+000, 2.397524e-001, 1.654932e+000, 5.625696e-001, // albedo 1, turbidity 5 -1.246640e+000, -3.202274e-001, -6.355032e+000, 6.364143e+000, 9.028376e-004, 3.146975e-001, 1.550718e-001, 3.413749e+000, 4.999065e-001, -1.477471e+000, -5.819223e-001, 1.329471e+000, -2.694229e-001, -4.575905e-002, 5.087866e-001, -6.857139e-002, 1.810092e+000, 6.318693e-001, -1.046136e+000, -6.763679e-002, 6.725076e-001, -1.036786e+000, -3.192799e-001, 1.724205e+000, 6.468388e-002, 3.953855e+000, 9.417528e-001, -1.033910e+000, -1.295544e-001, -4.551294e-001, 2.659205e+000, 8.887235e-001, -1.733153e+000, 6.540117e-001, 8.046523e-001, 3.597443e-001, -1.094530e+000, -2.282012e-001, 2.298267e+000, -5.184881e+000, -6.122309e+000, 2.590799e+000, -1.618707e-001, 1.116033e+000, 8.867666e-001, -1.095556e+000, -1.807112e-001, 1.406193e+000, 8.120385e+000, -3.058239e+000, -1.121150e+000, 2.933606e-001, 1.488339e+000, 6.374827e-001, // albedo 1, turbidity 6 -1.270123e+000, -3.552595e-001, -8.975893e+000, 9.110080e+000, -3.388207e-003, 3.559109e-001, 1.201097e-001, 3.109904e+000, 4.998957e-001, -1.663376e+000, -7.846840e-001, 6.951405e-001, 3.139107e-001, -2.448004e-002, 3.572505e-001, 1.453572e-002, 6.307761e-001, 5.142914e-001, -9.518772e-001, 7.764573e-002, 1.247094e+000, -2.224855e+000, -1.195310e-001, 1.709581e+000, -8.836329e-002, 5.688916e+000, 1.113629e+000, -1.087154e+000, -2.665646e-001, -8.624251e-001, 4.536060e+000, 4.180650e-001, -1.629798e+000, 8.479560e-001, -1.293696e+000, 1.869693e-001, -1.064826e+000, -1.599892e-001, 2.285337e+000, -8.584887e+000, -3.074560e+000, 2.139459e+000, -2.592372e-001, 1.937577e+000, 9.957954e-001, -1.099622e+000, -1.849797e-001, 1.193609e+000, 1.416481e+001, -5.009527e+000, -8.592493e-001, 3.485606e-001, 1.884203e+000, 6.097274e-001, // albedo 1, turbidity 7 -1.344841e+000, -4.339942e-001, -9.193112e+000, 9.385864e+000, -9.742818e-003, 4.812040e-001, 7.690647e-002, 2.843801e+000, 5.228047e-001, -1.975928e+000, -1.042040e+000, 9.695714e-001, 3.718000e-001, -3.334078e-002, 1.333620e-001, 8.180282e-002, -1.652429e-001, 3.267010e-001, -8.651864e-001, 1.288722e-001, 6.811456e-001, -3.282787e+000, -9.074685e-002, 1.894059e+000, -1.849744e-001, 6.610614e+000, 1.322978e+000, -1.103780e+000, -3.279618e-001, -4.193802e-001, 7.331165e+000, 6.529659e-001, -2.227297e+000, 9.625482e-001, -3.348971e+000, -7.261722e-003, -1.055963e+000, -1.527328e-001, 1.786114e+000, -1.367578e+001, -3.450729e+000, 2.641691e+000, -3.229222e-001, 2.800131e+000, 1.129409e+000, -1.111541e+000, -2.123518e-001, 1.286159e+000, 2.297563e+001, -4.591526e+000, -1.374672e+000, 3.462811e-001, 1.071127e+000, 5.498514e-001, // albedo 1, turbidity 8 -1.387544e+000, -4.964558e-001, -9.744778e+000, 1.014533e+001, -2.463089e-002, 7.188705e-001, 3.919951e-003, 2.760792e+000, 7.369418e-001, -2.206536e+000, -1.191342e+000, -2.244384e+000, 3.629413e+000, -3.601610e-002, 7.725349e-002, 5.357588e-002, -2.692147e-001, -1.142476e-001, -1.358286e+000, -2.268740e-001, 9.805731e-001, -5.163195e+000, -8.589000e-003, 7.697565e-001, 2.198750e-001, 7.029301e+000, 1.567170e+000, -7.167767e-001, -2.969978e-001, 2.300987e-001, 7.956088e+000, 6.339728e-001, -6.195374e-001, 2.502844e-001, -6.307569e+000, -2.208822e-002, -1.210525e+000, -1.245541e-001, 9.742409e-001, -9.705683e+000, -1.658899e+000, 1.365829e+000, 2.003500e-001, 4.400174e+000, 1.042345e+000, -1.061524e+000, -2.323500e-001, 1.284880e+000, 1.294836e+001, -5.011732e+000, -9.141086e-001, 2.723804e-001, 6.225528e-001, 6.030977e-001, // albedo 1, turbidity 9 -1.548946e+000, -6.802676e-001, -1.274231e+001, 1.312954e+001, -1.834225e-002, 7.051580e-001, -8.330446e-006, 2.320435e+000, 9.001244e-001, -1.867128e+000, -9.670210e-001, -6.847422e+000, 7.952765e+000, -1.985986e-002, 1.690548e-002, -1.176902e-002, 8.988469e-001, -3.242269e-001, -3.470633e+000, -1.555121e+000, 2.684966e+000, -5.964736e+000, -5.524158e-003, 1.187089e+000, 2.552534e-001, 4.394076e+000, 1.656399e+000, 4.095837e-001, 1.440005e-001, -5.602190e-001, 7.110869e+000, 2.313366e-001, -1.373206e+000, 1.973962e-001, -4.112998e+000, -5.877027e-002, -1.540633e+000, -3.264234e-001, 1.072405e+000, -7.205546e+000, -5.125251e-001, 2.009905e+000, 1.531985e-001, 2.113439e+000, 1.042547e+000, -1.013330e+000, -2.663837e-001, 1.168934e+000, 9.315778e+000, -4.320502e+000, -1.303393e+000, 2.825872e-001, 2.365015e-001, 5.993344e-001, // albedo 1, turbidity 10 -2.055426e+000, -1.093229e+000, -3.487182e+000, 3.753855e+000, -4.639837e-002, 5.797714e-001, -8.056992e-006, 1.916262e+000, 9.001298e-001, -1.643864e+000, -9.676934e-001, -1.147133e+001, 1.253880e+001, 2.347351e-002, -1.602964e-002, 4.481579e-003, 1.373645e+000, -2.884929e-001, -6.156336e+000, -2.568735e+000, 6.499533e+000, -9.136753e+000, -1.751599e-001, 1.876960e+000, -7.959051e-002, 3.074951e+000, 1.579874e+000, 7.378485e-001, -2.614544e-001, -2.861777e+000, 9.518947e+000, 5.033808e-001, -1.844722e+000, 6.855962e-001, -1.497263e+000, -9.081643e-002, -1.341940e+000, -3.847183e-001, 2.045437e+000, -1.179073e+001, -1.532773e+000, 1.639939e+000, -2.668175e-001, -8.401827e-001, 1.083722e+000, -1.086126e+000, -2.811402e-001, 7.554239e-001, 1.862181e+001, -4.343385e+000, -8.611011e-001, 3.146558e-001, 7.022438e-001, 5.872694e-001, }; static float datasetRad560[] = { // albedo 0, turbidity 1 1.518543e-002, 1.176421e-002, 1.736355e-002, 1.085640e-001, 4.928107e-002, 6.789277e-002, // albedo 0, turbidity 2 1.482072e-002, 1.335627e-002, 7.685462e-003, 1.336625e-001, 4.842644e-002, 7.083679e-002, // albedo 0, turbidity 3 1.406436e-002, 1.604888e-002, -9.000273e-003, 1.735923e-001, 4.526955e-002, 7.742648e-002, // albedo 0, turbidity 4 1.296165e-002, 2.074811e-002, -3.672731e-002, 2.310227e-001, 4.272776e-002, 8.807197e-002, // albedo 0, turbidity 5 1.185836e-002, 2.557920e-002, -6.240734e-002, 2.766326e-001, 4.714655e-002, 9.809189e-002, // albedo 0, turbidity 6 1.107469e-002, 2.825097e-002, -7.618392e-002, 2.978619e-001, 5.429803e-002, 1.044545e-001, // albedo 0, turbidity 7 1.030435e-002, 3.060206e-002, -8.858708e-002, 3.072427e-001, 8.473378e-002, 1.077059e-001, // albedo 0, turbidity 8 9.197751e-003, 3.269422e-002, -9.785581e-002, 2.997964e-001, 1.328366e-001, 1.192367e-001, // albedo 0, turbidity 9 8.191103e-003, 3.038883e-002, -8.623921e-002, 2.362785e-001, 2.259917e-001, 1.331360e-001, // albedo 0, turbidity 10 7.275920e-003, 2.128876e-002, -4.464890e-002, 1.022425e-001, 3.640615e-001, 1.521652e-001, // albedo 1, turbidity 1 1.623600e-002, 1.386631e-002, 1.790676e-002, 9.999420e-002, 1.334051e-001, 1.524062e-001, // albedo 1, turbidity 2 1.580346e-002, 1.594123e-002, 5.795411e-003, 1.311774e-001, 1.256680e-001, 1.627637e-001, // albedo 1, turbidity 3 1.508292e-002, 1.888592e-002, -1.186753e-002, 1.719109e-001, 1.235706e-001, 1.739866e-001, // albedo 1, turbidity 4 1.385430e-002, 2.238574e-002, -3.390048e-002, 2.155912e-001, 1.366535e-001, 1.840316e-001, // albedo 1, turbidity 5 1.289448e-002, 2.572803e-002, -5.406854e-002, 2.481650e-001, 1.539663e-001, 1.943329e-001, // albedo 1, turbidity 6 1.229427e-002, 2.715903e-002, -6.212273e-002, 2.543339e-001, 1.780617e-001, 1.961306e-001, // albedo 1, turbidity 7 1.142362e-002, 2.928317e-002, -7.246911e-002, 2.573202e-001, 2.123595e-001, 2.030761e-001, // albedo 1, turbidity 8 1.030850e-002, 2.979460e-002, -7.568370e-002, 2.359473e-001, 2.693691e-001, 2.158786e-001, // albedo 1, turbidity 9 9.256414e-003, 2.622384e-002, -5.910990e-002, 1.602850e-001, 3.679614e-001, 2.281095e-001, // albedo 1, turbidity 10 8.220083e-003, 1.701079e-002, -1.768254e-002, 2.593519e-002, 4.977242e-001, 2.394514e-001, }; static float dataset600[] = { // albedo 0, turbidity 1 -1.120756e+000, -1.756050e-001, -3.557732e+000, 5.117996e+000, -1.042966e-001, 1.269364e+000, 1.318863e-002, 3.718263e+000, 5.393663e-001, -1.170564e+000, -1.845108e-001, 1.081952e+000, 1.330153e+000, -2.486698e-001, 7.864551e-001, 3.710973e-003, 4.567181e+000, 4.998408e-001, -1.036563e+000, -2.605284e-001, 3.803752e+000, -3.585400e+000, -9.070196e-001, 2.380958e+000, -1.320680e-002, -4.210738e+000, 1.085121e+000, -1.193752e+000, -1.236757e-001, -2.036484e-001, 4.137855e+000, 1.566414e+000, 8.510547e-001, 1.653213e-002, 5.488784e+000, 2.335910e-001, -9.950781e-001, -2.103974e-001, 2.992004e+000, -4.050491e+000, -6.354208e+000, 2.250652e+000, -1.548511e-002, -1.876535e+000, 9.733518e-001, -1.106820e+000, -1.804412e-001, 1.960315e+000, 3.667064e+000, -2.460232e+000, 9.553453e-001, 1.238019e-002, 1.307691e+000, 5.564710e-001, // albedo 0, turbidity 2 -1.112834e+000, -1.534956e-001, -4.968015e+000, 6.079068e+000, -8.917942e-002, 1.167545e+000, 5.945633e-002, 5.295468e+000, 6.272123e-001, -1.160910e+000, -1.640745e-001, 7.416807e-001, -2.894668e-001, -8.983936e-002, 3.778575e-002, 2.133300e-001, 6.390765e+000, 3.592393e-001, -1.054872e+000, -2.642844e-001, 4.375802e+000, -1.434824e+000, -7.521504e-001, 3.669027e+000, -2.992879e-001, -5.159653e+000, 1.284643e+000, -1.147542e+000, 1.011446e-002, -2.308529e+000, 1.587994e+000, 1.226957e+000, -1.328837e+000, 5.996235e-001, 1.004278e+001, 5.212352e-002, -1.023945e+000, -2.867193e-001, 3.733660e+000, -2.572157e+000, -7.749675e+000, 3.927326e+000, -3.230666e-001, -4.260418e+000, 1.091761e+000, -1.100815e+000, -1.590204e-001, 1.413330e+000, 6.546557e+000, -2.407235e+000, -2.678587e-001, 2.367155e-001, 2.242596e+000, 5.273419e-001, // albedo 0, turbidity 3 -1.137271e+000, -1.838447e-001, -2.268731e+000, 3.013967e+000, -1.471213e-001, 9.047947e-001, 8.086373e-002, 4.834215e+000, 6.545047e-001, -1.136415e+000, -1.536696e-001, -1.821062e+000, 1.756804e+000, -9.313635e-002, 2.208938e-001, 2.021774e-001, 7.289664e+000, 4.997813e-001, -1.173214e+000, -3.202233e-001, 4.868221e+000, -2.485467e+000, -7.693969e-001, 3.027854e+000, -1.745243e-001, -4.896365e+000, 1.014186e+000, -1.021346e+000, 7.262425e-002, -2.940205e+000, 3.357462e+000, 1.150486e+000, -1.710207e+000, 7.381637e-001, 9.857427e+000, 3.036725e-001, -1.082107e+000, -2.721172e-001, 3.071962e+000, -7.058088e+000, -5.103538e+000, 3.852302e+000, -2.281911e-001, -2.565665e+000, 9.669584e-001, -1.076296e+000, -1.655466e-001, 1.323765e+000, 1.496892e+001, -3.773928e+000, -5.211752e-001, 2.583009e-001, 1.797906e+000, 5.888323e-001, // albedo 0, turbidity 4 -1.180432e+000, -2.327942e-001, -7.152650e-001, 1.078120e+000, -2.935788e-001, 6.977295e-001, 1.118530e-001, 4.270574e+000, 6.241267e-001, -1.260549e+000, -2.865438e-001, -2.736770e+000, 2.720969e+000, 1.291231e-001, 4.072562e-001, 4.510932e-002, 5.412464e+000, 6.781695e-001, -1.119712e+000, -2.521160e-001, 4.860527e+000, -1.950603e+000, -1.598805e+000, 2.556718e+000, 2.462723e-002, -2.059404e+000, 8.000995e-001, -1.056386e+000, 2.018258e-002, -3.728955e+000, 1.022270e+000, 1.722210e+000, -2.691554e+000, 8.329883e-001, 6.982450e+000, 4.746778e-001, -1.044811e+000, -2.531291e-001, 3.102204e+000, -3.662632e+000, -5.609358e+000, 4.574385e+000, -2.173600e-001, -1.646110e+000, 8.593305e-001, -1.090027e+000, -1.699462e-001, 7.118896e-001, 1.287572e+001, -2.747429e+000, -1.706223e+000, 4.483382e-001, 2.029605e+000, 6.366599e-001, // albedo 0, turbidity 5 -1.232266e+000, -2.905676e-001, -4.158347e-001, 5.285264e-001, -3.064312e-001, 5.569478e-001, 1.195289e-001, 3.788091e+000, 5.970680e-001, -1.451205e+000, -5.169964e-001, -2.018331e-001, 1.499655e+000, -1.575963e+000, 2.761459e-001, 5.184923e-002, 2.301119e+000, 6.177771e-001, -1.059832e+000, -7.658003e-002, 6.456894e-001, -4.398594e+000, 5.369604e+000, 2.121235e+000, 3.210869e-002, 3.542794e+000, 9.114953e-001, -1.040966e+000, -1.269405e-001, -3.751056e-001, 1.229395e+001, -1.977090e+001, -2.458488e+000, 7.711932e-001, 8.079227e-001, 3.865305e-001, -1.061923e+000, -1.981907e-001, 1.089854e+000, -3.414507e+000, 8.032592e+000, 3.459965e+000, -1.253984e-001, 1.188198e+000, 8.639277e-001, -1.070607e+000, -1.627049e-001, 7.012071e-001, 2.138780e+000, -5.006595e+000, -1.096698e+000, 6.658771e-001, 1.999430e+000, 6.557122e-001, // albedo 0, turbidity 6 -1.280090e+000, -3.357179e-001, -9.337154e-002, -5.075553e-003, -3.096112e+000, 4.001499e-001, 1.489818e-001, 3.515349e+000, 5.571477e-001, -1.648190e+000, -7.024227e-001, -2.925797e-002, 1.658094e+000, 4.229924e+000, 3.502683e-001, 3.180108e-002, 1.430955e+000, 5.739552e-001, -9.589189e-001, 2.559557e-002, 2.192186e-001, -5.276316e+000, -4.153922e+000, 1.855574e+000, 3.052317e-002, 4.323694e+000, 9.839497e-001, -1.076589e+000, -1.936109e-001, -4.162615e-001, 1.202609e+001, -9.327314e+000, -2.326508e+000, 7.983253e-001, 2.100845e-001, 3.135170e-001, -1.049437e+000, -1.694738e-001, 1.062110e+000, 5.575299e+000, 4.846701e-001, 3.089474e+000, -1.584214e-001, 1.369457e+000, 8.995377e-001, -1.069986e+000, -1.830827e-001, 5.006422e-001, -3.063835e-003, -2.768514e+000, -1.258027e+000, 6.679955e-001, 1.840288e+000, 6.498676e-001, // albedo 0, turbidity 7 -1.328971e+000, -3.853230e-001, -2.343098e-001, -6.505414e-003, -4.859294e+000, 3.752993e-001, 1.670718e-001, 3.474961e+000, 4.998573e-001, -2.023062e+000, -1.023840e+000, 4.308501e-001, 1.473146e+000, 6.112105e+000, 5.767265e-001, -3.107377e-002, 7.748759e-002, 5.016978e-001, -8.575747e-001, 1.580212e-001, -7.365004e-001, -4.007773e+000, -4.051657e+000, 8.889282e-001, 1.978413e-001, 6.282132e+000, 1.063928e+000, -1.073428e+000, -3.228761e-001, 4.793085e-001, 5.455778e+000, -7.830559e+000, -9.794478e-001, 5.370543e-001, -3.022750e+000, 2.818600e-001, -1.057120e+000, -1.266841e-001, 4.555368e-001, 1.201278e+001, -9.293773e-001, 1.439595e+000, 3.262182e-002, 2.890364e+000, 8.821540e-001, -1.060079e+000, -1.816680e-001, 3.541107e-001, -2.642196e-003, -2.588317e+000, -5.640010e-001, 6.643994e-001, 1.673077e+000, 6.658333e-001, // albedo 0, turbidity 8 -1.395409e+000, -4.658947e-001, -4.370597e-001, 1.342039e+000, -1.108674e+000, 6.439316e-001, 1.355229e-002, 3.241153e+000, 6.696079e-001, -2.418167e+000, -1.266061e+000, 3.287382e-001, -1.486721e+000, -6.770180e-001, 2.439008e-001, 1.703788e-001, 1.664559e-002, -6.330217e-003, -1.221212e+000, -1.072571e-001, -1.655914e+000, 2.659047e+000, 6.830770e+000, 4.984792e-001, 2.538158e-001, 6.500660e+000, 1.486576e+000, -7.182331e-001, -2.519055e-001, 1.641261e+000, -5.500375e+000, -1.253143e+001, -1.542672e-001, 1.741161e-001, -4.907497e+000, 7.968864e-002, -1.207117e+000, -1.635739e-001, -3.256308e-001, 1.409033e+001, 1.107883e+000, 7.217342e-001, 3.158860e-001, 3.537550e+000, 9.389751e-001, -1.015927e+000, -1.890895e-001, 4.180376e-001, 9.528535e+000, -4.073979e+000, -8.713087e-001, 4.899379e-001, 1.277831e+000, 6.519818e-001, // albedo 0, turbidity 9 -1.551242e+000, -6.400568e-001, -3.673011e-001, 1.623228e+000, -1.482572e+000, 5.625944e-001, -1.130924e-005, 2.792007e+000, 9.000924e-001, -1.971409e+000, -9.004995e-001, -2.337582e-001, -1.511905e+000, 6.645432e-002, 6.149087e-001, -3.184094e-002, 2.026210e+000, -2.799058e-001, -3.464015e+000, -1.604654e+000, -1.514516e+000, 2.768075e+000, 4.084166e+000, -4.287171e-001, 7.112107e-001, 2.896460e+000, 1.502031e+000, 4.069978e-001, 2.775394e-001, 1.525761e+000, -5.264056e+000, -7.108445e+000, 1.134996e+000, -4.122625e-001, -2.558151e+000, 2.009854e-001, -1.504217e+000, -3.618442e-001, -2.305374e-001, 1.434481e+001, -1.713254e+000, -5.670708e-001, 5.206848e-001, 1.704009e+000, 8.447497e-001, -9.753124e-001, -2.080868e-001, 2.450141e-001, -3.535206e-003, -2.121317e+000, -1.425634e-001, 4.670084e-001, 1.027875e+000, 6.735543e-001, // albedo 0, turbidity 10 -2.027207e+000, -1.003600e+000, -3.813114e-001, 9.357907e-001, -1.031886e+000, 5.523389e-001, -8.883940e-006, 2.339379e+000, 9.001659e-001, -1.506235e+000, -7.795241e-001, -4.313309e-001, 9.124054e-001, -7.484352e-001, -8.417756e-002, -1.426561e-002, 2.571178e+000, -2.504298e-001, -6.482777e+000, -2.700075e+000, -1.556622e+000, -2.978497e+000, 4.623255e+000, 1.953868e+000, 3.113178e-001, 2.311303e+000, 1.451021e+000, 9.357272e-001, -1.066566e-001, 1.476763e+000, 6.889797e+000, -1.038036e+001, -2.094856e+000, 1.330069e-001, -1.446404e+000, 1.121890e-001, -1.398229e+000, -3.167573e-001, -1.276866e-001, 1.239440e+000, 1.816678e+000, 1.586775e+000, 8.043533e-002, 3.219192e-001, 9.200620e-001, -1.070734e+000, -3.636167e-001, 2.426490e-001, 8.282765e+000, -3.588710e+000, -9.105402e-001, 3.760276e-001, 5.756358e-001, 6.508161e-001, // albedo 1, turbidity 1 -1.120757e+000, -1.756034e-001, -3.557732e+000, 5.117996e+000, -1.042960e-001, 1.269364e+000, 1.318834e-002, 3.718263e+000, 5.393663e-001, -1.170565e+000, -1.845093e-001, 1.081952e+000, 1.330153e+000, -2.486697e-001, 7.864550e-001, 3.709405e-003, 4.567181e+000, 4.998408e-001, -1.036564e+000, -2.605265e-001, 3.803752e+000, -3.585400e+000, -9.070196e-001, 2.380958e+000, -1.320996e-002, -4.210738e+000, 1.085121e+000, -1.193753e+000, -1.236733e-001, -2.036483e-001, 4.137855e+000, 1.566414e+000, 8.510543e-001, 1.652749e-002, 5.488784e+000, 2.335910e-001, -9.950796e-001, -2.103948e-001, 2.992004e+000, -4.050491e+000, -6.354208e+000, 2.250652e+000, -1.548996e-002, -1.876535e+000, 9.733518e-001, -1.106823e+000, -1.804388e-001, 1.960315e+000, 3.667064e+000, -2.460232e+000, 9.553451e-001, 1.237721e-002, 1.307692e+000, 5.564710e-001, // albedo 1, turbidity 2 -1.113356e+000, -1.560185e-001, -7.788803e+000, 8.963658e+000, -5.322872e-002, 1.116670e+000, 7.024842e-002, 4.886694e+000, 5.931909e-001, -1.134232e+000, -1.667475e-001, 4.176259e+000, -3.242194e+000, -7.889230e-002, 8.254326e-002, 1.400333e-001, 5.395289e+000, 4.862375e-001, -1.105040e+000, -2.389195e-001, 9.866260e-001, 1.271557e+000, -6.066849e-001, 3.599900e+000, -1.681445e-001, -2.812867e+000, 1.053791e+000, -1.078302e+000, -2.258635e-002, 7.407482e-001, 1.805864e-001, 9.070580e-001, -1.720820e+000, 4.256187e-001, 6.982502e+000, 3.350778e-001, -1.070883e+000, -2.752054e-001, 2.937203e+000, -2.246366e+000, -9.847865e+000, 3.104714e+000, -2.573859e-001, -2.816401e+000, 8.478900e-001, -1.090880e+000, -1.453755e-001, 2.046382e+000, 5.595795e+000, -2.809181e+000, -9.239576e-001, 1.783176e-001, 2.051350e+000, 5.815062e-001, // albedo 1, turbidity 3 -1.136641e+000, -1.825277e-001, -3.464338e+000, 4.413974e+000, -1.123917e-001, 1.009115e+000, 5.542918e-002, 4.702599e+000, 6.799974e-001, -1.146478e+000, -1.593833e-001, -9.055790e-001, 8.991902e-001, -4.711416e-002, -3.813573e-001, 2.290428e-001, 6.961903e+000, 4.206011e-001, -1.136317e+000, -3.103198e-001, 4.219694e+000, -2.031887e+000, -7.184952e-001, 3.795646e+000, -1.650547e-001, -5.402471e+000, 1.118561e+000, -1.044973e+000, 7.826651e-002, -2.043684e+000, 3.410720e+000, 1.974969e+000, -2.736513e+000, 6.828176e-001, 1.049084e+001, 1.894241e-001, -1.076125e+000, -2.930526e-001, 3.722784e+000, -7.364061e+000, -7.399428e+000, 4.034307e+000, -3.489831e-001, -3.438955e+000, 1.077145e+000, -1.100551e+000, -1.533449e-001, 1.767589e+000, 1.479022e+001, -2.910058e+000, -1.732923e+000, 2.193598e-001, 1.880974e+000, 4.999331e-001, // albedo 1, turbidity 4 -1.175282e+000, -2.274651e-001, -8.788053e-001, 1.446934e+000, -2.568124e-001, 7.201567e-001, 1.054963e-001, 4.149007e+000, 6.084060e-001, -1.224868e+000, -2.528005e-001, -2.861303e+000, 3.033667e+000, 1.405049e-001, 2.481768e-001, 6.435189e-002, 5.409907e+000, 6.372238e-001, -1.144647e+000, -3.063749e-001, 4.347579e+000, -2.473291e+000, -1.180139e+000, 2.550631e+000, 3.833967e-002, -3.231444e+000, 8.737219e-001, -1.028428e+000, 8.888974e-002, -2.431225e+000, 2.811511e+000, 2.400771e+000, -2.380403e+000, 7.114868e-001, 8.190106e+000, 4.166861e-001, -1.076730e+000, -3.129260e-001, 3.582560e+000, -5.902417e+000, -6.959342e+000, 3.528030e+000, -2.613596e-001, -2.993803e+000, 8.934226e-001, -1.107957e+000, -1.728652e-001, 1.679540e+000, 1.238391e+001, -2.945620e+000, -1.568811e+000, 2.418421e-001, 1.360652e+000, 6.182405e-001, // albedo 1, turbidity 5 -1.215034e+000, -2.755459e-001, -1.477751e-001, 4.448730e-001, -4.027817e-001, 4.787013e-001, 1.200617e-001, 3.613995e+000, 5.999756e-001, -1.443500e+000, -5.194350e-001, 1.588243e-001, 1.429114e+000, -2.310655e+000, 3.033213e-001, 2.308566e-002, 1.894189e+000, 6.066576e-001, -1.051421e+000, -9.990731e-002, 5.187710e-001, -3.890856e+000, 7.794599e+000, 1.810628e+000, 6.532073e-002, 2.564480e+000, 9.334916e-001, -1.034548e+000, -6.777012e-002, -2.587520e-002, 1.062675e+001, -2.266196e+001, -2.002081e+000, 7.508804e-001, 2.022771e+000, 3.517577e-001, -1.090576e+000, -2.542157e-001, 2.213560e+000, -3.563890e+000, 9.180955e+000, 2.780121e+000, -2.656654e-001, -5.012514e-002, 8.968751e-001, -1.104356e+000, -1.955634e-001, 1.782217e+000, 1.085584e+000, -5.011522e+000, -1.075140e+000, 3.828238e-001, 6.133363e-001, 6.448312e-001, // albedo 1, turbidity 6 -1.261147e+000, -3.271435e-001, 1.136430e-001, -3.464762e-003, -3.025565e+000, 3.660675e-001, 1.337332e-001, 3.190374e+000, 5.655627e-001, -1.611753e+000, -6.914768e-001, 2.911405e-001, 1.806475e+000, 2.823240e+000, 3.320241e-001, 2.606391e-002, 9.946717e-001, 5.581393e-001, -9.491151e-001, 9.848038e-003, 2.711804e-001, -5.319331e+000, 1.135835e-001, 1.669815e+000, 3.604115e-002, 3.506230e+000, 1.008650e+000, -1.109597e+000, -1.650703e-001, -3.529912e-001, 1.209251e+001, -1.435008e+001, -2.085063e+000, 7.955493e-001, 1.240407e+000, 2.856509e-001, -1.035803e+000, -1.963707e-001, 2.407913e+000, -1.564693e+000, 4.483717e+000, 2.795295e+000, -2.799711e-001, 6.851892e-002, 9.312311e-001, -1.132687e+000, -2.383551e-001, 1.590132e+000, 1.025733e+000, -4.837236e+000, -1.334195e+000, 4.022060e-001, 4.281273e-001, 6.334802e-001, // albedo 1, turbidity 7 -1.310240e+000, -3.819813e-001, 2.469845e-002, -7.043983e-003, -5.009925e+000, 3.560980e-001, 1.582176e-001, 2.966421e+000, 4.998910e-001, -1.993638e+000, -1.029241e+000, 7.780588e-001, 1.080741e+000, 7.179598e+000, 2.478857e-001, 1.935012e-002, -3.434240e-001, 4.813586e-001, -8.209344e-001, 1.728853e-001, -7.045676e-001, -3.384688e+000, -4.855111e+000, 1.661563e+000, 4.252574e-002, 5.701648e+000, 1.110774e+000, -1.130678e+000, -3.273624e-001, 5.555549e-001, 5.800793e+000, -8.817085e+000, -2.344445e+000, 7.532869e-001, -2.418368e+000, 2.201826e-001, -1.032417e+000, -1.335568e-001, 1.707051e+000, 8.168228e+000, -5.151972e-003, 2.785504e+000, -2.123703e-001, 1.770173e+000, 9.064082e-001, -1.125604e+000, -2.328530e-001, 1.537245e+000, 4.347312e+000, -4.368526e+000, -1.527321e+000, 3.574251e-001, 5.982159e-001, 6.705880e-001, // albedo 1, turbidity 8 -1.381743e+000, -4.607543e-001, -2.754732e-001, 9.134243e-001, -7.581174e-001, 6.220814e-001, 2.353878e-002, 2.891536e+000, 6.426078e-001, -2.362341e+000, -1.306326e+000, 6.909936e-001, -7.196658e-001, -4.501812e-001, -5.219928e-002, 2.111683e-001, -9.499603e-001, 3.301774e-002, -1.218829e+000, -6.834768e-002, -1.241760e+000, 1.122890e+000, 5.750762e+000, 1.231058e+000, 6.884716e-003, 6.801032e+000, 1.512485e+000, -6.781560e-001, -2.446588e-001, 1.302166e+000, -2.334650e+000, -1.218960e+001, -1.257952e+000, 5.387955e-001, -5.559859e+000, -1.209718e-002, -1.270037e+000, -1.870204e-001, 9.650201e-001, 9.976613e+000, 1.444014e+000, 1.523442e+000, -2.753646e-002, 3.415790e+000, 1.017645e+000, -1.046712e+000, -2.173979e-001, 1.473981e+000, 4.368847e+000, -4.642506e+000, -1.049951e+000, 3.511771e-001, 2.379457e-001, 6.307946e-001, // albedo 1, turbidity 9 -1.532302e+000, -6.390752e-001, -1.369123e-001, 1.480171e+000, -1.313391e+000, 5.210118e-001, -1.053608e-005, 2.352090e+000, 9.000581e-001, -2.042866e+000, -1.015386e+000, 1.750126e-001, -9.921800e-001, -9.449241e-002, 4.791921e-001, -2.744712e-002, 9.337925e-001, -2.902902e-001, -3.413474e+000, -1.485380e+000, -1.301300e+000, 1.266203e+000, 3.869657e+000, -1.405606e-002, 6.109944e-001, 3.883967e+000, 1.540321e+000, 5.838664e-001, 2.370098e-001, 1.420200e+000, -1.803001e+000, -6.672775e+000, 2.866921e-001, -2.599250e-001, -4.162164e+000, 1.296901e-001, -1.654226e+000, -3.296843e-001, 6.245723e-001, 7.899655e+000, -1.079857e+000, 3.145485e-001, 4.085894e-001, 2.258895e+000, 9.071309e-001, -9.748612e-001, -2.545963e-001, 1.374064e+000, -2.816107e-003, -2.589259e+000, -5.960628e-001, 2.656787e-001, -1.458520e-001, 6.529731e-001, // albedo 1, turbidity 10 -1.944006e+000, -9.776516e-001, -2.425412e-001, 8.187180e-001, -6.620102e-001, 5.676187e-001, -7.857556e-006, 1.944153e+000, 9.001463e-001, -1.294455e+000, -7.294996e-001, -1.718682e-002, 1.261264e+000, -1.170104e+000, -2.029198e-001, -1.306023e-002, 1.821821e+000, -2.533820e-001, -6.849943e+000, -2.937611e+000, -1.107710e+000, -3.923478e+000, 5.018293e+000, 2.040419e+000, 2.845113e-001, 2.080902e+000, 1.460328e+000, 1.445166e+000, 1.641979e-001, 9.591325e-001, 8.676572e+000, -1.098801e+001, -2.274573e+000, 1.340040e-001, -1.166380e+000, 1.014270e-001, -1.596800e+000, -4.130457e-001, 9.250919e-001, -1.406592e+000, 2.474727e+000, 1.748285e+000, 9.929937e-002, -6.705073e-001, 9.210646e-001, -1.035617e+000, -3.537996e-001, 1.073337e+000, 6.090616e+000, -3.710420e+000, -9.390485e-001, 2.233788e-001, -3.213961e-004, 6.545784e-001, }; static float datasetRad600[] = { // albedo 0, turbidity 1 1.605147e-002, 1.028116e-002, 2.949675e-002, 7.265851e-002, 4.608279e-002, 5.069475e-002, // albedo 0, turbidity 2 1.569474e-002, 1.190744e-002, 1.996322e-002, 1.044303e-001, 3.746120e-002, 5.764085e-002, // albedo 0, turbidity 3 1.507252e-002, 1.350309e-002, 7.291417e-003, 1.433035e-001, 3.625213e-002, 6.291384e-002, // albedo 0, turbidity 4 1.383183e-002, 1.670171e-002, -1.576321e-002, 1.993796e-001, 3.837478e-002, 7.063028e-002, // albedo 0, turbidity 5 1.253723e-002, 2.261520e-002, -4.847485e-002, 2.646653e-001, 2.855366e-002, 8.568437e-002, // albedo 0, turbidity 6 1.179552e-002, 2.546904e-002, -6.503150e-002, 2.924065e-001, 3.516626e-002, 9.101182e-002, // albedo 0, turbidity 7 1.070809e-002, 3.005971e-002, -8.793572e-002, 3.255182e-001, 4.780714e-002, 1.014896e-001, // albedo 0, turbidity 8 9.466972e-003, 3.330913e-002, -1.028545e-001, 3.284098e-001, 9.602966e-002, 1.103224e-001, // albedo 0, turbidity 9 8.190696e-003, 3.248675e-002, -9.882934e-002, 2.798409e-001, 1.829752e-001, 1.263322e-001, // albedo 0, turbidity 10 7.225549e-003, 2.433471e-002, -6.029571e-002, 1.468935e-001, 3.282492e-001, 1.441367e-001, // albedo 1, turbidity 1 1.676204e-002, 1.269480e-002, 2.674342e-002, 7.380770e-002, 1.072658e-001, 1.211512e-001, // albedo 1, turbidity 2 1.649305e-002, 1.445974e-002, 1.662432e-002, 1.056364e-001, 1.002831e-001, 1.317330e-001, // albedo 1, turbidity 3 1.577677e-002, 1.637005e-002, 2.821156e-003, 1.465189e-001, 9.971575e-002, 1.424798e-001, // albedo 1, turbidity 4 1.469049e-002, 1.969668e-002, -2.105278e-002, 2.024104e-001, 1.062768e-001, 1.557134e-001, // albedo 1, turbidity 5 1.339480e-002, 2.402713e-002, -4.671234e-002, 2.518382e-001, 1.135974e-001, 1.711111e-001, // albedo 1, turbidity 6 1.274349e-002, 2.648472e-002, -6.068209e-002, 2.720113e-001, 1.285128e-001, 1.776298e-001, // albedo 1, turbidity 7 1.165402e-002, 2.958682e-002, -7.746524e-002, 2.912132e-001, 1.536569e-001, 1.896419e-001, // albedo 1, turbidity 8 1.048769e-002, 3.115400e-002, -8.550235e-002, 2.769964e-001, 2.173505e-001, 1.991057e-001, // albedo 1, turbidity 9 9.312926e-003, 2.881725e-002, -7.387358e-002, 2.079818e-001, 3.221838e-001, 2.120657e-001, // albedo 1, turbidity 10 8.151793e-003, 1.998414e-002, -3.316224e-002, 6.957927e-002, 4.654511e-001, 2.260782e-001, }; static float dataset640[] = { // albedo 0, turbidity 1 -1.113346e+000, -1.715076e-001, -2.657094e+000, 4.632520e+000, -1.092310e-001, 1.421516e+000, 3.230348e-003, 2.697889e+000, 6.262031e-001, -1.193355e+000, -2.074379e-001, 1.431777e+000, 8.245570e-001, -1.936967e-001, 9.392137e-001, 1.972523e-002, 3.001209e+000, 4.415825e-001, -9.337792e-001, -2.037239e-001, 3.943675e+000, -2.487730e+000, -9.876315e-001, 2.772411e+000, -4.919462e-002, -4.176827e+000, 1.026227e+000, -1.297623e+000, -1.296758e-001, -3.144502e-001, 2.454199e+000, 2.433614e+000, 5.298928e-001, 7.814939e-002, 6.564581e+000, 5.587597e-001, -9.325270e-001, -1.997966e-001, 3.363315e+000, -1.887198e+000, -8.905212e+000, 2.808597e+000, -9.537165e-002, -3.059702e+000, 5.403718e-001, -1.125650e+000, -1.904795e-001, 2.099998e+000, 1.251930e+000, -1.899312e+000, 5.255919e-001, 9.848260e-002, 9.627433e-001, 6.251236e-001, // albedo 0, turbidity 2 -1.104956e+000, -1.372068e-001, -2.996624e+000, 4.260021e+000, -1.263137e-001, 1.327775e+000, 7.595887e-002, 5.301229e+000, 6.478109e-001, -1.158426e+000, -1.921879e-001, 3.371987e-001, 8.543727e-001, -1.195421e-001, 2.178871e-001, 1.573997e-001, 3.059646e+000, 5.355391e-001, -1.012076e+000, -1.456275e-001, 3.857821e+000, -1.137640e+000, -7.400821e-001, 4.132381e+000, -2.101470e-001, -1.704290e-001, 1.094519e+000, -1.200085e+000, -9.008631e-002, -1.764929e+000, 4.584027e-001, 8.033799e-001, -1.730728e+000, 5.892683e-001, 6.438112e+000, 2.141131e-001, -9.836248e-001, -1.983419e-001, 3.519957e+000, -9.777763e-001, -5.727911e+000, 4.397457e+000, -2.864495e-001, -2.511187e+000, 9.881415e-001, -1.111842e+000, -1.992363e-001, 1.746814e+000, 5.036170e+000, -2.993753e+000, -5.348114e-001, 2.332738e-001, 8.970344e-001, 5.806194e-001, // albedo 0, turbidity 3 -1.120087e+000, -1.577355e-001, -1.165606e+000, 1.782016e+000, -1.771264e-001, 8.928578e-001, 1.613110e-001, 4.975693e+000, 6.258796e-001, -1.182069e+000, -2.047357e-001, -4.041517e-001, 1.732659e+000, -4.322749e-001, 6.549554e-001, 5.392767e-002, 4.838218e+000, 6.441461e-001, -1.071518e+000, -2.057500e-001, 2.808685e+000, -1.990080e+000, -8.491815e-001, 2.193915e+000, 2.411077e-001, -3.251587e+000, 7.470978e-001, -1.113379e+000, -6.708322e-003, -2.181109e+000, 2.107674e+000, 2.216970e+000, -6.233552e-001, 3.558080e-001, 9.251876e+000, 6.319555e-001, -1.026698e+000, -2.260748e-001, 3.031659e+000, -1.615765e+000, -1.323341e+000, 2.835147e+000, 1.186568e-001, -3.366247e+000, 6.850407e-001, -1.088223e+000, -1.817555e-001, 1.435855e+000, 1.845164e+000, -3.488539e+000, 2.554837e-001, 2.144895e-001, 1.558895e+000, 7.315398e-001, // albedo 0, turbidity 4 -1.164089e+000, -2.003003e-001, -2.998423e-001, 2.713689e-001, -1.828861e-001, 5.800779e-001, 1.968402e-001, 4.650130e+000, 6.156174e-001, -1.209796e+000, -2.733887e-001, -9.360003e-001, 2.769100e+000, -1.870929e+000, 7.049322e-001, -8.477045e-002, 4.120960e+000, 7.444509e-001, -1.232839e+000, -2.622151e-001, 2.857050e+000, -2.866256e+000, 3.128232e+000, 1.897877e+000, 4.581244e-001, -2.112943e+000, 6.384882e-001, -9.291113e-001, 4.110508e-002, -2.235781e+000, 2.969741e+000, -9.758544e+000, -1.941571e+000, 3.426656e-001, 6.907158e+000, 6.945892e-001, -1.103614e+000, -2.279953e-001, 2.314490e+000, -6.307971e-001, 3.369674e+000, 3.787928e+000, 2.456513e-001, -1.776073e+000, 6.864316e-001, -1.072160e+000, -1.984678e-001, 1.092192e+000, 8.472734e-001, -3.126637e+000, -1.076607e+000, 3.908469e-001, 1.205671e+000, 7.035925e-001, // albedo 0, turbidity 5 -1.222416e+000, -2.654298e-001, -1.149975e-001, -6.277756e-003, -1.369463e+000, 4.402179e-001, 1.881320e-001, 3.896722e+000, 6.037946e-001, -1.407746e+000, -4.603243e-001, -3.071475e-001, 2.937390e+000, -9.164938e-001, 6.696693e-001, -6.608327e-002, 2.444782e+000, 6.905594e-001, -1.120454e+000, -1.466269e-001, 7.829076e-001, -7.009271e+000, 5.364470e+000, 1.294280e+000, 4.109552e-001, 1.525889e+000, 7.709564e-001, -9.792886e-001, -4.325464e-002, -4.059461e-001, 1.522559e+001, -1.867598e+001, -1.169367e+000, 3.589556e-001, 2.368951e+000, 5.526839e-001, -1.091118e+000, -2.286983e-001, 9.896666e-001, -6.655971e+000, 8.168041e+000, 1.923773e+000, 3.116805e-001, 1.852611e-001, 7.524175e-001, -1.053081e+000, -1.598496e-001, 9.684194e-001, 3.620674e+000, -5.015769e+000, 8.125082e-002, 4.669502e-001, 1.415221e+000, 7.044272e-001, // albedo 0, turbidity 6 -1.267172e+000, -3.101221e-001, -8.556526e-002, -3.602153e-003, -4.988229e+000, 4.099753e-001, 1.555248e-001, 3.585489e+000, 6.128833e-001, -1.613116e+000, -6.560485e-001, 9.250270e-002, 2.119268e+000, 8.031058e+000, 4.019483e-001, 4.526662e-002, 1.362051e+000, 5.999628e-001, -1.012405e+000, -2.251592e-002, 2.836289e-001, -7.904006e+000, -9.544755e+000, 1.754891e+000, 1.283266e-001, 3.042478e+000, 9.234755e-001, -1.022835e+000, -1.361070e-001, -4.207218e-001, 1.947050e+001, -5.511234e+000, -2.417169e+000, 7.837822e-001, 8.288902e-001, 3.509734e-001, -1.068370e+000, -1.806143e-001, 1.059217e+000, 7.087518e-001, -1.671865e+000, 3.098645e+000, -9.859822e-002, 9.336021e-001, 8.929147e-001, -1.065467e+000, -1.928982e-001, 6.159162e-001, -4.157538e-003, -9.397621e-001, -1.193139e+000, 6.979501e-001, 1.118894e+000, 6.467115e-001, // albedo 0, turbidity 7 -1.345697e+000, -3.906019e-001, -1.921159e-001, -7.410201e-003, -4.683006e+000, 4.591917e-001, 1.919817e-001, 3.158844e+000, 5.319014e-001, -2.096314e+000, -1.056514e+000, 7.665515e-001, 1.602483e+000, 6.290779e+000, 4.693208e-001, -6.258855e-002, -3.745685e-001, 5.853677e-001, -7.573573e-001, 2.265213e-001, -1.283398e+000, -4.696984e+000, -4.261986e+000, 1.197826e+000, 3.444468e-001, 6.004387e+000, 9.413954e-001, -1.140929e+000, -3.489820e-001, 1.095429e+000, 7.531589e+000, -8.153320e+000, -1.722207e+000, 4.427477e-001, -3.072440e+000, 3.874398e-001, -1.009003e+000, -9.087616e-002, 4.181128e-002, 1.154023e+001, -5.092155e-001, 2.166116e+000, 1.620893e-001, 2.824826e+000, 8.289491e-001, -1.080842e+000, -2.166745e-001, 6.939662e-001, -2.316636e-003, -2.616711e+000, -1.012238e+000, 6.132021e-001, 7.579828e-001, 6.813755e-001, // albedo 0, turbidity 8 -1.394668e+000, -4.508268e-001, -2.615024e-001, -7.412740e-003, -4.811648e+000, 4.235635e-001, 1.627041e-001, 3.134174e+000, 5.225016e-001, -2.715734e+000, -1.409574e+000, 6.485110e-001, 6.307101e-001, 8.120123e+000, 3.677567e-001, 6.430919e-002, -3.729191e-001, 3.463130e-001, -8.973624e-001, 2.859206e-002, -1.610007e+000, -1.483136e+000, -5.613288e+000, 7.093329e-001, 2.936945e-001, 5.541210e+000, 1.143952e+000, -8.450858e-001, -1.969825e-001, 1.399585e+000, 1.418708e-001, -4.532026e+000, -7.432040e-001, 3.410858e-001, -3.386293e+000, 2.885614e-001, -1.180533e+000, -2.469972e-001, -2.694505e-002, 1.635998e+001, -2.378676e+000, 9.477733e-001, 1.105776e-001, 1.954485e+000, 8.559872e-001, -1.022908e+000, -1.650807e-001, 3.812483e-001, -2.139201e-003, -2.300711e+000, -5.917998e-001, 6.793527e-001, 1.248273e+000, 6.747565e-001, // albedo 0, turbidity 9 -1.557922e+000, -6.294681e-001, -2.355549e-001, -8.743568e-003, -5.017111e+000, 4.034446e-001, 1.005643e-001, 2.735289e+000, 5.667004e-001, -3.061673e+000, -1.398157e+000, 1.597008e-001, 1.066059e+000, 8.207018e+000, 4.785780e-001, 4.629487e-002, 1.324020e+000, 2.540204e-001, -2.371583e+000, -1.100187e+000, -1.279309e+000, -3.340819e+000, -6.556706e+000, 2.636750e-001, 4.298705e-001, 2.649782e+000, 1.060950e+000, -5.315727e-002, 2.306821e-001, 1.091037e+000, 5.297610e+000, -2.412315e+000, -7.083157e-002, 7.256586e-002, -1.330891e+000, 4.168205e-001, -1.375983e+000, -4.677570e-001, 2.271650e-001, 8.771601e+000, -2.511780e+000, 1.487082e-001, 8.542210e-002, 5.509707e-003, 7.821447e-001, -1.006483e+000, -1.435513e-001, 5.802646e-002, -3.181899e-003, -2.010861e+000, -1.746922e-001, 7.487809e-001, 1.623209e+000, 6.848148e-001, // albedo 0, turbidity 10 -1.919035e+000, -9.396362e-001, -3.059418e-001, 1.542398e+000, -1.488273e+000, 5.133825e-001, -7.992185e-006, 2.276361e+000, 8.334381e-001, -2.470138e+000, -1.108577e+000, -5.521438e-001, -9.047033e-001, 6.905739e-001, 3.774300e-001, -2.801883e-002, 2.413470e+000, -8.986266e-002, -5.532450e+000, -2.346497e+000, -1.734654e+000, 1.461689e+000, 1.765938e+000, 4.969811e-001, 6.205943e-001, 2.112232e+000, 1.159488e+000, 4.159150e-001, -2.306809e-001, 1.540502e+000, -1.006923e+000, -5.275092e+000, -2.776202e-002, -1.632884e-001, -1.467491e+000, 4.177919e-001, -1.248112e+000, -3.080519e-001, -1.229235e-001, 8.972757e+000, -1.532948e+000, -8.283794e-002, 1.561573e-001, 1.856113e-001, 7.696948e-001, -1.054499e+000, -2.660558e-001, 1.307025e-001, -2.167883e-003, -1.531056e+000, 1.525856e-001, 5.356892e-001, 7.181428e-001, 6.837654e-001, // albedo 1, turbidity 1 -1.113347e+000, -1.715068e-001, -2.657094e+000, 4.632520e+000, -1.092308e-001, 1.421516e+000, 3.229759e-003, 2.697889e+000, 6.262031e-001, -1.193355e+000, -2.074367e-001, 1.431777e+000, 8.245569e-001, -1.936966e-001, 9.392136e-001, 1.972263e-002, 3.001209e+000, 4.415825e-001, -9.337795e-001, -2.037221e-001, 3.943675e+000, -2.487730e+000, -9.876315e-001, 2.772410e+000, -4.919872e-002, -4.176827e+000, 1.026227e+000, -1.297624e+000, -1.296733e-001, -3.144502e-001, 2.454199e+000, 2.433614e+000, 5.298925e-001, 7.814503e-002, 6.564581e+000, 5.587597e-001, -9.325285e-001, -1.997939e-001, 3.363316e+000, -1.887198e+000, -8.905212e+000, 2.808596e+000, -9.537523e-002, -3.059702e+000, 5.403717e-001, -1.125653e+000, -1.904767e-001, 2.099998e+000, 1.251930e+000, -1.899312e+000, 5.255917e-001, 9.848033e-002, 9.627434e-001, 6.251233e-001, // albedo 1, turbidity 2 -1.115892e+000, -1.571450e-001, -5.361081e+000, 6.833528e+000, -6.891479e-002, 1.309709e+000, 6.046362e-002, 3.972373e+000, 6.651606e-001, -1.147479e+000, -1.855896e-001, 2.239259e+000, -5.937930e-001, -1.005125e-001, 2.773971e-001, 1.337105e-001, 3.136906e+000, 5.194230e-001, -1.030450e+000, -1.533626e-001, 2.268967e+000, -4.886576e-001, -6.336865e-001, 3.911080e+000, -1.602643e-001, 1.513730e-001, 1.130153e+000, -1.159297e+000, -5.818314e-002, -1.488690e-001, 1.358829e+000, 1.208889e+000, -1.827456e+000, 4.867277e-001, 6.185880e+000, 1.951064e-001, -1.023581e+000, -2.517540e-001, 3.635148e+000, -2.375150e+000, -9.409992e+000, 3.209554e+000, -3.006489e-001, -3.235953e+000, 9.969505e-001, -1.102864e+000, -1.644399e-001, 2.160645e+000, 5.685422e+000, -2.867248e+000, -1.020916e+000, 2.064591e-001, 1.192668e+000, 5.029621e-001, // albedo 1, turbidity 3 -1.120417e+000, -1.543428e-001, -2.173869e+000, 2.965267e+000, -1.062190e-001, 8.112859e-001, 1.448682e-001, 4.993622e+000, 6.373394e-001, -1.168618e+000, -1.948508e-001, -6.247560e-001, 2.203402e+000, -2.724794e-001, 8.364691e-001, 5.608377e-002, 4.262497e+000, 6.310098e-001, -1.080229e+000, -2.282841e-001, 2.194035e+000, -1.203336e+000, -3.861545e-001, 2.234045e+000, 1.553866e-001, -3.266039e+000, 8.246847e-001, -1.101698e+000, 2.182410e-002, -1.179116e+000, 8.533844e-001, 8.777171e-001, -1.222988e+000, 5.021882e-001, 9.364642e+000, 4.790363e-001, -1.047144e+000, -2.539571e-001, 3.684827e+000, 9.827861e-002, -2.297266e-001, 3.038327e+000, -2.609445e-001, -3.685112e+000, 8.596057e-001, -1.103227e+000, -1.861499e-001, 2.098952e+000, 1.030900e-001, -4.268311e+000, -1.120060e+000, 2.879792e-001, 7.160893e-001, 6.213207e-001, // albedo 1, turbidity 4 -1.155288e+000, -2.006105e-001, -5.822630e-002, 3.970794e-001, -2.828885e-001, 5.093569e-001, 1.631119e-001, 4.152479e+000, 6.357376e-001, -1.241627e+000, -2.673712e-001, -6.444494e-001, 2.257014e+000, -1.630843e+000, 5.967071e-001, 9.888683e-003, 4.308732e+000, 6.751366e-001, -1.136812e+000, -2.811418e-001, 2.220215e+000, -1.535870e+000, 2.354743e+000, 2.041362e+000, 2.387976e-001, -3.453756e+000, 7.672245e-001, -1.028322e+000, 9.134962e-002, -1.151053e+000, 6.511620e-001, -5.683098e+000, -2.001006e+000, 6.430642e-001, 8.523367e+000, 5.422240e-001, -1.076830e+000, -3.101207e-001, 3.052794e+000, 3.177593e-001, 3.054756e+000, 3.386727e+000, -2.312489e-001, -3.908802e+000, 7.978614e-001, -1.107083e+000, -1.880372e-001, 2.001810e+000, -3.352202e-003, -1.526356e+000, -1.480550e+000, 3.486524e-001, 7.220325e-001, 6.581821e-001, // albedo 1, turbidity 5 -1.214879e+000, -2.719222e-001, 2.247747e-001, 1.509740e-002, -5.438281e-001, 3.728351e-001, 1.749880e-001, 3.132220e+000, 6.001432e-001, -1.424202e+000, -4.768943e-001, -6.396040e-001, 2.060101e+000, -1.113780e+000, 6.993089e-001, -2.098291e-002, 2.504826e+000, 6.757213e-001, -1.048548e+000, -1.173837e-001, 1.885902e+000, -3.700301e+000, 4.667326e+000, 1.344798e+000, 2.140261e-001, 1.525414e-001, 8.450168e-001, -1.056271e+000, -5.272364e-002, -1.391708e+000, 9.711492e+000, -1.742761e+001, -1.677628e+000, 6.906304e-001, 4.107662e+000, 4.268005e-001, -1.072328e+000, -2.450563e-001, 3.125155e+000, -2.470389e+000, 6.794968e+000, 2.678049e+000, -2.092059e-001, -1.651858e+000, 8.708740e-001, -1.107628e+000, -2.089585e-001, 1.799168e+000, 4.621596e-001, -5.008181e+000, -1.121127e+000, 3.917217e-001, 2.703209e-001, 6.449597e-001, // albedo 1, turbidity 6 -1.249741e+000, -3.073987e-001, 1.398829e-001, -2.878563e-003, -5.008845e+000, 4.535605e-001, 1.447766e-001, 3.091173e+000, 6.138128e-001, -1.577209e+000, -6.213162e-001, 2.895282e-001, 1.670732e+000, 8.708786e+000, 2.480283e-001, 7.326386e-002, 1.395638e+000, 5.814691e-001, -1.015394e+000, -9.306378e-002, 4.870291e-001, -6.558243e+000, -1.073347e+001, 1.842159e+000, 2.135043e-002, 1.655269e+000, 9.750505e-001, -1.030222e+000, -3.712071e-002, -4.565649e-001, 1.827249e+001, -4.505703e+000, -2.635230e+000, 9.447498e-001, 2.450865e+000, 2.757082e-001, -1.086063e+000, -2.709359e-001, 2.527868e+000, -1.786375e+000, -2.329338e+000, 3.367729e+000, -4.201670e-001, -9.372873e-001, 9.570917e-001, -1.113156e+000, -2.162986e-001, 1.815038e+000, 1.036606e-001, -1.106537e+000, -1.657558e+000, 4.923976e-001, -1.768985e-002, 6.218745e-001, // albedo 1, turbidity 7 -1.345662e+000, -4.038158e-001, 1.601105e-001, -6.892546e-003, -5.010308e+000, 3.903794e-001, 1.543535e-001, 2.538245e+000, 5.555141e-001, -1.998866e+000, -9.786972e-001, 5.763250e-001, 1.007104e+000, 8.983795e+000, 3.752110e-001, 7.375525e-002, 1.792659e-001, 4.969463e-001, -7.854213e-001, 1.186171e-001, -1.925047e-001, -3.567464e+000, -8.901606e+000, 1.181923e+000, 4.049067e-002, 3.603602e+000, 1.081550e+000, -1.113558e+000, -1.964692e-001, -6.175963e-002, 7.345047e+000, -5.293662e+000, -1.720046e+000, 8.863695e-001, -1.699694e-001, 2.184709e-001, -1.077319e+000, -2.429937e-001, 2.226652e+000, 8.082352e+000, -5.647382e-001, 2.187018e+000, -3.571678e-001, -2.370890e-001, 9.528157e-001, -1.101702e+000, -2.020333e-001, 1.637670e+000, 5.276716e-001, -4.006007e+000, -1.066501e+000, 4.548015e-001, 4.055769e-001, 6.485706e-001, // albedo 1, turbidity 8 -1.411469e+000, -4.870956e-001, 1.017578e-001, -8.806763e-003, -5.014847e+000, 4.306981e-001, 1.278033e-001, 2.361142e+000, 5.472925e-001, -2.735007e+000, -1.453253e+000, 5.783189e-001, 5.673243e-001, 9.968637e+000, 2.236397e-001, 1.860109e-001, -3.781953e-001, 2.505082e-001, -7.371503e-001, 1.290592e-001, -5.349577e-001, -1.885854e+000, -8.623054e+000, 1.078614e+000, -5.694996e-002, 4.526279e+000, 1.347569e+000, -9.678370e-001, -2.562830e-001, 2.961987e-001, 2.461144e+000, -4.753928e+000, -1.657373e+000, 8.388825e-001, -2.440974e+000, 1.816225e-002, -1.148918e+000, -2.271366e-001, 1.817890e+000, 1.097345e+001, -1.126160e+000, 1.993895e+000, -2.870862e-001, 7.269217e-001, 1.032783e+000, -1.090291e+000, -2.315314e-001, 1.491197e+000, 9.632479e+000, -4.323932e+000, -1.326631e+000, 3.604933e-001, 1.905995e-001, 6.312241e-001, // albedo 1, turbidity 9 -1.552618e+000, -6.336918e-001, 4.605315e-002, -8.452985e-003, -4.979015e+000, 3.484674e-001, 8.791637e-002, 2.297399e+000, 5.705230e-001, -2.770597e+000, -1.302036e+000, 3.421676e-001, 1.220769e+000, 7.584372e+000, 4.050789e-001, 4.478808e-002, 9.435710e-001, 2.393878e-001, -2.631791e+000, -1.247576e+000, -8.423940e-001, -3.955998e+000, -5.341100e+000, 6.385142e-001, 3.872948e-001, 2.279807e+000, 1.101259e+000, 1.875824e-001, 3.564184e-001, 7.973268e-001, 7.159160e+000, -3.857340e+000, -9.227702e-001, 8.283793e-002, -1.444145e+000, 3.654244e-001, -1.489693e+000, -4.947623e-001, 1.253918e+000, 3.949282e+000, -1.320903e+000, 1.088652e+000, 1.489763e-001, -3.855853e-001, 8.130960e-001, -1.042349e+000, -2.134514e-001, 1.289359e+000, -3.129206e-003, -2.385397e+000, -7.642278e-001, 3.772293e-001, 3.683001e-001, 6.811674e-001, // albedo 1, turbidity 10 -1.924886e+000, -9.354584e-001, -1.879067e-001, 1.267892e+000, -1.174622e+000, 5.570232e-001, -1.060836e-005, 2.002481e+000, 9.001398e-001, -1.556107e+000, -8.200410e-001, -1.065249e-001, -3.241942e-001, 1.552504e-001, 7.662815e-002, -2.568474e-002, 1.738474e+000, -2.100942e-001, -7.169297e+000, -2.972878e+000, -1.324108e+000, 7.276378e-003, 2.638975e+000, 1.186150e+000, 5.695709e-001, 2.027718e+000, 1.328077e+000, 1.889259e+000, 2.600110e-001, 1.309033e+000, 1.187864e+000, -6.905754e+000, -1.163025e+000, -1.642758e-001, -1.774036e+000, 2.566466e-001, -1.816439e+000, -3.601966e-001, 6.367922e-001, 6.798160e+000, -6.431562e-001, 9.014269e-001, 2.490693e-001, -6.685128e-003, 8.542883e-001, -9.684886e-001, -3.866519e-001, 1.268224e+000, -4.187273e-003, -1.833316e+000, -4.626197e-001, 2.263859e-001, -5.583963e-001, 6.650112e-001, }; static float datasetRad640[] = { // albedo 0, turbidity 1 1.479989e-002, 9.575884e-003, 2.973854e-002, 4.822245e-002, 3.622965e-002, 3.714381e-002, // albedo 0, turbidity 2 1.494233e-002, 1.021187e-002, 2.574697e-002, 7.232352e-002, 3.290719e-002, 4.167409e-002, // albedo 0, turbidity 3 1.434641e-002, 1.147574e-002, 1.506677e-002, 1.142492e-001, 2.532042e-002, 4.995278e-002, // albedo 0, turbidity 4 1.326292e-002, 1.444403e-002, -7.612369e-003, 1.768500e-001, 1.846871e-002, 6.093428e-002, // albedo 0, turbidity 5 1.210064e-002, 1.800376e-002, -3.160469e-002, 2.285807e-001, 2.227077e-002, 6.824549e-002, // albedo 0, turbidity 6 1.130890e-002, 2.150486e-002, -5.124749e-002, 2.648020e-001, 2.123060e-002, 7.588774e-002, // albedo 0, turbidity 7 1.023130e-002, 2.633945e-002, -7.626006e-002, 3.042057e-001, 3.007536e-002, 8.597681e-002, // albedo 0, turbidity 8 8.913856e-003, 3.088076e-002, -9.896179e-002, 3.274618e-001, 6.060024e-002, 9.959796e-002, // albedo 0, turbidity 9 7.548425e-003, 3.088764e-002, -9.837988e-002, 2.862874e-001, 1.450480e-001, 1.121877e-001, // albedo 0, turbidity 10 6.525594e-003, 2.429771e-002, -6.656565e-002, 1.679199e-001, 2.792664e-001, 1.313366e-001, // albedo 1, turbidity 1 1.534297e-002, 1.199131e-002, 2.491229e-002, 5.492441e-002, 7.679650e-002, 9.300994e-002, // albedo 1, turbidity 2 1.542409e-002, 1.237811e-002, 2.235351e-002, 7.606092e-002, 7.888526e-002, 9.886009e-002, // albedo 1, turbidity 3 1.501351e-002, 1.379279e-002, 1.162514e-002, 1.159528e-001, 7.784537e-002, 1.097624e-001, // albedo 1, turbidity 4 1.398757e-002, 1.622679e-002, -9.033929e-003, 1.740587e-001, 8.042195e-002, 1.246928e-001, // albedo 1, turbidity 5 1.276036e-002, 2.055104e-002, -3.597123e-002, 2.310287e-001, 8.109251e-002, 1.421324e-001, // albedo 1, turbidity 6 1.198617e-002, 2.326685e-002, -5.243143e-002, 2.599544e-001, 8.840775e-002, 1.517899e-001, // albedo 1, turbidity 7 1.092344e-002, 2.669375e-002, -7.074274e-002, 2.830300e-001, 1.143047e-001, 1.610563e-001, // albedo 1, turbidity 8 9.699402e-003, 2.953350e-002, -8.582613e-002, 2.867195e-001, 1.638123e-001, 1.760228e-001, // albedo 1, turbidity 9 8.432894e-003, 2.784449e-002, -7.740437e-002, 2.250221e-001, 2.667103e-001, 1.889583e-001, // albedo 1, turbidity 10 7.395069e-003, 2.031820e-002, -4.154554e-002, 9.577204e-002, 4.084819e-001, 2.043633e-001, }; static float dataset680[] = { // albedo 0, turbidity 1 -1.112655e+000, -1.844098e-001, -3.170582e+000, 5.334685e+000, -6.690891e-002, 1.561122e+000, -2.792088e-006, 1.400688e+000, 6.639418e-001, -1.138469e+000, -1.797086e-001, 1.271179e+000, 1.158372e+000, -1.687824e-001, 1.414051e+000, 4.258569e-003, 2.135675e+000, 5.322718e-001, -1.026337e+000, -1.861539e-001, 2.119648e+000, -6.753200e-001, -1.972700e-001, 2.384659e+000, -1.304972e-002, -1.804518e+000, 1.207802e+000, -1.198321e+000, -1.585305e-001, 1.339219e+000, 5.796904e-001, -5.143433e-002, 1.107455e+000, 2.551349e-002, 3.346946e+000, -3.387602e-002, -9.935091e-001, -1.747698e-001, 2.816779e+000, -3.496148e-001, 1.832218e+000, 2.324658e+000, -3.408305e-002, -1.618451e+000, 1.189512e+000, -1.092682e+000, -1.840784e-001, 2.455887e+000, 1.441429e-001, -4.002347e+000, 1.186375e+000, 3.634755e-002, 3.070963e-001, 5.512501e-001, // albedo 0, turbidity 2 -1.104975e+000, -1.425541e-001, -1.889148e+000, 3.408593e+000, -1.252648e-001, 1.396095e+000, 8.358812e-002, 3.814297e+000, 6.848154e-001, -1.131570e+000, -1.500053e-001, -1.048539e+000, 3.133642e+000, -2.651219e-001, 1.193999e+000, 7.013543e-002, 4.592749e+000, 6.857750e-001, -1.030016e+000, -1.667752e-001, 6.179600e+000, -5.163198e+000, -4.084328e-001, 2.617798e+000, 1.966627e-003, -2.417731e+000, 8.402310e-001, -1.167563e+000, -3.644294e-002, -4.501893e+000, 4.471663e+000, -5.377956e-001, 4.971351e-002, 4.621337e-001, 1.014187e+001, 4.411276e-001, -1.018402e+000, -2.068288e-001, 4.710566e+000, -1.425858e+000, 1.287815e-001, 3.605281e+000, -2.164599e-001, -4.336932e+000, 9.051639e-001, -1.078985e+000, -1.995548e-001, 1.678948e+000, 3.074167e-001, -1.642830e+000, -1.235470e-001, 2.735898e-001, 6.360197e-001, 5.870665e-001, // albedo 0, turbidity 3 -1.132881e+000, -1.676238e-001, -1.179974e+000, 1.902080e+000, -7.980402e-002, 8.946611e-001, 1.939671e-001, 3.793414e+000, 6.357246e-001, -1.138356e+000, -1.681053e-001, 1.548320e+000, -6.001024e-001, -4.138892e-001, 2.586807e-001, 2.126762e-001, 4.742849e+000, 5.910253e-001, -1.093982e+000, -1.847904e-001, 1.234133e+000, -4.707125e-001, 1.076579e+000, 3.355751e+000, 5.394600e-002, -2.314910e+000, 8.900752e-001, -1.117812e+000, -6.182272e-002, -4.681118e-001, 5.075227e+000, -1.561122e+001, -2.343845e+000, 5.618788e-001, 7.005713e+000, 4.622191e-001, -1.013135e+000, -1.529086e-001, 1.960772e+000, -3.022528e+000, 8.938126e+000, 4.411437e+000, 3.156643e-002, -1.449180e+000, 8.181914e-001, -1.087086e+000, -2.231900e-001, 1.871061e+000, 1.830836e+000, -4.397140e+000, -5.441402e-001, 2.728682e-001, -5.607736e-002, 6.741811e-001, // albedo 0, turbidity 4 -1.176035e+000, -2.099056e-001, -8.221907e-001, 1.520994e+000, -2.507738e-001, 9.100863e-001, 1.507234e-001, 3.661138e+000, 6.726424e-001, -1.140180e+000, -1.918480e-001, 2.844393e-001, -3.842927e-001, -5.520764e-001, -1.868484e-001, 2.247948e-001, 5.381202e+000, 6.059726e-001, -1.282085e+000, -3.059464e-001, 1.619956e+000, -1.362117e+000, 2.324649e+000, 3.350678e+000, 2.102082e-001, -4.028753e+000, 8.172091e-001, -9.092985e-001, 4.843416e-002, -1.076741e+000, 8.143038e+000, -1.618418e+001, -3.681285e+000, 5.217800e-001, 7.307672e+000, 5.312006e-001, -1.110248e+000, -2.047143e-001, 1.565253e+000, -4.575474e+000, 8.737741e+000, 5.023419e+000, 2.469230e-001, -1.716906e+000, 7.856742e-001, -1.054900e+000, -2.018466e-001, 1.352034e+000, 2.656066e+000, -4.403444e+000, -1.479998e+000, 3.939305e-001, 6.455032e-001, 6.775162e-001, // albedo 0, turbidity 5 -1.237521e+000, -2.734963e-001, -4.554763e-001, 3.417711e-001, 2.054204e-001, 3.954470e-001, 2.366979e-001, 3.239693e+000, 6.083737e-001, -1.354583e+000, -4.251172e-001, -3.241668e-001, 2.077967e+000, -1.910410e+000, 8.755633e-001, -8.365829e-002, 2.443727e+000, 7.260119e-001, -1.152500e+000, -1.277879e-001, 1.089367e+000, -4.497520e+000, 5.636501e+000, 1.249272e+000, 5.829396e-001, 9.198423e-001, 7.039872e-001, -9.782313e-001, -8.253891e-002, -5.673470e-001, 1.098032e+001, -1.689550e+001, -1.619205e+000, 2.125660e-001, 2.080566e+000, 6.315535e-001, -1.064286e+000, -1.710957e-001, 9.336921e-001, -5.525059e+000, 8.053084e+000, 2.664602e+000, 4.815015e-001, 4.884965e-001, 7.093015e-001, -1.067798e+000, -1.817268e-001, 1.095720e+000, 3.551145e+000, -5.009504e+000, -4.802047e-001, 4.854159e-001, 8.021585e-001, 7.133339e-001, // albedo 0, turbidity 6 -1.251896e+000, -2.936510e-001, -3.090944e-002, -5.488869e-003, -6.577788e-001, 4.577691e-001, 1.780002e-001, 3.335561e+000, 6.394482e-001, -1.615603e+000, -6.405318e-001, -4.651954e-001, 2.332689e+000, -1.893131e-001, 3.391170e-001, 3.495888e-002, 1.058634e+000, 6.310524e-001, -9.703572e-001, 1.437971e-002, 6.532383e-001, -6.450045e+000, 4.026380e+000, 2.198628e+000, 2.684967e-001, 2.873804e+000, 8.626816e-001, -1.053437e+000, -1.577255e-001, -2.354526e-001, 1.753047e+001, -1.802766e+001, -3.193379e+000, 6.264380e-001, 3.733714e-001, 4.466776e-001, -1.051388e+000, -1.690749e-001, 6.925698e-001, -7.450365e+000, 7.747780e+000, 3.681960e+000, 1.688173e-001, 9.054528e-001, 8.229209e-001, -1.060369e+000, -1.751603e-001, 8.678290e-001, 5.136962e+000, -5.014566e+000, -1.283438e+000, 6.547844e-001, 9.420523e-001, 6.738511e-001, // albedo 0, turbidity 7 -1.358251e+000, -3.909003e-001, -7.590093e-002, -8.010253e-003, -2.417641e-001, 5.031789e-001, 1.882499e-001, 2.807060e+000, 5.884485e-001, -2.043506e+000, -9.923881e-001, -4.530797e-001, 1.750575e+000, -4.362236e-001, 2.997323e-001, 2.328504e-002, 1.626543e-001, 5.806819e-001, -7.280672e-001, 2.228069e-001, 2.169765e-001, -3.681736e+000, 4.308793e+000, 1.308622e+000, 3.451835e-001, 4.037459e+000, 9.113772e-001, -1.155299e+000, -3.079453e-001, -1.640569e-001, 7.663297e+000, -1.327817e+001, -1.431157e+000, 4.096359e-001, -9.185502e-001, 4.578034e-001, -1.006427e+000, -1.250087e-001, 7.477012e-001, 2.612704e+000, 2.531799e+000, 1.565371e+000, 3.452604e-001, 9.129266e-001, 7.684386e-001, -1.068759e+000, -1.729191e-001, 5.265652e-001, 7.074812e+000, -4.259958e+000, -4.833255e-001, 6.043380e-001, 1.489203e+000, 7.089074e-001, // albedo 0, turbidity 8 -1.398983e+000, -4.500153e-001, -5.189309e-001, 1.546325e-001, 4.187327e-001, 2.811516e-001, 2.379667e-001, 2.801040e+000, 5.198375e-001, -2.970455e+000, -1.529948e+000, 1.094532e-001, 7.382263e-001, -1.024683e+000, 2.074091e-001, 1.397605e-001, -6.743828e-001, 3.496944e-001, -3.942086e-001, 3.424842e-001, -1.253259e+000, -9.268654e-001, 5.636065e+000, 8.224289e-001, 2.452235e-001, 5.864258e+000, 1.202820e+000, -1.181174e+000, -4.197175e-001, 1.429102e+000, -7.894317e-003, -1.239152e+001, -5.753431e-001, 3.552180e-001, -4.495555e+000, 2.141883e-001, -1.060281e+000, -1.080598e-001, -3.276480e-001, 1.369250e+001, 1.504389e+000, 6.401191e-001, 2.437501e-001, 3.212918e+000, 9.172133e-001, -1.037564e+000, -2.018083e-001, 6.250668e-001, -2.525843e-003, -3.269998e+000, -2.649814e-001, 6.600589e-001, 3.337508e-001, 6.516131e-001, // albedo 0, turbidity 9 -1.610481e+000, -6.353902e-001, -5.968977e-001, 1.414037e+000, -7.941453e-001, 7.888684e-001, 2.209045e-002, 2.615106e+000, 6.870260e-001, -3.073343e+000, -1.365905e+000, -2.651943e-001, -1.685310e+000, 4.755874e-001, -1.110669e-001, 2.561961e-001, 1.222045e+000, 3.362780e-002, -2.207768e+000, -1.009608e+000, -1.329601e+000, 3.393091e+000, 3.419104e+000, -4.733375e-002, 5.989185e-001, 2.814641e+000, 1.245189e+000, -1.981173e-002, 2.018414e-001, 1.457765e+000, -6.316169e+000, -6.640569e+000, 7.150646e-001, -2.993748e-001, -2.703376e+000, 3.218596e-001, -1.435873e+000, -3.390505e-001, -3.859047e-001, 1.457464e+001, -1.121591e+000, -6.089868e-002, 5.319220e-001, 1.852395e+000, 8.379521e-001, -9.812568e-001, -2.273751e-001, 5.108069e-001, -3.735693e-003, -2.547988e+000, -4.492561e-001, 5.069199e-001, 2.977910e-001, 6.639273e-001, // albedo 0, turbidity 10 -2.056405e+000, -9.703512e-001, -3.731953e-001, 2.052022e+000, -1.445283e+000, 6.103743e-001, -9.389644e-006, 2.198652e+000, 8.567335e-001, -2.105651e+000, -8.924283e-001, -6.868702e-001, -1.665838e+000, 4.795702e-001, 5.228080e-001, -4.272483e-002, 2.661317e+000, -1.154062e-001, -6.179767e+000, -2.651580e+000, -1.527652e+000, 2.692054e+000, 2.293427e+000, -1.005611e-001, 9.545323e-001, 1.367438e+000, 1.169193e+000, 1.240848e+000, 1.126706e-001, 1.620422e+000, -3.384604e+000, -5.545532e+000, 4.928203e-001, -5.999585e-001, -1.407078e+000, 4.193816e-001, -1.539149e+000, -2.081890e-001, -4.552234e-001, 1.056410e+001, -1.048637e+000, -2.780921e-001, 5.682296e-001, 6.785092e-001, 7.729892e-001, -1.036841e+000, -4.359099e-001, 4.767834e-001, -3.794262e-003, -1.980492e+000, 9.954067e-002, 3.037557e-001, 2.156592e-002, 6.845201e-001, // albedo 1, turbidity 1 -1.110980e+000, -1.799491e-001, -3.168600e+000, 5.336662e+000, -6.318131e-002, 1.559251e+000, 3.204341e-003, 1.401140e+000, 6.638144e-001, -1.132332e+000, -1.786787e-001, 1.272954e+000, 1.160211e+000, -1.685885e-001, 1.409550e+000, 7.140682e-003, 2.136473e+000, 5.320908e-001, -1.015776e+000, -1.825058e-001, 2.122848e+000, -6.725506e-001, -1.976294e-001, 2.376807e+000, -1.859856e-002, -1.803033e+000, 1.207528e+000, -1.189845e+000, -1.509036e-001, 1.345709e+000, 5.832609e-001, -5.130839e-002, 1.097035e+000, 2.686911e-002, 3.349361e+000, -3.431297e-002, -1.000281e+000, -1.696328e-001, 2.829408e+000, -3.466041e-001, 1.832532e+000, 2.314637e+000, -2.721994e-002, -1.614939e+000, 1.188720e+000, -1.120411e+000, -1.974172e-001, 2.474172e+000, 1.453506e-001, -4.002206e+000, 1.180333e+000, 2.229171e-002, 3.112615e-001, 5.505539e-001, // albedo 1, turbidity 2 -1.112667e+000, -1.574855e-001, -2.284814e+000, 4.255050e+000, -1.386097e-001, 1.459506e+000, 4.508931e-002, 2.944474e+000, 7.339984e-001, -1.113577e+000, -1.331062e-001, -1.828757e+000, 3.910596e+000, -2.095519e-001, 1.159335e+000, 9.311608e-002, 4.517295e+000, 6.365313e-001, -1.061651e+000, -2.007134e-001, 5.907472e+000, -4.808769e+000, -2.120206e-001, 2.727568e+000, -4.222666e-002, -2.599674e+000, 9.265659e-001, -1.136633e+000, -4.281875e-003, -3.407541e+000, 4.132332e+000, -3.866153e-001, -5.082717e-001, 4.828348e-001, 9.797167e+000, 3.325034e-001, -1.027909e+000, -2.334388e-001, 4.972147e+000, -1.499736e+000, 9.598438e-002, 2.744895e+000, -3.558702e-001, -4.288054e+000, 1.000138e+000, -1.102843e+000, -1.875642e-001, 2.087760e+000, 3.692600e-001, -6.520835e-001, -9.598766e-001, 2.984231e-001, 4.045786e-001, 5.091931e-001, // albedo 1, turbidity 3 -1.117485e+000, -1.492968e-001, -2.639425e+000, 3.672106e+000, -1.058342e-001, 1.098101e+000, 1.544782e-001, 4.496691e+000, 6.582312e-001, -1.123872e+000, -1.467158e-001, 3.049045e+000, -2.607634e+000, -2.505495e-001, -8.310458e-002, 3.333822e-001, 4.631418e+000, 5.120491e-001, -1.118262e+000, -2.462050e-001, -8.333919e-002, 2.438788e+000, 6.143236e-001, 3.745903e+000, -2.043295e-001, -3.451983e+000, 1.056003e+000, -1.095394e+000, 2.009680e-002, 8.468659e-001, 1.230624e-002, -8.638525e+000, -2.989487e+000, 8.735734e-001, 8.533740e+000, 2.548062e-001, -1.035035e+000, -2.296018e-001, 2.722309e+000, 1.849369e-001, 3.440975e+000, 4.372083e+000, -4.747494e-001, -2.984092e+000, 1.009737e+000, -1.113497e+000, -1.931400e-001, 2.288509e+000, 4.973129e-002, -1.353292e-001, -1.587772e+000, 4.073801e-001, -8.180513e-003, 5.682569e-001, // albedo 1, turbidity 4 -1.172242e+000, -2.084847e-001, -1.212027e+000, 1.991627e+000, -1.403495e-001, 7.684996e-001, 1.582914e-001, 3.407597e+000, 6.659386e-001, -1.167834e+000, -2.117291e-001, 1.196578e+000, -1.438719e+000, -3.137939e-001, -4.537552e-002, 2.260096e-001, 4.659389e+000, 5.776369e-001, -1.222298e+000, -2.893306e-001, 9.080116e-001, 1.413518e+000, 1.709237e+000, 2.915962e+000, 8.464584e-002, -3.867076e+000, 9.110543e-001, -9.554071e-001, 6.610246e-002, -3.323811e-001, 2.702543e+000, -1.345592e+001, -3.119309e+000, 7.740473e-001, 7.452516e+000, 3.929172e-001, -1.119763e+000, -2.579942e-001, 2.830634e+000, -1.333418e+000, 6.825773e+000, 4.230596e+000, -2.654108e-001, -2.669457e+000, 9.126183e-001, -1.084261e+000, -2.086570e-001, 2.248616e+000, 6.993871e-001, -2.391760e+000, -1.738827e+000, 3.674794e-001, -5.324741e-001, 6.183292e-001, // albedo 1, turbidity 5 -1.226325e+000, -2.688667e-001, -1.462040e-001, 4.749868e-001, -8.718681e-002, 4.956704e-001, 1.752427e-001, 2.933911e+000, 6.470198e-001, -1.359737e+000, -3.985716e-001, -1.570034e-001, 1.277905e+000, -1.314322e+000, 4.320873e-001, 8.532731e-002, 2.774395e+000, 6.318556e-001, -1.088212e+000, -1.688766e-001, 1.399098e+000, -3.254950e+000, 4.733557e+000, 2.079183e+000, 1.907990e-001, -9.540048e-001, 8.714774e-001, -1.034524e+000, -1.050729e-002, -8.054376e-001, 1.166351e+001, -1.879498e+001, -3.021428e+000, 7.755251e-001, 4.516574e+000, 4.092690e-001, -1.076150e+000, -2.551781e-001, 2.797790e+000, -5.437950e+000, 9.156159e+000, 3.988462e+000, -2.324172e-001, -2.124766e+000, 8.863276e-001, -1.103432e+000, -2.058047e-001, 2.117130e+000, 2.401558e+000, -5.015370e+000, -1.829480e+000, 4.046378e-001, -2.078794e-001, 6.449045e-001, // albedo 1, turbidity 6 -1.263516e+000, -3.133966e-001, 3.174560e-001, -4.989246e-003, -2.317630e+000, 3.963746e-001, 1.677262e-001, 2.563898e+000, 6.335899e-001, -1.577927e+000, -5.893907e-001, -2.991531e-001, 1.783728e+000, 3.693827e+000, 5.704918e-001, 6.768069e-002, 2.215180e+000, 6.196162e-001, -9.191335e-001, -4.529201e-002, 1.577262e+000, -6.455191e+000, -4.020064e+000, 1.309911e+000, 1.373281e-001, -7.178508e-001, 9.243738e-001, -1.144508e+000, -9.289247e-002, -1.606387e+000, 2.061805e+001, -1.051527e+001, -2.077164e+000, 8.328239e-001, 4.729795e+000, 3.298487e-001, -1.018834e+000, -2.186851e-001, 3.321767e+000, -7.887012e+000, 3.374834e+000, 3.005232e+000, -2.515037e-001, -2.656610e+000, 9.316017e-001, -1.125230e+000, -2.422532e-001, 1.850916e+000, 6.213105e+000, -5.017914e+000, -1.644457e+000, 3.811828e-001, -1.772362e-001, 6.297360e-001, // albedo 1, turbidity 7 -1.365631e+000, -4.017085e-001, 1.942501e-001, -7.073927e-003, -1.461125e-001, 4.898017e-001, 1.623346e-001, 2.330174e+000, 5.983242e-001, -1.957177e+000, -9.640834e-001, -2.217521e-001, 1.316645e+000, -1.907085e-001, 1.134191e-002, 9.704476e-002, 3.828565e-002, 5.538419e-001, -7.832629e-001, 1.949904e-001, 6.232354e-001, -2.947737e+000, 3.702377e+000, 2.212239e+000, 9.128296e-002, 3.131504e+000, 9.923939e-001, -1.121562e+000, -2.704893e-001, -5.161748e-001, 8.115427e+000, -1.443497e+001, -3.292676e+000, 8.232212e-001, -1.548451e-002, 3.199244e-001, -1.059207e+000, -1.613941e-001, 2.375866e+000, -9.517705e-002, 4.514722e+000, 3.755824e+000, -1.696953e-001, -2.539157e-001, 8.992553e-001, -1.108877e+000, -2.404852e-001, 1.830175e+000, 2.808956e+000, -4.932362e+000, -2.042775e+000, 4.168739e-001, -2.534590e-001, 6.533212e-001, // albedo 1, turbidity 8 -1.405398e+000, -4.540068e-001, -4.766512e-001, 1.871207e-001, 5.535070e-001, -4.467365e-002, 2.846366e-001, 2.443422e+000, 5.035706e-001, -2.843953e+000, -1.562366e+000, 8.527921e-001, 5.991182e-001, -9.984088e-001, 7.599314e-001, -2.025184e-002, -1.515050e+000, 4.397429e-001, -5.156586e-001, 3.789775e-001, -1.194407e+000, -7.591558e-001, 4.515532e+000, 4.795814e-001, 3.163186e-001, 5.993132e+000, 1.096327e+000, -1.070353e+000, -4.037269e-001, 1.108932e+000, 1.269159e+000, -1.099135e+001, -1.049849e+000, 4.644725e-001, -4.387074e+000, 2.704008e-001, -1.136211e+000, -1.473182e-001, 1.235769e+000, 5.725364e+000, 1.712036e+000, 1.630777e+000, 3.656685e-002, 2.082798e+000, 9.036801e-001, -1.083101e+000, -2.468910e-001, 1.894919e+000, 6.574012e+000, -4.949098e+000, -1.132033e+000, 3.336584e-001, -7.321133e-001, 6.606587e-001, // albedo 1, turbidity 9 -1.609910e+000, -6.550380e-001, -5.773346e-001, 1.426156e+000, -5.000686e-001, 8.257866e-001, 1.839148e-002, 2.106656e+000, 6.957214e-001, -3.047283e+000, -1.421592e+000, -4.003615e-001, -6.531692e-001, 5.643821e-001, -2.693762e-001, 2.295553e-001, 5.533910e-001, 2.751822e-002, -2.160824e+000, -9.212504e-001, -8.438420e-001, 1.466021e+000, 1.124686e+000, -6.848173e-002, 6.224893e-001, 3.137662e+000, 1.224147e+000, 1.444817e-002, 1.418426e-001, 7.055176e-001, -1.787432e+000, -1.625625e+000, 7.638401e-001, -3.309940e-001, -3.414755e+000, 3.580691e-001, -1.480512e+000, -3.141638e-001, 1.193403e+000, 6.152773e+000, -3.314867e+000, 1.345353e-001, 5.359935e-001, 1.409582e+000, 8.072343e-001, -1.016066e+000, -2.346375e-001, 1.457587e+000, -2.761458e-003, -2.546952e+000, -6.058542e-001, 3.134230e-001, -2.232281e-001, 6.760089e-001, // albedo 1, turbidity 10 -2.019395e+000, -9.550942e-001, -1.187885e-001, 1.995372e+000, -1.604228e+000, 4.995785e-001, -9.647137e-006, 1.929333e+000, 8.659254e-001, -2.071307e+000, -9.485438e-001, -3.817151e-001, -1.657017e+000, 9.488626e-001, 5.816145e-001, -3.856514e-002, 1.677756e+000, -1.262572e-001, -6.388445e+000, -2.738739e+000, -9.872469e-001, 2.450058e+000, 1.075999e+000, 2.305434e-002, 8.598771e-001, 1.853582e+000, 1.180017e+000, 1.742851e+000, 2.950102e-001, 1.015937e+000, -2.511194e+000, -3.829361e+000, -1.126698e-001, -4.564605e-001, -2.097128e+000, 4.012648e-001, -1.845177e+000, -3.242819e-001, 7.060963e-001, 7.747868e+000, -1.721532e+000, 6.057347e-001, 4.266212e-001, 3.153697e-001, 7.958222e-001, -9.599955e-001, -3.732025e-001, 1.381129e+000, -3.983023e-003, -1.941446e+000, -5.943490e-001, 2.269207e-001, -7.249738e-001, 6.710888e-001, }; static float datasetRad680[] = { // albedo 0, turbidity 1 1.320908e-002, 9.179272e-003, 2.540842e-002, 3.413687e-002, 2.736575e-002, 2.799241e-002, // albedo 0, turbidity 2 1.364418e-002, 9.639315e-003, 2.455688e-002, 5.468867e-002, 2.423200e-002, 3.240293e-002, // albedo 0, turbidity 3 1.356642e-002, 9.864007e-003, 2.017166e-002, 8.738638e-002, 2.138981e-002, 3.828822e-002, // albedo 0, turbidity 4 1.274664e-002, 1.046958e-002, 7.076299e-003, 1.378101e-001, 2.058352e-002, 4.607358e-002, // albedo 0, turbidity 5 1.151617e-002, 1.429568e-002, -1.804673e-002, 1.974118e-001, 1.313176e-002, 5.733295e-002, // albedo 0, turbidity 6 1.089311e-002, 1.719127e-002, -3.582843e-002, 2.315641e-001, 1.402940e-002, 6.289477e-002, // albedo 0, turbidity 7 9.705879e-003, 2.218462e-002, -6.221073e-002, 2.771148e-001, 1.651339e-002, 7.346287e-002, // albedo 0, turbidity 8 8.356372e-003, 2.724501e-002, -8.836051e-002, 3.099528e-001, 4.114206e-002, 8.518889e-002, // albedo 0, turbidity 9 7.026434e-003, 2.944084e-002, -9.824183e-002, 2.940735e-001, 1.048477e-001, 1.012199e-001, // albedo 0, turbidity 10 5.935885e-003, 2.429070e-002, -7.239967e-002, 1.895904e-001, 2.306596e-001, 1.177261e-001, // albedo 1, turbidity 1 1.370741e-002, 1.011873e-002, 2.499587e-002, 3.362880e-002, 6.416750e-002, 6.673258e-002, // albedo 1, turbidity 2 1.417558e-002, 1.065771e-002, 2.402602e-002, 5.330606e-002, 6.505571e-002, 7.324558e-002, // albedo 1, turbidity 3 1.406012e-002, 1.182138e-002, 1.636956e-002, 9.161153e-002, 6.031840e-002, 8.638638e-002, // albedo 1, turbidity 4 1.321071e-002, 1.310944e-002, 1.017467e-003, 1.450040e-001, 6.291618e-002, 1.003625e-001, // albedo 1, turbidity 5 1.194910e-002, 1.687076e-002, -2.332212e-002, 2.021394e-001, 6.093196e-002, 1.177929e-001, // albedo 1, turbidity 6 1.126778e-002, 1.905450e-002, -3.804088e-002, 2.298767e-001, 7.038318e-002, 1.240367e-001, // albedo 1, turbidity 7 1.025282e-002, 2.337214e-002, -6.236283e-002, 2.708195e-001, 7.801793e-002, 1.406577e-001, // albedo 1, turbidity 8 9.018216e-003, 2.718840e-002, -8.215497e-002, 2.866465e-001, 1.194106e-001, 1.556975e-001, // albedo 1, turbidity 9 7.747698e-003, 2.701679e-002, -8.076599e-002, 2.419548e-001, 2.126954e-001, 1.683085e-001, // albedo 1, turbidity 10 6.701188e-003, 2.085440e-002, -5.068221e-002, 1.256935e-001, 3.480598e-001, 1.851691e-001, }; static float dataset720[] = { // albedo 0, turbidity 1 -1.110553e+000, -1.675726e-001, -2.349324e-001, 2.433790e+000, -1.342878e-001, 1.755516e+000, -1.879493e-006, 1.509217e+000, 7.216495e-001, -1.149960e+000, -2.418229e-001, 2.341927e+000, 1.486508e-001, -4.333388e-001, 9.028740e-001, 9.450710e-003, -3.134790e-001, 5.923234e-001, -9.702430e-001, -5.384657e-002, 3.025898e+000, -6.450284e-001, 9.728166e-001, 3.532967e+000, -2.429753e-002, 1.343614e+000, 1.067807e+000, -1.278773e+000, -2.072018e-001, -2.458359e-001, 3.749133e-001, -9.580484e+000, 3.066020e-001, 4.056471e-002, 4.343208e+000, 1.865704e-001, -9.511618e-001, -1.674143e-001, 4.195842e+000, -1.205785e-001, 2.160133e+000, 3.048813e+000, -4.826924e-002, -3.779096e+000, 1.024834e+000, -1.095577e+000, -1.855865e-001, 1.973593e+000, 7.894097e-002, 9.578182e-001, 8.565674e-001, 4.663966e-002, 7.375811e-001, 5.577192e-001, // albedo 0, turbidity 2 -1.099352e+000, -1.338612e-001, -8.419373e-001, 2.710346e+000, -2.241044e-001, 1.645463e+000, 7.621625e-002, 3.548772e+000, 7.268231e-001, -1.140694e+000, -1.723890e-001, 1.413194e+000, 3.429051e-001, -4.431396e-001, 9.757402e-001, 1.248306e-001, 1.780103e+000, 6.637254e-001, -9.861499e-001, -8.032931e-002, 2.396682e+000, 7.281382e-001, 1.472495e-001, 3.316479e+000, -1.028439e-001, 3.729469e+000, 9.059004e-001, -1.233397e+000, -9.896833e-002, -1.679568e+000, 1.542653e+000, -9.977726e+000, -6.579124e-001, 6.386315e-001, 6.157752e+000, 3.985939e-001, -9.438092e-001, -1.629239e-001, 4.213446e+000, -3.419684e-001, 2.110121e+000, 3.552183e+000, -2.817116e-001, -3.323718e+000, 8.785077e-001, -1.120794e+000, -2.121477e-001, 1.326767e+000, 2.317528e-001, 5.648291e-001, 4.155089e-001, 3.048162e-001, 3.186797e-001, 6.285665e-001, // albedo 0, turbidity 3 -1.117191e+000, -1.510453e-001, -3.511136e-001, 1.706946e+000, -3.820460e-001, 1.228101e+000, 1.641555e-001, 3.663544e+000, 6.846104e-001, -1.130950e+000, -1.622534e-001, 1.197076e+000, -1.342532e+000, 6.608991e-002, -1.955817e-001, 3.515286e-001, 3.237403e+000, 5.732364e-001, -1.103903e+000, -1.810472e-001, 1.254237e+000, 3.367565e+000, -1.746589e+000, 4.464939e+000, -2.831757e-001, -2.424241e-001, 9.961252e-001, -1.107818e+000, -2.407723e-002, -7.518594e-001, 7.115830e+000, -1.603375e+001, -4.077248e+000, 1.210904e+000, 6.281392e+000, 2.496837e-001, -1.012153e+000, -1.911658e-001, 2.357463e+000, -2.392720e+000, 7.080581e+000, 6.002768e+000, -5.120158e-001, -2.039879e+000, 1.008071e+000, -1.083766e+000, -1.889743e-001, 1.669813e+000, 1.205140e+000, -2.973102e+000, -1.420288e+000, 5.838643e-001, 1.338574e-001, 5.902153e-001, // albedo 0, turbidity 4 -1.176390e+000, -2.045914e-001, -1.035177e+000, 1.521425e+000, -9.698257e-002, 7.561111e-001, 2.338582e-001, 3.264500e+000, 6.520267e-001, -1.132876e+000, -1.921539e-001, 9.661015e-001, -2.470184e-001, -5.825797e-001, 5.044517e-001, 1.418233e-001, 4.416172e+000, 6.580570e-001, -1.296062e+000, -2.855719e-001, 1.143329e+000, -1.640682e+000, 1.921828e+000, 1.625086e+000, 5.248871e-001, -3.757434e+000, 7.293814e-001, -9.026255e-001, 2.670242e-002, -8.632572e-001, 7.076787e+000, -1.407525e+001, -1.251814e+000, 1.806495e-001, 6.575978e+000, 6.367149e-001, -1.103623e+000, -1.818983e-001, 1.490037e+000, -3.276017e+000, 6.936153e+000, 2.689183e+000, 5.705211e-001, -1.354153e+000, 7.095230e-001, -1.049370e+000, -1.854814e-001, 1.385509e+000, 1.714977e+000, -3.205204e+000, -1.161420e-001, 3.453320e-001, 4.355508e-001, 7.115006e-001, // albedo 0, turbidity 5 -1.225291e+000, -2.574996e-001, -4.766919e-001, 4.951357e-001, 5.242961e-002, 4.702062e-001, 2.428653e-001, 3.095075e+000, 6.424221e-001, -1.318856e+000, -3.713082e-001, -4.987985e-001, 2.026237e+000, -1.457426e+000, 7.809557e-001, 1.419197e-003, 2.776845e+000, 7.058454e-001, -1.168038e+000, -1.572586e-001, 1.786834e+000, -4.594005e+000, 4.780600e+000, 1.639416e+000, 5.324063e-001, -1.000719e+000, 7.325083e-001, -9.862998e-001, -7.482649e-002, -1.332445e+000, 1.329260e+001, -1.803019e+001, -2.669936e+000, 3.591475e-001, 3.852972e+000, 5.714399e-001, -1.049025e+000, -1.404280e-001, 1.342894e+000, -5.633938e+000, 8.396123e+000, 3.809869e+000, 4.313231e-001, -5.373938e-001, 7.693298e-001, -1.069033e+000, -2.091865e-001, 1.088280e+000, 3.125506e+000, -4.664580e+000, -1.191484e+000, 5.195344e-001, 3.961673e-001, 6.817393e-001, // albedo 0, turbidity 6 -1.267895e+000, -3.004228e-001, -5.149611e-001, 4.302967e-001, 1.504018e-001, 3.700643e-001, 2.354209e-001, 2.887788e+000, 6.298388e-001, -1.551925e+000, -5.917820e-001, -5.915642e-001, 2.016019e+000, -1.252286e+000, 8.651065e-001, 7.721402e-003, 1.148828e+000, 6.589887e-001, -9.782795e-001, 3.652455e-002, 1.331304e+000, -4.804135e+000, 5.130801e+000, 1.052586e+000, 4.439877e-001, 2.100157e+000, 8.308236e-001, -1.077598e+000, -2.015253e-001, -1.037818e+000, 1.307045e+001, -1.715211e+001, -1.607252e+000, 4.472382e-001, 6.802371e-001, 4.848934e-001, -1.025969e+000, -1.170376e-001, 1.139546e+000, -3.374680e+000, 6.330035e+000, 2.199093e+000, 3.928627e-001, 8.428666e-001, 7.960910e-001, -1.062382e+000, -1.881842e-001, 8.863153e-001, 4.266858e+000, -5.011692e+000, -4.086830e-001, 5.889147e-001, 5.341939e-001, 6.866073e-001, // albedo 0, turbidity 7 -1.352417e+000, -3.836953e-001, -5.951560e-001, 4.053297e-001, 2.468304e-001, 2.565711e-001, 2.321365e-001, 2.512376e+000, 6.089904e-001, -1.976438e+000, -9.152777e-001, -4.417666e-001, 1.790189e+000, -1.085567e+000, 4.562228e-001, 2.133332e-002, 4.989856e-001, 6.257100e-001, -7.197412e-001, 2.165210e-001, 6.233215e-001, -3.960686e+000, 4.694083e+000, 2.062797e+000, 3.121864e-001, 2.942681e+000, 8.846033e-001, -1.189984e+000, -3.151612e-001, -5.020073e-001, 1.015136e+001, -1.483684e+001, -3.476730e+000, 6.049863e-001, -1.941153e-001, 4.281015e-001, -9.781383e-001, -8.764833e-002, 8.290915e-001, 1.086960e-001, 4.467570e+000, 3.905633e+000, 1.975895e-001, 6.964295e-001, 8.333166e-001, -1.081242e+000, -2.051949e-001, 6.056482e-001, 5.219268e+000, -4.410608e+000, -1.963212e+000, 7.277904e-001, 8.509624e-001, 6.689251e-001, // albedo 0, turbidity 8 -1.443212e+000, -4.725757e-001, -9.477961e-001, 2.671049e-001, 6.163577e-001, -3.965036e-001, 4.071134e-001, 2.464218e+000, 4.997820e-001, -3.021428e+000, -1.558459e+000, 1.389763e-001, 1.122031e+000, -1.014816e+000, 1.265687e+000, -1.649604e-001, -6.627923e-001, 5.494665e-001, -1.593477e-001, 5.076305e-001, -7.283933e-001, -1.265076e+000, 3.904153e+000, -8.196757e-002, 6.585734e-001, 4.998464e+000, 9.330667e-001, -1.378374e+000, -5.064534e-001, 7.231197e-001, 1.385088e+000, -9.500118e+000, -4.806746e-001, 1.067642e-001, -3.297209e+000, 4.441955e-001, -9.436176e-001, -6.189764e-002, 1.144482e-001, 9.137694e+000, 2.948867e-001, 1.224655e+000, 3.675148e-001, 2.124090e+000, 8.014519e-001, -1.078915e+000, -2.051854e-001, 4.754209e-001, 5.826389e-003, -2.498632e+000, -8.265078e-001, 7.644670e-001, 6.066256e-001, 6.811963e-001, // albedo 0, turbidity 9 -1.621711e+000, -6.425839e-001, -7.307813e-001, 1.109519e+000, -4.107299e-001, 7.789953e-001, 7.764812e-002, 2.335627e+000, 6.230915e-001, -4.003597e+000, -1.736865e+000, -6.062450e-001, -7.370264e-001, 7.002778e-001, -4.140325e-001, 3.926087e-001, 8.316399e-001, 1.516341e-001, -7.696712e-001, -3.872306e-001, -1.159436e+000, 1.660752e+000, 2.031840e+000, -7.697685e-001, 5.481684e-001, 2.788249e+000, 1.112977e+000, -8.506589e-001, -5.430791e-002, 1.088719e+000, -2.513532e+000, -4.144477e+000, 2.760914e+000, -3.011272e-001, -2.383556e+000, 4.496070e-001, -1.150061e+000, -3.009215e-001, -9.176868e-002, 8.996074e+000, -1.753862e+000, -2.428423e+000, 5.764492e-001, 1.218492e+000, 7.552230e-001, -1.020853e+000, -1.499849e-001, 3.437744e-001, -2.339597e-003, -2.646520e+000, 1.378457e+000, 6.708410e-001, 9.149680e-001, 6.961806e-001, // albedo 0, turbidity 10 -1.982394e+000, -9.369621e-001, -3.767595e-001, 2.514582e+000, -1.501415e+000, 6.258952e-001, -5.260430e-006, 2.100142e+000, 7.824077e-001, -3.432415e+000, -1.264283e+000, -9.042363e-001, -2.930432e+000, 8.249096e-001, 7.244840e-001, 3.055253e-002, 2.527405e+000, -2.107031e-003, -4.333533e+000, -2.156157e+000, -8.341654e-001, 5.048387e+000, 1.803580e+000, -9.318434e-001, 1.085401e+000, 8.728330e-001, 1.050061e+000, 4.889224e-001, 5.956721e-002, 8.445388e-001, -7.479177e+000, -4.049292e+000, 1.199966e+000, -7.060560e-001, -9.742353e-001, 4.893674e-001, -1.347508e+000, -1.874523e-001, -5.063342e-002, 1.299813e+001, -1.707387e+000, -4.076088e-001, 6.119042e-001, 3.717790e-001, 7.662157e-001, -1.047037e+000, -3.743109e-001, 3.452375e-001, -3.615559e-003, -2.169432e+000, -7.166880e-002, 3.747046e-001, 2.746126e-001, 6.773818e-001, // albedo 1, turbidity 1 -1.105396e+000, -1.663441e-001, -2.359634e-001, 2.476496e+000, -1.329052e-001, 1.715759e+000, 2.103991e-003, 1.421966e+000, 6.270733e-001, -1.132480e+000, -2.330883e-001, 2.273938e+000, 2.422717e-001, -4.159883e-001, 9.350714e-001, 1.432347e-002, -4.176684e-001, 4.664640e-001, -1.036155e+000, -9.432450e-002, 3.117262e+000, -6.369808e-001, 1.060389e+000, 3.386481e+000, -4.605081e-002, 1.248000e+000, 9.701974e-001, -1.162485e+000, -1.382303e-001, 1.544122e-001, 3.716511e-001, -9.520209e+000, -2.739605e-001, 8.489054e-002, 4.371570e+000, 7.694391e-002, -1.031787e+000, -2.165067e-001, 4.446666e+000, -1.470711e-001, 2.143436e+000, 1.922123e+000, -9.589030e-002, -3.594664e+000, 8.629249e-001, -1.081125e+000, -1.623953e-001, 2.048137e+000, 8.639386e-002, 1.225845e+000, 1.239255e-001, 8.366038e-002, 8.322625e-001, 5.604708e-001, // albedo 1, turbidity 2 -1.112606e+000, -1.514491e-001, -1.608942e+000, 3.592344e+000, -1.616115e-001, 1.593861e+000, 5.488306e-002, 2.854783e+000, 7.519999e-001, -1.098630e+000, -1.410161e-001, 2.155487e+000, -4.381610e-001, -3.635146e-001, 1.313843e+000, 1.201277e-001, 2.469958e+000, 6.481071e-001, -1.077575e+000, -1.275645e-001, 1.418205e+000, 2.057232e+000, -7.778503e-002, 2.433840e+000, -7.094034e-002, 3.347259e+000, 9.344752e-001, -1.099714e+000, -4.474282e-002, -1.247041e-001, -1.578342e-001, -7.968895e+000, 1.730912e-001, 5.303765e-001, 5.523179e+000, 3.840340e-001, -1.061945e+000, -2.200148e-001, 4.333103e+000, 1.818948e-002, 1.907751e+000, 1.560633e+000, -3.182192e-001, -3.010282e+000, 8.844351e-001, -1.087782e+000, -1.709041e-001, 1.834683e+000, 7.351214e-002, 1.282669e+000, 2.075884e-001, 2.698971e-001, 3.373859e-001, 5.808336e-001, // albedo 1, turbidity 3 -1.121417e+000, -1.551220e-001, -1.527123e+000, 2.788105e+000, -1.477847e-001, 1.152139e+000, 1.742181e-001, 3.473417e+000, 6.737050e-001, -1.118910e+000, -1.496848e-001, 2.736873e+000, -1.829596e+000, -3.411991e-001, 1.177538e-001, 2.960683e-001, 3.273898e+000, 5.743833e-001, -1.121145e+000, -1.980292e-001, -5.407002e-001, 2.886807e+000, 4.877852e-001, 3.692424e+000, -1.104033e-001, -2.358878e-001, 9.976295e-001, -1.078889e+000, -1.541161e-003, 1.370650e+000, 1.644450e+000, -1.425572e+001, -3.075430e+000, 9.346385e-001, 5.871863e+000, 2.618026e-001, -1.053346e+000, -2.262166e-001, 2.532003e+000, -8.720058e-001, 7.667901e+000, 4.357082e+000, -5.367969e-001, -2.073329e+000, 1.023965e+000, -1.100093e+000, -1.810893e-001, 2.566430e+000, 4.757700e-001, -2.069684e+000, -1.585209e+000, 4.693140e-001, -6.719615e-001, 5.569453e-001, // albedo 1, turbidity 4 -1.181528e+000, -2.151896e-001, -1.076470e+000, 2.037517e+000, -1.683559e-001, 8.780110e-001, 1.782773e-001, 2.768650e+000, 6.743293e-001, -1.142132e+000, -1.825403e-001, 1.320992e+000, -1.895472e+000, -2.160241e-001, -2.079637e-001, 3.424953e-001, 4.333355e+000, 5.663420e-001, -1.225408e+000, -2.906477e-001, 8.323962e-001, 2.176300e+000, 1.943859e+000, 3.003671e+000, 1.130255e-001, -4.449977e+000, 8.867390e-001, -9.815988e-001, 5.577004e-002, -4.240348e-001, 1.488466e+000, -1.279361e+001, -3.110899e+000, 7.360104e-001, 7.937751e+000, 4.474817e-001, -1.103439e+000, -2.481553e-001, 3.045691e+000, -6.993993e-001, 6.081464e+000, 3.986228e+000, -1.616828e-001, -3.373973e+000, 8.572294e-001, -1.081695e+000, -1.943361e-001, 2.303236e+000, 3.906537e-001, -1.498982e+000, -1.372140e+000, 3.379214e-001, -4.953601e-001, 6.521383e-001, // albedo 1, turbidity 5 -1.235776e+000, -2.745978e-001, 2.205316e-002, 4.505193e-001, -1.569202e-001, 5.065039e-001, 2.016320e-001, 2.449382e+000, 6.535188e-001, -1.268478e+000, -3.078367e-001, -2.041769e-001, 1.189583e+000, -1.311782e+000, 4.724677e-001, 1.025764e-001, 3.300615e+000, 6.689797e-001, -1.190389e+000, -2.597641e-001, 1.377486e+000, -2.289003e+000, 4.214767e+000, 1.900318e+000, 3.126604e-001, -2.537399e+000, 7.980811e-001, -9.632300e-001, 7.067379e-002, -6.690546e-001, 9.507059e+000, -1.721426e+001, -2.850631e+000, 6.931159e-001, 5.722238e+000, 4.856193e-001, -1.119689e+000, -3.019499e-001, 2.657474e+000, -5.208105e+000, 1.015200e+001, 3.863887e+000, -1.603721e-001, -3.132328e+000, 8.543154e-001, -1.078742e+000, -1.840880e-001, 2.341448e+000, 2.576821e+000, -5.011296e+000, -1.671996e+000, 3.955131e-001, -4.700684e-001, 6.516593e-001, // albedo 1, turbidity 6 -1.263449e+000, -3.016185e-001, -1.680842e-001, 4.791728e-001, -8.989862e-002, 5.069014e-001, 1.892810e-001, 2.535339e+000, 6.506411e-001, -1.544305e+000, -5.656222e-001, -2.084263e-001, 1.312304e+000, -8.580598e-001, 4.039133e-001, 1.008588e-001, 1.268784e+000, 6.333075e-001, -9.436041e-001, -1.620107e-002, 1.253874e+000, -3.499120e+000, 4.452594e+000, 1.870490e+000, 1.524710e-001, 8.031346e-001, 8.930942e-001, -1.106718e+000, -1.102586e-001, -8.803979e-001, 1.326904e+001, -1.878253e+001, -2.994671e+000, 9.501205e-001, 2.284893e+000, 3.662824e-001, -1.048783e+000, -2.156089e-001, 2.786728e+000, -4.862603e+000, 8.438175e+000, 3.683031e+000, -3.092444e-001, -1.293934e+000, 9.110045e-001, -1.108140e+000, -2.156079e-001, 2.181504e+000, 2.124553e+000, -5.007442e+000, -1.711417e+000, 4.904871e-001, -8.710312e-001, 6.376965e-001, // albedo 1, turbidity 7 -1.345282e+000, -3.856197e-001, -1.975094e-001, 3.016919e-001, 2.765844e-001, 2.092275e-001, 2.251325e-001, 2.058589e+000, 6.014266e-001, -1.907309e+000, -8.881952e-001, -4.827860e-001, 1.495665e+000, -9.243173e-001, 3.864061e-001, 7.491538e-002, 2.719526e-001, 6.046039e-001, -7.540737e-001, 1.800167e-001, 1.174575e+000, -3.052295e+000, 4.669060e+000, 1.793876e+000, 1.664066e-001, 2.376187e+000, 9.261122e-001, -1.165479e+000, -2.500464e-001, -9.603937e-001, 8.919733e+000, -1.561899e+001, -2.850650e+000, 8.368531e-001, 3.404393e-001, 3.694265e-001, -1.032259e+000, -1.593662e-001, 2.621639e+000, -5.369281e-001, 6.011517e+000, 3.234312e+000, -1.842335e-001, -3.749684e-001, 8.913063e-001, -1.119906e+000, -2.533313e-001, 2.017975e+000, 4.776492e-001, -5.005474e+000, -1.503414e+000, 4.694448e-001, -1.039200e+000, 6.438630e-001, // albedo 1, turbidity 8 -1.457842e+000, -4.806585e-001, -6.807833e-001, 2.682520e-001, 5.586195e-001, -2.806536e-001, 3.694491e-001, 2.169304e+000, 4.997873e-001, -2.906600e+000, -1.558470e+000, 4.048869e-001, 1.012321e+000, -8.709928e-001, 9.025637e-001, -9.171486e-002, -1.279805e+000, 5.327924e-001, -2.500868e-001, 5.175467e-001, -4.366020e-001, -1.156645e+000, 3.657335e+000, 4.092973e-001, 4.611188e-001, 4.971048e+000, 9.789196e-001, -1.282240e+000, -4.792753e-001, 3.824491e-001, 2.061672e+000, -9.474747e+000, -1.080446e+000, 3.852100e-001, -3.234591e+000, 3.696703e-001, -1.046065e+000, -1.097023e-001, 1.672284e+000, 4.799701e+000, 1.286403e+000, 1.712569e+000, 1.099301e-001, 1.214451e+000, 8.572886e-001, -1.104124e+000, -2.576744e-001, 1.919030e+000, -1.296687e-003, -3.500874e+000, -1.048831e+000, 3.929400e-001, -9.229794e-001, 6.687909e-001, // albedo 1, turbidity 9 -1.658918e+000, -6.637256e-001, -1.162850e+000, 1.829549e+000, -2.525065e-001, 8.624803e-001, 5.214746e-002, 1.977784e+000, 6.455044e-001, -3.553256e+000, -1.639022e+000, -8.821743e-001, -2.660037e-001, 5.168738e-001, -8.582770e-001, 4.110780e-001, 1.034123e-001, 1.039852e-001, -1.299367e+000, -4.890457e-001, -5.595307e-001, 1.129115e+000, 5.445041e-001, 5.361314e-001, 4.579589e-001, 3.385708e+000, 1.184267e+000, -4.366852e-001, -2.303554e-002, 5.417530e-001, -9.106900e-001, -4.398484e-001, 3.178252e-001, -2.132156e-001, -3.682761e+000, 3.754470e-001, -1.334075e+000, -2.466639e-001, 1.293237e+000, 4.685982e+000, -4.032879e+000, 4.666293e-001, 5.337822e-001, 1.603290e+000, 8.067400e-001, -1.052460e+000, -2.501759e-001, 1.601487e+000, 1.713504e+000, -2.810006e+000, -8.042597e-001, 3.216101e-001, -5.944876e-001, 6.740783e-001, // albedo 1, turbidity 10 -1.974746e+000, -9.111910e-001, -2.159155e-001, 2.437415e+000, -1.592257e+000, 6.133797e-001, -6.243023e-006, 1.960399e+000, 7.806415e-001, -2.677119e+000, -1.100702e+000, -6.847246e-001, -2.820855e+000, 1.577837e+000, 6.243833e-001, 2.218481e-002, 1.568717e+000, 2.327673e-002, -5.323827e+000, -2.461050e+000, -3.941307e-001, 4.908417e+000, -1.657232e-001, -9.501763e-001, 1.063520e+000, 1.455622e+000, 9.781890e-001, 1.325000e+000, 3.538115e-001, 1.783573e-001, -6.903650e+000, -8.079921e-001, 1.215973e+000, -6.852540e-001, -1.735835e+000, 5.744662e-001, -1.741196e+000, -3.448017e-001, 1.242377e+000, 1.098613e+001, -3.386782e+000, -3.128683e-001, 5.792848e-001, 1.364330e-002, 7.112763e-001, -9.762671e-001, -3.368355e-001, 1.374728e+000, -3.312353e-003, -2.576919e+000, -1.778015e-001, 2.024288e-001, -6.128666e-001, 6.917938e-001, }; static float datasetRad720[] = { // albedo 0, turbidity 1 1.130152e-002, 8.671843e-003, 2.004792e-002, 2.515879e-002, 2.020140e-002, 2.117353e-002, // albedo 0, turbidity 2 1.224368e-002, 8.839480e-003, 2.189489e-002, 4.083873e-002, 1.919064e-002, 2.455945e-002, // albedo 0, turbidity 3 1.252249e-002, 8.009335e-003, 2.371432e-002, 6.397292e-002, 2.042384e-002, 2.862112e-002, // albedo 0, turbidity 4 1.180325e-002, 8.958479e-003, 1.183940e-002, 1.148189e-001, 1.354571e-002, 3.848691e-002, // albedo 0, turbidity 5 1.085725e-002, 1.134459e-002, -7.554548e-003, 1.671603e-001, 8.431212e-003, 4.772824e-002, // albedo 0, turbidity 6 1.014547e-002, 1.403737e-002, -2.479898e-002, 2.032831e-001, 5.127749e-003, 5.409735e-002, // albedo 0, turbidity 7 9.143208e-003, 1.825961e-002, -4.902126e-002, 2.473204e-001, 7.992708e-003, 6.238918e-002, // albedo 0, turbidity 8 7.784746e-003, 2.352715e-002, -7.647231e-002, 2.868914e-001, 2.581232e-002, 7.345921e-002, // albedo 0, turbidity 9 6.425568e-003, 2.680506e-002, -9.216963e-002, 2.866525e-001, 7.712816e-002, 8.877708e-002, // albedo 0, turbidity 10 5.348459e-003, 2.347534e-002, -7.499904e-002, 2.035369e-001, 1.874982e-001, 1.045961e-001, // albedo 1, turbidity 1 1.168435e-002, 9.445039e-003, 1.950520e-002, 2.563333e-002, 4.729214e-002, 5.096829e-002, // albedo 1, turbidity 2 1.252521e-002, 1.012940e-002, 2.002302e-002, 4.276714e-002, 4.778275e-002, 5.748908e-002, // albedo 1, turbidity 3 1.285682e-002, 9.705956e-003, 2.018767e-002, 6.797612e-002, 5.181662e-002, 6.548541e-002, // albedo 1, turbidity 4 1.218970e-002, 1.070161e-002, 8.436124e-003, 1.177409e-001, 5.124773e-002, 8.069723e-002, // albedo 1, turbidity 5 1.129406e-002, 1.339498e-002, -1.193989e-002, 1.709051e-001, 5.001995e-002, 9.558448e-002, // albedo 1, turbidity 6 1.056724e-002, 1.570995e-002, -2.759057e-002, 2.030760e-001, 5.311962e-002, 1.037882e-001, // albedo 1, turbidity 7 9.594077e-003, 1.966415e-002, -5.024827e-002, 2.432607e-001, 6.172355e-002, 1.169276e-001, // albedo 1, turbidity 8 8.348105e-003, 2.415281e-002, -7.475064e-002, 2.748209e-001, 8.753187e-002, 1.356651e-001, // albedo 1, turbidity 9 7.106169e-003, 2.513833e-002, -7.928946e-002, 2.463668e-001, 1.685984e-001, 1.485820e-001, // albedo 1, turbidity 10 6.031610e-003, 2.016534e-002, -5.448075e-002, 1.436689e-001, 2.971830e-001, 1.639884e-001, }; static float *datasets[] = {dataset320, dataset360, dataset400, dataset440, dataset480, dataset520, dataset560, dataset600, dataset640, dataset680, dataset720}; static float *datasetsRad[] = {datasetRad320, datasetRad360, datasetRad400, datasetRad440, datasetRad480, datasetRad520, datasetRad560, datasetRad600, datasetRad640, datasetRad680, datasetRad720}; // Uses Feb 9 dataset static float solarDataset320[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.162049e+02, 4.610588e+00, 0, 0, -3.824759e+00, 1.338698e+01, 5.595274e-02, 3.125000e-04, -2.161500e+03, 1.113209e+02, 3.458172e-01, 2.500000e-03, 8.294600e+01, 1.711252e+02, 2.111274e+00, 1.984375e-02, -4.229939e+03, 6.275308e+02, 6.980643e+00, 8.375000e-02, -1.740178e+04, 1.708634e+03, 2.367820e+01, 3.350000e-01, -1.976851e+04, 2.817040e+03, 6.781352e+01, 1.193125e+00, -3.810737e+04, 4.836590e+03, 1.556846e+02, 3.466250e+00, -4.549929e+04, 6.516914e+03, 3.119331e+02, 8.744219e+00, -5.263436e+04, 8.036785e+03, 5.455303e+02, 1.930562e+01, -6.309578e+04, 9.205958e+03, 8.581439e+02, 3.815516e+01, -4.954890e+04, 8.736703e+03, 1.229615e+03, 6.870672e+01, -6.343828e+04, 9.001550e+03, 1.628815e+03, 1.138184e+02, -3.475406e+04, 6.615408e+03, 2.019023e+03, 1.763652e+02, -4.201833e+04, 6.105544e+03, 2.362030e+03, 2.567578e+02, -2.667604e+04, 4.055614e+03, 2.646799e+03, 3.559691e+02, -2.036310e+04, 2.748587e+03, 2.846313e+03, 4.723367e+02, -2.032124e+04, 1.878732e+03, 2.969980e+03, 6.041547e+02, -1.073640e+04, 4.777580e+02, 3.009645e+03, 7.491283e+02, -1.005389e+04, -3.672131e+01, 2.973858e+03, 9.033814e+02, -1.030868e+04, -4.464229e+02, 2.879841e+03, 1.064085e+03, -2.157918e+03, -1.342683e+03, 2.723843e+03, 1.227711e+03, -3.651657e+03, -1.197013e+03, 2.534012e+03, 1.389789e+03, -7.289195e+03, -9.708760e+02, 2.331442e+03, 1.548851e+03, -7.704469e+02, -1.628402e+03, 2.093848e+03, 1.702493e+03, -4.214558e+03, -1.153021e+03, 1.844767e+03, 1.845862e+03, -2.390689e+03, -1.287373e+03, 1.593697e+03, 1.978602e+03, -6.413034e+03, -8.008887e+02, 1.339243e+03, 2.097559e+03, -2.988481e+03, -1.136665e+03, 1.064931e+03, 2.201486e+03, -6.139876e+03, -5.991924e+02, 7.913266e+02, 2.285209e+03, -1.196221e+04, 1.344918e+02, 5.186582e+02, 2.348895e+03, -5.971683e+03, -6.555303e+01, 2.013157e+02, 2.389728e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.229445e+02, 7.374485e+00, 0, 0, -1.231740e+01, 1.262553e+01, 7.960490e-02, 4.687500e-04, -2.643352e+02, 5.605647e+01, 3.498905e-01, 2.812500e-03, -2.454452e+03, 2.369608e+02, 1.620789e+00, 1.531250e-02, -4.320948e+03, 5.952227e+02, 6.834726e+00, 7.828125e-02, -1.272903e+04, 1.474486e+03, 2.244014e+01, 3.187500e-01, -1.829132e+04, 2.679893e+03, 6.267850e+01, 1.107500e+00, -3.969700e+04, 4.797859e+03, 1.468690e+02, 3.237813e+00, -4.233637e+04, 6.288595e+03, 2.991805e+02, 8.289531e+00, -5.378742e+04, 8.016312e+03, 5.272841e+02, 1.845875e+01, -6.132387e+04, 9.078358e+03, 8.364539e+02, 3.679578e+01, -5.902508e+04, 9.037411e+03, 1.204972e+03, 6.666500e+01, -4.718111e+04, 8.049720e+03, 1.595444e+03, 1.110180e+02, -4.077260e+04, 7.049147e+03, 1.976792e+03, 1.719842e+02, -4.205766e+04, 6.112440e+03, 2.327488e+03, 2.511269e+02, -2.791505e+04, 4.115557e+03, 2.612616e+03, 3.489953e+02, -1.609988e+04, 2.510900e+03, 2.810607e+03, 4.639409e+02, -2.314164e+04, 2.163386e+03, 2.938786e+03, 5.940591e+02, -1.330257e+04, 6.221024e+02, 2.986256e+03, 7.378767e+02, -5.675969e+03, -3.846177e+02, 2.945011e+03, 8.909630e+02, -6.495665e+03, -5.518256e+02, 2.852178e+03, 1.049766e+03, -1.215437e+04, -4.405937e+02, 2.722478e+03, 1.212177e+03, 2.719602e+03, -1.879784e+03, 2.530070e+03, 1.375258e+03, -8.647169e+03, -7.569952e+02, 2.319694e+03, 1.532926e+03, -1.867684e+03, -1.528257e+03, 2.092233e+03, 1.686330e+03, -4.025935e+03, -1.211125e+03, 1.840308e+03, 1.829689e+03, -1.081717e+03, -1.411956e+03, 1.583655e+03, 1.961830e+03, -7.350389e+03, -6.622648e+02, 1.334664e+03, 2.079855e+03, -2.343916e+03, -1.205267e+03, 1.063635e+03, 2.183818e+03, -7.430550e+03, -4.556049e+02, 7.931502e+02, 2.267336e+03, -1.068232e+04, -2.114828e+01, 5.135211e+02, 2.331394e+03, -6.217560e+03, -3.350260e+01, 2.024873e+02, 2.371433e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.203441e+02, 4.171995e+00, 0, 0, 1.426480e+02, -4.022426e-01, 2.425240e-02, 1.562500e-04, -4.009478e+01, 1.125399e+01, 5.471435e-02, 4.687500e-04, -6.200072e+02, 5.758122e+01, 2.853042e-01, 2.343750e-03, -6.987267e+02, 1.643846e+02, 1.429285e+00, 1.359375e-02, -5.632468e+03, 5.971678e+02, 5.643686e+00, 6.437500e-02, -1.136274e+04, 1.361972e+03, 2.032334e+01, 2.812500e-01, -1.952933e+04, 2.607796e+03, 5.786257e+01, 1.004844e+00, -3.532941e+04, 4.461645e+03, 1.377803e+02, 3.003125e+00, -4.143687e+04, 6.064540e+03, 2.816662e+02, 7.743281e+00, -5.085245e+04, 7.694233e+03, 5.005985e+02, 1.737797e+01, -6.042859e+04, 8.861458e+03, 7.989383e+02, 3.484813e+01, -5.375945e+04, 8.686126e+03, 1.157257e+03, 6.348969e+01, -4.609594e+04, 8.037224e+03, 1.541142e+03, 1.061803e+02, -5.818693e+04, 7.796026e+03, 1.925333e+03, 1.653475e+02, -1.234873e+04, 4.326471e+03, 2.261366e+03, 2.427720e+02, -4.100578e+04, 5.301137e+03, 2.543132e+03, 3.370997e+02, -2.570418e+04, 3.036407e+03, 2.771427e+03, 4.502481e+02, -9.930667e+03, 1.185082e+03, 2.888544e+03, 5.787917e+02, -1.540011e+04, 1.011847e+03, 2.933616e+03, 7.193989e+02, -8.074592e+03, -9.360958e+01, 2.915801e+03, 8.705267e+02, -1.229699e+04, -1.891092e+02, 2.833288e+03, 1.028212e+03, 1.425166e+02, -1.460737e+03, 2.687065e+03, 1.189614e+03, -7.667229e+03, -7.968169e+02, 2.508850e+03, 1.349517e+03, -2.347845e+03, -1.408348e+03, 2.307273e+03, 1.507527e+03, -4.419120e+03, -1.175822e+03, 2.079767e+03, 1.659044e+03, -4.704423e+03, -1.172710e+03, 1.838621e+03, 1.802379e+03, -3.231727e+01, -1.540847e+03, 1.575896e+03, 1.934311e+03, -7.381753e+03, -6.308022e+02, 1.326603e+03, 2.051421e+03, -2.673977e+03, -1.159966e+03, 1.060234e+03, 2.154908e+03, -6.512200e+03, -5.471063e+02, 7.899642e+02, 2.238250e+03, -9.505497e+03, -1.111579e+02, 5.172803e+02, 2.301960e+03, -6.085971e+03, -7.278179e+01, 2.224392e+02, 2.342608e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.398243e+02, 5.776206e+00, 0, 0, 2.463155e+02, -2.094592e-01, 4.496203e-02, 3.125000e-04, -1.010040e+03, 5.790287e+01, 1.278306e-01, 1.093750e-03, -3.545764e+02, 1.294156e+02, 1.099066e+00, 9.687500e-03, -6.451710e+03, 5.563384e+02, 4.533285e+00, 4.984375e-02, -5.934123e+03, 1.056602e+03, 1.730255e+01, 2.356250e-01, -2.331347e+04, 2.539950e+03, 4.913378e+01, 8.401563e-01, -2.454544e+04, 3.778662e+03, 1.219910e+02, 2.611719e+00, -4.570703e+04, 5.952157e+03, 2.514711e+02, 6.796719e+00, -4.332230e+04, 7.038252e+03, 4.577067e+02, 1.558687e+01, -6.059598e+04, 8.589735e+03, 7.371821e+02, 3.161938e+01, -4.538550e+04, 8.101580e+03, 1.079569e+03, 5.827141e+01, -5.158798e+04, 8.232570e+03, 1.451372e+03, 9.823734e+01, -4.012520e+04, 6.957081e+03, 1.830066e+03, 1.543975e+02, -3.793394e+04, 5.939944e+03, 2.176636e+03, 2.281206e+02, -3.211292e+04, 4.482161e+03, 2.467196e+03, 3.200717e+02, -1.588792e+04, 2.521470e+03, 2.673764e+03, 4.292442e+02, -1.756764e+04, 1.927386e+03, 2.804183e+03, 5.532441e+02, -1.277374e+04, 8.843716e+02, 2.867650e+03, 6.906603e+02, -8.721587e+03, 7.343786e+01, 2.857501e+03, 8.384222e+02, -1.210720e+04, -1.134775e+02, 2.787446e+03, 9.933153e+02, -7.324531e+02, -1.323481e+03, 2.651921e+03, 1.152349e+03, -7.693693e+03, -7.693487e+02, 2.480657e+03, 1.310405e+03, -2.653371e+03, -1.366675e+03, 2.282324e+03, 1.466687e+03, -3.648018e+03, -1.230454e+03, 2.056210e+03, 1.616582e+03, -2.664373e+03, -1.284624e+03, 1.819352e+03, 1.758212e+03, -5.222558e+03, -9.816239e+02, 1.575433e+03, 1.888928e+03, -2.865965e+03, -1.196481e+03, 1.315007e+03, 2.006915e+03, -3.599541e+03, -9.578621e+02, 1.050151e+03, 2.108105e+03, -6.734962e+03, -5.085043e+02, 7.938554e+02, 2.191497e+03, -1.211854e+04, 1.393363e+02, 5.225520e+02, 2.255726e+03, -5.940851e+03, -7.200209e+01, 2.016666e+02, 2.296840e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -5.810245e+01, 2.305294e+00, 0, 0, -4.677095e+01, 7.181418e+00, 2.797637e-02, 1.562500e-04, -2.390763e+02, 3.399401e+01, 1.676014e-01, 1.250000e-03, -1.572353e+03, 1.448172e+02, 9.018003e-01, 8.125000e-03, -1.932258e+03, 3.555380e+02, 4.045229e+00, 4.515625e-02, -8.021604e+03, 1.011597e+03, 1.385505e+01, 1.907813e-01, -1.760146e+04, 2.142284e+03, 4.213012e+01, 7.085938e-01, -2.771190e+04, 3.598579e+03, 1.059734e+02, 2.232031e+00, -2.685562e+04, 4.912314e+03, 2.231363e+02, 5.951250e+00, -5.816933e+04, 7.488614e+03, 4.119772e+02, 1.372719e+01, -5.375236e+04, 7.934157e+03, 6.844993e+02, 2.860453e+01, -4.429083e+04, 7.764848e+03, 1.006186e+03, 5.337641e+01, -4.260900e+04, 7.623473e+03, 1.360246e+03, 9.077234e+01, -4.165134e+04, 7.075685e+03, 1.728438e+03, 1.435205e+02, -4.199611e+04, 6.142734e+03, 2.077584e+03, 2.136358e+02, -1.823240e+04, 3.778736e+03, 2.365364e+03, 3.017798e+02, -2.860530e+04, 3.604470e+03, 2.586318e+03, 4.064622e+02, -1.609512e+04, 1.794040e+03, 2.736939e+03, 5.275606e+02, -1.254070e+04, 8.805854e+02, 2.797800e+03, 6.615970e+02, -6.090084e+03, -5.143658e+01, 2.789103e+03, 8.057959e+02, -1.308790e+04, 9.060229e+01, 2.728964e+03, 9.570091e+02, -1.747122e+03, -1.183227e+03, 2.607217e+03, 1.113144e+03, -4.502060e+03, -9.631705e+02, 2.441686e+03, 1.268743e+03, -4.925191e+03, -1.030626e+03, 2.258761e+03, 1.422545e+03, -4.605435e+03, -1.142309e+03, 2.046600e+03, 1.571669e+03, -2.008970e+03, -1.371278e+03, 1.807372e+03, 1.712698e+03, -4.054953e+03, -1.064272e+03, 1.561721e+03, 1.842282e+03, -4.186489e+03, -1.014859e+03, 1.310764e+03, 1.959238e+03, -4.536370e+03, -8.990475e+02, 1.048215e+03, 2.060568e+03, -4.732931e+03, -7.451517e+02, 7.801005e+02, 2.143593e+03, -1.235209e+04, 2.174097e+02, 5.169935e+02, 2.206104e+03, -6.154950e+03, -5.382014e+01, 2.046788e+02, 2.247203e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.126883e+02, 5.520338e+00, 0, 0, 1.263603e+02, 2.194173e+00, 4.737462e-02, 3.125000e-04, -1.508116e+01, 2.129591e+01, 1.399562e-01, 1.250000e-03, -9.018236e+02, 1.098378e+02, 6.623187e-01, 6.250000e-03, -3.504771e+03, 3.721805e+02, 3.219475e+00, 3.484375e-02, -6.289506e+03, 8.722241e+02, 1.237269e+01, 1.653125e-01, -1.480606e+04, 1.913931e+03, 3.734160e+01, 6.228125e-01, -2.450066e+04, 3.351021e+03, 9.544644e+01, 1.985000e+00, -3.693950e+04, 5.083189e+03, 2.063989e+02, 5.391406e+00, -4.358414e+04, 6.496516e+03, 3.861177e+02, 1.272703e+01, -4.530622e+04, 7.428171e+03, 6.366847e+02, 2.650891e+01, -4.733767e+04, 7.964659e+03, 9.501384e+02, 4.969906e+01, -5.370278e+04, 8.090009e+03, 1.307795e+03, 8.545641e+01, -3.321384e+04, 6.411379e+03, 1.669725e+03, 1.365462e+02, -3.641652e+04, 5.884973e+03, 2.004006e+03, 2.040570e+02, -2.540098e+04, 4.300449e+03, 2.297230e+03, 2.892628e+02, -2.760640e+04, 3.474278e+03, 2.524065e+03, 3.914722e+02, -8.048468e+03, 1.366510e+03, 2.669037e+03, 5.095961e+02, -2.029543e+04, 1.620800e+03, 2.744637e+03, 6.402722e+02, -3.964493e+03, -2.191741e+02, 2.750646e+03, 7.826442e+02, -1.106059e+04, 3.180232e+01, 2.691209e+03, 9.316025e+02, -4.643371e+03, -8.533850e+02, 2.583124e+03, 1.085744e+03, -4.533634e+03, -9.829180e+02, 2.425278e+03, 1.240435e+03, -6.144697e+03, -9.649133e+02, 2.239377e+03, 1.393075e+03, 1.615287e+03, -1.671132e+03, 2.018903e+03, 1.540777e+03, -9.492625e+03, -5.137586e+02, 1.801463e+03, 1.679387e+03, -4.863360e+02, -1.552130e+03, 1.555354e+03, 1.810186e+03, -4.150248e+03, -9.569455e+02, 1.295372e+03, 1.925326e+03, -3.336249e+03, -9.666328e+02, 1.043430e+03, 2.025790e+03, -8.928017e+03, -2.828557e+02, 7.918380e+02, 2.108700e+03, -8.901351e+03, -2.240739e+02, 5.052828e+02, 2.172922e+03, -6.226979e+03, -2.346247e+01, 2.056987e+02, 2.211881e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.915526e+02, 7.366238e+00, 0, 0, 6.163369e+01, 1.204175e+01, 9.225802e-02, 6.250000e-04, -6.773000e+02, 7.896783e+01, 4.201401e-01, 3.750000e-03, -1.616556e+03, 2.639201e+02, 2.241390e+00, 2.343750e-02, -1.059666e+04, 9.232364e+02, 9.386152e+00, 1.187500e-01, -8.791318e+03, 1.500107e+03, 3.211158e+01, 5.154688e-01, -2.227497e+04, 2.999099e+03, 8.091825e+01, 1.660469e+00, -3.111629e+04, 4.548813e+03, 1.797262e+02, 4.607656e+00, -4.734025e+04, 6.313047e+03, 3.438787e+02, 1.107969e+01, -3.301271e+04, 6.534868e+03, 5.771119e+02, 2.356234e+01, -5.497932e+04, 8.077472e+03, 8.696235e+02, 4.460859e+01, -3.691249e+04, 7.075388e+03, 1.212190e+03, 7.774641e+01, -4.535714e+04, 7.102579e+03, 1.562845e+03, 1.251120e+02, -3.169379e+04, 5.490801e+03, 1.899280e+03, 1.890709e+02, -1.728180e+04, 3.949454e+03, 2.183344e+03, 2.698602e+02, -3.714132e+04, 4.285851e+03, 2.423673e+03, 3.672678e+02, -5.215022e+03, 1.183427e+03, 2.583754e+03, 4.816480e+02, -1.863398e+04, 1.625851e+03, 2.661413e+03, 6.081128e+02, -6.406195e+03, 7.803378e+01, 2.681066e+03, 7.464519e+02, -1.136441e+04, 7.752814e+01, 2.632242e+03, 8.920981e+02, -2.047264e+03, -1.002831e+03, 2.526395e+03, 1.042912e+03, -6.248742e+03, -7.263883e+02, 2.379661e+03, 1.194150e+03, -5.489763e+03, -9.816353e+02, 2.205342e+03, 1.344432e+03, -1.167746e+02, -1.486682e+03, 1.991891e+03, 1.489923e+03, -6.259862e+03, -8.113410e+02, 1.773796e+03, 1.626878e+03, -1.374682e+03, -1.342055e+03, 1.539054e+03, 1.755264e+03, -5.056021e+03, -8.353907e+02, 1.295621e+03, 1.869990e+03, -4.537758e+03, -8.790940e+02, 1.044749e+03, 1.970797e+03, -6.706975e+03, -5.509051e+02, 7.801558e+02, 2.053670e+03, -1.020946e+04, -4.372454e+01, 5.016635e+02, 2.116272e+03, -6.221044e+03, -1.982749e+01, 1.997960e+02, 2.155378e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -7.471287e+01, 3.454011e+00, 0, 0, -5.151738e+01, 1.088983e+01, 4.862104e-02, 3.125000e-04, -5.554154e+02, 5.853337e+01, 2.954357e-01, 2.500000e-03, -1.401631e+03, 1.899381e+02, 1.613639e+00, 1.671875e-02, -3.677010e+03, 5.381794e+02, 6.576231e+00, 8.437500e-02, -1.130930e+04, 1.351274e+03, 2.217409e+01, 3.490625e-01, -1.610460e+04, 2.382976e+03, 6.220396e+01, 1.221875e+00, -3.182774e+04, 4.050808e+03, 1.429730e+02, 3.534531e+00, -2.661339e+04, 4.911419e+03, 2.820920e+02, 8.833438e+00, -4.684400e+04, 6.742349e+03, 4.845560e+02, 1.910938e+01, -3.607371e+04, 6.710619e+03, 7.550675e+02, 3.735891e+01, -4.154781e+04, 7.152810e+03, 1.067429e+03, 6.618859e+01, -4.204317e+04, 6.774326e+03, 1.407564e+03, 1.085970e+02, -2.942193e+04, 5.355563e+03, 1.733269e+03, 1.666419e+02, -2.313904e+04, 4.280577e+03, 2.017180e+03, 2.408670e+02, -2.385720e+04, 3.520820e+03, 2.254320e+03, 3.314445e+02, -1.513209e+04, 2.112956e+03, 2.426267e+03, 4.378639e+02, -9.126023e+03, 1.113924e+03, 2.524502e+03, 5.577991e+02, -1.571455e+04, 1.029708e+03, 2.566730e+03, 6.890491e+02, -7.238440e+03, -2.206829e+02, 2.538549e+03, 8.297720e+02, -3.160979e+03, -7.760560e+02, 2.439782e+03, 9.749502e+02, -5.602452e+03, -6.902848e+02, 2.308307e+03, 1.121456e+03, -3.553157e+03, -1.014479e+03, 2.146930e+03, 1.267419e+03, -4.461083e+03, -9.863057e+02, 1.956534e+03, 1.409364e+03, -2.326809e+03, -1.209321e+03, 1.742287e+03, 1.544723e+03, -4.135229e+03, -9.712685e+02, 1.515864e+03, 1.670126e+03, -3.963535e+03, -9.751278e+02, 1.278348e+03, 1.783945e+03, -3.590545e+03, -9.317344e+02, 1.027352e+03, 1.882948e+03, -7.816601e+03, -3.861471e+02, 7.759248e+02, 1.964524e+03, -8.824559e+03, -1.916167e+02, 4.991662e+02, 2.027263e+03, -6.003275e+03, -4.576937e+01, 2.081407e+02, 2.066007e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -5.625582e+01, 1.932575e+00, 0, 0, 6.414978e+01, 1.472767e+00, 2.207452e-02, 1.562500e-04, -2.922836e+02, 2.777474e+01, 8.841004e-02, 7.812500e-04, -8.188740e+02, 1.059625e+02, 6.968160e-01, 6.718750e-03, -2.889488e+03, 3.500503e+02, 3.437535e+00, 4.109375e-02, -6.748480e+03, 8.561885e+02, 1.311485e+01, 1.956250e-01, -9.511546e+03, 1.611095e+03, 3.896265e+01, 7.334375e-01, -2.290021e+04, 3.066546e+03, 9.552066e+01, 2.243906e+00, -2.821286e+04, 4.251733e+03, 2.028843e+02, 5.967656e+00, -2.913541e+04, 5.203704e+03, 3.675117e+02, 1.368859e+01, -4.048369e+04, 6.372044e+03, 5.934689e+02, 2.775234e+01, -3.547831e+04, 6.262590e+03, 8.720572e+02, 5.110688e+01, -3.218587e+04, 5.921591e+03, 1.172909e+03, 8.616875e+01, -2.477427e+04, 5.121564e+03, 1.475680e+03, 1.350383e+02, -2.868072e+04, 4.746820e+03, 1.762617e+03, 1.991086e+02, -1.754454e+04, 3.266592e+03, 2.009591e+03, 2.794042e+02, -1.913506e+04, 2.655854e+03, 2.197015e+03, 3.748694e+02, -9.992284e+03, 1.320722e+03, 2.319693e+03, 4.845859e+02, -1.419455e+04, 1.062222e+03, 2.376302e+03, 6.057533e+02, -2.694677e+03, -3.023730e+02, 2.365281e+03, 7.364186e+02, -9.185589e+03, -8.118530e+00, 2.302949e+03, 8.721534e+02, -2.847409e+03, -8.444596e+02, 2.197532e+03, 1.011741e+03, -3.035145e+03, -8.775668e+02, 2.051168e+03, 1.150592e+03, -5.533588e+03, -7.385513e+02, 1.887015e+03, 1.286758e+03, -3.565998e+03, -1.040906e+03, 1.691788e+03, 1.417959e+03, -2.327347e+03, -1.126813e+03, 1.469339e+03, 1.539923e+03, -3.906176e+03, -8.827879e+02, 1.242034e+03, 1.649925e+03, -6.221863e+03, -6.310295e+02, 1.007942e+03, 1.746547e+03, -3.114073e+03, -8.975397e+02, 7.474580e+02, 1.826920e+03, -1.186080e+04, 2.407749e+02, 4.982586e+02, 1.886371e+03, -6.394004e+03, -1.686521e+01, 2.046311e+02, 1.926321e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.355371e+02, 8.998932e+00, 0, 0, -3.468260e+02, 4.003623e+01, 1.728223e-01, 1.406250e-03, -1.659534e+03, 1.606414e+02, 1.180182e+00, 1.281250e-02, -5.133751e+02, 3.182364e+02, 5.307610e+00, 7.484375e-02, -1.044783e+04, 1.132211e+03, 1.723019e+01, 2.984375e-01, -1.232620e+04, 1.809523e+03, 5.164214e+01, 1.100625e+00, -1.492798e+04, 2.716347e+03, 1.170312e+02, 3.201250e+00, -2.509641e+04, 4.034536e+03, 2.285777e+02, 7.860000e+00, -3.139992e+04, 4.936112e+03, 3.976305e+02, 1.709562e+01, -1.992734e+04, 4.752382e+03, 6.133259e+02, 3.325813e+01, -3.583565e+04, 5.733661e+03, 8.653644e+02, 5.850203e+01, -1.864658e+04, 4.463079e+03, 1.140041e+03, 9.577875e+01, -2.806870e+04, 4.628337e+03, 1.403590e+03, 1.460806e+02, -1.224450e+04, 3.007469e+03, 1.643849e+03, 2.111303e+02, -1.837221e+04, 2.895966e+03, 1.840158e+03, 2.900925e+02, -1.305949e+04, 1.813863e+03, 1.991237e+03, 3.832811e+02, -7.995788e+03, 9.019857e+02, 2.074227e+03, 4.884772e+02, -5.202137e+03, 3.292653e+02, 2.101192e+03, 6.031734e+02, -9.894927e+03, 3.490710e+02, 2.086841e+03, 7.252181e+02, -2.081824e+03, -6.584184e+02, 2.017335e+03, 8.526909e+02, -5.753047e+03, -4.455308e+02, 1.904978e+03, 9.807998e+02, -2.548608e+03, -9.027576e+02, 1.761653e+03, 1.108055e+03, -4.593746e+03, -7.480921e+02, 1.589904e+03, 1.230419e+03, -2.237374e+03, -1.028298e+03, 1.394230e+03, 1.345830e+03, -4.404710e+03, -7.547906e+02, 1.184581e+03, 1.450460e+03, -3.128602e+03, -8.687342e+02, 9.614427e+02, 1.542825e+03, -7.364928e+03, -3.355787e+02, 7.322318e+02, 1.619357e+03, -9.377841e+03, -7.234116e+01, 4.767442e+02, 1.678824e+03, -6.106783e+03, -2.487557e+00, 1.931677e+02, 1.715997e+03, }; static float solarDataset360[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -9.078413e+03, 7.118205e+01, 0, 0, 4.658139e+03, -1.838006e+01, 1.514489e-01, 5.208333e-04, -1.266691e+04, 2.223605e+02, 2.846817e-01, 1.302083e-03, 5.376673e+03, 1.263979e+02, 1.585011e+00, 7.812500e-03, -6.287382e+03, 6.310960e+02, 4.070404e+00, 2.630208e-02, -1.089068e+04, 1.566596e+03, 1.304182e+01, 9.713542e-02, -5.578495e+04, 4.275269e+03, 3.968016e+01, 3.502604e-01, -7.874206e+04, 8.041790e+03, 1.128851e+02, 1.215885e+00, -1.523996e+05, 1.484058e+04, 2.762902e+02, 3.709896e+00, -2.545257e+05, 2.361556e+04, 6.036183e+02, 1.011875e+01, -2.941122e+05, 3.066092e+04, 1.160209e+03, 2.459557e+01, -3.612497e+05, 3.709042e+04, 1.969276e+03, 5.311250e+01, -2.820800e+05, 3.689189e+04, 3.009049e+03, 1.034445e+02, -3.813699e+05, 4.027793e+04, 4.213037e+03, 1.833859e+02, -3.197931e+05, 3.414742e+04, 5.485024e+03, 3.019268e+02, -1.923698e+05, 2.458254e+04, 6.615509e+03, 4.632190e+02, -2.078027e+05, 2.080724e+04, 7.548980e+03, 6.677510e+02, -1.360611e+05, 1.255134e+04, 8.240067e+03, 9.159479e+02, -6.729497e+04, 5.762938e+03, 8.622622e+03, 1.202090e+03, -9.900171e+04, 4.710833e+03, 8.774927e+03, 1.519642e+03, -3.788016e+04, -1.223413e+03, 8.689075e+03, 1.864136e+03, -3.007086e+04, -2.674663e+03, 8.385744e+03, 2.224184e+03, -1.454468e+04, -4.149445e+03, 7.962237e+03, 2.593449e+03, -3.313233e+04, -3.256536e+03, 7.461974e+03, 2.965295e+03, -2.461750e+03, -5.667421e+03, 6.865987e+03, 3.335167e+03, -5.859709e+03, -4.818237e+03, 6.224765e+03, 3.692920e+03, -1.114171e+04, -4.055929e+03, 5.606249e+03, 4.036827e+03, -2.940298e+01, -4.599486e+03, 4.980260e+03, 4.363959e+03, -8.192323e+03, -3.332635e+03, 4.380331e+03, 4.669007e+03, -1.314651e+02, -3.690650e+03, 3.804426e+03, 4.952310e+03, -9.321444e+03, -2.355513e+03, 3.265525e+03, 5.209421e+03, -4.323778e+03, -2.664833e+03, 2.740069e+03, 5.441705e+03, -4.030446e+03, -2.268601e+03, 2.225562e+03, 5.643180e+03, -7.709530e+03, -1.532269e+03, 1.753678e+03, 5.813184e+03, -9.915496e+03, -1.081222e+03, 1.297245e+03, 5.951777e+03, -1.918399e+04, 1.650147e+02, 8.356870e+02, 6.055439e+03, -9.182623e+03, -1.363456e+02, 3.168424e+02, 6.120820e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.007459e+06, 1.920534e+03, 0, 0, 4.479837e+05, -7.065871e+02, 0, 2.604167e-04, 0, 0, 0, 0, -4.964101e+04, 1.630114e+02, 0, 0, 2.106646e+04, -9.205597e+01, 0, 2.604167e-04, 0, 0, 0, 0, -1.305437e+04, 1.325834e+02, 0, 0, 7.455004e+03, -2.985865e+01, 3.840792e-01, 1.562500e-03, -2.055425e+04, 4.505399e+02, 7.714470e-01, 4.166667e-03, 1.086675e+04, 2.797690e+02, 4.050099e+00, 2.395833e-02, -1.873506e+04, 1.575040e+03, 1.070445e+01, 8.072917e-02, -4.327245e+04, 3.801002e+03, 3.540976e+01, 3.059896e-01, -1.102894e+05, 8.242103e+03, 1.027385e+02, 1.085156e+00, -7.645743e+04, 1.218373e+04, 2.565037e+02, 3.423437e+00, -3.095499e+05, 2.422173e+04, 5.541844e+02, 9.238802e+00, -1.908061e+05, 2.675484e+04, 1.088555e+03, 2.286589e+01, -3.934663e+05, 3.821301e+04, 1.856451e+03, 4.946328e+01, -3.390953e+05, 3.834252e+04, 2.902994e+03, 9.776536e+01, -3.420266e+05, 3.790490e+04, 4.089229e+03, 1.755013e+02, -2.686944e+05, 3.228911e+04, 5.315213e+03, 2.902633e+02, -2.564538e+05, 2.755072e+04, 6.453482e+03, 4.467523e+02, -1.509348e+05, 1.825991e+04, 7.399666e+03, 6.475846e+02, -1.630120e+05, 1.453409e+04, 8.097017e+03, 8.903924e+02, -9.950958e+04, 7.104934e+03, 8.521488e+03, 1.172941e+03, -2.923012e+04, 1.025880e+03, 8.643788e+03, 1.487047e+03, -8.585662e+04, 2.418502e+03, 8.589889e+03, 1.824949e+03, -1.614087e+04, -3.639570e+03, 8.338546e+03, 2.183701e+03, -2.320497e+04, -3.485113e+03, 7.912837e+03, 2.550157e+03, -2.187702e+04, -3.972423e+03, 7.416360e+03, 2.920199e+03, -1.034810e+04, -4.884562e+03, 6.835820e+03, 3.287367e+03, -2.759089e+03, -5.058797e+03, 6.209527e+03, 3.644522e+03, -9.328274e+03, -4.074038e+03, 5.594421e+03, 3.987341e+03, -4.936422e+03, -4.126474e+03, 4.986817e+03, 4.314099e+03, -3.321617e+03, -3.792265e+03, 4.386012e+03, 4.620225e+03, -1.003521e+04, -2.819991e+03, 3.816137e+03, 4.903331e+03, 2.907803e+03, -3.685267e+03, 3.246729e+03, 5.162089e+03, -7.981799e+03, -2.001596e+03, 2.732990e+03, 5.390627e+03, -8.279987e+03, -1.868805e+03, 2.254065e+03, 5.593927e+03, -5.136369e+03, -1.945934e+03, 1.758273e+03, 5.766632e+03, -9.493658e+03, -1.095077e+03, 1.289392e+03, 5.904171e+03, -1.816478e+04, 8.782733e+01, 8.362875e+02, 6.007321e+03, -1.016501e+04, -5.757161e+01, 3.316172e+02, 6.072978e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.106646e+04, 9.205597e+01, 0, 0, 9.951134e+03, -5.583492e+01, 0, 2.604167e-04, -6.862369e+03, 7.979095e+01, 0, 0, 3.093701e+03, 1.042453e+01, 2.962179e-01, 1.041667e-03, -3.848975e+03, 1.884300e+02, 7.173252e-01, 3.645833e-03, -1.922464e+03, 4.118046e+02, 2.755566e+00, 1.614583e-02, -1.029728e+04, 1.238807e+03, 9.037110e+00, 6.432292e-02, -5.326510e+04, 3.551966e+03, 2.965222e+01, 2.510417e-01, -5.119148e+04, 6.178442e+03, 8.801668e+01, 9.252604e-01, -1.102076e+05, 1.208818e+04, 2.178717e+02, 2.875260e+00, -2.455519e+05, 2.133109e+04, 4.927790e+02, 8.033333e+00, -2.314605e+05, 2.675653e+04, 9.837470e+02, 2.021667e+01, -3.383926e+05, 3.503899e+04, 1.713479e+03, 4.473359e+01, -3.279210e+05, 3.710837e+04, 2.699082e+03, 8.941484e+01, -3.295655e+05, 3.695410e+04, 3.847503e+03, 1.622500e+02, -2.654830e+05, 3.200589e+04, 5.049391e+03, 2.708594e+02, -2.374300e+05, 2.701443e+04, 6.179434e+03, 4.202516e+02, -1.686326e+05, 1.951749e+04, 7.141543e+03, 6.132620e+02, -1.530711e+05, 1.439417e+04, 7.865806e+03, 8.487388e+02, -8.333989e+04, 7.055607e+03, 8.314596e+03, 1.123732e+03, -8.130111e+04, 4.141743e+03, 8.497304e+03, 1.431033e+03, -3.575768e+04, -5.696968e+02, 8.448170e+03, 1.764856e+03, -3.255295e+04, -1.826416e+03, 8.210999e+03, 2.116095e+03, -3.660834e+04, -2.550753e+03, 7.848763e+03, 2.478988e+03, -7.337777e+03, -5.008166e+03, 7.349120e+03, 2.846617e+03, -5.379678e+03, -4.784496e+03, 6.777142e+03, 3.209571e+03, -2.374637e+04, -3.331316e+03, 6.206260e+03, 3.564630e+03, 1.080518e+04, -5.854954e+03, 5.579585e+03, 3.908975e+03, -1.909992e+04, -2.668851e+03, 4.981595e+03, 4.232768e+03, 1.911058e+03, -4.437068e+03, 4.390299e+03, 4.540824e+03, -3.848120e+03, -3.213454e+03, 3.806091e+03, 4.822876e+03, -9.851976e+03, -2.361374e+03, 3.277626e+03, 5.081202e+03, -1.578794e+03, -2.943684e+03, 2.741918e+03, 5.314140e+03, -5.601199e+03, -2.034313e+03, 2.236027e+03, 5.515390e+03, -8.507381e+03, -1.484607e+03, 1.769983e+03, 5.687009e+03, -8.981222e+03, -1.217297e+03, 1.303053e+03, 5.826869e+03, -1.807778e+04, 6.647867e+01, 8.405294e+02, 5.930647e+03, -1.028919e+04, -5.100950e+01, 3.341801e+02, 5.996596e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.528365e+03, 1.907311e+01, 0, 0, 1.516070e+03, 1.652342e+00, 7.814024e-02, 2.604167e-04, -1.566422e+04, 2.938113e+02, 2.450638e-01, 1.041667e-03, 9.323103e+03, 7.951170e+01, 2.065634e+00, 1.145833e-02, -7.689699e+03, 8.647270e+02, 5.179331e+00, 3.828125e-02, -4.120250e+04, 2.746625e+03, 1.943548e+01, 1.575521e-01, -5.390461e+04, 5.341204e+03, 6.456184e+01, 6.408854e-01, -1.009697e+05, 1.038629e+04, 1.723484e+02, 2.164844e+00, -1.920166e+05, 1.804640e+04, 4.048162e+02, 6.370052e+00, -2.372478e+05, 2.492915e+04, 8.320197e+02, 1.654844e+01, -2.793231e+05, 3.114679e+04, 1.491609e+03, 3.777448e+01, -3.104765e+05, 3.519482e+04, 2.392658e+03, 7.703568e+01, -3.177075e+05, 3.568983e+04, 3.482617e+03, 1.424852e+02, -2.494221e+05, 3.108444e+04, 4.644386e+03, 2.418099e+02, -2.364069e+05, 2.715189e+04, 5.759209e+03, 3.802539e+02, -1.404746e+05, 1.898809e+04, 6.731675e+03, 5.613974e+02, -2.017016e+05, 1.743282e+04, 7.504484e+03, 7.844820e+02, -4.320413e+04, 5.367012e+03, 7.992650e+03, 1.048910e+03, -9.571801e+04, 5.908238e+03, 8.211533e+03, 1.344214e+03, -3.686322e+04, 6.522573e+01, 8.234419e+03, 1.668699e+03, -4.436791e+04, -8.088656e+02, 8.044739e+03, 2.011998e+03, -2.002588e+04, -3.383672e+03, 7.702298e+03, 2.368391e+03, -1.741256e+04, -3.854559e+03, 7.237658e+03, 2.728893e+03, -7.888695e+03, -4.546112e+03, 6.704484e+03, 3.087804e+03, -6.588850e+03, -4.351038e+03, 6.137185e+03, 3.439195e+03, -1.547834e+04, -3.487809e+03, 5.565533e+03, 3.779451e+03, 3.267247e+03, -4.786579e+03, 4.960190e+03, 4.105218e+03, -6.089460e+03, -3.295662e+03, 4.377885e+03, 4.409076e+03, -1.218322e+04, -2.582626e+03, 3.837023e+03, 4.693073e+03, 3.616890e+03, -3.794143e+03, 3.268057e+03, 4.953780e+03, -9.102661e+03, -1.913822e+03, 2.750126e+03, 5.183632e+03, -6.696343e+03, -2.063778e+03, 2.263473e+03, 5.388297e+03, -3.048448e+03, -2.093974e+03, 1.768789e+03, 5.561364e+03, -1.551802e+04, -4.318095e+02, 1.323227e+03, 5.700141e+03, -1.234976e+04, -6.368560e+02, 8.363357e+02, 5.807329e+03, -9.311490e+03, -1.488186e+02, 3.568924e+02, 5.871500e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.492148e+03, 2.451223e+01, 0, 0, 1.641003e+03, 8.115125e+00, 1.339882e-01, 5.208333e-04, -1.214574e+04, 3.860017e+02, 4.756144e-01, 2.343750e-03, -1.064944e+04, 7.243819e+02, 4.335378e+00, 2.500000e-02, -6.266723e+03, 1.498871e+03, 1.515545e+01, 1.213542e-01, -4.724146e+04, 4.315847e+03, 4.553783e+01, 4.554687e-01, -8.443089e+04, 8.583278e+03, 1.309248e+02, 1.597396e+00, -1.541231e+05, 1.527165e+04, 3.224487e+02, 4.907813e+00, -2.382286e+05, 2.297833e+04, 6.902681e+02, 1.323568e+01, -2.235609e+05, 2.735690e+04, 1.279864e+03, 3.133542e+01, -2.906342e+05, 3.320621e+04, 2.096545e+03, 6.539010e+01, -3.123834e+05, 3.467834e+04, 3.128177e+03, 1.236672e+02, -2.393461e+05, 3.025589e+04, 4.250709e+03, 2.140122e+02, -2.028333e+05, 2.609503e+04, 5.342867e+03, 3.417609e+02, -2.151191e+05, 2.250055e+04, 6.337131e+03, 5.109326e+02, -9.763169e+04, 1.271519e+04, 7.112202e+03, 7.229203e+02, -1.312211e+05, 1.094586e+04, 7.636174e+03, 9.727784e+02, -3.907836e+04, 2.892178e+03, 7.911983e+03, 1.258277e+03, -5.691819e+04, 2.234234e+03, 7.958878e+03, 1.569822e+03, -4.605984e+04, -2.949351e+02, 7.845258e+03, 1.903886e+03, -9.288844e+03, -3.584873e+03, 7.538797e+03, 2.252188e+03, -3.275040e+04, -2.362390e+03, 7.129354e+03, 2.605553e+03, 7.240576e+03, -5.434321e+03, 6.628154e+03, 2.960763e+03, -2.435119e+04, -2.700395e+03, 6.099256e+03, 3.307801e+03, -3.407342e+03, -4.548247e+03, 5.539707e+03, 3.647942e+03, -4.437134e+03, -3.961614e+03, 4.941027e+03, 3.970917e+03, -3.090062e+03, -3.635715e+03, 4.368076e+03, 4.274897e+03, -6.315304e+03, -2.954206e+03, 3.823070e+03, 4.557586e+03, -5.534764e+03, -2.764660e+03, 3.293166e+03, 4.817570e+03, -7.186551e+03, -2.326088e+03, 2.771736e+03, 5.051273e+03, -2.914677e+03, -2.446875e+03, 2.255978e+03, 5.256005e+03, -7.073055e+03, -1.589272e+03, 1.777935e+03, 5.427988e+03, -1.092444e+04, -9.714652e+02, 1.326496e+03, 5.568739e+03, -1.803434e+04, 5.807577e+00, 8.590316e+02, 5.675268e+03, -1.059246e+04, -4.287520e+01, 3.420559e+02, 5.742487e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -5.109094e+03, 3.580031e+01, 0, 0, 2.803934e+03, -2.399769e+01, 0, 2.604167e-04, -3.970877e+03, 8.834116e+01, 0, 0, -5.636564e+02, 1.192399e+02, 6.512142e-01, 2.864583e-03, -6.086357e+02, 3.883172e+02, 2.468692e+00, 1.562500e-02, -2.893914e+04, 1.718661e+03, 9.629309e+00, 7.291667e-02, -2.076572e+04, 3.183627e+03, 3.674586e+01, 3.437500e-01, -1.011023e+05, 8.189104e+03, 1.062582e+02, 1.252344e+00, -1.095898e+05, 1.282006e+04, 2.767597e+02, 4.090625e+00, -2.297269e+05, 2.151665e+04, 6.004328e+02, 1.125651e+01, -2.107325e+05, 2.568211e+04, 1.146269e+03, 2.735495e+01, -2.800842e+05, 3.166650e+04, 1.911957e+03, 5.823177e+01, -2.923688e+05, 3.303608e+04, 2.891607e+03, 1.118773e+02, -2.033237e+05, 2.870850e+04, 3.969933e+03, 1.959010e+02, -2.617431e+05, 2.851329e+04, 5.055149e+03, 3.158836e+02, -1.440848e+05, 1.921772e+04, 6.043374e+03, 4.774372e+02, -1.420361e+05, 1.553418e+04, 6.820003e+03, 6.792667e+02, -9.006131e+04, 9.284458e+03, 7.382916e+03, 9.207971e+02, -7.093812e+04, 5.455005e+03, 7.700927e+03, 1.196878e+03, -3.964068e+04, 1.575567e+03, 7.802084e+03, 1.502182e+03, -7.280366e+04, 1.632438e+03, 7.724594e+03, 1.829778e+03, 1.690897e+04, -5.252913e+03, 7.429101e+03, 2.174115e+03, -4.574865e+04, -9.598807e+02, 7.041073e+03, 2.521259e+03, 2.816103e+03, -5.134375e+03, 6.581128e+03, 2.873876e+03, -1.565202e+04, -3.351712e+03, 6.045391e+03, 3.218518e+03, -2.906298e+03, -4.297581e+03, 5.498150e+03, 3.555040e+03, -9.963636e+03, -3.361737e+03, 4.936026e+03, 3.876524e+03, -2.334266e+02, -3.922430e+03, 4.370841e+03, 4.181196e+03, -1.330539e+04, -2.367708e+03, 3.827009e+03, 4.463648e+03, 2.006252e+03, -3.636281e+03, 3.271498e+03, 4.724332e+03, -6.128696e+03, -2.215009e+03, 2.749376e+03, 4.954650e+03, -5.894247e+03, -2.020601e+03, 2.272207e+03, 5.158856e+03, -8.330230e+03, -1.530492e+03, 1.802163e+03, 5.333464e+03, -8.185462e+03, -1.311486e+03, 1.331275e+03, 5.475951e+03, -2.089177e+04, 3.374858e+02, 8.719856e+02, 5.582192e+03, -9.930639e+03, -1.239258e+02, 3.378337e+02, 5.651177e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -5.109094e+03, 3.580031e+01, 0, 0, 2.803934e+03, -2.399769e+01, 0, 2.604167e-04, -5.944797e+02, 2.075013e+01, 0, 0, -4.117657e+03, 1.320064e+02, 2.004808e-01, 7.812500e-04, 2.833792e+03, 1.774131e+02, 1.527515e+00, 8.854167e-03, -2.276165e+04, 1.257648e+03, 5.629040e+00, 4.140625e-02, -1.581115e+04, 2.383463e+03, 2.490926e+01, 2.221354e-01, -8.271046e+04, 6.514143e+03, 7.682795e+01, 8.695312e-01, -7.892773e+04, 1.023660e+04, 2.110950e+02, 3.012500e+00, -1.833413e+05, 1.835639e+04, 4.760003e+02, 8.611719e+00, -2.594243e+05, 2.515475e+04, 9.535555e+02, 2.177422e+01, -1.626629e+05, 2.553274e+04, 1.641990e+03, 4.828620e+01, -3.138765e+05, 3.311180e+04, 2.521424e+03, 9.437135e+01, -2.023791e+05, 2.790945e+04, 3.566488e+03, 1.692937e+02, -2.361401e+05, 2.715103e+04, 4.611801e+03, 2.781815e+02, -1.387146e+05, 1.936281e+04, 5.584871e+03, 4.265570e+02, -1.260435e+05, 1.563798e+04, 6.386036e+03, 6.144526e+02, -1.326077e+05, 1.212714e+04, 7.010195e+03, 8.421141e+02, -3.897682e+04, 3.959405e+03, 7.366325e+03, 1.106369e+03, -5.889334e+04, 3.350540e+03, 7.497170e+03, 1.398210e+03, -3.933554e+04, 2.719489e+02, 7.466882e+03, 1.714702e+03, -2.390631e+04, -1.853368e+03, 7.252314e+03, 2.047736e+03, -2.178522e+04, -2.640984e+03, 6.907977e+03, 2.389698e+03, -6.125885e+03, -4.003762e+03, 6.464812e+03, 2.734296e+03, -1.126017e+04, -3.477681e+03, 5.972548e+03, 3.074501e+03, -1.131751e+04, -3.475106e+03, 5.455067e+03, 3.407229e+03, -5.340261e+02, -4.136362e+03, 4.898586e+03, 3.727215e+03, -8.792165e+03, -2.990082e+03, 4.352596e+03, 4.028768e+03, -4.742079e+03, -3.169825e+03, 3.815352e+03, 4.311590e+03, -4.254148e+03, -2.851538e+03, 3.279048e+03, 4.570477e+03, -4.354544e+03, -2.480152e+03, 2.766874e+03, 4.803165e+03, -7.432540e+03, -1.878460e+03, 2.281570e+03, 5.007989e+03, -6.205415e+03, -1.788706e+03, 1.802434e+03, 5.183474e+03, -1.145931e+04, -9.481364e+02, 1.336118e+03, 5.325439e+03, -1.587470e+04, -2.321854e+02, 8.590106e+02, 5.432634e+03, -1.049374e+04, -6.518902e+01, 3.575002e+02, 5.499596e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -8.531048e+02, 1.695939e+01, 0, 0, 6.095111e+02, 9.076932e+00, 1.122616e-01, 5.208333e-04, -6.857359e+02, 1.069152e+02, 3.785397e-01, 2.343750e-03, -6.528912e+03, 5.478130e+02, 2.211863e+00, 1.484375e-02, -2.807616e+04, 1.924054e+03, 1.181174e+01, 9.531250e-02, -4.135252e+04, 3.975660e+03, 4.662733e+01, 4.854167e-01, -6.513897e+04, 7.571929e+03, 1.340027e+02, 1.815104e+00, -1.130550e+05, 1.330006e+04, 3.248641e+02, 5.579167e+00, -2.128461e+05, 2.104638e+04, 6.894764e+02, 1.487135e+01, -1.938231e+05, 2.394323e+04, 1.270357e+03, 3.495443e+01, -2.250683e+05, 2.733125e+04, 2.036520e+03, 7.189036e+01, -1.878061e+05, 2.633878e+04, 2.957468e+03, 1.331286e+02, -2.270545e+05, 2.650296e+04, 3.950502e+03, 2.252544e+02, -1.452222e+05, 1.974198e+04, 4.908788e+03, 3.544242e+02, -9.739988e+04, 1.480522e+04, 5.714679e+03, 5.215013e+02, -1.391311e+05, 1.365247e+04, 6.380017e+03, 7.267320e+02, -4.788766e+04, 5.382256e+03, 6.821131e+03, 9.697984e+02, -5.285286e+04, 3.809721e+03, 7.022384e+03, 1.241959e+03, -3.337682e+04, 9.042881e+02, 7.062654e+03, 1.539764e+03, -4.007437e+04, -2.699339e+01, 6.941219e+03, 1.856429e+03, -6.051283e+03, -3.209377e+03, 6.660347e+03, 2.185851e+03, -2.435908e+04, -2.124954e+03, 6.283149e+03, 2.518370e+03, 2.551445e+03, -4.363071e+03, 5.832923e+03, 2.851286e+03, -1.489483e+04, -2.673771e+03, 5.352245e+03, 3.175629e+03, -9.389643e+03, -3.278006e+03, 4.853753e+03, 3.491487e+03, 3.161923e+03, -4.031601e+03, 4.306797e+03, 3.791312e+03, -1.194090e+04, -2.196499e+03, 3.796276e+03, 4.069944e+03, -2.953957e+03, -3.004063e+03, 3.287319e+03, 4.329823e+03, -6.149918e+03, -2.304854e+03, 2.774682e+03, 4.562834e+03, -3.373794e+03, -2.296007e+03, 2.282599e+03, 4.768486e+03, -1.034299e+04, -1.265867e+03, 1.820241e+03, 4.943532e+03, -1.110375e+04, -1.092537e+03, 1.348590e+03, 5.088307e+03, -1.629907e+04, -2.127533e+02, 8.538122e+02, 5.195697e+03, -1.089887e+04, -2.417175e+00, 3.439132e+02, 5.261939e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -9.508513e+01, 4.753078e+00, 0, 0, -7.542336e+02, 4.194538e+01, 5.820865e-02, 2.604167e-04, -1.284200e+03, 1.590937e+02, 6.480504e-01, 3.906250e-03, -7.617453e+03, 6.908946e+02, 3.653193e+00, 2.812500e-02, -2.285529e+04, 2.070239e+03, 1.729678e+01, 1.656250e-01, -4.265825e+04, 4.564970e+03, 6.200908e+01, 7.559896e-01, -8.135927e+04, 8.796250e+03, 1.745256e+02, 2.714323e+00, -1.186992e+05, 1.383851e+04, 4.094748e+02, 8.109375e+00, -1.729788e+05, 1.934059e+04, 8.160818e+02, 2.061328e+01, -1.630315e+05, 2.150283e+04, 1.411697e+03, 4.571406e+01, -1.624940e+05, 2.289915e+04, 2.160330e+03, 8.952969e+01, -1.678006e+05, 2.296466e+04, 3.025299e+03, 1.588792e+02, -1.625820e+05, 2.081553e+04, 3.926482e+03, 2.601164e+02, -1.026208e+05, 1.529805e+04, 4.748836e+03, 3.972128e+02, -9.110283e+04, 1.222390e+04, 5.429607e+03, 5.703201e+02, -7.839298e+04, 8.798951e+03, 5.957019e+03, 7.792841e+02, -4.969894e+04, 4.718760e+03, 6.285543e+03, 1.021049e+03, -3.394798e+04, 2.050471e+03, 6.418885e+03, 1.289738e+03, -2.926526e+04, 4.598630e+02, 6.397153e+03, 1.579698e+03, -1.911569e+04, -1.195949e+03, 6.238186e+03, 1.885275e+03, -2.090631e+04, -1.729267e+03, 5.964421e+03, 2.199667e+03, -1.444247e+03, -3.487510e+03, 5.588336e+03, 2.516915e+03, -1.151447e+04, -2.536741e+03, 5.168912e+03, 2.829230e+03, -1.111331e+04, -2.723565e+03, 4.725716e+03, 3.135111e+03, 1.710810e+03, -3.676459e+03, 4.229067e+03, 3.428469e+03, -1.164580e+04, -2.096150e+03, 3.746819e+03, 3.702957e+03, -1.692949e+03, -2.995892e+03, 3.257140e+03, 3.959883e+03, -8.118107e+03, -2.006853e+03, 2.767986e+03, 4.191197e+03, -4.383850e+03, -2.223397e+03, 2.285550e+03, 4.397215e+03, -9.697211e+03, -1.380502e+03, 1.813706e+03, 4.572417e+03, -7.068293e+03, -1.463914e+03, 1.337003e+03, 4.716157e+03, -2.122598e+04, 3.866204e+02, 8.784811e+02, 4.822514e+03, -1.022737e+04, -1.101296e+02, 3.443440e+02, 4.892292e+03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -9.856739e+02, 1.195308e+01, 0, 0, 0, 0, 0, 2.604167e-04, -1.720472e+02, 1.507814e+01, 0, 2.604167e-04, -5.197869e+03, 2.521753e+02, 2.669468e-01, 1.822917e-03, -1.789035e+03, 4.897775e+02, 4.126558e+00, 3.411458e-02, -2.356297e+04, 1.990572e+03, 1.685742e+01, 1.843750e-01, -3.079983e+04, 3.806333e+03, 6.218522e+01, 8.572917e-01, -5.867444e+04, 7.219324e+03, 1.679956e+02, 2.980208e+00, -9.193536e+04, 1.140888e+04, 3.838865e+02, 8.630729e+00, -1.093232e+05, 1.496515e+04, 7.495575e+02, 2.142161e+01, -1.454474e+05, 1.835651e+04, 1.277678e+03, 4.640313e+01, -1.060384e+05, 1.738770e+04, 1.939819e+03, 8.983255e+01, -1.317236e+05, 1.829440e+04, 2.673577e+03, 1.569544e+02, -9.918836e+04, 1.511239e+04, 3.428617e+03, 2.536474e+02, -6.597280e+04, 1.172004e+04, 4.108547e+03, 3.822750e+02, -8.933787e+04, 1.089011e+04, 4.698809e+03, 5.437974e+02, -3.303439e+04, 5.345711e+03, 5.140684e+03, 7.388943e+02, -4.639993e+04, 4.646300e+03, 5.414926e+03, 9.618318e+02, -2.854970e+04, 1.826186e+03, 5.551188e+03, 1.210728e+03, -2.483031e+04, 4.061465e+02, 5.528659e+03, 1.478848e+03, -1.065058e+04, -1.391460e+03, 5.374176e+03, 1.760276e+03, -7.673933e+03, -1.880549e+03, 5.126809e+03, 2.047961e+03, -1.467883e+04, -1.593262e+03, 4.830964e+03, 2.337684e+03, -7.526978e+03, -2.499826e+03, 4.467952e+03, 2.625599e+03, -4.169590e+03, -2.726037e+03, 4.046171e+03, 2.904100e+03, -4.507799e+03, -2.496923e+03, 3.611144e+03, 3.168575e+03, -6.215844e+03, -2.180448e+03, 3.176433e+03, 3.416260e+03, -9.828176e+03, -1.778987e+03, 2.732565e+03, 3.644142e+03, -2.786098e+03, -2.382096e+03, 2.253500e+03, 3.847887e+03, -6.796697e+03, -1.565581e+03, 1.789222e+03, 4.020204e+03, -1.447871e+04, -6.111844e+02, 1.348581e+03, 4.162343e+03, -1.363735e+04, -5.238507e+02, 8.553840e+02, 4.271182e+03, -9.848364e+03, -1.203178e+02, 3.610664e+02, 4.337093e+03, }; static float solarDataset400[] = { 1.117129e+12, -1.629427e+07, -4.340837e+02, 2.288813e-02, -3.507469e+09, 6.348417e+05, 0, 1.628578e-02, 2.505700e+07, -1.230995e+04, 0, 1.936688e-02, -1.719863e+07, 2.178956e+04, 0, 1.892672e-02, 1.438988e+06, -1.616402e+03, 6.806146e+00, 2.332828e-02, 1.696702e+05, 1.495455e+03, 8.179956e+00, 3.037078e-02, -1.912560e+06, 7.286691e+03, 1.412411e+01, 4.753688e-02, 1.068454e+06, -3.820033e+03, 1.852974e+01, 9.331313e-02, -4.480441e+05, 7.070752e+03, 2.347567e+01, 1.412902e-01, -2.844742e+05, 7.763926e+03, 5.756619e+01, 3.045881e-01, 3.820870e+05, 5.835991e+03, 1.114800e+02, 7.139334e-01, -5.903447e+05, 2.442660e+04, 2.153938e+02, 1.610972e+00, -2.022151e+05, 3.048178e+04, 4.667749e+02, 4.039754e+00, -7.774876e+05, 5.556041e+04, 9.199868e+02, 9.698843e+00, -7.414445e+05, 7.551752e+04, 1.760381e+03, 2.266144e+01, -1.531201e+06, 1.128349e+05, 3.140037e+03, 4.978959e+01, -1.554180e+06, 1.298094e+05, 5.235208e+03, 1.033051e+02, -1.695156e+06, 1.421715e+05, 7.966732e+03, 1.984392e+02, -1.678161e+06, 1.399827e+05, 1.119495e+04, 3.535841e+02, -1.463039e+06, 1.225635e+05, 1.457341e+04, 5.863313e+02, -1.215237e+06, 9.771091e+04, 1.769675e+04, 9.092475e+02, -8.636409e+05, 6.734484e+04, 2.022204e+04, 1.327606e+03, -6.651680e+05, 4.343026e+04, 2.196126e+04, 1.837785e+03, -3.857503e+05, 1.929567e+04, 2.286749e+04, 2.430659e+03, -3.671416e+05, 8.823173e+03, 2.302563e+04, 3.090578e+03, -1.503106e+05, -7.693949e+03, 2.251190e+04, 3.802935e+03, -1.434123e+05, -1.080121e+04, 2.148437e+04, 4.545612e+03, -7.621756e+04, -1.576213e+04, 2.013222e+04, 5.304807e+03, -7.041412e+04, -1.599827e+04, 1.854944e+04, 6.063558e+03, 1.247797e+04, -1.940579e+04, 1.683252e+04, 6.809340e+03, -4.230704e+04, -1.372257e+04, 1.516152e+04, 7.528765e+03, -1.341378e+04, -1.442508e+04, 1.354734e+04, 8.221723e+03, 1.305159e+04, -1.404328e+04, 1.196086e+04, 8.877132e+03, -3.228613e+04, -8.830029e+03, 1.054343e+04, 9.490735e+03, 6.334330e+03, -1.081216e+04, 9.192167e+03, 1.006662e+04, -1.320077e+04, -7.485103e+03, 7.933060e+03, 1.059296e+04, 9.474767e+03, -8.180859e+03, 6.789131e+03, 1.107455e+04, -1.394154e+04, -4.679057e+03, 5.796750e+03, 1.150659e+04, -3.468549e+03, -5.125712e+03, 4.894953e+03, 1.189805e+04, -1.168377e+04, -3.552944e+03, 4.047968e+03, 1.224160e+04, -3.595156e+03, -3.828358e+03, 3.246376e+03, 1.253896e+04, -9.636883e+03, -2.443091e+03, 2.519269e+03, 1.278460e+04, -1.695233e+04, -1.289283e+03, 1.854717e+03, 1.298280e+04, -1.903977e+04, -6.528410e+02, 1.170083e+03, 1.313098e+04, -1.350669e+04, -1.652916e+02, 4.953127e+02, 1.322139e+04, 1.427101e+11, -1.957428e+06, -5.973210e+01, 1.232438e-02, -2.505335e+09, 4.534583e+05, 0, 1.144406e-02, 2.505700e+07, -1.230995e+04, 0, 1.364484e-02, -1.530567e+07, 1.841817e+04, 0, 1.320469e-02, 1.680202e+06, -2.365652e+03, 4.815713e+00, 1.672594e-02, -1.426389e+06, 3.973627e+03, 5.413944e+00, 2.112750e-02, 6.318979e+05, -1.710393e+03, 7.350863e+00, 3.389203e-02, -1.473582e+05, 2.336923e+03, 8.947389e+00, 4.841719e-02, 6.750351e+04, 2.142457e+03, 1.881145e+01, 9.067219e-02, -6.137863e+04, 5.312427e+03, 3.767319e+01, 1.945491e-01, -2.368579e+05, 1.056334e+04, 8.328836e+01, 4.802105e-01, -3.502458e+04, 1.450254e+04, 1.806983e+02, 1.255326e+00, -3.536828e+05, 2.941026e+04, 3.742713e+02, 3.159882e+00, -5.525650e+05, 4.829087e+04, 7.804581e+02, 7.921052e+00, -1.131425e+06, 7.774385e+04, 1.543754e+03, 1.911026e+01, -9.674282e+05, 9.542627e+04, 2.833425e+03, 4.364369e+01, -1.726176e+06, 1.303805e+05, 4.757123e+03, 9.174177e+01, -1.560050e+06, 1.354377e+05, 7.402393e+03, 1.797757e+02, -1.659007e+06, 1.378766e+05, 1.051897e+04, 3.248278e+02, -1.371101e+06, 1.198850e+05, 1.384088e+04, 5.450543e+02, -1.299875e+06, 1.013112e+05, 1.696555e+04, 8.532262e+02, -7.373351e+05, 6.441420e+04, 1.952739e+04, 1.256523e+03, -6.447884e+05, 4.627416e+04, 2.134307e+04, 1.750144e+03, -5.825478e+05, 2.880250e+04, 2.244015e+04, 2.329148e+03, -1.914632e+05, 1.757698e+03, 2.265971e+04, 2.980030e+03, -2.801179e+05, 8.443567e+01, 2.221525e+04, 3.679473e+03, -9.016021e+04, -1.353444e+04, 2.127045e+04, 4.416034e+03, -5.848055e+04, -1.550950e+04, 1.993050e+04, 5.166405e+03, -8.007881e+04, -1.426653e+04, 1.844888e+04, 5.918714e+03, 4.462178e+03, -1.832929e+04, 1.682629e+04, 6.662612e+03, -8.309437e+04, -1.148821e+04, 1.520348e+04, 7.383206e+03, 4.995264e+04, -1.893244e+04, 1.352107e+04, 8.078812e+03, -3.495005e+04, -9.918410e+03, 1.197260e+04, 8.729566e+03, -2.254439e+03, -1.140785e+04, 1.057610e+04, 9.348295e+03, -1.194317e+04, -9.037030e+03, 9.229099e+03, 9.923259e+03, 4.037681e+03, -8.955305e+03, 7.980764e+03, 1.045434e+04, -1.351607e+04, -6.061553e+03, 6.864874e+03, 1.093757e+04, 7.338831e+03, -6.963548e+03, 5.837108e+03, 1.137736e+04, -2.292706e+04, -3.086934e+03, 4.940689e+03, 1.176787e+04, 4.648356e+03, -5.474011e+03, 4.063248e+03, 1.211814e+04, -1.227871e+04, -2.657876e+03, 3.270644e+03, 1.241280e+04, -8.698683e+03, -2.708755e+03, 2.554663e+03, 1.266362e+04, -1.098022e+04, -1.900095e+03, 1.865115e+03, 1.286352e+04, -2.959044e+04, 5.140675e+02, 1.222700e+03, 1.301222e+04, -1.386763e+04, -1.800631e+02, 4.732027e+02, 1.310906e+04, -2.250626e+10, 2.821518e+05, 2.735822e+01, 3.081094e-03, 1.015964e+08, -6.264336e+04, 1.702289e+01, 3.521250e-03, -1.603967e+07, -1.803368e+03, 6.342924e+00, 4.841719e-03, 2.035804e+07, -1.947652e+04, 0, 6.162188e-03, -6.628634e+06, 1.134906e+04, 0, 3.521250e-03, 5.620458e+05, -1.364648e+03, 1.880042e+00, 8.362969e-03, -3.417573e+05, 2.062172e+03, 1.747725e+00, 1.012359e-02, -7.534766e+03, 8.619116e+02, 5.863022e+00, 2.024719e-02, 8.599540e+04, 9.720702e+02, 1.069301e+01, 4.445578e-02, -1.156890e+05, 3.868880e+03, 2.157506e+01, 1.025564e-01, 7.657473e+04, 4.835159e+03, 5.014776e+01, 2.759780e-01, -2.781167e+05, 1.440504e+04, 1.128026e+02, 7.337405e-01, -2.634244e+05, 2.323850e+04, 2.708874e+02, 2.091182e+00, -5.456420e+05, 4.153386e+04, 5.949804e+02, 5.660850e+00, -7.962351e+05, 6.431258e+04, 1.232698e+03, 1.450623e+01, -1.197053e+06, 9.234505e+04, 2.349153e+03, 3.449857e+01, -1.230918e+06, 1.114998e+05, 4.089853e+03, 7.566110e+01, -1.644144e+06, 1.336157e+05, 6.498004e+03, 1.519362e+02, -1.555109e+06, 1.322636e+05, 9.493547e+03, 2.818699e+02, -1.357583e+06, 1.188301e+05, 1.271440e+04, 4.827603e+02, -1.116449e+06, 9.761383e+04, 1.581326e+04, 7.684710e+02, -9.139236e+05, 7.403173e+04, 1.847437e+04, 1.146857e+03, -6.990817e+05, 4.906624e+04, 2.044711e+04, 1.618387e+03, -3.467195e+05, 2.202997e+04, 2.157873e+04, 2.174869e+03, -4.305811e+05, 1.548297e+04, 2.198860e+04, 2.801117e+03, -1.289765e+05, -5.992939e+03, 2.170495e+04, 3.485799e+03, -1.198868e+05, -8.943475e+03, 2.086422e+04, 4.204074e+03, -1.470410e+05, -1.001341e+04, 1.974012e+04, 4.944323e+03, 1.334018e+03, -1.882254e+04, 1.828199e+04, 5.692294e+03, -3.345755e+04, -1.481065e+04, 1.670764e+04, 6.427177e+03, -4.222028e+04, -1.336937e+04, 1.517112e+04, 7.146100e+03, -1.048132e+04, -1.430800e+04, 1.359152e+04, 7.840347e+03, -2.882922e+03, -1.287178e+04, 1.204023e+04, 8.498728e+03, -1.162564e+04, -1.046185e+04, 1.060814e+04, 9.117565e+03, 8.458319e+02, -9.934087e+03, 9.276245e+03, 9.695744e+03, -1.175585e+04, -7.451056e+03, 8.062850e+03, 1.022931e+04, 3.308565e+02, -7.420070e+03, 6.941772e+03, 1.071991e+04, -1.318812e+04, -5.104680e+03, 5.924005e+03, 1.116308e+04, 2.440679e+03, -5.803752e+03, 4.972255e+03, 1.156184e+04, -1.312707e+04, -3.300552e+03, 4.125489e+03, 1.190999e+04, -6.642305e+03, -3.582143e+03, 3.336437e+03, 1.221449e+04, -7.838423e+03, -2.777393e+03, 2.585322e+03, 1.246768e+04, -1.594267e+04, -1.412070e+03, 1.904021e+03, 1.267038e+04, -2.650924e+04, 5.450457e+01, 1.222878e+03, 1.282292e+04, -1.407506e+04, -1.421113e+02, 4.719557e+02, 1.291827e+04, 0, 0, 0, 0, -1.002134e+09, 1.813833e+05, 0, 0, 2.505700e+07, -1.230995e+04, 0, 8.803125e-04, -3.540684e+06, 4.422303e+03, 0, 4.401563e-04, -1.077551e+06, 1.071832e+03, 1.320161e+00, 1.320469e-03, 4.561374e+05, -1.073274e+03, 0, 2.640938e-03, -1.241178e+05, 7.309221e+02, 0, 1.760625e-03, -6.807449e+03, 4.155531e+02, 1.415729e+00, 3.961406e-03, -5.892697e+04, 1.065543e+03, 3.663583e+00, 1.144406e-02, 7.462404e+04, 7.963727e+02, 9.161593e+00, 3.697313e-02, -1.449805e+05, 4.808397e+03, 2.148746e+01, 1.047572e-01, -7.483031e+04, 7.438418e+03, 6.219855e+01, 3.569667e-01, -1.551526e+05, 1.519258e+04, 1.534935e+02, 1.106993e+00, -3.869766e+05, 3.031932e+04, 3.687213e+02, 3.258917e+00, -7.418804e+05, 5.270793e+04, 8.372727e+02, 9.106833e+00, -8.892984e+05, 7.452028e+04, 1.720571e+03, 2.349510e+01, -1.173248e+06, 9.980147e+04, 3.160816e+03, 5.468281e+01, -1.451666e+06, 1.199829e+05, 5.273780e+03, 1.157149e+02, -1.406590e+06, 1.229404e+05, 7.982304e+03, 2.235989e+02, -1.256174e+06, 1.143387e+05, 1.101269e+04, 3.956375e+02, -1.047141e+06, 9.726801e+04, 1.405257e+04, 6.469126e+02, -9.893584e+05, 7.986424e+04, 1.679688e+04, 9.875755e+02, -6.207149e+05, 4.968663e+04, 1.891915e+04, 1.421301e+03, -4.129199e+05, 2.877273e+04, 2.024445e+04, 1.939607e+03, -3.571950e+05, 1.606478e+04, 2.087749e+04, 2.531703e+03, -1.930391e+05, 8.010621e+02, 2.084215e+04, 3.184647e+03, -1.137334e+05, -6.987208e+03, 2.024103e+04, 3.879152e+03, -9.850133e+04, -9.863565e+03, 1.928338e+04, 4.599642e+03, -9.788409e+04, -1.144184e+04, 1.805974e+04, 5.332882e+03, 1.245732e+04, -1.762258e+04, 1.658022e+04, 6.064098e+03, -5.720841e+04, -1.160080e+04, 1.506961e+04, 6.775777e+03, 1.067936e+04, -1.514209e+04, 1.355611e+04, 7.467565e+03, -2.175393e+04, -1.083518e+04, 1.208639e+04, 8.124791e+03, -1.089978e+04, -1.053521e+04, 1.070786e+04, 8.749151e+03, 1.343549e+03, -9.970273e+03, 9.374791e+03, 9.333012e+03, -1.328865e+04, -7.346112e+03, 8.162598e+03, 9.872624e+03, -1.034417e+03, -7.407299e+03, 7.035667e+03, 1.036975e+04, -5.754438e+03, -5.779644e+03, 6.000216e+03, 1.081900e+04, -9.018099e+03, -4.670102e+03, 5.068244e+03, 1.122259e+04, -9.313739e+02, -4.706751e+03, 4.193278e+03, 1.157960e+04, -1.674258e+04, -2.394722e+03, 3.415508e+03, 1.188682e+04, -4.162404e+03, -3.416222e+03, 2.647810e+03, 1.214910e+04, -1.641018e+04, -1.375684e+03, 1.940197e+03, 1.235489e+04, -2.597781e+04, -4.072350e+01, 1.253613e+03, 1.251075e+04, -1.550160e+04, -5.658062e+01, 4.993210e+02, 1.260869e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -7.571821e+05, 1.194273e+03, 0, 0, 2.280687e+05, -5.366371e+02, 0, 4.401563e-04, -3.880904e+04, 2.686421e+02, 0, 0, -1.184002e+05, 6.513468e+02, 6.182344e-01, 8.803125e-04, 6.120952e+04, -2.568675e+02, 1.398755e+00, 5.281875e-03, -2.456577e+04, 8.465396e+02, 2.046431e+00, 1.012359e-02, -5.560163e+04, 2.207308e+03, 8.347310e+00, 3.565266e-02, -6.365941e+04, 4.514850e+03, 2.810550e+01, 1.448114e-01, -1.150207e+05, 9.826355e+03, 8.095553e+01, 5.281875e-01, -2.675326e+05, 2.088122e+04, 2.172854e+02, 1.764146e+00, -4.855776e+05, 3.851471e+04, 5.397100e+02, 5.445173e+00, -8.721331e+05, 6.367194e+04, 1.205217e+03, 1.524745e+01, -9.184539e+05, 8.282197e+04, 2.383759e+03, 3.838735e+01, -1.307361e+06, 1.073647e+05, 4.170076e+03, 8.581991e+01, -1.216270e+06, 1.119986e+05, 6.587459e+03, 1.736267e+02, -1.276352e+06, 1.124177e+05, 9.409381e+03, 3.185987e+02, -9.788697e+05, 9.416016e+04, 1.235028e+04, 5.374427e+02, -7.995613e+05, 7.618671e+04, 1.505625e+04, 8.403357e+02, -7.460602e+05, 5.950676e+04, 1.732816e+04, 1.232937e+03, -4.349269e+05, 3.288320e+04, 1.890991e+04, 1.714067e+03, -2.903175e+05, 1.679987e+04, 1.972389e+04, 2.270884e+03, -2.341700e+05, 6.717412e+03, 1.992757e+04, 2.890724e+03, -1.591140e+05, -2.541145e+03, 1.958483e+04, 3.559598e+03, -9.377026e+04, -9.049582e+03, 1.877055e+04, 4.259945e+03, -3.112181e+04, -1.324477e+04, 1.763230e+04, 4.974656e+03, -6.713941e+04, -1.097160e+04, 1.635475e+04, 5.689683e+03, -1.171086e+04, -1.418498e+04, 1.495911e+04, 6.397430e+03, -1.203079e+04, -1.259366e+04, 1.351290e+04, 7.082987e+03, -2.735949e+04, -1.036650e+04, 1.212531e+04, 7.741638e+03, 8.398267e+03, -1.176714e+04, 1.074781e+04, 8.368608e+03, -2.360952e+04, -7.700526e+03, 9.466757e+03, 8.954412e+03, 3.871276e+03, -9.056076e+03, 8.250344e+03, 9.502464e+03, -6.443405e+03, -6.671943e+03, 7.119198e+03, 1.000279e+04, -7.871410e+03, -5.649041e+03, 6.108047e+03, 1.045952e+04, -8.718557e+03, -4.829450e+03, 5.161480e+03, 1.087083e+04, -1.292495e+03, -4.766287e+03, 4.267365e+03, 1.123419e+04, -9.861345e+03, -3.065607e+03, 3.472933e+03, 1.154681e+04, -1.727524e+04, -2.001187e+03, 2.739962e+03, 1.181333e+04, -9.339880e+03, -2.491882e+03, 1.972342e+03, 1.202929e+04, -2.480383e+04, -8.960043e+01, 1.262307e+03, 1.218417e+04, -1.550976e+04, -1.052398e+02, 5.321763e+02, 1.228360e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.280687e+05, 5.366371e+02, 0, 0, 0, 0, 0, 4.401563e-04, 0, 0, 0, 4.401563e-04, -1.733338e+04, 2.221243e+02, 0, 4.401563e-04, -1.275858e+04, 4.042146e+02, 9.341664e-01, 2.640938e-03, 1.648620e+03, 8.526882e+02, 3.875433e+00, 1.452516e-02, -1.019729e+05, 3.723777e+03, 1.376684e+01, 6.470297e-02, -5.222279e+04, 6.376447e+03, 5.040666e+01, 3.006267e-01, -1.972467e+05, 1.575596e+04, 1.432681e+02, 1.097310e+00, -4.522255e+05, 3.224516e+04, 3.877865e+02, 3.683668e+00, -6.472011e+05, 5.229836e+04, 9.287428e+02, 1.113463e+01, -9.846451e+05, 7.751316e+04, 1.928807e+03, 2.951336e+01, -1.120147e+06, 9.516690e+04, 3.526207e+03, 6.930084e+01, -1.060774e+06, 1.024968e+05, 5.698072e+03, 1.445909e+02, -1.080278e+06, 1.054362e+05, 8.329768e+03, 2.717027e+02, -1.167184e+06, 1.012812e+05, 1.122358e+04, 4.681035e+02, -8.134116e+05, 7.589663e+04, 1.397221e+04, 7.479364e+02, -5.142486e+05, 5.263146e+04, 1.620649e+04, 1.114264e+03, -5.840860e+05, 4.293903e+04, 1.790499e+04, 1.565472e+03, -2.806635e+05, 1.804160e+04, 1.892835e+04, 2.098314e+03, -1.902676e+05, 6.983141e+03, 1.923705e+04, 2.694941e+03, -2.082007e+05, 2.150441e+03, 1.906114e+04, 3.342563e+03, -5.374742e+04, -9.636906e+03, 1.839341e+04, 4.027727e+03, -9.427047e+04, -8.455175e+03, 1.739289e+04, 4.729183e+03, -1.263315e+04, -1.383242e+04, 1.618343e+04, 5.437924e+03, -5.405956e+04, -1.051530e+04, 1.486152e+04, 6.137134e+03, 4.123323e+03, -1.373276e+04, 1.347434e+04, 6.821774e+03, -1.966848e+04, -1.038438e+04, 1.209746e+04, 7.477629e+03, -1.751199e+04, -9.652355e+03, 1.078686e+04, 8.104279e+03, 3.295847e+03, -1.002127e+04, 9.489445e+03, 8.694407e+03, -1.938731e+03, -7.963785e+03, 8.293167e+03, 9.241338e+03, -2.615570e+04, -5.085764e+03, 7.230361e+03, 9.747489e+03, 1.004382e+04, -7.737635e+03, 6.157052e+03, 1.021296e+04, -1.151870e+04, -4.264058e+03, 5.190961e+03, 1.062368e+04, -5.395239e+03, -4.360268e+03, 4.334166e+03, 1.099135e+04, -1.187237e+04, -3.068215e+03, 3.525120e+03, 1.130985e+04, -8.828785e+03, -2.951184e+03, 2.748294e+03, 1.157956e+04, -1.425606e+04, -1.790576e+03, 2.012464e+03, 1.179469e+04, -3.104649e+04, 4.096561e+02, 1.304758e+03, 1.195543e+04, -1.414188e+04, -2.345618e+02, 4.929940e+02, 1.205795e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.284378e+03, 4.000235e+01, 0, 0, -1.596943e+04, 2.327633e+02, 2.033762e-01, 4.401563e-04, 1.547436e+04, 9.728437e+01, 1.332585e+00, 4.841719e-03, -4.391863e+04, 1.611874e+03, 3.954053e+00, 1.848656e-02, -1.774277e+04, 3.338879e+03, 1.984506e+01, 1.069580e-01, -2.636354e+05, 1.231744e+04, 7.035266e+01, 4.762491e-01, -1.523250e+05, 1.881496e+04, 2.323194e+02, 2.013715e+00, -5.937322e+05, 4.171430e+04, 5.875574e+02, 6.570653e+00, -7.266381e+05, 6.055013e+04, 1.349311e+03, 1.917673e+01, -8.860678e+05, 8.010778e+04, 2.622440e+03, 4.815926e+01, -1.086569e+06, 9.639717e+04, 4.493415e+03, 1.062836e+02, -9.745768e+05, 9.666372e+04, 6.884892e+03, 2.100144e+02, -1.047773e+06, 9.496512e+04, 9.556296e+03, 3.754075e+02, -6.732150e+05, 7.257512e+04, 1.219959e+04, 6.172408e+02, -6.412646e+05, 6.073496e+04, 1.451547e+04, 9.412046e+02, -4.770761e+05, 4.172546e+04, 1.637709e+04, 1.351410e+03, -3.658491e+05, 2.573258e+04, 1.759304e+04, 1.842114e+03, -1.459050e+05, 7.797252e+03, 1.813296e+04, 2.402150e+03, -2.270501e+05, 6.345087e+03, 1.816235e+04, 3.015249e+03, -5.163556e+04, -7.248933e+03, 1.772472e+04, 3.672398e+03, -9.784000e+04, -6.113061e+03, 1.692069e+04, 4.351479e+03, -4.721276e+04, -1.058933e+04, 1.588911e+04, 5.044252e+03, -2.325812e+04, -1.187676e+04, 1.464898e+04, 5.733633e+03, -7.615191e+03, -1.186838e+04, 1.334468e+04, 6.408326e+03, -2.309797e+04, -9.681961e+03, 1.206642e+04, 7.060851e+03, -1.619285e+04, -9.482512e+03, 1.080185e+04, 7.687342e+03, 2.078178e+03, -9.714292e+03, 9.537486e+03, 8.279170e+03, -1.618945e+04, -6.927762e+03, 8.365159e+03, 8.829938e+03, 7.335199e+02, -7.533587e+03, 7.255793e+03, 9.341236e+03, -1.450326e+03, -6.043556e+03, 6.228118e+03, 9.805634e+03, -1.816953e+04, -3.758371e+03, 5.326053e+03, 1.022606e+04, -1.744599e+03, -5.007206e+03, 4.429541e+03, 1.060407e+04, -1.013527e+04, -3.265815e+03, 3.587398e+03, 1.092797e+04, -1.259356e+04, -2.582008e+03, 2.814548e+03, 1.120259e+04, -1.274805e+04, -2.097313e+03, 2.054883e+03, 1.142390e+04, -2.791789e+04, 7.523855e+01, 1.329347e+03, 1.158716e+04, -1.719612e+04, -4.713965e+00, 5.420132e+02, 1.169180e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -7.176421e+02, 3.113526e+01, 0, 0, -1.800870e+04, 5.044997e+02, 2.852090e-01, 8.803125e-04, -6.298356e+03, 1.097487e+03, 4.660042e+00, 2.068734e-02, -8.791947e+04, 4.920687e+03, 2.117041e+01, 1.267650e-01, -1.511792e+05, 1.141104e+04, 9.051543e+01, 6.901650e-01, -3.106193e+05, 2.415462e+04, 2.850943e+02, 2.830205e+00, -5.405713e+05, 4.217464e+04, 7.415631e+02, 9.508255e+00, -5.706933e+05, 5.709472e+04, 1.607830e+03, 2.680684e+01, -8.596668e+05, 7.785137e+04, 2.987113e+03, 6.433676e+01, -8.771786e+05, 8.485822e+04, 4.935285e+03, 1.368477e+02, -8.102174e+05, 8.281917e+04, 7.255334e+03, 2.600694e+02, -6.674694e+05, 7.297462e+04, 9.707332e+03, 4.485879e+02, -6.717545e+05, 6.389033e+04, 1.205217e+04, 7.132714e+02, -3.554819e+05, 4.055708e+04, 1.401631e+04, 1.060593e+03, -4.167811e+05, 3.366675e+04, 1.546312e+04, 1.485747e+03, -1.323838e+05, 1.206436e+04, 1.634842e+04, 1.985782e+03, -2.565296e+05, 1.235833e+04, 1.671070e+04, 2.544205e+03, -7.754431e+04, -2.778930e+03, 1.659321e+04, 3.155150e+03, -6.065238e+04, -5.532359e+03, 1.601994e+04, 3.795263e+03, -6.016013e+04, -6.874641e+03, 1.523403e+04, 4.453979e+03, -3.842724e+04, -9.051155e+03, 1.424960e+04, 5.120220e+03, -1.505812e+04, -1.038403e+04, 1.311185e+04, 5.780549e+03, -1.932609e+04, -9.311433e+03, 1.192713e+04, 6.424029e+03, -2.567878e+03, -9.668649e+03, 1.073681e+04, 7.044632e+03, -2.137310e+04, -7.226824e+03, 9.588529e+03, 7.634721e+03, -4.048428e+03, -8.024655e+03, 8.455858e+03, 8.192586e+03, -9.345105e+03, -6.504380e+03, 7.358232e+03, 8.708498e+03, 1.110868e+03, -6.498387e+03, 6.328846e+03, 9.181543e+03, -1.038927e+04, -4.423289e+03, 5.401265e+03, 9.607874e+03, -8.382929e+03, -4.148725e+03, 4.539967e+03, 9.991244e+03, -1.284061e+04, -3.196734e+03, 3.706702e+03, 1.032616e+04, -7.952644e+03, -3.238144e+03, 2.887171e+03, 1.060975e+04, -2.012766e+04, -1.354531e+03, 2.121075e+03, 1.083559e+04, -2.131326e+04, -8.004748e+02, 1.341130e+03, 1.100550e+04, -1.524196e+04, -2.164961e+02, 5.721496e+02, 1.110911e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.811733e+03, 6.623464e+01, 0, 0, 2.568464e+03, 8.432503e+01, 5.115023e-01, 2.200781e-03, -2.004794e+04, 1.119994e+03, 2.378582e+00, 1.320469e-02, -5.899960e+04, 3.846531e+03, 1.815237e+01, 1.184020e-01, -1.105061e+05, 9.320633e+03, 8.088947e+01, 6.950067e-01, -2.221620e+05, 1.985802e+04, 2.613633e+02, 2.927919e+00, -4.065581e+05, 3.551385e+04, 6.885058e+02, 9.926844e+00, -5.094984e+05, 4.979654e+04, 1.507612e+03, 2.812995e+01, -6.336678e+05, 6.263542e+04, 2.791695e+03, 6.759920e+01, -5.771321e+05, 6.548998e+04, 4.520174e+03, 1.419161e+02, -5.870919e+05, 6.615160e+04, 6.549199e+03, 2.651867e+02, -5.916423e+05, 6.099313e+04, 8.705613e+03, 4.515611e+02, -3.105146e+05, 4.215730e+04, 1.068282e+04, 7.107075e+02, -3.690182e+05, 3.754835e+04, 1.233110e+04, 1.043000e+03, -2.480750e+05, 2.322678e+04, 1.359551e+04, 1.450970e+03, -1.497117e+05, 1.185092e+04, 1.431604e+04, 1.925035e+03, -8.514757e+04, 4.263741e+03, 1.458441e+04, 2.453455e+03, -1.505205e+05, 4.067158e+03, 1.452717e+04, 3.025317e+03, -3.556097e+03, -7.629858e+03, 1.407200e+04, 3.631602e+03, -5.542532e+04, -4.547126e+03, 1.336358e+04, 4.249173e+03, -2.492334e+04, -7.511616e+03, 1.254118e+04, 4.875408e+03, -3.228374e+04, -7.095606e+03, 1.157333e+04, 5.495835e+03, 8.005456e+03, -9.642728e+03, 1.050910e+04, 6.101611e+03, -2.540419e+04, -5.998865e+03, 9.470682e+03, 6.680639e+03, -1.534258e+03, -7.644748e+03, 8.443364e+03, 7.234962e+03, -1.521422e+04, -5.588894e+03, 7.427301e+03, 7.752369e+03, 2.151713e+03, -6.514804e+03, 6.440484e+03, 8.232600e+03, -1.841369e+04, -3.729884e+03, 5.527030e+03, 8.667363e+03, 1.579701e+03, -5.323167e+03, 4.630580e+03, 9.060834e+03, -1.605496e+04, -2.666378e+03, 3.802381e+03, 9.400648e+03, -1.363337e+04, -2.777913e+03, 3.003439e+03, 9.694207e+03, -9.563748e+03, -2.638621e+03, 2.184130e+03, 9.930046e+03, -3.556888e+04, 7.624686e+02, 1.440821e+03, 1.010325e+04, -1.690964e+04, -1.764955e+02, 5.681839e+02, 1.021822e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.643694e+03, 1.140404e+02, 0, 0, -6.562979e+03, 4.816660e+02, 1.445460e+00, 7.922813e-03, -1.299063e+04, 1.609270e+03, 9.594276e+00, 7.218563e-02, -7.131240e+04, 5.726209e+03, 4.357593e+01, 4.150673e-01, -1.117634e+05, 1.180640e+04, 1.624316e+02, 1.965298e+00, -2.304253e+05, 2.279086e+04, 4.523525e+02, 7.057025e+00, -3.315911e+05, 3.411993e+04, 1.042647e+03, 2.092943e+01, -3.603710e+05, 4.191874e+04, 1.999991e+03, 5.211274e+01, -3.916216e+05, 4.727670e+04, 3.311539e+03, 1.116914e+02, -3.844057e+05, 4.753490e+04, 4.900611e+03, 2.125391e+02, -3.148316e+05, 4.217486e+04, 6.599279e+03, 3.665476e+02, -2.947627e+05, 3.672338e+04, 8.238001e+03, 5.821150e+02, -1.877393e+05, 2.615824e+04, 9.665892e+03, 8.644409e+02, -1.939038e+05, 2.109766e+04, 1.078832e+04, 1.211959e+03, -1.268775e+05, 1.194889e+04, 1.155350e+04, 1.622333e+03, -5.212276e+04, 4.145660e+03, 1.190591e+04, 2.084908e+03, -1.041510e+05, 4.464942e+03, 1.197827e+04, 2.588510e+03, -1.984863e+04, -3.569719e+03, 1.174725e+04, 3.127176e+03, -3.741808e+04, -3.091579e+03, 1.126593e+04, 3.681872e+03, -2.888744e+04, -4.650632e+03, 1.065302e+04, 4.246808e+03, -6.248874e+03, -6.533785e+03, 9.886316e+03, 4.810160e+03, -1.492326e+04, -5.462305e+03, 9.064728e+03, 5.360728e+03, -1.612605e+04, -5.277340e+03, 8.222609e+03, 5.894540e+03, -1.302281e+04, -5.381978e+03, 7.329188e+03, 6.403576e+03, 1.844868e+03, -6.123135e+03, 6.402092e+03, 6.878745e+03, -1.598640e+04, -3.668586e+03, 5.540739e+03, 7.312670e+03, -3.218371e+03, -4.662379e+03, 4.696477e+03, 7.708645e+03, -1.404880e+04, -2.925585e+03, 3.881197e+03, 8.055558e+03, -1.463165e+04, -2.666220e+03, 3.081586e+03, 8.355163e+03, -1.277586e+04, -2.405669e+03, 2.258415e+03, 8.598143e+03, -3.742817e+04, 7.803610e+02, 1.474543e+03, 8.777701e+03, -1.548654e+04, -3.160486e+02, 5.519917e+02, 8.894396e+03, }; static float solarDataset440[] = { -6.439155e+11, 7.682264e+06, 1.061520e+03, 2.039373e+00, -1.551568e+09, -1.644546e+06, 7.523669e+02, 2.056656e+00, 1.570174e+09, -8.522139e+05, 2.877172e+02, 2.120770e+00, -3.012090e+08, 4.421119e+05, 2.347757e+02, 2.178751e+00, -2.081867e+07, 7.272809e+04, 4.311484e+02, 2.430188e+00, 7.899508e+06, 1.295109e+04, 5.150411e+02, 2.939752e+00, 4.151745e+06, 2.883739e+04, 6.139858e+02, 3.810026e+00, 3.293018e+06, 4.361918e+04, 7.999407e+02, 5.335932e+00, -3.828120e+06, 9.429242e+04, 1.137923e+03, 8.117909e+00, 2.986346e+06, 6.726090e+04, 1.682654e+03, 1.349342e+01, -1.518315e+06, 1.401839e+05, 2.506574e+03, 2.312609e+01, -2.560500e+06, 1.889565e+05, 3.957987e+03, 4.170958e+01, -3.827648e+06, 2.429145e+05, 6.184460e+03, 7.682438e+01, -3.299120e+06, 2.716569e+05, 9.361640e+03, 1.406772e+02, -4.786591e+06, 3.230548e+05, 1.360464e+04, 2.503356e+02, -5.235884e+06, 3.347402e+05, 1.893351e+04, 4.303752e+02, -4.344959e+06, 2.992049e+05, 2.482781e+04, 7.073441e+02, -4.495848e+06, 2.671507e+05, 3.067007e+04, 1.104209e+03, -2.904965e+06, 1.819224e+05, 3.574947e+04, 1.639240e+03, -2.295257e+06, 1.245881e+05, 3.945941e+04, 2.313019e+03, -2.021822e+06, 7.712727e+04, 4.169658e+04, 3.119853e+03, -5.892701e+05, 4.095196e+03, 4.218370e+04, 4.041884e+03, -1.166644e+06, 8.504980e+03, 4.136899e+04, 5.044736e+03, -1.972687e+05, -4.070728e+04, 3.941477e+04, 6.112839e+03, -2.093258e+05, -3.893157e+04, 3.660650e+04, 7.200837e+03, -2.639589e+05, -3.598837e+04, 3.358396e+04, 8.293512e+03, 8.246154e+03, -4.584505e+04, 3.026767e+04, 9.372228e+03, -6.438522e+04, -3.581717e+04, 2.697011e+04, 1.041147e+04, -7.353188e+04, -3.121684e+04, 2.387281e+04, 1.140770e+04, 5.933961e+04, -3.366294e+04, 2.086077e+04, 1.235002e+04, -3.538054e+04, -2.202528e+04, 1.819119e+04, 1.322614e+04, -2.443121e+04, -1.981273e+04, 1.582620e+04, 1.404641e+04, 3.781173e+04, -2.036056e+04, 1.359973e+04, 1.480309e+04, -1.650133e+04, -1.256169e+04, 1.171377e+04, 1.549140e+04, -1.983390e+04, -1.069497e+04, 1.008886e+04, 1.612572e+04, 1.056101e+04, -1.130558e+04, 8.546710e+03, 1.670160e+04, -2.713816e+03, -7.912829e+03, 7.207588e+03, 1.721354e+04, -4.452889e+03, -6.395793e+03, 6.078559e+03, 1.767169e+04, -6.835308e+03, -5.126471e+03, 5.077617e+03, 1.807822e+04, -9.922932e+03, -4.054774e+03, 4.171164e+03, 1.843425e+04, -4.659839e+03, -3.888745e+03, 3.322981e+03, 1.873921e+04, -9.547958e+03, -2.601152e+03, 2.562645e+03, 1.899026e+04, -1.701043e+04, -1.361229e+03, 1.872053e+03, 1.919113e+04, -1.872608e+04, -7.127307e+02, 1.172457e+03, 1.934026e+04, -1.350361e+04, -1.647467e+02, 4.949774e+02, 1.943062e+04, 2.157451e+11, 1.943248e+06, -2.593158e+02, 9.505553e-01, -7.114316e+10, 1.371541e+07, 0, 9.477677e-01, 1.280844e+09, -7.152589e+05, 2.024044e+02, 1.022474e+00, -3.379517e+08, 4.237257e+05, 1.460656e+02, 1.057040e+00, 3.483677e+07, -4.170331e+04, 2.741455e+02, 1.234886e+00, -6.107958e+06, 4.113951e+04, 3.019965e+02, 1.517543e+00, 6.609522e+06, 7.210950e+03, 3.859744e+02, 2.068921e+00, 6.293178e+05, 4.235131e+04, 5.125775e+02, 3.017804e+00, -8.119125e+05, 6.395016e+04, 7.753549e+02, 4.886021e+00, -1.001544e+06, 8.369718e+04, 1.219698e+03, 8.638624e+00, 2.469002e+05, 1.020158e+05, 1.936104e+03, 1.606076e+01, -3.071414e+06, 1.744496e+05, 3.124365e+03, 3.047463e+01, -2.398553e+06, 2.065189e+05, 5.080502e+03, 5.904147e+01, -4.148108e+06, 2.720416e+05, 7.949415e+03, 1.123456e+02, -4.421216e+06, 3.044491e+05, 1.197323e+04, 2.080105e+02, -4.886328e+06, 3.225125e+05, 1.702702e+04, 3.685740e+02, -4.260302e+06, 2.983774e+05, 2.277937e+04, 6.206306e+02, -4.488843e+06, 2.719539e+05, 2.864869e+04, 9.887191e+02, -3.035307e+06, 1.911892e+05, 3.388554e+04, 1.492962e+03, -2.303207e+06, 1.301134e+05, 3.780104e+04, 2.135924e+03, -1.695747e+06, 7.533493e+04, 4.024633e+04, 2.912218e+03, -1.131339e+06, 2.856670e+04, 4.111774e+04, 3.805227e+03, -7.045700e+05, -4.867972e+03, 4.054360e+04, 4.789173e+03, -3.620224e+05, -2.694148e+04, 3.883948e+04, 5.834790e+03, -4.066279e+05, -2.925181e+04, 3.641435e+04, 6.913749e+03, -1.132796e+05, -4.305023e+04, 3.342235e+04, 8.003883e+03, 3.570589e+03, -4.331910e+04, 3.014234e+04, 9.074909e+03, -1.133431e+05, -3.225022e+04, 2.700976e+04, 1.011271e+04, 1.186040e+03, -3.456607e+04, 2.396680e+04, 1.111301e+04, -4.979073e+04, -2.665824e+04, 2.106894e+04, 1.205891e+04, 1.592532e+04, -2.657005e+04, 1.836669e+04, 1.294864e+04, 8.401869e+03, -2.123268e+04, 1.592066e+04, 1.377255e+04, -2.611279e+04, -1.551961e+04, 1.380784e+04, 1.453477e+04, 1.246222e+04, -1.579531e+04, 1.187851e+04, 1.523848e+04, -6.658919e+03, -1.142901e+04, 1.017094e+04, 1.587713e+04, 1.928404e+03, -1.015849e+04, 8.688190e+03, 1.645836e+04, -1.608648e+04, -7.006837e+03, 7.388582e+03, 1.698200e+04, 6.840295e+03, -7.868280e+03, 6.193951e+03, 1.745255e+04, -1.757879e+04, -4.203383e+03, 5.158025e+03, 1.786403e+04, 6.926599e+03, -5.876158e+03, 4.203700e+03, 1.822680e+04, -1.598552e+04, -2.390669e+03, 3.390699e+03, 1.853138e+04, -6.027778e+03, -3.175285e+03, 2.640031e+03, 1.879204e+04, -1.851678e+04, -1.220782e+03, 1.930943e+03, 1.899774e+04, -2.290692e+04, -3.911046e+02, 1.218154e+03, 1.915237e+04, -1.519600e+04, -2.633004e+01, 4.835101e+02, 1.924636e+04, -3.704596e+12, 5.454497e+07, 1.421905e+03, 2.926930e-01, 3.173305e+09, -5.743591e+05, 0, 3.144359e-01, -3.364539e+06, 6.299289e+03, 0, 3.116483e-01, -3.980029e+08, 4.573928e+05, 3.043542e+00, 3.122058e-01, 4.559887e+07, -6.916950e+04, 1.007848e+02, 3.969474e-01, -2.443350e+07, 8.526024e+04, 1.065719e+02, 4.794590e-01, 5.589237e+06, -4.160307e+03, 1.936915e+02, 7.621167e-01, 9.451238e+04, 2.614347e+04, 2.558371e+02, 1.224850e+00, 3.067526e+04, 3.723230e+04, 4.105653e+02, 2.194361e+00, -7.036798e+05, 5.911092e+04, 6.903957e+02, 4.252689e+00, -5.513797e+05, 8.299526e+04, 1.196595e+03, 8.696047e+00, -2.191497e+06, 1.345808e+05, 2.089839e+03, 1.812299e+01, -2.070793e+06, 1.743475e+05, 3.623925e+03, 3.802500e+01, -4.038717e+06, 2.455242e+05, 6.036923e+03, 7.762385e+01, -3.761674e+06, 2.746045e+05, 9.589842e+03, 1.529898e+02, -5.050391e+06, 3.152332e+05, 1.422849e+04, 2.849469e+02, -4.033593e+06, 2.876971e+05, 1.972387e+04, 5.007826e+02, -3.837058e+06, 2.611389e+05, 2.542725e+04, 8.243544e+02, -3.415481e+06, 2.122601e+05, 3.081216e+04, 1.277441e+03, -2.263710e+06, 1.384666e+05, 3.511626e+04, 1.870490e+03, -1.502418e+06, 8.143096e+04, 3.793597e+04, 2.597510e+03, -1.629920e+06, 5.437166e+04, 3.934644e+04, 3.445165e+03, -3.463979e+05, -1.248103e+04, 3.915122e+04, 4.394698e+03, -4.796136e+05, -1.400399e+04, 3.778512e+04, 5.405067e+03, -4.525999e+05, -2.265499e+04, 3.581125e+04, 6.461725e+03, -3.180239e+04, -4.281554e+04, 3.309592e+04, 7.538118e+03, -1.696614e+05, -3.260128e+04, 3.010816e+04, 8.601531e+03, 2.216761e+03, -3.819533e+04, 2.706857e+04, 9.643927e+03, -5.840964e+04, -2.977311e+04, 2.409090e+04, 1.064435e+04, -5.917126e+04, -2.642897e+04, 2.128022e+04, 1.159950e+04, 7.415464e+04, -2.984562e+04, 1.854160e+04, 1.249835e+04, -4.015798e+04, -1.708081e+04, 1.618474e+04, 1.332958e+04, -2.724330e+04, -1.610742e+04, 1.411441e+04, 1.410972e+04, 3.392267e+04, -1.758161e+04, 1.211073e+04, 1.482824e+04, -1.941985e+04, -1.017686e+04, 1.041268e+04, 1.547855e+04, -1.295582e+04, -9.453817e+03, 8.939028e+03, 1.607642e+04, 1.103183e+04, -9.749963e+03, 7.541593e+03, 1.661529e+04, -1.309367e+04, -5.774869e+03, 6.355166e+03, 1.709222e+04, -6.434020e+03, -5.622814e+03, 5.307434e+03, 1.751883e+04, -4.996029e+03, -4.764721e+03, 4.331959e+03, 1.788974e+04, -4.447507e+03, -3.893715e+03, 3.465440e+03, 1.820564e+04, -1.239499e+04, -2.374546e+03, 2.708845e+03, 1.846887e+04, -1.791766e+04, -1.467369e+03, 1.990862e+03, 1.868255e+04, -2.061413e+04, -6.862093e+02, 1.247688e+03, 1.884111e+04, -1.468218e+04, -1.400460e+02, 5.211565e+02, 1.893732e+04, 1.308076e+12, -1.882941e+07, -5.168990e+02, 4.404332e-02, -8.250594e+09, 1.493334e+06, 0, 3.623818e-02, 6.347536e+07, -3.118404e+04, 0, 4.348581e-02, -6.744998e+07, 8.687614e+04, 0, 4.237079e-02, -1.059940e+06, 1.737933e+03, 2.850557e+01, 6.021112e-02, 3.873147e+06, -6.437214e+03, 2.864464e+01, 9.087420e-02, -2.038775e+06, 1.383359e+04, 3.704050e+01, 1.349175e-01, 1.734783e+06, 9.982716e+02, 6.829641e+01, 2.609149e-01, -1.300032e+06, 2.675349e+04, 1.182804e+02, 5.112371e-01, -4.406929e+05, 3.149201e+04, 2.638582e+02, 1.259974e+00, -8.366025e+05, 5.266660e+04, 5.292339e+02, 3.134881e+00, -7.924932e+05, 7.942542e+04, 1.048528e+03, 7.713714e+00, -2.114312e+06, 1.343945e+05, 2.024267e+03, 1.835492e+01, -3.185798e+06, 1.914041e+05, 3.782729e+03, 4.238696e+01, -3.032631e+06, 2.279831e+05, 6.542534e+03, 9.240122e+01, -4.568244e+06, 2.833195e+05, 1.042573e+04, 1.866350e+02, -3.365946e+06, 2.645481e+05, 1.535126e+04, 3.512042e+02, -4.471630e+06, 2.758277e+05, 2.079988e+04, 6.104689e+02, -2.224000e+06, 1.886401e+05, 2.617243e+04, 9.914146e+02, -2.922616e+06, 1.750678e+05, 3.076047e+04, 1.501533e+03, -1.487031e+06, 9.279157e+04, 3.425527e+04, 2.152028e+03, -1.120184e+06, 5.413495e+04, 3.618144e+04, 2.925201e+03, -9.574249e+05, 2.560661e+04, 3.684905e+04, 3.805894e+03, -4.688823e+05, -8.953231e+03, 3.622075e+04, 4.771127e+03, -2.008025e+05, -2.566219e+04, 3.456168e+04, 5.787472e+03, -2.845628e+05, -2.408577e+04, 3.238769e+04, 6.829708e+03, -9.819349e+04, -3.380507e+04, 2.980207e+04, 7.880871e+03, -2.605063e+04, -3.403133e+04, 2.695787e+04, 8.913987e+03, -6.318205e+04, -2.810438e+04, 2.417620e+04, 9.914760e+03, -4.302365e+04, -2.624841e+04, 2.148046e+04, 1.087609e+04, 6.156530e+04, -2.811597e+04, 1.885622e+04, 1.178578e+04, -7.492135e+04, -1.496397e+04, 1.657837e+04, 1.263475e+04, 1.109430e+04, -1.929611e+04, 1.445066e+04, 1.343597e+04, 2.424357e+04, -1.637395e+04, 1.244181e+04, 1.416959e+04, -4.234273e+04, -8.757096e+03, 1.078613e+04, 1.484129e+04, 2.003718e+04, -1.262376e+04, 9.226693e+03, 1.546219e+04, -1.526070e+04, -7.207988e+03, 7.836505e+03, 1.601547e+04, -1.628001e+03, -7.394836e+03, 6.625916e+03, 1.651619e+04, -7.377006e+03, -5.561068e+03, 5.524485e+03, 1.695833e+04, -6.725890e+03, -4.724347e+03, 4.541853e+03, 1.734582e+04, -4.572217e+03, -4.074851e+03, 3.648060e+03, 1.767801e+04, -1.896547e+04, -1.949759e+03, 2.858043e+03, 1.795535e+04, -1.298453e+04, -2.311439e+03, 2.059357e+03, 1.818104e+04, -2.551484e+04, -2.163187e+02, 1.287627e+03, 1.834266e+04, -1.600338e+04, -4.270993e+01, 5.122679e+02, 1.844268e+04, -1.846467e+11, 2.613334e+06, 7.450276e+01, 3.902573e-03, 1.667286e+09, -3.160544e+05, 0, 5.017594e-03, -3.902174e+05, 5.452947e+03, -3.446309e+00, 3.345062e-03, -2.708707e+06, 4.468648e+03, 0, 2.787552e-03, -1.153853e+06, 2.969827e+03, 2.394593e+00, 3.902573e-03, 3.457846e+05, 1.456899e+01, 4.812851e+00, 8.362656e-03, 2.322128e+04, 1.682256e+03, 7.411109e+00, 1.728282e-02, -9.250953e+04, 3.491170e+03, 1.511058e+01, 4.181328e-02, -1.140402e+04, 5.499039e+03, 3.309618e+01, 1.131746e-01, 2.602436e+05, 9.641526e+03, 7.375697e+01, 3.133209e-01, -1.325523e+06, 3.732442e+04, 1.808742e+02, 8.948042e-01, -4.382676e+05, 4.642239e+04, 4.773414e+02, 2.895709e+00, -1.636631e+06, 9.209222e+04, 1.051141e+03, 8.195961e+00, -2.042284e+06, 1.355507e+05, 2.219278e+03, 2.184828e+01, -2.868143e+06, 1.895901e+05, 4.230793e+03, 5.311346e+01, -3.378460e+06, 2.314211e+05, 7.337166e+03, 1.178716e+02, -3.383704e+06, 2.485497e+05, 1.152400e+04, 2.383223e+02, -3.611693e+06, 2.504024e+05, 1.651144e+04, 4.404639e+02, -2.710830e+06, 2.062171e+05, 2.172585e+04, 7.505122e+02, -2.193920e+06, 1.640529e+05, 2.647851e+04, 1.184719e+03, -1.888746e+06, 1.220847e+05, 3.038570e+04, 1.752278e+03, -1.180573e+06, 6.785978e+04, 3.301593e+04, 2.451054e+03, -9.119347e+05, 3.479131e+04, 3.423626e+04, 3.263083e+03, -4.432393e+05, 6.671025e+02, 3.418252e+04, 4.167016e+03, -3.338143e+05, -1.199384e+04, 3.313578e+04, 5.133589e+03, -1.979577e+05, -2.245575e+04, 3.142588e+04, 6.140752e+03, -1.443444e+05, -2.612535e+04, 2.924376e+04, 7.164707e+03, -1.039579e+05, -2.759601e+04, 2.677478e+04, 8.185464e+03, 6.889591e+03, -3.078271e+04, 2.413897e+04, 9.184259e+03, -7.514438e+04, -2.239874e+04, 2.158917e+04, 1.014449e+04, 4.257686e+04, -2.654203e+04, 1.911626e+04, 1.106395e+04, -6.392534e+04, -1.575459e+04, 1.685800e+04, 1.192695e+04, 3.833671e+04, -2.059340e+04, 1.473601e+04, 1.274193e+04, -4.175233e+04, -1.138346e+04, 1.282932e+04, 1.349170e+04, 1.568732e+04, -1.428547e+04, 1.108599e+04, 1.418980e+04, -1.592132e+04, -9.200685e+03, 9.505594e+03, 1.482175e+04, 9.423744e+03, -9.833787e+03, 8.103365e+03, 1.539779e+04, -2.081387e+04, -5.508437e+03, 6.882485e+03, 1.591251e+04, 2.938513e+03, -6.992832e+03, 5.751007e+03, 1.637591e+04, -1.006852e+04, -4.396123e+03, 4.730716e+03, 1.677699e+04, -9.845785e+03, -3.800704e+03, 3.824602e+03, 1.712480e+04, -1.466034e+04, -2.720469e+03, 2.967253e+03, 1.741587e+04, -1.131802e+04, -2.508277e+03, 2.133736e+03, 1.764822e+04, -2.788700e+04, -1.062039e+01, 1.368856e+03, 1.781643e+04, -1.738426e+04, -4.486282e+01, 5.656062e+02, 1.792414e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.297648e+06, 4.111555e+03, 0, 0, 0, 0, 0, 5.575104e-04, -5.581082e+05, 1.781758e+03, 0, 5.575104e-04, 1.843572e+05, -3.770991e+02, 1.469976e+00, 2.787552e-03, -3.952308e+05, 2.931368e+03, 2.469540e+00, 6.132615e-03, 2.621871e+05, -9.011830e+01, 9.486217e+00, 2.843303e-02, -1.562634e+05, 6.783349e+03, 1.981770e+01, 7.637893e-02, -5.987073e+05, 1.920998e+04, 7.296369e+01, 3.010556e-01, -4.734045e+05, 3.233755e+04, 2.337040e+02, 1.231541e+00, -1.292884e+06, 6.785280e+04, 6.097906e+02, 4.193593e+00, -1.682559e+06, 1.071776e+05, 1.453400e+03, 1.287515e+01, -2.404541e+06, 1.584818e+05, 3.025797e+03, 3.469778e+01, -3.146009e+06, 2.066665e+05, 5.619983e+03, 8.326530e+01, -2.709797e+06, 2.201851e+05, 9.299217e+03, 1.789965e+02, -3.778700e+06, 2.492082e+05, 1.388870e+04, 3.460623e+02, -2.343804e+06, 1.957822e+05, 1.893955e+04, 6.135988e+02, -2.283303e+06, 1.718623e+05, 2.366783e+04, 9.972451e+02, -1.924180e+06, 1.288603e+05, 2.777848e+04, 1.511863e+03, -9.241237e+05, 6.747835e+04, 3.065304e+04, 2.156804e+03, -1.086438e+06, 5.116178e+04, 3.229492e+04, 2.915626e+03, -4.632157e+05, 7.870416e+03, 3.273955e+04, 3.776818e+03, -3.230504e+05, -6.985506e+03, 3.205541e+04, 4.707586e+03, -2.475074e+05, -1.596795e+04, 3.068760e+04, 5.686358e+03, -1.378401e+05, -2.375715e+04, 2.877374e+04, 6.690937e+03, -8.940252e+04, -2.589151e+04, 2.650252e+04, 7.698058e+03, -2.683560e+04, -2.716741e+04, 2.406685e+04, 8.689683e+03, -5.526493e+04, -2.270183e+04, 2.164225e+04, 9.650765e+03, -8.489383e+03, -2.300292e+04, 1.926287e+04, 1.057381e+04, -1.388131e+04, -1.936649e+04, 1.699055e+04, 1.144637e+04, 7.094209e+03, -1.780787e+04, 1.489322e+04, 1.226540e+04, -2.836236e+04, -1.264700e+04, 1.301116e+04, 1.302698e+04, 2.092988e+04, -1.443269e+04, 1.125648e+04, 1.373400e+04, -2.156834e+04, -8.504181e+03, 9.717555e+03, 1.437710e+04, -6.708749e+03, -8.789276e+03, 8.334151e+03, 1.496836e+04, -1.692188e+03, -7.736227e+03, 7.027454e+03, 1.549866e+04, -4.473494e+03, -6.083076e+03, 5.875349e+03, 1.596817e+04, -1.208879e+04, -4.407527e+03, 4.863871e+03, 1.638080e+04, -8.618245e+03, -4.133615e+03, 3.916455e+03, 1.673821e+04, -8.899190e+03, -3.323467e+03, 3.029126e+03, 1.703543e+04, -1.897729e+04, -1.633485e+03, 2.225304e+03, 1.727258e+04, -3.279575e+04, 2.298052e+02, 1.423357e+03, 1.745072e+04, -1.484592e+04, -2.882339e+02, 5.261383e+02, 1.756148e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -5.090528e+04, 4.110663e+02, 0, 0, 2.437332e+04, 1.728558e+02, 1.098978e+00, 2.230042e-03, -5.251004e+04, 1.839037e+03, 3.415254e+00, 1.003519e-02, -1.034817e+05, 5.494798e+03, 1.715950e+01, 6.076864e-02, -3.817933e+05, 1.664499e+04, 6.975643e+01, 3.183384e-01, -5.260784e+05, 3.421596e+04, 2.439328e+02, 1.452872e+00, -1.288699e+06, 7.236937e+04, 6.940201e+02, 5.383321e+00, -1.884821e+06, 1.157847e+05, 1.715049e+03, 1.728115e+01, -2.068708e+06, 1.540029e+05, 3.564861e+03, 4.720887e+01, -2.701302e+06, 1.965799e+05, 6.434261e+03, 1.113315e+02, -2.916540e+06, 2.134724e+05, 1.036392e+04, 2.333911e+02, -2.526077e+06, 1.969947e+05, 1.493163e+04, 4.395490e+02, -1.965767e+06, 1.637507e+05, 1.953147e+04, 7.516110e+02, -1.697977e+06, 1.315705e+05, 2.369155e+04, 1.184152e+03, -1.124648e+06, 8.674265e+04, 2.700457e+04, 1.743860e+03, -9.015866e+05, 5.643048e+04, 2.922375e+04, 2.423722e+03, -7.506628e+05, 3.028053e+04, 3.032450e+04, 3.211428e+03, -1.502096e+05, -6.976241e+03, 3.021703e+04, 4.084801e+03, -4.313262e+05, -4.280012e+02, 2.934955e+04, 5.011680e+03, -8.356901e+04, -2.305404e+04, 2.785722e+04, 5.981843e+03, -6.447470e+04, -2.307799e+04, 2.585185e+04, 6.959204e+03, -6.518919e+04, -2.177705e+04, 2.375067e+04, 7.931175e+03, -6.379765e+04, -2.063416e+04, 2.157590e+04, 8.885643e+03, 3.719946e+02, -2.246051e+04, 1.933079e+04, 9.809115e+03, -2.302765e+04, -1.787789e+04, 1.717219e+04, 1.068719e+04, -8.297077e+03, -1.659973e+04, 1.515538e+04, 1.151822e+04, 7.842093e+02, -1.472122e+04, 1.326753e+04, 1.229522e+04, -1.859957e+04, -1.110603e+04, 1.156662e+04, 1.301583e+04, 4.434424e+03, -1.134157e+04, 9.987902e+03, 1.368140e+04, -2.070461e+04, -7.474109e+03, 8.566013e+03, 1.428543e+04, 1.277143e+04, -9.241875e+03, 7.241224e+03, 1.483337e+04, -1.508531e+04, -4.897739e+03, 6.099617e+03, 1.531603e+04, -1.471159e+04, -4.527480e+03, 5.082794e+03, 1.574803e+04, -3.968351e+03, -4.893573e+03, 4.064790e+03, 1.612095e+04, -1.081038e+04, -3.174699e+03, 3.148908e+03, 1.642812e+04, -2.027976e+04, -1.650839e+03, 2.326102e+03, 1.667577e+04, -2.971391e+04, -2.147712e+02, 1.486818e+03, 1.686212e+04, -1.842872e+04, -5.515463e+01, 5.911260e+02, 1.697771e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.548164e+03, 5.832732e+01, 0, 0, -4.254350e+04, 1.106875e+03, 4.435921e-01, 1.115021e-03, -6.186367e+04, 3.476985e+03, 8.919585e+00, 3.177809e-02, -2.400450e+05, 1.236929e+04, 4.781682e+01, 2.358269e-01, -5.044807e+05, 3.042742e+04, 2.007490e+02, 1.304017e+00, -1.089476e+06, 6.341001e+04, 6.399979e+02, 5.479212e+00, -1.227911e+06, 9.442542e+04, 1.632738e+03, 1.854057e+01, -1.843917e+06, 1.380790e+05, 3.410850e+03, 5.106126e+01, -2.151846e+06, 1.665970e+05, 6.202903e+03, 1.213332e+02, -2.042129e+06, 1.709803e+05, 9.861164e+03, 2.528505e+02, -2.013808e+06, 1.629299e+05, 1.399494e+04, 4.696808e+02, -1.226414e+06, 1.227890e+05, 1.806697e+04, 7.926443e+02, -1.415486e+06, 1.097980e+05, 2.166666e+04, 1.230785e+03, -7.867272e+05, 6.384606e+04, 2.448953e+04, 1.792229e+03, -6.455655e+05, 4.083803e+04, 2.621488e+04, 2.463119e+03, -4.555601e+05, 1.792048e+04, 2.696774e+04, 3.230170e+03, -9.267617e+04, -6.476458e+03, 2.676322e+04, 4.071033e+03, -2.927601e+05, -1.052446e+03, 2.601313e+04, 4.960256e+03, -1.217774e+05, -1.516011e+04, 2.477810e+04, 5.889640e+03, -3.133872e+04, -2.038053e+04, 2.303332e+04, 6.828298e+03, -8.323439e+04, -1.637279e+04, 2.115509e+04, 7.757606e+03, 2.477021e+04, -2.169634e+04, 1.917545e+04, 8.668998e+03, -6.502164e+04, -1.334719e+04, 1.725980e+04, 9.544082e+03, 5.350009e+03, -1.721099e+04, 1.537623e+04, 1.038587e+04, -1.384803e+04, -1.325894e+04, 1.354377e+04, 1.117533e+04, 4.594548e+03, -1.274668e+04, 1.186473e+04, 1.191404e+04, -3.094085e+04, -8.212376e+03, 1.034769e+04, 1.259716e+04, 2.132700e+04, -1.145801e+04, 8.882879e+03, 1.322813e+04, -3.035282e+04, -4.902982e+03, 7.607703e+03, 1.379274e+04, 5.411916e+03, -7.830371e+03, 6.412932e+03, 1.430841e+04, -1.810219e+04, -4.158606e+03, 5.307838e+03, 1.475643e+04, -3.007288e+02, -5.370719e+03, 4.283134e+03, 1.514813e+04, -2.178750e+04, -2.173925e+03, 3.365475e+03, 1.547263e+04, -1.511740e+04, -2.655632e+03, 2.459696e+03, 1.573975e+04, -3.355339e+04, 7.946364e+01, 1.567829e+03, 1.593402e+04, -1.896481e+04, -1.109393e+02, 6.194191e+02, 1.605676e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -7.491786e+03, 2.774529e+02, 0, 0, -4.543511e+04, 1.887313e+03, 2.744877e+00, 1.059270e-02, -6.058786e+04, 5.419371e+03, 2.435209e+01, 1.321300e-01, -2.888232e+05, 1.859427e+04, 1.103914e+02, 7.927798e-01, -6.056967e+05, 4.106824e+04, 4.123811e+02, 3.821734e+00, -8.632473e+05, 6.819488e+04, 1.152532e+03, 1.412787e+01, -1.223397e+06, 9.931776e+04, 2.559702e+03, 4.147376e+01, -1.340520e+06, 1.187963e+05, 4.785345e+03, 1.020841e+02, -1.331923e+06, 1.258200e+05, 7.731127e+03, 2.165939e+02, -1.384212e+06, 1.233902e+05, 1.113473e+04, 4.071911e+02, -6.897551e+05, 8.991942e+04, 1.453688e+04, 6.933099e+02, -1.214735e+06, 9.534407e+04, 1.765376e+04, 1.082844e+03, -4.097940e+05, 4.438210e+04, 2.014827e+04, 1.588657e+03, -3.878253e+05, 3.305638e+04, 2.168065e+04, 2.190812e+03, -4.045554e+05, 2.233340e+04, 2.261177e+04, 2.884151e+03, -1.793317e+05, 1.946184e+03, 2.274125e+04, 3.654479e+03, -6.062687e+04, -7.801344e+03, 2.217293e+04, 4.474418e+03, -1.596910e+05, -4.718906e+03, 2.128443e+04, 5.326097e+03, -4.954925e+04, -1.385354e+04, 2.004253e+04, 6.200059e+03, -1.408864e+04, -1.539126e+04, 1.849437e+04, 7.069552e+03, -3.886102e+04, -1.263844e+04, 1.691557e+04, 7.922135e+03, -2.899779e+04, -1.274985e+04, 1.531142e+04, 8.751657e+03, 3.490567e+03, -1.374791e+04, 1.365887e+04, 9.545296e+03, -1.297414e+04, -1.056211e+04, 1.209829e+04, 1.029242e+04, -9.319178e+03, -9.642875e+03, 1.065048e+04, 1.099410e+04, -9.836923e+03, -8.388618e+03, 9.274745e+03, 1.164472e+04, -1.192357e+04, -7.167599e+03, 7.978709e+03, 1.224070e+04, 1.301938e+03, -7.300621e+03, 6.746966e+03, 1.277847e+04, -2.409152e+04, -3.801826e+03, 5.650636e+03, 1.325335e+04, 2.135069e+03, -6.018935e+03, 4.566522e+03, 1.367190e+04, -2.471835e+04, -2.111991e+03, 3.591472e+03, 1.401725e+04, -1.336144e+04, -3.118779e+03, 2.626973e+03, 1.430292e+04, -3.618346e+04, 1.887078e+02, 1.694546e+03, 1.451020e+04, -2.192421e+04, -1.048766e+01, 6.919574e+02, 1.464393e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.298658e+02, 1.891811e+01, 0, 0, -1.240277e+04, 5.345032e+02, 2.608164e-01, 1.115021e-03, -1.596284e+04, 1.741852e+03, 7.032467e+00, 4.069826e-02, -1.027246e+05, 7.361202e+03, 3.925922e+01, 3.027282e-01, -2.060335e+05, 1.759016e+04, 1.746335e+02, 1.730512e+00, -4.143519e+05, 3.512883e+04, 5.474948e+02, 7.103240e+00, -5.194204e+05, 5.235380e+04, 1.348534e+03, 2.294490e+01, -7.226607e+05, 7.188365e+04, 2.713832e+03, 6.034437e+01, -8.224504e+05, 8.236982e+04, 4.702827e+03, 1.360303e+02, -5.759747e+05, 7.532407e+04, 7.117950e+03, 2.687273e+02, -7.814308e+05, 7.950876e+04, 9.732035e+03, 4.740952e+02, -4.677243e+05, 5.706459e+04, 1.228851e+04, 7.694051e+02, -3.405356e+05, 4.326742e+04, 1.440361e+04, 1.156059e+03, -3.661262e+05, 3.527188e+04, 1.610547e+04, 1.634736e+03, -2.050564e+05, 1.800520e+04, 1.723562e+04, 2.202346e+03, -1.739701e+05, 9.803099e+03, 1.773202e+04, 2.842272e+03, -4.267503e+04, -1.775289e+03, 1.770045e+04, 3.540405e+03, -1.174590e+05, 2.979865e+02, 1.732537e+04, 4.277679e+03, -6.005372e+04, -6.416114e+03, 1.663838e+04, 5.047353e+03, -1.009872e+04, -1.033768e+04, 1.560400e+04, 5.826299e+03, -4.043125e+04, -7.878538e+03, 1.446322e+04, 6.598461e+03, -2.113247e+04, -9.484497e+03, 1.324051e+04, 7.358438e+03, 2.589035e+03, -1.043233e+04, 1.192600e+04, 8.090833e+03, -2.651877e+04, -6.981116e+03, 1.067108e+04, 8.786026e+03, -6.138087e+03, -8.355998e+03, 9.423123e+03, 9.444529e+03, -1.199978e+04, -6.803323e+03, 8.184259e+03, 1.005210e+04, -5.136721e+03, -6.606467e+03, 7.004292e+03, 1.060672e+04, -8.765806e+03, -5.278347e+03, 5.900880e+03, 1.110251e+04, -2.318204e+04, -3.325419e+03, 4.877837e+03, 1.153968e+04, -6.973830e+03, -4.679254e+03, 3.813233e+03, 1.191537e+04, -2.198839e+04, -2.109273e+03, 2.813720e+03, 1.221296e+04, -4.232767e+04, 4.552064e+02, 1.844062e+03, 1.243947e+04, -2.133196e+04, -2.242884e+02, 7.171137e+02, 1.258462e+04, }; static float solarDataset480[] = { -2.547404e+13, 3.635631e+08, 1.293910e+04, 3.796038e+01, 1.491564e+11, -3.082064e+07, 2.764923e+03, 3.816097e+01, -4.508309e+10, 2.784696e+07, 1.842137e+03, 3.830790e+01, 1.877320e+09, -2.075191e+06, 5.574952e+03, 4.031446e+01, 1.363759e+08, 1.060735e+05, 5.218855e+03, 4.351307e+01, -4.042173e+07, 4.168932e+05, 5.894289e+03, 4.927657e+01, -1.979427e+07, 3.130223e+05, 6.903811e+03, 5.939239e+01, 6.227794e+07, 3.355382e+04, 7.989751e+03, 7.579875e+01, -2.611063e+07, 5.428849e+05, 9.770848e+03, 1.008989e+02, 6.751575e+06, 3.486580e+05, 1.273626e+04, 1.436773e+02, -7.094370e+06, 5.158292e+05, 1.643574e+04, 2.114709e+02, -9.375221e+06, 5.686982e+05, 2.162922e+04, 3.207238e+02, -9.044998e+06, 5.787047e+05, 2.809570e+04, 4.923702e+02, -1.059918e+07, 5.884594e+05, 3.567928e+04, 7.525556e+02, -1.032559e+07, 5.383256e+05, 4.394951e+04, 1.132412e+03, -9.508141e+06, 4.496710e+05, 5.199543e+04, 1.660855e+03, -6.314974e+06, 3.051184e+05, 5.876680e+04, 2.358284e+03, -6.086400e+06, 2.212357e+05, 6.360343e+04, 3.228792e+03, -3.788528e+06, 9.381155e+04, 6.603062e+04, 4.267693e+03, -2.077730e+06, 4.085149e+03, 6.579013e+04, 5.445031e+03, -1.998244e+06, -2.581562e+04, 6.353956e+04, 6.724786e+03, -5.455764e+05, -8.455452e+04, 5.958479e+04, 8.073218e+03, -5.401502e+05, -8.066396e+04, 5.460598e+04, 9.442031e+03, -4.626920e+05, -7.878633e+04, 4.927072e+04, 1.080685e+04, 4.307696e+04, -8.866941e+04, 4.363750e+04, 1.213911e+04, -9.896498e+04, -6.809587e+04, 3.825652e+04, 1.340968e+04, -4.046726e+04, -6.013412e+04, 3.334045e+04, 1.461550e+04, 2.465424e+04, -5.267288e+04, 2.881215e+04, 1.574516e+04, -6.606890e+04, -3.886479e+04, 2.480495e+04, 1.679298e+04, 8.625368e+04, -3.988716e+04, 2.118987e+04, 1.776151e+04, -5.094497e+04, -2.400663e+04, 1.812357e+04, 1.864229e+04, 3.521782e+04, -2.523723e+04, 1.545985e+04, 1.945299e+04, -2.910575e+04, -1.612809e+04, 1.314789e+04, 2.018464e+04, 2.987436e+04, -1.729633e+04, 1.112528e+04, 2.084999e+04, -2.392041e+04, -9.871844e+03, 9.419435e+03, 2.144328e+04, 1.318656e+04, -1.113363e+04, 7.932171e+03, 2.198012e+04, -8.189886e+03, -7.083342e+03, 6.648923e+03, 2.245346e+04, 8.760018e+02, -6.634529e+03, 5.556208e+03, 2.287527e+04, -7.219063e+03, -4.650361e+03, 4.605098e+03, 2.324459e+04, -7.443951e+03, -3.898973e+03, 3.764874e+03, 2.356703e+04, -5.229746e+03, -3.417661e+03, 2.990255e+03, 2.384152e+04, -9.160621e+03, -2.339852e+03, 2.297538e+03, 2.406739e+04, -1.337575e+04, -1.443204e+03, 1.662712e+03, 2.424699e+04, -1.609842e+04, -6.573803e+02, 1.042947e+03, 2.437881e+04, -1.154888e+04, -2.049765e+02, 4.517902e+02, 2.445949e+04, 4.227183e+11, 1.389648e+06, 1.036346e+03, 1.739462e+01, -4.523986e+10, 1.309428e+07, 1.461077e+03, 1.741507e+01, -1.974469e+09, 2.075506e+06, 2.645040e+03, 1.770254e+01, -1.554063e+09, 1.591460e+06, 3.369179e+03, 1.872211e+01, 5.672809e+08, -8.382778e+05, 3.502720e+03, 2.111515e+01, -1.132935e+08, 5.257210e+05, 3.621481e+03, 2.453096e+01, 5.367205e+07, 3.863978e+04, 4.434495e+03, 3.106808e+01, -7.651470e+05, 2.973158e+05, 5.375363e+03, 4.152440e+01, -5.641271e+06, 3.520079e+05, 7.088158e+03, 5.968817e+01, -3.575740e+05, 3.595429e+05, 9.484804e+03, 9.083227e+01, -5.432283e+06, 4.570748e+05, 1.282057e+04, 1.429497e+02, -8.493195e+06, 5.345880e+05, 1.750590e+04, 2.299714e+02, -9.361727e+06, 5.742448e+05, 2.362945e+04, 3.720855e+02, -1.230376e+07, 6.089220e+05, 3.107881e+04, 5.957043e+02, -8.209413e+06, 5.098829e+05, 3.928027e+04, 9.325726e+02, -9.315159e+06, 4.745999e+05, 4.745855e+04, 1.409587e+03, -8.627264e+06, 3.733993e+05, 5.493900e+04, 2.054851e+03, -4.714765e+06, 2.032292e+05, 6.032301e+04, 2.878534e+03, -3.679437e+06, 1.165562e+05, 6.321237e+04, 3.866403e+03, -2.929350e+06, 4.492419e+04, 6.387975e+04, 5.001581e+03, -1.392612e+06, -3.265661e+04, 6.224732e+04, 6.253081e+03, -1.117804e+06, -5.501965e+04, 5.885362e+04, 7.576411e+03, -4.075604e+05, -8.239287e+04, 5.430578e+04, 8.936806e+03, -2.459750e+05, -8.099482e+04, 4.915270e+04, 1.029496e+04, -3.665911e+05, -6.851276e+04, 4.392374e+04, 1.162710e+04, 2.205685e+05, -8.274490e+04, 3.860977e+04, 1.291372e+04, -3.040342e+05, -4.570146e+04, 3.379260e+04, 1.412701e+04, 1.469667e+05, -6.087770e+04, 2.926964e+04, 1.527950e+04, -6.797871e+04, -3.790137e+04, 2.518196e+04, 1.633998e+04, 3.949307e+04, -3.733814e+04, 2.163770e+04, 1.732591e+04, -7.975621e+03, -2.732830e+04, 1.851668e+04, 1.822774e+04, -4.377782e+03, -2.272640e+04, 1.583173e+04, 1.905445e+04, 1.693589e+04, -1.978767e+04, 1.346464e+04, 1.980645e+04, -1.488896e+04, -1.382418e+04, 1.145439e+04, 2.048569e+04, -5.303294e+03, -1.226164e+04, 9.699219e+03, 2.110102e+04, 2.706972e+04, -1.214607e+04, 8.129372e+03, 2.165037e+04, -3.562524e+04, -4.676288e+03, 6.891074e+03, 2.213611e+04, 2.093737e+04, -9.026232e+03, 5.739331e+03, 2.257705e+04, -2.006414e+04, -3.337389e+03, 4.758662e+03, 2.295476e+04, -1.964465e+03, -4.781112e+03, 3.893292e+03, 2.329090e+04, -7.979526e+03, -3.208613e+03, 3.083342e+03, 2.357289e+04, -3.882281e+03, -2.975486e+03, 2.366732e+03, 2.380648e+04, -1.970221e+04, -7.385175e+02, 1.744297e+03, 2.399093e+04, -2.049545e+04, -4.245408e+02, 1.090574e+03, 2.413137e+04, -1.271643e+04, -9.063678e+01, 4.186658e+02, 2.421482e+04, -3.562425e+12, 4.547613e+07, 3.869422e+03, 4.918330e+00, 4.689183e+10, -1.281786e+07, 2.261597e+03, 4.980296e+00, 2.022864e+09, -1.220456e+06, 1.216501e+03, 5.148946e+00, 2.776720e+08, -1.053418e+05, 1.068025e+03, 5.487525e+00, -1.590271e+08, 4.112991e+05, 1.272512e+03, 6.197900e+00, 6.495931e+07, -3.603970e+04, 1.609987e+03, 7.805828e+00, -2.064038e+07, 2.320516e+05, 1.976444e+03, 1.049337e+01, 1.765744e+07, 1.028749e+05, 2.695696e+03, 1.571579e+01, -1.181768e+07, 3.056096e+05, 3.744644e+03, 2.487848e+01, 3.197837e+06, 2.544026e+05, 5.534911e+03, 4.254333e+01, -9.201137e+06, 4.284098e+05, 8.121123e+03, 7.427706e+01, -8.890947e+06, 4.785445e+05, 1.211126e+04, 1.328518e+02, -7.071586e+06, 5.059339e+05, 1.741186e+04, 2.352960e+02, -1.166674e+07, 5.930738e+05, 2.420576e+04, 4.053939e+02, -1.014664e+07, 5.469944e+05, 3.227826e+04, 6.765805e+02, -8.709155e+06, 4.717684e+05, 4.057628e+04, 1.079331e+03, -6.589641e+06, 3.640900e+05, 4.826717e+04, 1.639785e+03, -5.956205e+06, 2.764700e+05, 5.460139e+04, 2.373352e+03, -4.410054e+06, 1.636818e+05, 5.887661e+04, 3.284026e+03, -2.573675e+06, 5.767791e+04, 6.052561e+04, 4.353163e+03, -1.725557e+06, -2.089540e+03, 5.980763e+04, 5.546333e+03, -7.726710e+05, -4.982537e+04, 5.727085e+04, 6.827655e+03, -9.367723e+05, -5.118449e+04, 5.356326e+04, 8.157893e+03, -2.139498e+05, -7.920098e+04, 4.895601e+04, 9.508497e+03, -1.552485e+05, -7.235301e+04, 4.390792e+04, 1.083723e+04, -1.628579e+04, -6.809604e+04, 3.896658e+04, 1.212598e+04, -1.983318e+05, -5.059195e+04, 3.433105e+04, 1.335883e+04, 8.171771e+04, -5.652750e+04, 2.987115e+04, 1.452950e+04, -1.382147e+04, -4.085430e+04, 2.582431e+04, 1.561625e+04, -1.903892e+04, -3.373542e+04, 2.231868e+04, 1.662797e+04, 1.630797e+04, -2.980642e+04, 1.916625e+04, 1.756241e+04, -1.470429e+04, -2.241600e+04, 1.641147e+04, 1.841734e+04, 1.183830e+04, -2.013913e+04, 1.399466e+04, 1.919851e+04, -7.425767e+03, -1.497561e+04, 1.190037e+04, 1.990483e+04, 2.348122e+04, -1.430663e+04, 1.008697e+04, 2.054362e+04, -3.407580e+04, -7.210622e+03, 8.592568e+03, 2.111580e+04, 8.410728e+03, -9.841158e+03, 7.218391e+03, 2.163577e+04, 5.333101e+03, -7.356348e+03, 5.982069e+03, 2.208915e+04, -1.934314e+04, -3.841909e+03, 4.996690e+03, 2.248734e+04, 3.189408e+03, -5.483261e+03, 4.066681e+03, 2.283908e+04, -1.021377e+04, -2.980445e+03, 3.244087e+03, 2.313320e+04, -9.790041e+03, -2.583961e+03, 2.517956e+03, 2.338071e+04, -1.444370e+04, -1.591158e+03, 1.824665e+03, 2.357756e+04, -2.379887e+04, -1.133726e+02, 1.149303e+03, 2.372235e+04, -1.332327e+04, -1.181356e+02, 4.433913e+02, 2.381143e+04, -4.062495e+12, 5.889514e+07, 1.822539e+03, 5.934704e-01, 1.116655e+10, -2.476749e+06, 2.315678e+02, 6.215788e-01, -2.883849e+08, 3.186874e+05, 1.216092e+02, 6.330776e-01, -3.334973e+08, 3.506258e+05, 2.375575e+02, 6.969603e-01, 9.502123e+07, -1.388013e+05, 2.778272e+02, 9.045791e-01, -3.169474e+07, 1.355526e+05, 3.011117e+02, 1.153722e+00, 1.354177e+07, 8.549983e+03, 4.924110e+02, 1.837267e+00, -9.788296e+06, 1.268912e+05, 7.245476e+02, 3.098311e+00, 8.321999e+06, 5.975755e+04, 1.214653e+03, 6.043943e+00, -9.981085e+06, 2.455768e+05, 2.011040e+03, 1.185919e+01, -2.885803e+06, 2.397529e+05, 3.652004e+03, 2.559525e+01, -6.329634e+06, 3.478969e+05, 6.106085e+03, 5.370172e+01, -7.960277e+06, 4.345711e+05, 9.978396e+03, 1.097524e+02, -7.895936e+06, 4.855802e+05, 1.544416e+04, 2.146203e+02, -1.056970e+07, 5.455151e+05, 2.249529e+04, 3.967972e+02, -8.772676e+06, 4.836844e+05, 3.061098e+04, 6.924183e+02, -6.125317e+06, 3.824122e+05, 3.856863e+04, 1.130737e+03, -6.234374e+06, 3.223025e+05, 4.569520e+04, 1.732649e+03, -4.135207e+06, 1.989626e+05, 5.121311e+04, 2.512630e+03, -2.831010e+06, 1.064359e+05, 5.436969e+04, 3.458681e+03, -1.771421e+06, 3.391272e+04, 5.527105e+04, 4.547677e+03, -1.352058e+06, -6.747689e+03, 5.423442e+04, 5.746928e+03, -4.737948e+05, -5.056302e+04, 5.159311e+04, 7.021275e+03, -5.178401e+05, -5.085618e+04, 4.797068e+04, 8.329029e+03, -3.165613e+05, -5.894560e+04, 4.379803e+04, 9.645661e+03, -3.525713e+04, -6.498724e+04, 3.922274e+04, 1.093910e+04, -1.698033e+03, -5.646027e+04, 3.473194e+04, 1.218335e+04, -8.252137e+04, -4.418587e+04, 3.062394e+04, 1.337026e+04, -4.452976e+04, -4.012949e+04, 2.678876e+04, 1.449551e+04, 1.756583e+04, -3.688401e+04, 2.318145e+04, 1.554675e+04, 2.497374e+04, -3.028839e+04, 1.996805e+04, 1.651698e+04, -4.542787e+04, -2.074654e+04, 1.722708e+04, 1.741034e+04, 4.577114e+04, -2.317554e+04, 1.473888e+04, 1.823360e+04, -2.941513e+04, -1.335336e+04, 1.261663e+04, 1.897704e+04, 9.540414e+03, -1.422160e+04, 1.076932e+04, 1.965858e+04, -1.333019e+04, -9.795617e+03, 9.126910e+03, 2.026983e+04, 6.872783e+03, -9.753800e+03, 7.680151e+03, 2.081939e+04, -6.794840e+03, -6.642494e+03, 6.433964e+03, 2.130449e+04, -6.512347e+03, -5.595285e+03, 5.359979e+03, 2.173466e+04, -7.453009e+03, -4.569078e+03, 4.387344e+03, 2.210973e+04, -8.453112e+03, -3.685525e+03, 3.504406e+03, 2.243008e+04, -1.058157e+04, -2.798516e+03, 2.696662e+03, 2.269567e+04, -1.175275e+04, -2.070349e+03, 1.946314e+03, 2.290618e+04, -2.725053e+04, 1.473825e+02, 1.251869e+03, 2.306034e+04, -1.529872e+04, -8.045642e+01, 4.978280e+02, 2.315872e+04, 0, 0, 0, 3.002487e-02, -1.090846e+10, 1.974400e+06, 0, 3.002487e-02, 3.636683e+07, -1.786622e+04, 0, 3.960728e-02, -7.026847e+07, 9.507055e+04, 0, 3.896845e-02, 1.333478e+06, 3.529875e+03, 3.551876e+01, 5.941092e-02, 2.003892e+06, 3.786981e+03, 4.736528e+01, 1.022123e-01, -1.002646e+05, 1.491867e+04, 7.403866e+01, 1.935646e-01, 8.840045e+05, 2.053897e+04, 1.379171e+02, 4.260977e-01, -1.799941e+06, 5.585624e+04, 2.800918e+02, 1.024040e+00, -1.272606e+06, 8.353843e+04, 6.224092e+02, 2.759094e+00, -3.142945e+06, 1.498386e+05, 1.319586e+03, 7.359927e+00, -5.325514e+06, 2.353986e+05, 2.722502e+03, 1.918334e+01, -4.367873e+06, 2.950794e+05, 5.196144e+03, 4.713202e+01, -8.293792e+06, 4.208244e+05, 9.110856e+03, 1.061188e+02, -8.395418e+06, 4.579295e+05, 1.483469e+04, 2.224875e+02, -6.520037e+06, 4.312038e+05, 2.181675e+04, 4.272194e+02, -7.601962e+06, 4.292473e+05, 2.951377e+04, 7.524578e+02, -5.359980e+06, 3.235804e+05, 3.708090e+04, 1.232011e+03, -4.257096e+06, 2.366275e+05, 4.329759e+04, 1.879326e+03, -2.362298e+06, 1.320983e+05, 4.767316e+04, 2.696374e+03, -2.586387e+06, 9.404854e+04, 5.012795e+04, 3.667154e+03, -1.346937e+06, 1.521702e+04, 5.055045e+04, 4.774654e+03, -6.311932e+05, -2.761653e+04, 4.896823e+04, 5.973547e+03, -2.859925e+05, -4.535140e+04, 4.622372e+04, 7.225477e+03, -5.833449e+05, -3.576030e+04, 4.293299e+04, 8.502104e+03, 5.723729e+03, -6.133686e+04, 3.902591e+04, 9.783052e+03, -8.123325e+04, -4.879934e+04, 3.491969e+04, 1.102637e+04, -5.068165e+04, -4.411026e+04, 3.105343e+04, 1.222640e+04, -3.207428e+04, -3.889547e+04, 2.737029e+04, 1.337046e+04, -1.066219e+04, -3.412928e+04, 2.393260e+04, 1.444923e+04, -1.141680e+04, -2.854544e+04, 2.079563e+04, 1.545628e+04, -4.908479e+03, -2.421760e+04, 1.796966e+04, 1.638943e+04, 2.053346e+04, -2.145813e+04, 1.544534e+04, 1.724714e+04, -3.179755e+04, -1.406796e+04, 1.328479e+04, 1.803018e+04, 3.081852e+04, -1.632250e+04, 1.133044e+04, 1.874762e+04, -2.520860e+04, -8.744463e+03, 9.671271e+03, 1.939042e+04, -5.258707e+02, -9.682975e+03, 8.210156e+03, 1.997663e+04, -3.603629e+03, -7.596047e+03, 6.868361e+03, 2.049617e+04, -1.284514e+04, -5.501197e+03, 5.706315e+03, 2.095412e+04, 5.408753e+03, -6.215871e+03, 4.636466e+03, 2.135343e+04, -1.729670e+04, -2.725560e+03, 3.738994e+03, 2.168992e+04, -8.133455e+03, -3.384342e+03, 2.903206e+03, 2.197692e+04, -1.400569e+04, -2.007834e+03, 2.106764e+03, 2.220291e+04, -3.787921e+04, 9.695897e+02, 1.365023e+03, 2.237077e+04, -1.169926e+04, -4.806728e+02, 4.665493e+02, 2.247814e+04, 6.525532e+11, -9.597776e+06, -2.508142e+02, 5.110617e-03, -7.272307e+08, 1.316266e+05, 0, 1.277654e-03, 7.273367e+07, -3.573244e+04, 0, 1.916481e-03, -9.307074e+05, 2.164022e+03, 0, 6.388271e-04, -3.846153e+06, 8.276968e+03, 1.624622e+00, 1.277654e-03, 7.045428e+05, -9.506031e+02, 6.273509e+00, 7.665925e-03, 5.471221e+05, 7.881141e+02, 8.492069e+00, 1.788716e-02, -1.157790e+06, 1.343443e+04, 1.980918e+01, 4.599555e-02, 5.648178e+05, 1.177962e+04, 6.860591e+01, 1.890928e-01, -2.168944e+06, 5.449721e+04, 1.804408e+02, 6.401047e-01, -1.936415e+06, 8.671467e+04, 5.476078e+02, 2.451180e+00, -2.778014e+06, 1.502939e+05, 1.348026e+03, 8.039000e+00, -5.988957e+06, 2.595586e+05, 3.014769e+03, 2.341237e+01, -4.953844e+06, 3.123771e+05, 6.037281e+03, 6.158549e+01, -8.072078e+06, 4.188727e+05, 1.060684e+04, 1.421314e+02, -6.102258e+06, 4.036899e+05, 1.685401e+04, 2.966719e+02, -7.081157e+06, 4.155400e+05, 2.406072e+04, 5.567832e+02, -5.275326e+06, 3.322858e+05, 3.155165e+04, 9.582758e+02, -3.846919e+06, 2.463955e+05, 3.810789e+04, 1.520520e+03, -3.514763e+06, 1.822427e+05, 4.321496e+04, 2.251031e+03, -1.456565e+06, 7.443224e+04, 4.630479e+04, 3.144755e+03, -1.859068e+06, 5.498326e+04, 4.747600e+04, 4.171486e+03, -4.928980e+05, -1.792985e+04, 4.691705e+04, 5.312605e+03, -8.773971e+05, -1.418775e+04, 4.496428e+04, 6.519951e+03, -2.751454e+04, -5.502387e+04, 4.200632e+04, 7.772248e+03, -1.594475e+05, -4.385961e+04, 3.851029e+04, 9.022491e+03, -2.928118e+05, -3.624179e+04, 3.501918e+04, 1.026196e+04, 9.244874e+04, -5.182584e+04, 3.122779e+04, 1.147202e+04, -7.298447e+04, -3.463156e+04, 2.759798e+04, 1.261967e+04, -2.297138e+04, -3.303978e+04, 2.430195e+04, 1.371250e+04, -7.257520e+03, -2.883089e+04, 2.118824e+04, 1.473725e+04, 1.617806e+04, -2.529034e+04, 1.836369e+04, 1.568909e+04, -1.048687e+04, -1.906491e+04, 1.589586e+04, 1.656705e+04, -2.280875e+03, -1.656326e+04, 1.371907e+04, 1.737679e+04, -1.173034e+04, -1.313659e+04, 1.177337e+04, 1.811680e+04, 1.764221e+03, -1.200134e+04, 1.002274e+04, 1.878901e+04, -5.443919e+03, -9.216609e+03, 8.480824e+03, 1.939176e+04, -2.042247e+03, -7.901444e+03, 7.133254e+03, 1.993055e+04, -8.037811e+03, -5.968600e+03, 5.951562e+03, 2.040675e+04, -1.379071e+04, -4.556409e+03, 4.894801e+03, 2.082428e+04, -5.451456e+02, -5.063627e+03, 3.890115e+03, 2.118233e+04, -2.023326e+04, -2.060668e+03, 3.019280e+03, 2.147555e+04, -2.864907e+03, -3.469182e+03, 2.170665e+03, 2.171383e+04, -4.564474e+04, 1.914149e+03, 1.447545e+03, 2.188399e+04, -1.285998e+04, -5.186207e+02, 5.108418e+02, 2.200120e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -7.075985e+04, 4.214961e+02, 0, 0, 5.562181e+04, 8.061994e+01, 8.281078e-01, 1.277654e-03, -3.121437e+05, 4.825055e+03, 2.713965e+00, 5.749444e-03, -1.563799e+05, 9.395735e+03, 2.570856e+01, 6.707684e-02, -7.453272e+05, 3.122976e+04, 1.032542e+02, 3.762692e-01, -1.989081e+06, 7.880134e+04, 3.868377e+02, 1.843655e+00, -3.098191e+06, 1.440545e+05, 1.185918e+03, 7.543909e+00, -4.215556e+06, 2.225784e+05, 2.907656e+03, 2.490978e+01, -4.786020e+06, 2.938944e+05, 5.980692e+03, 6.858128e+01, -6.298563e+06, 3.655079e+05, 1.067540e+04, 1.622455e+02, -5.412413e+06, 3.568233e+05, 1.684205e+04, 3.392913e+02, -4.918343e+06, 3.291889e+05, 2.367207e+04, 6.321366e+02, -3.916896e+06, 2.666399e+05, 3.039895e+04, 1.070198e+03, -3.234356e+06, 2.003322e+05, 3.615701e+04, 1.670192e+03, -2.040334e+06, 1.180905e+05, 4.028384e+04, 2.434229e+03, -1.401604e+06, 6.196017e+04, 4.252555e+04, 3.344716e+03, -8.510153e+05, 1.754662e+04, 4.308474e+04, 4.377716e+03, -5.868429e+05, -7.897552e+03, 4.225322e+04, 5.502610e+03, -4.777308e+05, -2.215277e+04, 4.036574e+04, 6.689373e+03, -2.027395e+05, -3.838610e+04, 3.760893e+04, 7.906894e+03, 4.688571e+04, -4.650040e+04, 3.433909e+04, 9.120592e+03, -1.731682e+05, -3.045624e+04, 3.114684e+04, 1.030870e+04, -9.393385e+04, -3.336297e+04, 2.796966e+04, 1.146998e+04, 5.520659e+04, -3.698224e+04, 2.466929e+04, 1.257910e+04, -3.127735e+04, -2.548739e+04, 2.167580e+04, 1.361953e+04, -2.886510e+04, -2.234154e+04, 1.900618e+04, 1.459990e+04, 4.803892e+04, -2.356220e+04, 1.648513e+04, 1.551250e+04, -6.916297e+04, -1.140155e+04, 1.434094e+04, 1.635055e+04, 2.995112e+04, -1.761090e+04, 1.231851e+04, 1.713096e+04, -1.131187e+04, -1.076782e+04, 1.049085e+04, 1.782950e+04, -5.672132e+03, -9.605872e+03, 8.943086e+03, 1.846438e+04, -2.342928e+02, -8.391650e+03, 7.538626e+03, 1.903310e+04, -1.356312e+04, -5.763390e+03, 6.314320e+03, 1.953688e+04, -1.029218e+04, -5.313462e+03, 5.191616e+03, 1.998094e+04, -4.820491e+03, -4.883491e+03, 4.133093e+03, 2.035985e+04, -1.332017e+04, -3.043612e+03, 3.200526e+03, 2.067237e+04, -1.507804e+04, -2.298738e+03, 2.341341e+03, 2.092387e+04, -3.372668e+04, 2.668844e+02, 1.517180e+03, 2.111023e+04, -1.829462e+04, -1.213923e+02, 6.004736e+02, 2.122965e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.017242e+04, 1.750194e+02, 0, 0, -1.457144e+04, 7.281291e+02, 8.823561e-01, 1.916481e-03, -8.138557e+04, 3.915626e+03, 6.731239e+00, 2.044247e-02, -3.416115e+05, 1.616098e+04, 4.346558e+01, 1.712057e-01, -1.112109e+06, 4.948532e+04, 2.166628e+02, 1.116031e+00, -1.851122e+06, 9.973810e+04, 7.987332e+02, 5.514355e+00, -2.976474e+06, 1.703720e+05, 2.185875e+03, 2.036134e+01, -3.752852e+06, 2.346189e+05, 4.835726e+03, 6.046371e+01, -3.916406e+06, 2.725329e+05, 8.928559e+03, 1.496005e+02, -4.124056e+06, 2.880126e+05, 1.427455e+04, 3.184585e+02, -3.454381e+06, 2.560391e+05, 2.029483e+04, 6.004725e+02, -2.730599e+06, 2.065880e+05, 2.611242e+04, 1.020835e+03, -2.156132e+06, 1.532252e+05, 3.106996e+04, 1.593564e+03, -1.423653e+06, 9.444510e+04, 3.467497e+04, 2.319182e+03, -1.066952e+06, 5.365130e+04, 3.674970e+04, 3.182752e+03, -5.913676e+05, 1.479975e+04, 3.736478e+04, 4.162645e+03, -4.507312e+05, -3.442068e+03, 3.676283e+04, 5.228191e+03, -3.349898e+05, -1.694648e+04, 3.524585e+04, 6.352700e+03, -5.373997e+04, -3.272371e+04, 3.296933e+04, 7.506143e+03, -1.042929e+05, -2.794349e+04, 3.037961e+04, 8.657850e+03, -1.338463e+05, -2.558203e+04, 2.771508e+04, 9.797088e+03, 4.568200e+04, -3.329463e+04, 2.485715e+04, 1.090629e+04, -6.786858e+04, -2.165789e+04, 2.213772e+04, 1.196178e+04, 1.306047e+04, -2.435543e+04, 1.958249e+04, 1.296915e+04, -3.322576e+04, -1.756840e+04, 1.718597e+04, 1.391169e+04, 2.749390e+04, -1.920271e+04, 1.496912e+04, 1.479267e+04, -3.110219e+04, -1.154084e+04, 1.301793e+04, 1.560216e+04, -6.075291e+03, -1.225057e+04, 1.124355e+04, 1.635251e+04, 6.180475e+02, -1.069972e+04, 9.569241e+03, 1.703160e+04, -6.748771e+03, -8.170462e+03, 8.103632e+03, 1.764032e+04, -1.585713e+04, -6.165047e+03, 6.808130e+03, 1.818386e+04, -6.803412e+01, -6.704295e+03, 5.583407e+03, 1.866238e+04, -1.271216e+04, -4.147672e+03, 4.500136e+03, 1.906922e+04, -1.789297e+04, -3.078470e+03, 3.522047e+03, 1.941335e+04, -1.300839e+04, -2.995513e+03, 2.547822e+03, 1.968999e+04, -3.739496e+04, 4.124892e+02, 1.647666e+03, 1.989124e+04, -1.991360e+04, -1.343689e+02, 6.540701e+02, 2.002139e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.836497e+03, 1.200044e+02, 0, 0, -6.317725e+03, 7.299639e+02, 9.947280e-01, 3.194135e-03, -1.879736e+05, 7.112439e+03, 1.009800e+01, 4.216259e-02, -2.264187e+05, 1.783873e+04, 8.824183e+01, 4.893415e-01, -1.027429e+06, 5.516548e+04, 3.642565e+02, 2.717570e+00, -1.310055e+06, 9.297558e+04, 1.199666e+03, 1.188410e+01, -2.088964e+06, 1.472067e+05, 2.903674e+03, 3.864073e+01, -2.404946e+06, 1.832584e+05, 5.807015e+03, 1.028959e+02, -2.419199e+06, 1.963782e+05, 9.802613e+03, 2.313167e+02, -2.144173e+06, 1.846474e+05, 1.448111e+04, 4.529782e+02, -1.755673e+06, 1.566924e+05, 1.925615e+04, 7.929135e+02, -1.556385e+06, 1.260006e+05, 2.357954e+04, 1.267487e+03, -9.670740e+05, 7.884178e+04, 2.693555e+04, 1.882001e+03, -5.837683e+05, 4.472897e+04, 2.907526e+04, 2.623982e+03, -5.604275e+05, 2.840427e+04, 3.020165e+04, 3.477349e+03, -3.582842e+05, 6.067834e+03, 3.034485e+04, 4.425576e+03, -2.245319e+05, -8.290479e+03, 2.953728e+04, 5.439338e+03, -1.015845e+05, -1.802273e+04, 2.804648e+04, 6.490440e+03, -4.708202e+04, -2.097995e+04, 2.617044e+04, 7.553762e+03, -9.140648e+04, -1.778019e+04, 2.415851e+04, 8.612631e+03, -3.474920e+04, -2.078888e+04, 2.200252e+04, 9.655604e+03, 2.006550e+04, -2.169175e+04, 1.976088e+04, 1.066217e+04, -7.457237e+04, -1.281394e+04, 1.769310e+04, 1.162183e+04, 1.660390e+04, -1.849862e+04, 1.562554e+04, 1.253795e+04, -1.242914e+03, -1.387174e+04, 1.364603e+04, 1.338579e+04, -2.136653e+04, -1.038594e+04, 1.192412e+04, 1.417293e+04, 8.461670e+02, -1.092230e+04, 1.029799e+04, 1.490007e+04, -1.726136e+04, -7.648424e+03, 8.804960e+03, 1.555802e+04, -5.951019e+03, -7.711382e+03, 7.418584e+03, 1.615128e+04, -1.124333e+04, -5.937896e+03, 6.131419e+03, 1.667197e+04, -7.000456e+03, -5.382316e+03, 4.953545e+03, 1.712215e+04, -1.739957e+04, -3.384351e+03, 3.889292e+03, 1.749934e+04, -2.766408e+04, -1.885413e+03, 2.872322e+03, 1.780661e+04, -2.473009e+04, -1.511121e+03, 1.795912e+03, 1.803592e+04, -1.893613e+04, -4.433274e+02, 7.896820e+02, 1.817402e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.795339e+03, 1.024806e+02, 0, 0, -2.505222e+04, 1.240280e+03, 1.304988e+00, 5.749444e-03, -4.666245e+04, 4.461716e+03, 1.801239e+01, 1.073229e-01, -2.724635e+05, 1.761495e+04, 9.851115e+01, 7.710643e-01, -4.861356e+05, 3.717743e+04, 4.101052e+02, 4.193261e+00, -6.383714e+05, 6.152061e+04, 1.168007e+03, 1.598473e+01, -1.205391e+06, 9.889684e+04, 2.636565e+03, 4.738883e+01, -1.147720e+06, 1.106241e+05, 5.004828e+03, 1.183715e+02, -1.133494e+06, 1.155726e+05, 8.024451e+03, 2.508700e+02, -1.063750e+06, 1.090501e+05, 1.144213e+04, 4.682622e+02, -7.206625e+05, 8.651512e+04, 1.483243e+04, 7.896286e+02, -8.230661e+05, 7.733914e+04, 1.788080e+04, 1.224383e+03, -3.893929e+05, 4.348949e+04, 2.028440e+04, 1.779031e+03, -4.194027e+05, 3.349138e+04, 2.185878e+04, 2.439030e+03, -1.895883e+05, 1.198418e+04, 2.268839e+04, 3.196090e+03, -2.138071e+05, 6.670906e+03, 2.280864e+04, 4.026859e+03, -6.125361e+04, -6.683706e+03, 2.234923e+04, 4.916377e+03, -1.266566e+05, -5.092214e+03, 2.146339e+04, 5.838900e+03, -3.668092e+04, -1.292182e+04, 2.023530e+04, 6.783060e+03, -4.502149e+04, -1.220835e+04, 1.873724e+04, 7.722602e+03, -6.724879e+03, -1.428205e+04, 1.712856e+04, 8.645906e+03, -3.147242e+04, -1.120290e+04, 1.550800e+04, 9.537867e+03, 4.822493e+03, -1.299009e+04, 1.388952e+04, 1.039406e+04, -3.661611e+04, -8.222351e+03, 1.234509e+04, 1.120095e+04, 7.706524e+02, -1.086522e+04, 1.080666e+04, 1.196049e+04, -1.428372e+04, -7.903936e+03, 9.320418e+03, 1.265373e+04, -1.558705e+04, -6.942237e+03, 7.944124e+03, 1.328427e+04, 3.569541e+03, -7.689284e+03, 6.605008e+03, 1.384543e+04, -2.207606e+04, -3.799092e+03, 5.433831e+03, 1.433020e+04, -2.173362e+04, -3.685308e+03, 4.312741e+03, 1.475032e+04, -1.842206e+04, -3.390404e+03, 3.139013e+03, 1.508986e+04, -4.332377e+04, 1.904433e+02, 2.023367e+03, 1.533848e+04, -2.551285e+04, -6.475346e+01, 8.159825e+02, 1.549771e+04, }; static float solarDataset520[] = { 3.441260e+12, 4.257012e+05, 9.159649e+03, 2.155997e+02, -3.813319e+11, 9.728458e+07, 1.224196e+04, 2.157753e+02, -8.993466e+09, 5.812620e+06, 1.906304e+04, 2.179990e+02, 2.219112e+09, -1.465148e+06, 1.997638e+04, 2.245501e+02, -4.029785e+08, 1.497071e+06, 2.081556e+04, 2.372707e+02, 7.073014e+07, 4.201511e+05, 2.262724e+04, 2.603452e+02, 1.148052e+08, 3.113398e+05, 2.446750e+04, 2.971461e+02, -6.975728e+07, 9.816228e+05, 2.748132e+04, 3.534071e+02, 4.543997e+07, 3.776559e+05, 3.142461e+04, 4.400715e+02, -1.929005e+07, 8.214878e+05, 3.615734e+04, 5.652811e+02, -6.188209e+06, 6.920153e+05, 4.256955e+04, 7.501487e+02, -2.183429e+07, 7.943841e+05, 4.986206e+04, 1.014418e+03, -1.140788e+07, 5.966216e+05, 5.766701e+04, 1.385850e+03, -1.246868e+07, 5.332061e+05, 6.507698e+04, 1.885028e+03, -1.535117e+07, 4.615705e+05, 7.180659e+04, 2.535598e+03, -6.922309e+06, 2.072982e+05, 7.639904e+04, 3.351496e+03, -7.654747e+06, 1.405907e+05, 7.834404e+04, 4.319751e+03, -3.608348e+06, -1.032324e+04, 7.774929e+04, 5.429596e+03, -3.310273e+06, -5.122568e+04, 7.470562e+04, 6.644330e+03, -1.803698e+06, -1.089710e+05, 6.977953e+04, 7.932441e+03, -4.481058e+05, -1.414144e+05, 6.339972e+04, 9.249011e+03, -8.474652e+05, -1.138910e+05, 5.661672e+04, 1.055570e+04, 9.091255e+04, -1.286682e+05, 4.971740e+04, 1.183266e+04, -3.296997e+05, -9.203473e+04, 4.316623e+04, 1.304789e+04, 6.138098e+04, -9.130578e+04, 3.710169e+04, 1.419808e+04, 8.019984e+04, -7.334147e+04, 3.160993e+04, 1.526375e+04, -1.056039e+05, -5.125085e+04, 2.694897e+04, 1.624692e+04, 3.523169e+04, -4.850597e+04, 2.280818e+04, 1.715304e+04, 6.870219e+04, -3.957775e+04, 1.917548e+04, 1.797303e+04, -1.326338e+04, -2.682913e+04, 1.621399e+04, 1.871381e+04, 1.157345e+03, -2.265762e+04, 1.371834e+04, 1.938801e+04, 1.114799e+04, -1.872180e+04, 1.154622e+04, 1.999570e+04, 4.035315e+02, -1.421776e+04, 9.712803e+03, 2.054042e+04, -8.685193e+01, -1.141822e+04, 8.163078e+03, 2.102864e+04, 2.765763e+03, -9.358492e+03, 6.836780e+03, 2.146394e+04, 9.596016e+02, -7.320212e+03, 5.716072e+03, 2.184997e+04, -3.591287e+03, -5.538701e+03, 4.774094e+03, 2.219169e+04, 4.877164e+02, -4.837933e+03, 3.959721e+03, 2.249316e+04, -3.944127e+03, -3.487922e+03, 3.263769e+03, 2.275573e+04, -8.194186e+03, -2.533610e+03, 2.659495e+03, 2.298365e+04, 1.810861e+03, -3.022148e+03, 2.090564e+03, 2.317744e+04, -8.870991e+03, -1.251568e+03, 1.616934e+03, 2.333414e+04, -1.072378e+04, -9.168446e+02, 1.182863e+03, 2.346196e+04, -1.120528e+04, -5.191012e+02, 7.308553e+02, 2.355571e+04, -8.359487e+03, -1.040853e+02, 3.073388e+02, 2.361176e+04, 2.035431e+12, 2.901375e+07, 4.780096e+03, 9.809298e+01, -5.474072e+11, 1.251406e+08, 7.594803e+03, 9.819442e+01, 1.394761e+10, -7.629265e+06, 1.388420e+04, 9.997117e+01, -1.679680e+09, 2.117312e+06, 1.337516e+04, 1.041901e+02, 8.766416e+08, -9.398136e+05, 1.402618e+04, 1.131463e+02, -1.075785e+08, 9.687180e+05, 1.495756e+04, 1.278750e+02, 2.864970e+07, 5.123123e+05, 1.720256e+04, 1.533065e+02, 9.381308e+06, 5.907406e+05, 1.985760e+04, 1.937223e+02, 6.513705e+05, 6.528921e+05, 2.353833e+04, 2.568166e+02, -5.060574e+06, 7.148069e+05, 2.845009e+04, 3.540337e+02, -2.618546e+07, 8.664181e+05, 3.479716e+04, 5.020198e+02, -3.042888e+06, 6.182842e+05, 4.212681e+04, 7.239051e+02, -2.186162e+07, 7.922891e+05, 5.016165e+04, 1.040177e+03, -1.315392e+07, 5.761193e+05, 5.868562e+04, 1.485943e+03, -1.193382e+07, 4.596976e+05, 6.604172e+04, 2.079489e+03, -1.054882e+07, 3.262631e+05, 7.180635e+04, 2.836858e+03, -7.325607e+06, 1.634016e+05, 7.502793e+04, 3.759447e+03, -3.572050e+06, 1.753149e+04, 7.527153e+04, 4.828034e+03, -3.650321e+06, -2.059097e+04, 7.313771e+04, 6.010651e+03, -1.306615e+06, -1.038379e+05, 6.897657e+04, 7.278719e+03, -1.434776e+06, -1.010734e+05, 6.337556e+04, 8.585264e+03, -2.928626e+05, -1.291286e+05, 5.694775e+04, 9.900359e+03, -2.016734e+05, -1.130713e+05, 5.027089e+04, 1.118410e+04, -2.496937e+05, -9.435927e+04, 4.393471e+04, 1.241926e+04, 2.877942e+04, -8.902541e+04, 3.793319e+04, 1.359137e+04, -4.486830e+04, -6.924231e+04, 3.248876e+04, 1.468407e+04, 6.596483e+04, -6.067637e+04, 2.767914e+04, 1.569668e+04, 1.919128e+03, -4.535751e+04, 2.353265e+04, 1.662511e+04, -1.625891e+04, -3.587718e+04, 1.999336e+04, 1.747626e+04, 4.744522e+02, -2.997748e+04, 1.689298e+04, 1.825163e+04, 4.486151e+04, -2.618098e+04, 1.419742e+04, 1.895127e+04, -1.216274e+04, -1.716435e+04, 1.198976e+04, 1.957871e+04, -1.352060e+03, -1.478644e+04, 1.013202e+04, 2.014715e+04, 1.854542e+04, -1.309060e+04, 8.504452e+03, 2.065628e+04, -1.365895e+04, -8.081327e+03, 7.172319e+03, 2.110940e+04, 7.774980e+03, -8.328556e+03, 6.022138e+03, 2.151710e+04, -1.162068e+04, -5.117308e+03, 5.035574e+03, 2.187637e+04, 5.375795e+02, -5.332525e+03, 4.164918e+03, 2.219523e+04, 4.583329e+03, -4.486221e+03, 3.397818e+03, 2.247013e+04, -1.191642e+04, -2.061146e+03, 2.790819e+03, 2.270630e+04, -4.488671e+02, -2.946084e+03, 2.225430e+03, 2.291181e+04, -1.079293e+04, -1.286923e+03, 1.715923e+03, 2.307911e+04, -7.008889e+03, -1.462410e+03, 1.229813e+03, 2.321411e+04, -1.789120e+04, 1.465535e+02, 7.731271e+02, 2.331052e+04, -8.173676e+03, -1.495901e+02, 2.878103e+02, 2.337081e+04, 1.247757e+12, -4.159768e+06, 4.106319e+03, 2.671606e+01, -1.699001e+11, 3.477713e+07, 5.075193e+03, 2.679200e+01, 7.370859e+09, -4.831578e+06, 6.046716e+03, 2.761225e+01, 1.300189e+09, -8.314183e+05, 5.253834e+03, 2.933335e+01, -4.200184e+08, 1.179100e+06, 5.779982e+03, 3.268336e+01, 1.995671e+08, -6.254952e+04, 6.866446e+03, 3.957643e+01, -6.307859e+07, 7.234239e+05, 8.143396e+03, 5.096381e+01, 2.152375e+07, 3.977221e+05, 1.040391e+04, 7.159662e+01, -8.539422e+06, 6.140945e+05, 1.326918e+04, 1.058127e+02, -1.078821e+07, 6.779304e+05, 1.750490e+04, 1.635930e+02, -1.275937e+07, 7.382400e+05, 2.313246e+04, 2.590606e+02, -1.872188e+07, 8.098821e+05, 3.031069e+04, 4.127114e+02, -1.831776e+07, 7.681029e+05, 3.876504e+04, 6.520684e+02, -1.327143e+07, 6.348936e+05, 4.759282e+04, 1.005990e+03, -1.250117e+07, 5.390875e+05, 5.602596e+04, 1.500068e+03, -1.108426e+07, 4.074780e+05, 6.331628e+04, 2.157158e+03, -7.144209e+06, 2.282751e+05, 6.830848e+04, 2.985745e+03, -5.593622e+06, 1.138962e+05, 7.048728e+04, 3.973074e+03, -2.744275e+06, -8.550059e+03, 6.988463e+04, 5.096047e+03, -2.060504e+06, -5.271929e+04, 6.700169e+04, 6.315326e+03, -1.188937e+06, -8.943405e+04, 6.253661e+04, 7.597067e+03, -7.019956e+05, -1.025893e+05, 5.696328e+04, 8.901951e+03, -1.520013e+05, -1.094255e+05, 5.085384e+04, 1.019564e+04, -4.279199e+05, -8.501426e+04, 4.481075e+04, 1.144946e+04, 2.473795e+05, -9.671243e+04, 3.890686e+04, 1.265006e+04, -1.850617e+05, -6.070952e+04, 3.361721e+04, 1.377212e+04, -1.055200e+04, -5.889414e+04, 2.890583e+04, 1.482700e+04, 8.554444e+04, -5.153152e+04, 2.458599e+04, 1.579867e+04, -3.284826e+04, -3.517891e+04, 2.094752e+04, 1.668657e+04, 2.250379e+04, -3.169404e+04, 1.781798e+04, 1.750203e+04, 7.187402e+02, -2.410799e+04, 1.510178e+04, 1.824183e+04, -1.312021e+04, -1.879373e+04, 1.278706e+04, 1.891267e+04, 2.993219e+04, -1.781145e+04, 1.075453e+04, 1.951760e+04, -4.534421e+03, -1.160389e+04, 9.076530e+03, 2.005681e+04, -9.759605e+03, -9.241454e+03, 7.683732e+03, 2.054363e+04, 1.191358e+04, -9.141714e+03, 6.435051e+03, 2.097932e+04, -8.934994e+03, -5.555194e+03, 5.395231e+03, 2.136320e+04, -6.609238e+03, -4.931263e+03, 4.502483e+03, 2.170563e+04, 5.379062e+03, -5.019351e+03, 3.680346e+03, 2.200446e+04, -1.353400e+04, -2.242077e+03, 3.005639e+03, 2.225951e+04, 2.319882e+03, -3.483057e+03, 2.379456e+03, 2.248033e+04, -1.195571e+04, -1.258098e+03, 1.838619e+03, 2.265852e+04, -8.857921e+03, -1.424507e+03, 1.329970e+03, 2.280386e+04, -1.138151e+04, -6.455122e+02, 8.319621e+02, 2.290844e+04, -8.381217e+03, -2.582078e+02, 3.786418e+02, 2.297301e+04, -6.454234e+12, 9.523189e+07, 2.495739e+03, 3.168572e+00, 1.564445e+09, -3.199648e+05, 2.543842e+01, 3.206831e+00, -1.131465e+10, 7.292156e+06, 1.655634e+01, 3.207991e+00, 4.572081e+08, -3.622419e+05, 1.152075e+03, 3.598120e+00, -1.359952e+08, 3.523478e+05, 1.247960e+03, 4.304180e+00, 8.530206e+07, -7.761152e+04, 1.537856e+03, 5.847887e+00, -4.046656e+06, 2.350133e+05, 1.924059e+03, 8.398513e+00, -9.369154e+06, 3.013373e+05, 2.894860e+03, 1.369454e+01, 1.558148e+05, 3.157345e+05, 4.412027e+03, 2.445354e+01, -9.593296e+06, 4.737070e+05, 6.780646e+03, 4.538315e+01, -1.399124e+07, 5.975570e+05, 1.057839e+04, 8.641807e+01, -1.458432e+07, 6.713753e+05, 1.603092e+04, 1.636301e+02, -1.575957e+07, 7.190945e+05, 2.317086e+04, 3.001042e+02, -1.469259e+07, 6.919930e+05, 3.170783e+04, 5.261023e+02, -1.349217e+07, 6.160599e+05, 4.083870e+04, 8.742847e+02, -1.067177e+07, 4.778233e+05, 4.945175e+04, 1.374014e+03, -7.035158e+06, 3.153236e+05, 5.638367e+04, 2.041943e+03, -6.267557e+06, 2.139302e+05, 6.107922e+04, 2.878901e+03, -3.507150e+06, 7.645845e+04, 6.313857e+04, 3.875261e+03, -2.677493e+06, 9.369796e+03, 6.254822e+04, 4.997522e+03, -1.075512e+06, -6.097170e+04, 5.980948e+04, 6.210996e+03, -7.903147e+05, -7.423698e+04, 5.563430e+04, 7.471213e+03, -4.489454e+05, -8.347235e+04, 5.072914e+04, 8.748128e+03, -2.919591e+05, -8.138940e+04, 4.543441e+04, 1.001114e+04, -1.257206e+05, -7.734475e+04, 4.007037e+04, 1.123568e+04, 7.103736e+04, -7.237268e+04, 3.490447e+04, 1.240137e+04, -1.651301e+05, -4.973913e+04, 3.027758e+04, 1.349609e+04, 2.019954e+05, -5.792714e+04, 2.601103e+04, 1.452225e+04, -2.203643e+05, -2.570562e+04, 2.240670e+04, 1.546308e+04, 1.590559e+05, -4.244143e+04, 1.908034e+04, 1.634265e+04, -4.466576e+04, -2.108640e+04, 1.622655e+04, 1.712995e+04, -3.174091e+03, -2.048205e+04, 1.388742e+04, 1.785684e+04, 2.790637e+04, -1.838833e+04, 1.176019e+04, 1.851513e+04, -2.641650e+04, -1.106596e+04, 1.000103e+04, 1.910723e+04, 1.001047e+04, -1.197742e+04, 8.449539e+03, 1.964524e+04, -6.360157e+03, -8.288998e+03, 7.088763e+03, 2.012232e+04, 9.035106e+03, -7.929982e+03, 5.927220e+03, 2.054736e+04, -1.377516e+04, -4.429300e+03, 4.963148e+03, 2.092106e+04, -1.844206e+03, -4.907418e+03, 4.100319e+03, 2.125328e+04, -1.021359e+03, -3.955754e+03, 3.315436e+03, 2.153793e+04, -1.171826e+04, -2.188327e+03, 2.657105e+03, 2.177916e+04, -3.402617e+03, -2.688462e+03, 2.032883e+03, 2.198166e+04, -1.058462e+04, -1.288381e+03, 1.472992e+03, 2.213899e+04, -1.978474e+04, 9.938386e+00, 9.552157e+02, 2.225671e+04, -1.234013e+04, -2.436993e+00, 3.887609e+02, 2.233175e+04, 0, 0, 0, 1.826016e-01, -1.781927e+10, 3.424198e+06, 0, 1.826016e-01, 3.387426e+08, -1.818905e+05, 4.801526e+01, 2.011516e-01, -1.332156e+08, 1.980034e+05, 3.787939e+01, 2.092672e-01, 7.713524e+06, 2.074307e+04, 1.278808e+02, 2.794094e-01, -1.191841e+07, 6.762032e+04, 1.970895e+02, 4.457797e-01, 1.168172e+07, 9.597587e+03, 3.212529e+02, 8.753281e-01, -7.375921e+06, 1.272459e+05, 5.312329e+02, 1.747178e+00, -1.857624e+06, 1.420437e+05, 1.084825e+03, 4.192300e+00, -4.445982e+06, 2.336181e+05, 2.069508e+03, 1.014047e+01, -9.256611e+06, 3.691046e+05, 3.961112e+03, 2.445296e+01, -1.146668e+07, 4.853842e+05, 7.269072e+03, 5.735080e+01, -1.079778e+07, 5.581243e+05, 1.230141e+04, 1.261528e+02, -1.490989e+07, 6.582014e+05, 1.920854e+04, 2.563772e+02, -1.194617e+07, 5.952954e+05, 2.764421e+04, 4.835162e+02, -1.014583e+07, 5.122274e+05, 3.635427e+04, 8.392605e+02, -7.408351e+06, 3.853587e+05, 4.438509e+04, 1.350733e+03, -6.570506e+06, 2.855657e+05, 5.083123e+04, 2.031559e+03, -3.758086e+06, 1.418179e+05, 5.493214e+04, 2.882348e+03, -2.683018e+06, 6.098002e+04, 5.642001e+04, 3.878421e+03, -1.659085e+06, -4.330207e+03, 5.570503e+04, 4.991285e+03, -7.795872e+05, -4.882689e+04, 5.316507e+04, 6.183054e+03, -5.845028e+05, -5.942304e+04, 4.949336e+04, 7.415604e+03, -5.798157e+05, -6.026377e+04, 4.517923e+04, 8.660316e+03, 1.100702e+05, -8.130453e+04, 4.031747e+04, 9.888095e+03, -6.137872e+04, -6.032203e+04, 3.558748e+04, 1.106470e+04, -1.487668e+05, -4.829607e+04, 3.132184e+04, 1.219098e+04, 6.027672e+04, -5.086659e+04, 2.722487e+04, 1.325775e+04, -5.216647e+04, -3.589720e+04, 2.352245e+04, 1.424838e+04, 3.877460e+04, -3.464697e+04, 2.023029e+04, 1.516931e+04, 2.888551e+03, -2.575328e+04, 1.734715e+04, 1.601318e+04, -2.191980e+04, -1.979610e+04, 1.488919e+04, 1.678848e+04, 2.034645e+04, -1.902784e+04, 1.268427e+04, 1.749745e+04, -1.314803e+04, -1.300850e+04, 1.078756e+04, 1.813689e+04, 7.781400e+03, -1.225965e+04, 9.144667e+03, 1.871660e+04, -1.204517e+04, -8.419968e+03, 7.723806e+03, 1.923488e+04, 7.765000e+03, -8.536896e+03, 6.472742e+03, 1.969918e+04, -4.584280e+03, -5.708889e+03, 5.406950e+03, 2.010716e+04, -7.904211e+03, -4.491134e+03, 4.503836e+03, 2.046843e+04, -5.550058e+03, -3.997071e+03, 3.675945e+03, 2.078373e+04, -5.689591e+03, -3.236437e+03, 2.922488e+03, 2.105140e+04, -7.906009e+03, -2.378643e+03, 2.250590e+03, 2.127255e+04, -9.071692e+03, -1.745359e+03, 1.638712e+03, 2.144855e+04, -2.806270e+04, 6.649150e+02, 1.075166e+03, 2.157900e+04, -1.103646e+04, -2.530936e+02, 3.990825e+02, 2.166428e+04, 1.172160e+12, -1.700048e+07, -4.587932e+02, 9.275000e-03, -5.008907e+09, 9.229085e+05, 0, 2.318750e-03, 3.111030e+07, -1.680365e+04, 3.936294e+00, 6.956250e-03, -5.703770e+07, 5.741850e+04, 2.940735e+00, 7.535938e-03, 4.750408e+06, -7.579855e+03, 6.576946e+00, 1.797031e-02, -4.550239e+06, 1.931719e+04, 6.393513e+00, 2.202812e-02, 1.542980e+06, 4.706168e+03, 3.340755e+01, 6.202656e-02, -1.997114e+06, 3.649206e+04, 7.619777e+01, 1.739063e-01, -1.593482e+06, 6.356589e+04, 2.379679e+02, 6.562062e-01, -4.537893e+06, 1.384804e+05, 6.466292e+02, 2.352372e+00, -5.704782e+06, 2.258349e+05, 1.643354e+03, 7.932444e+00, -8.516026e+06, 3.526078e+05, 3.663294e+03, 2.360140e+01, -1.066595e+07, 4.742071e+05, 7.292901e+03, 6.245495e+01, -1.234505e+07, 5.621427e+05, 1.286902e+04, 1.467728e+02, -1.044587e+07, 5.508898e+05, 2.017730e+04, 3.077457e+02, -9.750714e+06, 5.176087e+05, 2.845385e+04, 5.789490e+02, -8.773548e+06, 4.361175e+05, 3.680154e+04, 9.938209e+02, -4.887482e+06, 2.768423e+05, 4.386506e+04, 1.574100e+03, -4.580514e+06, 2.042767e+05, 4.895668e+04, 2.319036e+03, -3.037548e+06, 1.001684e+05, 5.188273e+04, 3.224335e+03, -1.252849e+06, 9.423824e+03, 5.229785e+04, 4.260421e+03, -1.512708e+06, -4.514040e+03, 5.093166e+04, 5.388799e+03, -3.330454e+05, -5.840272e+04, 4.812166e+04, 6.583262e+03, -4.555910e+05, -5.259927e+04, 4.437818e+04, 7.797270e+03, -2.055898e+05, -6.043330e+04, 4.025830e+04, 9.011318e+03, -6.518244e+04, -5.931446e+04, 3.591151e+04, 1.019675e+04, -4.788129e+04, -5.148756e+04, 3.170073e+04, 1.133492e+04, -1.294721e+04, -4.516239e+04, 2.777118e+04, 1.241608e+04, -4.132531e+04, -3.650926e+04, 2.417892e+04, 1.343242e+04, 4.353457e+04, -3.480201e+04, 2.089273e+04, 1.438065e+04, -3.999510e+04, -2.363060e+04, 1.802457e+04, 1.525446e+04, 1.132551e+04, -2.302607e+04, 1.547307e+04, 1.606249e+04, 2.024966e+04, -1.900290e+04, 1.319929e+04, 1.679741e+04, -2.275982e+04, -1.253345e+04, 1.130444e+04, 1.746504e+04, 2.065540e+03, -1.244152e+04, 9.619555e+03, 1.807448e+04, 1.308942e+04, -1.073860e+04, 8.111327e+03, 1.861996e+04, -1.540943e+04, -6.359948e+03, 6.878335e+03, 1.910663e+04, -6.509802e+03, -6.323129e+03, 5.782487e+03, 1.954531e+04, 2.137483e+03, -5.897918e+03, 4.759477e+03, 1.992990e+04, -1.089014e+04, -3.529000e+03, 3.892929e+03, 2.026106e+04, -7.464418e+03, -3.372208e+03, 3.110704e+03, 2.054648e+04, -4.499778e+03, -2.965848e+03, 2.377458e+03, 2.078153e+04, -1.809100e+04, -9.389300e+02, 1.742044e+03, 2.096658e+04, -1.603605e+04, -8.315728e+02, 1.093057e+03, 2.110637e+04, -1.205302e+04, -2.096724e+02, 4.696001e+02, 2.119034e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6.475609e+04, 3.371635e+02, 0, 0, 1.073009e+04, 4.374122e+02, 5.797537e-01, 5.796875e-04, -1.153454e+05, 2.841920e+03, 2.649198e+00, 4.057812e-03, -4.687182e+05, 1.144817e+04, 1.627061e+01, 3.304219e-02, -6.252477e+05, 3.031476e+04, 8.224170e+01, 2.295562e-01, -3.526268e+06, 9.906712e+04, 3.245361e+02, 1.211547e+00, -3.609003e+06, 1.630030e+05, 1.110639e+03, 5.633403e+00, -5.915653e+06, 2.810662e+05, 2.834579e+03, 1.971111e+01, -9.862311e+06, 4.241441e+05, 6.219224e+03, 5.787194e+01, -8.614873e+06, 4.527786e+05, 1.158730e+04, 1.459555e+02, -7.889704e+06, 4.557367e+05, 1.837941e+04, 3.144735e+02, -7.157548e+06, 4.205437e+05, 2.605154e+04, 5.981511e+02, -6.360659e+06, 3.497342e+05, 3.363796e+04, 1.028460e+03, -4.118223e+06, 2.292622e+05, 3.992991e+04, 1.623818e+03, -2.878278e+06, 1.400867e+05, 4.417527e+04, 2.379710e+03, -1.927495e+06, 6.762589e+04, 4.634548e+04, 3.280857e+03, -1.164354e+06, 1.289313e+04, 4.655326e+04, 4.300420e+03, -7.359802e+05, -1.922557e+04, 4.517303e+04, 5.404912e+03, -4.551779e+05, -3.785206e+04, 4.265242e+04, 6.561340e+03, -2.858538e+05, -4.634143e+04, 3.937600e+04, 7.738135e+03, -3.103799e+04, -5.354515e+04, 3.567211e+04, 8.907358e+03, -1.299037e+05, -4.253021e+04, 3.196524e+04, 1.004530e+04, -2.685978e+04, -4.253756e+04, 2.836175e+04, 1.114396e+04, -1.368389e+04, -3.669976e+04, 2.491097e+04, 1.218658e+04, -2.352848e+04, -3.043266e+04, 2.175512e+04, 1.316727e+04, -1.339091e+03, -2.684603e+04, 1.887271e+04, 1.408263e+04, 1.046307e+04, -2.278972e+04, 1.628025e+04, 1.492832e+04, 9.352423e+03, -1.845807e+04, 1.402391e+04, 1.570518e+04, -4.319180e+04, -1.193961e+04, 1.209103e+04, 1.641770e+04, 4.028668e+04, -1.613776e+04, 1.026860e+04, 1.707080e+04, -3.050514e+04, -7.295972e+03, 8.739795e+03, 1.765114e+04, 8.928799e+03, -9.664089e+03, 7.399996e+03, 1.818133e+04, -7.753111e+03, -6.276519e+03, 6.195452e+03, 1.864823e+04, -6.909366e+03, -5.375705e+03, 5.159494e+03, 1.906262e+04, -3.726578e+03, -4.729953e+03, 4.213524e+03, 1.942343e+04, -9.907304e+03, -3.262236e+03, 3.377412e+03, 1.973067e+04, -4.707397e+03, -3.194871e+03, 2.610089e+03, 1.998764e+04, -2.459705e+04, -5.431231e+02, 1.928936e+03, 2.019144e+04, -1.504684e+04, -1.268530e+03, 1.183585e+03, 2.034684e+04, -1.274940e+04, -2.357602e+02, 5.030266e+02, 2.043642e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -7.625111e+03, 1.942406e+02, 0, 0, -7.931768e+04, 2.359336e+03, 1.133080e+00, 2.318750e-03, -4.492099e+05, 1.342479e+04, 1.798340e+01, 5.101250e-02, -7.104236e+05, 3.641425e+04, 1.273072e+02, 5.072266e-01, -2.419312e+06, 1.031931e+05, 5.258904e+02, 2.856120e+00, -3.805147e+06, 1.873084e+05, 1.720050e+03, 1.257400e+01, -5.317208e+06, 2.798090e+05, 4.237425e+03, 4.225574e+01, -5.851424e+06, 3.374836e+05, 8.437182e+03, 1.146083e+02, -5.507526e+06, 3.474492e+05, 1.411444e+04, 2.603661e+02, -4.895399e+06, 3.204240e+05, 2.062382e+04, 5.126727e+02, -3.869675e+06, 2.596800e+05, 2.709028e+04, 9.003364e+02, -3.250395e+06, 1.961919e+05, 3.264631e+04, 1.439837e+03, -1.719326e+06, 1.064571e+05, 3.659167e+04, 2.133101e+03, -1.508329e+06, 6.693764e+04, 3.878265e+04, 2.961132e+03, -7.388517e+05, 1.449523e+04, 3.939682e+04, 3.906030e+03, -7.540220e+05, -5.614775e+02, 3.863621e+04, 4.934280e+03, -7.321527e+04, -3.634823e+04, 3.675864e+04, 6.019820e+03, -3.975025e+05, -2.269491e+04, 3.429005e+04, 7.123780e+03, 3.467499e+04, -4.367236e+04, 3.141477e+04, 8.236199e+03, -1.266303e+05, -3.044243e+04, 2.837963e+04, 9.321237e+03, -4.572541e+04, -3.225554e+04, 2.541711e+04, 1.037709e+04, 8.047126e+03, -3.069461e+04, 2.246501e+04, 1.138452e+04, 2.719321e+02, -2.520116e+04, 1.975091e+04, 1.233417e+04, -3.455116e+04, -1.935606e+04, 1.732791e+04, 1.322610e+04, -4.689464e+03, -1.871996e+04, 1.506835e+04, 1.405968e+04, 1.058268e+04, -1.648905e+04, 1.298115e+04, 1.482619e+04, -7.793109e+03, -1.216890e+04, 1.117406e+04, 1.552613e+04, -1.325167e+04, -9.935753e+03, 9.587327e+03, 1.616604e+04, 5.085932e+03, -9.803685e+03, 8.123301e+03, 1.674503e+04, -3.985046e+03, -7.120467e+03, 6.844793e+03, 1.725984e+04, -1.845867e+04, -4.797864e+03, 5.745869e+03, 1.771845e+04, 5.144229e+03, -6.303880e+03, 4.684891e+03, 1.812240e+04, -1.572588e+04, -2.947990e+03, 3.768049e+03, 1.846208e+04, -1.031994e+04, -3.174327e+03, 2.928434e+03, 1.875090e+04, -1.099561e+04, -2.380398e+03, 2.117366e+03, 1.897926e+04, -3.437355e+04, 6.816807e+02, 1.384817e+03, 1.914731e+04, -1.532091e+04, -2.375851e+02, 5.307093e+02, 1.925714e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.099496e+03, 3.170007e+01, 0, 0, -4.582160e+03, 2.717530e+02, 2.241895e-01, 5.796875e-04, -3.585634e+04, 2.139538e+03, 2.877762e+00, 9.854688e-03, -2.609433e+05, 1.233333e+04, 2.712355e+01, 1.182562e-01, -6.784321e+05, 3.792404e+04, 1.753766e+02, 1.005758e+00, -1.704870e+06, 9.086509e+04, 7.096012e+02, 5.462395e+00, -2.182629e+06, 1.428588e+05, 2.081180e+03, 2.173712e+01, -3.045174e+06, 2.017171e+05, 4.620780e+03, 6.547976e+01, -3.120058e+06, 2.258261e+05, 8.490531e+03, 1.620580e+02, -2.909976e+06, 2.219603e+05, 1.329642e+04, 3.408296e+02, -2.611518e+06, 1.958497e+05, 1.841926e+04, 6.296374e+02, -1.382570e+06, 1.339214e+05, 2.309259e+04, 1.047807e+03, -1.998218e+06, 1.265819e+05, 2.695490e+04, 1.598845e+03, -5.702259e+05, 4.570461e+04, 2.958101e+04, 2.288355e+03, -8.368829e+05, 3.927422e+04, 3.080162e+04, 3.084010e+03, -1.837335e+05, -2.241597e+03, 3.099690e+04, 3.976339e+03, -5.682648e+05, 6.527088e+03, 3.032646e+04, 4.930989e+03, 5.233127e+04, -2.991358e+04, 2.883729e+04, 5.936664e+03, -1.539996e+05, -1.717267e+04, 2.687146e+04, 6.947084e+03, -8.235537e+04, -2.202557e+04, 2.482136e+04, 7.962612e+03, -7.507519e+04, -2.154411e+04, 2.253483e+04, 8.960347e+03, 3.590736e+04, -2.572879e+04, 2.013928e+04, 9.924107e+03, -6.467983e+03, -1.870191e+04, 1.791295e+04, 1.083747e+04, -6.478698e+04, -1.295785e+04, 1.594240e+04, 1.170658e+04, 2.068703e+04, -1.780974e+04, 1.394673e+04, 1.252823e+04, 1.440187e+03, -1.297839e+04, 1.208844e+04, 1.328175e+04, -2.660685e+04, -8.967767e+03, 1.050701e+04, 1.397703e+04, 7.110755e+03, -1.063004e+04, 8.998969e+03, 1.461637e+04, -5.590234e+03, -7.510638e+03, 7.635425e+03, 1.518826e+04, -2.267292e+04, -5.019825e+03, 6.454280e+03, 1.570168e+04, 7.270321e+03, -7.162343e+03, 5.284981e+03, 1.615674e+04, -1.519724e+04, -3.427299e+03, 4.271128e+03, 1.654037e+04, -1.855140e+04, -2.800418e+03, 3.361608e+03, 1.686874e+04, -6.231274e+03, -3.489017e+03, 2.421245e+03, 1.713283e+04, -4.271753e+04, 1.261302e+03, 1.606297e+03, 1.732348e+04, -1.812555e+04, -2.715809e+02, 6.259157e+02, 1.745271e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -7.063987e+03, 3.054462e+02, 0, 0, -2.813574e+04, 1.877042e+03, 3.553681e+00, 1.623125e-02, -1.257337e+05, 8.447415e+03, 3.144681e+01, 1.930359e-01, -3.207497e+05, 2.447929e+04, 1.705861e+02, 1.372700e+00, -8.991627e+05, 5.794734e+04, 6.304306e+02, 6.658291e+00, -8.788635e+05, 7.984047e+04, 1.727592e+03, 2.451846e+01, -1.340991e+06, 1.142918e+05, 3.595521e+03, 6.842863e+01, -1.502817e+06, 1.295800e+05, 6.381372e+03, 1.604604e+02, -1.121162e+06, 1.171558e+05, 9.734555e+03, 3.246644e+02, -1.189577e+06, 1.116388e+05, 1.323854e+04, 5.801037e+02, -7.285780e+05, 8.048449e+04, 1.653685e+04, 9.441805e+02, -7.755311e+05, 6.738083e+04, 1.925313e+04, 1.419287e+03, -3.489333e+05, 3.413203e+04, 2.120419e+04, 2.006116e+03, -3.711578e+05, 2.473199e+04, 2.231455e+04, 2.686863e+03, -1.949665e+05, 6.860180e+03, 2.271868e+04, 3.451178e+03, -2.043607e+05, 1.205191e+03, 2.244544e+04, 4.276031e+03, -2.253753e+04, -1.242250e+04, 2.160182e+04, 5.143546e+03, -1.162624e+05, -7.671662e+03, 2.043880e+04, 6.027415e+03, -1.819840e+04, -1.508886e+04, 1.904169e+04, 6.921183e+03, -3.748045e+04, -1.282426e+04, 1.746345e+04, 7.800341e+03, -2.463956e+04, -1.307192e+04, 1.585114e+04, 8.657676e+03, 1.800068e+04, -1.453209e+04, 1.420241e+04, 9.480546e+03, -5.751030e+04, -7.191141e+03, 1.269744e+04, 1.025942e+04, 2.143863e+04, -1.325078e+04, 1.115837e+04, 1.100036e+04, -2.937991e+04, -6.800654e+03, 9.704313e+03, 1.167727e+04, 6.744357e+03, -9.354022e+03, 8.348776e+03, 1.230400e+04, -1.635229e+04, -5.637506e+03, 7.095223e+03, 1.286429e+04, -9.355270e+03, -5.739525e+03, 5.942650e+03, 1.336770e+04, -1.379714e+04, -4.465673e+03, 4.833668e+03, 1.380493e+04, -1.440112e+04, -3.753966e+03, 3.778207e+03, 1.417440e+04, -1.584389e+04, -2.861359e+03, 2.766756e+03, 1.447096e+04, -4.596605e+04, 9.777166e+02, 1.817438e+03, 1.469152e+04, -1.955254e+04, -3.565949e+02, 6.882263e+02, 1.483566e+04, }; static float solarDataset560[] = { 9.427478e+12, -2.974054e+07, 3.050751e+04, 6.870437e+02, -1.142007e+12, 2.473531e+08, 3.788610e+04, 6.876090e+02, 6.030303e+10, -3.189085e+07, 4.769687e+04, 6.937756e+02, -1.001912e+10, 1.190166e+07, 4.621301e+04, 7.080949e+02, 2.017518e+09, -2.733973e+06, 4.916779e+04, 7.398116e+02, -1.421427e+08, 1.460792e+06, 5.011031e+04, 7.908346e+02, -1.387029e+07, 8.966726e+05, 5.364395e+04, 8.724855e+02, 9.871561e+06, 7.113724e+05, 5.737052e+04, 9.940749e+02, 1.877554e+07, 6.336258e+05, 6.176658e+04, 1.167487e+03, -3.308155e+07, 8.873357e+05, 6.729500e+04, 1.408380e+03, -9.604436e+06, 6.024616e+05, 7.341952e+04, 1.738737e+03, -2.182764e+07, 6.203282e+05, 7.935645e+04, 2.175477e+03, -1.396323e+07, 4.168430e+05, 8.478006e+04, 2.740602e+03, -1.869470e+07, 3.550893e+05, 8.878213e+04, 3.445876e+03, -8.924426e+06, 9.938325e+04, 9.049216e+04, 4.298909e+03, -6.077214e+06, -9.169328e+03, 8.948659e+04, 5.283471e+03, -9.030289e+06, -1.361099e+04, 8.644249e+04, 6.382569e+03, -6.018017e+05, -2.166279e+05, 8.068593e+04, 7.572041e+03, -2.261151e+06, -1.582668e+05, 7.336941e+04, 8.793475e+03, -1.285988e+06, -1.711686e+05, 6.563977e+04, 1.003020e+04, -3.781520e+05, -1.714659e+05, 5.741413e+04, 1.124523e+04, 6.312955e+04, -1.524940e+05, 4.942384e+04, 1.240834e+04, -2.965801e+05, -1.122897e+05, 4.224018e+04, 1.350369e+04, 3.140122e+04, -1.022589e+05, 3.574972e+04, 1.452741e+04, 6.861713e+04, -8.171721e+04, 2.998492e+04, 1.546584e+04, 8.598786e+04, -6.438726e+04, 2.510945e+04, 1.632002e+04, -5.450437e+04, -4.482419e+04, 2.107040e+04, 1.709492e+04, 3.899927e+04, -4.009451e+04, 1.759867e+04, 1.779846e+04, 3.081603e+04, -3.072117e+04, 1.464125e+04, 1.842779e+04, 2.777883e+04, -2.372218e+04, 1.222329e+04, 1.899091e+04, -2.403858e+04, -1.592528e+04, 1.025673e+04, 1.949554e+04, 2.604334e+04, -1.580705e+04, 8.557456e+03, 1.994946e+04, -6.779180e+03, -1.020950e+04, 7.140866e+03, 2.035049e+04, 1.072751e+04, -9.367305e+03, 5.964755e+03, 2.070901e+04, -7.568154e+03, -6.091544e+03, 4.985814e+03, 2.102574e+04, 7.747026e+03, -6.090631e+03, 4.149838e+03, 2.130780e+04, -5.115560e+03, -3.749778e+03, 3.454636e+03, 2.155454e+04, 2.055488e+03, -3.682627e+03, 2.865067e+03, 2.177309e+04, -8.313760e+03, -2.062212e+03, 2.362034e+03, 2.196277e+04, 2.244934e+03, -2.716908e+03, 1.899309e+03, 2.212797e+04, -8.606358e+03, -1.085119e+03, 1.504703e+03, 2.226472e+04, 7.692302e+02, -1.849182e+03, 1.134821e+03, 2.237930e+04, -4.992822e+03, -7.414604e+02, 8.237234e+02, 2.246625e+04, -2.212781e+04, 1.130582e+03, 5.545028e+02, 2.253265e+04, -2.342747e+03, -3.239579e+02, 1.400637e+02, 2.257701e+04, -5.454661e+13, 6.695227e+08, 7.553013e+04, 3.151823e+02, 1.134950e+12, -2.733669e+08, 4.998801e+04, 3.164039e+02, 2.457067e+09, -5.372394e+05, 3.359107e+04, 3.204494e+02, 1.705050e+09, -3.885735e+05, 3.402986e+04, 3.314798e+02, -4.762097e+08, 1.872482e+06, 3.561497e+04, 3.534683e+02, 2.502076e+08, 3.098756e+05, 3.797324e+04, 3.924344e+02, 9.657814e+05, 9.594652e+05, 4.079242e+04, 4.537291e+02, 2.387841e+07, 8.134300e+05, 4.500723e+04, 5.476404e+02, -3.806754e+07, 1.053126e+06, 5.035453e+04, 6.862488e+02, 1.459099e+06, 7.335645e+05, 5.663526e+04, 8.873484e+02, -2.588512e+07, 8.852511e+05, 6.358440e+04, 1.168074e+03, -2.562254e+07, 7.542671e+05, 7.115830e+04, 1.554880e+03, -1.380731e+07, 5.011328e+05, 7.788194e+04, 2.068958e+03, -1.739894e+07, 4.295264e+05, 8.327746e+04, 2.724056e+03, -1.402960e+07, 2.469259e+05, 8.673685e+04, 3.532888e+03, -5.683137e+06, 1.809832e+04, 8.712896e+04, 4.487490e+03, -7.386279e+06, -5.267831e+03, 8.494526e+04, 5.562255e+03, -2.550597e+06, -1.428422e+05, 8.040191e+04, 6.736888e+03, -2.244178e+06, -1.494782e+05, 7.395598e+04, 7.964592e+03, -9.741098e+05, -1.707178e+05, 6.655347e+04, 9.214554e+03, -7.847748e+05, -1.541107e+05, 5.870751e+04, 1.045010e+04, 4.829605e+04, -1.529932e+05, 5.089533e+04, 1.164534e+04, -2.588837e+05, -1.146882e+05, 4.366237e+04, 1.277539e+04, 8.471593e+04, -1.046703e+05, 3.712384e+04, 1.383538e+04, -3.204309e+04, -7.873300e+04, 3.135177e+04, 1.481233e+04, 3.884792e+04, -6.547482e+04, 2.637054e+04, 1.570881e+04, 3.311172e+04, -5.122588e+04, 2.209839e+04, 1.652310e+04, 5.272904e+04, -4.098012e+04, 1.850837e+04, 1.725973e+04, -2.098666e+04, -2.870596e+04, 1.554469e+04, 1.792411e+04, -7.645698e+03, -2.392850e+04, 1.302179e+04, 1.852490e+04, 4.529440e+04, -2.168625e+04, 1.082138e+04, 1.906182e+04, 7.563854e+03, -1.438042e+04, 9.049216e+03, 1.953729e+04, -2.029968e+04, -9.904209e+03, 7.633053e+03, 1.996482e+04, 2.455605e+04, -1.104624e+04, 6.369259e+03, 2.034892e+04, -2.217501e+04, -5.312960e+03, 5.335176e+03, 2.068618e+04, 1.389523e+04, -7.222185e+03, 4.429009e+03, 2.098929e+04, 3.350305e+03, -4.596824e+03, 3.664659e+03, 2.125113e+04, -1.643678e+04, -2.165698e+03, 3.078933e+03, 2.148290e+04, 8.244762e+03, -4.103965e+03, 2.503118e+03, 2.168904e+04, -4.309852e+03, -1.906462e+03, 2.019271e+03, 2.186052e+04, -4.502906e+03, -1.615093e+03, 1.627422e+03, 2.200877e+04, -6.673494e+03, -1.145054e+03, 1.256210e+03, 2.213245e+04, -4.431929e+03, -1.125020e+03, 8.934107e+02, 2.223054e+04, -1.277831e+04, 1.017818e+02, 5.672148e+02, 2.230057e+04, -6.550689e+03, -6.795150e+01, 2.200245e+02, 2.234508e+04, 7.028093e+11, -5.632931e+06, 1.212518e+04, 8.786962e+01, 1.096934e+10, 3.427657e+06, 1.255748e+04, 8.808056e+01, -8.620693e+09, 6.311300e+06, 1.386382e+04, 8.966498e+01, 1.905895e+09, -7.785063e+05, 1.522377e+04, 9.457978e+01, -6.642623e+08, 2.069152e+06, 1.655659e+04, 1.044673e+02, 2.755384e+08, 1.270856e+05, 1.870469e+04, 1.233922e+02, -1.858521e+07, 9.802503e+05, 2.113739e+04, 1.541094e+02, 1.127113e+07, 8.555788e+05, 2.516211e+04, 2.048864e+02, -2.155426e+07, 1.035915e+06, 3.043400e+04, 2.857281e+02, -2.670990e+07, 1.046843e+06, 3.727913e+04, 4.129363e+02, -2.064658e+07, 9.583745e+05, 4.531105e+04, 6.072056e+02, -2.771027e+07, 9.488663e+05, 5.423102e+04, 8.931027e+02, -2.275812e+07, 7.675189e+05, 6.332478e+04, 1.299785e+03, -1.807120e+07, 5.679364e+05, 7.127246e+04, 1.849876e+03, -1.307118e+07, 3.611235e+05, 7.716269e+04, 2.557254e+03, -1.108885e+07, 2.095800e+05, 8.037925e+04, 3.422462e+03, -4.138438e+06, -1.246738e+03, 8.045019e+04, 4.432538e+03, -5.721080e+06, -1.375766e+04, 7.795263e+04, 5.553735e+03, -1.846673e+06, -1.340584e+05, 7.320954e+04, 6.762429e+03, -7.381453e+05, -1.533237e+05, 6.672674e+04, 8.006215e+03, -1.220612e+06, -1.255252e+05, 5.983885e+04, 9.253691e+03, -4.493834e+05, -1.350154e+05, 5.265160e+04, 1.048256e+04, 2.241188e+05, -1.320572e+05, 4.542483e+04, 1.165807e+04, -1.586451e+05, -9.300775e+04, 3.897017e+04, 1.276097e+04, -8.185331e+04, -7.944104e+04, 3.326870e+04, 1.379450e+04, 1.437491e+05, -7.221282e+04, 2.809949e+04, 1.474832e+04, -8.452171e+04, -4.730130e+04, 2.373007e+04, 1.561713e+04, 7.065088e+04, -4.526031e+04, 1.995960e+04, 1.641256e+04, -1.228967e+04, -3.137736e+04, 1.674335e+04, 1.712822e+04, 8.313530e+04, -2.961873e+04, 1.404205e+04, 1.777530e+04, -9.556767e+04, -1.350497e+04, 1.188112e+04, 1.835489e+04, 7.279899e+04, -2.152115e+04, 9.918036e+03, 1.888459e+04, -1.801529e+04, -1.047619e+04, 8.284368e+03, 1.934672e+04, 1.422292e+04, -1.081166e+04, 6.978533e+03, 1.976507e+04, -1.971096e+04, -6.232236e+03, 5.867255e+03, 2.013646e+04, 2.555580e+04, -8.493675e+03, 4.875924e+03, 2.046942e+04, -2.220971e+04, -2.736626e+03, 4.094432e+03, 2.075821e+04, 6.086730e+03, -4.963141e+03, 3.401028e+03, 2.102006e+04, -4.421174e+03, -2.900042e+03, 2.775707e+03, 2.124349e+04, -4.520515e+03, -2.411202e+03, 2.253152e+03, 2.143723e+04, -2.508622e+03, -2.146013e+03, 1.775733e+03, 2.160097e+04, -2.936199e+03, -1.618598e+03, 1.357499e+03, 2.173462e+04, -9.367685e+03, -6.231229e+02, 9.992896e+02, 2.184062e+04, -1.206672e+04, -1.719530e+02, 6.376552e+02, 2.192089e+04, -8.102102e+03, -5.838292e+00, 2.573335e+02, 2.197034e+04, -4.403129e+12, 5.670988e+07, 4.522792e+03, 1.062499e+01, 1.009104e+11, -2.052389e+07, 2.552832e+03, 1.069725e+01, -1.358716e+10, 8.667774e+06, 2.007574e+03, 1.088375e+01, 9.860870e+08, -7.696195e+05, 3.312868e+03, 1.199369e+01, -7.263205e+07, 5.079683e+05, 3.534528e+03, 1.404941e+01, 6.095618e+07, 2.370154e+05, 4.361871e+03, 1.824319e+01, 1.451466e+07, 4.286776e+05, 5.555429e+03, 2.590389e+01, -1.400850e+07, 6.184504e+05, 7.641043e+03, 4.027263e+01, -1.241073e+07, 6.950653e+05, 1.088771e+04, 6.743470e+01, -1.795027e+07, 8.260387e+05, 1.556669e+04, 1.172372e+02, -2.319572e+07, 9.411195e+05, 2.210913e+04, 2.061525e+02, -3.010013e+07, 1.015888e+06, 3.058323e+04, 3.586307e+02, -2.022242e+07, 8.484787e+05, 4.025853e+04, 6.058539e+02, -1.910299e+07, 7.492166e+05, 5.001245e+04, 9.760963e+02, -1.557142e+07, 5.745389e+05, 5.904610e+04, 1.498265e+03, -1.230740e+07, 3.873126e+05, 6.601791e+04, 2.188449e+03, -6.940073e+06, 1.748956e+05, 6.994206e+04, 3.045149e+03, -5.177292e+06, 6.314485e+04, 7.073880e+04, 4.045467e+03, -2.366516e+06, -4.755500e+04, 6.884163e+04, 5.161344e+03, -2.358205e+06, -6.773915e+04, 6.493284e+04, 6.352030e+03, -5.046368e+05, -1.245616e+05, 5.953143e+04, 7.585005e+03, -7.352958e+05, -1.050440e+05, 5.340095e+04, 8.814996e+03, -4.712122e+04, -1.140651e+05, 4.711703e+04, 1.002166e+04, -1.940792e+05, -9.000891e+04, 4.104669e+04, 1.117633e+04, -5.334300e+04, -8.040981e+04, 3.542982e+04, 1.227079e+04, 3.617207e+04, -6.882656e+04, 3.028288e+04, 1.329163e+04, 3.113110e+04, -5.478774e+04, 2.577621e+04, 1.423360e+04, -6.129565e+04, -4.010649e+04, 2.191962e+04, 1.509901e+04, 8.799100e+04, -3.960913e+04, 1.850097e+04, 1.589132e+04, -3.273914e+04, -2.471044e+04, 1.563896e+04, 1.660515e+04, 5.062606e+04, -2.465741e+04, 1.321567e+04, 1.725598e+04, -4.331664e+04, -1.394978e+04, 1.119464e+04, 1.784036e+04, 2.151457e+04, -1.584838e+04, 9.420701e+03, 1.837225e+04, 2.057252e+04, -1.209662e+04, 7.881816e+03, 1.884308e+04, -3.218097e+04, -5.996226e+03, 6.685549e+03, 1.926382e+04, 1.272473e+04, -8.675284e+03, 5.581521e+03, 1.964513e+04, 1.293397e+04, -6.525058e+03, 4.612838e+03, 1.997558e+04, -2.512579e+04, -2.085553e+03, 3.897889e+03, 2.026666e+04, 9.631166e+03, -5.124486e+03, 3.195860e+03, 2.052944e+04, -8.369392e+03, -2.217471e+03, 2.579994e+03, 2.074865e+04, -4.945385e+03, -2.272369e+03, 2.058660e+03, 2.093800e+04, -3.084443e+03, -1.973310e+03, 1.566386e+03, 2.109326e+04, -7.303688e+03, -1.067347e+03, 1.141462e+03, 2.121494e+04, -1.970787e+04, 4.640662e+02, 7.508659e+02, 2.130630e+04, -7.520008e+03, -1.899019e+02, 2.755003e+02, 2.136575e+04, 1.985745e+12, -2.912097e+07, -7.661830e+02, 6.684121e-01, -6.636634e+08, 2.990354e+05, 0, 6.567228e-01, -2.343986e+09, 1.611661e+06, 4.317728e+01, 6.599108e-01, 2.254208e+07, 4.359743e+04, 3.445681e+02, 7.645827e-01, 1.156883e+07, 5.539843e+04, 4.276905e+02, 1.007931e+00, 1.328478e+07, 6.727963e+04, 5.825680e+02, 1.532353e+00, -1.427828e+06, 1.497926e+05, 8.917103e+02, 2.663022e+00, 9.122115e+05, 2.061081e+05, 1.527034e+03, 5.318074e+00, -1.436027e+07, 3.894326e+05, 2.751124e+03, 1.153834e+01, -1.297819e+07, 4.891972e+05, 5.061759e+03, 2.652661e+01, -1.440164e+07, 6.231437e+05, 8.782631e+03, 5.952481e+01, -2.071955e+07, 7.895515e+05, 1.448705e+04, 1.272475e+02, -2.105556e+07, 8.342286e+05, 2.238247e+04, 2.567244e+02, -1.730582e+07, 7.638287e+05, 3.174262e+04, 4.810755e+02, -1.649409e+07, 6.787079e+05, 4.153117e+04, 8.337819e+02, -1.213281e+07, 4.915370e+05, 5.044160e+04, 1.344592e+03, -7.204027e+06, 2.923513e+05, 5.703735e+04, 2.024137e+03, -6.395770e+06, 1.876444e+05, 6.098537e+04, 2.865273e+03, -3.652266e+06, 5.084202e+04, 6.211538e+04, 3.853040e+03, -1.242084e+06, -4.545439e+04, 6.048160e+04, 4.948354e+03, -2.077700e+06, -3.761168e+04, 5.725210e+04, 6.110893e+03, -4.035125e+05, -9.878235e+04, 5.267188e+04, 7.316266e+03, -2.774259e+05, -9.184399e+04, 4.725635e+04, 8.513608e+03, -7.489327e+04, -8.630250e+04, 4.187600e+04, 9.683030e+03, -1.824318e+05, -6.931827e+04, 3.676257e+04, 1.080698e+04, -2.043178e+04, -6.528394e+04, 3.193106e+04, 1.187602e+04, -2.125564e+04, -5.356901e+04, 2.747061e+04, 1.287528e+04, 3.802628e+04, -4.622590e+04, 2.349523e+04, 1.380133e+04, -1.011949e+04, -3.479996e+04, 2.005371e+04, 1.465185e+04, 1.957445e+04, -2.979789e+04, 1.707635e+04, 1.543211e+04, -2.310000e+04, -2.169519e+04, 1.451302e+04, 1.614210e+04, 4.887815e+04, -2.176628e+04, 1.226507e+04, 1.678755e+04, -3.010570e+04, -1.212523e+04, 1.041726e+04, 1.736624e+04, 1.141261e+04, -1.307324e+04, 8.823028e+03, 1.789421e+04, 2.115730e+03, -9.658469e+03, 7.420827e+03, 1.836449e+04, -3.130044e+03, -7.419199e+03, 6.255799e+03, 1.878518e+04, -1.015496e+04, -5.605767e+03, 5.248800e+03, 1.916053e+04, 1.197197e+04, -6.387298e+03, 4.331709e+03, 1.949224e+04, -9.451760e+03, -3.045742e+03, 3.592623e+03, 1.977809e+04, -9.143314e+03, -2.779727e+03, 2.959049e+03, 2.003133e+04, -4.060531e+02, -3.138927e+03, 2.331861e+03, 2.024720e+04, -8.374759e+03, -1.630913e+03, 1.790562e+03, 2.042217e+04, -9.631227e+03, -1.214229e+03, 1.300725e+03, 2.056279e+04, -1.757971e+04, -7.909526e+00, 8.217597e+02, 2.066585e+04, -9.360190e+03, -1.008561e+02, 3.151603e+02, 2.072972e+04, 7.057544e+11, -1.002630e+07, -2.834657e+02, 2.019051e-02, -5.762712e+09, 1.096773e+06, 0, 1.593987e-02, 9.580494e+07, -5.116182e+04, 1.296875e+01, 2.178450e-02, -7.314732e+07, 8.930245e+04, 1.028639e+01, 2.390981e-02, 1.212836e+07, -1.522072e+04, 3.493413e+01, 4.781962e-02, 1.107723e+06, 1.523353e+04, 4.315452e+01, 8.182469e-02, -3.122114e+06, 4.692205e+04, 9.912353e+01, 1.912785e-01, -1.218946e+05, 6.710879e+04, 2.596781e+02, 6.004020e-01, -7.767512e+06, 1.781769e+05, 6.475762e+02, 1.923412e+00, -7.081599e+06, 2.703169e+05, 1.654503e+03, 6.432271e+00, -1.388268e+07, 4.599894e+05, 3.716433e+03, 1.933826e+01, -1.677008e+07, 6.152583e+05, 7.609712e+03, 5.293951e+01, -1.773788e+07, 7.158283e+05, 1.367450e+04, 1.284552e+02, -1.673161e+07, 7.330517e+05, 2.177075e+04, 2.764208e+02, -1.582636e+07, 6.844310e+05, 3.113206e+04, 5.328466e+02, -1.143484e+07, 5.250286e+05, 4.040399e+04, 9.320810e+02, -7.912410e+06, 3.651709e+05, 4.815568e+04, 1.493388e+03, -6.534461e+06, 2.459158e+05, 5.373328e+04, 2.221905e+03, -3.824178e+06, 1.046254e+05, 5.660509e+04, 3.108860e+03, -2.225738e+06, 1.563807e+04, 5.671396e+04, 4.122526e+03, -1.458328e+06, -3.221722e+04, 5.474607e+04, 5.227111e+03, -8.183570e+05, -6.333746e+04, 5.127832e+04, 6.386920e+03, -2.794557e+05, -7.986545e+04, 4.684627e+04, 7.565535e+03, -3.250386e+05, -7.038672e+04, 4.208904e+04, 8.732396e+03, -1.754872e+05, -6.847775e+04, 3.727257e+04, 9.869589e+03, 1.159607e+05, -6.912938e+04, 3.251333e+04, 1.095548e+04, -9.178916e+04, -4.742331e+04, 2.825702e+04, 1.197515e+04, -3.478289e+04, -4.291868e+04, 2.444894e+04, 1.293450e+04, 4.096451e+04, -3.883179e+04, 2.093198e+04, 1.382302e+04, 1.018149e+04, -2.939198e+04, 1.788632e+04, 1.463685e+04, -6.312718e+03, -2.298834e+04, 1.530245e+04, 1.538327e+04, 8.853193e+01, -1.922555e+04, 1.304664e+04, 1.606557e+04, -4.315150e+03, -1.538511e+04, 1.107414e+04, 1.668446e+04, 2.613878e+04, -1.434570e+04, 9.354640e+03, 1.724279e+04, -3.056698e+04, -7.440654e+03, 7.953552e+03, 1.774252e+04, 1.201257e+04, -9.709738e+03, 6.690044e+03, 1.819679e+04, 2.315698e+03, -6.742600e+03, 5.577442e+03, 1.859490e+04, -9.440768e+03, -4.516726e+03, 4.681297e+03, 1.894793e+04, 1.196941e+03, -4.741381e+03, 3.874527e+03, 1.926086e+04, -7.702191e+03, -2.981726e+03, 3.168711e+03, 1.953055e+04, -8.882011e+03, -2.461540e+03, 2.537074e+03, 1.976277e+04, -1.422894e+03, -2.714319e+03, 1.927726e+03, 1.995485e+04, -1.333538e+04, -8.409366e+02, 1.410345e+03, 2.010401e+04, -1.909208e+04, -3.880590e+01, 9.041545e+02, 2.021755e+04, -1.040053e+04, -1.016679e+02, 3.480591e+02, 2.028776e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -9.747318e+05, 3.472389e+03, 0, 0, 4.067195e+05, -3.625279e+02, 3.698487e+00, 4.781962e-03, -2.201325e+05, 7.112541e+03, 7.958936e+00, 1.540855e-02, -1.375506e+06, 3.099300e+04, 4.379474e+01, 9.351393e-02, -2.748196e+06, 8.093983e+04, 2.179212e+02, 6.189985e-01, -4.968397e+06, 1.759744e+05, 7.942168e+02, 3.123153e+00, -9.224231e+06, 3.310828e+05, 2.317096e+03, 1.246073e+01, -1.172345e+07, 4.760308e+05, 5.552592e+03, 4.086665e+01, -1.364940e+07, 5.855323e+05, 1.095084e+04, 1.106753e+02, -1.160214e+07, 5.818835e+05, 1.835230e+04, 2.545476e+02, -1.186484e+07, 5.618680e+05, 2.689271e+04, 5.080793e+02, -8.404699e+06, 4.221755e+05, 3.536085e+04, 9.063264e+02, -5.194575e+06, 2.784763e+05, 4.225115e+04, 1.464581e+03, -5.350129e+06, 2.094167e+05, 4.716334e+04, 2.183139e+03, -1.602308e+06, 5.042204e+04, 4.954778e+04, 3.054031e+03, -2.214826e+06, 3.646787e+04, 4.967168e+04, 4.035868e+03, -9.356126e+05, -3.084597e+04, 4.811762e+04, 5.110060e+03, -4.549349e+05, -5.386665e+04, 4.503815e+04, 6.230077e+03, -3.040345e+05, -5.796460e+04, 4.128150e+04, 7.364268e+03, -1.176667e+05, -6.013046e+04, 3.722607e+04, 8.489020e+03, -2.285004e+05, -4.899339e+04, 3.315231e+04, 9.583239e+03, 1.171614e+05, -5.738783e+04, 2.908158e+04, 1.063408e+04, -6.209781e+04, -3.832039e+04, 2.537658e+04, 1.162023e+04, -2.092407e+04, -3.477457e+04, 2.209397e+04, 1.255044e+04, 7.150074e+03, -3.032506e+04, 1.906153e+04, 1.341566e+04, -1.872806e+04, -2.346902e+04, 1.637525e+04, 1.421280e+04, 3.845397e+04, -2.256213e+04, 1.398698e+04, 1.494422e+04, -2.212050e+04, -1.416819e+04, 1.197514e+04, 1.560777e+04, 1.117884e+04, -1.415931e+04, 1.022919e+04, 1.621605e+04, -9.805903e+03, -9.936432e+03, 8.698553e+03, 1.676423e+04, -6.284957e+03, -8.619152e+03, 7.363785e+03, 1.725975e+04, 8.194854e+03, -8.133936e+03, 6.160163e+03, 1.770134e+04, -1.348632e+03, -5.585066e+03, 5.156021e+03, 1.808984e+04, -2.129218e+04, -3.033875e+03, 4.322259e+03, 1.843476e+04, 1.090528e+04, -5.636095e+03, 3.481772e+03, 1.873867e+04, -1.576162e+04, -1.719787e+03, 2.785226e+03, 1.898864e+04, -3.646745e+03, -2.827982e+03, 2.153210e+03, 1.920291e+04, -1.365574e+04, -1.131453e+03, 1.562656e+03, 1.936968e+04, -1.907849e+04, -2.359625e+02, 9.938042e+02, 1.949465e+04, -1.267951e+04, -2.792363e+00, 3.995119e+02, 1.957176e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4.253495e+03, 7.499863e+01, 0, 0, -1.750552e+04, 6.611353e+02, 3.286766e-01, 5.313292e-04, -1.773001e+05, 5.748574e+03, 4.539952e+00, 1.009525e-02, -9.223470e+05, 2.879966e+04, 4.664094e+01, 1.386769e-01, -1.930323e+06, 7.899737e+04, 2.852048e+02, 1.171049e+00, -4.376965e+06, 1.804810e+05, 1.095224e+03, 6.203799e+00, -6.199410e+06, 2.925007e+05, 3.155202e+03, 2.454156e+01, -8.265951e+06, 3.988727e+05, 7.017706e+03, 7.510072e+01, -7.418139e+06, 4.164357e+05, 1.276099e+04, 1.879864e+02, -7.040578e+06, 4.038613e+05, 1.967473e+04, 3.966702e+02, -5.686102e+06, 3.336694e+05, 2.686086e+04, 7.341906e+02, -4.304528e+06, 2.438082e+05, 3.315168e+04, 1.220839e+03, -2.692813e+06, 1.463149e+05, 3.773689e+04, 1.860259e+03, -1.797320e+06, 7.842619e+04, 4.036734e+04, 2.638594e+03, -1.480552e+06, 3.567044e+04, 4.122917e+04, 3.534651e+03, -4.691014e+05, -1.943763e+04, 4.039585e+04, 4.520549e+03, -4.771614e+05, -2.551283e+04, 3.841306e+04, 5.556536e+03, -2.993912e+05, -3.669547e+04, 3.578773e+04, 6.621797e+03, -7.863820e+04, -4.472026e+04, 3.264362e+04, 7.688512e+03, -7.947163e+04, -3.968368e+04, 2.936882e+04, 8.732777e+03, -4.626689e+04, -3.655540e+04, 2.617168e+04, 9.743299e+03, -3.298749e+04, -3.228438e+04, 2.309979e+04, 1.070825e+04, 7.557068e+03, -2.951923e+04, 2.021271e+04, 1.161922e+04, -1.131117e+04, -2.346075e+04, 1.760143e+04, 1.246985e+04, -8.138479e+02, -2.029297e+04, 1.526546e+04, 1.326110e+04, -6.482612e+03, -1.648920e+04, 1.317628e+04, 1.399093e+04, -9.595959e+02, -1.408842e+04, 1.131675e+04, 1.466044e+04, -8.934017e+03, -1.109881e+04, 9.671678e+03, 1.526962e+04, 1.509275e+04, -1.089459e+04, 8.203717e+03, 1.582083e+04, -1.453210e+04, -6.361619e+03, 6.975921e+03, 1.631342e+04, -1.009911e+04, -6.003604e+03, 5.892338e+03, 1.675910e+04, 4.806694e+03, -6.254916e+03, 4.858851e+03, 1.715199e+04, -1.071047e+04, -3.527770e+03, 3.984625e+03, 1.748987e+04, -8.640748e+03, -3.280218e+03, 3.206107e+03, 1.778279e+04, -5.456272e+03, -2.969433e+03, 2.463075e+03, 1.802588e+04, -1.521043e+04, -1.321653e+03, 1.804258e+03, 1.821785e+04, -2.367697e+04, -9.087804e+01, 1.159175e+03, 1.836246e+04, -1.433487e+04, -4.953068e+01, 4.611681e+02, 1.845283e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.175559e+04, 9.319479e+02, 0, 0, -1.155952e+05, 5.362912e+03, 7.533434e+00, 2.444114e-02, -4.781473e+05, 2.294213e+04, 6.469392e+01, 2.901057e-01, -1.186903e+06, 6.363668e+04, 3.418921e+02, 2.059963e+00, -2.457058e+06, 1.339813e+05, 1.225389e+03, 9.946482e+00, -3.689532e+06, 2.089429e+05, 3.267949e+03, 3.596461e+01, -3.635500e+06, 2.440573e+05, 6.751900e+03, 1.017719e+02, -4.240893e+06, 2.702413e+05, 1.146298e+04, 2.351121e+02, -2.806952e+06, 2.203272e+05, 1.683224e+04, 4.676621e+02, -2.755320e+06, 1.948001e+05, 2.199412e+04, 8.191252e+02, -2.060483e+06, 1.377770e+05, 2.645927e+04, 1.306106e+03, -1.097631e+06, 7.499210e+04, 2.952827e+04, 1.925185e+03, -1.000923e+06, 4.815843e+04, 3.123190e+04, 2.659039e+03, -4.315165e+05, 8.335406e+03, 3.169514e+04, 3.491872e+03, -4.699637e+05, -3.883861e+02, 3.111515e+04, 4.393927e+03, -1.358086e+05, -2.181426e+04, 2.973216e+04, 5.345470e+03, -2.102148e+05, -1.969387e+04, 2.780408e+04, 6.315553e+03, -2.056386e+03, -3.015444e+04, 2.554160e+04, 7.289349e+03, -1.214515e+05, -2.109060e+04, 2.317332e+04, 8.242094e+03, 2.283767e+04, -2.752130e+04, 2.075837e+04, 9.169350e+03, 7.777847e+02, -2.167302e+04, 1.841980e+04, 1.004997e+04, -5.404760e+04, -1.555831e+04, 1.633979e+04, 1.088609e+04, 2.732346e+04, -1.905176e+04, 1.431599e+04, 1.167632e+04, -2.032427e+04, -1.233088e+04, 1.247912e+04, 1.240595e+04, -1.714066e+04, -1.113399e+04, 1.084237e+04, 1.308473e+04, 1.575944e+04, -1.185483e+04, 9.276789e+03, 1.370596e+04, -1.758306e+04, -6.912145e+03, 7.932318e+03, 1.426459e+04, -4.249523e+03, -7.239515e+03, 6.729422e+03, 1.477256e+04, -2.329697e+03, -6.114440e+03, 5.608986e+03, 1.522204e+04, -5.910026e+03, -4.665776e+03, 4.630493e+03, 1.561502e+04, -1.798960e+04, -2.846416e+03, 3.762089e+03, 1.595518e+04, -3.910095e+03, -3.884273e+03, 2.890839e+03, 1.624284e+04, -1.926873e+04, -1.391269e+03, 2.105855e+03, 1.646675e+04, -2.740709e+04, -1.634349e+02, 1.341530e+03, 1.663561e+04, -1.586965e+04, -1.115448e+02, 5.221589e+02, 1.673964e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -9.127396e+02, 4.028231e+01, 0, 0, -2.922208e+03, 3.533675e+02, 4.231000e-01, 1.593987e-03, -7.834748e+04, 3.913683e+03, 5.563741e+00, 2.656646e-02, -1.794238e+05, 1.330030e+04, 5.847158e+01, 3.613038e-01, -7.133529e+05, 4.140932e+04, 2.841249e+02, 2.339974e+00, -8.219289e+05, 6.765098e+04, 9.828657e+02, 1.089809e+01, -1.608881e+06, 1.135553e+05, 2.399301e+03, 3.586206e+01, -1.380790e+06, 1.250011e+05, 4.785818e+03, 9.597186e+01, -1.681694e+06, 1.416683e+05, 7.913429e+03, 2.122113e+02, -1.342164e+06, 1.248846e+05, 1.153453e+04, 4.098636e+02, -1.138530e+06, 1.048019e+05, 1.506125e+04, 7.058108e+02, -7.560038e+05, 7.458648e+04, 1.812017e+04, 1.110256e+03, -7.365586e+05, 5.736215e+04, 2.047117e+04, 1.622284e+03, -2.829319e+05, 2.385083e+04, 2.194529e+04, 2.236639e+03, -3.746521e+05, 1.866296e+04, 2.260812e+04, 2.932459e+03, -2.109677e+05, 1.572390e+03, 2.259219e+04, 3.699650e+03, -4.422227e+04, -1.078135e+04, 2.187151e+04, 4.512166e+03, -1.480152e+05, -6.663066e+03, 2.082518e+04, 5.348479e+03, -3.470247e+04, -1.527565e+04, 1.948176e+04, 6.200584e+03, -1.374575e+04, -1.543198e+04, 1.789581e+04, 7.043310e+03, -4.756536e+04, -1.215076e+04, 1.631547e+04, 7.867040e+03, -2.328940e+03, -1.445670e+04, 1.469261e+04, 8.665875e+03, -2.943259e+04, -1.086144e+04, 1.309232e+04, 9.424964e+03, 2.219356e+04, -1.335516e+04, 1.153409e+04, 1.014250e+04, -3.753978e+04, -6.601135e+03, 1.014219e+04, 1.080706e+04, 6.462929e+03, -9.897952e+03, 8.803313e+03, 1.142966e+04, -1.185789e+04, -6.587254e+03, 7.531425e+03, 1.199133e+04, -5.585795e+03, -6.310054e+03, 6.385138e+03, 1.249966e+04, -1.095521e+04, -4.847504e+03, 5.319253e+03, 1.294953e+04, -1.433834e+04, -3.906517e+03, 4.322975e+03, 1.334142e+04, -3.995946e+03, -4.280124e+03, 3.350694e+03, 1.367127e+04, -2.687799e+04, -1.046360e+03, 2.493151e+03, 1.393293e+04, -3.083327e+04, -4.093439e+02, 1.594075e+03, 1.413478e+04, -1.950779e+04, -7.012349e+01, 6.281431e+02, 1.425796e+04, }; static float solarDataset600[] = { 1.454828e+13, -1.753873e+07, 4.108891e+04, 1.618972e+03, -1.384284e+12, 3.644504e+08, 5.345299e+04, 1.619749e+03, -5.626237e+10, 3.552050e+07, 8.094015e+04, 1.629074e+03, 3.728997e+09, -3.217893e+06, 8.610187e+04, 1.657417e+03, -1.341046e+09, 2.537266e+06, 8.654787e+04, 1.711991e+03, 1.037406e+09, -1.842154e+06, 8.743552e+04, 1.804243e+03, -2.281591e+08, 1.692114e+06, 8.931420e+04, 1.940869e+03, 4.381924e+07, 4.651551e+05, 9.344253e+04, 2.142112e+03, -4.759171e+07, 8.163875e+05, 9.726835e+04, 2.419359e+03, -1.821050e+07, 4.964279e+05, 1.013782e+05, 2.792134e+03, -2.368294e+07, 4.294862e+05, 1.048241e+05, 3.274694e+03, -1.941022e+07, 2.763683e+05, 1.074121e+05, 3.882373e+03, -1.590314e+07, 1.381601e+05, 1.084676e+05, 4.624161e+03, -1.691643e+07, 5.407009e+04, 1.075833e+05, 5.501698e+03, -9.692053e+06, -1.241486e+05, 1.040909e+05, 6.506736e+03, -4.836417e+06, -2.247011e+05, 9.795019e+04, 7.611780e+03, -5.822942e+06, -2.072205e+05, 9.012361e+04, 8.785157e+03, -4.934677e+05, -2.953874e+05, 8.082216e+04, 9.997030e+03, -1.972241e+06, -2.181519e+05, 7.109185e+04, 1.120129e+04, -2.891157e+05, -2.240168e+05, 6.151353e+04, 1.238053e+04, -4.966324e+05, -1.758467e+05, 5.236592e+04, 1.350154e+04, 1.641487e+05, -1.585700e+05, 4.401724e+04, 1.455163e+04, 8.034773e+04, -1.203842e+05, 3.671628e+04, 1.551563e+04, -1.271137e+04, -9.085232e+04, 3.057720e+04, 1.639592e+04, 3.823284e+04, -7.282635e+04, 2.535605e+04, 1.719488e+04, 4.041914e+04, -5.648343e+04, 2.094476e+04, 1.791302e+04, 9.493516e+04, -4.559175e+04, 1.728272e+04, 1.855507e+04, -5.146686e+04, -2.872101e+04, 1.434663e+04, 1.912718e+04, 7.274758e+04, -2.868041e+04, 1.186372e+04, 1.964130e+04, -1.137111e+04, -1.752581e+04, 9.839214e+03, 2.009446e+04, -1.008472e+04, -1.422576e+04, 8.192508e+03, 2.050076e+04, 2.515788e+04, -1.323360e+04, 6.753657e+03, 2.086086e+04, 1.584386e+04, -9.397442e+03, 5.594194e+03, 2.117599e+04, -1.982323e+04, -5.090890e+03, 4.709331e+03, 2.145612e+04, 9.160687e+03, -6.384271e+03, 3.918052e+03, 2.170842e+04, 6.487543e+03, -4.632844e+03, 3.236203e+03, 2.192755e+04, -1.558850e+04, -2.009499e+03, 2.714977e+03, 2.212059e+04, 1.214568e+04, -4.063965e+03, 2.216067e+03, 2.229301e+04, -9.387616e+03, -1.151481e+03, 1.817672e+03, 2.243736e+04, 1.549500e+03, -2.094099e+03, 1.475644e+03, 2.256570e+04, -4.531227e+03, -1.034617e+03, 1.167963e+03, 2.267195e+04, -2.936346e+03, -1.036553e+03, 8.946197e+02, 2.276081e+04, -4.991516e+03, -5.847746e+02, 6.400900e+02, 2.283020e+04, -8.686370e+03, -8.226384e+00, 4.001762e+02, 2.288082e+04, -4.282608e+03, -6.966287e+01, 1.490135e+02, 2.291176e+04, -8.258616e+13, 9.904778e+08, 1.318286e+05, 7.747884e+02, 2.062665e+12, -4.786463e+08, 9.235644e+04, 7.769322e+02, -3.538830e+10, 2.205724e+07, 6.694206e+04, 7.847311e+02, 4.058662e+09, -3.295631e+06, 7.000223e+04, 8.077786e+02, -1.994471e+07, 1.416720e+06, 7.075137e+04, 8.521384e+02, -1.187269e+08, 1.283696e+06, 7.366460e+04, 9.280772e+02, 2.540619e+08, 2.026807e+05, 7.681548e+04, 1.046331e+03, -1.391960e+08, 1.579054e+06, 8.135576e+04, 1.218133e+03, 2.530622e+07, 5.920718e+05, 8.701200e+04, 1.465097e+03, -3.251666e+07, 8.728196e+05, 9.250368e+04, 1.800184e+03, -4.349050e+07, 7.754678e+05, 9.852956e+04, 2.248042e+03, -2.011892e+07, 3.930905e+05, 1.031312e+05, 2.827391e+03, -1.799797e+07, 2.525175e+05, 1.056848e+05, 3.545122e+03, -1.574729e+07, 1.139525e+05, 1.062387e+05, 4.406529e+03, -1.205118e+07, -2.983359e+04, 1.041875e+05, 5.405193e+03, -6.697812e+06, -1.674924e+05, 9.926112e+04, 6.519409e+03, -4.384345e+06, -2.195876e+05, 9.199400e+04, 7.714342e+03, -1.862072e+06, -2.540928e+05, 8.320020e+04, 8.954122e+03, -1.908592e+06, -2.218975e+05, 7.374786e+04, 1.020097e+04, -6.595484e+05, -2.191046e+05, 6.409677e+04, 1.142642e+04, 5.591668e+05, -2.065625e+05, 5.471249e+04, 1.259732e+04, -8.093373e+05, -1.264564e+05, 4.652504e+04, 1.369474e+04, 1.688527e+05, -1.334041e+05, 3.909025e+04, 1.472375e+04, 2.419749e+05, -1.045422e+05, 3.245138e+04, 1.565887e+04, -1.230208e+05, -6.804517e+04, 2.707154e+04, 1.650613e+04, 1.126806e+05, -6.300250e+04, 2.249086e+04, 1.727731e+04, -7.142991e+04, -4.118624e+04, 1.863553e+04, 1.796673e+04, 1.675606e+05, -4.267365e+04, 1.536107e+04, 1.858582e+04, -6.485362e+04, -2.110609e+04, 1.279192e+04, 1.913137e+04, 2.637560e+04, -2.212235e+04, 1.067530e+04, 1.962669e+04, 7.981750e+03, -1.608272e+04, 8.844225e+03, 2.006475e+04, 1.871909e+04, -1.315898e+04, 7.352146e+03, 2.045392e+04, -1.840475e+04, -8.056233e+03, 6.149474e+03, 2.079909e+04, 1.957039e+04, -9.075917e+03, 5.104541e+03, 2.110797e+04, -8.536233e+03, -4.982923e+03, 4.248788e+03, 2.137749e+04, 3.499200e+03, -5.020523e+03, 3.538293e+03, 2.161816e+04, -2.000849e+03, -3.512066e+03, 2.928448e+03, 2.182841e+04, 3.638545e+03, -3.264362e+03, 2.415994e+03, 2.201285e+04, -1.015257e+04, -1.420977e+03, 1.998918e+03, 2.217269e+04, 4.403337e+03, -2.590383e+03, 1.602086e+03, 2.231300e+04, -7.875874e+03, -7.971346e+02, 1.270059e+03, 2.242772e+04, 2.108760e+03, -1.686184e+03, 9.648043e+02, 2.252491e+04, -9.024057e+03, -1.121285e+02, 7.146217e+02, 2.259896e+04, -1.078560e+04, 5.370255e+01, 4.574484e+02, 2.265738e+04, -4.144847e+03, -1.351749e+02, 1.580973e+02, 2.269255e+04, -7.925848e+12, 7.954113e+07, 4.342033e+04, 2.306639e+02, 2.269955e+11, -6.495581e+07, 3.909724e+04, 2.313954e+02, 3.302993e+10, -1.552044e+07, 3.333664e+04, 2.355661e+02, -4.784910e+09, 7.541830e+06, 3.379938e+04, 2.459800e+02, 3.613537e+08, 7.051546e+05, 3.758040e+04, 2.693637e+02, 2.012123e+08, 9.047518e+05, 4.026196e+04, 3.100796e+02, -3.247217e+07, 1.458624e+06, 4.458575e+04, 3.762391e+02, 3.509220e+07, 1.133284e+06, 5.050532e+04, 4.804963e+02, -6.375528e+07, 1.554986e+06, 5.800171e+04, 6.381134e+02, -2.892941e+07, 1.197304e+06, 6.695868e+04, 8.734957e+02, -5.164969e+07, 1.213830e+06, 7.625104e+04, 1.209469e+03, -2.739672e+07, 7.928510e+05, 8.505819e+04, 1.674458e+03, -2.787464e+07, 6.247649e+05, 9.206065e+04, 2.284897e+03, -1.871019e+07, 3.383328e+05, 9.669688e+04, 3.055270e+03, -1.379705e+07, 1.369205e+05, 9.808678e+04, 3.981429e+03, -8.704135e+06, -3.571846e+04, 9.616835e+04, 5.046769e+03, -4.155272e+06, -1.581929e+05, 9.124700e+04, 6.219767e+03, -4.104771e+06, -1.676177e+05, 8.431879e+04, 7.461843e+03, -1.265230e+06, -2.229547e+05, 7.591780e+04, 8.739201e+03, -9.083431e+05, -2.002438e+05, 6.683417e+04, 1.000630e+04, -5.255757e+05, -1.783831e+05, 5.790308e+04, 1.123644e+04, 4.993118e+05, -1.719879e+05, 4.940310e+04, 1.240539e+04, -7.487545e+05, -9.942973e+04, 4.203530e+04, 1.349507e+04, 3.978438e+05, -1.195978e+05, 3.528825e+04, 1.451412e+04, -2.047206e+04, -7.632391e+04, 2.942983e+04, 1.543376e+04, 6.154258e+04, -6.346317e+04, 2.463164e+04, 1.627325e+04, -2.863798e+04, -4.606248e+04, 2.057180e+04, 1.703219e+04, 7.388099e+04, -4.085648e+04, 1.711248e+04, 1.771723e+04, -2.064163e+04, -2.712556e+04, 1.425554e+04, 1.832846e+04, 3.328744e+04, -2.433972e+04, 1.186725e+04, 1.887791e+04, 1.002028e+04, -1.754222e+04, 9.878580e+03, 1.936576e+04, 8.911729e+03, -1.374369e+04, 8.260222e+03, 1.980154e+04, -2.085488e+04, -9.181720e+03, 6.920058e+03, 2.019044e+04, 2.914076e+04, -1.070749e+04, 5.730227e+03, 2.053766e+04, -1.293038e+04, -5.174966e+03, 4.781798e+03, 2.083987e+04, 5.221232e+03, -5.721930e+03, 3.997709e+03, 2.111160e+04, 2.329131e+03, -4.209210e+03, 3.318380e+03, 2.134929e+04, -1.120600e+04, -2.323414e+03, 2.771525e+03, 2.155871e+04, 4.077728e+03, -3.348798e+03, 2.255768e+03, 2.174367e+04, -4.397494e+03, -1.781340e+03, 1.814239e+03, 2.189875e+04, -2.371566e+03, -1.679149e+03, 1.440870e+03, 2.203123e+04, -3.509356e+03, -1.211255e+03, 1.104800e+03, 2.213993e+04, -6.401342e+03, -6.643209e+02, 8.055120e+02, 2.222624e+04, -9.121022e+03, -1.798506e+02, 5.138316e+02, 2.229047e+04, -6.114652e+03, -5.727757e+01, 2.165918e+02, 2.233048e+04, 9.465569e+11, 2.157107e+07, 2.323822e+03, 3.141042e+01, -3.198079e+11, 7.414625e+07, 3.911285e+03, 3.146173e+01, 9.476628e+09, -4.475969e+06, 7.835770e+03, 3.245139e+01, -8.928972e+08, 1.881666e+06, 7.953473e+03, 3.487056e+01, 3.171872e+08, 2.635279e+05, 9.264064e+03, 4.047706e+01, -5.849106e+07, 9.732834e+05, 1.087038e+04, 5.087843e+01, 8.242971e+07, 6.037953e+05, 1.349207e+04, 7.009928e+01, -3.032662e+07, 1.159453e+06, 1.732089e+04, 1.033948e+02, -3.561716e+07, 1.251423e+06, 2.330419e+04, 1.629440e+02, -3.448639e+07, 1.286417e+06, 3.117127e+04, 2.657617e+02, -3.649510e+07, 1.300592e+06, 4.093241e+04, 4.359338e+02, -4.363745e+07, 1.276591e+06, 5.220971e+04, 7.050447e+02, -2.840810e+07, 9.451539e+05, 6.355126e+04, 1.108138e+03, -2.581926e+07, 7.360833e+05, 7.326328e+04, 1.668684e+03, -1.354418e+07, 3.883004e+05, 8.025788e+04, 2.403289e+03, -1.377454e+07, 2.590663e+05, 8.389776e+04, 3.304769e+03, -6.998331e+06, 2.378317e+04, 8.395422e+04, 4.361063e+03, -3.017568e+06, -1.031107e+05, 8.045998e+04, 5.528584e+03, -3.053944e+06, -1.159054e+05, 7.492129e+04, 6.765323e+03, -9.988790e+05, -1.670190e+05, 6.794613e+04, 8.038403e+03, -7.984465e+05, -1.523819e+05, 6.021692e+04, 9.302581e+03, -9.338634e+04, -1.494507e+05, 5.246052e+04, 1.053131e+04, -1.035431e+05, -1.215806e+05, 4.515398e+04, 1.169887e+04, -7.357601e+04, -9.990059e+04, 3.857402e+04, 1.279598e+04, 1.792570e+03, -8.319324e+04, 3.268700e+04, 1.381455e+04, 3.874347e+04, -6.749650e+04, 2.752666e+04, 1.474920e+04, 4.244814e+04, -5.329079e+04, 2.311818e+04, 1.560008e+04, -7.930994e+03, -3.984100e+04, 1.941511e+04, 1.637147e+04, 8.733277e+04, -3.589956e+04, 1.626214e+04, 1.706943e+04, -7.640893e+04, -1.973546e+04, 1.370832e+04, 1.769570e+04, 6.465562e+04, -2.412718e+04, 1.146747e+04, 1.826574e+04, -1.257959e+04, -1.387134e+04, 9.594876e+03, 1.876880e+04, -3.216704e+03, -1.199645e+04, 8.071823e+03, 1.922295e+04, 1.185898e+04, -1.055074e+04, 6.732374e+03, 1.962756e+04, -8.043290e+02, -7.356438e+03, 5.627495e+03, 1.998509e+04, -1.628058e+03, -5.891328e+03, 4.712682e+03, 2.030343e+04, -3.439586e+03, -4.645427e+03, 3.923985e+03, 2.058511e+04, 3.075924e+03, -4.271196e+03, 3.234865e+03, 2.083229e+04, -1.635081e+03, -2.923961e+03, 2.662415e+03, 2.104614e+04, -7.090127e+03, -1.933064e+03, 2.185308e+03, 2.123232e+04, -4.437563e+03, -1.933243e+03, 1.734860e+03, 2.139234e+04, -3.653738e+02, -1.892874e+03, 1.311083e+03, 2.152288e+04, -1.354368e+04, -1.252045e+02, 9.651989e+02, 2.162438e+04, -6.525776e+03, -7.519351e+02, 5.872714e+02, 2.170241e+04, -6.046958e+03, -1.425454e+02, 2.526236e+02, 2.174657e+04, 7.685478e+11, -3.587368e+06, -5.614277e+02, 2.176726e+00, -6.325697e+10, 1.540102e+07, 0, 2.169919e+00, 6.037976e+08, -1.269417e+05, 9.536601e+02, 2.283023e+00, -1.231879e+08, 2.884108e+05, 1.064814e+03, 2.602961e+00, 1.338161e+08, -3.138454e+04, 1.282376e+03, 3.367459e+00, -8.742091e+06, 3.029956e+05, 1.660242e+03, 4.836763e+00, 4.214728e+05, 3.431726e+05, 2.546292e+03, 8.152906e+00, -8.769409e+06, 4.935859e+05, 4.054901e+03, 1.537637e+01, -2.118875e+07, 7.043190e+05, 6.707452e+03, 3.116117e+01, -1.956295e+07, 8.532277e+05, 1.108718e+04, 6.499704e+01, -3.731153e+07, 1.135945e+06, 1.777807e+04, 1.334155e+02, -3.091261e+07, 1.121036e+06, 2.709678e+04, 2.649024e+02, -3.270901e+07, 1.105922e+06, 3.809708e+04, 4.929304e+02, -2.200409e+07, 8.529194e+05, 4.956525e+04, 8.559269e+02, -2.038642e+07, 6.855276e+05, 5.978076e+04, 1.380667e+03, -1.117204e+07, 3.795010e+05, 6.745803e+04, 2.085776e+03, -9.901093e+06, 2.365954e+05, 7.171413e+04, 2.961349e+03, -4.354972e+06, 3.054048e+04, 7.248689e+04, 3.990590e+03, -3.140714e+06, -3.946535e+04, 7.017581e+04, 5.129246e+03, -1.994865e+06, -9.051388e+04, 6.582553e+04, 6.341791e+03, -5.803806e+05, -1.294484e+05, 5.994991e+04, 7.586278e+03, -8.405790e+05, -1.086236e+05, 5.349962e+04, 8.822279e+03, 2.303613e+05, -1.273856e+05, 4.686398e+04, 1.002781e+04, -4.101851e+05, -8.285763e+04, 4.066681e+04, 1.117171e+04, 2.025071e+05, -9.176353e+04, 3.492952e+04, 1.225612e+04, -1.241871e+05, -6.014883e+04, 2.981741e+04, 1.325813e+04, 7.450568e+04, -5.766421e+04, 2.535029e+04, 1.418817e+04, -3.498195e+04, -4.081103e+04, 2.145641e+04, 1.503639e+04, 5.737509e+04, -3.728994e+04, 1.810341e+04, 1.581109e+04, 1.553564e+04, -2.696393e+04, 1.527417e+04, 1.651003e+04, -3.264956e+04, -1.915601e+04, 1.294140e+04, 1.714428e+04, 2.039836e+04, -1.885321e+04, 1.087146e+04, 1.771893e+04, 3.616331e+04, -1.547233e+04, 9.097636e+03, 1.822993e+04, -4.400956e+04, -6.947860e+03, 7.730975e+03, 1.868663e+04, 2.524433e+04, -1.107087e+04, 6.479718e+03, 1.910332e+04, -1.159559e+04, -5.722883e+03, 5.403721e+03, 1.946613e+04, 8.803311e+03, -6.362971e+03, 4.509957e+03, 1.979080e+04, -7.832658e+03, -3.602953e+03, 3.758517e+03, 2.007421e+04, -6.382527e+03, -3.252304e+03, 3.110174e+03, 2.032548e+04, 1.111503e+03, -3.330009e+03, 2.499038e+03, 2.054191e+04, -6.645172e+03, -1.857684e+03, 1.983350e+03, 2.072246e+04, -4.647336e+02, -2.123280e+03, 1.524736e+03, 2.087328e+04, -1.619462e+04, -7.161461e+01, 1.135444e+03, 2.099191e+04, -1.145722e+04, -5.148367e+02, 6.981336e+02, 2.108415e+04, -8.317955e+03, -3.174918e+01, 2.682136e+02, 2.113680e+04, 6.686770e+09, -5.232905e+04, 9.004540e+01, 8.220978e-02, -1.221062e+09, 1.938090e+05, 9.420210e+01, 8.378067e-02, 9.327238e+07, -6.870038e+04, 8.763799e+01, 9.582414e-02, 5.996937e+07, -4.274478e+04, 7.265223e+01, 1.204347e-01, -1.133786e+07, 6.147611e+04, 9.131150e+01, 1.649432e-01, 3.386784e+05, 5.305621e+04, 1.829889e+02, 3.157484e-01, 3.484062e+06, 8.082698e+04, 3.519414e+02, 7.346517e-01, -8.136297e+06, 2.145670e+05, 7.559280e+02, 1.929050e+00, -1.422495e+07, 3.782352e+05, 1.798927e+03, 5.751019e+00, -1.921481e+07, 5.817554e+05, 4.031473e+03, 1.702790e+01, -2.466374e+07, 8.092501e+05, 8.208813e+03, 4.659724e+01, -2.957367e+07, 9.988951e+05, 1.503472e+04, 1.151984e+02, -2.934849e+07, 1.043498e+06, 2.455141e+04, 2.553897e+02, -2.437625e+07, 9.281228e+05, 3.566919e+04, 5.065714e+02, -1.808598e+07, 7.249953e+05, 4.667018e+04, 9.049815e+02, -1.413967e+07, 5.250627e+05, 5.602253e+04, 1.475116e+03, -9.253251e+06, 3.021326e+05, 6.252165e+04, 2.225350e+03, -4.436136e+06, 1.093543e+05, 6.552585e+04, 3.139939e+03, -4.814005e+06, 5.669314e+04, 6.565072e+04, 4.187778e+03, -1.840489e+06, -6.337635e+04, 6.313183e+04, 5.341067e+03, -6.904183e+05, -1.012176e+05, 5.850287e+04, 6.544246e+03, -7.497582e+05, -9.311380e+04, 5.312391e+04, 7.761001e+03, -4.210654e+05, -9.618680e+04, 4.738566e+04, 8.967658e+03, 8.995083e+04, -9.946898e+04, 4.148243e+04, 1.013491e+04, -2.075976e+05, -7.103257e+04, 3.602031e+04, 1.124072e+04, 8.338291e+04, -7.078879e+04, 3.100960e+04, 1.228431e+04, -2.730415e+04, -5.205078e+04, 2.653114e+04, 1.325030e+04, 2.150946e+04, -4.459231e+04, 2.264211e+04, 1.414394e+04, -1.423980e+04, -3.417936e+04, 1.925258e+04, 1.496260e+04, 1.473821e+04, -2.918906e+04, 1.630554e+04, 1.571000e+04, 3.220392e+04, -2.405451e+04, 1.376762e+04, 1.638610e+04, -2.684524e+04, -1.571254e+04, 1.167668e+04, 1.699638e+04, 3.088042e+04, -1.651758e+04, 9.851958e+03, 1.755058e+04, -1.721349e+04, -9.750730e+03, 8.323807e+03, 1.804451e+04, 1.345637e+04, -1.027197e+04, 7.017991e+03, 1.849141e+04, -2.174811e+04, -5.602956e+03, 5.906349e+03, 1.888762e+04, 1.177125e+04, -7.439854e+03, 4.898836e+03, 1.924275e+04, 1.647970e+03, -4.795697e+03, 4.041270e+03, 1.954881e+04, -5.843917e+03, -3.222697e+03, 3.369872e+03, 1.981799e+04, -9.789821e+03, -2.446804e+03, 2.772770e+03, 2.005474e+04, -1.378097e+03, -2.879752e+03, 2.186681e+03, 2.025740e+04, -6.290251e+03, -1.724383e+03, 1.668369e+03, 2.042133e+04, -1.101343e+04, -9.097999e+02, 1.211492e+03, 2.055181e+04, -1.111452e+04, -5.639870e+02, 7.532181e+02, 2.064806e+04, -8.320836e+03, -1.432660e+02, 3.235242e+02, 2.070595e+04, 0, 0, 0, 0, 0, 0, 0, 0, -1.472727e+07, 9.704940e+03, 0, 0, -2.351848e+05, 1.879504e+02, 1.617783e+00, 5.236292e-04, 8.699198e+05, -9.875575e+02, 1.570521e+00, 1.570887e-03, -6.250379e+05, 4.145386e+03, 2.379199e+00, 3.141775e-03, 4.286236e+05, 4.412056e+03, 1.077048e+01, 1.466162e-02, -2.043447e+06, 3.157819e+04, 3.625093e+01, 6.388276e-02, -1.085061e+06, 6.162908e+04, 1.682113e+02, 3.869620e-01, -6.697354e+06, 1.915110e+05, 5.837246e+02, 1.821706e+00, -1.347910e+07, 3.939200e+05, 1.934535e+03, 8.045039e+00, -1.740487e+07, 5.943821e+05, 5.113283e+03, 2.940335e+01, -2.005659e+07, 7.567963e+05, 1.080316e+04, 8.665382e+01, -1.933757e+07, 8.074300e+05, 1.910717e+04, 2.128584e+02, -1.922524e+07, 7.785521e+05, 2.917605e+04, 4.485973e+02, -1.197210e+07, 5.629568e+05, 3.928913e+04, 8.333176e+02, -9.951533e+06, 4.244022e+05, 4.773463e+04, 1.385596e+03, -6.709627e+06, 2.506304e+05, 5.376726e+04, 2.114235e+03, -3.571100e+06, 9.933375e+04, 5.665657e+04, 3.002215e+03, -2.574425e+06, 2.579319e+04, 5.681603e+04, 4.016538e+03, -1.456834e+06, -3.525546e+04, 5.484294e+04, 5.124406e+03, -8.939211e+05, -6.390266e+04, 5.124523e+04, 6.284900e+03, -1.101180e+05, -8.746416e+04, 4.665656e+04, 7.461369e+03, -4.681458e+05, -6.529437e+04, 4.184970e+04, 8.621092e+03, -4.045757e+03, -7.596463e+04, 3.697388e+04, 9.752269e+03, -1.734660e+04, -6.231731e+04, 3.224549e+04, 1.082680e+04, -9.987665e+04, -4.861101e+04, 2.799504e+04, 1.184010e+04, 7.265535e+04, -4.826171e+04, 2.406867e+04, 1.278797e+04, -1.134999e+04, -3.441852e+04, 2.062683e+04, 1.365988e+04, 6.090832e+03, -2.914563e+04, 1.767500e+04, 1.446480e+04, -6.974627e+02, -2.329559e+04, 1.508844e+04, 1.520183e+04, -1.472800e+04, -1.825859e+04, 1.284207e+04, 1.587375e+04, 3.206836e+04, -1.770135e+04, 1.085176e+04, 1.648269e+04, -2.032028e+03, -1.153400e+04, 9.204911e+03, 1.702789e+04, -2.968679e+04, -7.797147e+03, 7.845514e+03, 1.752289e+04, 3.245165e+04, -1.117046e+04, 6.548123e+03, 1.796936e+04, -1.709462e+04, -4.558688e+03, 5.505584e+03, 1.835768e+04, -9.796017e+03, -4.811111e+03, 4.633948e+03, 1.870978e+04, 3.674447e+03, -5.128812e+03, 3.778722e+03, 1.901758e+04, 1.967537e+02, -3.600181e+03, 3.057183e+03, 1.927876e+04, -1.317163e+04, -1.679278e+03, 2.480028e+03, 1.950210e+04, -2.183190e+03, -2.611229e+03, 1.910794e+03, 1.969236e+04, -1.531156e+04, -6.658682e+02, 1.393683e+03, 1.984029e+04, -1.371122e+04, -5.957229e+02, 8.684685e+02, 1.995218e+04, -1.023819e+04, -8.502304e+01, 3.579622e+02, 2.001862e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -9.585623e+03, 2.130250e+02, 0, 0, -1.935079e+05, 3.900197e+03, 9.971148e-01, 1.570887e-03, -6.527066e+05, 1.858015e+04, 2.205255e+01, 4.974477e-02, -1.500053e+06, 6.028248e+04, 1.529140e+02, 4.916878e-01, -4.974313e+06, 1.764505e+05, 6.943200e+02, 3.048045e+00, -8.678217e+06, 3.342531e+05, 2.410493e+03, 1.446892e+01, -1.052839e+07, 4.688102e+05, 6.113438e+03, 5.121774e+01, -1.280428e+07, 5.701865e+05, 1.214618e+04, 1.417166e+02, -9.465653e+06, 5.125406e+05, 2.000545e+04, 3.248129e+02, -9.176467e+06, 4.685079e+05, 2.835925e+04, 6.344485e+02, -6.639283e+06, 3.383421e+05, 3.609536e+04, 1.101131e+03, -3.945560e+06, 2.017257e+05, 4.181661e+04, 1.731452e+03, -3.291661e+06, 1.255684e+05, 4.524933e+04, 2.513072e+03, -1.322687e+06, 2.510134e+04, 4.636870e+04, 3.426583e+03, -1.300582e+06, 1.614129e+03, 4.558508e+04, 4.432770e+03, -4.698930e+05, -4.109357e+04, 4.343189e+04, 5.505804e+03, -4.863562e+05, -4.316647e+04, 4.031339e+04, 6.606426e+03, -1.901139e+05, -5.444630e+04, 3.665707e+04, 7.711348e+03, 5.980810e+04, -5.772322e+04, 3.272677e+04, 8.791214e+03, -1.495518e+05, -3.987647e+04, 2.904712e+04, 9.828835e+03, -6.078588e+04, -3.976407e+04, 2.555865e+04, 1.082406e+04, 5.486112e+04, -3.893029e+04, 2.216912e+04, 1.175926e+04, 1.144987e+04, -2.896840e+04, 1.918876e+04, 1.262592e+04, -5.371250e+04, -2.059823e+04, 1.665072e+04, 1.343193e+04, 5.297801e+04, -2.371871e+04, 1.429575e+04, 1.417935e+04, -5.458191e+04, -1.220823e+04, 1.227995e+04, 1.485766e+04, 2.920703e+04, -1.633866e+04, 1.045753e+04, 1.548314e+04, -2.082029e+03, -1.050044e+04, 8.856110e+03, 1.604077e+04, -2.664664e+03, -8.621342e+03, 7.539708e+03, 1.654564e+04, -1.404636e+04, -6.326128e+03, 6.381937e+03, 1.699969e+04, 1.024075e+04, -7.296601e+03, 5.310162e+03, 1.740478e+04, -1.510660e+04, -3.541083e+03, 4.411345e+03, 1.775632e+04, 3.804952e+03, -4.830017e+03, 3.602141e+03, 1.806686e+04, -1.490810e+04, -2.032319e+03, 2.896991e+03, 1.832807e+04, -1.242364e+03, -3.160581e+03, 2.230378e+03, 1.855009e+04, -1.894988e+04, -6.198991e+02, 1.637798e+03, 1.872279e+04, -1.737924e+04, -5.863084e+02, 1.025930e+03, 1.885493e+04, -1.268231e+04, -3.096204e+01, 4.118873e+02, 1.893342e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -5.049934e+03, 5.631291e+01, 0, 0, 6.967623e+03, 1.862467e+01, 2.093108e-01, 5.236292e-04, -7.322636e+04, 2.442067e+03, 8.394707e-01, 2.618146e-03, -3.181040e+05, 1.374125e+04, 2.155526e+01, 7.330808e-02, -1.148779e+06, 5.153572e+04, 1.649367e+02, 7.624041e-01, -2.733073e+06, 1.274952e+05, 7.729699e+02, 4.857184e+00, -4.098947e+06, 2.168990e+05, 2.448323e+03, 2.118970e+01, -5.332313e+06, 2.988307e+05, 5.711927e+03, 6.820689e+01, -5.635984e+06, 3.325101e+05, 1.066895e+04, 1.751199e+02, -4.580008e+06, 3.018134e+05, 1.668111e+04, 3.755809e+02, -3.996023e+06, 2.577529e+05, 2.279537e+04, 6.973693e+02, -2.766915e+06, 1.817487e+05, 2.816438e+04, 1.159531e+03, -1.990806e+06, 1.182930e+05, 3.210268e+04, 1.762734e+03, -1.289423e+06, 6.188542e+04, 3.442340e+04, 2.495993e+03, -8.057612e+05, 2.131305e+04, 3.517139e+04, 3.336770e+03, -4.410684e+05, -6.496765e+03, 3.463019e+04, 4.257853e+03, -4.309360e+05, -1.502963e+04, 3.317952e+04, 5.231419e+03, -1.311448e+05, -3.210778e+04, 3.100030e+04, 6.234108e+03, -4.415939e+04, -3.380143e+04, 2.839568e+04, 7.235375e+03, -1.499349e+05, -2.599550e+04, 2.576558e+04, 8.220003e+03, 1.383474e+04, -3.242390e+04, 2.304396e+04, 9.179023e+03, -2.218020e+04, -2.541662e+04, 2.039304e+04, 1.009087e+04, -1.073837e+04, -2.250757e+04, 1.797035e+04, 1.095521e+04, -2.943186e+03, -1.953326e+04, 1.573007e+04, 1.176649e+04, -1.123711e+04, -1.592828e+04, 1.370204e+04, 1.252187e+04, 2.490499e+03, -1.435292e+04, 1.186123e+04, 1.322100e+04, -1.794959e+04, -1.053958e+04, 1.022032e+04, 1.386157e+04, 7.179634e+03, -1.085313e+04, 8.718724e+03, 1.444657e+04, 8.523870e+02, -8.182112e+03, 7.395488e+03, 1.497070e+04, -1.097305e+04, -5.802531e+03, 6.280139e+03, 1.544169e+04, -8.647890e+03, -5.258780e+03, 5.262032e+03, 1.586351e+04, -5.795295e+03, -4.678129e+03, 4.303340e+03, 1.623208e+04, -6.554213e+03, -3.732850e+03, 3.435184e+03, 1.654581e+04, -7.571927e+03, -2.901504e+03, 2.660403e+03, 1.680635e+04, -2.053198e+04, -1.047036e+03, 1.963335e+03, 1.701494e+04, -2.185000e+04, -5.709901e+02, 1.230253e+03, 1.717247e+04, -1.551733e+04, -6.146695e+00, 4.907671e+02, 1.726691e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -7.205704e+02, 2.019571e+01, 0, 0, 5.648551e+02, 8.455095e+01, 1.600871e-01, 5.236292e-04, -2.062497e+04, 1.347926e+03, 1.396682e+00, 5.759921e-03, -1.861333e+05, 9.330316e+03, 1.914727e+01, 9.425325e-02, -4.557963e+05, 2.826252e+04, 1.454540e+02, 9.482924e-01, -9.818830e+05, 6.498886e+04, 5.985040e+02, 5.287607e+00, -1.707438e+06, 1.141619e+05, 1.758923e+03, 2.087971e+01, -2.036629e+06, 1.496179e+05, 3.958518e+03, 6.352460e+01, -2.012618e+06, 1.637584e+05, 7.165573e+03, 1.556844e+02, -1.950650e+06, 1.617404e+05, 1.107139e+04, 3.226943e+02, -1.667168e+06, 1.387401e+05, 1.516993e+04, 5.881769e+02, -1.142383e+06, 1.009370e+05, 1.883831e+04, 9.663550e+02, -7.952061e+05, 6.944554e+04, 2.170582e+04, 1.458843e+03, -7.726009e+05, 5.004691e+04, 2.370696e+04, 2.060531e+03, -2.850905e+05, 1.452110e+04, 2.467497e+04, 2.760501e+03, -3.098623e+05, 7.430022e+03, 2.475227e+04, 3.532009e+03, -2.339934e+05, -3.779062e+03, 2.420063e+04, 4.361069e+03, 9.185211e+03, -1.890242e+04, 2.300010e+04, 5.223842e+03, -1.739850e+05, -8.944235e+03, 2.156361e+04, 6.095069e+03, -2.235243e+04, -1.943860e+04, 1.989104e+04, 6.972243e+03, 1.198136e+04, -1.908709e+04, 1.800541e+04, 7.826082e+03, -5.284415e+04, -1.280211e+04, 1.625202e+04, 8.649491e+03, 7.936083e+03, -1.590172e+04, 1.452061e+04, 9.442641e+03, -3.481822e+04, -1.076757e+04, 1.285434e+04, 1.018969e+04, 2.668691e+04, -1.397913e+04, 1.125258e+04, 1.089268e+04, -4.318571e+04, -6.253629e+03, 9.834934e+03, 1.153860e+04, 1.098736e+04, -1.042348e+04, 8.469408e+03, 1.214108e+04, -2.425142e+02, -7.313199e+03, 7.189537e+03, 1.267873e+04, -2.017386e+04, -4.486061e+03, 6.121964e+03, 1.316283e+04, -2.992189e+03, -5.709493e+03, 5.078553e+03, 1.359667e+04, -9.666249e+03, -3.987421e+03, 4.098707e+03, 1.396771e+04, -1.813279e+04, -2.576703e+03, 3.213557e+03, 1.428080e+04, -1.133652e+04, -2.823670e+03, 2.323008e+03, 1.453377e+04, -3.741587e+04, 7.057299e+02, 1.498721e+03, 1.471689e+04, -1.584264e+04, -3.098032e+02, 5.619166e+02, 1.483525e+04, }; static float solarDataset640[] = { -4.439940e+13, 4.727269e+08, 1.531960e+05, 2.789585e+03, 1.591240e+12, -3.752929e+08, 1.299147e+05, 2.792139e+03, -1.520825e+10, 9.464386e+06, 1.088507e+05, 2.805146e+03, 4.968166e+09, -3.484485e+06, 1.101562e+05, 2.841278e+03, -1.879797e+09, 4.089612e+06, 1.117743e+05, 2.911407e+03, 3.175884e+08, -3.936103e+05, 1.141396e+05, 3.031274e+03, -1.247720e+08, 7.638848e+05, 1.152491e+05, 3.210576e+03, -5.488648e+07, 3.411906e+05, 1.167998e+05, 3.465231e+03, 7.500485e+07, -2.624350e+05, 1.173902e+05, 3.807030e+03, -7.626345e+07, 6.188938e+05, 1.185754e+05, 4.246394e+03, -3.559987e+07, 1.218147e+05, 1.193649e+05, 4.806045e+03, -5.712451e+04, -2.445439e+05, 1.172780e+05, 5.484460e+03, -2.917238e+07, 2.280130e+04, 1.139230e+05, 6.275571e+03, -5.538333e+06, -3.268659e+05, 1.085716e+05, 7.182661e+03, -1.121999e+07, -2.401591e+05, 1.009303e+05, 8.172688e+03, -2.076868e+06, -3.706500e+05, 9.172349e+04, 9.227661e+03, -3.291261e+06, -2.970064e+05, 8.154785e+04, 1.030640e+04, -1.434784e+06, -2.886252e+05, 7.122383e+04, 1.138676e+04, -1.028562e+06, -2.454059e+05, 6.099909e+04, 1.243693e+04, 5.490447e+05, -2.301291e+05, 5.134306e+04, 1.343419e+04, -3.430376e+05, -1.558810e+05, 4.292772e+04, 1.435918e+04, 1.571421e+03, -1.323344e+05, 3.566474e+04, 1.521511e+04, 9.796970e+04, -1.046920e+05, 2.933950e+04, 1.599219e+04, 3.387552e+04, -7.798390e+04, 2.405845e+04, 1.669041e+04, 8.586974e+04, -6.144906e+04, 1.968644e+04, 1.731476e+04, 2.430737e+04, -4.445872e+04, 1.611932e+04, 1.786927e+04, 8.554925e+04, -3.643019e+04, 1.321141e+04, 1.836202e+04, -4.184780e+04, -2.225372e+04, 1.090368e+04, 1.879790e+04, 1.450911e+04, -2.047436e+04, 8.970817e+03, 1.918782e+04, 5.758854e+04, -1.762438e+04, 7.327434e+03, 1.952962e+04, -2.647884e+04, -8.760163e+03, 6.090933e+03, 1.982896e+04, 9.619644e+03, -9.392713e+03, 5.064150e+03, 2.009878e+04, 1.331023e+04, -7.397082e+03, 4.176136e+03, 2.033522e+04, -1.686056e+04, -3.825364e+03, 3.487137e+03, 2.054344e+04, 1.693753e+04, -5.541195e+03, 2.872701e+03, 2.072965e+04, -8.264414e+03, -2.280044e+03, 2.383048e+03, 2.088944e+04, 4.622434e+03, -2.963743e+03, 1.980519e+03, 2.103278e+04, -5.561131e+03, -1.469762e+03, 1.637947e+03, 2.115668e+04, -5.453383e+02, -1.717846e+03, 1.335926e+03, 2.126589e+04, -4.010140e+02, -1.347042e+03, 1.062944e+03, 2.135796e+04, 1.078165e+02, -1.080735e+03, 8.377248e+02, 2.143475e+04, -4.695232e+03, -3.873397e+02, 6.567006e+02, 2.149810e+04, -3.120412e+03, -5.195693e+02, 4.759587e+02, 2.155020e+04, -6.441655e+03, 1.058743e+00, 2.972071e+02, 2.158758e+04, -3.280148e+03, -4.465469e+01, 1.123506e+02, 2.161064e+04, -2.992526e+13, 3.093632e+08, 1.285107e+05, 1.370598e+03, 1.480405e+12, -3.114235e+08, 1.125000e+05, 1.372752e+03, -1.218458e+11, 6.632321e+07, 1.020083e+05, 1.384393e+03, 1.665317e+10, -1.847940e+07, 1.062419e+05, 1.420637e+03, -9.113149e+08, 3.008784e+06, 1.029925e+05, 1.485201e+03, 1.490734e+08, 6.212466e+05, 1.062972e+05, 1.595766e+03, -1.105384e+08, 1.142941e+06, 1.093467e+05, 1.764612e+03, -5.228906e+06, 5.746185e+05, 1.127616e+05, 2.008312e+03, -4.552848e+07, 6.442601e+05, 1.159764e+05, 2.341555e+03, -3.742689e+07, 4.419059e+05, 1.188852e+05, 2.782009e+03, -3.101838e+07, 2.582848e+05, 1.205636e+05, 3.343203e+03, -2.861615e+07, 1.118720e+05, 1.204816e+05, 4.033752e+03, -1.284625e+07, -1.383981e+05, 1.179923e+05, 4.854326e+03, -1.827905e+07, -1.249114e+05, 1.132356e+05, 5.792405e+03, -3.759817e+06, -3.523765e+05, 1.060046e+05, 6.833684e+03, -8.330140e+06, -2.577154e+05, 9.700446e+04, 7.940175e+03, -1.445189e+06, -3.560434e+05, 8.673825e+04, 9.089991e+03, -2.022213e+06, -2.868506e+05, 7.584981e+04, 1.023690e+04, -2.065185e+05, -2.739897e+05, 6.523903e+04, 1.135845e+04, -2.118780e+05, -2.174656e+05, 5.534385e+04, 1.242638e+04, -3.909280e+05, -1.684039e+05, 4.654358e+04, 1.342916e+04, 1.510131e+05, -1.471904e+05, 3.866829e+04, 1.435729e+04, 1.105359e+05, -1.114876e+05, 3.188896e+04, 1.519973e+04, 2.486681e+04, -8.288938e+04, 2.627788e+04, 1.596027e+04, 8.548810e+04, -6.590200e+04, 2.160359e+04, 1.664380e+04, 1.020428e+04, -4.763506e+04, 1.775888e+04, 1.725353e+04, 9.132896e+04, -3.989775e+04, 1.458947e+04, 1.779729e+04, -5.893551e+04, -2.401330e+04, 1.205272e+04, 1.827892e+04, 8.786788e+04, -2.590156e+04, 9.903800e+03, 1.871007e+04, -4.375724e+04, -1.286701e+04, 8.192812e+03, 1.908692e+04, 3.806013e+04, -1.494288e+04, 6.768657e+03, 1.942561e+04, -2.022679e+04, -7.996085e+03, 5.595118e+03, 1.972091e+04, 4.406976e+04, -1.028506e+04, 4.614651e+03, 1.998424e+04, -3.557882e+04, -2.482117e+03, 3.885495e+03, 2.021282e+04, 1.494002e+04, -6.049385e+03, 3.237819e+03, 2.042301e+04, -4.199329e+03, -3.113389e+03, 2.662895e+03, 2.060288e+04, 3.034471e+03, -3.103970e+03, 2.203542e+03, 2.076205e+04, 1.633791e+03, -2.268264e+03, 1.819033e+03, 2.090013e+04, -1.012340e+04, -8.623465e+02, 1.515031e+03, 2.102106e+04, 2.750467e+03, -2.003038e+03, 1.204360e+03, 2.112756e+04, -6.190024e-03, -1.186111e+03, 9.348330e+02, 2.121315e+04, -5.805871e+03, -3.823047e+02, 7.336037e+02, 2.128391e+04, -3.542666e+03, -5.948154e+02, 5.273264e+02, 2.134212e+04, -5.934580e+03, -1.228610e+02, 3.234636e+02, 2.138330e+04, -4.084604e+03, -1.983933e+00, 1.289217e+02, 2.140821e+04, -3.727579e+12, 5.679231e+08, -1.625664e+04, 4.250653e+02, -4.419365e+12, 1.046109e+09, 0, 4.249347e+02, 3.326869e+10, -2.023689e+07, 5.941925e+04, 4.324018e+02, 3.471040e+09, -1.203176e+06, 5.686938e+04, 4.508607e+02, -6.372727e+08, 3.160899e+06, 5.957054e+04, 4.875431e+02, 2.755881e+08, 1.055176e+06, 6.410412e+04, 5.529359e+02, -1.275647e+08, 1.970311e+06, 6.944887e+04, 6.571524e+02, 5.075274e+07, 1.126893e+06, 7.624159e+04, 8.172947e+02, -8.482724e+07, 1.658999e+06, 8.409947e+04, 1.050219e+03, -6.311669e+07, 1.260619e+06, 9.295005e+04, 1.383576e+03, -4.552108e+07, 8.872372e+05, 1.005958e+05, 1.838863e+03, -3.875198e+07, 6.047687e+05, 1.062746e+05, 2.433263e+03, -1.845368e+07, 2.163822e+05, 1.091074e+05, 3.176447e+03, -2.407756e+07, 1.539447e+05, 1.089878e+05, 4.062922e+03, -9.843639e+06, -1.515457e+05, 1.054688e+05, 5.084079e+03, -6.115161e+06, -2.330786e+05, 9.867827e+04, 6.200673e+03, -4.041083e+06, -2.626724e+05, 9.005089e+04, 7.379350e+03, -2.210499e+06, -2.717189e+05, 8.024778e+04, 8.584178e+03, -7.206211e+05, -2.613685e+05, 6.997467e+04, 9.778451e+03, -3.314310e+05, -2.216301e+05, 6.004300e+04, 1.093132e+04, -3.603027e+05, -1.775358e+05, 5.094016e+04, 1.202401e+04, 1.605319e+04, -1.514987e+05, 4.271129e+04, 1.304370e+04, 2.002792e+05, -1.228584e+05, 3.549450e+04, 1.397850e+04, -8.648454e+04, -8.570485e+04, 2.947253e+04, 1.482726e+04, 1.357791e+05, -7.475766e+04, 2.436487e+04, 1.559714e+04, -3.989941e+03, -5.194180e+04, 2.011571e+04, 1.628557e+04, 8.306635e+04, -4.386703e+04, 1.660847e+04, 1.690318e+04, -2.096461e+04, -2.912937e+04, 1.375069e+04, 1.745251e+04, 5.301057e+04, -2.639084e+04, 1.137582e+04, 1.794452e+04, -3.157995e+04, -1.607394e+04, 9.439187e+03, 1.837976e+04, 5.385344e+04, -1.741312e+04, 7.800361e+03, 1.876916e+04, -2.015355e+04, -8.869094e+03, 6.498800e+03, 1.911013e+04, -2.198646e+03, -8.557864e+03, 5.429310e+03, 1.941755e+04, 2.183501e+04, -8.210271e+03, 4.474652e+03, 1.968824e+04, -1.617257e+04, -3.638040e+03, 3.742270e+03, 1.992456e+04, 1.241488e+04, -5.232775e+03, 3.110539e+03, 2.013736e+04, -1.201730e+04, -2.114134e+03, 2.586648e+03, 2.032131e+04, 4.745978e+03, -3.261955e+03, 2.124178e+03, 2.048556e+04, 1.127970e+03, -2.123757e+03, 1.725024e+03, 2.062462e+04, -7.597785e+03, -9.417226e+02, 1.419309e+03, 2.074488e+04, 1.883744e+03, -1.753948e+03, 1.118928e+03, 2.084928e+04, -6.322678e+03, -5.176974e+02, 8.620266e+02, 2.093272e+04, -1.605836e+03, -9.285398e+02, 6.193314e+02, 2.100093e+04, -1.097960e+04, 3.171899e+02, 4.038220e+02, 2.104937e+04, -4.141973e+03, -9.836002e+01, 1.504665e+02, 2.108164e+04, -2.330422e+13, 2.884024e+08, 3.068028e+04, 6.138150e+01, 4.881998e+11, -1.148322e+08, 1.984912e+04, 6.187669e+01, 1.916792e+09, 9.729664e+05, 1.346125e+04, 6.345753e+01, -6.675440e+08, 2.022162e+06, 1.471542e+04, 6.803805e+01, 3.159170e+08, 5.956514e+05, 1.648024e+04, 7.807293e+01, 1.478614e+08, 9.030786e+05, 1.878080e+04, 9.642790e+01, -3.518216e+07, 1.443802e+06, 2.270551e+04, 1.286811e+02, 1.119347e+07, 1.312378e+06, 2.852122e+04, 1.849385e+02, -7.701323e+07, 1.801352e+06, 3.645263e+04, 2.794408e+02, -4.292657e+07, 1.527104e+06, 4.669619e+04, 4.369697e+02, -5.878099e+07, 1.547497e+06, 5.815348e+04, 6.840577e+02, -4.645158e+07, 1.228475e+06, 7.007176e+04, 1.055326e+03, -3.318499e+07, 8.600360e+05, 8.035939e+04, 1.577501e+03, -2.625219e+07, 5.584589e+05, 8.775849e+04, 2.265846e+03, -1.490142e+07, 2.204949e+05, 9.128794e+04, 3.120972e+03, -9.255229e+06, 2.252877e+04, 9.079563e+04, 4.120827e+03, -7.977564e+06, -6.768208e+04, 8.706674e+04, 5.234990e+03, -1.201566e+06, -2.257152e+05, 8.041358e+04, 6.425469e+03, -2.557683e+06, -1.738737e+05, 7.235760e+04, 7.637924e+03, -6.451356e+05, -2.017795e+05, 6.379658e+04, 8.850205e+03, -3.054659e+05, -1.757830e+05, 5.511053e+04, 1.002201e+04, 4.282739e+03, -1.507765e+05, 4.703559e+04, 1.113375e+04, -6.875119e+04, -1.179384e+05, 3.983315e+04, 1.217219e+04, -6.539296e+04, -9.429366e+04, 3.351548e+04, 1.313309e+04, 1.390880e+05, -8.139794e+04, 2.796880e+04, 1.401195e+04, 1.433916e+04, -5.814147e+04, 2.331691e+04, 1.480596e+04, 4.800799e+04, -4.699949e+04, 1.945486e+04, 1.552491e+04, 3.355324e+04, -3.590662e+04, 1.623079e+04, 1.617181e+04, -4.753516e+04, -2.457913e+04, 1.357598e+04, 1.675372e+04, 4.184174e+04, -2.433031e+04, 1.125925e+04, 1.727713e+04, 1.681958e+04, -1.719019e+04, 9.323416e+03, 1.773841e+04, 1.359243e+04, -1.318457e+04, 7.786144e+03, 1.814905e+04, -1.223584e+04, -8.858780e+03, 6.540344e+03, 1.851573e+04, 6.675612e+03, -8.506817e+03, 5.462955e+03, 1.884458e+04, 9.691761e+03, -6.794523e+03, 4.542950e+03, 1.913430e+04, -1.311304e+04, -3.705444e+03, 3.816631e+03, 1.939046e+04, 3.177047e+03, -4.478421e+03, 3.166507e+03, 1.961984e+04, 1.744567e+02, -3.216510e+03, 2.594630e+03, 1.981779e+04, -3.774980e+03, -2.236340e+03, 2.129548e+03, 1.998954e+04, 7.002038e+02, -2.227548e+03, 1.720140e+03, 2.013795e+04, -5.785630e+03, -1.144891e+03, 1.374334e+03, 2.026261e+04, -1.111106e+03, -1.431800e+03, 1.055204e+03, 2.036742e+04, -9.405081e+03, -2.669856e+02, 7.737057e+02, 2.044926e+04, -7.953502e+03, -3.131021e+02, 4.776272e+02, 2.051154e+04, -5.955234e+03, -2.333631e+00, 1.878496e+02, 2.054783e+04, 5.900736e+12, -6.184322e+07, -3.127993e+03, 4.662247e+00, -2.586883e+11, 5.655632e+07, 0, 4.620175e+00, 6.674828e+09, -3.908526e+06, 2.349221e+03, 4.989151e+00, 1.823458e+08, 2.419007e+05, 1.936986e+03, 5.573806e+00, -9.320896e+07, 5.604882e+05, 2.468082e+03, 6.954925e+00, 7.579802e+07, 2.506737e+05, 3.337623e+03, 1.006148e+01, -1.611317e+07, 6.330473e+05, 4.683591e+03, 1.620640e+01, -1.376354e+07, 7.637402e+05, 7.223657e+03, 2.932462e+01, -2.583591e+07, 1.010277e+06, 1.132308e+04, 5.650986e+01, -4.465643e+07, 1.303261e+06, 1.779668e+04, 1.116488e+02, -4.722198e+07, 1.403819e+06, 2.704938e+04, 2.186730e+02, -4.285916e+07, 1.335126e+06, 3.845701e+04, 4.099392e+02, -3.417982e+07, 1.121722e+06, 5.070906e+04, 7.219074e+02, -2.901563e+07, 8.791541e+05, 6.214431e+04, 1.187121e+03, -1.838120e+07, 5.316987e+05, 7.098441e+04, 1.826925e+03, -1.217421e+07, 2.767583e+05, 7.602698e+04, 2.638278e+03, -7.803981e+06, 8.631945e+04, 7.726482e+04, 3.602555e+03, -4.483355e+06, -4.639403e+04, 7.505263e+04, 4.686021e+03, -2.447868e+06, -1.176936e+05, 7.020737e+04, 5.845505e+03, -1.057698e+06, -1.499728e+05, 6.373873e+04, 7.037935e+03, -5.877838e+05, -1.450739e+05, 5.661180e+04, 8.225507e+03, -3.775252e+05, -1.299298e+05, 4.947172e+04, 9.381489e+03, -4.735522e+04, -1.179415e+05, 4.261136e+04, 1.048487e+04, -3.826733e+04, -9.552913e+04, 3.633754e+04, 1.151890e+04, 7.634655e+04, -8.044760e+04, 3.078666e+04, 1.247799e+04, -1.166207e+04, -6.027152e+04, 2.601237e+04, 1.335852e+04, -3.488352e+04, -4.748362e+04, 2.191882e+04, 1.416472e+04, 1.451432e+05, -4.532720e+04, 1.833155e+04, 1.489651e+04, -1.018718e+05, -2.331123e+04, 1.545194e+04, 1.555285e+04, 6.092841e+04, -2.791611e+04, 1.295407e+04, 1.615327e+04, 9.914125e+03, -1.852473e+04, 1.081145e+04, 1.668531e+04, -1.018421e+04, -1.364660e+04, 9.097815e+03, 1.716368e+04, 2.677632e+04, -1.320567e+04, 7.616752e+03, 1.759324e+04, -3.190707e+04, -6.537187e+03, 6.413697e+03, 1.797428e+04, 3.224420e+04, -1.002234e+04, 5.332416e+03, 1.831827e+04, -1.790675e+04, -3.819177e+03, 4.465077e+03, 1.861606e+04, 5.741706e+03, -5.269812e+03, 3.739037e+03, 1.888589e+04, -7.215146e+03, -3.071621e+03, 3.094632e+03, 1.912037e+04, -1.751587e+03, -3.077939e+03, 2.533371e+03, 1.932641e+04, 1.684196e+03, -2.713112e+03, 2.030604e+03, 1.950173e+04, -5.727454e+03, -1.411693e+03, 1.625658e+03, 1.964880e+04, -4.801342e+03, -1.316339e+03, 1.262519e+03, 1.977305e+04, -6.741413e+03, -8.448004e+02, 9.137641e+02, 1.987167e+04, -1.490630e+04, 2.471177e+02, 5.794638e+02, 1.994416e+04, -5.125526e+03, -1.870754e+02, 1.995830e+02, 1.998926e+04, -2.869444e+12, 4.196504e+07, 1.111129e+03, 1.914998e-01, 7.156578e+09, -1.295320e+06, 0, 2.084253e-01, -1.403689e+09, 9.962077e+05, 0, 2.021387e-01, -8.216375e+07, 1.203012e+05, 2.008386e+02, 2.596854e-01, 6.555093e+07, -5.683459e+04, 2.540250e+02, 4.153999e-01, -1.211732e+07, 1.476175e+05, 3.519336e+02, 6.958794e-01, 6.522379e+05, 1.744630e+05, 7.256024e+02, 1.564399e+00, -1.052628e+07, 3.516827e+05, 1.498850e+03, 3.995866e+00, -2.574797e+07, 6.281950e+05, 3.279889e+03, 1.108668e+01, -3.086743e+07, 8.810812e+05, 6.898743e+03, 3.079762e+01, -3.884285e+07, 1.142616e+06, 1.310979e+04, 7.910539e+01, -3.943960e+07, 1.250215e+06, 2.235506e+04, 1.838892e+02, -3.665357e+07, 1.197647e+06, 3.392539e+04, 3.827845e+02, -2.694963e+07, 9.520602e+05, 4.610324e+04, 7.159656e+02, -2.036503e+07, 6.966329e+05, 5.686927e+04, 1.212730e+03, -1.444636e+07, 4.337031e+05, 6.479572e+04, 1.887513e+03, -7.699672e+06, 1.790196e+05, 6.888180e+04, 2.732083e+03, -5.257205e+06, 4.882563e+04, 6.934273e+04, 3.716165e+03, -3.250320e+06, -4.591330e+04, 6.693171e+04, 4.806015e+03, -1.348332e+06, -1.107657e+05, 6.225009e+04, 5.958500e+03, -6.591738e+05, -1.229398e+05, 5.632815e+04, 7.129749e+03, -5.308371e+05, -1.127866e+05, 5.004913e+04, 8.289289e+03, -2.262225e+05, -1.068280e+05, 4.374560e+04, 9.414179e+03, 3.731957e+04, -9.700161e+04, 3.768587e+04, 1.048232e+04, -1.736652e+04, -7.613110e+04, 3.223589e+04, 1.148048e+04, -2.414547e+04, -6.138152e+04, 2.745864e+04, 1.240735e+04, 6.789920e+04, -5.299159e+04, 2.324807e+04, 1.326047e+04, -1.736037e+04, -3.809564e+04, 1.966746e+04, 1.403819e+04, 2.647414e+04, -3.277573e+04, 1.660775e+04, 1.474812e+04, 8.534694e+03, -2.499570e+04, 1.399418e+04, 1.538991e+04, -7.165778e+03, -1.917919e+04, 1.179604e+04, 1.596990e+04, 1.820885e+04, -1.685831e+04, 9.900832e+03, 1.649223e+04, 5.374457e+03, -1.240641e+04, 8.314451e+03, 1.695838e+04, -6.216827e+03, -9.208817e+03, 7.007123e+03, 1.737642e+04, 6.178700e+03, -8.349800e+03, 5.875342e+03, 1.775088e+04, -5.600157e+03, -5.764635e+03, 4.917613e+03, 1.808234e+04, 6.164147e+03, -5.602643e+03, 4.094812e+03, 1.837682e+04, -9.844895e+03, -3.124692e+03, 3.410559e+03, 1.863437e+04, 1.870561e+03, -3.694799e+03, 2.799852e+03, 1.886209e+04, -1.653556e+03, -2.538690e+03, 2.266366e+03, 1.905585e+04, -7.849600e+03, -1.504537e+03, 1.824372e+03, 1.922132e+04, -6.752870e+03, -1.437372e+03, 1.399671e+03, 1.936046e+04, -3.301713e+03, -1.417094e+03, 9.829110e+02, 1.946895e+04, -1.406390e+04, 1.486421e+02, 6.317347e+02, 1.954571e+04, -8.038091e+03, -1.892693e+01, 2.567819e+02, 1.959578e+04, 8.092438e+10, -1.162467e+06, -3.206142e+01, 9.671708e-04, -5.505060e+08, 9.964000e+04, 0, 4.835854e-04, 2.752931e+07, -1.352454e+04, 0, 9.671708e-04, -1.833317e+07, 2.120320e+04, 0, 4.835854e-04, 2.571019e+06, -3.649190e+03, 4.673637e+00, 4.352269e-03, -7.491211e+04, 4.848017e+03, 5.527414e+00, 8.220952e-03, -7.418260e+05, 1.692347e+04, 2.018402e+01, 2.853154e-02, -2.336180e+06, 5.229333e+04, 8.361598e+01, 1.460428e-01, -4.201515e+06, 1.305820e+05, 3.288177e+02, 7.756710e-01, -1.289169e+07, 3.289640e+05, 1.129365e+03, 3.612867e+00, -1.762035e+07, 5.566023e+05, 3.358858e+03, 1.475322e+01, -2.747414e+07, 8.490401e+05, 7.989587e+03, 4.876524e+01, -2.619987e+07, 9.449800e+05, 1.575022e+04, 1.343985e+02, -2.483176e+07, 9.407079e+05, 2.589242e+04, 3.096513e+02, -2.096394e+07, 7.980703e+05, 3.700925e+04, 6.166125e+02, -1.260854e+07, 5.301678e+05, 4.692981e+04, 1.086607e+03, -1.011947e+07, 3.644354e+05, 5.426536e+04, 1.727560e+03, -6.162520e+06, 1.740138e+05, 5.850899e+04, 2.535811e+03, -3.372106e+06, 4.020494e+04, 5.938275e+04, 3.481855e+03, -2.254455e+06, -2.599647e+04, 5.763576e+04, 4.527013e+03, -9.857144e+05, -7.745357e+04, 5.399678e+04, 5.633404e+03, -5.863116e+05, -8.788475e+04, 4.923235e+04, 6.760406e+03, -1.620644e+05, -9.249139e+04, 4.402444e+04, 7.879244e+03, -2.699903e+05, -7.601326e+04, 3.884746e+04, 8.965668e+03, -1.358876e+05, -7.057037e+04, 3.384431e+04, 1.000696e+04, 1.675314e+05, -6.959774e+04, 2.906964e+04, 1.098559e+04, -9.302058e+04, -4.442220e+04, 2.495681e+04, 1.189088e+04, 7.251168e+03, -4.169873e+04, 2.136185e+04, 1.273426e+04, 5.481866e+04, -3.555078e+04, 1.813324e+04, 1.350642e+04, -3.479656e+04, -2.368568e+04, 1.543658e+04, 1.420950e+04, 1.551094e+04, -2.236704e+04, 1.309303e+04, 1.485312e+04, 1.826623e+04, -1.782883e+04, 1.104855e+04, 1.543299e+04, 1.003366e+04, -1.355278e+04, 9.363013e+03, 1.595548e+04, -3.906669e+04, -7.936198e+03, 7.972150e+03, 1.642815e+04, 3.712882e+04, -1.211740e+04, 6.656119e+03, 1.685648e+04, -2.359586e+04, -4.682025e+03, 5.586378e+03, 1.722895e+04, 1.313605e+04, -7.041172e+03, 4.675363e+03, 1.756662e+04, -8.595405e+03, -3.626245e+03, 3.892172e+03, 1.785962e+04, -4.083225e+03, -3.541047e+03, 3.228339e+03, 1.812020e+04, -2.079108e+03, -3.062724e+03, 2.613468e+03, 1.834503e+04, -4.585763e+03, -2.207125e+03, 2.078593e+03, 1.853488e+04, -8.379371e+03, -1.445921e+03, 1.605151e+03, 1.869252e+04, -3.288252e+03, -1.643252e+03, 1.148159e+03, 1.881809e+04, -1.880134e+04, 4.395417e+02, 7.550833e+02, 1.890833e+04, -9.040297e+03, -8.067476e+01, 3.009619e+02, 1.896881e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -9.709387e+03, 1.221581e+02, 0, 0, -5.051096e+04, 1.037139e+03, 3.952580e-01, 4.835854e-04, -1.390577e+05, 5.605787e+03, 5.152017e+00, 9.188123e-03, -1.185086e+06, 3.357945e+04, 4.125296e+01, 9.961860e-02, -3.324630e+06, 1.101904e+05, 2.773980e+02, 9.043047e-01, -7.853728e+06, 2.688967e+05, 1.210126e+03, 5.456778e+00, -1.227331e+07, 4.602241e+05, 3.787044e+03, 2.381416e+01, -1.502364e+07, 6.070524e+05, 8.821902e+03, 7.802554e+01, -1.336220e+07, 6.235281e+05, 1.626265e+04, 2.025851e+02, -1.337434e+07, 5.982898e+05, 2.508429e+04, 4.360495e+02, -8.551671e+06, 4.261216e+05, 3.375827e+04, 8.145489e+02, -6.484517e+06, 2.997790e+05, 4.067227e+04, 1.350606e+03, -3.892800e+06, 1.628204e+05, 4.528823e+04, 2.044370e+03, -3.174152e+06, 8.617744e+04, 4.739307e+04, 2.875549e+03, -7.858401e+05, -1.795473e+04, 4.709930e+04, 3.816879e+03, -1.506677e+06, -1.051765e+04, 4.520483e+04, 4.824117e+03, -1.654844e+05, -6.662056e+04, 4.211810e+04, 5.878308e+03, -3.325870e+05, -5.482462e+04, 3.828890e+04, 6.932492e+03, -1.669931e+05, -5.691599e+04, 3.434296e+04, 7.973661e+03, 3.176809e+04, -5.704259e+04, 3.032616e+04, 8.979996e+03, -1.281974e+05, -4.107245e+04, 2.659716e+04, 9.936586e+03, 5.251609e+04, -4.338252e+04, 2.310631e+04, 1.084227e+04, -3.310454e+04, -3.100850e+04, 1.995372e+04, 1.168280e+04, 1.373580e+04, -2.826584e+04, 1.717322e+04, 1.246385e+04, 1.486695e+04, -2.286523e+04, 1.471232e+04, 1.318078e+04, -2.699775e+04, -1.623475e+04, 1.261542e+04, 1.383733e+04, 3.280403e+04, -1.719400e+04, 1.073590e+04, 1.443831e+04, -2.669848e+04, -9.678436e+03, 9.151064e+03, 1.497882e+04, 1.838055e+04, -1.142924e+04, 7.757786e+03, 1.547212e+04, -1.527434e+04, -6.522392e+03, 6.559644e+03, 1.591064e+04, 6.134069e+03, -7.241503e+03, 5.514782e+03, 1.630624e+04, -6.323445e+03, -4.711065e+03, 4.604267e+03, 1.665383e+04, -4.073073e+03, -4.157336e+03, 3.818693e+03, 1.696133e+04, -3.689038e+03, -3.435628e+03, 3.109516e+03, 1.722780e+04, -5.989523e+03, -2.575961e+03, 2.483016e+03, 1.745440e+04, -7.028686e+03, -2.007072e+03, 1.916696e+03, 1.764283e+04, -1.237906e+04, -1.066394e+03, 1.391888e+03, 1.779266e+04, -1.530568e+04, -3.931004e+02, 8.686103e+02, 1.790328e+04, -1.075759e+04, -3.241883e+01, 3.519534e+02, 1.797018e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3.054978e+04, 7.410320e+02, 0, 0, -9.722180e+04, 4.326381e+03, 4.923375e+00, 1.305681e-02, -3.957187e+05, 2.108857e+04, 4.479837e+01, 1.639355e-01, -2.217090e+06, 8.601666e+04, 2.778367e+02, 1.331311e+00, -3.595510e+06, 1.730620e+05, 1.233921e+03, 8.028002e+00, -5.986757e+06, 2.900617e+05, 3.538550e+03, 3.203512e+01, -6.769567e+06, 3.551039e+05, 7.723701e+03, 9.713732e+01, -5.667593e+06, 3.457250e+05, 1.341347e+04, 2.349867e+02, -5.458172e+06, 3.222378e+05, 1.977905e+04, 4.766324e+02, -3.782412e+06, 2.373311e+05, 2.587928e+04, 8.491315e+02, -2.850464e+06, 1.657680e+05, 3.072606e+04, 1.360673e+03, -2.076195e+06, 9.869617e+04, 3.393877e+04, 2.007443e+03, -8.459967e+05, 2.822829e+04, 3.528651e+04, 2.770476e+03, -7.874505e+05, 9.303483e+03, 3.518552e+04, 3.618710e+03, -4.961071e+05, -1.453427e+04, 3.405307e+04, 4.532258e+03, -2.021158e+05, -3.136214e+04, 3.200853e+04, 5.481500e+03, -1.413239e+05, -3.330948e+04, 2.947684e+04, 6.438940e+03, -1.032936e+05, -3.292416e+04, 2.675684e+04, 7.387225e+03, -2.743197e+04, -3.315766e+04, 2.395645e+04, 8.310655e+03, -4.213430e+04, -2.797667e+04, 2.123679e+04, 9.195288e+03, 1.688152e+04, -2.708199e+04, 1.866320e+04, 1.003492e+04, -3.945755e+04, -1.950281e+04, 1.632798e+04, 1.082159e+04, 3.775898e+04, -2.118019e+04, 1.417740e+04, 1.155761e+04, -3.951332e+04, -1.232675e+04, 1.230190e+04, 1.223448e+04, 1.628466e+04, -1.456907e+04, 1.060143e+04, 1.286326e+04, 2.475050e+03, -1.062776e+04, 9.074832e+03, 1.343267e+04, -2.958304e+04, -6.604437e+03, 7.794557e+03, 1.395159e+04, 2.382873e+04, -9.973204e+03, 6.556652e+03, 1.442337e+04, -1.898300e+04, -4.141927e+03, 5.521709e+03, 1.483557e+04, -6.649303e+02, -5.415087e+03, 4.618044e+03, 1.520793e+04, -5.006126e+03, -3.945080e+03, 3.776118e+03, 1.552981e+04, -8.901394e+03, -2.910036e+03, 3.041676e+03, 1.580619e+04, -1.200711e+04, -2.169750e+03, 2.355820e+03, 1.603784e+04, -4.968676e+03, -2.395668e+03, 1.683550e+03, 1.622197e+04, -2.774133e+04, 6.568597e+02, 1.105917e+03, 1.635428e+04, -1.302099e+04, -1.357563e+02, 4.374897e+02, 1.644280e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -9.717292e+02, 3.525304e+01, 0, 0, -5.304463e+03, 3.218125e+02, 3.073832e-01, 9.671708e-04, -1.934360e+04, 2.085146e+03, 3.966715e+00, 1.644190e-02, -3.180464e+05, 1.510232e+04, 3.388872e+01, 1.745743e-01, -6.480828e+05, 4.043076e+04, 2.338605e+02, 1.570202e+00, -1.516090e+06, 9.036847e+04, 8.833714e+02, 8.063303e+00, -2.034832e+06, 1.366083e+05, 2.427098e+03, 3.009062e+01, -2.361191e+06, 1.706568e+05, 5.064127e+03, 8.568311e+01, -2.387942e+06, 1.804522e+05, 8.693407e+03, 1.993470e+02, -2.155769e+06, 1.647391e+05, 1.283741e+04, 3.965541e+02, -1.303862e+06, 1.206826e+05, 1.681586e+04, 6.963707e+02, -1.382930e+06, 1.028904e+05, 2.021420e+04, 1.105526e+03, -7.363076e+05, 5.682299e+04, 2.276260e+04, 1.628739e+03, -7.293309e+05, 3.878596e+04, 2.422386e+04, 2.250501e+03, -1.958146e+05, 3.375079e+03, 2.465448e+04, 2.957056e+03, -2.527096e+05, 3.571719e+02, 2.429786e+04, 3.719856e+03, -1.824193e+05, -8.454398e+03, 2.346440e+04, 4.527808e+03, -1.207450e+05, -1.454655e+04, 2.212836e+04, 5.360145e+03, -1.873828e+04, -2.014348e+04, 2.043631e+04, 6.196165e+03, -6.547356e+04, -1.592640e+04, 1.864471e+04, 7.017728e+03, 1.538025e+04, -1.940620e+04, 1.681319e+04, 7.818656e+03, -3.081477e+04, -1.380759e+04, 1.505269e+04, 8.584346e+03, -3.688264e+04, -1.237202e+04, 1.339212e+04, 9.316279e+03, 3.700757e+04, -1.579093e+04, 1.171025e+04, 1.000491e+04, -3.096457e+04, -7.862788e+03, 1.025124e+04, 1.063862e+04, -3.624742e+03, -9.431423e+03, 8.931243e+03, 1.123263e+04, -7.771562e+02, -8.102068e+03, 7.655642e+03, 1.177367e+04, -9.869735e+03, -6.022230e+03, 6.528116e+03, 1.226242e+04, -4.868512e+03, -5.631664e+03, 5.495559e+03, 1.270154e+04, -9.937763e+03, -4.263030e+03, 4.546326e+03, 1.308752e+04, -4.005424e+03, -4.161767e+03, 3.664244e+03, 1.342139e+04, -1.613158e+04, -2.200682e+03, 2.871716e+03, 1.369982e+04, -1.400113e+04, -2.118312e+03, 2.095777e+03, 1.392675e+04, -2.681191e+04, -1.270264e+02, 1.333515e+03, 1.409262e+04, -1.703298e+04, -1.198066e+01, 5.383685e+02, 1.419677e+04, }; static float solarDataset680[] = { -352468042275216, 4.565228e+09, 3.493754e+05, 4.079590e+03, 5.683662e+12, -1.328402e+09, 1.925649e+05, 4.085164e+03, -7.764229e+10, 4.963131e+07, 1.202445e+05, 4.099044e+03, 5.563528e+09, -4.324424e+06, 1.277691e+05, 4.141022e+03, -3.769498e+09, 6.005153e+06, 1.290424e+05, 4.222198e+03, 9.852032e+08, -2.967738e+06, 1.291679e+05, 4.360144e+03, -3.875109e+07, 1.836524e+05, 1.271300e+05, 4.559262e+03, -1.192922e+08, 3.590793e+05, 1.273769e+05, 4.838049e+03, 5.235498e+06, -2.993428e+05, 1.264319e+05, 5.209221e+03, -3.536095e+07, -5.551723e+04, 1.244122e+05, 5.678238e+03, -3.682262e+07, -1.175068e+05, 1.215785e+05, 6.254607e+03, -1.683494e+07, -3.365406e+05, 1.166413e+05, 6.937634e+03, -6.725039e+06, -4.184973e+05, 1.096698e+05, 7.714702e+03, -1.347547e+07, -3.110082e+05, 1.015845e+05, 8.570426e+03, -5.796493e+06, -3.962767e+05, 9.212522e+04, 9.489327e+03, -1.470687e+06, -3.999603e+05, 8.144721e+04, 1.043704e+04, -3.891564e+06, -2.924573e+05, 7.082390e+04, 1.138470e+04, 1.268637e+06, -3.320372e+05, 6.027083e+04, 1.231325e+04, -1.553830e+06, -2.010288e+05, 5.070597e+04, 1.318976e+04, 6.401092e+05, -2.083886e+05, 4.212731e+04, 1.401579e+04, -4.089157e+05, -1.325947e+05, 3.467286e+04, 1.476862e+04, 4.689382e+05, -1.255255e+05, 2.832884e+04, 1.545545e+04, -2.414026e+05, -7.345191e+04, 2.313068e+04, 1.606742e+04, 2.093406e+05, -7.131366e+04, 1.878759e+04, 1.661838e+04, 8.730097e+04, -4.851327e+04, 1.522608e+04, 1.710171e+04, -2.825615e+04, -3.260464e+04, 1.246629e+04, 1.753026e+04, 9.246158e+03, -2.696444e+04, 1.017736e+04, 1.791157e+04, 5.845154e+04, -2.256224e+04, 8.255250e+03, 1.824608e+04, -1.623206e+03, -1.409944e+04, 6.758571e+03, 1.853795e+04, 1.397299e+04, -1.179690e+04, 5.565383e+03, 1.879686e+04, 9.810044e+03, -8.809613e+03, 4.588390e+03, 1.902473e+04, -1.056924e+04, -5.731825e+03, 3.808836e+03, 1.922618e+04, 1.867460e+04, -6.355988e+03, 3.137056e+03, 1.940511e+04, -2.207924e+04, -2.223620e+03, 2.609823e+03, 1.956056e+04, 2.317944e+04, -5.069146e+03, 2.128577e+03, 1.970022e+04, -1.315186e+04, -9.880525e+02, 1.767994e+03, 1.981745e+04, 4.416039e+03, -2.401660e+03, 1.471594e+03, 1.992484e+04, 2.469023e+02, -1.450777e+03, 1.203539e+03, 2.001628e+04, -7.126793e+03, -5.842061e+02, 9.964367e+02, 2.009623e+04, 5.680761e+03, -1.675038e+03, 7.812342e+02, 2.016597e+04, -3.303117e+03, -3.317838e+02, 6.218765e+02, 2.022109e+04, -3.628281e+03, -3.367296e+02, 4.942834e+02, 2.026943e+04, -1.932363e+03, -4.513063e+02, 3.479496e+02, 2.030822e+04, -2.905107e+03, -1.741303e+02, 2.130510e+02, 2.033521e+04, -2.186812e+03, -6.044464e+01, 9.550916e+01, 2.035167e+04, 2.566491e+12, -2.160143e+07, 1.253489e+05, 2.094745e+03, 1.072830e+11, 3.373914e+06, 1.268921e+05, 2.096912e+03, -6.278151e+10, 3.625360e+07, 1.323924e+05, 2.112461e+03, 5.355040e+09, -6.437409e+06, 1.359364e+05, 2.157505e+03, 6.328454e+08, -3.831994e+05, 1.342600e+05, 2.242976e+03, -3.525021e+08, 1.289271e+06, 1.355533e+05, 2.384464e+03, 7.237564e+06, 1.315110e+05, 1.369959e+05, 2.598910e+03, -8.490662e+07, 3.829063e+05, 1.376758e+05, 2.899528e+03, -3.478052e+07, 3.597080e+04, 1.377450e+05, 3.301754e+03, -5.179258e+07, 5.107895e+04, 1.365542e+05, 3.815687e+03, -2.559535e+07, -2.211796e+05, 1.336407e+05, 4.449428e+03, -2.591427e+07, -2.568699e+05, 1.286169e+05, 5.199989e+03, -1.373490e+07, -3.999240e+05, 1.214603e+05, 6.059833e+03, -1.260242e+07, -3.952445e+05, 1.123008e+05, 7.008387e+03, -2.957989e+06, -4.813305e+05, 1.014858e+05, 8.021575e+03, -5.251237e+06, -3.746148e+05, 8.996501e+04, 9.064690e+03, -4.198038e+05, -3.933644e+05, 7.821981e+04, 1.011487e+04, -1.996456e+06, -2.874528e+05, 6.689029e+04, 1.113727e+04, 4.266078e+05, -2.786719e+05, 5.627982e+04, 1.211684e+04, -3.919704e+05, -1.965459e+05, 4.681414e+04, 1.302821e+04, 1.091816e+05, -1.649710e+05, 3.862777e+04, 1.386995e+04, 3.750077e+05, -1.318222e+05, 3.161062e+04, 1.463277e+04, -2.406655e+05, -8.206026e+04, 2.595029e+04, 1.531832e+04, 2.170257e+05, -7.837065e+04, 2.115790e+04, 1.593722e+04, -7.134165e+04, -4.885270e+04, 1.721207e+04, 1.648268e+04, 1.378171e+05, -4.537327e+04, 1.397250e+04, 1.696781e+04, 3.258145e+04, -2.938905e+04, 1.138823e+04, 1.739164e+04, 1.146137e+03, -2.126903e+04, 9.382346e+03, 1.776806e+04, 1.883121e+04, -1.738343e+04, 7.723831e+03, 1.810256e+04, -1.217855e+04, -1.191290e+04, 6.363021e+03, 1.839774e+04, 1.663010e+04, -1.094152e+04, 5.216659e+03, 1.865889e+04, 1.933224e+04, -8.372961e+03, 4.279327e+03, 1.888639e+04, -6.277107e+03, -4.826426e+03, 3.572708e+03, 1.908656e+04, -1.213908e+04, -3.694135e+03, 2.989211e+03, 1.926630e+04, 1.843629e+04, -5.074897e+03, 2.437722e+03, 1.942497e+04, -3.720726e+03, -2.060727e+03, 2.022513e+03, 1.956010e+04, -7.571230e+03, -1.529007e+03, 1.706477e+03, 1.968213e+04, 3.388922e+03, -2.219310e+03, 1.387955e+03, 1.978997e+04, -8.136688e+02, -1.296765e+03, 1.118924e+03, 1.988048e+04, -2.113553e+00, -1.105284e+03, 9.057690e+02, 1.995827e+04, -5.605613e+03, -3.817953e+02, 7.273565e+02, 2.002416e+04, 2.555659e+03, -1.135591e+03, 5.415747e+02, 2.007969e+04, -7.323743e+03, 1.792085e+02, 4.001082e+02, 2.012072e+04, -1.158262e+03, -4.852916e+02, 2.418730e+02, 2.015369e+04, -1.923105e+03, -1.119911e+02, 1.136166e+02, 2.017163e+04, -4.453960e+13, 4.901918e+08, 1.224067e+05, 6.971794e+02, 1.428199e+12, -3.402263e+08, 9.960258e+04, 6.992069e+02, 2.850891e+09, 1.332939e+06, 7.987958e+04, 7.087809e+02, 3.653290e+09, -2.318826e+05, 8.167014e+04, 7.351861e+02, -1.710126e+09, 5.205901e+06, 8.583269e+04, 7.881288e+02, 3.500513e+08, 7.327072e+05, 9.110828e+04, 8.821503e+02, -3.667415e+07, 1.644077e+06, 9.599104e+04, 1.028221e+03, -6.427903e+07, 1.499947e+06, 1.026622e+05, 1.245859e+03, -8.902301e+07, 1.348587e+06, 1.097649e+05, 1.556074e+03, -5.458529e+07, 8.715855e+05, 1.161171e+05, 1.980872e+03, -7.078158e+07, 7.296954e+05, 1.206867e+05, 2.536762e+03, -2.407104e+07, 9.613678e+04, 1.221006e+05, 3.235974e+03, -2.892878e+07, 3.067619e+04, 1.200345e+05, 4.068347e+03, -1.424189e+07, -2.367188e+05, 1.148582e+05, 5.025490e+03, -8.468524e+06, -3.287116e+05, 1.065955e+05, 6.075512e+03, -4.418101e+06, -3.647176e+05, 9.643889e+04, 7.185170e+03, -3.842678e+06, -3.284474e+05, 8.532578e+04, 8.318939e+03, -5.278715e+05, -3.366958e+05, 7.378807e+04, 9.444730e+03, -3.937578e+05, -2.707005e+05, 6.272309e+04, 1.052705e+04, -4.639425e+05, -2.130327e+05, 5.276832e+04, 1.155043e+04, 2.817660e+05, -1.847892e+05, 4.384989e+04, 1.250236e+04, 2.903034e+04, -1.344634e+05, 3.621580e+04, 1.337110e+04, 4.635096e+03, -1.030736e+05, 2.983586e+04, 1.416051e+04, 2.047168e+05, -8.515824e+04, 2.444758e+04, 1.487116e+04, -1.279274e+05, -5.337031e+04, 2.008387e+04, 1.550475e+04, 1.415452e+05, -5.181761e+04, 1.640018e+04, 1.607299e+04, 5.602843e+04, -3.510271e+04, 1.339511e+04, 1.657132e+04, -1.127698e+04, -2.404607e+04, 1.106697e+04, 1.701421e+04, 1.253660e+04, -2.007243e+04, 9.134211e+03, 1.740961e+04, 1.780279e+04, -1.574977e+04, 7.514154e+03, 1.775883e+04, 5.640618e+03, -1.147763e+04, 6.204614e+03, 1.806675e+04, 2.936546e+03, -8.829144e+03, 5.139387e+03, 1.833932e+04, 5.299726e+03, -7.061936e+03, 4.256417e+03, 1.858020e+04, 5.686652e+03, -5.507486e+03, 3.532321e+03, 1.879251e+04, -7.404946e+03, -3.452414e+03, 2.950484e+03, 1.898008e+04, 3.770764e+03, -3.682956e+03, 2.441272e+03, 1.914689e+04, 3.794749e+03, -2.805228e+03, 2.009244e+03, 1.929140e+04, -9.089152e+03, -1.190131e+03, 1.676729e+03, 1.941776e+04, 3.011825e+03, -2.138990e+03, 1.359400e+03, 1.952992e+04, 1.428751e+02, -1.319583e+03, 1.084559e+03, 1.962291e+04, -4.913817e+03, -5.934187e+02, 8.743950e+02, 1.970191e+04, -5.071407e+02, -9.664004e+02, 6.676441e+02, 1.976881e+04, -4.650836e+03, -3.007170e+02, 4.834242e+02, 1.982025e+04, -5.376321e+03, -1.327924e+02, 3.054971e+02, 1.985899e+04, -3.742214e+03, -1.749535e+01, 1.250497e+02, 1.988258e+04, -7.893237e+12, 8.288681e+07, 3.010748e+04, 1.136166e+02, 3.103597e+11, -7.118740e+07, 2.592881e+04, 1.141198e+02, 8.428280e+09, -8.028634e+05, 2.230568e+04, 1.167572e+02, -3.605961e+09, 5.798521e+06, 2.449204e+04, 1.242727e+02, 8.783630e+08, -1.200222e+04, 2.748804e+04, 1.413170e+02, 1.044530e+08, 1.460532e+06, 3.037633e+04, 1.712288e+02, -9.170265e+05, 1.717708e+06, 3.572950e+04, 2.228753e+02, -4.501713e+07, 1.862117e+06, 4.323714e+04, 3.093172e+02, -7.396908e+07, 1.935003e+06, 5.294040e+04, 4.499654e+02, -6.169410e+07, 1.717830e+06, 6.431161e+04, 6.711980e+02, -7.366754e+07, 1.587813e+06, 7.632218e+04, 1.002824e+03, -4.663231e+07, 1.055055e+06, 8.724662e+04, 1.476305e+03, -4.048764e+07, 7.247687e+05, 9.513528e+04, 2.107835e+03, -1.960904e+07, 2.489285e+05, 9.891534e+04, 2.902937e+03, -1.894416e+07, 9.872926e+04, 9.837949e+04, 3.841311e+03, -4.442386e+06, -2.116653e+05, 9.380338e+04, 4.898693e+03, -5.834290e+06, -1.885613e+05, 8.648343e+04, 6.023302e+03, -1.719788e+06, -2.613590e+05, 7.770079e+04, 7.187578e+03, -1.691541e+06, -2.251616e+05, 6.812535e+04, 8.346053e+03, -5.227803e+05, -2.157890e+05, 5.856276e+04, 9.472141e+03, 4.814127e+05, -1.960903e+05, 4.946763e+04, 1.053652e+04, -4.579357e+05, -1.276666e+05, 4.162523e+04, 1.152409e+04, 1.805291e+05, -1.211531e+05, 3.473519e+04, 1.244006e+04, 1.359116e+05, -9.125698e+04, 2.876191e+04, 1.326975e+04, -8.572899e+04, -6.301636e+04, 2.388140e+04, 1.401999e+04, 1.408473e+05, -5.792684e+04, 1.972080e+04, 1.469810e+04, -3.746225e+04, -3.691816e+04, 1.630243e+04, 1.530117e+04, 6.587470e+04, -3.359362e+04, 1.347244e+04, 1.584278e+04, 1.012335e+04, -2.298597e+04, 1.114689e+04, 1.632227e+04, 6.639102e+03, -1.787249e+04, 9.269274e+03, 1.675072e+04, -6.477797e+02, -1.369067e+04, 7.700812e+03, 1.713232e+04, 2.142191e+04, -1.198949e+04, 6.378977e+03, 1.747105e+04, -4.414359e+03, -7.644321e+03, 5.317687e+03, 1.776972e+04, 1.533924e+03, -6.582866e+03, 4.443001e+03, 1.803667e+04, 1.981630e+03, -5.240241e+03, 3.694367e+03, 1.827267e+04, -1.052148e+03, -3.932107e+03, 3.071754e+03, 1.848069e+04, 7.306138e+02, -3.290251e+03, 2.545786e+03, 1.866390e+04, 4.229719e+02, -2.571537e+03, 2.102797e+03, 1.882392e+04, -7.944393e+03, -1.390188e+03, 1.735472e+03, 1.896341e+04, 4.214760e+03, -2.291285e+03, 1.382288e+03, 1.908470e+04, -5.750642e+03, -7.694022e+02, 1.094846e+03, 1.918353e+04, 1.100272e+02, -1.256194e+03, 8.401738e+02, 1.926736e+04, -1.010048e+04, 6.181541e+01, 6.190195e+02, 1.933230e+04, -3.820373e+03, -5.389325e+02, 3.661653e+02, 1.938243e+04, -3.917769e+03, -6.433621e+01, 1.509301e+02, 1.940952e+04, -8.070633e+12, 1.076138e+08, 6.631032e+03, 1.018617e+01, 1.369399e+11, -2.815586e+07, 3.146703e+03, 1.029111e+01, -1.827832e+10, 1.209860e+07, 2.333390e+03, 1.050144e+01, 9.521666e+08, -5.255783e+05, 4.376365e+03, 1.192131e+01, 1.173580e+07, 6.003251e+05, 4.867928e+03, 1.474579e+01, 1.090046e+08, 4.481858e+05, 6.169347e+03, 2.054185e+01, -8.730001e+06, 9.393270e+05, 8.380095e+03, 3.174291e+01, -3.942600e+07, 1.234005e+06, 1.236733e+04, 5.449888e+01, -5.058522e+07, 1.455714e+06, 1.855333e+04, 1.000252e+02, -5.517395e+07, 1.596469e+06, 2.732046e+04, 1.871469e+02, -5.839261e+07, 1.629707e+06, 3.862401e+04, 3.439872e+02, -5.114727e+07, 1.444003e+06, 5.151836e+04, 6.065740e+02, -3.969641e+07, 1.116577e+06, 6.409615e+04, 1.010369e+03, -3.222007e+07, 7.829705e+05, 7.436652e+04, 1.580560e+03, -1.492637e+07, 3.287719e+05, 8.053808e+04, 2.324370e+03, -1.367783e+07, 1.737145e+05, 8.239238e+04, 3.220077e+03, -5.409060e+06, -6.916228e+04, 8.037208e+04, 4.244663e+03, -3.749200e+06, -1.294274e+05, 7.520553e+04, 5.347740e+03, -1.438150e+06, -1.808190e+05, 6.828222e+04, 6.491727e+03, -1.031219e+06, -1.695525e+05, 6.052789e+04, 7.635895e+03, -5.897295e+05, -1.566876e+05, 5.266149e+04, 8.752942e+03, 2.142786e+05, -1.502598e+05, 4.501376e+04, 9.817549e+03, -3.080940e+05, -1.038003e+05, 3.819615e+04, 1.081081e+04, 2.489975e+05, -1.015549e+05, 3.212658e+04, 1.173425e+04, -1.029353e+05, -6.635146e+04, 2.693457e+04, 1.257483e+04, 1.251409e+05, -6.152113e+04, 2.251714e+04, 1.334400e+04, -3.664596e+04, -4.097680e+04, 1.880373e+04, 1.403645e+04, 5.410562e+04, -3.659535e+04, 1.568214e+04, 1.466359e+04, -8.388199e+03, -2.544703e+04, 1.306777e+04, 1.522421e+04, 3.381060e+04, -2.226293e+04, 1.088538e+04, 1.572764e+04, 8.123732e+03, -1.580665e+04, 9.086832e+03, 1.617555e+04, -5.569137e+02, -1.204825e+04, 7.622303e+03, 1.657705e+04, -3.528642e+03, -9.509650e+03, 6.381344e+03, 1.693640e+04, 1.153206e+04, -8.551674e+03, 5.310794e+03, 1.725604e+04, -7.248790e+03, -5.378741e+03, 4.434661e+03, 1.753772e+04, 3.681099e+03, -5.223851e+03, 3.690070e+03, 1.778863e+04, 1.885868e+03, -3.926101e+03, 3.056040e+03, 1.800796e+04, -4.915319e+03, -2.588201e+03, 2.541884e+03, 1.820050e+04, 4.294262e+02, -2.621170e+03, 2.087430e+03, 1.836978e+04, -5.053803e+03, -1.594382e+03, 1.693140e+03, 1.851459e+04, -1.007074e+02, -1.793775e+03, 1.337123e+03, 1.863817e+04, -7.506678e+03, -6.792374e+02, 1.030627e+03, 1.873863e+04, 8.309197e+02, -1.383974e+03, 7.309777e+02, 1.881973e+04, -1.813795e+04, 9.635944e+02, 4.941701e+02, 1.887662e+04, -3.621577e+03, -2.330195e+02, 1.616740e+02, 1.891720e+04, 6.535480e+11, -5.929338e+06, -3.781728e+02, 5.184347e-01, -3.304103e+10, 7.713900e+06, 0, 5.135015e-01, 1.605064e+08, -1.634788e+05, 4.183612e+02, 5.677667e-01, 3.242006e+08, -2.400051e+05, 3.629284e+02, 6.928907e-01, -1.079961e+08, 3.789254e+05, 4.524209e+02, 9.108485e-01, 1.466292e+07, 1.653131e+05, 8.910833e+02, 1.679980e+00, 5.139923e+06, 3.030831e+05, 1.517958e+03, 3.541142e+00, -2.137928e+07, 6.141632e+05, 2.918879e+03, 8.370747e+00, -4.382682e+07, 9.923543e+05, 5.952912e+03, 2.155764e+01, -4.591369e+07, 1.251039e+06, 1.153723e+04, 5.541645e+01, -5.599871e+07, 1.504362e+06, 2.021971e+04, 1.319322e+02, -4.905457e+07, 1.461205e+06, 3.191749e+04, 2.858732e+02, -4.156802e+07, 1.274441e+06, 4.502474e+04, 5.570078e+02, -3.338034e+07, 9.727163e+05, 5.748065e+04, 9.823445e+02, -1.872780e+07, 5.500384e+05, 6.692099e+04, 1.582833e+03, -1.333256e+07, 3.021913e+05, 7.223951e+04, 2.351712e+03, -6.921961e+06, 7.087433e+04, 7.357275e+04, 3.270621e+03, -5.394556e+06, -2.381757e+04, 7.145035e+04, 4.301491e+03, -2.089262e+06, -1.282498e+05, 6.663436e+04, 5.405952e+03, -6.847307e+05, -1.546674e+05, 6.012913e+04, 6.533810e+03, -7.349015e+05, -1.335175e+05, 5.325038e+04, 7.651409e+03, -2.879821e+05, -1.272674e+05, 4.640416e+04, 8.738273e+03, -8.462746e+03, -1.130442e+05, 3.982467e+04, 9.771057e+03, -1.063739e+05, -8.787637e+04, 3.388731e+04, 1.073618e+04, 1.343560e+05, -7.883937e+04, 2.860691e+04, 1.162993e+04, 1.389387e+04, -5.691194e+04, 2.410021e+04, 1.244608e+04, -5.177439e+04, -4.289378e+04, 2.031934e+04, 1.319275e+04, 8.139572e+04, -4.013155e+04, 1.699864e+04, 1.387169e+04, 2.468899e+04, -2.814082e+04, 1.423289e+04, 1.448002e+04, -6.571990e+04, -1.805698e+04, 1.199929e+04, 1.503010e+04, 8.726906e+04, -2.301298e+04, 9.974486e+03, 1.552759e+04, -3.911454e+04, -9.959665e+03, 8.366133e+03, 1.596392e+04, 2.754859e+04, -1.261897e+04, 7.034917e+03, 1.636173e+04, -2.143616e+04, -6.578940e+03, 5.902874e+03, 1.671286e+04, 1.445855e+04, -8.060233e+03, 4.922564e+03, 1.702911e+04, -1.068146e+03, -5.007837e+03, 4.094606e+03, 1.730495e+04, -1.446239e+03, -4.042107e+03, 3.428210e+03, 1.755026e+04, -7.646742e+03, -2.833790e+03, 2.850615e+03, 1.776680e+04, 6.036580e+03, -3.510960e+03, 2.317098e+03, 1.795618e+04, -5.012745e+03, -1.656924e+03, 1.885239e+03, 1.811589e+04, -4.810884e+03, -1.478773e+03, 1.519931e+03, 1.825459e+04, -6.234266e+03, -1.106439e+03, 1.165198e+03, 1.836994e+04, -2.823139e+03, -1.181941e+03, 8.197310e+02, 1.846054e+04, -1.258697e+04, 2.043762e+02, 5.250146e+02, 1.852450e+04, -5.978057e+03, -7.475415e+01, 2.034009e+02, 1.856604e+04, -8.418277e+10, 1.154661e+06, 5.714404e+01, 4.036256e-03, -2.687024e+07, -8.592069e+04, 2.190888e+01, 4.933202e-03, 1.021218e+08, -5.017017e+04, 0, 6.278621e-03, -1.255189e+07, 1.903032e+04, 0, 4.484729e-03, 1.558282e+06, 2.417039e+03, 8.957179e+00, 8.969458e-03, -3.914997e+05, 1.370244e+04, 1.920907e+01, 2.287212e-02, -6.741212e+05, 3.455420e+04, 5.930749e+01, 8.520985e-02, -4.870917e+06, 1.084084e+05, 2.009074e+02, 3.735779e-01, -9.230984e+06, 2.505707e+05, 7.085224e+02, 1.758462e+00, -2.106645e+07, 5.356899e+05, 2.195612e+03, 7.431645e+00, -2.950385e+07, 8.461586e+05, 5.821344e+03, 2.723083e+01, -3.782577e+07, 1.119956e+06, 1.259572e+04, 8.251229e+01, -3.282215e+07, 1.127447e+06, 2.260996e+04, 2.090373e+02, -3.131878e+07, 1.051472e+06, 3.440400e+04, 4.481747e+02, -2.053329e+07, 7.431721e+05, 4.587941e+04, 8.398019e+02, -1.369182e+07, 4.785742e+05, 5.475855e+04, 1.400337e+03, -9.066544e+06, 2.627224e+05, 6.030965e+04, 2.128540e+03, -6.437927e+06, 1.088040e+05, 6.231489e+04, 3.004682e+03, -2.053492e+06, -4.777547e+04, 6.091525e+04, 3.993557e+03, -1.949825e+06, -6.605211e+04, 5.729296e+04, 5.045588e+03, -9.414086e+05, -9.996283e+04, 5.243186e+04, 6.132059e+03, -1.890967e+05, -1.121647e+05, 4.675167e+04, 7.214864e+03, -3.045963e+05, -9.180211e+04, 4.106393e+04, 8.265942e+03, -5.330101e+04, -8.608205e+04, 3.562988e+04, 9.272761e+03, -3.028050e+04, -7.119125e+04, 3.058189e+04, 1.021899e+04, 3.389382e+04, -6.002974e+04, 2.607403e+04, 1.109889e+04, 2.504837e+04, -4.749684e+04, 2.215132e+04, 1.190918e+04, 3.155848e+04, -3.811928e+04, 1.880026e+04, 1.265226e+04, -7.201400e+04, -2.586018e+04, 1.596321e+04, 1.333116e+04, 7.110271e+04, -2.854939e+04, 1.340926e+04, 1.395078e+04, 4.710820e+03, -1.819806e+04, 1.127146e+04, 1.450295e+04, -1.716947e+04, -1.351549e+04, 9.553127e+03, 1.500363e+04, 1.705228e+04, -1.317062e+04, 8.030335e+03, 1.545596e+04, -7.296253e+03, -8.740504e+03, 6.744056e+03, 1.585811e+04, 1.124590e+04, -8.382692e+03, 5.655728e+03, 1.621866e+04, -6.404979e+03, -5.276710e+03, 4.751552e+03, 1.653766e+04, -4.078801e+03, -4.618901e+03, 3.982096e+03, 1.682316e+04, 5.784536e+03, -4.519947e+03, 3.287528e+03, 1.707427e+04, -1.229816e+04, -2.021194e+03, 2.721875e+03, 1.729168e+04, 1.842108e+03, -3.109246e+03, 2.195199e+03, 1.748291e+04, 1.022085e+03, -2.237389e+03, 1.729408e+03, 1.764076e+04, -1.355747e+04, -3.814936e+02, 1.371889e+03, 1.777199e+04, -4.135917e+03, -1.405750e+03, 9.812738e+02, 1.788158e+04, -1.176006e+04, -1.122970e+02, 6.103796e+02, 1.795760e+04, -7.664940e+03, -2.255428e+01, 2.505438e+02, 1.800524e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.756796e+04, 3.410796e+02, 0, 0, -1.318358e+05, 2.755397e+03, 1.097018e+00, 1.345419e-03, -5.608807e+05, 1.562207e+04, 1.379447e+01, 2.466601e-02, -2.514261e+06, 6.918882e+04, 1.071228e+02, 2.654960e-01, -6.065589e+06, 1.944641e+05, 5.889450e+02, 2.019474e+00, -1.283506e+07, 4.191455e+05, 2.215660e+03, 1.058396e+01, -1.846805e+07, 6.414717e+05, 6.149145e+03, 4.126265e+01, -1.742585e+07, 7.178521e+05, 1.289995e+04, 1.231435e+02, -1.832815e+07, 7.396414e+05, 2.178945e+04, 2.939924e+02, -1.255612e+07, 5.674151e+05, 3.137447e+04, 5.949191e+02, -9.863656e+06, 4.196776e+05, 3.966016e+04, 1.048397e+03, -6.077376e+06, 2.402884e+05, 4.561200e+04, 1.662630e+03, -3.971539e+06, 1.160875e+05, 4.864964e+04, 2.421336e+03, -1.807408e+06, 1.308620e+04, 4.902579e+04, 3.296939e+03, -1.659778e+06, -1.565950e+04, 4.744301e+04, 4.252506e+03, -6.733442e+05, -5.969285e+04, 4.440953e+04, 5.259324e+03, -2.473511e+05, -7.140758e+04, 4.040044e+04, 6.277780e+03, -2.042537e+05, -6.499188e+04, 3.615217e+04, 7.282236e+03, -1.170966e+05, -6.002899e+04, 3.193951e+04, 8.257070e+03, -2.352214e+04, -5.459684e+04, 2.787370e+04, 9.187282e+03, 4.937715e+04, -4.785421e+04, 2.412159e+04, 1.006206e+04, -1.156724e+05, -3.191696e+04, 2.084086e+04, 1.087739e+04, 1.297973e+05, -3.849662e+04, 1.781328e+04, 1.163679e+04, -9.774888e+04, -1.844295e+04, 1.526608e+04, 1.232678e+04, 5.200490e+04, -2.438844e+04, 1.301188e+04, 1.296761e+04, -8.135849e+03, -1.543929e+04, 1.102631e+04, 1.354296e+04, 1.028947e+04, -1.379101e+04, 9.377438e+03, 1.406704e+04, -8.156883e+03, -9.874940e+03, 7.962838e+03, 1.453982e+04, -9.036508e+01, -8.750479e+03, 6.734128e+03, 1.496712e+04, 1.570054e+03, -7.174620e+03, 5.655807e+03, 1.534847e+04, -1.278293e+03, -5.539760e+03, 4.740587e+03, 1.568705e+04, -2.566299e+03, -4.405104e+03, 3.959008e+03, 1.598696e+04, -1.910568e+03, -3.654087e+03, 3.277553e+03, 1.625060e+04, -8.951905e+03, -2.385243e+03, 2.683652e+03, 1.647951e+04, -2.863973e+03, -2.620958e+03, 2.123866e+03, 1.667582e+04, -5.366473e+03, -1.785690e+03, 1.617383e+03, 1.683538e+04, -4.998538e+03, -1.403221e+03, 1.171570e+03, 1.696147e+04, -1.930573e+04, 4.416717e+02, 7.785677e+02, 1.705459e+04, -9.332163e+03, -8.178539e+01, 3.103724e+02, 1.711692e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -8.909025e+02, 3.538429e+01, 0, 0, -6.422168e+04, 1.628264e+03, 2.273205e-01, 4.484729e-04, -1.684485e+05, 8.745175e+03, 1.123560e+01, 3.049616e-02, -1.396076e+06, 4.954183e+04, 9.457898e+01, 3.480150e-01, -3.153636e+06, 1.315038e+05, 5.765050e+02, 2.867984e+00, -5.753237e+06, 2.566029e+05, 2.084437e+03, 1.445742e+01, -8.015029e+06, 3.742078e+05, 5.388979e+03, 5.210269e+01, -8.074433e+06, 4.135002e+05, 1.068476e+04, 1.446774e+02, -6.661386e+06, 3.790568e+05, 1.722141e+04, 3.258434e+02, -6.077928e+06, 3.260624e+05, 2.393450e+04, 6.249524e+02, -3.712201e+06, 2.107243e+05, 2.968932e+04, 1.061776e+03, -2.467015e+06, 1.292915e+05, 3.366006e+04, 1.632819e+03, -1.882443e+06, 7.221017e+04, 3.588291e+04, 2.326102e+03, -1.086002e+06, 1.703520e+04, 3.635384e+04, 3.120870e+03, -4.605255e+05, -1.927992e+04, 3.530604e+04, 3.984944e+03, -4.341743e+05, -2.590209e+04, 3.334915e+04, 4.887920e+03, -1.327876e+05, -3.966641e+04, 3.080680e+04, 5.809224e+03, -1.434539e+05, -3.617659e+04, 2.795994e+04, 6.723427e+03, -3.317195e+04, -3.750287e+04, 2.503988e+04, 7.617373e+03, -7.415801e+04, -3.064914e+04, 2.218438e+04, 8.475763e+03, 5.703238e+04, -3.265980e+04, 1.944651e+04, 9.292128e+03, -6.193252e+04, -2.057404e+04, 1.700446e+04, 1.005564e+04, 1.215735e+04, -2.212679e+04, 1.477610e+04, 1.077365e+04, 1.341243e+04, -1.799234e+04, 1.273145e+04, 1.143468e+04, -3.132178e+04, -1.206636e+04, 1.099078e+04, 1.204245e+04, 3.848496e+04, -1.481817e+04, 9.392096e+03, 1.260173e+04, -3.404114e+04, -6.555128e+03, 8.060933e+03, 1.310445e+04, 4.790791e+03, -8.972117e+03, 6.866951e+03, 1.356787e+04, 2.423192e+03, -6.922553e+03, 5.758467e+03, 1.397865e+04, 1.399033e+03, -5.445455e+03, 4.839055e+03, 1.434333e+04, -1.893961e+04, -2.804734e+03, 4.069198e+03, 1.466700e+04, 1.877066e+03, -4.505274e+03, 3.305315e+03, 1.495392e+04, -2.115025e+03, -3.042529e+03, 2.614916e+03, 1.519227e+04, -1.104184e+04, -1.582042e+03, 2.053080e+03, 1.539091e+04, -1.188713e+04, -1.306613e+03, 1.508474e+03, 1.555342e+04, -2.215601e+04, 1.527387e+02, 9.531955e+02, 1.567324e+04, -9.598320e+03, -2.176024e+02, 3.465646e+02, 1.574722e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.644955e+03, 6.448869e+01, 0, 0, -1.029582e+04, 6.950336e+02, 5.752530e-01, 1.793892e-03, -1.273869e+05, 6.122692e+03, 8.641528e+00, 3.498089e-02, -4.160031e+05, 2.380720e+04, 8.266186e+01, 4.377096e-01, -1.255311e+06, 6.800200e+04, 4.206646e+02, 2.985036e+00, -2.081254e+06, 1.244833e+05, 1.454439e+03, 1.399056e+01, -2.900617e+06, 1.789184e+05, 3.584258e+03, 4.729999e+01, -2.756955e+06, 1.947111e+05, 6.897862e+03, 1.251625e+02, -2.672126e+06, 1.929093e+05, 1.099130e+04, 2.723388e+02, -2.086269e+06, 1.602556e+05, 1.530917e+04, 5.125534e+02, -1.573510e+06, 1.215890e+05, 1.919192e+04, 8.597800e+02, -1.355439e+06, 8.820952e+04, 2.224744e+04, 1.318242e+03, -5.451509e+05, 3.738095e+04, 2.414097e+04, 1.882051e+03, -6.036619e+05, 2.573667e+04, 2.497727e+04, 2.530007e+03, -3.048824e+05, 1.354461e+03, 2.497001e+04, 3.250364e+03, -2.405107e+05, -7.845169e+03, 2.417257e+04, 4.017749e+03, -7.981406e+04, -1.839566e+04, 2.282880e+04, 4.812674e+03, -5.359818e+04, -1.914615e+04, 2.117668e+04, 5.613727e+03, -9.539372e+04, -1.631387e+04, 1.943298e+04, 6.409506e+03, -4.737571e+03, -2.057378e+04, 1.755731e+04, 7.189996e+03, -1.608912e+04, -1.712993e+04, 1.567655e+04, 7.938106e+03, -2.088100e+03, -1.571847e+04, 1.391656e+04, 8.650875e+03, -3.661972e+04, -1.147036e+04, 1.228681e+04, 9.323355e+03, 1.657977e+04, -1.377689e+04, 1.070581e+04, 9.954345e+03, -3.463596e+03, -9.698335e+03, 9.274149e+03, 1.053254e+04, -5.891139e+03, -8.043333e+03, 8.040790e+03, 1.106587e+04, -1.191734e+04, -6.450980e+03, 6.917247e+03, 1.155414e+04, 3.491650e+02, -6.574146e+03, 5.858587e+03, 1.199621e+04, -7.578241e+03, -4.689544e+03, 4.907900e+03, 1.238765e+04, -1.092448e+04, -3.741680e+03, 4.055337e+03, 1.273290e+04, 4.106714e+03, -4.518819e+03, 3.238118e+03, 1.303002e+04, -2.102369e+04, -1.074664e+03, 2.560131e+03, 1.327469e+04, -1.056000e+04, -2.204585e+03, 1.868347e+03, 1.347934e+04, -2.377808e+04, -1.032248e+02, 1.180047e+03, 1.362602e+04, -1.508705e+04, -9.908849e+00, 4.767186e+02, 1.371823e+04, }; static float solarDataset720[] = { 2.525918e+14, -2.554558e+09, -1.370972e+05, 5.293898e+03, -9.815726e+12, 2.361968e+09, 0, 5.292070e+03, -2.161284e+10, 3.681165e+06, 1.412622e+05, 5.309215e+03, 5.368037e+09, -9.739389e+06, 1.367183e+05, 5.355116e+03, 1.822593e+09, -3.920899e+06, 1.308458e+05, 5.439746e+03, 7.141674e+07, -1.791913e+05, 1.286456e+05, 5.575115e+03, -2.827977e+08, 6.550345e+05, 1.286106e+05, 5.776749e+03, -4.278581e+07, -3.471843e+05, 1.274126e+05, 6.058476e+03, -4.678445e+07, -3.154022e+05, 1.243004e+05, 6.425649e+03, -1.705526e+06, -5.419689e+05, 1.199770e+05, 6.883746e+03, -4.511176e+07, -2.088734e+05, 1.148018e+05, 7.432212e+03, -9.899075e+06, -5.263774e+05, 1.080124e+05, 8.072059e+03, -1.136389e+07, -4.495800e+05, 9.941715e+04, 8.783408e+03, -4.432855e+06, -4.699310e+05, 8.991963e+04, 9.551761e+03, -6.678983e+06, -3.711487e+05, 7.987525e+04, 1.035412e+04, -1.048795e+06, -3.923684e+05, 6.943065e+04, 1.117043e+04, -1.487792e+06, -3.054383e+05, 5.919156e+04, 1.197072e+04, -5.138917e+05, -2.592954e+05, 4.970314e+04, 1.273960e+04, 4.638959e+05, -2.185755e+05, 4.110096e+04, 1.345986e+04, -3.133674e+05, -1.488658e+05, 3.379813e+04, 1.412155e+04, 7.701003e+02, -1.222341e+05, 2.757857e+04, 1.472633e+04, 1.443326e+05, -9.575337e+04, 2.226568e+04, 1.526806e+04, 1.586498e+05, -7.156428e+04, 1.793449e+04, 1.574764e+04, 1.756484e+04, -4.896879e+04, 1.451310e+04, 1.617102e+04, 8.828851e+04, -3.944113e+04, 1.175869e+04, 1.654602e+04, -6.323419e+04, -2.418904e+04, 9.565046e+03, 1.687570e+04, 9.171615e+04, -2.493151e+04, 7.723482e+03, 1.716762e+04, -1.428085e+04, -1.376363e+04, 6.275414e+03, 1.741964e+04, 2.437380e+04, -1.256407e+04, 5.133211e+03, 1.764318e+04, 1.709855e+03, -8.360511e+03, 4.206652e+03, 1.783845e+04, -1.602339e+03, -6.380326e+03, 3.464464e+03, 1.801101e+04, 1.086892e+04, -5.672266e+03, 2.839413e+03, 1.816274e+04, 1.947834e+03, -3.743557e+03, 2.343114e+03, 1.829498e+04, -4.914126e+03, -2.541311e+03, 1.951555e+03, 1.841212e+04, 7.500891e+03, -2.900219e+03, 1.606900e+03, 1.851587e+04, -6.683859e+03, -1.171479e+03, 1.335113e+03, 1.860554e+04, 2.524698e+03, -1.755106e+03, 1.097230e+03, 1.868573e+04, 1.413303e+02, -1.123324e+03, 8.913331e+02, 1.875383e+04, -5.972485e+02, -8.258019e+02, 7.301851e+02, 1.881276e+04, -1.374811e+03, -6.044738e+02, 5.930501e+02, 1.886362e+04, -2.464199e+02, -6.001397e+02, 4.686460e+02, 1.890681e+04, -3.386839e+03, -1.749768e+02, 3.615101e+02, 1.894210e+04, 1.115795e+03, -5.876697e+02, 2.497363e+02, 1.897051e+04, -5.909912e+03, 3.198230e+02, 1.691543e+02, 1.898962e+04, -1.580136e+03, -5.978889e+01, 6.196234e+01, 1.900370e+04, 2.989518e+13, -1.289421e+08, 1.099829e+05, 2.834177e+03, -3.090365e+12, 6.856653e+08, 1.321869e+05, 2.836187e+03, 9.682967e+10, -5.904165e+07, 1.626712e+05, 2.856692e+03, -5.436058e+09, 6.318661e+06, 1.551570e+05, 2.907038e+03, 6.591801e+08, -1.130499e+06, 1.565831e+05, 3.007157e+03, -7.138774e+08, 1.316135e+06, 1.563922e+05, 3.171322e+03, 3.237601e+07, -7.953836e+05, 1.552515e+05, 3.417128e+03, -4.655197e+07, -3.938954e+05, 1.522345e+05, 3.753533e+03, -2.305480e+07, -4.616706e+05, 1.487543e+05, 4.192527e+03, -8.350406e+07, -1.385543e+05, 1.443327e+05, 4.741292e+03, -2.273311e+07, -6.254407e+05, 1.375714e+05, 5.403999e+03, -2.274408e+07, -5.692192e+05, 1.282140e+05, 6.164358e+03, -6.189259e+06, -6.624563e+05, 1.172277e+05, 7.007832e+03, -1.040898e+07, -5.161737e+05, 1.053028e+05, 7.908995e+03, -2.699482e+06, -5.346775e+05, 9.279238e+04, 8.847287e+03, -2.235491e+06, -4.383825e+05, 8.020280e+04, 9.789863e+03, -1.374288e+06, -3.645659e+05, 6.827003e+04, 1.071465e+04, -1.221563e+04, -3.098323e+05, 5.718372e+04, 1.159997e+04, -3.432144e+05, -2.317054e+05, 4.735807e+04, 1.242805e+04, 1.796722e+05, -1.889060e+05, 3.883150e+04, 1.319192e+04, 5.940359e+04, -1.395754e+05, 3.160908e+04, 1.388396e+04, 1.898772e+05, -1.085417e+05, 2.562541e+04, 1.450571e+04, 6.259607e+04, -7.758476e+04, 2.076082e+04, 1.505893e+04, 9.493680e+03, -5.706448e+04, 1.682657e+04, 1.555047e+04, 1.154325e+05, -4.666948e+04, 1.358994e+04, 1.598475e+04, -6.600032e+03, -3.033826e+04, 1.102596e+04, 1.636513e+04, 5.150180e+04, -2.556832e+04, 8.962958e+03, 1.670138e+04, -5.043216e+03, -1.683693e+04, 7.309487e+03, 1.699565e+04, 4.630010e+04, -1.531867e+04, 5.969269e+03, 1.725549e+04, -3.176222e+04, -7.688050e+03, 4.927359e+03, 1.748265e+04, 1.990387e+04, -9.109929e+03, 4.042288e+03, 1.768595e+04, 1.136736e+04, -6.270534e+03, 3.303928e+03, 1.786155e+04, -1.921046e+03, -4.000413e+03, 2.750164e+03, 1.801613e+04, -8.295624e+03, -2.881436e+03, 2.295908e+03, 1.815411e+04, 1.158890e+04, -3.694378e+03, 1.877598e+03, 1.827603e+04, -7.985865e+03, -1.327338e+03, 1.554511e+03, 1.838032e+04, 6.287924e+03, -2.268548e+03, 1.279719e+03, 1.847378e+04, -5.841113e+03, -7.169778e+02, 1.056665e+03, 1.855324e+04, 2.331521e+03, -1.372167e+03, 8.596951e+02, 1.862405e+04, -6.715950e+02, -7.448262e+02, 6.904255e+02, 1.868294e+04, -2.277589e+03, -4.673925e+02, 5.571070e+02, 1.873345e+04, -2.143745e+03, -4.255135e+02, 4.286454e+02, 1.877595e+04, -2.342452e+03, -3.095573e+02, 3.018268e+02, 1.880924e+04, -2.141651e+03, -1.996398e+02, 1.826752e+02, 1.883282e+04, -1.800736e+03, -5.698464e+01, 8.207416e+01, 1.884678e+04, 1.447401e+13, -8.993067e+07, 7.803754e+04, 1.013116e+03, -8.727215e+11, 2.292335e+08, 8.783964e+04, 1.014508e+03, -2.637424e+10, 1.849076e+07, 1.050400e+05, 1.026912e+03, 2.501031e+09, -8.153203e+05, 1.086648e+05, 1.062371e+03, 6.350316e+08, 1.081054e+06, 1.106769e+05, 1.131995e+03, -5.067515e+08, 2.734648e+06, 1.150568e+05, 1.250306e+03, 8.471154e+07, 7.604123e+05, 1.198954e+05, 1.435562e+03, -5.169626e+07, 1.125922e+06, 1.244427e+05, 1.702570e+03, -1.420182e+08, 1.257137e+06, 1.296866e+05, 2.073373e+03, -6.016236e+07, 4.507910e+05, 1.331301e+05, 2.568637e+03, -6.181395e+07, 2.560844e+05, 1.334031e+05, 3.194251e+03, -2.944661e+07, -1.809190e+05, 1.302883e+05, 3.952267e+03, -1.974673e+07, -3.302753e+05, 1.236749e+05, 4.825974e+03, -1.831211e+07, -3.630744e+05, 1.144628e+05, 5.793807e+03, -1.063314e+05, -5.671483e+05, 1.027316e+05, 6.825455e+03, -7.428135e+06, -3.646082e+05, 9.035604e+04, 7.875637e+03, -4.224498e+05, -4.226070e+05, 7.785079e+04, 8.928044e+03, -5.225200e+05, -3.292931e+05, 6.569603e+04, 9.939440e+03, 1.351084e+05, -2.692418e+05, 5.486961e+04, 1.089545e+04, -6.986607e+05, -1.900635e+05, 4.546374e+04, 1.178319e+04, 8.151561e+05, -1.826275e+05, 3.717645e+04, 1.259855e+04, -2.097157e+05, -1.087743e+05, 3.039241e+04, 1.332873e+04, 8.873651e+04, -9.305999e+04, 2.483143e+04, 1.399033e+04, 8.394321e+04, -7.004892e+04, 2.014053e+04, 1.457831e+04, 2.568894e+04, -5.092930e+04, 1.634436e+04, 1.509840e+04, 1.280322e+05, -4.220220e+04, 1.325641e+04, 1.555749e+04, -3.361001e+04, -2.513248e+04, 1.085224e+04, 1.596046e+04, 2.979468e+04, -2.253703e+04, 8.893598e+03, 1.631985e+04, 3.723816e+04, -1.735501e+04, 7.267372e+03, 1.663501e+04, -1.726087e+04, -1.053326e+04, 6.006399e+03, 1.691243e+04, 1.578262e+04, -1.021949e+04, 4.953342e+03, 1.715986e+04, 1.743296e+03, -6.992042e+03, 4.079600e+03, 1.737627e+04, 1.170557e+03, -5.467831e+03, 3.375752e+03, 1.756744e+04, 7.317985e+03, -4.658490e+03, 2.788852e+03, 1.773572e+04, -2.944508e+03, -2.890565e+03, 2.322051e+03, 1.788333e+04, -1.384627e+03, -2.499429e+03, 1.932715e+03, 1.801462e+04, 3.870094e+03, -2.380198e+03, 1.589263e+03, 1.812959e+04, -7.589419e+03, -9.387526e+02, 1.316390e+03, 1.822906e+04, 6.765004e+03, -2.055863e+03, 1.059421e+03, 1.831691e+04, -7.908487e+03, -1.944332e+02, 8.634886e+02, 1.838909e+04, 2.402999e+03, -1.255047e+03, 6.776365e+02, 1.845334e+04, -3.022120e+03, -3.713633e+02, 5.165854e+02, 1.850326e+04, -2.480041e+03, -3.839458e+02, 3.785083e+02, 1.854419e+04, -7.542281e+03, 2.431373e+02, 2.418575e+02, 1.857417e+04, -1.557329e+03, -1.160108e+02, 7.276011e+01, 1.859310e+04, -4.132444e+13, 4.983149e+08, 6.380020e+04, 1.851747e+02, 1.098450e+12, -2.448093e+08, 4.414219e+04, 1.862109e+02, -3.624187e+10, 2.421969e+07, 3.304274e+04, 1.899028e+02, 3.813707e+09, -2.123873e+06, 3.724471e+04, 2.020496e+02, -9.762495e+07, 2.271395e+06, 3.918961e+04, 2.259298e+02, 3.247350e+08, 1.259102e+06, 4.364256e+04, 2.695358e+02, -7.726482e+07, 2.316327e+06, 4.998989e+04, 3.423470e+02, -1.019017e+08, 2.228401e+06, 5.902081e+04, 4.620756e+02, -5.107875e+07, 1.805353e+06, 6.940990e+04, 6.504069e+02, -9.891926e+07, 1.883571e+06, 8.077203e+04, 9.326294e+02, -6.594961e+07, 1.309945e+06, 9.189406e+04, 1.340972e+03, -5.421313e+07, 8.991718e+05, 1.004014e+05, 1.895689e+03, -3.766459e+07, 4.481471e+05, 1.050914e+05, 2.607513e+03, -2.032421e+07, 5.007750e+04, 1.049523e+05, 3.466517e+03, -1.278947e+07, -1.455609e+05, 1.004758e+05, 4.443536e+03, -6.566446e+06, -2.703383e+05, 9.276981e+04, 5.502737e+03, -2.497008e+06, -3.170135e+05, 8.300714e+04, 6.601359e+03, -2.210423e+06, -2.754951e+05, 7.259218e+04, 7.700522e+03, -8.795482e+05, -2.564902e+05, 6.219949e+04, 8.772571e+03, 4.875594e+05, -2.333622e+05, 5.229111e+04, 9.788438e+03, -3.924964e+05, -1.589745e+05, 4.367724e+04, 1.073035e+04, 2.878946e+05, -1.428811e+05, 3.620966e+04, 1.160062e+04, -8.617935e+04, -9.818419e+04, 2.987112e+04, 1.238861e+04, 1.563730e+05, -8.375478e+04, 2.455211e+04, 1.310190e+04, 3.157587e+04, -5.922817e+04, 2.015025e+04, 1.373849e+04, 1.956095e+04, -4.524892e+04, 1.656404e+04, 1.430792e+04, 4.832654e+04, -3.595669e+04, 1.358688e+04, 1.481455e+04, 4.014487e+04, -2.701491e+04, 1.116623e+04, 1.526291e+04, -8.957043e+03, -1.852113e+04, 9.237221e+03, 1.566073e+04, 1.813805e+04, -1.597159e+04, 7.633708e+03, 1.601542e+04, 7.265770e+03, -1.171307e+04, 6.306238e+03, 1.632830e+04, 5.845122e+03, -9.056395e+03, 5.229642e+03, 1.660539e+04, 1.705465e+03, -6.842519e+03, 4.346327e+03, 1.685070e+04, -3.099670e+03, -5.132762e+03, 3.614027e+03, 1.706799e+04, 9.091824e+03, -4.904382e+03, 2.986894e+03, 1.725985e+04, -3.097208e+03, -2.861985e+03, 2.486454e+03, 1.742725e+04, -5.115305e+03, -2.254430e+03, 2.073917e+03, 1.757629e+04, 3.305222e+03, -2.536090e+03, 1.690410e+03, 1.770681e+04, 8.613358e+02, -1.693291e+03, 1.373974e+03, 1.781760e+04, -5.270481e+03, -8.177981e+02, 1.129554e+03, 1.791337e+04, 7.202933e+01, -1.244067e+03, 8.946304e+02, 1.799642e+04, -3.932364e+03, -5.617175e+02, 6.851235e+02, 1.806340e+04, -2.555341e+03, -5.981541e+02, 4.914744e+02, 1.811718e+04, -7.312382e+03, 8.261489e+01, 3.128333e+02, 1.815579e+04, -3.444405e+03, -5.151392e+01, 1.189236e+02, 1.818034e+04, 8.583418e+11, -5.864616e+06, 5.801889e+03, 1.923411e+01, -6.597669e+10, 1.477868e+07, 6.364852e+03, 1.933677e+01, 2.967102e+09, -1.520837e+06, 7.049525e+03, 2.020405e+01, 1.724924e+09, -8.185196e+05, 7.008149e+03, 2.245400e+01, -3.378314e+08, 1.650445e+06, 8.069082e+03, 2.703836e+01, 1.552037e+08, 6.585714e+05, 1.041940e+04, 3.695513e+01, -3.403201e+07, 1.345522e+06, 1.363123e+04, 5.551902e+01, -1.703697e+07, 1.439665e+06, 1.903317e+04, 9.145205e+01, -9.003897e+07, 1.961474e+06, 2.698744e+04, 1.586961e+02, -6.267348e+07, 1.801412e+06, 3.788213e+04, 2.823781e+02, -7.470787e+07, 1.811829e+06, 5.060948e+04, 4.922647e+02, -5.781055e+07, 1.427287e+06, 6.398865e+04, 8.261355e+02, -4.006817e+07, 9.697074e+05, 7.540147e+04, 1.312352e+03, -3.092562e+07, 6.019593e+05, 8.322421e+04, 1.964145e+03, -1.617086e+07, 1.930166e+05, 8.632748e+04, 2.776467e+03, -7.153255e+06, -5.054112e+04, 8.478684e+04, 3.717483e+03, -8.315402e+06, -7.881484e+04, 8.021572e+04, 4.749714e+03, -1.434409e+06, -2.349591e+05, 7.304797e+04, 5.840556e+03, -1.429239e+06, -2.030418e+05, 6.452381e+04, 6.933083e+03, -6.545407e+05, -1.903916e+05, 5.599103e+04, 8.003800e+03, -3.793090e+04, -1.703670e+05, 4.774203e+04, 9.026419e+03, -9.296898e+04, -1.335883e+05, 4.028177e+04, 9.983296e+03, 5.681627e+04, -1.098699e+05, 3.373445e+04, 1.086875e+04, 7.934290e+04, -8.617558e+04, 2.809759e+04, 1.167776e+04, -1.118900e+05, -6.075673e+04, 2.336891e+04, 1.241185e+04, 2.127956e+05, -5.972293e+04, 1.927296e+04, 1.307544e+04, -1.157300e+04, -3.572063e+04, 1.597792e+04, 1.366415e+04, -1.006642e+04, -2.856674e+04, 1.333737e+04, 1.419680e+04, 2.851548e+04, -2.432571e+04, 1.105653e+04, 1.467415e+04, 1.366951e+04, -1.801951e+04, 9.163722e+03, 1.509781e+04, 2.547955e+03, -1.350032e+04, 7.624751e+03, 1.547499e+04, 1.201292e+04, -1.116877e+04, 6.343424e+03, 1.581086e+04, -7.993522e+03, -7.540323e+03, 5.292034e+03, 1.610860e+04, 1.389183e+04, -7.477679e+03, 4.396669e+03, 1.637388e+04, -4.384238e+03, -4.479632e+03, 3.669053e+03, 1.660659e+04, -3.138125e+03, -3.810639e+03, 3.067716e+03, 1.681444e+04, 2.205661e+03, -3.486730e+03, 2.530998e+03, 1.699733e+04, 3.541657e+03, -2.789475e+03, 2.081942e+03, 1.715588e+04, -6.419750e+03, -1.349094e+03, 1.732402e+03, 1.729391e+04, -3.412184e+03, -1.520739e+03, 1.412396e+03, 1.741589e+04, -1.601511e+03, -1.397792e+03, 1.100329e+03, 1.751816e+04, 1.155029e+03, -1.304754e+03, 8.286155e+02, 1.760046e+04, -1.103308e+04, 2.218581e+02, 6.236810e+02, 1.766473e+04, -2.654581e+03, -6.688353e+02, 3.763136e+02, 1.771593e+04, -3.364310e+03, -1.387471e+02, 1.691463e+02, 1.774386e+04, -3.366371e+12, 4.551509e+07, 2.521199e+03, 1.176103e+00, 4.269705e+10, -9.375992e+06, 1.089486e+03, 1.215845e+00, -2.678077e+09, 1.632330e+06, 6.917876e+02, 1.285806e+00, 5.646428e+08, -4.307335e+05, 8.992048e+02, 1.593390e+00, -6.281455e+07, 4.035231e+05, 1.038831e+03, 2.138181e+00, 3.725795e+07, 2.678653e+05, 1.679090e+03, 3.603652e+00, -1.868599e+07, 6.078925e+05, 2.794495e+03, 7.040473e+00, -2.585413e+07, 8.892713e+05, 5.187431e+03, 1.587553e+01, -6.872034e+07, 1.419539e+06, 9.710418e+03, 3.789527e+01, -5.812931e+07, 1.579306e+06, 1.744566e+04, 9.048376e+01, -7.327242e+07, 1.818701e+06, 2.839538e+04, 2.005187e+02, -6.016819e+07, 1.612661e+06, 4.199317e+04, 4.081326e+02, -4.581463e+07, 1.252723e+06, 5.561195e+04, 7.517504e+02, -3.153234e+07, 8.265349e+05, 6.688402e+04, 1.259016e+03, -1.853079e+07, 4.259439e+05, 7.406056e+04, 1.936723e+03, -1.281312e+07, 1.802667e+05, 7.674943e+04, 2.768831e+03, -5.976285e+06, -3.734133e+04, 7.529271e+04, 3.725956e+03, -3.885336e+06, -1.139315e+05, 7.068494e+04, 4.762226e+03, -1.400809e+06, -1.718468e+05, 6.415010e+04, 5.837947e+03, -8.976969e+05, -1.633241e+05, 5.674855e+04, 6.911982e+03, -2.378758e+05, -1.548497e+05, 4.928211e+04, 7.958122e+03, -4.067629e+05, -1.224513e+05, 4.221302e+04, 8.953753e+03, 3.647054e+05, -1.214788e+05, 3.566013e+04, 9.887462e+03, -3.019450e+05, -7.317725e+04, 3.004861e+04, 1.074445e+04, 2.857755e+05, -7.965496e+04, 2.512925e+04, 1.153600e+04, -1.459626e+05, -4.460431e+04, 2.100972e+04, 1.224792e+04, 1.068546e+05, -4.654852e+04, 1.751428e+04, 1.289850e+04, 1.656740e+04, -3.151584e+04, 1.455586e+04, 1.347833e+04, 3.276173e+04, -2.545561e+04, 1.216656e+04, 1.400043e+04, -2.466748e+04, -1.712349e+04, 1.020130e+04, 1.446904e+04, 1.127833e+04, -1.587340e+04, 8.510004e+03, 1.489124e+04, 1.967525e+04, -1.277787e+04, 7.060958e+03, 1.526518e+04, -5.566324e+03, -8.375268e+03, 5.904955e+03, 1.559653e+04, 6.832170e+03, -7.582035e+03, 4.940098e+03, 1.589320e+04, -1.505137e+03, -5.380298e+03, 4.129024e+03, 1.615572e+04, -4.851997e+03, -4.146360e+03, 3.449533e+03, 1.638915e+04, 6.220823e+03, -4.200678e+03, 2.847212e+03, 1.659502e+04, -2.257540e+03, -2.529572e+03, 2.356955e+03, 1.677328e+04, -6.506661e+03, -1.772864e+03, 1.953201e+03, 1.693045e+04, 1.966362e+03, -2.261074e+03, 1.566694e+03, 1.706682e+04, -2.160232e+03, -1.314709e+03, 1.240209e+03, 1.717955e+04, -6.509197e+03, -6.756691e+02, 9.705296e+02, 1.727398e+04, -3.335667e+03, -8.945697e+02, 6.952550e+02, 1.735046e+04, -1.024257e+04, 1.096345e+02, 4.408097e+02, 1.740488e+04, -4.884337e+03, -6.995646e+01, 1.680061e+02, 1.743947e+04, 5.051346e+10, -3.482968e+05, -3.302132e+01, 1.117732e-02, -6.399594e+09, 1.170259e+06, 0, 1.076335e-02, 2.378197e+07, -1.273564e+04, 2.884079e+00, 1.655900e-02, -4.193101e+07, 6.299121e+04, 2.194923e+00, 1.697297e-02, 2.186069e+06, 9.422620e+03, 3.137534e+01, 3.311800e-02, 3.955651e+06, 1.710432e+04, 5.844243e+01, 7.906922e-02, -5.048300e+06, 8.807915e+04, 1.413038e+02, 2.281002e-01, -5.834264e+06, 1.808251e+05, 4.543665e+02, 9.066052e-01, -1.717877e+07, 4.260059e+05, 1.359382e+03, 3.620625e+00, -3.208799e+07, 7.976457e+05, 3.825320e+03, 1.376715e+01, -4.503408e+07, 1.172645e+06, 9.176929e+03, 4.577239e+01, -4.518399e+07, 1.327171e+06, 1.816020e+04, 1.279439e+02, -4.202028e+07, 1.290199e+06, 2.997675e+04, 2.998951e+02, -3.158344e+07, 1.021061e+06, 4.259877e+04, 6.043667e+02, -2.250542e+07, 7.018793e+05, 5.343008e+04, 1.070337e+03, -1.237124e+07, 3.643660e+05, 6.071096e+04, 1.705578e+03, -9.254795e+06, 1.838508e+05, 6.403515e+04, 2.492654e+03, -4.016937e+06, -5.014300e+03, 6.370683e+04, 3.405094e+03, -3.183145e+06, -5.838735e+04, 6.052375e+04, 4.397082e+03, -6.326153e+05, -1.310928e+05, 5.546362e+04, 5.432589e+03, -8.980466e+05, -1.100814e+05, 4.957269e+04, 6.467941e+03, -1.845464e+05, -1.171335e+05, 4.351408e+04, 7.484261e+03, -7.330240e+04, -1.000436e+05, 3.759655e+04, 8.455153e+03, -8.536306e+04, -8.124805e+04, 3.220664e+04, 9.369683e+03, 6.271460e+04, -7.084973e+04, 2.735632e+04, 1.022133e+04, -6.549462e+04, -5.149641e+04, 2.313856e+04, 1.100420e+04, 1.042378e+05, -4.819678e+04, 1.945257e+04, 1.172164e+04, -6.586040e+03, -3.243944e+04, 1.636407e+04, 1.236958e+04, 1.937888e+04, -2.723890e+04, 1.379626e+04, 1.295960e+04, -2.094192e+04, -1.965536e+04, 1.161032e+04, 1.349253e+04, 2.879330e+04, -1.852871e+04, 9.713757e+03, 1.397336e+04, 1.432240e+04, -1.343548e+04, 8.130835e+03, 1.440101e+04, -1.821063e+04, -8.725253e+03, 6.865050e+03, 1.478482e+04, 1.419588e+04, -9.358718e+03, 5.748762e+03, 1.513083e+04, 1.055273e+03, -6.305478e+03, 4.805868e+03, 1.543573e+04, -5.662820e+03, -4.626779e+03, 4.041581e+03, 1.570792e+04, 3.620958e+02, -4.298662e+03, 3.366303e+03, 1.595011e+04, 1.279925e+03, -3.472943e+03, 2.779108e+03, 1.616176e+04, -8.119412e+03, -1.999793e+03, 2.294268e+03, 1.634600e+04, 2.703808e+03, -2.683207e+03, 1.844539e+03, 1.650646e+04, -5.608882e+03, -1.263187e+03, 1.464334e+03, 1.663925e+04, -2.539837e+03, -1.379024e+03, 1.128950e+03, 1.675095e+04, -6.360200e+03, -6.734980e+02, 8.228503e+02, 1.683877e+04, -1.233536e+04, 1.203160e+02, 5.305324e+02, 1.690457e+04, -5.730992e+03, -9.461582e+01, 1.996954e+02, 1.694608e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.824802e+05, 5.662913e+02, 0, 0, -2.089360e+05, 7.956041e+02, 5.856313e-01, 4.139750e-04, 2.204465e+05, -3.219661e+02, 1.539320e+00, 2.483850e-03, -2.076559e+05, 5.716207e+03, 3.299164e+00, 6.623600e-03, -1.630833e+06, 3.651570e+04, 3.131705e+01, 5.961240e-02, -4.750601e+06, 1.270860e+05, 2.360423e+02, 6.023336e-01, -1.059805e+07, 3.175159e+05, 1.112384e+03, 3.994031e+00, -1.908619e+07, 5.949891e+05, 3.700632e+03, 1.870919e+01, -2.366093e+07, 8.041978e+05, 9.162593e+03, 6.578187e+01, -2.229039e+07, 8.434683e+05, 1.752631e+04, 1.799168e+02, -1.954097e+07, 7.599747e+05, 2.748722e+04, 4.014783e+02, -1.339870e+07, 5.499302e+05, 3.708410e+04, 7.652249e+02, -1.029819e+07, 3.727003e+05, 4.454472e+04, 1.285347e+03, -4.368519e+06, 1.495000e+05, 4.891481e+04, 1.957839e+03, -4.419116e+06, 8.860581e+04, 5.036253e+04, 2.752876e+03, -1.481145e+06, -3.114013e+04, 4.934483e+04, 3.647707e+03, -1.131953e+06, -5.304541e+04, 4.640097e+04, 4.594923e+03, -4.087520e+05, -7.696885e+04, 4.249037e+04, 5.566846e+03, -4.277536e+05, -6.969004e+04, 3.810892e+04, 6.533158e+03, -3.981790e+04, -7.471184e+04, 3.357954e+04, 7.475552e+03, -5.532513e+04, -6.146236e+04, 2.921408e+04, 8.372805e+03, 2.297742e+04, -5.372960e+04, 2.523788e+04, 9.218872e+03, -4.526357e+04, -4.095211e+04, 2.170188e+04, 1.000775e+04, 2.858501e+04, -3.694172e+04, 1.854799e+04, 1.073977e+04, -3.310096e+04, -2.679609e+04, 1.578940e+04, 1.141043e+04, 8.050741e+04, -2.739862e+04, 1.336283e+04, 1.202398e+04, -6.328003e+04, -1.355651e+04, 1.138577e+04, 1.257725e+04, 3.556582e+04, -1.753080e+04, 9.641932e+03, 1.308660e+04, -1.740585e+03, -1.121468e+04, 8.123657e+03, 1.354004e+04, 4.908269e+03, -9.544626e+03, 6.882834e+03, 1.395006e+04, -1.374891e+04, -6.463029e+03, 5.824501e+03, 1.431834e+04, 1.616534e+04, -7.552350e+03, 4.872531e+03, 1.464918e+04, -1.772732e+04, -3.244296e+03, 4.094072e+03, 1.493915e+04, 9.689841e+03, -5.153985e+03, 3.394548e+03, 1.520003e+04, -9.718081e+03, -2.277143e+03, 2.798639e+03, 1.542337e+04, -6.633543e+02, -2.845618e+03, 2.278206e+03, 1.562014e+04, -4.278643e+03, -1.892766e+03, 1.806022e+03, 1.578510e+04, -5.433639e+03, -1.433992e+03, 1.392542e+03, 1.592207e+04, -7.648617e+03, -9.150271e+02, 1.007781e+03, 1.603088e+04, -8.612245e+03, -4.992492e+02, 6.366121e+02, 1.611080e+04, -6.343749e+03, -2.056231e+02, 2.914770e+02, 1.616025e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1.135457e+04, 2.791630e+02, 0, 0, -7.955274e+04, 2.985927e+03, 1.611854e+00, 3.311800e-03, -6.493155e+05, 2.185150e+04, 2.430096e+01, 6.789190e-02, -2.078383e+06, 8.094823e+04, 2.102422e+02, 7.973158e-01, -6.000804e+06, 2.164166e+05, 1.026160e+03, 5.360976e+00, -7.509681e+06, 3.346173e+05, 3.348784e+03, 2.463110e+01, -9.709505e+06, 4.476003e+05, 7.656050e+03, 7.966162e+01, -9.777442e+06, 4.686826e+05, 1.394700e+04, 2.033979e+02, -7.272808e+06, 3.875450e+05, 2.106614e+04, 4.303630e+02, -6.067236e+06, 3.045882e+05, 2.765451e+04, 7.835942e+02, -3.743681e+06, 1.836085e+05, 3.273701e+04, 1.274002e+03, -2.204422e+06, 9.353882e+04, 3.571808e+04, 1.890326e+03, -1.657859e+06, 4.246821e+04, 3.683928e+04, 2.612254e+03, -8.290594e+05, -6.996218e+03, 3.633556e+04, 3.416065e+03, -4.247261e+05, -3.007731e+04, 3.457926e+04, 4.269476e+03, -4.641352e+05, -3.218306e+04, 3.213056e+04, 5.146662e+03, 3.361520e+04, -5.076883e+04, 2.915608e+04, 6.027337e+03, -1.771637e+05, -3.534656e+04, 2.610100e+04, 6.884571e+03, -4.187517e+04, -3.789010e+04, 2.312238e+04, 7.715656e+03, 8.157849e+04, -3.709787e+04, 2.020432e+04, 8.503474e+03, -1.077364e+05, -2.122007e+04, 1.767673e+04, 9.241847e+03, 3.794355e+04, -2.646253e+04, 1.532351e+04, 9.938986e+03, -2.130421e+03, -1.891377e+04, 1.317205e+04, 1.057852e+04, 2.458205e+03, -1.585926e+04, 1.133734e+04, 1.116822e+04, -1.024932e+04, -1.227472e+04, 9.729063e+03, 1.170859e+04, 1.302318e+04, -1.167431e+04, 8.296256e+03, 1.220175e+04, -2.645825e+03, -8.200160e+03, 7.072718e+03, 1.264649e+04, -1.946731e+04, -5.712138e+03, 6.033100e+03, 1.305017e+04, 1.908928e+04, -7.856404e+03, 5.040421e+03, 1.341373e+04, -1.921842e+04, -2.904171e+03, 4.229674e+03, 1.372996e+04, 7.815975e+03, -5.041356e+03, 3.502309e+03, 1.401481e+04, -1.222105e+04, -2.090158e+03, 2.867188e+03, 1.425719e+04, -1.443808e+03, -2.926865e+03, 2.291167e+03, 1.446851e+04, -8.489031e+03, -1.591866e+03, 1.763443e+03, 1.464092e+04, -6.705956e+03, -1.467380e+03, 1.277843e+03, 1.477936e+04, -2.081073e+04, 4.070825e+02, 8.281583e+02, 1.488046e+04, -8.711751e+03, -1.750566e+02, 3.099560e+02, 1.494590e+04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.563361e+03, 1.163545e+02, 0, 0, -4.016111e+04, 1.858785e+03, 1.077420e+00, 3.311800e-03, -2.538882e+05, 1.204296e+04, 2.087577e+01, 8.486487e-02, -8.568045e+05, 4.291307e+04, 1.658171e+02, 9.066052e-01, -1.848280e+06, 9.915324e+04, 7.465497e+02, 5.567136e+00, -2.940953e+06, 1.660291e+05, 2.247529e+03, 2.303978e+01, -3.370234e+06, 2.089797e+05, 5.011666e+03, 7.097312e+01, -3.259946e+06, 2.186080e+05, 8.892565e+03, 1.735888e+02, -3.097047e+06, 2.032584e+05, 1.336445e+04, 3.563617e+02, -1.821542e+06, 1.437017e+05, 1.764923e+04, 6.394746e+02, -1.802035e+06, 1.171823e+05, 2.118802e+04, 1.028337e+03, -1.000732e+06, 6.321832e+04, 2.372803e+04, 1.525758e+03, -7.690809e+05, 3.504376e+04, 2.503483e+04, 2.115529e+03, -3.914894e+05, 6.298728e+03, 2.528814e+04, 2.781267e+03, -3.035803e+05, -5.220347e+03, 2.468978e+04, 3.499590e+03, -1.135560e+05, -1.761802e+04, 2.348786e+04, 4.251977e+03, -1.801992e+05, -1.570171e+04, 2.191753e+04, 5.017650e+03, 1.706318e+04, -2.545515e+04, 2.006382e+04, 5.784350e+03, -6.797234e+04, -1.795386e+04, 1.815090e+04, 6.531178e+03, -1.793578e+04, -1.930896e+04, 1.628261e+04, 7.256949e+03, -2.326593e+04, -1.656161e+04, 1.443550e+04, 7.949046e+03, 2.835627e+04, -1.719413e+04, 1.268036e+04, 8.602624e+03, -3.200616e+04, -1.034425e+04, 1.113968e+04, 9.211894e+03, -1.865985e+04, -1.040495e+04, 9.723009e+03, 9.784332e+03, 3.642018e+04, -1.251177e+04, 8.326634e+03, 1.030995e+04, -3.566772e+04, -4.462584e+03, 7.200285e+03, 1.078360e+04, 1.006844e+04, -8.044621e+03, 6.164034e+03, 1.122405e+04, -1.216649e+04, -4.566143e+03, 5.198882e+03, 1.161386e+04, 2.635189e+03, -5.240412e+03, 4.341674e+03, 1.196312e+04, -9.610371e+03, -3.091591e+03, 3.584704e+03, 1.226633e+04, -5.856573e+03, -3.064976e+03, 2.898065e+03, 1.253040e+04, -1.080053e+04, -2.040908e+03, 2.251652e+03, 1.275061e+04, -1.117498e+04, -1.629984e+03, 1.631049e+03, 1.292734e+04, -1.961133e+04, -2.300963e+02, 1.034000e+03, 1.305636e+04, -1.288515e+04, -4.832654e+01, 4.255474e+02, 1.313697e+04, }; static float *solarDatasets[] = {solarDataset320, solarDataset360, solarDataset400, solarDataset440, solarDataset480, solarDataset520, solarDataset560, solarDataset600, solarDataset640, solarDataset680, solarDataset720}; static float limbDarkeningDataset320[] = { 0.087657, 0.767174, 0.658123, -1.02953, 0.703297, -0.186735}; static float limbDarkeningDataset360[] = { 0.122953, 1.01278, 0.238687, -1.12208, 1.17087, -0.424947}; static float limbDarkeningDataset400[] = { 0.123511, 1.08444, -0.405598, 0.370629, -0.240567, 0.0674778}; static float limbDarkeningDataset440[] = { 0.158489, 1.23346, -0.875754, 0.857812, -0.484919, 0.110895}; static float limbDarkeningDataset480[] = { 0.198587, 1.30507, -1.25998, 1.49727, -1.04047, 0.299516}; static float limbDarkeningDataset520[] = { 0.23695, 1.29927, -1.28034, 1.37760, -0.85054, 0.21706}; static float limbDarkeningDataset560[] = { 0.26892, 1.34319, -1.58427, 1.91271, -1.31350, 0.37295}; static float limbDarkeningDataset600[] = { 0.299804, 1.36718, -1.80884, 2.29294, -1.60595, 0.454874}; static float limbDarkeningDataset640[] = { 0.33551, 1.30791, -1.79382, 2.44646, -1.89082, 0.594769}; static float limbDarkeningDataset680[] = { 0.364007, 1.27316, -1.73824, 2.28535, -1.70203, 0.517758}; static float limbDarkeningDataset720[] = { 0.389704, 1.2448, -1.69708, 2.14061, -1.51803, 0.440004}; static float *limbDarkeningDatasets[] = {limbDarkeningDataset320, limbDarkeningDataset360, limbDarkeningDataset400, limbDarkeningDataset440, limbDarkeningDataset480, limbDarkeningDataset520, limbDarkeningDataset560, limbDarkeningDataset600, limbDarkeningDataset640, limbDarkeningDataset680, limbDarkeningDataset720}; RenderKit-ospray-f2a61c2/modules/cpu/math/000077500000000000000000000000001456566705700205375ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/math/Distribution1D.ih000066400000000000000000000030531456566705700237260ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/math.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // input: importance in 'cdf' // output: cdf of importance in 'cdf' // return sum SYCL_EXTERNAL export uniform float Distribution1D_create( const uniform int size, uniform float *uniform cdf); struct Sample1D { int idx; // relative sample index to start float frac; // relative prosition of the random sample inside // the selected bin (useful for random sample re-using) float pdf; // the pdf of sampling the position idx+frac // when frac is sampled uniformly inside the idx^th bin float prob; // the probability of sampling the idx^th bin }; inline Sample1D Distribution1D_sample(const uniform int size, const uniform float *uniform cdf, // we may sample different rows within one gang: use a varying offset // 'start' instead of a varying pointer 'cdf' const int start, const float s) { // find minimum index where cdf[i-1] <= s < cdf[i] int first = start; int len = size; while (len > 0) { const int half = len >> 1; const int mid = first + half; if (s < cdf[mid]) { len = half; } else { first = mid + 1; len -= half + 1; } } Sample1D ret; ret.idx = first - start; const float bef = first == start ? 0.0f : cdf[first - 1]; const float dpdf = cdf[first] - bef; ret.prob = dpdf; ret.pdf = dpdf * size; ret.frac = (s - bef) * rcp(dpdf); // rescale return ret; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/math/Distribution1D.ispc000066400000000000000000000020661456566705700242670ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Distribution1D.ih" #ifdef OSPRAY_TARGET_SYCL #include #endif // Pre-condition: size > 0 OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL export uniform float Distribution1D_create( const uniform int size, uniform float *uniform cdf) { // accumulate the function // using varying float and exclusive_scan_add(float v) is much slower uniform float sum = cdf[0]; for (uniform int i = 1; i < size; i++) cdf[i] = sum += cdf[i]; // compute reciprocal sum const uniform float rcpSum = 1.0f / sum; // next representable number in float greater than 1.0f const uniform float nextAfter1 = 0x1.000002p+0f; // normalize #ifdef OSPRAY_TARGET_SYCL for (int i = 0; i < size; ++i) { #else foreach (i = 0 ... size) { #endif const float c = cdf[i]; // handle cornercases (sum=0 -> rcpSum=inf; correct termination of sampling // with s=1.0f) const float q = c >= sum ? nextAfter1 : c * rcpSum; cdf[i] = q; } return sum; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/math/Distribution2D.cpp000066400000000000000000000012001456566705700241010ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Distribution2D.h" #include "common/ISPCRTBuffers.h" namespace ospray { Distribution2D::Distribution2D(const vec2i &size, api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device) { getSh()->size = size; getSh()->rcpSize = vec2f(1.f / size.x, 1.f / size.y); cdf_x = make_buffer_shared_unique( device.getIspcrtContext(), size.x * size.y); cdf_y = make_buffer_shared_unique(device.getIspcrtContext(), size.y); getSh()->cdf_x = cdf_x->data(); getSh()->cdf_y = cdf_y->data(); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/math/Distribution2D.h000066400000000000000000000011141456566705700235520ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include "ISPCDevice.h" #include "ISPCDeviceObject.h" #include "common/OSPCommon.h" #include "common/StructShared.h" // ispc shared #include "Distribution2DShared.h" namespace ospray { struct OSPRAY_SDK_INTERFACE Distribution2D : public AddStructShared { Distribution2D(const vec2i &size, api::ISPCDevice &device); std::unique_ptr> cdf_x; std::unique_ptr> cdf_y; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/math/Distribution2D.ih000066400000000000000000000012751456566705700237330ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/vec.ih" // c++ shared #include "Distribution2DShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE // Initialize the 2D distribution after populating the input cdf_x array // and writing f_y into cdf_y. The distribution will then compute cdf_y from f_y SYCL_EXTERNAL void Distribution2D_init(Distribution2D *uniform self); struct Sample2D { vec2f uv; float pdf; }; // inline? SYCL_EXTERNAL Sample2D Distribution2D_sample( const Distribution2D *uniform, const vec2f &s); SYCL_EXTERNAL float Distribution2D_pdf( const Distribution2D *uniform, const vec2f &uv); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/math/Distribution2D.ispc000066400000000000000000000027121456566705700242660ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Distribution1D.ih" #include "Distribution2D.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL Sample2D Distribution2D_sample( const uniform Distribution2D *uniform self, const vec2f &s) { // use u.y to sample a row const Sample1D sy = Distribution1D_sample(self->size.y, self->cdf_y, 0, s.y); // use u.x to sample inside the row const int x0 = sy.idx * self->size.x; const Sample1D sx = Distribution1D_sample(self->size.x, self->cdf_x, x0, s.x); Sample2D ret; ret.uv = make_vec2f((sx.idx + sx.frac) * self->rcpSize.x, (sy.idx + sy.frac) * self->rcpSize.y); ret.pdf = sx.pdf * sy.pdf; return ret; } SYCL_EXTERNAL float Distribution2D_pdf( const uniform Distribution2D *uniform self, const vec2f &uv) { const int idy = clamp((int)(uv.y * self->size.y), 0, self->size.y - 1); const float befy = idy == 0 ? 0.0f : self->cdf_y[idy - 1]; const float pdf_y = (self->cdf_y[idy] - befy) * self->size.y; const int idx = clamp((int)(uv.x * self->size.x), 0, self->size.x - 1); const int x0 = idy * self->size.x; const float befx = idx == 0 ? 0.0f : self->cdf_x[x0 + idx - 1]; const float pdf_x = (self->cdf_x[x0 + idx] - befx) * self->size.x; return pdf_x * pdf_y; } SYCL_EXTERNAL void Distribution2D_init(Distribution2D *uniform self) { // initialize the y distribution Distribution1D_create(self->size.y, self->cdf_y); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/math/Distribution2DShared.h000066400000000000000000000007011456566705700247020ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Distribution2D { vec2i size; // 1/size vec2f rcpSize; // size.x*size.y elements float *cdf_x; // size.y elements float *cdf_y; #ifdef __cplusplus Distribution2D() : size(0), rcpSize(0.f), cdf_x(nullptr), cdf_y(nullptr) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/math/MathConstants.cpp000066400000000000000000000027111456566705700240320ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "math/MathConstants.h" #include "math/halton.h" #include "math/sobol.h" namespace ospray { MathConstants::MathConstants(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext()) { haltonPerm3Buf = make_buffer_shared_unique(device.getIspcrtContext(), 243); haltonPerm5Buf = make_buffer_shared_unique(device.getIspcrtContext(), 125); haltonPerm7Buf = make_buffer_shared_unique(device.getIspcrtContext(), 343); sobolMatricesBuf = make_buffer_shared_unique( device.getIspcrtContext(), Sobol_numDimensions * Sobol_numBits); std::memcpy(haltonPerm3Buf->begin(), halton_perm3, haltonPerm3Buf->size() * sizeof(unsigned int)); std::memcpy(haltonPerm5Buf->begin(), halton_perm5, haltonPerm5Buf->size() * sizeof(unsigned int)); std::memcpy(haltonPerm7Buf->begin(), halton_perm7, haltonPerm7Buf->size() * sizeof(unsigned int)); std::memcpy(sobolMatricesBuf->begin(), Sobol_matrices, sobolMatricesBuf->size() * sizeof(unsigned int)); getSh()->haltonPerm3 = haltonPerm3Buf->data(); getSh()->haltonPerm5 = haltonPerm5Buf->data(); getSh()->haltonPerm7 = haltonPerm7Buf->data(); getSh()->sobolMatrices = sobolMatricesBuf->data(); } std::string MathConstants::toString() const { return "ospray::MathConstants"; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/math/MathConstants.h000066400000000000000000000014521456566705700235000ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ISPCDevice.h" #include "common/Managed.h" #include "common/StructShared.h" // ispc shared #include "MathConstantsShared.h" namespace ospray { /* MathConstants manages storing the precompute RNG sequence data in USM */ struct OSPRAY_SDK_INTERFACE MathConstants : public AddStructShared { MathConstants(api::ISPCDevice &device); virtual std::string toString() const override; private: std::unique_ptr> haltonPerm3Buf; std::unique_ptr> haltonPerm5Buf; std::unique_ptr> haltonPerm7Buf; std::unique_ptr> sobolMatricesBuf; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/math/MathConstantsShared.h000066400000000000000000000010021456566705700246160ustar00rootroot00000000000000// Copyright 2009-2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct MathConstants { unsigned int *haltonPerm3; unsigned int *haltonPerm5; unsigned int *haltonPerm7; unsigned int *sobolMatrices; #ifdef __cplusplus MathConstants() : haltonPerm3(nullptr), haltonPerm5(nullptr), haltonPerm7(nullptr), sobolMatrices(nullptr) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/math/halton.cpp000066400000000000000000000164621456566705700225410ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // Copyright (c) 2012 Leonhard Gruenschloss (leonhard@gruenschloss.org) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #include "math/halton.h" namespace ospray { const unsigned int halton_perm3[243] = {0, 81, 162, 27, 108, 189, 54, 135, 216, 9, 90, 171, 36, 117, 198, 63, 144, 225, 18, 99, 180, 45, 126, 207, 72, 153, 234, 3, 84, 165, 30, 111, 192, 57, 138, 219, 12, 93, 174, 39, 120, 201, 66, 147, 228, 21, 102, 183, 48, 129, 210, 75, 156, 237, 6, 87, 168, 33, 114, 195, 60, 141, 222, 15, 96, 177, 42, 123, 204, 69, 150, 231, 24, 105, 186, 51, 132, 213, 78, 159, 240, 1, 82, 163, 28, 109, 190, 55, 136, 217, 10, 91, 172, 37, 118, 199, 64, 145, 226, 19, 100, 181, 46, 127, 208, 73, 154, 235, 4, 85, 166, 31, 112, 193, 58, 139, 220, 13, 94, 175, 40, 121, 202, 67, 148, 229, 22, 103, 184, 49, 130, 211, 76, 157, 238, 7, 88, 169, 34, 115, 196, 61, 142, 223, 16, 97, 178, 43, 124, 205, 70, 151, 232, 25, 106, 187, 52, 133, 214, 79, 160, 241, 2, 83, 164, 29, 110, 191, 56, 137, 218, 11, 92, 173, 38, 119, 200, 65, 146, 227, 20, 101, 182, 47, 128, 209, 74, 155, 236, 5, 86, 167, 32, 113, 194, 59, 140, 221, 14, 95, 176, 41, 122, 203, 68, 149, 230, 23, 104, 185, 50, 131, 212, 77, 158, 239, 8, 89, 170, 35, 116, 197, 62, 143, 224, 17, 98, 179, 44, 125, 206, 71, 152, 233, 26, 107, 188, 53, 134, 215, 80, 161, 242}; const unsigned int halton_perm5[125] = {0, 75, 50, 25, 100, 15, 90, 65, 40, 115, 10, 85, 60, 35, 110, 5, 80, 55, 30, 105, 20, 95, 70, 45, 120, 3, 78, 53, 28, 103, 18, 93, 68, 43, 118, 13, 88, 63, 38, 113, 8, 83, 58, 33, 108, 23, 98, 73, 48, 123, 2, 77, 52, 27, 102, 17, 92, 67, 42, 117, 12, 87, 62, 37, 112, 7, 82, 57, 32, 107, 22, 97, 72, 47, 122, 1, 76, 51, 26, 101, 16, 91, 66, 41, 116, 11, 86, 61, 36, 111, 6, 81, 56, 31, 106, 21, 96, 71, 46, 121, 4, 79, 54, 29, 104, 19, 94, 69, 44, 119, 14, 89, 64, 39, 114, 9, 84, 59, 34, 109, 24, 99, 74, 49, 124}; const unsigned int halton_perm7[343] = {0, 98, 245, 147, 49, 196, 294, 14, 112, 259, 161, 63, 210, 308, 35, 133, 280, 182, 84, 231, 329, 21, 119, 266, 168, 70, 217, 315, 7, 105, 252, 154, 56, 203, 301, 28, 126, 273, 175, 77, 224, 322, 42, 140, 287, 189, 91, 238, 336, 2, 100, 247, 149, 51, 198, 296, 16, 114, 261, 163, 65, 212, 310, 37, 135, 282, 184, 86, 233, 331, 23, 121, 268, 170, 72, 219, 317, 9, 107, 254, 156, 58, 205, 303, 30, 128, 275, 177, 79, 226, 324, 44, 142, 289, 191, 93, 240, 338, 5, 103, 250, 152, 54, 201, 299, 19, 117, 264, 166, 68, 215, 313, 40, 138, 285, 187, 89, 236, 334, 26, 124, 271, 173, 75, 222, 320, 12, 110, 257, 159, 61, 208, 306, 33, 131, 278, 180, 82, 229, 327, 47, 145, 292, 194, 96, 243, 341, 3, 101, 248, 150, 52, 199, 297, 17, 115, 262, 164, 66, 213, 311, 38, 136, 283, 185, 87, 234, 332, 24, 122, 269, 171, 73, 220, 318, 10, 108, 255, 157, 59, 206, 304, 31, 129, 276, 178, 80, 227, 325, 45, 143, 290, 192, 94, 241, 339, 1, 99, 246, 148, 50, 197, 295, 15, 113, 260, 162, 64, 211, 309, 36, 134, 281, 183, 85, 232, 330, 22, 120, 267, 169, 71, 218, 316, 8, 106, 253, 155, 57, 204, 302, 29, 127, 274, 176, 78, 225, 323, 43, 141, 288, 190, 92, 239, 337, 4, 102, 249, 151, 53, 200, 298, 18, 116, 263, 165, 67, 214, 312, 39, 137, 284, 186, 88, 235, 333, 25, 123, 270, 172, 74, 221, 319, 11, 109, 256, 158, 60, 207, 305, 32, 130, 277, 179, 81, 228, 326, 46, 144, 291, 193, 95, 242, 340, 6, 104, 251, 153, 55, 202, 300, 20, 118, 265, 167, 69, 216, 314, 41, 139, 286, 188, 90, 237, 335, 27, 125, 272, 174, 76, 223, 321, 13, 111, 258, 160, 62, 209, 307, 34, 132, 279, 181, 83, 230, 328, 48, 146, 293, 195, 97, 244, 342}; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/math/halton.h000066400000000000000000000025701456566705700222010ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // Copyright (c) 2012 Leonhard Gruenschloss (leonhard@gruenschloss.org) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. namespace ospray { extern const unsigned int halton_perm3[243]; extern const unsigned int halton_perm5[125]; extern const unsigned int halton_perm7[343]; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/math/halton.ih000066400000000000000000000065271456566705700223600ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // Copyright (c) 2012 Leonhard Gruenschloss (leonhard@gruenschloss.org) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #pragma once #include "rkcommon/math/math.ih" // c++ shared #include "math/MathConstantsShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE inline float Halton_sample2(unsigned int index) { index = (index << 16) | (index >> 16); index = ((index & 0x00ff00ff) << 8) | ((index & 0xff00ff00) >> 8); index = ((index & 0x0f0f0f0f) << 4) | ((index & 0xf0f0f0f0) >> 4); index = ((index & 0x33333333) << 2) | ((index & 0xcccccccc) >> 2); index = ((index & 0x55555555) << 1) | ((index & 0xaaaaaaaa) >> 1); unsigned int result = 0x3f800000u | (index >> 9); return floatbits(result) - 1.f; } inline float Halton_sample3( const MathConstants *uniform mathConstants, const unsigned int index) { // Mirek note: // with normalization using 1.f instead of original 0x1.fffffcp-1 // it generates results closer to the plain iterative implementation, // (before results were usually smaller by 1-2 ULPs) // but on the other hand results may be equal to 1.f, so the range // [0-1) is not guaranteed return (mathConstants->haltonPerm3[index % 243u] * 14348907u + mathConstants->haltonPerm3[(index / 243u) % 243u] * 59049u + mathConstants->haltonPerm3[(index / 59049u) % 243u] * 243u + mathConstants->haltonPerm3[(index / 14348907u) % 243u]) * (float)(1.0 / 3486784401u); } // Permuted Halton sequence base-5 inline float PermHalton_sample5( const MathConstants *uniform mathConstants, const unsigned int index) { return (mathConstants->haltonPerm5[index % 125u] * 1953125u + mathConstants->haltonPerm5[(index / 125u) % 125u] * 15625u + mathConstants->haltonPerm5[(index / 15625u) % 125u] * 125u + mathConstants->haltonPerm5[(index / 1953125u) % 125u]) * (float)(1.0 / 244140625u); } // Permuted Halton sequence base-7 inline float PermHalton_sample7( const MathConstants *uniform mathConstants, const unsigned int index) { return (mathConstants->haltonPerm7[index % 343u] * 117649u + mathConstants->haltonPerm7[(index / 343u) % 343u] * 343u + mathConstants->haltonPerm7[(index / 117649u) % 343u]) * (float)(1.0 / 40353607u); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/math/interpolation.ih000066400000000000000000000041441456566705700237530ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/math.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // x should be between [0..size-1] inline float interp1DLinear( float x, const uniform float *uniform f, uniform int size) { float xc = clamp(x, 0.f, (float)(size - 1)); float s = xc - floor(xc); int x0 = min((int)xc, size - 1); int x1 = min(x0 + 1, size - 1); return lerp(s, f[x0], f[x1]); } // p should be between [0..size-1] inline float interp2DLinear( vec2f p, const uniform float *uniform f, uniform vec2i size) { float xc = clamp(p.x, 0.f, (float)(size.x - 1)); float yc = clamp(p.y, 0.f, (float)(size.y - 1)); float sx = xc - floor(xc); float sy = yc - floor(yc); int x0 = min((int)xc, size.x - 1); int x1 = min(x0 + 1, size.x - 1); int y0 = min((int)yc, size.y - 1); int y1 = min(y0 + 1, size.y - 1); int ny = size.x; float f0 = lerp(sx, f[x0 + y0 * ny], f[x1 + y0 * ny]); float f1 = lerp(sx, f[x0 + y1 * ny], f[x1 + y1 * ny]); return lerp(sy, f0, f1); } // p should be between [0..size-1] inline float interp3DLinear( vec3f p, const uniform float *uniform f, uniform vec3i size) { float xc = clamp(p.x, 0.f, (float)(size.x - 1)); float yc = clamp(p.y, 0.f, (float)(size.y - 1)); float zc = clamp(p.z, 0.f, (float)(size.z - 1)); float sx = xc - floor(xc); float sy = yc - floor(yc); float sz = zc - floor(zc); int x0 = min((int)xc, size.x - 1); int x1 = min(x0 + 1, size.x - 1); int y0 = min((int)yc, size.y - 1); int y1 = min(y0 + 1, size.y - 1); int z0 = min((int)zc, size.z - 1); int z1 = min(z0 + 1, size.z - 1); int ny = size.x; int nz = size.x * size.y; float f00 = lerp(sx, f[x0 + y0 * ny + z0 * nz], f[x1 + y0 * ny + z0 * nz]); float f01 = lerp(sx, f[x0 + y1 * ny + z0 * nz], f[x1 + y1 * ny + z0 * nz]); float f10 = lerp(sx, f[x0 + y0 * ny + z1 * nz], f[x1 + y0 * ny + z1 * nz]); float f11 = lerp(sx, f[x0 + y1 * ny + z1 * nz], f[x1 + y1 * ny + z1 * nz]); float f0 = lerp(sy, f00, f01); float f1 = lerp(sy, f10, f11); return lerp(sz, f0, f1); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/math/random.ih000066400000000000000000000154021456566705700223430ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "halton.ih" #include "rkcommon/math/vec.ih" #include "sobol.ih" OSPRAY_BEGIN_ISPC_NAMESPACE /////////////////////////////////////////////////////////////////////////////// // Hash functions inline uint32 MurmurHash3_mix(uint32 hash, uint32 k) { const uint32 c1 = 0xcc9e2d51; const uint32 c2 = 0x1b873593; const uint32 r1 = 15; const uint32 r2 = 13; const uint32 m = 5; const uint32 n = 0xe6546b64; k *= c1; k = (k << r1) | (k >> (32 - r1)); k *= c2; hash ^= k; hash = ((hash << r2) | (hash >> (32 - r2))) * m + n; return hash; } inline uint32 MurmurHash3_finalize(uint32 hash) { hash ^= hash >> 16; hash *= 0x85ebca6b; hash ^= hash >> 13; hash *= 0xc2b2ae35; hash ^= hash >> 16; return hash; } inline uint32 hashToRandom(uint32 value, uint32 scramble) { value = (value ^ 61) ^ scramble; value += value << 3; value ^= value >> 4; value *= 0x27d4eb2d; return value; } /////////////////////////////////////////////////////////////////////////////// // Utility functions inline float CranleyPattersonRotation(float x, float dx) { x += dx; if (x >= 1.f) x -= 1.f; return x; } inline vec2f CranleyPattersonRotation(vec2f v, vec2f dv) { const float x = CranleyPattersonRotation(v.x, dv.x); const float y = CranleyPattersonRotation(v.y, dv.y); return make_vec2f(x, y); } inline float radicalInverse(uint32 idx, const uint32 base) { float f = 0.f, g = 1.0f, inv = 1.0f / base; while (idx > 0) { g *= inv; f += (idx % base) * g; idx /= base; } return f; } ////////////////////V/////////////////////////////////////////////////////////// // PCG pseudo-random number generator http://www.pcg-random.org/ struct RandomSampler { uint64 state; uint64 stream; }; inline uint32 RandomSampler_pcg32(varying RandomSampler *uniform self) { uint64 oldstate = self->state; self->state = oldstate * 6364136223846793005ULL + (self->stream | 1u); uint32 xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u; uint32 rot = oldstate >> 59u; return (xorshifted >> rot) | (xorshifted << ((-rot) & 31)); } inline float RandomSampler_getFloat(varying RandomSampler *uniform self) { return to_float_unorm(RandomSampler_pcg32(self)); } inline void RandomSampler_init( varying RandomSampler *uniform self, uint64 seed, uint64 stream) { self->state = 0; self->stream = (stream << 1u) | 1u; // hash seed to reduce correlation artefacts self->state = MurmurHash3_mix(self->state, seed); self->state = MurmurHash3_finalize(self->state); RandomSampler_pcg32(self); self->state += seed; RandomSampler_pcg32(self); } inline void RandomSampler_init(varying RandomSampler *uniform self, uint64 seed) { RandomSampler_init(self, seed, 0); } /////////////////////////////////////////////////////////////////////////////// // TEA - Random numbers based on Tiny Encryption Algorithm inline void tea8(uint32 &_v0, uint32 &_v1) { uint32 v0 = _v0; // operate on registers to avoid slowdown uint32 v1 = _v1; uint32 sum = 0; for (uniform int i = 0; i < 8; i++) { // just 8 instead of 32 rounds sum += 0x9e3779b9; v0 += ((v1 << 4) + 0xa341316c) ^ (v1 + sum) ^ ((v1 >> 5) + 0xc8013ea4); v1 += ((v0 << 4) + 0xad90777d) ^ (v0 + sum) ^ ((v0 >> 5) + 0x7e95761e); } _v0 = v0; _v1 = v1; } struct RandomTEA { vec2ui state; }; inline void RandomTEA_Constructor( varying RandomTEA *uniform self, const uint32 idx, const uint32 seed) { self->state.x = idx; self->state.y = seed; } inline varying vec2f RandomTEA_getFloats(varying RandomTEA *uniform self) { tea8(self->state.x, self->state.y); return to_float_unorm(self->state); } /////////////////////////////////////////////////////////////////////////////// // LCG - Linear Congruential Generator inline uint32 LCG_init(uint32 pixelID, uint32 sampleIndex) { uint32 state = 0; state = MurmurHash3_mix(state, pixelID); state = MurmurHash3_mix(state, sampleIndex); state = MurmurHash3_finalize(state); return state; } inline uint32 LCG_next(uint32 value) { const uint32 m = 1664525; const uint32 n = 1013904223; return value * m + n; } inline float LCG_getFloat(uint32 &state) { state = LCG_next(state); return to_float_unorm(state); } inline vec2f LCG_getFloat2(uint32 &state) { const float x = LCG_getFloat(state); const float y = LCG_getFloat(state); return make_vec2f(x, y); } inline vec3f LCG_getFloat3(uint32 &state) { const float x = LCG_getFloat(state); const float y = LCG_getFloat(state); const float z = LCG_getFloat(state); return make_vec3f(x, y, z); } //////////////////////////////////////////////////////////////////////////////// // Low-discrepancy (Sobol) sampler struct LDSampler { uint32 index; // sample index uint32 scramble; // random number for scrambling the samples uint32 lcg; // LCG used when we run out of dimensions const unsigned int *uniform sobolMatrices; }; inline void LDSampler_init(varying LDSampler *uniform self, const MathConstants *uniform mathConstants, uint32 pixelID, uint32 sampleIndex) { // skip the first few samples to reduce correlation artifacts self->index = sampleIndex + 64; uint32 hash = 0; hash = MurmurHash3_mix(hash, pixelID); self->scramble = MurmurHash3_finalize(hash); hash = MurmurHash3_mix(hash, sampleIndex); self->lcg = MurmurHash3_finalize(hash); self->sobolMatrices = mathConstants->sobolMatrices; } inline float LDSampler_getFloat( varying LDSampler *uniform self, uniform uint32 dimension) { if (dimension >= Sobol_numDimensions) return LCG_getFloat(self->lcg); // Sample the Sobol sequence const float s = Sobol_sample(self->sobolMatrices, self->index, dimension); // Apply Cranley-Patterson rotation to reduce correlation artifacts const float shift = to_float_unorm(hashToRandom(dimension, self->scramble)); return CranleyPattersonRotation(s, shift); } inline vec2f LDSampler_getFloat2( varying LDSampler *uniform self, uniform uint32 dimension) { const float x = LDSampler_getFloat(self, dimension); const float y = LDSampler_getFloat(self, dimension + 1); return make_vec2f(x, y); } /////////////////////////////////////////////////////////////////////////////// // Hammersley - low discrepancy random numbers; only two dimensions; no state inline varying vec2f RandomHammersley2_getFloats(varying uint32 idx) { return make_vec2f(rcp((float)idx), Halton_sample2(idx)); } /////////////////////////////////////////////////////////////////////////////// // halton - low discrepancy halton sequence; first two dimensions; no state inline varying vec2f HaltonSequence_get2D( const MathConstants *uniform mathConstants, varying uint32 idx) { return make_vec2f(Halton_sample2(idx), Halton_sample3(mathConstants, idx)); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/math/sampling.h000066400000000000000000000014101456566705700225160ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // utility library containing sampling functions // convention is to return the sample (vec3f) generated from given vec2f // 's'ample as last parameter sampling functions often come in pairs: sample and // pdf (needed later for MIS) good reference is "Total Compendium" by Philip // Dutre http://people.cs.kuleuven.be/~philip.dutre/GI/ #include "rkcommon/math/rkmath.h" namespace ospray { inline float uniformSampleConePDF(const float cosAngle) { return rcp(float(two_pi) * (1.0f - cosAngle)); } inline float uniformSampleRingPDF(const float radius, const float innerRadius) { return rcp(float(pi) * ((radius * radius) - (innerRadius * innerRadius))); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/math/sampling.ih000066400000000000000000000135031456566705700226750ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once /*! \brief utility library containing sampling functions */ // convention is to return the sample (vec3f) generated from given vec2f // 's'ample as last parameter sampling functions often come in pairs: sample and // pdf (needed later for MIS) good reference is "Total Compendium" by Philip // Dutre http://people.cs.kuleuven.be/~philip.dutre/GI/ #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE inline vec3f cartesian( const float phi, const float sinTheta, const float cosTheta) { float sinPhi, cosPhi; sincos(phi, &sinPhi, &cosPhi); return make_vec3f(cosPhi * sinTheta, sinPhi * sinTheta, cosTheta); } inline vec3f cartesian(const float phi, const float cosTheta) { return cartesian(phi, cos2sin(cosTheta), cosTheta); } /// uniform sampling of hemisphere oriented along the +z-axis //////////////////////////////////////////////////////////////////////////////// inline vec3f uniformSampleHemisphere(const vec2f s) { const float phi = (float)two_pi * s.x; const float cosTheta = s.y; const float sinTheta = cos2sin(s.y); return cartesian(phi, sinTheta, cosTheta); } inline float uniformSampleHemispherePDF() { return one_over_two_pi; } /// cosine-weighted sampling of hemisphere oriented along the +z-axis //////////////////////////////////////////////////////////////////////////////// inline vec3f cosineSampleHemisphere(const vec2f s) { const float phi = (float)two_pi * s.x; const float cosTheta = sqrt(s.y); const float sinTheta = sqrt(1.0f - s.y); return cartesian(phi, sinTheta, cosTheta); } inline float cosineSampleHemispherePDF(const vec3f &dir) { return dir.z * (float)one_over_pi; } inline float cosineSampleHemispherePDF(float cosTheta) { return cosTheta * (float)one_over_pi; } /// power cosine-weighted sampling of hemisphere oriented along the +z-axis //////////////////////////////////////////////////////////////////////////////// inline vec3f powerCosineSampleHemisphere(const float n, const vec2f &s) { const float phi = (float)two_pi * s.x; const float cosTheta = pow(s.y, 1.0f / (n + 1.0f)); return cartesian(phi, cosTheta); } inline float powerCosineSampleHemispherePDF( const float cosTheta, const float n) // TODO: order of arguments { return (n + 1.0f) * (float)one_over_two_pi * pow(cosTheta, n); } inline float powerCosineSampleHemispherePDF( const vec3f &dir, const float n) // TODO: order of arguments { return (n + 1.0f) * (float)one_over_two_pi * pow(dir.z, n); } /// uniform sampling of cone of directions oriented along the +z-axis //////////////////////////////////////////////////////////////////////////////// inline vec3f uniformSampleCone(const float cosAngle, const vec2f &s) { const float phi = (float)two_pi * s.x; const float cosTheta = 1.0f - s.y * (1.0f - cosAngle); return cartesian(phi, cosTheta); } inline float uniformSampleConePDF(const float cosAngle) { return rcp((float)two_pi * (1.0f - cosAngle)); } #ifndef OSPRAY_TARGET_SYCL inline uniform float uniformSampleConePDF(const uniform float cosAngle) { return rcp((float)two_pi * (1.0f - cosAngle)); } #endif /// uniform sampling of ring //////////////////////////////////////////////////////////////////////////////// inline vec3f uniformSampleRing( const float radius, const float innerRadius, const vec2f &s) { const float r = sqrtf(lerp(s.x, sqr(innerRadius), sqr(radius))); const float phi = (float)two_pi * s.y; float sinPhi, cosPhi; sincos(phi, &sinPhi, &cosPhi); return make_vec3f(r * cosPhi, r * sinPhi, 0.f); } inline float uniformSampleRingPDF(const float radius, const float innerRadius) { return rcp((float)pi * (sqr(radius) - sqr(innerRadius))); } #ifndef OSPRAY_TARGET_SYCL inline uniform float uniformSampleRingPDF( const uniform float radius, const uniform float innerRadius) { return rcp((float)pi * (sqr(radius) - sqr(innerRadius))); } #endif /// uniform sampling of disk //////////////////////////////////////////////////////////////////////////////// // TODO: just use uniformSampleRing with innerRadius = 0? inline vec3f uniformSampleDisk(const float radius, const vec2f &s) { const float r = sqrtf(s.x) * radius; const float phi = (float)two_pi * s.y; float sinPhi, cosPhi; sincos(phi, &sinPhi, &cosPhi); return make_vec3f(r * cosPhi, r * sinPhi, 0.f); } inline float uniformSampleDiskPDF(const float radius) { return rcp((float)pi * sqr(radius)); } #ifndef OSPRAY_TARGET_SYCL inline uniform float uniformSampleDiskPDF(const uniform float radius) { return rcp((float)pi * sqr(radius)); } #endif /// uniform sampling of triangle abc //////////////////////////////////////////////////////////////////////////////// inline vec2f uniformSampleTriangleUV(const vec2f &s) { const float su = sqrtf(s.x); vec2f uv; uv.x = s.y * su; uv.y = (1.0f - s.y) * su; return uv; } inline vec3f uniformSampleTriangle( const vec3f &a, const vec3f &b, const vec3f &c, const vec2f &s) { const vec2f uv = uniformSampleTriangleUV(s); return a + uv.x * (b - a) + uv.y * (c - a); } inline float uniformSampleTrianglePDF( const vec3f &a, const vec3f &b, const vec3f &c) { return 2.0f * rcp(length(cross(a - c, b - c))); } /// uniform sampling of sphere //////////////////////////////////////////////////////////////////////////////// inline vec3f uniformSampleSphere(const float radius, const vec2f s) { const float phi = (float)two_pi * s.x; const float cosTheta = radius * (1.f - 2.f * s.y); const float sinTheta = 2.f * radius * sqrt(s.y * (1.f - s.y)); return cartesian(phi, sinTheta, cosTheta); } inline float uniformSampleSpherePDF(const float radius) { return rcp((float)four_pi * sqr(radius)); } #ifndef OSPRAY_TARGET_SYCL inline uniform float uniformSampleSpherePDF(const uniform float radius) { return rcp((float)four_pi * sqr(radius)); } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/math/sobol.cpp000066400000000000000000033445501456566705700223770ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // Copyright (c) 2012 Leonhard Gruenschloss (leonhard@gruenschloss.org) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // These matrices are based on the following publication: // // S. Joe and F. Y. Kuo: "Constructing Sobol sequences with better // two-dimensional projections", SIAM J. Sci. Comput. 30, 2635-2654 (2008). // // The tabulated direction numbers are available here: // http://web.maths.unsw.edu.au/~fkuo/sobol/new-joe-kuo-6.21201 #include "sobol.h" namespace ospray { const unsigned int Sobol_matrices[Sobol_numDimensions * Sobol_numBits] = { 0x80000000U, 0x40000000U, 0x20000000U, 0x10000000U, 0x8000000U, 0x4000000U, 0x2000000U, 0x1000000U, 0x800000U, 0x400000U, 0x200000U, 0x100000U, 0x80000U, 0x40000U, 0x20000U, 0x10000U, 0x8000U, 0x4000U, 0x2000U, 0x1000U, 0x800U, 0x400U, 0x200U, 0x100U, 0x80U, 0x40U, 0x20U, 0x10U, 0x8U, 0x4U, 0x2U, 0x1U, 0x0U, 0x0U, 0x0U, 0x0U, 0x0U, 0x0U, 0x0U, 0x0U, 0x0U, 0x0U, 0x0U, 0x0U, 0x0U, 0x0U, 0x0U, 0x0U, 0x0U, 0x0U, 0x0U, 0x0U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xf0000000U, 0x88000000U, 0xcc000000U, 0xaa000000U, 0xff000000U, 0x80800000U, 0xc0c00000U, 0xa0a00000U, 0xf0f00000U, 0x88880000U, 0xcccc0000U, 0xaaaa0000U, 0xffff0000U, 0x80008000U, 0xc000c000U, 0xa000a000U, 0xf000f000U, 0x88008800U, 0xcc00cc00U, 0xaa00aa00U, 0xff00ff00U, 0x80808080U, 0xc0c0c0c0U, 0xa0a0a0a0U, 0xf0f0f0f0U, 0x88888888U, 0xccccccccU, 0xaaaaaaaaU, 0xffffffffU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xf0000000U, 0x88000000U, 0xcc000000U, 0xaa000000U, 0xff000000U, 0x80800000U, 0xc0c00000U, 0xa0a00000U, 0xf0f00000U, 0x88880000U, 0xcccc0000U, 0xaaaa0000U, 0xffff0000U, 0x80008000U, 0xc000c000U, 0xa000a000U, 0xf000f000U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0xe8000000U, 0x5c000000U, 0x8e000000U, 0xc5000000U, 0x68800000U, 0x9cc00000U, 0xee600000U, 0x55900000U, 0x80680000U, 0xc09c0000U, 0x60ee0000U, 0x90550000U, 0xe8808000U, 0x5cc0c000U, 0x8e606000U, 0xc5909000U, 0x6868e800U, 0x9c9c5c00U, 0xeeee8e00U, 0x5555c500U, 0x8000e880U, 0xc0005cc0U, 0x60008e60U, 0x9000c590U, 0xe8006868U, 0x5c009c9cU, 0x8e00eeeeU, 0xc5005555U, 0x68808000U, 0x9cc0c000U, 0xee606000U, 0x55909000U, 0x8068e800U, 0xc09c5c00U, 0x60ee8e00U, 0x9055c500U, 0xe880e880U, 0x5cc05cc0U, 0x8e608e60U, 0xc590c590U, 0x68686868U, 0x9c9c9c9cU, 0xeeeeeeeeU, 0x55555555U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x50000000U, 0xf8000000U, 0x74000000U, 0xa2000000U, 0x93000000U, 0xd8800000U, 0x25400000U, 0x59e00000U, 0xe6d00000U, 0x78080000U, 0xb40c0000U, 0x82020000U, 0xc3050000U, 0x208f8000U, 0x51474000U, 0xfbea2000U, 0x75d93000U, 0xa0858800U, 0x914e5400U, 0xdbe79e00U, 0x25db6d00U, 0x58800080U, 0xe54000c0U, 0x79e00020U, 0xb6d00050U, 0x800800f8U, 0xc00c0074U, 0x200200a2U, 0x50050093U, 0xf80f80d8U, 0x74074025U, 0xa20a2059U, 0x930930e6U, 0xd88d8878U, 0x254254b4U, 0x59e59e82U, 0xe6de6dc3U, 0x780f80a0U, 0xb4074091U, 0x820a20dbU, 0xc3093025U, 0x208d8858U, 0x514254e5U, 0xfbe59e79U, 0x75de6db6U, 0xa08f8000U, 0x91474000U, 0xdbea2000U, 0x25d93000U, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0xf8000000U, 0xdc000000U, 0x7a000000U, 0x9d000000U, 0x5a800000U, 0x2fc00000U, 0xa1600000U, 0xf0b00000U, 0xda880000U, 0x6fc40000U, 0x81620000U, 0x40bb0000U, 0x22878000U, 0xb3c9c000U, 0xfb65a000U, 0xddb2d000U, 0x78022800U, 0x9c0b3c00U, 0x5a0fb600U, 0x2d0ddb00U, 0xa2878080U, 0xf3c9c040U, 0xdb65a020U, 0x6db2d0b0U, 0x800228f8U, 0x400b3cdcU, 0x200fb67aU, 0xb00ddb9dU, 0xf80780daU, 0xdc09c06fU, 0x7a05a081U, 0x9d02d040U, 0x5a8a2822U, 0x2fcf3cb3U, 0xa16db6fbU, 0xf0b6dbddU, 0xda8000f8U, 0x6fc000dcU, 0x8160007aU, 0x40b0009dU, 0x2288005aU, 0xb3c4002fU, 0xfb6200a1U, 0xddbb00f0U, 0x780780daU, 0x9c09c06fU, 0x5a05a081U, 0x2d02d040U, 0x80000000U, 0x40000000U, 0x60000000U, 0x30000000U, 0xc8000000U, 0x24000000U, 0x56000000U, 0xfb000000U, 0xe0800000U, 0x70400000U, 0xa8600000U, 0x14300000U, 0x9ec80000U, 0xdf240000U, 0xb6d60000U, 0x8bbb0000U, 0x48008000U, 0x64004000U, 0x36006000U, 0xcb003000U, 0x2880c800U, 0x54402400U, 0xfe605600U, 0xef30fb00U, 0x7e48e080U, 0xaf647040U, 0x1eb6a860U, 0x9f8b1430U, 0xd6c81ec8U, 0xbb249f24U, 0x80d6d6d6U, 0x40bbbbbbU, 0x60800000U, 0x30400000U, 0xc8600000U, 0x24300000U, 0x56c80000U, 0xfb240000U, 0xe0d60000U, 0x70bb0000U, 0xa8808000U, 0x14404000U, 0x9e606000U, 0xdf303000U, 0xb648c800U, 0x8b642400U, 0x48b65600U, 0x648bfb00U, 0x36486080U, 0xcb643040U, 0x28b6c860U, 0x548b2430U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0x58000000U, 0x94000000U, 0x3e000000U, 0xe3000000U, 0xbe800000U, 0x23c00000U, 0x1e200000U, 0xf3100000U, 0x46780000U, 0x67840000U, 0x78460000U, 0x84670000U, 0xc6788000U, 0xa784c000U, 0xd846a000U, 0x5467d000U, 0x9e78d800U, 0x33845400U, 0xe6469e00U, 0xb7673300U, 0x20f86680U, 0x104477c0U, 0xf8668020U, 0x4477c010U, 0x668020f8U, 0x77c01044U, 0x8020f866U, 0xc0104477U, 0xa0f86680U, 0xd04477c0U, 0x58668020U, 0x9477c010U, 0x3e8020f8U, 0xe3c01044U, 0xbe20f866U, 0x23104477U, 0x1e786680U, 0xf38477c0U, 0x46468020U, 0x6767c010U, 0x78f820f8U, 0x84441044U, 0xc666f866U, 0xa7774477U, 0xd800e680U, 0x5400b7c0U, 0x9e002020U, 0x33001010U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0x88000000U, 0x24000000U, 0x12000000U, 0x2d000000U, 0x76800000U, 0x9e400000U, 0x8200000U, 0x64100000U, 0xb2280000U, 0x7d140000U, 0xfea20000U, 0xba490000U, 0x1a248000U, 0x491b4000U, 0xc4b5a000U, 0xe3739000U, 0xf6800800U, 0xde400400U, 0xa8200a00U, 0x34100500U, 0x3a280880U, 0x59140240U, 0xeca20120U, 0x974902d0U, 0x6ca48768U, 0xd75b49e4U, 0xcc95a082U, 0x87639641U, 0x44a80322U, 0xa35403d1U, 0x568205eaU, 0x8e590ea4U, 0x200c8922U, 0x100f46d1U, 0x2817ad6bU, 0x743a9ce7U, 0x9a248000U, 0x91b4000U, 0x64b5a000U, 0xb3739000U, 0x7e800800U, 0xfa400400U, 0xba200a00U, 0x19100500U, 0x4ca80880U, 0xc7540240U, 0xe4820120U, 0xf35902d0U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0x28000000U, 0xd4000000U, 0x6a000000U, 0x71000000U, 0x38800000U, 0x58400000U, 0xea200000U, 0x31100000U, 0x98a80000U, 0x8540000U, 0xc22a0000U, 0xe5250000U, 0xf2b28000U, 0x79484000U, 0xfaa42000U, 0xbd731000U, 0x18a80800U, 0x48540400U, 0x622a0a00U, 0xb5250500U, 0xdab28280U, 0xad484d40U, 0x90a426a0U, 0xcc731710U, 0x20280b88U, 0x10140184U, 0x880a04a2U, 0x84350611U, 0x421a8b0aU, 0xa51c4dc5U, 0x528e2a82U, 0x29561942U, 0xd29a84a3U, 0x695c4610U, 0x72ae2b08U, 0x39461dc6U, 0x5ab28280U, 0xed484d40U, 0x30a426a0U, 0x9c731710U, 0x8280b88U, 0xc4140184U, 0xe20a04a2U, 0xf5350611U, 0x7a9a8b0aU, 0xfd5c4dc5U, 0xb8ae2a82U, 0x18461942U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xb0000000U, 0x98000000U, 0x94000000U, 0x8a000000U, 0x5b000000U, 0x33800000U, 0xd9c00000U, 0x72200000U, 0x3f100000U, 0xc1b80000U, 0xa6ec0000U, 0x53860000U, 0x29f50000U, 0xa3a8000U, 0x1b2ac000U, 0xd392e000U, 0x69ff7000U, 0xea380800U, 0xab2c0400U, 0x4ba60e00U, 0xfde50b00U, 0x60028980U, 0xf006c940U, 0x7834e8a0U, 0x241a75b0U, 0x123a8b38U, 0xcf2ac99cU, 0xb992e922U, 0x82ff78f1U, 0x41b80d9bU, 0xe6ec072eU, 0xb3860398U, 0x99f50c2fU, 0x923a8a1bU, 0x8f2ac56eU, 0x5992e2bbU, 0x32ff70deU, 0xd9b80980U, 0x72ec0940U, 0x398608a0U, 0xc2f505b0U, 0xa1ba8338U, 0x56eacd9cU, 0x2bb2e722U, 0xdef73f1U, 0x1800041bU, 0xd4000e6eU, 0x6a000b38U, 0xeb00099fU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x10000000U, 0x8000000U, 0x6c000000U, 0x9e000000U, 0x23000000U, 0x57800000U, 0xadc00000U, 0x7fa00000U, 0x91d00000U, 0x49880000U, 0xced40000U, 0x880a0000U, 0x2c0f0000U, 0x3e0d8000U, 0x3317c000U, 0x5fb06000U, 0xc1f8b000U, 0xe18d8800U, 0xb2d7c400U, 0x1e106a00U, 0x6328b100U, 0xf7858880U, 0xbdc3c2c0U, 0x77ba63e0U, 0xfdf7b330U, 0xd7800df8U, 0xedc0081cU, 0xdfa0041aU, 0x81d00a2dU, 0x41880160U, 0xa2d400f1U, 0x160a069aU, 0xf0f09edU, 0x698d8200U, 0x9ed7c500U, 0x20106a81U, 0x5028b7c2U, 0xa8058160U, 0x7c03c0f1U, 0x961a669aU, 0x4f27b9edU, 0xc9880a00U, 0x8ed40100U, 0x280a0081U, 0x3c0f06c2U, 0x360d89e0U, 0x5f17c231U, 0xc1b0657aU, 0xe2f8baddU, 0x80000000U, 0x40000000U, 0x20000000U, 0x30000000U, 0x58000000U, 0xac000000U, 0x96000000U, 0x2b000000U, 0xd4800000U, 0x9400000U, 0xe2a00000U, 0x52500000U, 0x4e280000U, 0xc71c0000U, 0x629e0000U, 0x12670000U, 0x6e138000U, 0xf731c000U, 0x3a98a000U, 0xbe449000U, 0xf83b8800U, 0xdc2dc400U, 0xee06a200U, 0xb7239300U, 0x1aa80d80U, 0x8e5c0ec0U, 0xa03e0b60U, 0x703701b0U, 0x783b88c8U, 0x9c2dca54U, 0xce06a74aU, 0x87239795U, 0x42a801aaU, 0x225c08e5U, 0x363e0a03U, 0x5b370703U, 0xacbb8783U, 0x956dc9c2U, 0x2ca6ace0U, 0xd5739872U, 0xc800c2aU, 0xe5400625U, 0x54a00163U, 0x495006b3U, 0xc2a80f4bU, 0x625c0396U, 0x163e0baaU, 0x6b370fe7U, 0xf4bb8d80U, 0x396dcec0U, 0xbaa6ab60U, 0xfe7391b0U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x50000000U, 0xf8000000U, 0x8c000000U, 0xe2000000U, 0x33000000U, 0xf800000U, 0x21400000U, 0x95a00000U, 0x5e700000U, 0xd8080000U, 0x1c240000U, 0xba160000U, 0xef370000U, 0x15868000U, 0x9e6fc000U, 0x781b6000U, 0x4c349000U, 0x420e8800U, 0x630bcc00U, 0xf7ad6a00U, 0xad739500U, 0x77800780U, 0x6d4004c0U, 0xd7a00420U, 0x3d700630U, 0x2f880f78U, 0xb1640ad4U, 0xcdb6077aU, 0x824706d7U, 0xc20e8d78U, 0xa30bc3d6U, 0x57ad62fbU, 0xfd739b14U, 0x8f8004d8U, 0xe1400424U, 0x35a00620U, 0xe700f30U, 0x20080af8U, 0x90240716U, 0x581606dbU, 0xdc370d24U, 0x1a0683a0U, 0xbf2fc2f0U, 0xedbb6b5aU, 0x12449ce7U, 0x9a068000U, 0x7f2fc000U, 0x4dbb6000U, 0x42449000U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0x38000000U, 0xc4000000U, 0x42000000U, 0xa3000000U, 0xf1800000U, 0xaa400000U, 0xfce00000U, 0x85100000U, 0xe0080000U, 0x500c0000U, 0x58060000U, 0x54090000U, 0x7a038000U, 0x670c4000U, 0xb3842000U, 0x94a3000U, 0xd6f1800U, 0x2f5aa400U, 0x1ce7ce00U, 0xd5145100U, 0xb8000080U, 0x40000c0U, 0x22000060U, 0x33000090U, 0xc9800038U, 0x6e4000c4U, 0xbee00042U, 0x261000a3U, 0x118800f1U, 0xfa4c00aaU, 0xa4e600fcU, 0xd1190085U, 0x9a0b80e0U, 0x37004050U, 0xeb822058U, 0x5d433054U, 0x776c987aU, 0x4856e467U, 0xaf63eeb3U, 0xdc5e6109U, 0xb56f188dU, 0x2b5aa4efU, 0x3ee7ce7cU, 0xe6145145U, 0x71800000U, 0x6a400000U, 0x9ce00000U, 0x15100000U, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0xa8000000U, 0x54000000U, 0x9a000000U, 0x9d000000U, 0x1e800000U, 0x5cc00000U, 0x7d200000U, 0x8d100000U, 0x24880000U, 0x71c40000U, 0xeba20000U, 0x75df0000U, 0x6ba28000U, 0x35d14000U, 0x4ba3a000U, 0xc5d2d000U, 0xe3a16800U, 0x91db8c00U, 0x79aef200U, 0xcdf4100U, 0x672a8080U, 0x50154040U, 0x1a01a020U, 0xdd0dd0f0U, 0x3e83e8a8U, 0xaccacc54U, 0xd52d529aU, 0xd91d919dU, 0xbe83e89eU, 0xeccacc1cU, 0xf52d525dU, 0x291d917dU, 0x1683e80cU, 0xb8cacc65U, 0x6f2d5251U, 0xb41d9118U, 0x803e85dU, 0xe40acc7dU, 0x120d528cU, 0x390d9125U, 0x2c8be8f1U, 0x95cecca8U, 0xf9af5255U, 0x4cd29199U, 0x4729681eU, 0xa01f8c5cU, 0xb20cf27dU, 0x8900418dU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0xd8000000U, 0xc4000000U, 0x46000000U, 0x85000000U, 0xa5800000U, 0x76c00000U, 0xada00000U, 0x6ab00000U, 0x2da80000U, 0xaabc0000U, 0xdaa0000U, 0x7ab10000U, 0xd5a78000U, 0xbebd4000U, 0x93a3e000U, 0x3bb51000U, 0x3629b800U, 0x4d727c00U, 0x9b836200U, 0x27c4d700U, 0xb629b880U, 0x8d727cc0U, 0xbb836220U, 0xf7c4d7d0U, 0x6e29b858U, 0x49727c04U, 0xfd836266U, 0x72c4d755U, 0xcba9b8fdU, 0x3fb27c72U, 0x502362cbU, 0x1874d73fU, 0xe601b8d0U, 0x950e7cd8U, 0x5d8962c6U, 0x62c5d745U, 0x33a63805U, 0x2bb33c66U, 0xce2a8255U, 0x5970c77eU, 0x58f8033U, 0x66c1402bU, 0x55a9e0ceU, 0x7eb41059U, 0xb3a63805U, 0xebb33c66U, 0xee2a8255U, 0x8970c77eU, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0x38000000U, 0x14000000U, 0xf6000000U, 0x67000000U, 0x8f800000U, 0x50400000U, 0x8aa00000U, 0xff00000U, 0x12a80000U, 0xabf40000U, 0xfcaa0000U, 0x28fb0000U, 0xbd298000U, 0xbba4000U, 0x4e06e000U, 0x330c3000U, 0x59861800U, 0xc74d3400U, 0x3d2cb200U, 0x4bb2cb00U, 0x6e061880U, 0xc30d3440U, 0x618cb220U, 0xd342cbf0U, 0xcb2e18b8U, 0x2cb93454U, 0xe186b2d6U, 0x9349cb97U, 0xeb2f9837U, 0xdcb77404U, 0xd98a525cU, 0x874efb98U, 0x1d280025U, 0xbbb400afU, 0x560a00a0U, 0xd70b00b0U, 0x97818018U, 0xb44e40e4U, 0x44ace0ceU, 0x7cf73073U, 0x6b2f9879U, 0x9cb77437U, 0xf98a5205U, 0x774efb5fU, 0x25280018U, 0xafb400e4U, 0xa00a00ceU, 0xb00b0073U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xf0000000U, 0x68000000U, 0x64000000U, 0x36000000U, 0x6d000000U, 0x41800000U, 0xe0400000U, 0xd2e00000U, 0x9bf00000U, 0xce80000U, 0x52fc0000U, 0x5b6a0000U, 0x2fb30000U, 0xa00c8000U, 0x30054000U, 0x4807e000U, 0x940f9000U, 0x5e01f800U, 0x90e9400U, 0x778a5600U, 0x8d416b00U, 0x9369f880U, 0x7bb294c0U, 0xde005620U, 0xc9026bf0U, 0x578d78e8U, 0x7d4bd4a4U, 0xfb6db616U, 0x1fbefb9dU, 0xe80000a9U, 0xa4000044U, 0x160000c4U, 0x9d000006U, 0x29800025U, 0x844000d6U, 0xe4e000bfU, 0xf6f000d9U, 0x4d6800edU, 0xb2bc0082U, 0x898a00c1U, 0xb4430020U, 0xace480f2U, 0x62f9406bU, 0x136de064U, 0xbbbc9036U, 0xfe0d786dU, 0x390bd442U, 0x3f8db6e1U, 0x194efbd0U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0x98000000U, 0xf4000000U, 0xae000000U, 0xbb000000U, 0xe7800000U, 0x95c00000U, 0x1c200000U, 0xd0300000U, 0xdba80000U, 0x55f40000U, 0xff820000U, 0x21c10000U, 0x12238000U, 0x3b3a4000U, 0xa42b6000U, 0x3430f000U, 0x4da69800U, 0x4af3ec00U, 0x2e043a00U, 0xfb0a1f00U, 0x47851880U, 0xc5c9ac40U, 0x842f5aa0U, 0x243aef50U, 0x75a38018U, 0xeefa40b4U, 0x180b600eU, 0xb400f0ebU, 0xe0e987fU, 0xeb07ec61U, 0x7f863ab2U, 0x61cb1f6bU, 0xb22698bcU, 0x6b33ec80U, 0x3c243a43U, 0xc03a1fa1U, 0xe3ad18d1U, 0xf1fdacdaU, 0xc98d5a55U, 0x6ecbeffeU, 0x5ba800a0U, 0x15f40050U, 0x5f820098U, 0x71c100f4U, 0x8a2380aeU, 0xcf3a40bbU, 0xa2b60e7U, 0x8f30f095U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0xb8000000U, 0x3c000000U, 0xce000000U, 0x41000000U, 0x21800000U, 0x51c00000U, 0x9600000U, 0x85700000U, 0xf2780000U, 0x8e9c0000U, 0x60020000U, 0x70030000U, 0x58038000U, 0x8c02c000U, 0x7602e000U, 0x7d00f000U, 0xef833800U, 0x10c10400U, 0x28e08600U, 0xd4b14700U, 0xfb182580U, 0xbee15c0U, 0x9279c9e0U, 0xfe9d3a70U, 0x38000008U, 0xfc00000cU, 0x2e00000eU, 0xf100000bU, 0x9980000bU, 0x6dc00003U, 0xc760000cU, 0xc4700004U, 0xd3f80002U, 0xdf5c0005U, 0x69620000U, 0xf5730008U, 0xaa7b800fU, 0x29ec008U, 0x1600e006U, 0xd03f007U, 0xb780b805U, 0x9cc3c408U, 0x5ee26607U, 0xa9b1b707U, 0x149b1d8eU, 0x1b2f11c1U, 0xba994fe2U, 0x2a2c7d7dU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xd0000000U, 0x68000000U, 0x3c000000U, 0x8a000000U, 0x51000000U, 0xa9800000U, 0xddc00000U, 0x5ba00000U, 0x39d00000U, 0x95f80000U, 0x56d40000U, 0xa020000U, 0x91030000U, 0x49838000U, 0xdc34000U, 0x33a1a000U, 0x5d0f000U, 0x1ffa2800U, 0x7d54400U, 0xa380a600U, 0x4cc07700U, 0x1222ee80U, 0x3413a740U, 0xa65bf7e0U, 0x5305ab50U, 0x15f80008U, 0x96d4000cU, 0xea02000eU, 0x4103000dU, 0x21838006U, 0x31c34003U, 0xb9a1a008U, 0x54d0f005U, 0xb67a280aU, 0xda15440dU, 0xf820a605U, 0x75107703U, 0x87daee89U, 0x62c7a745U, 0xac59f7e0U, 0xc206ab59U, 0x5c7b800cU, 0x9b17400cU, 0xd9a3a00dU, 0x44d3f00dU, 0x3e79a807U, 0x36160403U, 0x1a210602U, 0x18108701U, 0x80000000U, 0x40000000U, 0x60000000U, 0xd0000000U, 0x38000000U, 0x8c000000U, 0x7e000000U, 0x71000000U, 0xc8800000U, 0x4c00000U, 0x1ba00000U, 0xbb700000U, 0x4a980000U, 0xc3bc0000U, 0xa6020000U, 0x6d010000U, 0xee818000U, 0x29c34000U, 0x9520e000U, 0x42b23000U, 0xe7b9f800U, 0xd0dc400U, 0x3fb92200U, 0x110d1300U, 0x19bbee80U, 0x3c0cadc0U, 0x973a4a60U, 0xc5cf7ef0U, 0x3a180008U, 0xb7c0004U, 0xa3a20006U, 0x7771000dU, 0x54998003U, 0x62bf4008U, 0x5682e007U, 0xe5c33007U, 0x8b20780cU, 0xe3b28400U, 0x173bc201U, 0x85ce230bU, 0x5a1b9684U, 0xdb7e29ccU, 0x9ba1886aU, 0xfb715df6U, 0x2a9b9686U, 0x13be29c6U, 0x9e01886fU, 0xe1015df9U, 0x90839685U, 0x58c229ccU, 0x5da38862U, 0x46705dfbU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x90000000U, 0x8000000U, 0x64000000U, 0x6a000000U, 0x89000000U, 0xa5800000U, 0xcb400000U, 0x18200000U, 0xad900000U, 0xaf880000U, 0x72f40000U, 0x25820000U, 0xb430000U, 0xb8228000U, 0x3d924000U, 0xa7882000U, 0x16f59000U, 0x4f83a800U, 0x82412400U, 0x1da01600U, 0xf6d16d00U, 0xbfa84080U, 0xbb672640U, 0xe0091620U, 0xf0b4efd0U, 0x38228008U, 0xfd92400cU, 0x788200aU, 0x86f59009U, 0x4783a800U, 0xe6412406U, 0x77a01606U, 0x7fd16d08U, 0x1a28408aU, 0x7027264cU, 0xf8291621U, 0x5d24efdaU, 0x97aa8002U, 0x8f66400bU, 0x220a2008U, 0x8db69009U, 0xffa1280bU, 0xdbd36405U, 0xd028360cU, 0x6924fd09U, 0x55abe88eU, 0xf2660244U, 0xe5890020U, 0xabf582d5U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0x48000000U, 0x8c000000U, 0xd6000000U, 0x39000000U, 0xd5800000U, 0x32400000U, 0xb2a00000U, 0x72100000U, 0x53d80000U, 0x82cc0000U, 0xcb820000U, 0x47430000U, 0x91208000U, 0xa9534000U, 0x7cf92000U, 0x4e9e3000U, 0xfcf95800U, 0x8e9fe400U, 0xdcf9d600U, 0x5e9c8900U, 0x94f96a80U, 0xd29fb840U, 0x42f9b760U, 0xeb9c9f30U, 0x97788008U, 0xd9df400cU, 0x25db2002U, 0xabcd300dU, 0x7601d804U, 0x2900a408U, 0xbd82f60dU, 0x6e41b903U, 0x2ca0b28dU, 0xc7131c43U, 0x5059416bU, 0x898e2637U, 0xaca0b28dU, 0x7131c44U, 0x7059416eU, 0x598e2639U, 0xe4a0b285U, 0x8b131c4eU, 0xa6594168U, 0x608e263aU, 0x3120b28eU, 0xb9531c4fU, 0x14f94169U, 0x129e263cU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x50000000U, 0xd8000000U, 0xf4000000U, 0x3e000000U, 0x95000000U, 0x8f800000U, 0x3d400000U, 0xf3200000U, 0x2ef00000U, 0xadc80000U, 0xa0c0000U, 0x8b220000U, 0x4af30000U, 0x6bc88000U, 0x3b0d4000U, 0xe2a16000U, 0x16b0d000U, 0x29687800U, 0xbdbf1400U, 0x33cb5e00U, 0xf0c2500U, 0xfca1b480U, 0xd3b0afc0U, 0x7eeb6920U, 0x74fe4d30U, 0xfee87808U, 0xb4ff140cU, 0xdeeb5e02U, 0xe4fc2505U, 0x6e9b48dU, 0x10fcafcfU, 0x38e96923U, 0x85fd4d39U, 0xb768f800U, 0xb8be540fU, 0x44483e0dU, 0x964ff507U, 0xe9814c87U, 0x9c42fbcfU, 0x62a1572bU, 0xd6b2b83dU, 0x969b486U, 0xedbcafccU, 0xebc96923U, 0xfb0d4d36U, 0xc2a0f80dU, 0x46b25408U, 0xf16a3e0aU, 0x49bcf508U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xb0000000U, 0x98000000U, 0xa4000000U, 0x7a000000U, 0xd5000000U, 0x2800000U, 0x60400000U, 0x51e00000U, 0x88700000U, 0x8c280000U, 0x47c40000U, 0xbe20000U, 0xad710000U, 0xb6aa8000U, 0x3386c000U, 0xb8006000U, 0x54039000U, 0x42036800U, 0xc1019400U, 0xe0826a00U, 0x11431100U, 0x2960af80U, 0x3d3175c0U, 0xdf4a3aa0U, 0xaff49e10U, 0xd62b6808U, 0x62c59404U, 0x31606a0aU, 0xd932110bU, 0x54a2f89U, 0xcaf7b5caU, 0x4caa5aa7U, 0xa6870e1dU, 0x1a800008U, 0x84400002U, 0x8be0000fU, 0xed700003U, 0x16a80001U, 0x8384000eU, 0x20020007U, 0xf0010007U, 0x3802800bU, 0x1402c005U, 0xe202600eU, 0x7102900dU, 0x7881e80cU, 0xb5435408U, 0x53600a0eU, 0xe831810bU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x30000000U, 0x18000000U, 0x34000000U, 0x8a000000U, 0x9d000000U, 0x67800000U, 0x82400000U, 0x40e00000U, 0x60f00000U, 0x91480000U, 0x29440000U, 0x2d620000U, 0xbfb30000U, 0x162a8000U, 0xfbf4c000U, 0xe4ca6000U, 0xc207d000U, 0x2002a800U, 0xf001b400U, 0xb8037e00U, 0x4021900U, 0x92034b80U, 0xa90327c0U, 0xed81f320U, 0x1f40d810U, 0x27602808U, 0xe2b1740cU, 0xd1ab1e0aU, 0x49b6c903U, 0xbc2b6381U, 0x96f653c3U, 0x3b48ed28U, 0x44451119U, 0xf2e1cb8eU, 0x39f3e7c4U, 0xc4c9932eU, 0x32040815U, 0x98000000U, 0xf400000dU, 0x2a000000U, 0xad000001U, 0x7f800006U, 0xb6400004U, 0xcae00002U, 0xfdf00003U, 0xf6c8000dU, 0xab040005U, 0x6d82000dU, 0xdf43000dU, 0x80000000U, 0x40000000U, 0xe0000000U, 0xd0000000U, 0x8000000U, 0x4c000000U, 0x2000000U, 0xb5000000U, 0x36800000U, 0xc2c00000U, 0x14200000U, 0x7500000U, 0x1bf80000U, 0x50340000U, 0x48a20000U, 0xac910000U, 0xd35b8000U, 0xbca74000U, 0x7bfa2000U, 0xc0343000U, 0xa0a18800U, 0x30909400U, 0xd95b7a00U, 0x45a57b00U, 0x4f7a7880U, 0xb7f6f940U, 0x82013de0U, 0xf502dfd0U, 0xd6820808U, 0x12c3d404U, 0x1c235a0eU, 0x4b504b0dU, 0x19f87080U, 0xe5352d44U, 0x7e2267e0U, 0x6e5294dbU, 0xc77a788bU, 0xbbf6f948U, 0x60013defU, 0x9002dfddU, 0xe8020809U, 0x9c03d405U, 0xa035a0aU, 0xf9004b0cU, 0x3480708eU, 0x77c12d43U, 0x22a067e6U, 0xc59394d7U, 0xfd9f880U, 0x5765b94eU, 0x53591de6U, 0xfca7efd3U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x50000000U, 0x68000000U, 0x4c000000U, 0x76000000U, 0xf7000000U, 0x36800000U, 0xd7400000U, 0x87e00000U, 0xef300000U, 0xa3a80000U, 0xd5440000U, 0x23aa0000U, 0x15470000U, 0xc3a98000U, 0x45464000U, 0xaba82000U, 0x9477000U, 0xdda9f800U, 0xfe44ac00U, 0xeb292200U, 0x2907f100U, 0x6ccb3d80U, 0xc6344dc0U, 0xcf61b320U, 0x137318d0U, 0xeccb3d88U, 0x6344dccU, 0x2f61b32eU, 0x437318d5U, 0x84cb3d8eU, 0x4a344dc8U, 0x5961b329U, 0xb47318daU, 0xb24b3d8dU, 0x9d744dc5U, 0xde81b321U, 0x5b4318d4U, 0x11e33d87U, 0x48304dc8U, 0xfd2bb323U, 0x4e0418d5U, 0xd24abd8bU, 0xd760dccU, 0x56839329U, 0x474368d5U, 0xfe34586U, 0xf332a1c3U, 0xbdaab127U, 0x6e4499d7U, 0x80000000U, 0x40000000U, 0x60000000U, 0x90000000U, 0xc8000000U, 0x74000000U, 0x52000000U, 0x3000000U, 0xeb800000U, 0x6f400000U, 0x64600000U, 0xdaf00000U, 0x17980000U, 0x297c0000U, 0xa59a0000U, 0xfa7d0000U, 0xe61b8000U, 0x713f4000U, 0x1878a000U, 0xdcce9000U, 0xb661e800U, 0x99f29c00U, 0x9c184600U, 0xd63e2100U, 0x9fa5780U, 0x548e0ac0U, 0xa380a9e0U, 0x5b413f30U, 0x56625788U, 0x49f20ac4U, 0x341aa9e6U, 0x323c3f39U, 0x93f9d784U, 0x238d4ac3U, 0x1a0209e3U, 0x3702af39U, 0xd9803f8aU, 0xfc43d6c5U, 0x47e04fe5U, 0xc1b18e34U, 0x21f9e80bU, 0xf08e9c07U, 0x5982460fU, 0xbc43210bU, 0x27e1d78dU, 0x51b14ac4U, 0xe9f809e8U, 0x848faf3fU, 0xb83bf82U, 0xbf4096ceU, 0xcc62efe2U, 0x3ef21e3bU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0xb8000000U, 0x4000000U, 0x6e000000U, 0x97000000U, 0xf2800000U, 0xedc00000U, 0x13600000U, 0x5c900000U, 0xdb580000U, 0x31e40000U, 0x9da0000U, 0xcc270000U, 0x2b88000U, 0x44b44000U, 0xfe26000U, 0xe6505000U, 0x9ab9d800U, 0x50b50c00U, 0x79e29200U, 0xa552fb00U, 0xbe38bf80U, 0x2e77d940U, 0xf6000ae0U, 0x830112d0U, 0x84803f88U, 0xaec3994cU, 0x37e26aeaU, 0x225142ddU, 0x54b9e783U, 0x17b6954cU, 0x3360f8ecU, 0x4c93b9d4U, 0xc359580cU, 0xe5e54c02U, 0xdfdaf20dU, 0x5f25ab01U, 0x9e39e789U, 0x3e76954dU, 0xee00f8e7U, 0x5703b9d0U, 0x5281580aU, 0x3dc14c05U, 0xab60f20bU, 0x5892ab0aU, 0xb559678fU, 0xa6e6d542U, 0xfb5898e1U, 0x21e4e9d1U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0x68000000U, 0xec000000U, 0x22000000U, 0x2b000000U, 0x36800000U, 0x9d400000U, 0x6a200000U, 0x16700000U, 0x4de80000U, 0x330c0000U, 0x936a0000U, 0x824f0000U, 0x3b498000U, 0x8f3fc000U, 0x28202000U, 0xcd707000U, 0xf36aa800U, 0x724fdc00U, 0xb34bf200U, 0x533e6900U, 0x62207a80U, 0xa7140c0U, 0xe7ea6520U, 0xc40d90f0U, 0xefe9fa88U, 0xd80e80ccU, 0x45ea452eU, 0x2f0de0f3U, 0x396b528eU, 0x754d5cc2U, 0x47cbb72cU, 0xd57c89f1U, 0x5682a80dU, 0x6d43dc0bU, 0xe221f20aU, 0xca716900U, 0x7e9fa81U, 0xf40e80c4U, 0x87ea452dU, 0x340de0fbU, 0x67eb528cU, 0x40d5cceU, 0xfebb723U, 0xe80c89f6U, 0x2deaa806U, 0xc30fdc0eU, 0x1b6bf20cU, 0x5e4e6900U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0x28000000U, 0xd4000000U, 0x8a000000U, 0xff000000U, 0x84800000U, 0x73c00000U, 0x13200000U, 0xc2b00000U, 0xfb380000U, 0x361c0000U, 0x401a0000U, 0xe0af0000U, 0x11228000U, 0x19b3c000U, 0xfdb82000U, 0x5edf9000U, 0x75b88800U, 0x7adfac00U, 0xf7baba00U, 0x61ddf300U, 0xd1387e80U, 0x391e55c0U, 0xcc9ba860U, 0x776cbeb0U, 0xa000f688U, 0xf001f9ccU, 0x8011262U, 0xe4014db3U, 0xa200880aU, 0x2b03ac01U, 0xe80ba0aU, 0x8cc2f30cU, 0x97a2fe8aU, 0xb17195caU, 0xe8198869U, 0xf4ac2eb3U, 0xbb22fe8fU, 0xd6b195c8U, 0x51398867U, 0xf91c2eb1U, 0xec9afe84U, 0x476d95c3U, 0x88038861U, 0x24032eb7U, 0x82007e84U, 0x1b0255c0U, 0x2681a86bU, 0x58c3beb3U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0xb8000000U, 0x84000000U, 0x1a000000U, 0xaf000000U, 0xbd800000U, 0xdfc00000U, 0x14e00000U, 0x43500000U, 0xda380000U, 0x4e1c0000U, 0x4cda0000U, 0x364d0000U, 0x29608000U, 0xdc904000U, 0x6ed86000U, 0x5d4f5000U, 0x2ee08800U, 0xfc51ac00U, 0x7fb81e00U, 0x45dc8300U, 0xfa3a4580U, 0x5e1d6240U, 0x54dbd360U, 0xe24ec930U, 0x8b62cd88U, 0xf790ce44U, 0xc959cd6aU, 0x2d8f4a35U, 0x87800803U, 0x60c1ec0cU, 0xb1607e0bU, 0x4893d30fU, 0x6cdacd80U, 0x264cce45U, 0x3163cd60U, 0x8924a3eU, 0xccd8880eU, 0x764dac0dU, 0x89621e0fU, 0x8c918302U, 0xd6dac584U, 0xd94d2241U, 0x34e3b363U, 0x5351993cU, 0xc23a4583U, 0x9a1d624bU, 0xeedbd36aU, 0x1d4ec930U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0x8000000U, 0xf4000000U, 0xf6000000U, 0x8b000000U, 0xc9800000U, 0x55400000U, 0x67200000U, 0xf3f00000U, 0x34780000U, 0x57440000U, 0x1ada0000U, 0xb1f50000U, 0xa9818000U, 0x6540c000U, 0x8f23a000U, 0x77f21000U, 0xca7bf800U, 0x2845fc00U, 0x255afe00U, 0x6fb67900U, 0x7233a80U, 0xc3f25ac0U, 0xdc7aed60U, 0xd34482d0U, 0xe4d94288U, 0xcef766c4U, 0x9603b36eU, 0xbb00ebd7U, 0x21818008U, 0xd140c00bU, 0x9923a001U, 0x8cf2100fU, 0xbfbf80cU, 0x8905fc0aU, 0xb47afe09U, 0x17467907U, 0xfadb3a8fU, 0xc1f65ac0U, 0xa180ed67U, 0x914182d4U, 0x7920c281U, 0xfcf3a6c7U, 0x3fa1367U, 0x7d07fbdbU, 0x427bf80eU, 0x9c45fc0fU, 0x335afe0bU, 0x94b6790eU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x90000000U, 0x68000000U, 0xf4000000U, 0x62000000U, 0xdf000000U, 0x79800000U, 0xdd400000U, 0x76e00000U, 0x2cf00000U, 0xcfb80000U, 0x51ec0000U, 0xc8da0000U, 0x845d0000U, 0x9b818000U, 0x42434000U, 0xef622000U, 0x61b19000U, 0xd1582800U, 0x891cac00U, 0x65626e00U, 0xab10900U, 0x2adbbd80U, 0x1b5d86c0U, 0x2014560U, 0xf032470U, 0xf1821588U, 0xb9426ac4U, 0x7ce10b6eU, 0x7f3bd79U, 0xd439800eU, 0x53af400bU, 0xc7b82008U, 0x75ec9004U, 0x22d9a801U, 0x3f5fec02U, 0xe8004e01U, 0xb400990fU, 0x8203958bU, 0x4f012ac8U, 0x11832b6bU, 0x29422d7aU, 0x14e1a80dU, 0xf3f3ec05U, 0xb63a4e0cU, 0x8cad9907U, 0xbe3a1582U, 0xa8ae6ac3U, 0x543b0b6eU, 0x13aebd7bU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0x18000000U, 0xdc000000U, 0x42000000U, 0x37000000U, 0x20800000U, 0xf1400000U, 0x28600000U, 0x94900000U, 0x87880000U, 0xa83c0000U, 0x556a0000U, 0xe6ef0000U, 0xf8038000U, 0x4c024000U, 0x3a01e000U, 0xbb023000U, 0x7a816800U, 0x1a43ac00U, 0x4ae18a00U, 0x52d31900U, 0x8f682380U, 0xcded9740U, 0xfa80bfa0U, 0xda43f2b0U, 0x2ae2cb88U, 0x2d07b4cU, 0x976ad5a6U, 0x11eddbb5U, 0xb8800009U, 0xed400001U, 0xa600002U, 0xf3900006U, 0xbf080003U, 0x857c0002U, 0x3f0a0006U, 0x457f000aU, 0x5f0b800aU, 0x157e4005U, 0x470be007U, 0xc97d3007U, 0x50ae807U, 0xfe7dec0eU, 0x258a6a06U, 0xf3e2905U, 0xdeacb88U, 0x9bac7b45U, 0x8a60d5a7U, 0x3392dbbeU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xf0000000U, 0xf8000000U, 0x34000000U, 0x62000000U, 0xf5000000U, 0xa8800000U, 0xfcc00000U, 0x8e200000U, 0x53f00000U, 0xc7780000U, 0x95740000U, 0xb8020000U, 0xd4e50000U, 0xb2808000U, 0xfdc0c000U, 0x64a02000U, 0xaa30f000U, 0x19d8f800U, 0xe443400U, 0x935a6200U, 0xe761f500U, 0x657a2880U, 0x40913cc0U, 0xe0022e20U, 0xd0e563f0U, 0x8809f78U, 0xccc09174U, 0x56200202U, 0x97f0e5e5U, 0x5d788000U, 0x5474c000U, 0x72822000U, 0xdd25f000U, 0x94207800U, 0x52f0f400U, 0x2df84200U, 0x6cb40500U, 0x66a25080U, 0x4fd5c8c0U, 0x99d86c20U, 0xce4466f0U, 0xb35a4ff8U, 0x176199b4U, 0x9d7a4e22U, 0x74917315U, 0x8202b7f8U, 0x25e5adb4U, 0xa0002c22U, 0x30008615U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xf0000000U, 0xf8000000U, 0xec000000U, 0x7e000000U, 0x61000000U, 0x5c800000U, 0xe6c00000U, 0xdda00000U, 0x2a700000U, 0x93380000U, 0x13cc0000U, 0xd3ce0000U, 0x73790000U, 0x83a08000U, 0x7b70c000U, 0x97b8a000U, 0xe90cf000U, 0x886ef800U, 0xd409ec00U, 0x3218fe00U, 0xef7ca100U, 0xc556fc80U, 0x56c516c0U, 0x4556a5a0U, 0x96c50670U, 0xe556cd38U, 0x66c542ccU, 0x1d56574eU, 0x8ac549b9U, 0x6356f800U, 0xebc5ec00U, 0x3fd6fe00U, 0xd05a100U, 0xe2767c80U, 0x2775d6c0U, 0x714e05a0U, 0x34b9f670U, 0xa2803538U, 0x47c0aeccU, 0x2120a94eU, 0x3cb0e8b9U, 0xb6988480U, 0xd5bc3ac0U, 0x3ef6fba0U, 0x1b55770U, 0xceec9b8U, 0xeec9b80cU, 0xc9b80ceeU, 0xb80ceec9U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0x58000000U, 0x2c000000U, 0x9a000000U, 0xf9000000U, 0x3c800000U, 0xb2c00000U, 0xad200000U, 0x3a300000U, 0x89980000U, 0x448c0000U, 0x2eea0000U, 0x6f810000U, 0xef208000U, 0x2f30c000U, 0xf182000U, 0xbf4cb000U, 0xe74a5800U, 0xcb712c00U, 0x51981a00U, 0xa88c3900U, 0x94ea1c80U, 0x268102c0U, 0x8ba07520U, 0xb1f0d630U, 0x38383398U, 0x7c7c0d8cU, 0x52524a6aU, 0x3d3df141U, 0xd2525800U, 0xfd3d2c00U, 0xf2521a00U, 0x4d3d3900U, 0xaa529c80U, 0x613dc2c0U, 0x30525520U, 0x983d6630U, 0xcd2eb98U, 0x2afde18cU, 0xa1f2706aU, 0x10cd7841U, 0x286a1c80U, 0x544102c0U, 0x6807520U, 0x3bc0d630U, 0xe9a03398U, 0x14f00d8cU, 0xe6b84a6aU, 0xabbcf141U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0xd8000000U, 0xac000000U, 0x8e000000U, 0x9000000U, 0x9e800000U, 0xa1c00000U, 0xcaa00000U, 0x33700000U, 0x95780000U, 0x85c0000U, 0x24b60000U, 0x6a350000U, 0x43788000U, 0x6d5cc000U, 0x14362000U, 0x72f5b000U, 0xcf585800U, 0x53ec6c00U, 0xc5eeae00U, 0x40d9b900U, 0xe016c680U, 0x9045cdc0U, 0x6880e4a0U, 0x74c04a70U, 0x2220f3f8U, 0x87b0b59cU, 0x9758b816U, 0x3fecfc45U, 0x6beec680U, 0xf9d9cdc0U, 0xa696e4a0U, 0x9d854a70U, 0x2c2073f8U, 0x4eb0759cU, 0x29d89816U, 0x2e2c4c45U, 0x794e1e80U, 0x66a961c0U, 0xbdee6aa0U, 0x9cd94370U, 0x9616ed78U, 0x8545d45cU, 0xa000d2b6U, 0x7000bf35U, 0xf800abf8U, 0x1c00d99cU, 0x56001616U, 0xa5004545U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xf0000000U, 0xa8000000U, 0x2c000000U, 0xa2000000U, 0x2d000000U, 0xda800000U, 0xf9400000U, 0xec600000U, 0x2b00000U, 0x3d480000U, 0x825c0000U, 0x7d4a0000U, 0x62610000U, 0x8dc88000U, 0xca1c4000U, 0xa1aae000U, 0x6891f000U, 0x8c602800U, 0xb2b06c00U, 0x75484200U, 0x5e5cdd00U, 0x774a7280U, 0x6361d540U, 0xf548ce60U, 0x1e5c6fb0U, 0x974a07c8U, 0x93618b1cU, 0x5d48b92aU, 0x325c0cd1U, 0x354af280U, 0xbe619540U, 0x87c82e60U, 0xcb1c9fb0U, 0xd92aafc8U, 0xbcd1a71cU, 0xba801b2aU, 0x494021d1U, 0xa4602800U, 0xdeb06c00U, 0x37484200U, 0x835cdd00U, 0x5ca7280U, 0xb621d540U, 0xbb28ce60U, 0x31ec6fb0U, 0x708207c8U, 0xe87d8b1cU, 0xcc62b92aU, 0x528d0cd1U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0xc8000000U, 0x7c000000U, 0x82000000U, 0x4f000000U, 0xbe800000U, 0xedc00000U, 0x21600000U, 0xab700000U, 0x78680000U, 0x746c0000U, 0x1e9a0000U, 0xfdcb0000U, 0x39088000U, 0x2f1cc000U, 0x4ef2e000U, 0xc5a73000U, 0x6d924800U, 0xe1d7bc00U, 0x4b7ae200U, 0x487bbf00U, 0xbc801680U, 0x62c061c0U, 0x7fe08b60U, 0x76b0a870U, 0x91088ce8U, 0xa31caaacU, 0xe4f2037aU, 0xc6a7f47bU, 0x99125e80U, 0x3f17ddc0U, 0x569a6960U, 0x41cb1770U, 0x5b089a68U, 0x501ccb6cU, 0x3872881aU, 0x54675c0bU, 0xcef2d268U, 0x5a7776cU, 0x8d926a1aU, 0xd1d7e30bU, 0x837a44e8U, 0x347bd6acU, 0x3e80017aU, 0x2dc07b7bU, 0xc1608000U, 0x9b70c000U, 0xb068e000U, 0x86c3000U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0x98000000U, 0x2c000000U, 0x6000000U, 0xcd000000U, 0x8a800000U, 0x1bc00000U, 0xffa00000U, 0xad500000U, 0x7af80000U, 0xb3dc0000U, 0x5b2e0000U, 0x1f290000U, 0x9d588000U, 0xf28cc000U, 0x7d62000U, 0x71f51000U, 0xd4f61800U, 0xda65ec00U, 0x632ea600U, 0xe3291d00U, 0x2358b280U, 0x38ce7c0U, 0x135641a0U, 0x8b355c50U, 0xa7d6ee78U, 0xa1f5891cU, 0x6cf6880eU, 0xe665b4b9U, 0xfd2eaa80U, 0x2290bc0U, 0xafd8e7a0U, 0xd54c4150U, 0x66765cf8U, 0x3da56edcU, 0x228ec9aeU, 0xbf79e8e9U, 0x4d20c4f8U, 0x4a9042dcU, 0x3b584faeU, 0xef8ce5e9U, 0x3556ee78U, 0x5635891cU, 0xb556880eU, 0x9635b4b9U, 0x9556aa80U, 0x86350bc0U, 0xd56e7a0U, 0xaa354150U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0x98000000U, 0x54000000U, 0x3a000000U, 0x9d000000U, 0x7e800000U, 0x7f400000U, 0x17200000U, 0xab500000U, 0x6df80000U, 0x96a40000U, 0x83d20000U, 0x71e10000U, 0xc0d88000U, 0xe0f44000U, 0x30aaa000U, 0x8059000U, 0xcc2a1800U, 0x6e451400U, 0xa78a1a00U, 0xe3554d00U, 0x1d2c680U, 0x68e1fb40U, 0xbc589520U, 0xc6b4b250U, 0xfb0a1178U, 0x1515b0e4U, 0xf272c872U, 0xb1f12cf1U, 0x2000de80U, 0xd000ef40U, 0x38008f20U, 0xc400ff50U, 0xa20057f8U, 0xc9000ba4U, 0x4480fd52U, 0xe2400ea1U, 0x69a0d7f8U, 0xd4104ba4U, 0x7ad85d52U, 0x3df49ea1U, 0xee2a4ff8U, 0xe7451fa4U, 0x430ae752U, 0x911543a1U, 0xf0721178U, 0xe8f1b0e4U, 0xfc80c872U, 0x66402cf1U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0x8000000U, 0x84000000U, 0xb2000000U, 0xb9000000U, 0xbe800000U, 0x4fc00000U, 0x55600000U, 0xf8f00000U, 0xac280000U, 0x66d40000U, 0xb30a0000U, 0x8bb50000U, 0xc7c88000U, 0x11e4c000U, 0xaa42e000U, 0xa591b000U, 0xd0ea8800U, 0x78854400U, 0x6c80d200U, 0x86c0c900U, 0x3e05680U, 0x83307bc0U, 0x4348ef60U, 0xa324c5f0U, 0x13a2a0a8U, 0x1ba19014U, 0x9f22d8eaU, 0x2d61fc85U, 0x94c25e80U, 0x2a51ffc0U, 0x658add60U, 0x3075bcf0U, 0xc8a87e28U, 0x6414afd4U, 0x2eae58aU, 0xb185f075U, 0x3a00a8a8U, 0xfd001414U, 0xec80eaeaU, 0x46c08585U, 0xe3e08000U, 0x3330c000U, 0x4b48e000U, 0x2724b000U, 0xa1a20800U, 0xa2a18400U, 0x21a23200U, 0x62a17900U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x30000000U, 0x78000000U, 0x24000000U, 0x9e000000U, 0x47000000U, 0x67800000U, 0xf7400000U, 0xdf200000U, 0xb3100000U, 0x71680000U, 0x8c4c0000U, 0x32520000U, 0xe5d50000U, 0xaa528000U, 0x31d5c000U, 0x2c52e000U, 0x62d5f000U, 0xadd29800U, 0xf695d400U, 0x8b720600U, 0xf5c59300U, 0x42ba6180U, 0x3dd96440U, 0xdea0bea0U, 0xe750d750U, 0x37c84fc8U, 0xbf1c9b1cU, 0x839a1d9aU, 0x9c94ec9U, 0xa8484fc8U, 0xac5c9b1cU, 0xa2ba1d9aU, 0xcdd94ec9U, 0xc6a04fc8U, 0xf3509b1cU, 0xd1c81d9aU, 0xdc1c4ec9U, 0x7a1acfc8U, 0xb9895b1cU, 0x10e8fd9aU, 0xe80cbec9U, 0xcf2d7c8U, 0xf2854f1cU, 0x859a1b9aU, 0x9ac9ddc9U, 0x49c8ae48U, 0x81c3f5cU, 0xfc1a433aU, 0xea896999U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0x78000000U, 0x9c000000U, 0xee000000U, 0x1b000000U, 0xcb800000U, 0xc3400000U, 0xc7a00000U, 0x5100000U, 0x88680000U, 0xc4740000U, 0x225a0000U, 0x3da10000U, 0x345a8000U, 0x7aa1c000U, 0xf1da6000U, 0x12e17000U, 0x85fa1800U, 0x48b1ec00U, 0x2432f600U, 0x92d5f700U, 0x45803d80U, 0xa8403440U, 0x94207a20U, 0xea50f150U, 0xd9c81248U, 0x46648524U, 0x8fb24812U, 0x21952485U, 0x1a201248U, 0x81508524U, 0x8a484812U, 0xa9242485U, 0xde129248U, 0xa3854524U, 0xb7c82812U, 0x9d645485U, 0xa4320a48U, 0x52d56924U, 0xa580be12U, 0x1840d385U, 0xec202fc8U, 0x7650b164U, 0x37c83232U, 0x5d64d5d5U, 0x44328000U, 0xe2d5c000U, 0xdd806000U, 0x84407000U, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0x58000000U, 0x7c000000U, 0xc2000000U, 0xe1000000U, 0xd800000U, 0xd7c00000U, 0x2aa00000U, 0xf5300000U, 0x9ba80000U, 0xc0f40000U, 0x20c60000U, 0x702f0000U, 0x48668000U, 0x241f4000U, 0xbe4ee000U, 0x232b5000U, 0xec28b800U, 0xda342c00U, 0xfde6fa00U, 0xdfdf8d00U, 0x6eee1780U, 0x5b1b0ac0U, 0xe0000520U, 0x500093f0U, 0x38008488U, 0x6c008e04U, 0x9a000bceU, 0x9d00d8ebU, 0xcf803c88U, 0x36c0a204U, 0x2720f1ceU, 0x22f055ebU, 0xb108ab08U, 0x35c4e8c4U, 0xbb6e14eeU, 0xb0db961bU, 0x68a09780U, 0x54304ac0U, 0xf628e520U, 0x734c3f0U, 0x5266bc88U, 0xf91fe204U, 0x11ce11ceU, 0x5eb05ebU, 0x93081308U, 0x84c4c4c4U, 0x8eeeeeeeU, 0xb1b1b1bU, 0x80000000U, 0x40000000U, 0x20000000U, 0x30000000U, 0xb8000000U, 0xac000000U, 0x72000000U, 0xb1000000U, 0x3800000U, 0xd2c00000U, 0xc1600000U, 0x9b900000U, 0x4e480000U, 0xb740000U, 0x864e0000U, 0x3f0b0000U, 0x68068000U, 0x447f4000U, 0x7648a000U, 0xe7747000U, 0xd44e9800U, 0xbe0b9c00U, 0xd3864a00U, 0x3abf5d00U, 0xc528d180U, 0xcde413c0U, 0x99865ae0U, 0x67bfd550U, 0x94a8c528U, 0x9e24cde4U, 0xe3669986U, 0x82ef67bfU, 0x698014a8U, 0xbfc0de24U, 0x28e0c366U, 0x6450b2efU, 0x46a8d180U, 0x5f2413c0U, 0x78e65ae0U, 0xcc2fd550U, 0x62e0c528U, 0x3950cde4U, 0x17289986U, 0xce467bfU, 0x20694a8U, 0x297f9e24U, 0x9fc86366U, 0x18b4c2efU, 0xdcae4980U, 0xea5b8fc0U, 0x2d2e10e0U, 0xc99b8850U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x70000000U, 0x88000000U, 0x44000000U, 0x4a000000U, 0x47000000U, 0xdd800000U, 0x42400000U, 0xc3200000U, 0x77100000U, 0x75b80000U, 0x966c0000U, 0x715e0000U, 0xfc950000U, 0xa6e68000U, 0xd9f9c000U, 0x28386000U, 0x142cb000U, 0x527e6800U, 0xfb853400U, 0x5b5e4200U, 0xb95c300U, 0x1366f780U, 0xafb9b540U, 0x2918f6a0U, 0x603cc150U, 0xb0469498U, 0x68a9927cU, 0x34a09b66U, 0xc250ebb9U, 0x3186318U, 0x973c273cU, 0x5c66dc6U, 0x1ee92ae9U, 0x35807780U, 0xb6407540U, 0xe12096a0U, 0x4107150U, 0x6a38fc98U, 0xd72ca67cU, 0x25fed966U, 0x8ec528b9U, 0xcdfe9498U, 0x7ac5927cU, 0xeffe9b66U, 0x9c5ebb9U, 0xf07ee318U, 0x4885e73cU, 0xa4de0dc6U, 0x3ad59ae9U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x50000000U, 0xd8000000U, 0xfc000000U, 0xf6000000U, 0xd5000000U, 0xbf800000U, 0x2c400000U, 0xeee00000U, 0x9700000U, 0x19080000U, 0x21640000U, 0xad6a0000U, 0xd3130000U, 0x22828000U, 0x9707c000U, 0x98e0a000U, 0x1c709000U, 0x8688f800U, 0x5d24ac00U, 0x9b8a2e00U, 0x26632900U, 0xcd8ac980U, 0x63633940U, 0x8a0af160U, 0xe323b530U, 0x4aea8fe8U, 0xc3534414U, 0x1a623a62U, 0x1b774b77U, 0xe668be68U, 0xed54d154U, 0x3302e502U, 0x5247d747U, 0x1f80f800U, 0xbc40ac00U, 0x16e02e00U, 0xa5702900U, 0x37084980U, 0x864f940U, 0xe4ea5160U, 0x2a532530U, 0x73e277e8U, 0xb237e814U, 0x6f081462U, 0x34646277U, 0x32ea77e8U, 0xaf53e814U, 0x14621462U, 0x62776277U, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0x58000000U, 0xac000000U, 0x6a000000U, 0x85000000U, 0xfb800000U, 0xa8c00000U, 0x84200000U, 0xae300000U, 0x4b080000U, 0xe0740000U, 0x10860000U, 0x388f0000U, 0xfc2e8000U, 0x320b4000U, 0x2980e000U, 0x91c01000U, 0x2da03800U, 0x7ff0fc00U, 0x6a83200U, 0xcf842900U, 0x4e2e9180U, 0x5b0b2dc0U, 0xd800ffa0U, 0xec0046f0U, 0xa00af28U, 0xd5001e44U, 0xa380038eU, 0x4c074fbU, 0xee2086a8U, 0x2b308f84U, 0xb0882e2eU, 0x48b40b0bU, 0x94a68000U, 0x96bf4000U, 0xb726e000U, 0xd27f1000U, 0x3906b800U, 0xa94fbc00U, 0xd18ed200U, 0x4dfb3900U, 0x2f282980U, 0x5e4491c0U, 0x638e2da0U, 0x24fb7ff0U, 0xdea886a8U, 0x23848f84U, 0x442e2e2eU, 0x8e0b0b0bU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x50000000U, 0xe8000000U, 0x44000000U, 0x5e000000U, 0xad000000U, 0xef800000U, 0x68400000U, 0x84600000U, 0xfe500000U, 0xfd280000U, 0x7f40000U, 0x2c620000U, 0xda4f0000U, 0x53068000U, 0x12dfc000U, 0x6f802000U, 0xa8403000U, 0x24602800U, 0xae501400U, 0x15283a00U, 0x43f41100U, 0x72621780U, 0x774f2b40U, 0xbc86bbe0U, 0x7a9fda10U, 0xebe00118U, 0x56100f94U, 0xd948174aU, 0xa9a415fdU, 0x394a3118U, 0x99bb2793U, 0x21648341U, 0x6590eff7U, 0xd3068000U, 0xd2dfc000U, 0xcf802000U, 0xf8403000U, 0xcc602800U, 0xea501400U, 0x4b283a00U, 0xeef41100U, 0x9de21780U, 0x1f0f2b40U, 0x38e6bbe0U, 0x84cfda10U, 0x16c80118U, 0x51e40f94U, 0xf52a174aU, 0x73eb15fdU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xb0000000U, 0x18000000U, 0x4000000U, 0xda000000U, 0x9000000U, 0x22800000U, 0xe8400000U, 0xbc600000U, 0xe300000U, 0x7b580000U, 0x378c0000U, 0x14c20000U, 0x874d0000U, 0x99d48000U, 0xbfb94000U, 0x18802000U, 0x91403000U, 0xe6e01800U, 0x52702c00U, 0x5380600U, 0x34bc0100U, 0x971a3680U, 0x51810240U, 0x13f688a0U, 0xde847a10U, 0x466c8f18U, 0x1745738cU, 0x91fa26d6U, 0x73f111e3U, 0x6ece9b30U, 0x5e384cd3U, 0x1376b6f5U, 0x4bc45caeU, 0x7a8c8000U, 0x4c354000U, 0xb6422000U, 0xaf0d3000U, 0x45b49800U, 0x1896c00U, 0x7bd82600U, 0xa2cc3100U, 0x28222e80U, 0xdc3d2e40U, 0xbe6c8ea0U, 0x63457b10U, 0x33fa3998U, 0xcef131ccU, 0x8e4e8e76U, 0xbb785bf3U, 0x80000000U, 0x40000000U, 0x20000000U, 0x50000000U, 0x88000000U, 0x9c000000U, 0x2e000000U, 0x5000000U, 0xab800000U, 0x1c400000U, 0x6e200000U, 0x25100000U, 0xfba80000U, 0x94040000U, 0xf26e0000U, 0xb070000U, 0xfeaa8000U, 0x3fd1c000U, 0xee202000U, 0x65101000U, 0xdba80800U, 0xc4041400U, 0x7a6e2200U, 0x97072700U, 0xd0aa8b80U, 0x3ad1c140U, 0x45a00ae0U, 0x79501710U, 0xb5881388U, 0xe1141d44U, 0x81c61ceaU, 0x3030201U, 0x22c4b71bU, 0x31d6c381U, 0xbb0ab54aU, 0x4681d8e4U, 0x5ba80800U, 0x84041400U, 0x5a6e2200U, 0xc7072700U, 0x58aa8b80U, 0xa6d1c140U, 0x6ba00ae0U, 0x7c501710U, 0x1e081388U, 0xfd541d44U, 0xefe61ceaU, 0x26130201U, 0xd96cb71bU, 0xa5d2c381U, 0x4964b54aU, 0x4d86d8e4U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x50000000U, 0xc8000000U, 0x3c000000U, 0x3e000000U, 0x67000000U, 0xf9800000U, 0xcc400000U, 0x66600000U, 0xb3100000U, 0xaba80000U, 0x5d240000U, 0xc4fe0000U, 0xb8cf0000U, 0x66bb8000U, 0x71a8c000U, 0x10602000U, 0x28103000U, 0x4c280800U, 0xa6641400U, 0x931e3200U, 0xfb9f0f00U, 0x95738f80U, 0xf89cd9c0U, 0x86b61e60U, 0x1bb0310U, 0x880d9198U, 0xdc13f8c4U, 0x4e6db8eaU, 0xff03e849U, 0xdc596bfU, 0xce27d3f3U, 0x3f3bbdceU, 0x2de8c47aU, 0x9e000800U, 0xf7001400U, 0x11803200U, 0xa0400f00U, 0x90600f80U, 0xe81019c0U, 0x6c283e60U, 0xf6643310U, 0x5b1e1998U, 0xc79f2cc4U, 0xab73aaeaU, 0x9f9cd749U, 0x7f36113fU, 0xcdfb1e33U, 0xee6d91aeU, 0x6f03c86aU, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0x58000000U, 0x44000000U, 0x7e000000U, 0x69000000U, 0x5b800000U, 0xdc400000U, 0x5a200000U, 0x87100000U, 0xdad80000U, 0x9bec0000U, 0xbc420000U, 0xca0f0000U, 0x6f7c8000U, 0xc6d9c000U, 0xa1a02000U, 0xab501000U, 0xf8f80800U, 0xe8fc2c00U, 0x409a1600U, 0x7ce31100U, 0xf6be9f80U, 0xb996da40U, 0xcf7cb6e0U, 0x36d9e710U, 0xd9a03e88U, 0x5f501dc4U, 0xdef828b6U, 0xc5fc1bfbU, 0x651a2690U, 0xc9a339c3U, 0xf71e92bfU, 0xe2c6dce6U, 0x4f848800U, 0x2a25ec00U, 0xbf3a3600U, 0xeb30100U, 0xdc69780U, 0xc92af640U, 0xabc6a0e0U, 0xa42af610U, 0xae46a108U, 0xa16ac784U, 0xf7e69e56U, 0xbe3afcebU, 0x91e9818U, 0xcbc6e407U, 0x34049a09U, 0x4665d71dU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xb0000000U, 0x48000000U, 0x74000000U, 0xc2000000U, 0xe7000000U, 0xb5800000U, 0xba400000U, 0x9b200000U, 0xa3d00000U, 0x2f180000U, 0x81840000U, 0xd82a0000U, 0xcc190000U, 0x5e078000U, 0xe138c000U, 0xd8982000U, 0x9cc41000U, 0x568a2800U, 0x65892c00U, 0xa23f9200U, 0xb76cdd00U, 0xedaa1080U, 0x365929c0U, 0x65278560U, 0xf2e8c290U, 0xbf8014c8U, 0x694025f4U, 0x4ca01346U, 0x4e9035a1U, 0x49b8096aU, 0xec140096U, 0xae1201c9U, 0x94d297aU, 0x1cb59080U, 0x16e5e9c0U, 0xc595a560U, 0x1235d290U, 0xff0dbcc8U, 0x99f1c9f4U, 0xf407a146U, 0x8238f8a1U, 0x471831eaU, 0x5840556U, 0xf22a16a9U, 0xef1936eaU, 0x618794c8U, 0xc878e5f4U, 0x34383346U, 0x625425a1U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xf0000000U, 0x98000000U, 0xb4000000U, 0x52000000U, 0x7000000U, 0xbf800000U, 0x5a400000U, 0x3b200000U, 0x91d00000U, 0xd3380000U, 0xfdec0000U, 0x954a0000U, 0x58f10000U, 0xb5df8000U, 0x91dc000U, 0x86b82000U, 0xa4ac1000U, 0x7bea2800U, 0xd0613c00U, 0x2847a600U, 0x8c61ed00U, 0x166a3480U, 0xcd2111c0U, 0xce787e0U, 0xb7f1ea90U, 0x667208c8U, 0x151d1974U, 0x1895884eU, 0x15ecc2bbU, 0xf9678cb2U, 0x1eb1fdacU, 0x10d23f3fU, 0x298d0bf3U, 0xd70db480U, 0x9790d1c0U, 0xd635a7e0U, 0x2d7cfa90U, 0x5cffa0c8U, 0xdfcde574U, 0x4a000e4eU, 0xf3003fbbU, 0x4d801032U, 0xad40106cU, 0x1ca03edfU, 0x7f901c63U, 0xba1820c8U, 0x6b3c2574U, 0xf9f22e4eU, 0xff5d2fbbU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x70000000U, 0xf8000000U, 0x4c000000U, 0xa6000000U, 0x89000000U, 0x6e800000U, 0x1a400000U, 0x17600000U, 0x4bf00000U, 0xa2f80000U, 0x7c5c0000U, 0x7e360000U, 0x551b0000U, 0x40808000U, 0x272d4000U, 0x93982000U, 0x7eac3000U, 0x524e3800U, 0x43071c00U, 0xd1d6be00U, 0x75c65300U, 0xd7e08980U, 0xacdd5240U, 0xd16003a0U, 0x72f02a90U, 0xd47803d8U, 0x5a1c1dfcU, 0x37563f3eU, 0xdbeb2e57U, 0x2af8adadU, 0xc8317196U, 0x944e2e58U, 0x7a072da7U, 0xa756b180U, 0x53864e40U, 0x9e80bda0U, 0x222d7990U, 0xbb180a58U, 0x9dec0fbcU, 0xd3ae1c9eU, 0x5eb734c7U, 0xc24e9675U, 0xcb6a706aU, 0x65aeaf66U, 0x9fda50f0U, 0xf8b695adU, 0x4b366d96U, 0xa5989058U, 0x7fc17ea7U, 0x80000000U, 0x40000000U, 0x20000000U, 0x30000000U, 0xb8000000U, 0x3c000000U, 0xde000000U, 0xdf000000U, 0x29800000U, 0x32400000U, 0xe9200000U, 0x62900000U, 0x71d80000U, 0x5e3c0000U, 0x9f2e0000U, 0x9e70000U, 0x26b8000U, 0x5176c000U, 0x5ef82000U, 0xafac1000U, 0x81760800U, 0xb69b0c00U, 0x3be5ae00U, 0xeb41cf00U, 0x33eb9780U, 0x2f36e7c0U, 0xf1d82260U, 0x1e3c1090U, 0xbf2e1c48U, 0x39e71ba4U, 0xba6b85f6U, 0x6d76ef4fU, 0x80f83a2bU, 0x70ac2929U, 0xa8f638b2U, 0x84db0c69U, 0xd2c59f80U, 0x89d1ebc0U, 0x42338c60U, 0x710adf90U, 0x6ef60bc8U, 0x17db3c64U, 0xbd458796U, 0x6891efdfU, 0xe493ae63U, 0xc2dafe8dU, 0x18e3344U, 0xc6373c26U, 0x9313ba2bU, 0x6f9ae929U, 0xe12e18b2U, 0xa6e71c69U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xd0000000U, 0xf8000000U, 0x3c000000U, 0x6e000000U, 0x19000000U, 0x50800000U, 0xca400000U, 0x7b200000U, 0xafd00000U, 0x97a80000U, 0x4b9c0000U, 0x55ae0000U, 0x64ef0000U, 0xf0288000U, 0x68524000U, 0x64082000U, 0x820c1000U, 0x8f262800U, 0x75a33400U, 0xf4aebe00U, 0xa8614f00U, 0x842ebb80U, 0xf2215640U, 0xa70e9c20U, 0xb1f15690U, 0xa6a6a8c8U, 0xdf6d40f4U, 0xcd88886aU, 0x68c27fa7U, 0x16002ccbU, 0x650006ebU, 0x9e803b62U, 0x3403e30U, 0xd3a01380U, 0x59902240U, 0x82880220U, 0xfd4c0990U, 0x92863b48U, 0xe53322b4U, 0xdea6aa4aU, 0xa36d6637U, 0x388bf83U, 0xa1c2505fU, 0xbe800f28U, 0x93400707U, 0x8ba03f83U, 0xb590105fU, 0x14882f28U, 0xd84c1707U, 0x80000000U, 0x40000000U, 0x60000000U, 0xd0000000U, 0xc8000000U, 0xbc000000U, 0x4e000000U, 0x57000000U, 0x80800000U, 0xa400000U, 0xfd200000U, 0x8db00000U, 0xffa80000U, 0xa6840000U, 0x110e0000U, 0x4bdf0000U, 0x74d78000U, 0xb8724000U, 0x84082000U, 0x8a741000U, 0xbd061800U, 0xedab3400U, 0x2fd1b200U, 0x6ed96f00U, 0xad59b380U, 0x5ed45c0U, 0x23ff9820U, 0x38b66690U, 0x8e263548U, 0x771b286cU, 0x30f9866aU, 0x121d6761U, 0x8977a5e3U, 0x7f827aa7U, 0xe68029ddU, 0x71403e20U, 0x9ba02b80U, 0xbcf031c0U, 0x4080a20U, 0xca741990U, 0xdd061ec8U, 0x3dab19acU, 0xe7d18c4aU, 0xd2d97ef1U, 0xe359bb2bU, 0x52ed630bU, 0xa37fa597U, 0x32f640d1U, 0x730610abU, 0xfaab12cbU, 0xcf518fb7U, 0xb4994941U, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0xa8000000U, 0xd4000000U, 0xfa000000U, 0xf9000000U, 0x92800000U, 0x19400000U, 0x42a00000U, 0x21500000U, 0x8ef80000U, 0xa7040000U, 0x59920000U, 0x36f90000U, 0x2b2e8000U, 0xffd04000U, 0x51922000U, 0x12f91000U, 0x592e8800U, 0x62d06c00U, 0x91120a00U, 0x26b92500U, 0x730eb680U, 0xa3c05240U, 0xcfca2ea0U, 0xb9ad2350U, 0xe6c4a628U, 0x136d5a14U, 0x338e8d1eU, 0xd7804a91U, 0xc5ea104cU, 0xc8bd07aaU, 0x101cafd5U, 0x58794965U, 0x5c44a628U, 0x9e2d5a14U, 0xab2e8d1eU, 0xbfd04a91U, 0x7192104cU, 0xa2f907aaU, 0xf12eafd5U, 0xb6d04965U, 0x6b122628U, 0xdfb91a14U, 0xe18ead1eU, 0xba805a91U, 0x8d6a184cU, 0x98fd2baaU, 0x683c85d5U, 0xb4697c65U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xb0000000U, 0x58000000U, 0x1c000000U, 0x72000000U, 0x4f000000U, 0xa1800000U, 0x77400000U, 0x4da00000U, 0xbd300000U, 0xaef80000U, 0x369c0000U, 0x8ab60000U, 0xa8850000U, 0xfe18000U, 0xea0dc000U, 0xf3362000U, 0x83c51000U, 0xd041b800U, 0xa83dec00U, 0xa44e3600U, 0xde191700U, 0x6557a480U, 0xf288ffc0U, 0xa4d79e60U, 0x75c8cad0U, 0x517797e8U, 0x64f8c08cU, 0xd58f8ddeU, 0x164eb77U, 0x8cb9a345U, 0x91a1edadU, 0x6f7812a6U, 0xb1dc0234U, 0x7f1617e8U, 0xb9b5008cU, 0x8b19addeU, 0x8f91fb77U, 0xaa001b45U, 0x130001adU, 0x338024a6U, 0x88401534U, 0xb4203368U, 0xd6703f4cU, 0x915813beU, 0xc4ac21a7U, 0x85ce34adU, 0xe9592d21U, 0xc8f79f78U, 0xffb8e943U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0x88000000U, 0x34000000U, 0xa2000000U, 0x3000000U, 0x41800000U, 0xf7400000U, 0x3a00000U, 0x4100000U, 0x9a080000U, 0x4f140000U, 0xfb20000U, 0xea550000U, 0xd73b8000U, 0x13a1c000U, 0x2c122000U, 0xfe451000U, 0x6533a800U, 0x38b5d400U, 0x9a00200U, 0x23101d00U, 0x51880080U, 0xdf5414c0U, 0x67923260U, 0x2e0530d0U, 0xad13a868U, 0xace5c1c4U, 0xfb8816e2U, 0xa8543e15U, 0x24122b04U, 0x8a452f91U, 0x6733b14cU, 0x6bb5da2dU, 0xc0200068U, 0xe05015c4U, 0xf02814e2U, 0xd8442315U, 0xbc1a2b84U, 0x96513b51U, 0xa101832cU, 0x42a0eafdU, 0xb6bba800U, 0xf4e1d400U, 0x7b20200U, 0x9e551d00U, 0xd53b8080U, 0x40a1d4c0U, 0xe5921260U, 0x3d0520d0U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xd0000000U, 0xb8000000U, 0x1c000000U, 0x82000000U, 0xfb000000U, 0xed800000U, 0x87400000U, 0xffa00000U, 0x24300000U, 0xde480000U, 0x992c0000U, 0xc6e60000U, 0xd2dd0000U, 0x64938000U, 0x59a7c000U, 0x1462000U, 0xaaed1000U, 0xd8dbb800U, 0xeb8bf400U, 0x92200e00U, 0xe3701700U, 0xc1e81880U, 0x6d1c0ac0U, 0xa0ae1560U, 0x57f126d0U, 0x20759f68U, 0x707af7ccU, 0x8855acf2U, 0x740ad79bU, 0x263d9651U, 0x6556d9bbU, 0x94b398b6U, 0x91d7d322U, 0x952e2768U, 0x5cb103ccU, 0x5d5a2f2U, 0x634ac09bU, 0x819d8ed1U, 0x8d66d37bU, 0x70fb8dd6U, 0xeffbf5f2U, 0x3c483800U, 0xf22c3400U, 0x73662e00U, 0x999d0700U, 0xa133a080U, 0x9a97fec0U, 0xb08e1b60U, 0x4f8131d0U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0x48000000U, 0xac000000U, 0x6000000U, 0x95000000U, 0x5800000U, 0xc9400000U, 0x3be00000U, 0x8100000U, 0xcc680000U, 0xb6740000U, 0xcd5e0000U, 0xe1a70000U, 0x635c8000U, 0xa8e1c000U, 0x98be2000U, 0xb73000U, 0x44b4a800U, 0xfed5c400U, 0x25803200U, 0x19401b00U, 0xd3e02980U, 0xb4102140U, 0x82681360U, 0x8f741950U, 0xcede0f78U, 0xbde72744U, 0x5d3cb27aU, 0x69b1dfcdU, 0x6f361dafU, 0xbed30a6dU, 0x458283cdU, 0xa906c3a5U, 0x8b82a778U, 0x5006e344U, 0x2802807aU, 0x1c46c4cdU, 0x5e62b42fU, 0x7116eb2dU, 0xafeab0adU, 0x5a72eaf5U, 0xab5c8000U, 0xc4e1c000U, 0x3ebe2000U, 0x85b73000U, 0x934a800U, 0x9b95c400U, 0x18603200U, 0x84501b00U, 0x80000000U, 0x40000000U, 0x60000000U, 0xd0000000U, 0xf8000000U, 0x34000000U, 0x1a000000U, 0xff000000U, 0xf3800000U, 0x93400000U, 0x2da00000U, 0x3e700000U, 0x3d480000U, 0x88cc0000U, 0x52b20000U, 0x8d910000U, 0xce358000U, 0x750cc000U, 0x94922000U, 0x84a11000U, 0x5cdd9800U, 0xd8b0f400U, 0xeae81e00U, 0xd9bc1d00U, 0x47a1e80U, 0x721d0bc0U, 0x532782e0U, 0xdede9d0U, 0x8e6fade8U, 0x1521e05cU, 0x44dd8bb2U, 0x7cb0e2e3U, 0x68e819c4U, 0xc2bc05f8U, 0x15fa1c5fU, 0x2a5d39b0U, 0x9707b5e8U, 0x5fddd45cU, 0x6d07b5b2U, 0x30ddefe3U, 0x6879f44U, 0x479dfa38U, 0xc92780bfU, 0xb2edcd60U, 0x1def8680U, 0x5661ffc0U, 0x917d9ce0U, 0x76c0f4d0U, 0x4fa03368U, 0xb5702b9cU, 0xb4c82952U, 0x348c1b33U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x10000000U, 0x28000000U, 0xfc000000U, 0xb2000000U, 0x5b000000U, 0x3f800000U, 0x7f400000U, 0x89e00000U, 0x22700000U, 0xb3680000U, 0xa3a40000U, 0xdd360000U, 0xfaad0000U, 0xe1a38000U, 0x7e6ec000U, 0x71562000U, 0xc09d3000U, 0x36ab9800U, 0xcbfac400U, 0x81682a00U, 0x38a40f00U, 0x82b63480U, 0x95ed12c0U, 0x404385e0U, 0xa01ee0d0U, 0x703e2ef8U, 0x38392e5cU, 0xd41dbb3aU, 0x4e17f339U, 0xe92bbf35U, 0x64baf937U, 0x40880032U, 0xf6d415b2U, 0xabde36f8U, 0x91492a5cU, 0x10f5b13aU, 0x7ef3cc39U, 0x27fd93b5U, 0x1b67eff7U, 0x9fc38fd2U, 0xf5eca62U, 0xb1de3480U, 0xf64912c0U, 0xfd7585e0U, 0x4ab3e0d0U, 0xb99daef8U, 0xba57ee5cU, 0x174b9b3aU, 0xd58ac339U, 0x80000000U, 0x40000000U, 0x60000000U, 0x30000000U, 0x8000000U, 0x4c000000U, 0xf6000000U, 0x7f000000U, 0x76800000U, 0x19400000U, 0x11a00000U, 0x7bf00000U, 0x8af80000U, 0xa7540000U, 0x42ae0000U, 0xcb170000U, 0xe4a58000U, 0x8c124000U, 0xd6562000U, 0x2f431000U, 0x4e8b9800U, 0x5d454c00U, 0xabd3a200U, 0xf2e14300U, 0x83058580U, 0xc8e243c0U, 0x4a2e27a0U, 0xa1570950U, 0x1585a3e8U, 0xa1a25e3cU, 0x338e209eU, 0xa6a73345U, 0x617dace3U, 0x35f679a9U, 0xf1a0205fU, 0xbf0117dU, 0xe2f82668U, 0xdb541dfcU, 0xbcae073eU, 0xf8173a15U, 0x64258f0bU, 0xea526795U, 0xb17620c1U, 0x4df33238U, 0xd5d3928bU, 0x81e16855U, 0x6385a561U, 0x9ea27868U, 0x250e34e3U, 0x8fe735a9U, 0x78dd825fU, 0x206527dU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x70000000U, 0xb8000000U, 0x7c000000U, 0x4a000000U, 0xf3000000U, 0x90800000U, 0x81400000U, 0x5fa00000U, 0xfb900000U, 0x5dd80000U, 0x8cec0000U, 0x5b360000U, 0xc4b10000U, 0xdf338000U, 0x52974000U, 0x166e2000U, 0x891d1000U, 0x7ba5a800U, 0x1db65c00U, 0x2c858e00U, 0x2b664f00U, 0x7cfd9a80U, 0xa31a70c0U, 0x18938220U, 0xe5077350U, 0x19b62368U, 0xfaf11124U, 0x4213a7d6U, 0xd7477cabU, 0x76963985U, 0xf0211c58U, 0xf86ba9f2U, 0xdc3b49eaU, 0x3a7839e8U, 0x4b7c21e4U, 0xecee05f6U, 0xcb5d1ffbU, 0xac85b2edU, 0x6b66517cU, 0xdcfd8024U, 0xd31a7a41U, 0xa0939aedU, 0x99074d7cU, 0x53b62e24U, 0x9f12541U, 0xd293a86dU, 0x560761bcU, 0x29362204U, 0xbb11911U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xb0000000U, 0x88000000U, 0xd4000000U, 0xea000000U, 0xb7000000U, 0xf5800000U, 0xa5400000U, 0xfea00000U, 0x7e900000U, 0x3eb80000U, 0x9ef40000U, 0x2e820000U, 0xa6d90000U, 0x729d8000U, 0x98c9c000U, 0x2fba2000U, 0xda6d1000U, 0x7f3fa800U, 0x81c0ec00U, 0xff3f8200U, 0xc1c0e500U, 0x5f3fb280U, 0x71c0d1c0U, 0xd73f9760U, 0xa5c0e050U, 0x3d3faf28U, 0x12c0fb64U, 0xc8bfa24eU, 0xb780ea2dU, 0x361f99e8U, 0xc910fb82U, 0x8a78141U, 0x57e4d3bbU, 0x26259da8U, 0xf13deaa4U, 0x54b8152eU, 0x69f41a7dU, 0x7b021ec0U, 0xb3992ce6U, 0x43d810fU, 0x3259cc96U, 0xfb021ec0U, 0xf3992ce6U, 0xa43d810fU, 0x8259cc96U, 0x73021ec0U, 0x27992ce6U, 0x4e3d810fU, 0x3559cc96U, 0x80000000U, 0x40000000U, 0x20000000U, 0x50000000U, 0x8000000U, 0x34000000U, 0x1a000000U, 0xd1000000U, 0xac800000U, 0x57400000U, 0x43a00000U, 0x18d00000U, 0xd480000U, 0xb2b40000U, 0xe4620000U, 0x52010000U, 0xc5668000U, 0xe6e94000U, 0x8e0a2000U, 0xdb251000U, 0x55ec8800U, 0x9f8c5400U, 0x6c6a200U, 0xbe395d00U, 0xa3422e80U, 0x39913040U, 0xb98ea120U, 0xf98d4cd0U, 0xd9a03468U, 0x89d02f74U, 0x81c826f2U, 0xb5f4193dU, 0xafc200d0U, 0x7ed10a64U, 0xd22ea463U, 0x855d6763U, 0xc6e812e8U, 0xde640b34U, 0xd32a05d2U, 0x61b518edU, 0x85849238U, 0xd7a84150U, 0x12cc81b1U, 0xf41c6f8eU, 0x7a2e88d0U, 0xa15d5e64U, 0xf4e80663U, 0x6b643a63U, 0x6daa3c68U, 0xd3f53b74U, 0x70a4a4f2U, 0x4938543dU, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0x8000000U, 0xe4000000U, 0xe6000000U, 0x7000000U, 0x10800000U, 0x7d400000U, 0x5da00000U, 0x8f00000U, 0x21180000U, 0x37940000U, 0xfdfa0000U, 0xd8ef0000U, 0xb9258000U, 0x2be14000U, 0xf7c22000U, 0xddcb1000U, 0x48e79800U, 0x412a7c00U, 0xc7a5a200U, 0xf5a16900U, 0x3ce20180U, 0x5f7b2dc0U, 0x2cdf9e20U, 0xe70e5a50U, 0xa0e78ce8U, 0x152a6afcU, 0x49a58de6U, 0xe6a17f75U, 0xc2621636U, 0xc13b3e57U, 0x87ff92e7U, 0x95be41e1U, 0xccdf9568U, 0x570e7b3cU, 0xc8e791c6U, 0x12a5c25U, 0xa7a5835eU, 0x5a1456bU, 0x34e20321U, 0xbb7b1dc4U, 0xcadf9636U, 0xe00e7e57U, 0xb067b2e7U, 0x686a51e1U, 0x14058d68U, 0xee51473cU, 0xe37a13c6U, 0xf6af2525U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0x38000000U, 0xac000000U, 0xa2000000U, 0xcf000000U, 0x57800000U, 0x2fc00000U, 0x63a00000U, 0x51b00000U, 0x16e80000U, 0xd5740000U, 0xf4e20000U, 0xfa130000U, 0x33448000U, 0x5dc74000U, 0xc4c4a000U, 0x2077000U, 0xbf64a800U, 0x4fb75c00U, 0x338ca600U, 0xf9c37700U, 0x32ee8e80U, 0xe31044c0U, 0x358a1b60U, 0xc0a70f30U, 0x8406a388U, 0x46646b5cU, 0xd9680e32U, 0x26b40201U, 0x2d42150aU, 0x78a30b85U, 0xe82cb75bU, 0xc4736834U, 0xa606950aU, 0x49644b85U, 0xaee8175bU, 0xb9741834U, 0x76e23d0aU, 0x85131785U, 0x5cc4b15bU, 0xde076f34U, 0x564b38aU, 0x9cb75345U, 0xfe0caa3bU, 0xb5036004U, 0xa4ce9002U, 0x52607819U, 0x17420409U, 0x6ba31205U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0x78000000U, 0x6c000000U, 0x7e000000U, 0xff000000U, 0x18800000U, 0xc0c00000U, 0x7ca00000U, 0x5ab00000U, 0xd9b80000U, 0xc7040000U, 0x94f20000U, 0x8eed0000U, 0xebe28000U, 0x5676c000U, 0xb62a000U, 0x3ab6f000U, 0x29c2a800U, 0x8f06f400U, 0x90fab600U, 0xe4c2ef00U, 0x6a8a980U, 0xcf9fd0c0U, 0x2c722fa0U, 0x9e2d20f0U, 0xcf429088U, 0x70c6c65cU, 0xd4da8ee6U, 0x6eb2c39dU, 0xdbb0bddaU, 0x3e2bff26U, 0x1f3806a2U, 0x28c40e7bU, 0xa8d23ddaU, 0x689d3f26U, 0x48faa6a2U, 0x58c2fe7bU, 0x20a895daU, 0x4c9fcb26U, 0x32f210a2U, 0xcded117bU, 0xd562bc5aU, 0x15b6dbe6U, 0x69429f02U, 0x33c6c18bU, 0xea5a84d2U, 0x2d72e9baU, 0xb990a7e4U, 0x375bed16U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x30000000U, 0xd8000000U, 0xf4000000U, 0xd2000000U, 0xab000000U, 0x98800000U, 0x90c00000U, 0xeca00000U, 0x82f00000U, 0xe7e80000U, 0x2a040000U, 0xaf3e0000U, 0x32b70000U, 0xfff28000U, 0x7e46c000U, 0x4d72a000U, 0x4186f000U, 0x93528800U, 0x3cb6fc00U, 0xa9abe00U, 0x5b82c100U, 0xe46c8a80U, 0xfa01ebc0U, 0x27682ca0U, 0x8ec40ff0U, 0x319e3788U, 0x2b471f4cU, 0x589aa672U, 0x3082d9cdU, 0xdcec9bbdU, 0x5ac1d860U, 0x13c838c1U, 0xf8342131U, 0x4761bbdU, 0xaa431860U, 0x6f2498c1U, 0x92f5d131U, 0xcfbe13bdU, 0xa6772460U, 0xb95286c1U, 0x93b6e031U, 0x381a913dU, 0xa442f3a0U, 0x9a4cb461U, 0xb731dec1U, 0x66a02435U, 0x1df03b2cU, 0xd6820b3U, 0x21c439fcU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x30000000U, 0x8000000U, 0xc000000U, 0x72000000U, 0xf9000000U, 0x4a800000U, 0x86c00000U, 0x14e00000U, 0x7db00000U, 0xf280000U, 0x8dec0000U, 0xe70a0000U, 0x11830000U, 0xad578000U, 0xecdec000U, 0x99b7a000U, 0xe16ed000U, 0x3e9f8800U, 0x5082dc00U, 0xa3958a00U, 0xb401df00U, 0x36421680U, 0x271f2140U, 0xf195a420U, 0x3d01d0f0U, 0xd4c22918U, 0x9ddf139cU, 0x9f75a0d2U, 0xb5b1efe7U, 0xe36a0f90U, 0x6ff30ac7U, 0x261fa0e5U, 0x5f42f100U, 0x55f58790U, 0x7371d6c7U, 0x578a2ae5U, 0x22432e00U, 0x21379110U, 0xdeaef787U, 0xc0ff8ec5U, 0x9bf2fef0U, 0xb05db808U, 0x485de41bU, 0xac602e17U, 0x42701117U, 0xf1483798U, 0x469c2edcU, 0xf4c22ef2U, 0xeddf3017U, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0x28000000U, 0xe4000000U, 0x1e000000U, 0xd000000U, 0x4f800000U, 0x3c00000U, 0xb9e00000U, 0xcad00000U, 0xd8780000U, 0xbc2c0000U, 0xe27e0000U, 0x8f410000U, 0x90ef8000U, 0xbb1c4000U, 0xe68fa000U, 0x320c5000U, 0xe717b800U, 0x14f04400U, 0xf511b200U, 0xc39d7d00U, 0x99803580U, 0xfac03e40U, 0xa0600660U, 0x70102eb0U, 0x18183018U, 0x9c3c0804U, 0xd2660c06U, 0xf77d1e0fU, 0x5c89b319U, 0x41617e9fU, 0xf58624c2U, 0x70ad00a8U, 0xab718b19U, 0xae8d7a9fU, 0x861836c2U, 0xd13c2da8U, 0xfde60699U, 0xa4bd00dfU, 0xcd6982a2U, 0x6fb17e18U, 0x33fe0301U, 0xc181369bU, 0x68f88c4U, 0x220c4ea7U, 0xaf178000U, 0xa0f04000U, 0xc311a000U, 0x2a9d5000U, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0x38000000U, 0x2c000000U, 0xd2000000U, 0x8d000000U, 0x70800000U, 0x14c00000U, 0xb2e00000U, 0x51f00000U, 0xf6280000U, 0xb740000U, 0x23c20000U, 0x8b7b0000U, 0x63858000U, 0xab51c000U, 0xd3e5a000U, 0x9361d000U, 0xffada800U, 0x4125fc00U, 0x72a7a600U, 0x31daf700U, 0x66481280U, 0x83441440U, 0x378a2ea0U, 0x753f0170U, 0x3c8f8a18U, 0x56aef90cU, 0xb78a1992U, 0x353f20d1U, 0x1c8f8de2U, 0xe6aedd4fU, 0x8f8a2f23U, 0x193f05abU, 0xce8fa5e2U, 0x6baee14fU, 0xff0a2923U, 0xdff22abU, 0x7c6f9f62U, 0x3a5ec90fU, 0x9220183U, 0x68b04dbU, 0x5fadaffaU, 0xb125d843U, 0x6aa790b1U, 0xaddad27aU, 0x8c483a80U, 0x22442840U, 0x950a28a0U, 0xecff2670U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0xd8000000U, 0xec000000U, 0xf2000000U, 0x65000000U, 0x87800000U, 0x5c00000U, 0x48a00000U, 0xcb100000U, 0x58f80000U, 0xb3340000U, 0x84d20000U, 0xc9130000U, 0xd5f58000U, 0x50944000U, 0x470da000U, 0xfaa07000U, 0xe5fb800U, 0xef736400U, 0x3e8a0e00U, 0xf8371f00U, 0x1c5f9280U, 0x1a737640U, 0x10a0b60U, 0x41f71330U, 0x7eff9748U, 0x58637ef4U, 0x2c7233f6U, 0x92031479U, 0x350d81a2U, 0x5fa0610dU, 0xe9dfb597U, 0xbab340dcU, 0xae2a1322U, 0xdf27174dU, 0xb6a7bef7U, 0xcc4753ecU, 0x258046aU, 0x8d2429b9U, 0xe3aa2d01U, 0xc3e73795U, 0x3387bdc8U, 0xdb976cb4U, 0xbf803696U, 0x79c01849U, 0x2a0046aU, 0x121029b9U, 0xf5782d01U, 0x3ff43795U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x90000000U, 0x58000000U, 0xc4000000U, 0x66000000U, 0x3b000000U, 0x39800000U, 0xd7c00000U, 0x10a00000U, 0xbb700000U, 0xf9f80000U, 0x77f40000U, 0x80a60000U, 0xe30d0000U, 0x3db48000U, 0x11c64000U, 0xbbcca000U, 0xdaf27000U, 0xea4a8800U, 0x14f5400U, 0xa61e00U, 0x230d2500U, 0x9db4a780U, 0x81c65bc0U, 0xe3cca1e0U, 0x1ef27a30U, 0x8c4a9bc8U, 0x3a4f41ecU, 0x39262a36U, 0xf4cd23d1U, 0x8d14bdffU, 0x3ab65022U, 0x1a34b0daU, 0x69065b7fU, 0xcec9a7fU, 0xd9424be2U, 0x492b13aU, 0xe50b514fU, 0x36d809b7U, 0xe0441e0eU, 0xf07e250cU, 0x6849279eU, 0xc4a9bc8U, 0xfa4f41ecU, 0x99262a36U, 0x64cd23d1U, 0xd514bdffU, 0xfeb65022U, 0x7c34b0daU, 0x52065b7fU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x10000000U, 0xb8000000U, 0xb4000000U, 0xfa000000U, 0x47000000U, 0xd1800000U, 0x1fc00000U, 0xe2e00000U, 0x94100000U, 0x4a580000U, 0xf240000U, 0xcd8e0000U, 0xe9bb0000U, 0xebe48000U, 0xf8a64000U, 0xc35ca000U, 0x23925000U, 0xa48a9800U, 0xd50d5400U, 0x3ae03600U, 0x70103900U, 0xe8582880U, 0xec2438c0U, 0x5e0e24e0U, 0x57b3b30U, 0x2284b258U, 0x34767334U, 0xba64be4eU, 0xa766713dU, 0xc1bc814dU, 0xa78248a3U, 0x56d2ad0cU, 0x6e297e8eU, 0xd6e31cdU, 0xdeab2463U, 0xd23cbfecU, 0xb427cbeU, 0x7fb2ab15U, 0xb2f96f97U, 0xcc562542U, 0xee5f36b3U, 0x4d0a9800U, 0x3ecd5400U, 0xc2003600U, 0xb3003900U, 0xcb802880U, 0x48c038c0U, 0x8b6024e0U, 0x3fd03b30U, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0xb8000000U, 0x14000000U, 0xd2000000U, 0x6d000000U, 0x25800000U, 0x73c00000U, 0x54e00000U, 0x38500000U, 0x54380000U, 0xb2440000U, 0x3d7e0000U, 0x9dbf0000U, 0x67958000U, 0x86ad4000U, 0x554da000U, 0x71b95000U, 0xc18bb800U, 0x69824400U, 0xa5801600U, 0x33c00100U, 0x34e00280U, 0x68500a40U, 0xec3813e0U, 0xa64402b0U, 0xef7e28d8U, 0xf0bf09a4U, 0x42158956U, 0xf56d7e75U, 0x1adaf69U, 0x49e955eaU, 0x95b3bbb4U, 0xdbc66e55U, 0x98fe15e9U, 0xae7f1baaU, 0x5375be54U, 0xeefd6de5U, 0xb975bfb1U, 0xd7fd584eU, 0x2ef584e2U, 0x993d4120U, 0xe7958000U, 0xc6ad4000U, 0x354da000U, 0x21b95000U, 0x798bb800U, 0x7d824400U, 0x77801600U, 0x5ec00100U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xf0000000U, 0x38000000U, 0x2c000000U, 0x86000000U, 0x79000000U, 0xe2800000U, 0xd8c00000U, 0xafe00000U, 0xc0100000U, 0xa0280000U, 0x10140000U, 0xc8720000U, 0x14490000U, 0xaa698000U, 0xff0ec000U, 0x9ba1a000U, 0x3a0ad000U, 0x777b9800U, 0x6f97ec00U, 0x60001600U, 0xb0002700U, 0xd8001780U, 0xdc002940U, 0xbe001720U, 0x55002370U, 0x648032d8U, 0xa1c01874U, 0x4d603b52U, 0x18d00231U, 0xfc831eeU, 0xd0043113U, 0x685a308cU, 0x45d3ed4U, 0x621bbe6eU, 0xeb47f453U, 0x31c831acU, 0xc5043aa4U, 0xecda1b36U, 0x559d0567U, 0x177bbddeU, 0xdf97cbe5U, 0xb8000000U, 0x6c000000U, 0x66000000U, 0x89000000U, 0xda800000U, 0xf4c00000U, 0x29e00000U, 0xb9100000U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0x48000000U, 0x34000000U, 0x3e000000U, 0x1b000000U, 0xe0800000U, 0xe2c00000U, 0xd3a00000U, 0xc6500000U, 0xa7080000U, 0xacc0000U, 0xf7e60000U, 0x60010000U, 0xf0188000U, 0xa80ac000U, 0x430a000U, 0x7656f000U, 0x2f7e9800U, 0xdecbfc00U, 0xf9880a00U, 0x330c3100U, 0x24c62580U, 0x749107c0U, 0xccb0a5a0U, 0x5096f370U, 0x6adea348U, 0x79bffe4U, 0xc8003d0aU, 0xf4003797U, 0xde000ad3U, 0x2b002a27U, 0xa88035bdU, 0xd6c03b71U, 0xeda03753U, 0xdd5011e7U, 0x47883a1dU, 0xe80c0901U, 0x2446299bU, 0xa65115c3U, 0x5710a8b7U, 0xa2c6fce6U, 0xf3d6a580U, 0x1657c7c0U, 0xdf6605a0U, 0x76c10370U, 0xfdb8bb48U, 0x455ac3e4U, 0xbb8970aU, 0xaa5af697U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xf0000000U, 0x98000000U, 0x9c000000U, 0x4e000000U, 0x59000000U, 0x7800000U, 0xddc00000U, 0xdea00000U, 0x1a300000U, 0x23080000U, 0x34a40000U, 0xa13a0000U, 0x8bc50000U, 0xdb958000U, 0x73d04000U, 0x57bda000U, 0x75847000U, 0xfaafa800U, 0x38154c00U, 0xac280e00U, 0xf6542b00U, 0x35123d80U, 0xd1910d40U, 0x1887b460U, 0x97414630U, 0x9eba05c8U, 0xfa0517bcU, 0xf335b68aU, 0x5ce040d5U, 0xa5359124U, 0x59e07e54U, 0xccb5ade9U, 0x2d20696cU, 0x8d9584a4U, 0x76d07f14U, 0x3e3db789U, 0x144745cU, 0xbb8f94ecU, 0x63e569e8U, 0x1f801b63U, 0x81c029b9U, 0xb0a01580U, 0xb3300140U, 0xbc881a60U, 0x75641d30U, 0x319a1048U, 0xc8f516fcU, 0xff1daceaU, 0x9ab45de5U, 0x80000000U, 0x40000000U, 0x20000000U, 0x10000000U, 0x8000000U, 0x84000000U, 0x92000000U, 0x91000000U, 0xbd800000U, 0x8cc00000U, 0x61600000U, 0xc5b00000U, 0x30d80000U, 0x6f6c0000U, 0x4af60000U, 0xa530000U, 0x5d2d8000U, 0x8bc04000U, 0x9fdba000U, 0x45935000U, 0x70f62800U, 0x4f531400U, 0x5aad8a00U, 0x2006500U, 0xd93b8680U, 0x19e35540U, 0xece23e0U, 0xf84f1370U, 0xfc63bd38U, 0x2e4f775cU, 0x9f5812eeU, 0x32ac3ff7U, 0xb6161d6bU, 0x53231a3fU, 0x495b0ceU, 0xa51c5338U, 0x77f5a053U, 0xb1ac6d63U, 0xdaada220U, 0x42006ccfU, 0xf93bbd38U, 0x9e3775cU, 0x6ce12eeU, 0x7c4f3ff7U, 0x6e639d6bU, 0xbf4f5a3fU, 0x22d810ceU, 0xbe6c0338U, 0xd7760853U, 0x96933963U, 0x344d8820U, 0xca7059cfU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xf0000000U, 0x78000000U, 0xac000000U, 0x3a000000U, 0xd000000U, 0xf1800000U, 0x6cc00000U, 0xf5200000U, 0x9df00000U, 0x76a80000U, 0x8640000U, 0x141a0000U, 0xb6230000U, 0xc75f8000U, 0x84944000U, 0x3145a000U, 0xa3b77000U, 0x659a2800U, 0x1ae30c00U, 0x127f9600U, 0xe9645700U, 0x3fedb080U, 0x7d35840U, 0x4b801ae0U, 0xa1c01470U, 0x24a01728U, 0x1302b4cU, 0xfb883062U, 0x39940d25U, 0x58b22a4cU, 0xb34737e1U, 0x22c5b5f9U, 0x5e7770e1U, 0x33a3d64U, 0xbad31cadU, 0x2277859bU, 0xb1307dc4U, 0x63ff9728U, 0x45a46b4cU, 0xeacd9062U, 0x6a237d25U, 0x4528024cU, 0x5a43be1U, 0xaba23f9U, 0xba1327e1U, 0xcd578de4U, 0xd1c044edU, 0x9cd79f7bU, 0x8d0069b4U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x30000000U, 0x98000000U, 0x6c000000U, 0xaa000000U, 0x83000000U, 0xd7800000U, 0xc0c00000U, 0xa1600000U, 0x30d00000U, 0x99280000U, 0x8cf40000U, 0x9b4a0000U, 0xfbdb0000U, 0x8ae88000U, 0x12644000U, 0x7f42a000U, 0x35af5000U, 0x87e21800U, 0x28ef1c00U, 0xb5429e00U, 0xc6af5700U, 0x28622c80U, 0xb42f2bc0U, 0x2622a760U, 0x197f5cf0U, 0xccca1bb8U, 0x7b1b3704U, 0xcb889c92U, 0x12b443c9U, 0x7e6ab378U, 0xd55b66fbU, 0xb6a81eb0U, 0x50340a9bU, 0xe82a30c0U, 0x140b0dffU, 0xf640bc22U, 0xb1504e52U, 0x38e8b738U, 0xbd645cc4U, 0xe2c29bf2U, 0x466f4f39U, 0x690230c0U, 0xb4ff0dffU, 0x270abc22U, 0xf98b4e52U, 0xfd803738U, 0x3c01cc4U, 0x96e03bf2U, 0xc0101f39U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x30000000U, 0x28000000U, 0x8c000000U, 0x2e000000U, 0xc3000000U, 0xae800000U, 0x79c00000U, 0x9d200000U, 0xe5d00000U, 0xb680000U, 0xd2ec0000U, 0x1fa20000U, 0xe2690000U, 0x4d328000U, 0x3dd8c000U, 0xcf30a000U, 0x40a1f000U, 0xdaca3800U, 0x3853c00U, 0xb4109200U, 0x1a71ef00U, 0x19222180U, 0xd7a923c0U, 0x9e12b820U, 0x2b08e2b0U, 0x42d8a6e8U, 0x678df404U, 0x76481612U, 0xc73c010fU, 0x5cca3c92U, 0x8c853d51U, 0x5490b26cU, 0x90b1dd58U, 0x282227aU, 0xc7b93555U, 0x265a967eU, 0xdf34c357U, 0xf8928768U, 0x2ec8d7c4U, 0xb9f8ae32U, 0xfd5de3bfU, 0xd5a01a7aU, 0x23100955U, 0x5ec8047eU, 0x31fc2c57U, 0x216a26e8U, 0xe3953404U, 0x4458b612U, 0x524df10fU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x70000000U, 0x48000000U, 0x6c000000U, 0x4e000000U, 0x3b000000U, 0x94800000U, 0xc1c00000U, 0xbe200000U, 0xb3500000U, 0x98880000U, 0xffdc0000U, 0xcd320000U, 0x4bc10000U, 0x17728000U, 0x7aabc000U, 0xeac8a000U, 0x12b6f000U, 0x56883800U, 0x4dc2c00U, 0x39b20a00U, 0xfa010700U, 0xe1528180U, 0xa5fbd5c0U, 0x3c4096a0U, 0xd66aceb0U, 0xf3a32a8U, 0x8edd30a4U, 0x90e083aaU, 0x33fad423U, 0x931234eeU, 0x489108c7U, 0xa7fa9830U, 0x9977eeeaU, 0x21fa87c6U, 0xe77eda3U, 0x9b7a8d3aU, 0x84b7f479U, 0xf9da8180U, 0x9a27d5c0U, 0x917296a0U, 0xedabceb0U, 0x5048b2a8U, 0x9876f0a4U, 0x342823aaU, 0x1a4c2423U, 0x511a0ceeU, 0x8d8d24c7U, 0x20689230U, 0xd026e9eaU, 0x80000000U, 0x40000000U, 0x60000000U, 0x90000000U, 0x58000000U, 0x44000000U, 0x1a000000U, 0xf1000000U, 0x4e800000U, 0xf5c00000U, 0x32600000U, 0x3d100000U, 0x28f80000U, 0xcaa40000U, 0xcfee0000U, 0x337f0000U, 0xbbad8000U, 0xc14bc000U, 0xa6bba000U, 0x1990d000U, 0xa4783800U, 0xca643400U, 0xc90e0e00U, 0x9aaf3500U, 0xb7b59080U, 0x873fed40U, 0x69cdb520U, 0x2c5bd130U, 0xb643a738U, 0x734c634U, 0x299628a6U, 0x4c1b18edU, 0x2623b145U, 0x5f24f736U, 0x6dee3e30U, 0x567f3cbdU, 0xd72d86fdU, 0x118bdc42U, 0x985ba3b6U, 0x6440f560U, 0xea601080U, 0x39102d40U, 0x52f81520U, 0xaba40130U, 0xd96e1f38U, 0x82bf3234U, 0x93cd86a6U, 0xd5bfdedU, 0xc0c399c5U, 0x26f4ee76U, 0x59f62510U, 0xc40b088dU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xf0000000U, 0xc8000000U, 0xe4000000U, 0x42000000U, 0xbd000000U, 0x6a800000U, 0x5c00000U, 0x2a200000U, 0x89100000U, 0xf0880000U, 0x64dc0000U, 0x2eb60000U, 0x97830000U, 0x4f578000U, 0x3fe7c000U, 0x9b69a000U, 0x55b8f000U, 0x32081800U, 0xb51c0c00U, 0x6e960a00U, 0xb7930500U, 0x5f5fa280U, 0x7fbd640U, 0xb77faa20U, 0xf3ebde30U, 0xcd778828U, 0x62f7ef34U, 0x1e19caaU, 0x9864ce73U, 0xfc3e0d0fU, 0x7e5f2697U, 0x23619858U, 0xb9a4c129U, 0x741e27a7U, 0xba4f1fe3U, 0x7169aed2U, 0x3cb8d16aU, 0x32882280U, 0x19dc1640U, 0xa4360a20U, 0x62432e30U, 0xad779028U, 0x52f7e334U, 0x29e196aaU, 0x8c64cb73U, 0x763e2f8fU, 0x275f30d7U, 0xbe19278U, 0x164ef19U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x10000000U, 0x48000000U, 0xdc000000U, 0x92000000U, 0x53000000U, 0x6c800000U, 0x85c00000U, 0x36600000U, 0xe5500000U, 0xc9f80000U, 0xac6c0000U, 0x8a6a0000U, 0x27570000U, 0x32e88000U, 0xcfbc000U, 0xd5faa000U, 0x9e00d000U, 0x29181800U, 0x13fc1400U, 0x23722a00U, 0x74ab3300U, 0xf19ab680U, 0x6850e3c0U, 0x6c601fa0U, 0x2a5025b0U, 0xd7782eb8U, 0x6aac1c24U, 0x988a2de6U, 0x9bc7254fU, 0x5f70b464U, 0x16c7f60eU, 0xfae89500U, 0x90fbfb9bU, 0xa7faac5cU, 0xdd00c9eaU, 0xd980746U, 0x4a3c2b64U, 0x87122e80U, 0xc2fb37c0U, 0x54e295a0U, 0x41fcc6b0U, 0xd06a0038U, 0xe8572be4U, 0x2c68b846U, 0xca3be3ffU, 0xc71ab45cU, 0x2290ddeaU, 0x44802d46U, 0x9c01864U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0x98000000U, 0x6c000000U, 0x2e000000U, 0x71000000U, 0x7c800000U, 0xebc00000U, 0xd2200000U, 0x67500000U, 0xd1d80000U, 0xf1640000U, 0xbc9a0000U, 0x8bd10000U, 0x2678000U, 0xff1ac000U, 0xbda5a000U, 0xdf6ff000U, 0xcdf83800U, 0xf7340400U, 0xe9c23e00U, 0x2d752f00U, 0xdaddad80U, 0xe9bc740U, 0x3c9a34a0U, 0x4bd116b0U, 0x6267b3a8U, 0x2f1ad724U, 0x25a586feU, 0xb36fce8dU, 0xe3f828d0U, 0x863406edU, 0x95420e9fU, 0xc6b508c2U, 0x8fdb6f8U, 0x69cbd689U, 0xed421cc1U, 0xbab520ffU, 0xdefd9580U, 0xa4cbc340U, 0x27c20aa0U, 0x4c7539b0U, 0x5e5d9e28U, 0x595bd064U, 0x58ba125eU, 0x3181283dU, 0xe13fa378U, 0x44bed5c9U, 0x379fb661U, 0xb42ee94fU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x30000000U, 0xb8000000U, 0xac000000U, 0x6000000U, 0xfd000000U, 0xef800000U, 0xf8c00000U, 0x8c200000U, 0xf6300000U, 0xe5480000U, 0x73c40000U, 0x46ca0000U, 0xdd750000U, 0x1fcd8000U, 0xe0814000U, 0x106fa000U, 0x48007000U, 0xb4200800U, 0x9a303c00U, 0x43480600U, 0xbec42700U, 0x114a2f80U, 0x89b51440U, 0x95edba60U, 0xebb14170U, 0x1aa7b8e8U, 0xc30473bcU, 0x7eca125aU, 0xb1751d7dU, 0xb9cdaee0U, 0x2d814cacU, 0x47ef99c1U, 0x1cc06b3dU, 0x3e003188U, 0x91001750U, 0x498037fbU, 0x35c01030U, 0xdba00800U, 0xa2f03c00U, 0x6f680600U, 0x78f42700U, 0x4c022f80U, 0x56711440U, 0xd527ba60U, 0xcbc44170U, 0xeaea38e8U, 0xdb4533bcU, 0xe285b25aU, 0xf456d7dU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0x58000000U, 0x14000000U, 0x5a000000U, 0x75000000U, 0x6c800000U, 0x87c00000U, 0xdc600000U, 0xf6700000U, 0xcb780000U, 0x4b840000U, 0xd2660000U, 0x79070000U, 0x82c78000U, 0xf8e4c000U, 0x9db9a000U, 0x917d000U, 0xcae00800U, 0x14b00400U, 0x83983e00U, 0x7e341100U, 0xc77e0080U, 0xa5f31840U, 0xad598da0U, 0x38a7fcb0U, 0x7df80c38U, 0xf9440c6cU, 0xc2862dc6U, 0x58b73b7dU, 0xcddf9047U, 0x5110c9a0U, 0xdea7a2a8U, 0x4e94ed38U, 0xf6c194ffU, 0x1293d98cU, 0x40863cceU, 0x79b73bf5U, 0x5b5f8800U, 0xf3d0c400U, 0x36479e00U, 0x2b24c100U, 0xbbd98880U, 0xda67dc40U, 0x351813a0U, 0xccf43db0U, 0xd79e04b8U, 0x8443102cU, 0xe2419e66U, 0x9153d6cdU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x70000000U, 0xe8000000U, 0x94000000U, 0x42000000U, 0x7b000000U, 0x49800000U, 0x3cc00000U, 0x90200000U, 0x58500000U, 0x1c080000U, 0xa64c0000U, 0xd13e0000U, 0xa6eb0000U, 0x375c8000U, 0xd7f94000U, 0x81caa000U, 0x78ce7000U, 0x2a003800U, 0x2f002c00U, 0x6b802200U, 0x37c03900U, 0x31a02a80U, 0xf0903bc0U, 0xce2802e0U, 0x851c11f0U, 0x84b63668U, 0x3c671924U, 0x7642a30aU, 0x29427f87U, 0xaa9e134dU, 0x97b3029U, 0x7af4a198U, 0xf1254044U, 0x76dcb7a5U, 0xcf397ecdU, 0xdbea8272U, 0xbf9e6733U, 0xd5880000U, 0x5a8c0000U, 0x211e0000U, 0x8ebb0000U, 0xc3548000U, 0xe5b54000U, 0x12f4a000U, 0xa5257000U, 0x54dcb800U, 0xc4396c00U, 0x7a6a8200U, 0x175e4900U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xf0000000U, 0x28000000U, 0x14000000U, 0x4a000000U, 0xe3000000U, 0x6f800000U, 0x72c00000U, 0x70200000U, 0xe8300000U, 0x34080000U, 0xba3c0000U, 0xcb0a0000U, 0x7b850000U, 0x38d28000U, 0x9318c000U, 0x87abe000U, 0x46d4b000U, 0xca000800U, 0x23000c00U, 0x4f800200U, 0x82c00f00U, 0x58200280U, 0xfc300140U, 0x7e0804a0U, 0x593c0e30U, 0xa48a06f8U, 0x945072cU, 0x48f28702U, 0x7b28ce83U, 0xb3a3e340U, 0xfce8bba3U, 0x10a04b0U, 0x58850bb8U, 0x7752818dU, 0x11d8c631U, 0xdf8beafaU, 0xbae4b52dU, 0xb4080000U, 0x7a3c0000U, 0xeb0a0000U, 0x8b850000U, 0x10d28000U, 0x8718c000U, 0xcdabe000U, 0xa5d4b000U, 0xa5800800U, 0x51c00c00U, 0x3fa00200U, 0x6af00f00U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x50000000U, 0x28000000U, 0x9c000000U, 0x7e000000U, 0xff000000U, 0x43800000U, 0x79c00000U, 0xb8200000U, 0x14100000U, 0x52380000U, 0xf9140000U, 0x88a0000U, 0xd8670000U, 0x40ff8000U, 0x108fc000U, 0x7c78e000U, 0x6ad27000U, 0x5d800800U, 0x96c00400U, 0x33a00e00U, 0xa1d00500U, 0xbc180280U, 0x8e0409c0U, 0x673207e0U, 0xa7b30ff0U, 0xb3d58438U, 0xa538c79cU, 0xd69f6b82U, 0x9759b141U, 0x7b4aed23U, 0xdd617b91U, 0x26558688U, 0xfff8cc86U, 0xb33f688fU, 0x5589bdc8U, 0xfad2eaa7U, 0xd5a5749dU, 0xbac78000U, 0x359bc000U, 0xeaf2e000U, 0x1db57000U, 0x76ff8800U, 0x638fc400U, 0x89f8ee00U, 0x20127500U, 0xf0200a80U, 0x98100dc0U, 0xe43809e0U, 0xca140af0U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x70000000U, 0x48000000U, 0x1c000000U, 0xae000000U, 0xf9000000U, 0x6c800000U, 0x95c00000U, 0x7c200000U, 0x3e300000U, 0xe1080000U, 0x489c0000U, 0x6fd20000U, 0x37270000U, 0x59b8000U, 0xe1764000U, 0xcde72000U, 0xb8277000U, 0x94200800U, 0x92300c00U, 0x27080200U, 0xdd9c0700U, 0xe5520480U, 0x47e701c0U, 0xbb3b8ae0U, 0xb3864f90U, 0x3c4f26c8U, 0x5b4b795cU, 0x66da0fc2U, 0xd3bb0fe3U, 0xac498c10U, 0x43514389U, 0x42fca27dU, 0x299132b2U, 0xe76722b9U, 0x78e77d87U, 0x42800016U, 0xacc009deU, 0x30a00800U, 0xdbf00c00U, 0xd5280200U, 0x6aac0700U, 0x20da0480U, 0x86bb01c0U, 0x6c98ae0U, 0x43914f90U, 0xb45ca6c8U, 0x6761395cU, 0xb8cf2fc2U, 0x628b7fe3U, 0x80000000U, 0x40000000U, 0x60000000U, 0xd0000000U, 0x48000000U, 0xbc000000U, 0xe000000U, 0xe1000000U, 0xb5800000U, 0x3dc00000U, 0x8c200000U, 0xd6100000U, 0x75180000U, 0xd7b40000U, 0x9ad20000U, 0x648f0000U, 0x50538000U, 0x25c04000U, 0x38296000U, 0x4157000U, 0x4a200800U, 0xcb100400U, 0xae980600U, 0xdb740d00U, 0xeb720480U, 0x335f0bc0U, 0xa76b80e0U, 0xc5644e10U, 0x62636b58U, 0x8aee73dcU, 0xc8180c2U, 0x5c4f4961U, 0xb3fae151U, 0x2d15307bU, 0x3a9652dU, 0x98d57988U, 0x13800be5U, 0xf0c0054cU, 0x1fa00a5aU, 0x66d0055dU, 0xab80800U, 0x61640400U, 0xd86a0600U, 0xb9eb0d00U, 0x86398480U, 0x7d2b4bc0U, 0xb90e0e0U, 0x44fe3e10U, 0xcd90e358U, 0x59fe37dcU, 0x1610e6c2U, 0x553e3461U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xd0000000U, 0x98000000U, 0x34000000U, 0x12000000U, 0x43000000U, 0x4800000U, 0xb8400000U, 0x46200000U, 0x41300000U, 0x3fb80000U, 0x58f40000U, 0x74460000U, 0x701d0000U, 0x680c8000U, 0x9c1cc000U, 0x6e132000U, 0xfd051000U, 0x61980800U, 0xedc40c00U, 0xb9fe0e00U, 0xbbe90d00U, 0x80ca8980U, 0x6041c340U, 0x523fa120U, 0x6329d430U, 0x34b32848U, 0xf0751784U, 0xea000262U, 0x67000513U, 0x6e80047bU, 0x1f400bcfU, 0xc8a00fe4U, 0x8e700071U, 0x6f1807e8U, 0xe2840675U, 0x95e02cbU, 0xd1990047U, 0x65d28180U, 0xf5c5cf40U, 0x4de1af20U, 0x49f0d930U, 0x13c1a1c8U, 0xfcc0d4c4U, 0xde79a342U, 0x3734d123U, 0x36bfac33U, 0xcb69dc4bU, 0xa932d86U, 0x55451562U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x50000000U, 0x98000000U, 0xec000000U, 0xe000000U, 0x29000000U, 0x9f800000U, 0xa9400000U, 0x52200000U, 0x8f300000U, 0x32a80000U, 0x1cd40000U, 0xa8460000U, 0x89ab0000U, 0xac5b8000U, 0x63964000U, 0x5f65e000U, 0x673f5000U, 0xd6880800U, 0xc6e40c00U, 0x336e0a00U, 0xa93f0500U, 0x5fbd8980U, 0x94d4ec0U, 0x23660e0U, 0x170d1290U, 0xdea3e1f8U, 0x12d45694U, 0x81738722U, 0x160241f3U, 0x503e0aaU, 0x31a45a0dU, 0xd07b8be4U, 0x55a648caU, 0xca4de9ddU, 0x6eab5b3dU, 0xbaee08acU, 0x57f06d4U, 0x3c1d8180U, 0x563d42c0U, 0x653e6ae0U, 0xc1a91790U, 0x186de878U, 0x219b5854U, 0x284607c2U, 0x49ab0363U, 0xc5b8952U, 0x33964099U, 0xc765e6c6U, 0x8b3f5c39U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x30000000U, 0xf8000000U, 0xfc000000U, 0x1e000000U, 0x2b000000U, 0x67800000U, 0xc5400000U, 0xab200000U, 0x27900000U, 0x65680000U, 0x9b2c0000U, 0xdfae0000U, 0x99570000U, 0x852b8000U, 0xf4a4c000U, 0xfecee000U, 0x405ad000U, 0x5fae0800U, 0xd9570400U, 0x252b8a00U, 0xc4a4c300U, 0x6ceef80U, 0xbc5adfc0U, 0x41ae09e0U, 0xf25706b0U, 0x42ab8c78U, 0x1e4cf54U, 0xadeee532U, 0x9bcaddb9U, 0x24c60fb6U, 0x697b0f02U, 0x9d058182U, 0x98b3c6c1U, 0x28c56d60U, 0x6f6e12f3U, 0xda08e05aU, 0x2921db07U, 0xc2ab8c78U, 0x41e4cf54U, 0xdeee532U, 0xabcaddb9U, 0xdcc60fb6U, 0x957b0f02U, 0x83058182U, 0xb3b3c6c1U, 0x4f456d60U, 0xaa2e12f3U, 0x7128e05aU, 0xeb1db07U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x90000000U, 0x68000000U, 0x9c000000U, 0x6000000U, 0x2f000000U, 0xf8800000U, 0x2a400000U, 0x7f200000U, 0x30900000U, 0xc6780000U, 0x81040000U, 0xeb8a0000U, 0xa4df0000U, 0x82458000U, 0x4321c000U, 0x46b12000U, 0x11571000U, 0x8d8a0800U, 0x5bdf0400U, 0xf2c58e00U, 0x6561c900U, 0x57912680U, 0x92c719c0U, 0xb5720860U, 0xdf9b06f0U, 0x9eef8188U, 0xdb6ecba4U, 0x6c8ca172U, 0x6072dac9U, 0xde312407U, 0xeb171ee0U, 0x7aaa0730U, 0x674f05e9U, 0x5abd8756U, 0x5765c7fbU, 0x429b2eecU, 0x33581235U, 0xb0978188U, 0x866acba4U, 0x6106a172U, 0x7baddac9U, 0xccf4a407U, 0x1e76dee0U, 0x453b2730U, 0x698815e9U, 0xe9cf8f56U, 0xa7fec3fbU, 0x24f4a0ecU, 0xc276db35U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x70000000U, 0xa8000000U, 0x44000000U, 0xc2000000U, 0x13000000U, 0xcf800000U, 0xe2400000U, 0x71200000U, 0x6cb00000U, 0xa5c80000U, 0xa77c0000U, 0x77ba0000U, 0x9e690000U, 0xf048000U, 0x2182c000U, 0x5740e000U, 0x1fa51000U, 0xfa720800U, 0xbd150c00U, 0x9abe8200U, 0xdcebc700U, 0x3fc46a80U, 0x9867d440U, 0x1e12e420U, 0xdd001d30U, 0xa8486f8U, 0x24c2c524U, 0xa3e0ef92U, 0xb655158bU, 0x8b1a04fcU, 0xc3990307U, 0x346c85a3U, 0x780ec1f2U, 0x5c12e19aU, 0xe001eb7U, 0xe5048c1aU, 0xb682c076U, 0x7ac0ec78U, 0x9ee51164U, 0xecd20bb2U, 0x77e508bbU, 0x8c568204U, 0x427c623U, 0x22366a31U, 0x4332d479U, 0x178c6566U, 0xe5bddb0U, 0xf708e9b9U, 0xbd991184U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x10000000U, 0x18000000U, 0x7c000000U, 0x8e000000U, 0x6f000000U, 0x52800000U, 0x1fc00000U, 0x59200000U, 0x71b00000U, 0x2b780000U, 0x5de40000U, 0x90160000U, 0xd8170000U, 0x9c1f8000U, 0x9e19c000U, 0x770da000U, 0x2ebb7000U, 0x91ee0800U, 0x36330c00U, 0x23298e00U, 0x34bec100U, 0x4ea2180U, 0xe186b7c0U, 0xf355a0e0U, 0xc1ef7af0U, 0xe000328U, 0xaf000cfcU, 0xb2800a12U, 0xfc001dbU, 0x41200bd7U, 0xdb004eeU, 0xa57804c9U, 0x32e40a8dU, 0xc296097bU, 0xc7d70f06U, 0xc53f8055U, 0xefa9c02eU, 0x5c75a2a8U, 0x735f7b3cU, 0x1f80af2U, 0xee240b2bU, 0xbf3600ffU, 0xaaa70412U, 0x73e780dbU, 0xcf3dca56U, 0x62bba32cU, 0xf7dc7c28U, 0x2d29847cU, 0x9bbec053U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xb0000000U, 0x8000000U, 0xf4000000U, 0xa6000000U, 0x77000000U, 0x65800000U, 0xd3c00000U, 0x45200000U, 0xe4900000U, 0xd9680000U, 0xbf4c0000U, 0x28720000U, 0x5de50000U, 0x361d8000U, 0x8f0bc000U, 0x39a26000U, 0x31ce7000U, 0x9c3a0800U, 0x2390400U, 0xc9078a00U, 0x5ea2cb00U, 0xec4de080U, 0xb3e0bf40U, 0x1525e260U, 0xfcacb370U, 0x9557e458U, 0xe549b23cU, 0xd4a66d2U, 0xe9427e09U, 0xf7680576U, 0x7c4c0cc4U, 0x4bf2043fU, 0x49250bd2U, 0x1ebd8b8bU, 0x4c5bc3b5U, 0x3ea6666U, 0x1d127cedU, 0x8a00cd8U, 0x3350097cU, 0x92480eb2U, 0x68dc0679U, 0x3a9a01aeU, 0xb26901b8U, 0x98cf808dU, 0x92bec6abU, 0xf677eaa5U, 0x36d9bd4dU, 0x11a2648bU, 0x35ce7936U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0x48000000U, 0xf4000000U, 0x26000000U, 0x61000000U, 0x17800000U, 0x8c00000U, 0xbb200000U, 0x4b00000U, 0xe8580000U, 0x5d540000U, 0x1cc20000U, 0x8d350000U, 0x4d958000U, 0xdbe64000U, 0x3bbee000U, 0x32d4b000U, 0xb83a0800U, 0xcc110c00U, 0x2a2f8600U, 0x2b374d00U, 0xecb16480U, 0xac53ff40U, 0xe3536a60U, 0xc1d6fa10U, 0x489eef78U, 0x264b18cU, 0x16620132U, 0x20450e0bU, 0x696d8e65U, 0x5ac24185U, 0x3c04e654U, 0x1205b10fU, 0x27358473U, 0xa6964769U, 0x5746e1f4U, 0x47f0bb3fU, 0x998003f8U, 0x8dc002ccU, 0xa2a00d52U, 0x4970091bU, 0x2af80d9dU, 0xc4240349U, 0x7e3a0b06U, 0xbd110814U, 0x15af81eeU, 0x7f74820U, 0x39916cf2U, 0x3de3fe2bU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0x78000000U, 0x74000000U, 0x7e000000U, 0x5f000000U, 0xd0800000U, 0x75400000U, 0x7d200000U, 0x2d900000U, 0x18f80000U, 0x85fc0000U, 0xd86e0000U, 0xb8950000U, 0x496b8000U, 0xef0dc000U, 0x8bb2000U, 0x9179d000U, 0xb360800U, 0x7eb90400U, 0xc25d8e00U, 0xd1b4c700U, 0x2ae6a780U, 0x30cd1740U, 0x59d0afe0U, 0x3a7411f0U, 0xe58d2b08U, 0xb4c0d454U, 0x1feb8652U, 0xf14dc699U, 0x3b1b2fefU, 0xe6a9ddefU, 0xc66e08eeU, 0xd7950a6dU, 0x1eb87acU, 0x9e4dc98dU, 0x739b2c5eU, 0x97e9d385U, 0xbd4e0488U, 0xd1050714U, 0xb79387b2U, 0x31f1c069U, 0x6552b67U, 0x77acdafbU, 0x91fd8f5cU, 0x9664ca04U, 0x7fbeaccbU, 0x9de11376U, 0x9c66a302U, 0x5e8d1981U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x90000000U, 0xc8000000U, 0x24000000U, 0x8e000000U, 0x39000000U, 0x6a800000U, 0x60400000U, 0x5aa00000U, 0xf8700000U, 0x96a80000U, 0xc2540000U, 0xe99a0000U, 0xb5dd0000U, 0x6d798000U, 0xb6334000U, 0xa5332000U, 0xb8b35000U, 0xab798800U, 0x6b334c00U, 0x61b32200U, 0x71f35900U, 0x53598480U, 0xd7034e40U, 0x23bb2ae0U, 0x72d75a90U, 0x46eb8228U, 0xc0ca4844U, 0xfdf8af4aU, 0x89491517U, 0x18092b42U, 0xc1e5461U, 0x1a2809d3U, 0xef14024aU, 0xbfba0795U, 0xa0ed0a02U, 0x8df18500U, 0xf1574e81U, 0x64212b42U, 0x6e0a5461U, 0x891209d3U, 0x32b9024aU, 0x8c6b8795U, 0xf08a4a02U, 0x4f58a500U, 0xc5391e81U, 0xc8a12342U, 0xd34a5861U, 0x17320bd3U, 0x3890b4aU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0xf8000000U, 0xbc000000U, 0xca000000U, 0x39000000U, 0x13800000U, 0x55400000U, 0xbba00000U, 0xd1700000U, 0x6d880000U, 0xf2440000U, 0xbf360000U, 0x8ab0000U, 0x9be48000U, 0x5b754000U, 0x34986000U, 0x91ec1000U, 0xc2648800U, 0xf7354c00U, 0x3cb86a00U, 0xc5dc1d00U, 0xec4c8780U, 0x680147c0U, 0x240666a0U, 0x6331e90U, 0xdb1e06b8U, 0x6e9f0294U, 0x30da8d1aU, 0x1dda4387U, 0x406ae860U, 0xfa0251b0U, 0x713064e9U, 0x2798120dU, 0xb7a8c5eU, 0xcaa4ec7U, 0x8de2e680U, 0xd8465243U, 0x36066860U, 0x933311b0U, 0x5a9e04e9U, 0x6edf020dU, 0xaafa845eU, 0x1cea42c7U, 0x4fc2ec80U, 0xb5765f43U, 0xbae67e0U, 0x59471a70U, 0xf9800849U, 0x7c40019dU, 0x80000000U, 0x40000000U, 0x60000000U, 0x30000000U, 0xf8000000U, 0xe4000000U, 0xfa000000U, 0xad000000U, 0xb6800000U, 0x89c00000U, 0x92a00000U, 0x53d00000U, 0x6fb80000U, 0x2d5c0000U, 0xfa460000U, 0xa1c50000U, 0xfea88000U, 0xd5d64000U, 0xec992000U, 0x34d23000U, 0x8c088800U, 0xf6064400U, 0x1b212600U, 0xcd8e3300U, 0x744e8780U, 0x1ec34a40U, 0xa909a9a0U, 0x3c9879d0U, 0xbcf7ace8U, 0xf00172dcU, 0xd819288aU, 0xb41238edU, 0x32288c13U, 0xb1164309U, 0xa8b920aeU, 0xdec238b1U, 0x89108a59U, 0x6c8a4784U, 0x74df2a8fU, 0xec173d20U, 0xc6200413U, 0xe3100709U, 0x299806aeU, 0x8e4c0bb1U, 0xb3de0dd9U, 0x1f890dc4U, 0xb576832fU, 0x2e5f44f0U, 0xa3efa8fbU, 0xb78d75d5U, 0x99672e24U, 0xc84b335cU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x10000000U, 0x68000000U, 0xe4000000U, 0x86000000U, 0x9d000000U, 0xe1800000U, 0xb0c00000U, 0xeda00000U, 0x12f00000U, 0x16980000U, 0x7e740000U, 0x2fc20000U, 0xc72d0000U, 0x56b38000U, 0x5e624000U, 0xdfe7e000U, 0xbf387000U, 0xda938800U, 0x3c524c00U, 0xc4dfee00U, 0xc3bc7100U, 0x8bc98e80U, 0x610b4240U, 0x3bae6660U, 0xc7f338d0U, 0xe31de098U, 0x3091794cU, 0xd37a00baU, 0x566905ffU, 0xebc987f1U, 0xb10b43abU, 0xb3ae62c6U, 0x33f33acdU, 0xd1dea7aU, 0x49917cddU, 0xb4fa09c0U, 0x7ba900a2U, 0xe7e98ff1U, 0x133b4fabU, 0x48966cc6U, 0x5f773bcdU, 0x3447ecfaU, 0xf0c8729dU, 0xcd8b81a0U, 0xe2e64972U, 0x6ebde1e9U, 0xf26174a7U, 0x4de20a1cU, 0xdc1d06e2U, 0x80000000U, 0x40000000U, 0x20000000U, 0x70000000U, 0xa8000000U, 0x34000000U, 0xd2000000U, 0x59000000U, 0xd6800000U, 0xf1400000U, 0x9aa00000U, 0x8f500000U, 0xada80000U, 0x96cc0000U, 0xa9420000U, 0x46a10000U, 0x49468000U, 0x56af4000U, 0xb1672000U, 0xbaa51000U, 0xff668800U, 0x5bf4400U, 0xa2ef2200U, 0x7b791700U, 0x1fac8280U, 0x9fc24740U, 0xa7e3af20U, 0x2beb5290U, 0x35e72fe8U, 0x52e51854U, 0x93468e8aU, 0xbaf4e65U, 0x3de72f32U, 0x56e51238U, 0xc9468c9eU, 0x16af4e4fU, 0x91672c06U, 0xcaa51182U, 0x576687c0U, 0x31bf4f61U, 0x70ef2732U, 0x22791638U, 0xc92c8e9eU, 0x6e82494fU, 0x3d43a686U, 0xa4bb52c2U, 0x984f2ae0U, 0xc4291af1U, 0x3a04825aU, 0x4d0e4d2cU, 0x74a1ad34U, 0x4a52baU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0x88000000U, 0xcc000000U, 0x5a000000U, 0x77000000U, 0x4e800000U, 0x23400000U, 0xd4a00000U, 0xb4500000U, 0xaa080000U, 0x8f340000U, 0x3a8a0000U, 0xad570000U, 0xbd948000U, 0x1bfec000U, 0xeacd2000U, 0x41411000U, 0x379c8800U, 0x44cac400U, 0xf8472a00U, 0xb0161900U, 0x58080080U, 0xe43408c0U, 0x60a0fa0U, 0xa5170e70U, 0xf5b48c68U, 0x37eecef4U, 0x80e528eaU, 0x2e651c35U, 0x3d3e8648U, 0xf1b9cec7U, 0x1f1a4e2U, 0x3ddbd890U, 0x9fd3a1f9U, 0x9ce8d18cU, 0x5c452aa4U, 0x163514b1U, 0x6d3686c8U, 0x998dc607U, 0xfdfbab42U, 0x7fccd6e0U, 0xace72d91U, 0x44461f78U, 0x5200024eU, 0xfb000884U, 0xb4800080U, 0xc44008c0U, 0x12200fa0U, 0x5b100e70U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x70000000U, 0x68000000U, 0xb4000000U, 0xb6000000U, 0x9000000U, 0x40800000U, 0xb9400000U, 0x3ea00000U, 0x54700000U, 0x30180000U, 0x482c0000U, 0x24220000U, 0xae310000U, 0xd5378000U, 0x42af4000U, 0x67da000U, 0x770c1000U, 0xadaf8800U, 0xb7c34c00U, 0x22ffae00U, 0x404d1700U, 0xd6000e80U, 0xb9000740U, 0xc8800560U, 0x7d400790U, 0xe0a00288U, 0xe97000d4U, 0xc698088aU, 0xf86c05d7U, 0x5a020709U, 0x43010f16U, 0xdb8f81a8U, 0x5ef34fa4U, 0x1247ae52U, 0x911110a8U, 0x5cba0a25U, 0x5b5d0193U, 0xf1b58989U, 0x75ee4856U, 0x7dd224c8U, 0x79cf5834U, 0x47d024daU, 0x8ace5c7cU, 0x145facafU, 0x103d1344U, 0xd8180000U, 0x3c2c0000U, 0x72220000U, 0xd7310000U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x10000000U, 0xb8000000U, 0xe4000000U, 0x86000000U, 0x8d000000U, 0x4b800000U, 0x8ec00000U, 0x79a00000U, 0x1df00000U, 0xab180000U, 0xf6b40000U, 0x8d560000U, 0xbb5d0000U, 0xbe5f8000U, 0x59f24000U, 0x1d1f6000U, 0x33a2f000U, 0x8ae78800U, 0xefb64c00U, 0x28d16e00U, 0x48bf100U, 0xfe4e0380U, 0x79e90240U, 0xed098660U, 0x9baf49d0U, 0xd6c0ef38U, 0x8d90b6acU, 0x23d8e7faU, 0xc224b50fU, 0x3b0ee809U, 0x8eb9ba87U, 0x897162cfU, 0x2d7bf92aU, 0x8b5604b4U, 0xf65d0164U, 0x15df805cU, 0xc73247f3U, 0xdcbf6389U, 0xca52f4c7U, 0xa7ff8aafU, 0x940241faU, 0xee07680cU, 0x3116f588U, 0x39b181c6U, 0x3deb4b2cU, 0x5b0eecb8U, 0x5eb9b4ecU, 0xd171619aU, 0xd97bfcdfU, 0x80000000U, 0x40000000U, 0x60000000U, 0xb0000000U, 0x88000000U, 0xbc000000U, 0xba000000U, 0x6b000000U, 0xbb800000U, 0x27400000U, 0x30a00000U, 0x6cd00000U, 0xfff80000U, 0x505c0000U, 0xa10a0000U, 0x788b0000U, 0xf0f88000U, 0x95dbc000U, 0x37d6000U, 0x2eba9000U, 0x59f28800U, 0x1150c400U, 0x2985e600U, 0x60615b00U, 0x690fe080U, 0xa4aa5fc0U, 0xfad765a0U, 0x76e199b0U, 0x4f20d38U, 0xb3d706b4U, 0x272862aU, 0xc610c0bdU, 0xf125e767U, 0xb15a01U, 0xa4f7e102U, 0x23f65181U, 0x5a5d6642U, 0x422a97e1U, 0x7f2a8052U, 0x6d9cc26bU, 0xce57ea5fU, 0xd4265cb5U, 0xf6256728U, 0x3936913cU, 0xdc808125U, 0xaec7cde0U, 0xc0d76150U, 0x5de193eaU, 0xdf720c1dU, 0x24970b54U, 0xbad2877aU, 0x16c0c357U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0x58000000U, 0x54000000U, 0x56000000U, 0x33000000U, 0x54800000U, 0xe4c00000U, 0x17a00000U, 0x18700000U, 0xcf780000U, 0x5c40000U, 0xbe1e0000U, 0xaf290000U, 0x6e8f8000U, 0x85dbc000U, 0x7e23a000U, 0xcf057000U, 0x3e918800U, 0xddf2cc00U, 0x2a2c2600U, 0x991eb500U, 0xd922d80U, 0x8947b940U, 0xcee5ab60U, 0x8e987a30U, 0x15f80ec8U, 0x4604020cU, 0xcb3e079aU, 0x309902f7U, 0xbad7895fU, 0x28afc860U, 0x4ee5aab3U, 0x4e987609U, 0x75f8062dU, 0x16040bcaU, 0x933e078eU, 0x649902d9U, 0xecd78797U, 0x1bafca6cU, 0x1a65ad29U, 0xaa5874feU, 0x62580f72U, 0xe7403aaU, 0x5c460d3dU, 0x615d04d0U, 0x52c989baU, 0xb486cda6U, 0x74ea2ca7U, 0x2f83b327U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x30000000U, 0x78000000U, 0xdc000000U, 0xca000000U, 0x43000000U, 0xe3800000U, 0x9c400000U, 0xb8a00000U, 0x73d00000U, 0x6c80000U, 0x1c7c0000U, 0xf8860000U, 0xd3c30000U, 0x36e88000U, 0x6445c000U, 0x24bb6000U, 0x19c65000U, 0x75ee8800U, 0x87c6c400U, 0xb8f3ea00U, 0xa1539300U, 0x61def80U, 0x813c99c0U, 0xa4bb6ea0U, 0x59c65330U, 0xd5ee8bb8U, 0xb7c6c304U, 0xc0f3eaaaU, 0x7d539dcdU, 0xcc1ded74U, 0xc23c95f3U, 0x473b649aU, 0xc58650f5U, 0x6d4e8330U, 0xc416c3baU, 0xc63be705U, 0x612f90aaU, 0x349be6ccU, 0x11ff96f7U, 0x71d3ee30U, 0xa1c39d38U, 0x49f5e644U, 0xddd09249U, 0xb3d5699fU, 0xe6e9535fU, 0x8c680a7cU, 0xb0ac0c8dU, 0x77ce0795U, 0x20ff0ea2U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x90000000U, 0x8000000U, 0x5c000000U, 0x3a000000U, 0x2f000000U, 0xac800000U, 0x94c00000U, 0x5fa00000U, 0xc2700000U, 0x44480000U, 0xa1740000U, 0x1afa0000U, 0xe68b0000U, 0x43f08000U, 0x9732c000U, 0xa8a4a000U, 0x5add7000U, 0x86aa8800U, 0x73c9cc00U, 0xf1c2a00U, 0xfc9bb900U, 0x3cf42880U, 0x939fb9c0U, 0xf04621a0U, 0x3760b7f0U, 0x37cca848U, 0xa119798cU, 0x15b884daU, 0x1546ce17U, 0x8cdea7acU, 0xcb967d6bU, 0x47a05bdU, 0xc14b0033U, 0x2ad086e9U, 0x7e82cdffU, 0x17cca0d3U, 0xf1197179U, 0xbdb887e4U, 0xd946c8e7U, 0xbedeab67U, 0xb8967724U, 0x92fa09c5U, 0x7a8b0954U, 0xd9f084ceU, 0x2832c6baU, 0xc24a945U, 0x921d7c94U, 0xe30a8f6eU, 0x9eb9c84aU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x70000000U, 0x28000000U, 0xc4000000U, 0x3a000000U, 0x9b000000U, 0xa1800000U, 0x93400000U, 0xa0a00000U, 0xf9f00000U, 0x2a580000U, 0x560c0000U, 0xa5020000U, 0xe0950000U, 0xd9d88000U, 0xba7dc000U, 0xe07e000U, 0x49049000U, 0x1e828800U, 0x78e4cc00U, 0x80dd6e00U, 0x3cec5700U, 0x7addea80U, 0x47dd9040U, 0xab7805a0U, 0xfcbc02b0U, 0xcffa0698U, 0x3f690274U, 0x7e828b2aU, 0xc8e4ca6fU, 0x48dd6b1dU, 0x88ec55e4U, 0x68dde242U, 0x18dd94a2U, 0x30f80332U, 0xf4fc0a58U, 0xceda0495U, 0x55d904b9U, 0xf47a8705U, 0x6718c7d0U, 0xc7876cc8U, 0x3e755c7dU, 0x14076eb7U, 0x42355dc8U, 0xe7276dfdU, 0x7855a74U, 0xde5f6f2aU, 0x6439586cU, 0x6a256a1fU, 0x23105c66U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x70000000U, 0x28000000U, 0xa4000000U, 0xfe000000U, 0x3d000000U, 0x82800000U, 0xb3400000U, 0x5a00000U, 0x42f00000U, 0x41780000U, 0xa28c0000U, 0x63620000U, 0x3d8d0000U, 0xbed98000U, 0x33544000U, 0xc5ba2000U, 0x22fe1000U, 0x31638800U, 0x8aa54c00U, 0xc779a600U, 0xc3ab5700U, 0x83e22a80U, 0xb1c21640U, 0x76d981e0U, 0x275448d0U, 0x73ba2ca8U, 0xcbfe1674U, 0x65e3853aU, 0xa0e541bfU, 0xbe59a5dfU, 0xf1b55ccU, 0x45ba24c4U, 0xe2fe1a83U, 0x51638e40U, 0xfaa545e2U, 0xef79a2d2U, 0x67ab5dabU, 0x7de22bf7U, 0x8cc219f8U, 0xf459861eU, 0x941444ecU, 0x761a2db7U, 0x890e101aU, 0x249b82ccU, 0x2694e47U, 0xdd3bacc0U, 0x32965fa2U, 0xfb63a532U, 0xd1aa527bU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x70000000U, 0x88000000U, 0x5c000000U, 0xea000000U, 0x43000000U, 0x40800000U, 0xfc400000U, 0x9da00000U, 0x19f00000U, 0x90580000U, 0xdf8c0000U, 0x96ea0000U, 0xc2d30000U, 0xb4d48000U, 0xfdcdc000U, 0x8e49a000U, 0xba835000U, 0x87468800U, 0xe922cc00U, 0x238f2e00U, 0x2ce19700U, 0x99e9a080U, 0x507359c0U, 0x3f9e88a0U, 0xe6eecf30U, 0x4ac52288U, 0xe8c29d04U, 0x17e527faU, 0xcd729c6fU, 0xfa1d25adU, 0x7b0e9d0cU, 0x74af2a3cU, 0x3a519cb6U, 0xbc91abb2U, 0x464f594bU, 0xc68c8ca7U, 0xfd41cf49U, 0x5223afa5U, 0xb71055c8U, 0x66b20b66U, 0xad5f08e9U, 0x4a3e8417U, 0x131ecc83U, 0x589d27c1U, 0x584e97a0U, 0xa38f23b2U, 0xece1954bU, 0x79e9a2a7U, 0x20735849U, 0x80000000U, 0x40000000U, 0x60000000U, 0xd0000000U, 0x58000000U, 0x9c000000U, 0x2a000000U, 0xcf000000U, 0x3d800000U, 0x4c400000U, 0xca00000U, 0x70d00000U, 0xb4780000U, 0x60840000U, 0xb2de0000U, 0x6f6b0000U, 0xb3188000U, 0x878ac000U, 0xbb4ee000U, 0x7d285000U, 0x4e9e8800U, 0xebf5c400U, 0x7d06600U, 0x85dd9d00U, 0x3eceed80U, 0x3d685dc0U, 0x503e8ca0U, 0x1825c5f0U, 0xfc286058U, 0xfa199004U, 0x9730efeaU, 0xa193563dU, 0x667e043fU, 0xc3bb073cU, 0x4d608bbfU, 0xf80ec1ffU, 0x6c10e79cU, 0xc2035c4dU, 0xdb2602a6U, 0xd3af0b18U, 0x356681e7U, 0xd431cef8U, 0xce2e6ef5U, 0xc9269f32U, 0x508e667bU, 0x7af692b5U, 0xcb766c53U, 0xd532942aU, 0x3a88679cU, 0xd5c99c4dU, 0x26c8e2a6U, 0xc1575b18U, 0x80000000U, 0x40000000U, 0x60000000U, 0x90000000U, 0xe8000000U, 0xc000000U, 0xbe000000U, 0x2f000000U, 0x73800000U, 0x12400000U, 0x3a600000U, 0x16700000U, 0x58680000U, 0xf4c0000U, 0x98f60000U, 0x38b50000U, 0x93fa8000U, 0xd9014000U, 0xe0b5a000U, 0xc7dd3000U, 0x7335a800U, 0x59d3400U, 0xc155ae00U, 0x8fed3d00U, 0xcf3da080U, 0xa3a13dc0U, 0x9a4bab60U, 0xa6543f30U, 0x40512c58U, 0x7b657e14U, 0xc2ec8ffeU, 0xa5844f73U, 0x71472278U, 0x97e07b87U, 0xbb1e05f7U, 0xf9b9050cU, 0x76c8c48U, 0x44c4455cU, 0xea72123U, 0x20d07211U, 0xfc960c48U, 0xd1c5055cU, 0x30128123U, 0x580d4211U, 0x1423a448U, 0xca18315cU, 0x75272f23U, 0xee907f11U, 0xf0f604c8U, 0x74b50c9cU, 0x4dfa8443U, 0x66014021U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x90000000U, 0x8000000U, 0x74000000U, 0xea000000U, 0x15000000U, 0xdc800000U, 0x40c00000U, 0xe8e00000U, 0xccd00000U, 0xed80000U, 0xfffc0000U, 0xc17e0000U, 0xe0a30000U, 0x3ef98000U, 0xa7ecc000U, 0x9d63e000U, 0xee9fd000U, 0xc9e3e800U, 0x1a5fdc00U, 0xeb03ea00U, 0x538fd500U, 0x315bea80U, 0x98b3d240U, 0xf2c5e420U, 0xa1c0d310U, 0x1e6469e8U, 0xb910171cU, 0xaa998766U, 0x7bfccbd1U, 0x535bef8bU, 0x39b3d82eU, 0xe445e99cU, 0x6400d324U, 0x220468f3U, 0x4100171aU, 0xa6a18f05U, 0x5dd0cfe3U, 0x407de8f3U, 0x662cd71aU, 0xf3226f05U, 0xef9f1fe3U, 0x8f4600f3U, 0xf78f0b1aU, 0x335f8505U, 0x49b3cae3U, 0x5c646a73U, 0x8810195aU, 0xb4198125U, 0xca3cc9f3U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0xa8000000U, 0x9c000000U, 0xfa000000U, 0xd3000000U, 0xdb800000U, 0xb4c00000U, 0x88e00000U, 0x62d00000U, 0x39d80000U, 0xae6c0000U, 0x48860000U, 0x8f410000U, 0xcc2f8000U, 0x92034000U, 0x6f39a000U, 0xf1829000U, 0xcfd9a800U, 0xcf529c00U, 0x2c01aa00U, 0x623e9100U, 0x1707a080U, 0xc5bf98c0U, 0xa9c82f20U, 0xe66cd5f0U, 0x24a98298U, 0xd424ebcU, 0x2b162216U, 0x2f81d491U, 0xf2e00b8bU, 0x71d00f77U, 0xc2580f83U, 0xcaac0f43U, 0x68660461U, 0x71910f93U, 0xff78a0aU, 0xef6f4f37U, 0xfc3fac61U, 0xca039393U, 0x8b16200aU, 0x3f81de37U, 0x7ae00ce1U, 0x3dd00b53U, 0x90580f2aU, 0x85ac0bc7U, 0x49e60e79U, 0x165105efU, 0x5c978d3cU, 0x397f4f56U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x30000000U, 0x88000000U, 0xfc000000U, 0xe6000000U, 0x59000000U, 0x18800000U, 0xc1400000U, 0x95600000U, 0x1f700000U, 0xf8480000U, 0xfdc40000U, 0xb6260000U, 0xa1390000U, 0x8c908000U, 0xeb7ec000U, 0xa254e000U, 0xa2d6b000U, 0xc7b4e800U, 0xf0e6b400U, 0x249ce600U, 0x8752b700U, 0x1c72ee80U, 0xbfefb8c0U, 0x4d2460e0U, 0x72987d50U, 0x16480168U, 0x18c40144U, 0xa8a6003eU, 0x97904b3U, 0x897081baU, 0xc94ec86fU, 0x297ce258U, 0x1962bdbcU, 0x915aecf1U, 0x6d5bb29bU, 0x8b4a695cU, 0xd26577a2U, 0xcafe84f1U, 0xb83c69bU, 0x9ee26f5cU, 0x819170a2U, 0x79f08271U, 0x840eca5bU, 0x321ce9bcU, 0x9312baf2U, 0x1f92ed99U, 0xf4dfb3dfU, 0x568c6962U, 0xf46c7311U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xd0000000U, 0x58000000U, 0x84000000U, 0xca000000U, 0x6b000000U, 0x1f800000U, 0x12400000U, 0x98600000U, 0xd3500000U, 0xfce80000U, 0x669c0000U, 0x22ea0000U, 0xbf9b0000U, 0xe2418000U, 0xf0474000U, 0xdf6aa000U, 0xead53000U, 0x4382a800U, 0x9c493c00U, 0xd968a600U, 0x77d23100U, 0xa9292380U, 0x68957940U, 0xa3c38f20U, 0xfb004ff0U, 0x67a126d8U, 0xa65972d4U, 0xda41895eU, 0x64474ee1U, 0xad6aa510U, 0xd5d531c8U, 0xce02a81eU, 0x610935c1U, 0x9488a0e2U, 0xddc23811U, 0xd2212c4aU, 0xcf19745dU, 0xe5a18362U, 0xf1574151U, 0x5be2a36aU, 0x8f193badU, 0xc580a5baU, 0xc14e3385U, 0xd3c32a34U, 0x530e754cU, 0x8b8200aaU, 0x6047024dU, 0xa74b822aU, 0x5ecc408dU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0x68000000U, 0xe4000000U, 0x7e000000U, 0x87000000U, 0xda800000U, 0x2c400000U, 0x62600000U, 0x3d700000U, 0x9bd80000U, 0x158c0000U, 0x2f60000U, 0xf83f0000U, 0x6c388000U, 0x6a354000U, 0xc125e000U, 0xd199f000U, 0x6cfde800U, 0xb715f400U, 0x28be200U, 0x506af100U, 0xc0536480U, 0x486fbf40U, 0x5c4e8360U, 0x1a4a4730U, 0x117d66c8U, 0x51dcb1f4U, 0x848002eeU, 0xbb400323U, 0x70e00fd3U, 0xa5300d3bU, 0xefb8049cU, 0x4bfc0188U, 0x3dae0e97U, 0x46f303dfU, 0xd62e8eebU, 0x833a47a5U, 0x54a56a17U, 0x9350bc9fU, 0x34f60d8bU, 0x8b3f0095U, 0xb88cdfU, 0x75754d6bU, 0x6fc5ef65U, 0xa3a9f3b6U, 0x31c5eb0cU, 0x34a9f450U, 0x2345e9f9U, 0xace9f33eU, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0xd8000000U, 0xfc000000U, 0xba000000U, 0x2f000000U, 0xd0800000U, 0x78c00000U, 0xaae00000U, 0x81f00000U, 0x7680000U, 0x42b40000U, 0x33e20000U, 0x5c6d0000U, 0x1c0b8000U, 0x8a244000U, 0x972a6000U, 0x5ca55000U, 0x1ac26800U, 0x79d15400U, 0xeb406e00U, 0x508c5300U, 0x38c3e380U, 0xcaec1cc0U, 0xf1e38820U, 0xdf504e30U, 0xbea86d28U, 0x89f85dbcU, 0x7341e986U, 0xccb116a3U, 0xf2e00270U, 0x3df00a48U, 0xdd680f6eU, 0x1db406beU, 0x3b620e06U, 0xd8ad0c60U, 0xceb8d52U, 0x24d449f9U, 0x40c26d86U, 0x66d150a0U, 0x83c06572U, 0xa44c57c9U, 0xf023e8aeU, 0x981c191cU, 0x9c0b82f4U, 0xca24426aU, 0xf72a615eU, 0x2ca55b94U, 0xc2c26bbaU, 0x85d159e4U, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0xb8000000U, 0x74000000U, 0x2000000U, 0xbf000000U, 0x18800000U, 0x5c00000U, 0x5be00000U, 0x6af00000U, 0xdb680000U, 0x6b2c0000U, 0x2aa20000U, 0x72ef0000U, 0x9f578000U, 0xa12c4000U, 0x49bc6000U, 0xa4741000U, 0x53b46800U, 0x5f681400U, 0x811e6e00U, 0x399b1500U, 0xc63e580U, 0x9f845240U, 0x294205a0U, 0x3c1f09b0U, 0x9e3f8c28U, 0x11004decU, 0xc19e6f96U, 0x185b1a43U, 0x8d83e1a0U, 0x2e745fb1U, 0x50aa052aU, 0x99f3026fU, 0xf5fd8ed7U, 0xb3df4b61U, 0xc6c1e9d2U, 0xbd6b5d79U, 0x6e158357U, 0xf9334d21U, 0x6d83e272U, 0x7e7451c9U, 0x88aa02ffU, 0xfdf3068dU, 0x4ffd8644U, 0x78df473aU, 0xdc41e2f7U, 0x7ab5290U, 0x2d758758U, 0x960343a6U, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0xc8000000U, 0xdc000000U, 0x12000000U, 0x65000000U, 0x6d800000U, 0x97c00000U, 0xc1e00000U, 0x72f00000U, 0xec680000U, 0x85140000U, 0xdd860000U, 0x3fe10000U, 0xeddd8000U, 0xa8e8c000U, 0x5559a000U, 0xfab75000U, 0x2f51a800U, 0x93935400U, 0x8dfae00U, 0x85565b00U, 0xa28c2280U, 0xcb7b96c0U, 0x958603a0U, 0xa3e10090U, 0x9fdd8d78U, 0x3de8cdecU, 0xf0d9a766U, 0xb17755c3U, 0xfcb1ad20U, 0x84635452U, 0x8937a7d8U, 0x97825efcU, 0xbeea235dU, 0x866a90ceU, 0x94338b36U, 0x8e1dce1aU, 0x170229ddU, 0xf8be920eU, 0x32558696U, 0x8a0cc58aU, 0xa137ae25U, 0xfb825d22U, 0x4ea2c50U, 0xcf6a9bd9U, 0x23b384fdU, 0xa0ddc65cU, 0xa962214eU, 0x788e9b76U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x70000000U, 0x38000000U, 0x4c000000U, 0x66000000U, 0xfb000000U, 0xc4800000U, 0x4cc00000U, 0x47e00000U, 0x7b500000U, 0x5b980000U, 0xa640000U, 0xb23a0000U, 0x61310000U, 0x418c8000U, 0x4f684000U, 0x91b86000U, 0xc77fd000U, 0xc5826800U, 0x9d4edc00U, 0x608eea00U, 0xeee69b00U, 0x8ed68980U, 0x1ec94fc0U, 0x76cce7e0U, 0x72e39c70U, 0x60f801a8U, 0xb1f403bcU, 0xe8420c56U, 0x9b050bc9U, 0x54ae8e0fU, 0x24fd471fU, 0x43eeec84U, 0x69769eb0U, 0x8aae8ecaU, 0x53fd4a8fU, 0xc16ee05eU, 0xaeb69e27U, 0x31ce8f62U, 0x286d4933U, 0xbb16ec08U, 0x248295eeU, 0x1cec816dU, 0xff84e2cU, 0xf40608cU, 0x718bdb5eU, 0x974067a7U, 0x8d8bd8a3U, 0xe9406ad2U, 0x4a8bde79U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x30000000U, 0xc8000000U, 0xdc000000U, 0x22000000U, 0x4b000000U, 0xa8800000U, 0xc00000U, 0xbfe00000U, 0x19500000U, 0xd8880000U, 0x68e40000U, 0x33c60000U, 0xc3590000U, 0x87858000U, 0x3e494000U, 0x5a366000U, 0x9f01d000U, 0x36906800U, 0x59c8dc00U, 0x947dee00U, 0x6d359f00U, 0x45858280U, 0x854942c0U, 0x5ab668a0U, 0x73c1da70U, 0x63706c28U, 0xd798d57cU, 0xc675ed56U, 0x4e119a29U, 0x61238e7eU, 0x5f8045d7U, 0xba5bedeaU, 0x3c3c915eU, 0xd2080ae4U, 0xe3240c23U, 0x44a60bb1U, 0xeac90008U, 0x28ed8eccU, 0x93fd455fU, 0x937868e7U, 0x7fbcd521U, 0x2a53ea32U, 0xa4189e48U, 0xf62e03adU, 0xd52d010fU, 0xf1ab8e7eU, 0x2b6445d7U, 0xcb9dedeaU, 0x8465915eU, 0x80000000U, 0x40000000U, 0x20000000U, 0xd0000000U, 0xc8000000U, 0x44000000U, 0x82000000U, 0x2d000000U, 0xef800000U, 0x67400000U, 0x48600000U, 0xcaf00000U, 0x62380000U, 0x9d2c0000U, 0xd78e0000U, 0x3b570000U, 0x46638000U, 0x21cac000U, 0x22a82000U, 0x38c57000U, 0x171e2800U, 0xdebe7400U, 0xa6f3aa00U, 0x1423b900U, 0xa380680U, 0x492c0d40U, 0xbd8e06a0U, 0x82570b90U, 0xe3e38a58U, 0x2f8ac0e4U, 0x748225eU, 0xb875780bU, 0xd2c6245dU, 0xee227709U, 0x5b25a5ddU, 0x78a8bfc8U, 0xf9ed89bdU, 0xce9dc53bU, 0xecbad94U, 0xa00fb9b5U, 0x90360565U, 0xe83b089fU, 0x940d896aU, 0x4a2dca2eU, 0x6913ab60U, 0x6d93bf72U, 0x4a600ee9U, 0xa7f00dedU, 0xadb80680U, 0x2a6c0d40U, 0x57ee06a0U, 0xb5a70b90U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0xd8000000U, 0xc4000000U, 0xc6000000U, 0xa1000000U, 0x6a800000U, 0xb5c00000U, 0xcae00000U, 0x65700000U, 0xec080000U, 0x9a340000U, 0x43120000U, 0x7d9b0000U, 0xa6768000U, 0xd188c000U, 0xdc536000U, 0xe2879000U, 0x79c96800U, 0x80e89400U, 0x6e4de600U, 0xfd8b5300U, 0xe6600b80U, 0x31b00f40U, 0xac680fe0U, 0x3a840150U, 0xbdfa0748U, 0x46df0d0cU, 0xcf6c8666U, 0x9727c71bU, 0x53b7e4c6U, 0xfb5454a8U, 0xc90c8e5fU, 0xd697cc2dU, 0x27dfee96U, 0x5d05462U, 0xb2f68613U, 0x3148cca9U, 0x8233625eU, 0x2737962eU, 0x2ba16f95U, 0xaf6c9ae2U, 0xa737e9d0U, 0x6b945b8aU, 0x4f6c81acU, 0xd727c2d4U, 0xb3b7e800U, 0x8b545400U, 0x110c8600U, 0x1297c300U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0xb8000000U, 0x14000000U, 0x56000000U, 0x29000000U, 0x7d800000U, 0xd6400000U, 0xe1600000U, 0x69d00000U, 0x88380000U, 0x7c1c0000U, 0x5a020000U, 0x7b2f0000U, 0xbabe8000U, 0x96dac000U, 0x1ca0a000U, 0x77d0b000U, 0x7d1aa800U, 0x4ba3bc00U, 0x4f462200U, 0x34c67d00U, 0x13800980U, 0x2b400c40U, 0x6ae004e0U, 0x869002d0U, 0xacd80938U, 0xd78c0eb4U, 0x655a0caeU, 0x47e30969U, 0x1504814dU, 0x47a9cc38U, 0x1d7c2335U, 0xf3f576eeU, 0x533c8e88U, 0xd6b5c51eU, 0x74fe25c1U, 0x739a78a2U, 0x9b620e30U, 0xc2ff07eaU, 0x2a868d8fU, 0xeec6c31bU, 0xa8a2ae45U, 0x31ffb966U, 0xec242014U, 0x2239719cU, 0xcf068000U, 0xfc86c000U, 0x7c2a000U, 0x752fb000U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x70000000U, 0x58000000U, 0xf4000000U, 0x4e000000U, 0x57000000U, 0xbf800000U, 0xd0c00000U, 0xf5e00000U, 0x4f500000U, 0xf5080000U, 0xf2b40000U, 0x66520000U, 0xe5970000U, 0x79c88000U, 0x25434000U, 0xa425a000U, 0xc6301000U, 0xeb1fa800U, 0x2d831c00U, 0x65ed2e00U, 0xa7735b00U, 0x393a0b80U, 0x38b30440U, 0x27728760U, 0xf9304d30U, 0x58b72a98U, 0x5750573cU, 0xa1208846U, 0xaca74089U, 0x197fadf6U, 0xf61311d2U, 0x13052bebU, 0xc99756c7U, 0x3e00449U, 0x5c500d56U, 0x3c8803c3U, 0xf1740522U, 0x3a320d51U, 0xd907022aU, 0x88a082e5U, 0x1f67439bU, 0x7d1fa9bfU, 0x4e831c84U, 0xf46d2828U, 0x50b353e5U, 0x2b5a0918U, 0x53230f7cU, 0x699a8126U, 0x13d446b9U, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0x68000000U, 0x1c000000U, 0x3a000000U, 0x7000000U, 0xfc800000U, 0xe6c00000U, 0xd2600000U, 0xf8b00000U, 0xe8c80000U, 0x93440000U, 0xc9160000U, 0x9d950000U, 0x476d8000U, 0x3f094000U, 0x58b3e000U, 0x38d71000U, 0x6b5e6800U, 0x4d1e5400U, 0xd38d8e00U, 0x66794b00U, 0xfe9be080U, 0x45e31ec0U, 0xf0e06d20U, 0xa77f55b0U, 0x8f3e0268U, 0x50a1051cU, 0xd4d3826eU, 0x39684f27U, 0x5600668aU, 0x150f570fU, 0x87960675U, 0xd0550af1U, 0x5b8d8c09U, 0xca7944ceU, 0xcc9be4d7U, 0xaee31702U, 0x5e606a83U, 0x5abf53c1U, 0x9bde02a2U, 0x49d10df3U, 0x12fb8e8aU, 0xb45c430fU, 0xa5be6875U, 0xe36e51f1U, 0xe1258489U, 0xe18d4e0eU, 0x8d45e7f7U, 0x503219b2U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x10000000U, 0x28000000U, 0x7c000000U, 0x5e000000U, 0x9d000000U, 0xde800000U, 0x7d400000U, 0xfbe00000U, 0x2900000U, 0x13480000U, 0xbedc0000U, 0x981e0000U, 0x641d0000U, 0xfa348000U, 0x873ec000U, 0x4985e000U, 0x1ce07000U, 0x9b316800U, 0xc79ebc00U, 0x49d48600U, 0x29aecd00U, 0xcccdec80U, 0x533c76c0U, 0xabaf6f60U, 0x3fc3b210U, 0xc8800e08U, 0x4c400304U, 0xb3600ed6U, 0x8ed0013dU, 0x402809eaU, 0x200c05d4U, 0xf03600bdU, 0x381103a8U, 0x54028474U, 0x222fc9cfU, 0xc30765b1U, 0x438fb279U, 0xa3d60d9eU, 0x86810c1bU, 0xf94a850cU, 0x11f3c1d1U, 0xad9961eaU, 0x26d2b9d4U, 0xfc0286bdU, 0x9e2fcea8U, 0x7d0768f4U, 0xce8fbf0fU, 0x55560ad1U, 0x87c10069U, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0x8000000U, 0xac000000U, 0x12000000U, 0x93000000U, 0x39800000U, 0x97400000U, 0x82e00000U, 0x47b00000U, 0x36480000U, 0x38640000U, 0x916e0000U, 0x87c10000U, 0x431b8000U, 0x61b64000U, 0x2347a000U, 0x44fa3000U, 0x62bc2800U, 0x22fc7400U, 0x17b38e00U, 0x2e624300U, 0xec61a680U, 0x275f3dc0U, 0xaac9a9a0U, 0xfb8b37f0U, 0x5c6facb8U, 0xf6e3344U, 0x16fa2536U, 0x91a974cfU, 0x6b6e04eaU, 0x88c1070dU, 0x9b8e4aU, 0xb9f6467eU, 0x8227a731U, 0xab0a3098U, 0xfd9427f7U, 0x596871edU, 0xbf58bdbU, 0x41374395U, 0x8abc27bdU, 0xbefc7493U, 0x6db38a6aU, 0x61624ecdU, 0xcfe1a9eaU, 0x8f1f328eU, 0x3a9ad09U, 0xb87b3e1cU, 0xd147ab61U, 0xe7fa32d2U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0x28000000U, 0x4000000U, 0xee000000U, 0xd3000000U, 0xe3800000U, 0xfa400000U, 0x65e00000U, 0x9d900000U, 0xa1680000U, 0x324c0000U, 0x71ee0000U, 0x3b830000U, 0xa6668000U, 0x17c94000U, 0x5ca32000U, 0x53def000U, 0x12a5a800U, 0x30c7bc00U, 0x90e8e00U, 0xe6854100U, 0x86cd2480U, 0x461dfd40U, 0x17232460U, 0x6d9ef170U, 0xf945aed8U, 0xae57b394U, 0x63e684e6U, 0x2a89473dU, 0x7cc32628U, 0x330efa8dU, 0xf3ada750U, 0xb25bbe48U, 0xb1e885feU, 0x5b9a4889U, 0x764da95cU, 0x3fcbbc58U, 0x58808bd6U, 0xbdd64e04U, 0xc1a3a00cU, 0xd348b310U, 0xf36602a8U, 0x835f07cdU, 0x1b608330U, 0xe7464f38U, 0x254bab26U, 0x1c44bb1dU, 0xc2e80dbaU, 0x80c0b65U, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0x68000000U, 0x4c000000U, 0x6000000U, 0xf3000000U, 0x25800000U, 0xd2c00000U, 0x51600000U, 0xb00000U, 0x2c480000U, 0x8a2c0000U, 0xd51e0000U, 0xe6910000U, 0xcf468000U, 0xa7874000U, 0x1bf6a000U, 0xd9c45000U, 0x70f82800U, 0xa86f1400U, 0xb0108e00U, 0x783a4100U, 0x442e2080U, 0x1a1211c0U, 0x9d280ee0U, 0x9a9c0ff0U, 0xf1560438U, 0x70bd071cU, 0x745881ceU, 0xfe1649e7U, 0xf73027b2U, 0x5f831799U, 0x1fee85cdU, 0xa3db4fe7U, 0xbdc0a2b3U, 0x5ac9511aU, 0xd68a10fU, 0xe955f86U, 0xc35ea581U, 0xc1985743U, 0xb8ce2a22U, 0x94621f91U, 0xee00030aU, 0xff000145U, 0x43800ae3U, 0x71c009f0U, 0x1ce00139U, 0x9e70019fU, 0x7b28050cU, 0x799c0986U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x70000000U, 0x8000000U, 0x4c000000U, 0xb6000000U, 0xf9000000U, 0xb2800000U, 0x93400000U, 0x87e00000U, 0x55900000U, 0xc4c80000U, 0x88040000U, 0x8c2e0000U, 0x56290000U, 0x89228000U, 0xba91c000U, 0xdf41e000U, 0x31c5f000U, 0xacab6800U, 0x76503c00U, 0x1b448600U, 0xbfccb00U, 0x3ad6e80U, 0x4ded33c0U, 0x328003e0U, 0x53400750U, 0x67e00e48U, 0x259001a4U, 0xccc803d6U, 0xc40408adU, 0x3a2e0f52U, 0xaf290249U, 0x3ba28fa6U, 0x29d1c4d6U, 0x58a1e82eU, 0x6455fb92U, 0x6863612aU, 0xfe543c35U, 0x976a89fcU, 0x5dd5ca1bU, 0x8a8fed6cU, 0xf77cffb3U, 0xedc1ef9aU, 0x6285f02dU, 0xcb4b6f90U, 0x53c03b2bU, 0xd78c8134U, 0xcff8c47fU, 0x39836b5aU, 0xe2c43b4eU, 0x80000000U, 0x40000000U, 0x20000000U, 0x90000000U, 0x8000000U, 0x64000000U, 0xda000000U, 0xc5000000U, 0x8b800000U, 0x66c00000U, 0x9f600000U, 0x88b00000U, 0x6e580000U, 0xb10c0000U, 0x19b60000U, 0xe7d30000U, 0x5eeb8000U, 0x2375c000U, 0x1eb2a000U, 0x8571d000U, 0x2d812800U, 0x55c81400U, 0x4fe58a00U, 0xeadacd00U, 0xd1572280U, 0x2fab1f40U, 0xdcd60520U, 0xea630e10U, 0x9b338718U, 0x64b9c33cU, 0x9064a1ceU, 0x8e12d8a7U, 0xc732aab3U, 0x2b1dbcbU, 0xc36125c6U, 0xeeb81e01U, 0x3d5d8703U, 0xd1a6cf81U, 0xe3d92dc0U, 0x34c41260U, 0x7e538f30U, 0xf909cb0aU, 0x5dbcad26U, 0xadded271U, 0x93e4a72bU, 0xccd2d3b7U, 0xa252ab28U, 0xdf01d5b6U, 0x2eb92028U, 0x5d741c36U, 0x618b86e8U, 0x7bc5c7d6U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xf0000000U, 0xb8000000U, 0xe4000000U, 0x76000000U, 0x87000000U, 0x5f800000U, 0x12c00000U, 0xf3600000U, 0xfa900000U, 0xe4780000U, 0xd140000U, 0x7aa20000U, 0x245f0000U, 0x2d388000U, 0x8aa24000U, 0x9c472000U, 0xc912d000U, 0xfc87a800U, 0x1b649c00U, 0x96828a00U, 0xee794300U, 0xe825a980U, 0x6c3b9140U, 0xa3a04e0U, 0xe51b0a30U, 0x16828098U, 0x2e79465cU, 0xc825a14eU, 0x9c3b90c5U, 0xb23a0e11U, 0x11b0b08U, 0x60828e15U, 0xa9794cb8U, 0x97a5a1cfU, 0x8efb9b06U, 0x415a0a30U, 0xfb8b009aU, 0x84fa865eU, 0xa46d414eU, 0xed07a0c5U, 0xaaa49612U, 0x6c628f09U, 0x71294014U, 0x18bda1bbU, 0x6d7f954dU, 0x118006c6U, 0xb1c00712U, 0xfae0018bU, 0x9f5006d7U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xf0000000U, 0xe8000000U, 0x54000000U, 0x4e000000U, 0xfd000000U, 0xbf800000U, 0x57400000U, 0x32e00000U, 0x36b00000U, 0x16f80000U, 0xd0b40000U, 0x1fd60000U, 0xd1270000U, 0x5daa8000U, 0x87ec000U, 0x7259a000U, 0xd163b000U, 0x2beb2800U, 0x8f197400U, 0x189c8200U, 0xfbe9cb00U, 0xd70b2480U, 0x4a97a40U, 0x11e48260U, 0x8c1dce90U, 0x123d2518U, 0xb73e75a4U, 0x14b60e56U, 0xa9d7075fU, 0xc0328ca1U, 0xe03aceb0U, 0x5017a5eaU, 0x1800b02dU, 0xbc0fabe9U, 0x1a04b52eU, 0xb321aa68U, 0x4297beeeU, 0xe8dd2bc8U, 0x658e75deU, 0x44e0fe2U, 0x20630b53U, 0xc66481b9U, 0xcf5dcf14U, 0xcedd29bcU, 0x8c8e7c72U, 0x55ce03c8U, 0x7a2301deU, 0xa3048de2U, 0xfaadc053U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0x98000000U, 0xb4000000U, 0x7a000000U, 0x97000000U, 0x63800000U, 0xf5400000U, 0x70e00000U, 0xd4900000U, 0x66e80000U, 0x2dac0000U, 0xd8420000U, 0xe4730000U, 0x12778000U, 0x7b554000U, 0x3dcc2000U, 0x10013000U, 0x3833a800U, 0x84287c00U, 0xb2358e00U, 0xbb264900U, 0xadbbaf80U, 0x18547e40U, 0x847f8620U, 0x42694e30U, 0xe3662798U, 0x89de3324U, 0x6a0620b6U, 0xaf0e355dU, 0xe78e28c0U, 0x47723fe3U, 0xcbc42a52U, 0x793d3189U, 0x7e99ab8dU, 0xa9f77f8bU, 0x9a00028dU, 0x700000bU, 0x9b8004cdU, 0x11400228U, 0x92e000ffU, 0xf79006b2U, 0x7f680f58U, 0x4fec0cc7U, 0xcb220ae4U, 0xc5a304d4U, 0x47f834dU, 0x82694068U, 0x836628dfU, 0xd9de3182U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0x48000000U, 0xf4000000U, 0xd6000000U, 0x8d000000U, 0x46800000U, 0x400000U, 0x3be00000U, 0x25100000U, 0x2980000U, 0xee5c0000U, 0xdac60000U, 0x9bf0000U, 0xadd08000U, 0xc82ac000U, 0x3424e000U, 0x7616b000U, 0x5d326800U, 0xe837c00U, 0xf4460200U, 0xedff0100U, 0xa8308e80U, 0x443ac240U, 0xee3ce9e0U, 0xe10ab790U, 0x2c946108U, 0xaf6c74d4U, 0x266e85d6U, 0xeed9c355U, 0x7faa6d17U, 0xf0df7ef4U, 0xc6800c65U, 0xc04005eeU, 0x9be00479U, 0xf51009cdU, 0x4a980ac9U, 0x1a5c06f6U, 0xcc60866U, 0x84bf03edU, 0xeb50837aU, 0xc86ac04dU, 0xfc4e108U, 0x5306b4d4U, 0x5faa65d6U, 0xe0df7355U, 0x2e800517U, 0xe44002f4U, 0x5e00e65U, 0x8c1004eeU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0xd8000000U, 0x64000000U, 0xaa000000U, 0x69000000U, 0x9a800000U, 0xf4c00000U, 0x9f600000U, 0x75100000U, 0x24b80000U, 0xcfe40000U, 0xb8fa0000U, 0x697f0000U, 0x422b8000U, 0x1524c000U, 0x74aee000U, 0x87d89000U, 0xb4ff6800U, 0x7f435c00U, 0xe51a0a00U, 0x4caf0700U, 0x73f38f80U, 0x76d0cd40U, 0xaa6ce720U, 0xb18390d0U, 0x7b4eeb08U, 0x1f0895dcU, 0x6da76a5eU, 0xe5775f1dU, 0x94380c3dU, 0x92240aefU, 0x9d1a0ce4U, 0x58af01b9U, 0x21f38125U, 0xcbd0c859U, 0x42ece996U, 0x484397a2U, 0xd4aee610U, 0xf7d8976aU, 0x4cff6f2cU, 0xab435906U, 0x971a0308U, 0x41af09dcU, 0x4373805eU, 0xeb10c81dU, 0xaf8cebbdU, 0x30539bafU, 0xc096e1c4U, 0xa5fc9669U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xb0000000U, 0x98000000U, 0x1c000000U, 0xe6000000U, 0xdf000000U, 0xae800000U, 0xac00000U, 0x7f600000U, 0xe1100000U, 0xcda80000U, 0x92740000U, 0x82aa0000U, 0xb4d10000U, 0xdc468000U, 0x19b24000U, 0x80526000U, 0x5fba1000U, 0x8f5ee800U, 0xd9095c00U, 0x1820e00U, 0x5c650700U, 0xd98c8f80U, 0xe0734ac0U, 0xefbce7e0U, 0x177c5c30U, 0xc5268c88U, 0xe7a2415cU, 0x837a6b1eU, 0x770e15bdU, 0xea94eaacU, 0x90c85af6U, 0xf66c8490U, 0x8a3489aU, 0x75f4e086U, 0x1d850baU, 0xc3c48dd7U, 0x36d74a41U, 0x895eeea2U, 0x76095710U, 0x57020c59U, 0xfaa50066U, 0xd8ec8308U, 0xc2634b9cU, 0x6a94ecfeU, 0x50c8598dU, 0x966c8e24U, 0xb8a347aaU, 0xedf4e18eU, 0x1dd85a27U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x90000000U, 0xa8000000U, 0x9c000000U, 0xf6000000U, 0x15000000U, 0x89800000U, 0xe7c00000U, 0x75600000U, 0x9a300000U, 0x9b280000U, 0x489c0000U, 0x944e0000U, 0xd9ad0000U, 0xefca8000U, 0x9960c000U, 0x54332000U, 0xba199000U, 0xab1fa800U, 0x90885400U, 0x30480600U, 0x1bac0d00U, 0x90e60480U, 0xf3f100c0U, 0x2f6485e0U, 0xa13dc890U, 0xa3b1a7f8U, 0xe4d55f2cU, 0x79ca87ceU, 0x5c60c3dfU, 0x95b320e4U, 0x51d9942aU, 0x807fa276U, 0x83b854d3U, 0xd4e00ed8U, 0xa1f0085cU, 0xf84807a7U, 0x57ac0c8bU, 0x2ee60d44U, 0xeaf1039aU, 0xf8e487ffU, 0xcffdc317U, 0xa951ac80U, 0x8c2554c0U, 0x1e0283e0U, 0x690cc590U, 0xefb52378U, 0x5ad89fecU, 0x60d3222eU, 0x8be99b4fU, 0x80000000U, 0x40000000U, 0xe0000000U, 0xd0000000U, 0x78000000U, 0xa4000000U, 0x5e000000U, 0xf3000000U, 0x97800000U, 0x6d400000U, 0x4be00000U, 0x18300000U, 0x34280000U, 0xc60c0000U, 0x872a0000U, 0xb1b70000U, 0x3a7e8000U, 0x824b4000U, 0x86692000U, 0xe876b000U, 0xb375a800U, 0xf8f6f400U, 0x6f800600U, 0x89400900U, 0xf5e00980U, 0x3b300740U, 0xdba80260U, 0xf4c0570U, 0x92ca0c98U, 0x5a8709e4U, 0x99d68dc6U, 0x29074757U, 0x4aa327fcU, 0x41f1bde3U, 0xbd232330U, 0xbcb1b37bU, 0x6ec32dd5U, 0xd081ba3fU, 0x7ceb2a41U, 0x418db5e3U, 0x32412731U, 0x6e7abd78U, 0xd45fa0d7U, 0x9941fdbfU, 0x2dfe8000U, 0xaf0b4000U, 0x2d892000U, 0x2046b000U, 0xff5da800U, 0x9afaf400U, 0xb6aa0600U, 0xcbf70900U, 0x80000000U, 0x40000000U, 0x20000000U, 0x70000000U, 0x38000000U, 0xc000000U, 0x1e000000U, 0x63000000U, 0xcc800000U, 0xb3c00000U, 0xc6600000U, 0xb0300000U, 0x58180000U, 0x5c140000U, 0x56120000U, 0x570d0000U, 0xde848000U, 0xcedf4000U, 0x69cbe000U, 0xcf6fd000U, 0x2da56800U, 0x2a599400U, 0xbe000a00U, 0x53000300U, 0xd4800180U, 0xcfc007c0U, 0xe0600260U, 0xdf3006f0U, 0x8a980d28U, 0x8cd40d0cU, 0x5cf200aeU, 0x54fd003fU, 0x40fc89e7U, 0x22fb4ec2U, 0x67c1e0e0U, 0xc476d0b1U, 0xa533e089U, 0xb38bdd9dU, 0x94f6174U, 0x52b0931bU, 0x90ee8dc6U, 0x2af64d93U, 0x73c5695aU, 0xa6699665U, 0xe0180000U, 0x10140000U, 0x68120000U, 0x440d0000U, 0x2a048000U, 0x711f4000U, 0xb1abe000U, 0x1c5fd000U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xf0000000U, 0xd8000000U, 0xc4000000U, 0xe2000000U, 0x7b000000U, 0x38800000U, 0x10c00000U, 0x3aa00000U, 0xe0100000U, 0x30180000U, 0xb80c0000U, 0x341e0000U, 0x3a1b0000U, 0xbf188000U, 0xda9c4000U, 0x6bcf6000U, 0x2271000U, 0xf0d21800U, 0xabf5400U, 0x58000200U, 0x4000300U, 0x82000180U, 0x8b0003c0U, 0xe0800360U, 0xd4c00310U, 0xd8a00388U, 0x9b1001ecU, 0x89800e2U, 0xa8cc0043U, 0xebe00eaU, 0xda0b0380U, 0x8f0080c0U, 0x629042e0U, 0x5fd160d0U, 0x383c10e8U, 0x4fca9afcU, 0xd023176aU, 0x33cf63afU, 0x6271308U, 0x72d21a43U, 0x81bf57eaU, 0xb8800000U, 0xd0c00000U, 0x5aa00000U, 0x10100000U, 0xe8180000U, 0x7c0c0000U, 0xd61e0000U, 0x411b0000U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0x18000000U, 0x5c000000U, 0xae000000U, 0xa9000000U, 0x3b800000U, 0x78c00000U, 0x18e00000U, 0xb8100000U, 0xcc180000U, 0xe61c0000U, 0x5d160000U, 0xd1830000U, 0x23cb8000U, 0x2475c000U, 0x52452000U, 0x97bf7000U, 0x3e231800U, 0x31fd1c00U, 0x43800200U, 0x54c00300U, 0x4ee00380U, 0xfd1002c0U, 0x41980060U, 0x6bdc0170U, 0xd07602b8U, 0xb85302a4U, 0xccb380eeU, 0x2b9c1e3U, 0xdbab2063U, 0x183072e0U, 0x8ce69b30U, 0x2217df98U, 0x6f18a374U, 0x3689b046U, 0x14dbb0fU, 0x7f27ae51U, 0x6e7e3b29U, 0x995e6c2eU, 0xe3351bc0U, 0x207e1fa3U, 0x804b8000U, 0xc0b5c000U, 0x4a52000U, 0x36af7000U, 0xd1bb1800U, 0xf3211c00U, 0xa8760200U, 0x94530300U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xf0000000U, 0x38000000U, 0x44000000U, 0xda000000U, 0xe5000000U, 0x59800000U, 0x35400000U, 0x5ca00000U, 0x74100000U, 0x2080000U, 0xf1140000U, 0x4b9e0000U, 0xac470000U, 0x9b288000U, 0x7e4b4000U, 0xe234a000U, 0xe9cf3000U, 0x2070a800U, 0x75e89400U, 0xa6a00200U, 0x21100100U, 0xc3880280U, 0x705403c0U, 0xf53e00e0U, 0x79570110U, 0x1aa08368U, 0x5f1f4394U, 0xac8aa166U, 0x4d830d5U, 0xe5f02972U, 0x8ea7d5d0U, 0xd02a208U, 0x958c32c4U, 0x334e2baeU, 0xd7b0d571U, 0x2a82208cU, 0xcfc371e9U, 0x1b6c8a60U, 0xb36ce7f3U, 0xdf640b07U, 0x2977a512U, 0x9a78a800U, 0x80fc9400U, 0x973e0200U, 0x98570100U, 0x39208280U, 0x7f5f43c0U, 0x91aaa0e0U, 0x1883110U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xd0000000U, 0x58000000U, 0x44000000U, 0x32000000U, 0x87000000U, 0xc9800000U, 0x8b400000U, 0xb3200000U, 0xb4100000U, 0xfa080000U, 0x3b140000U, 0x6f9a0000U, 0x664b0000U, 0xb9a88000U, 0xc4d64000U, 0x4578e000U, 0xf5bd3000U, 0xaad36800U, 0x14616400U, 0x59200200U, 0x37100100U, 0xa1880280U, 0xe7540340U, 0x4d3a0160U, 0x1d1b0110U, 0xc28080c8U, 0xccd2421cU, 0x196ae326U, 0x23a2322dU, 0xcfc1eaccU, 0x2ec26d0U, 0x5ff861e8U, 0x3d6f71ecU, 0x21b98b3eU, 0x60c356d9U, 0x761e986U, 0xfabc2703U, 0x7f50615dU, 0xe92b738aU, 0x5f0b8a6dU, 0xcd8c542cU, 0x195b6800U, 0xe4356400U, 0x259a0200U, 0x354b0100U, 0xba288280U, 0x5c964340U, 0x55d8e160U, 0x9ed3110U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0x8000000U, 0xf4000000U, 0x86000000U, 0xd7000000U, 0x5e800000U, 0xec400000U, 0x9b600000U, 0xe6100000U, 0x27180000U, 0x66840000U, 0x420000U, 0xe1610000U, 0x430e8000U, 0x2888c000U, 0x35ee000U, 0x29e9d000U, 0x704c8800U, 0x1975ec00U, 0x8f180200U, 0x42840300U, 0xae420080U, 0xd2610040U, 0x938e8020U, 0xe7c8c3d0U, 0x40bee218U, 0xf4b9d35cU, 0x92b4897aU, 0x75a1efb1U, 0x3322006dU, 0x23710098U, 0xca16801cU, 0x7d0cc1daU, 0xd39ce021U, 0x7c8d055U, 0x70a20b14U, 0xecad2ffeU, 0x6ebee377U, 0x7b9d016U, 0x62348b2cU, 0xaae1efbdU, 0x78c20080U, 0xa210040U, 0xaeee8020U, 0xc6d8c3d0U, 0x3126e218U, 0x8a7dd35cU, 0x8f96897aU, 0xa5d0efb1U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xd0000000U, 0x88000000U, 0x84000000U, 0x12000000U, 0xdd000000U, 0xd6800000U, 0x36400000U, 0xd1e00000U, 0x56100000U, 0x6f080000U, 0x3b9c0000U, 0xb8da0000U, 0xebb10000U, 0x11e08000U, 0xf61a4000U, 0x5f0fa000U, 0x639cd000U, 0xb4cdc800U, 0x7dbbbc00U, 0xdee80200U, 0xfd8c0100U, 0xbfd20380U, 0x842d0340U, 0x333a8220U, 0x44ab4210U, 0x8a6f2048U, 0x7ec69374U, 0xeca26b5aU, 0x7e776cd9U, 0xd4cdc947U, 0xedbbbc58U, 0xb6e8003cU, 0xa98c02aeU, 0x25d20343U, 0xdd2d02feU, 0xf7ba822fU, 0xafeb42bcU, 0x8d0f226eU, 0x1e969223U, 0x524a6aceU, 0x13fb6c77U, 0x31fcb80U, 0x3d96bf40U, 0x1fd28020U, 0xb4274310U, 0x6b3d23c8U, 0x48ab9034U, 0x1c78e97aU, 0xb1cc2ec9U, 0x80000000U, 0x40000000U, 0x60000000U, 0xb0000000U, 0xd8000000U, 0xc000000U, 0x1e000000U, 0x5d000000U, 0x2e800000U, 0xd8400000U, 0x83200000U, 0xf2100000U, 0xb3080000U, 0xcb8c0000U, 0x4ad60000U, 0x9d7b0000U, 0x20318000U, 0x719bc000U, 0xfdcfa000U, 0x2cffd000U, 0xfde60800U, 0x8d72e400U, 0x68280200U, 0x759c0100U, 0x87de0180U, 0xbbf702c0U, 0x9c678360U, 0x38a0c030U, 0x40de2078U, 0xf2741174U, 0x9da1a8baU, 0xb2413761U, 0x5c38080cU, 0x9785e6c8U, 0x7ccf814cU, 0x747cc0eeU, 0xaca023cbU, 0x32d31085U, 0x16e2b98U, 0x363df482U, 0x48982935U, 0x1956f7a6U, 0xbba1aac1U, 0x1341355cU, 0xd4b80980U, 0xaec5e6c0U, 0x176f8160U, 0xf2cc130U, 0xac0821f8U, 0x8e0f13b4U, 0x55102bdaU, 0x4a9af751U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x70000000U, 0xc8000000U, 0xa4000000U, 0xf2000000U, 0x23000000U, 0xba800000U, 0x5ec00000U, 0xc1600000U, 0x1e100000U, 0xb5180000U, 0x8b9c0000U, 0xb74e0000U, 0xed390000U, 0x25a48000U, 0x98764000U, 0x3906000U, 0x335d5000U, 0x8f20d800U, 0xbeabac00U, 0x4ef80200U, 0xb4c0300U, 0x23360380U, 0x8b501c0U, 0xeff28320U, 0x5ad34290U, 0x637ae3c8U, 0x6512108cU, 0x13943aeaU, 0x4b40bd7bU, 0x328b905U, 0x98aaff78U, 0x57f6db54U, 0x36ceaceeU, 0x3572807dU, 0xb41343e4U, 0x8a1ae3feU, 0xaf0211bdU, 0x9c8c3a0cU, 0x47dcbfaaU, 0xfce6ba1bU, 0x853fc75U, 0x9b25b80U, 0xee68edc0U, 0x429ae120U, 0x12c21190U, 0x76c3848U, 0x770cbd4cU, 0x409ebbcaU, 0x39dffcebU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0x58000000U, 0x8c000000U, 0x5a000000U, 0xcd000000U, 0x78800000U, 0x2400000U, 0x7600000U, 0x5e100000U, 0xe3180000U, 0x938c0000U, 0x25d20000U, 0x64ab0000U, 0xf5a18000U, 0x2f234000U, 0x9c7da000U, 0x71991000U, 0x34cd4800U, 0x7e246c00U, 0x26f80200U, 0x52dc0300U, 0x812a0180U, 0xb7770240U, 0x360b8160U, 0xc7144230U, 0x8d962168U, 0x66dd5334U, 0x72369e2U, 0x18653c09U, 0x9f916a1dU, 0xbfde3e78U, 0xc9a8e80cU, 0x1d317f0eU, 0x75674a77U, 0x17136ee2U, 0x7593805eU, 0x1ad840f8U, 0x9524221bU, 0x166528bU, 0x311ae924U, 0x2a8a7d8dU, 0x7b5ec980U, 0x39fc2e40U, 0x935c2360U, 0xddfa5130U, 0xed50e8e8U, 0xeed7d74U, 0xd6cd4a82U, 0x6f246d39U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x70000000U, 0x18000000U, 0xcc000000U, 0xe000000U, 0xb1000000U, 0x1a800000U, 0xf3c00000U, 0xb200000U, 0x61100000U, 0xb2980000U, 0x7c40000U, 0xb92e0000U, 0xc6130000U, 0xd5018000U, 0xe085c000U, 0xf0d82000U, 0xb6a05000U, 0xf557f800U, 0x5ef8a400U, 0x2f2e0200U, 0x7b130300U, 0xe1818080U, 0xd245c1c0U, 0xf9782060U, 0xe8705330U, 0x42eff838U, 0x892ca6c4U, 0x3e18026aU, 0x490400cfU, 0x868e00acU, 0x95c30044U, 0x6e3982aaU, 0xb991c32fU, 0xfe4e22dcU, 0xa76751dcU, 0x31607b3eU, 0x8c6a644dU, 0xb8f9a1efU, 0x8a35905eU, 0x8397d99fU, 0xdd5cf4a4U, 0x6af7f838U, 0xbd28a6c4U, 0xac16026aU, 0x9e0700cfU, 0xf91780acU, 0xbe82c044U, 0x29cfa2aaU, 0x7822932fU, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0xd8000000U, 0x4000000U, 0xe2000000U, 0xe7000000U, 0x95800000U, 0xbdc00000U, 0x6ba00000U, 0xdf100000U, 0x81880000U, 0xe7cc0000U, 0xd8aa0000U, 0x708b0000U, 0xdf488000U, 0xfbf04000U, 0x5d66e000U, 0xf31b000U, 0x5a433800U, 0xc97f3400U, 0x152a0200U, 0x894b0100U, 0x36e88180U, 0x93e04140U, 0x916ee360U, 0x513db010U, 0xb493b88U, 0x81e4379cU, 0xde6a8056U, 0x28b743f7U, 0xd884602eU, 0x334af23cU, 0x95ed5966U, 0x847ec78fU, 0x9bafdaeaU, 0x7715875eU, 0x6d89baabU, 0x89d87558U, 0x1a6603bU, 0xe40df310U, 0xf20fda07U, 0x5f058676U, 0xc181bb88U, 0x87d4779cU, 0x88ac6056U, 0xa896f3f7U, 0xdb4f582eU, 0x19f9c63cU, 0xba6d5b66U, 0x9abec68fU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xf0000000U, 0xc8000000U, 0x74000000U, 0xa000000U, 0xff000000U, 0x45800000U, 0xdec00000U, 0xfde00000U, 0xe7100000U, 0xa9980000U, 0xf8cc0000U, 0x44fe0000U, 0xeb890000U, 0xb3d68000U, 0x6b6d4000U, 0x3a51e000U, 0xc3a9b000U, 0x26a95800U, 0x6428fc00U, 0x237e0200U, 0x8e490300U, 0xa9b68180U, 0x29bd43c0U, 0xe9a9e320U, 0x89b5b1d0U, 0x79af5828U, 0xb1bdfffcU, 0xc5ae8316U, 0xcfb1407bU, 0x30b7e277U, 0x752cb05cU, 0xabe1d986U, 0x561cbe33U, 0xb101633bU, 0x1891f352U, 0xe0483a59U, 0xa4a90d16U, 0x4f2e3a3eU, 0xfcec0e42U, 0x9786b994U, 0xadc84d4fU, 0x6e61d828U, 0x48dcbffcU, 0x2ce16316U, 0xf81f07bU, 0x81d03a77U, 0x28650c5cU, 0x1d03b86U, 0xe8650d33U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0x68000000U, 0x24000000U, 0xda000000U, 0xc1000000U, 0xd1800000U, 0x17c00000U, 0x2200000U, 0x75100000U, 0xa3980000U, 0xd2c40000U, 0x19a20000U, 0xcbdd0000U, 0x543c8000U, 0x6a0f4000U, 0x79022000U, 0xbd933000U, 0xf9c47800U, 0x71360400U, 0x41820200U, 0xbfcd0300U, 0x6248080U, 0xbf0b4040U, 0xa8021a0U, 0x275e3090U, 0xd460fb68U, 0x8fd4704U, 0xf0a22146U, 0xde43335fU, 0xa9fc7888U, 0xd1220594U, 0x9198012eU, 0xf7c400dbU, 0x3222038eU, 0xd1d006bU, 0xef9c83b6U, 0x2cdf4167U, 0x2ba2284U, 0xdb473026U, 0x927e7a2fU, 0x7fef06d0U, 0xe3c8368U, 0x6b0f4304U, 0x88822346U, 0xba53305fU, 0x93e47808U, 0x202605d4U, 0x381a008eU, 0xac09004bU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x90000000U, 0x18000000U, 0x1c000000U, 0x3a000000U, 0x29000000U, 0x43800000U, 0xd1c00000U, 0x6c600000U, 0xad100000U, 0x25880000U, 0x22dc0000U, 0x96f20000U, 0x27530000U, 0x842b8000U, 0xd9ab4000U, 0x376f2000U, 0x638f7000U, 0xe1dfb800U, 0x467cc00U, 0x39120200U, 0x1b830100U, 0x2dc38380U, 0xc6674240U, 0x9c152060U, 0x7a007070U, 0xc90638e8U, 0xd39f8ca4U, 0xc9d6a30eU, 0x70673247U, 0x97131a31U, 0xc9ffcf4U, 0x61509af6U, 0x4738bdfbU, 0x4b25bb33U, 0x2928cf79U, 0xfc2b82feU, 0x15ab4311U, 0xf56f2264U, 0xc68f71aeU, 0x805fba97U, 0xe0a7cf09U, 0x2cf200e8U, 0x4e5300a4U, 0x27ab810eU, 0x986b4347U, 0x430f21b1U, 0xd29f72b4U, 0xfe57b896U, 0xfbbcc8bU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x90000000U, 0xc8000000U, 0xc4000000U, 0xf6000000U, 0xd9000000U, 0x38800000U, 0xe3400000U, 0x1ae00000U, 0x9f100000U, 0x19880000U, 0xa7dc0000U, 0x93b20000U, 0xa6e90000U, 0x55008000U, 0x4a8ac000U, 0x2c552000U, 0x6b6c1000U, 0x8ccde800U, 0x242d1c00U, 0xd43a0200U, 0xcc350100U, 0x20328380U, 0x8223c240U, 0x6535a320U, 0x40b6d310U, 0x6d70cbd8U, 0x4dcd0f64U, 0xf0adeae2U, 0x957d1e8dU, 0x31d201ebU, 0x9ab9013cU, 0xb66880c6U, 0xe246c3cfU, 0x6e6f22b6U, 0xae5912efU, 0xbc7f6a6eU, 0x114eddc3U, 0x95efa238U, 0xe93d15cU, 0x9a4a49beU, 0x5272ce33U, 0x244a4858U, 0xf72cd24U, 0xaca49c2U, 0xa532cd9dU, 0xe0aa4a33U, 0x1d62ce58U, 0x15c24a24U, 0xfcaecd42U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x30000000U, 0xb8000000U, 0x3c000000U, 0x56000000U, 0x85000000U, 0x6c800000U, 0x51c00000U, 0x70a00000U, 0xeb100000U, 0x95880000U, 0x8b5c0000U, 0x94660000U, 0x4f270000U, 0x135f8000U, 0x387ec000U, 0x713aa000U, 0x22449000U, 0x86eeb800U, 0xcfe95400U, 0xed6e0200U, 0xd5bb0100U, 0x17998380U, 0xac49c0c0U, 0x4fed22e0U, 0xad6650f0U, 0x35b21958U, 0x278ac614U, 0x145f3bb2U, 0x73ec9447U, 0xfb6d2042U, 0xb0a6526cU, 0x4b121b36U, 0x459ac61dU, 0x3573be9U, 0x107096d8U, 0x252b2127U, 0xc0515272U, 0xd1e598d4U, 0x4c680652U, 0x3239837U, 0x1d5f055aU, 0xb1741ad8U, 0xf3bdc6d4U, 0xca88b952U, 0xccce54b7U, 0xf031811aU, 0x64c5c078U, 0xe4232284U, 0x66cd535aU, 0x80000000U, 0x40000000U, 0x60000000U, 0x30000000U, 0x68000000U, 0xd4000000U, 0x7e000000U, 0x7b000000U, 0xee800000U, 0xb1c00000U, 0xad600000U, 0x51100000U, 0xab880000U, 0x444c0000U, 0xc2260000U, 0x25bd0000U, 0x83e28000U, 0xc0dbc000U, 0x56ed6000U, 0x4d4ad000U, 0xd5afb800U, 0xcbf1ec00U, 0x44ce0200U, 0x70e10100U, 0x8a4c8180U, 0x912ac0c0U, 0x7f29e1a0U, 0x7c2c1350U, 0x7ea059f8U, 0x3d60fdecU, 0x290cd9baU, 0x479a3fc7U, 0xb64d3935U, 0x7b2a2c84U, 0x1a23608eU, 0xd9abd381U, 0x49e33ad0U, 0xf5db2eeaU, 0xab67e3edU, 0xc60d1278U, 0xb70cd82cU, 0x4c9a3f9aU, 0x50cd3b57U, 0x2eea2fedU, 0xa1436078U, 0x27bbd12cU, 0x72eb3a1aU, 0x7b572d97U, 0x2aa1e14dU, 0x36011a8U, 0x32065894U, 0x991dff16U, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0x38000000U, 0x74000000U, 0x96000000U, 0x77000000U, 0x5a800000U, 0xef400000U, 0x1ee00000U, 0x35100000U, 0x6b880000U, 0x6acc0000U, 0x173e0000U, 0x1eb70000U, 0xd5768000U, 0x8fc6c000U, 0xd4b4e000U, 0xc86e5000U, 0x18526800U, 0x47c9c00U, 0xba560200U, 0x856b0100U, 0x67c08180U, 0x8bdc3c0U, 0xe27c60e0U, 0xb55f91d0U, 0xcbf00a58U, 0xee840ddcU, 0x59588b6aU, 0xf9e5cebdU, 0xa792ebfbU, 0xc8c15e14U, 0x962a62ceU, 0xc33492bbU, 0x58b08b64U, 0xa79cfb6U, 0x6944ea87U, 0xe1ea5c8eU, 0x438ae39bU, 0x96d95354U, 0xad24e9beU, 0x7bba5cc3U, 0x56e2e3d8U, 0x3905521cU, 0xe992e98aU, 0x7bc15e6dU, 0x2aa6023U, 0xdf749008U, 0xb2d08944U, 0xd329cdd6U, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0xd8000000U, 0x64000000U, 0xda000000U, 0x97000000U, 0x85800000U, 0x18c00000U, 0xb6a00000U, 0x59100000U, 0x70880000U, 0xfe440000U, 0x99f60000U, 0xdc6b0000U, 0xa4b48000U, 0x82074000U, 0xb308e000U, 0x7f99b000U, 0x3fc29800U, 0xeb3a1400U, 0x25de0200U, 0x1c3f0100U, 0x304a8080U, 0x6ce842c0U, 0x3aea6360U, 0x8be5f190U, 0x776fb68U, 0x6720e65cU, 0x3c27816U, 0x1527a563U, 0x48ca985aU, 0xbebe16a4U, 0x75080022U, 0xa68401a9U, 0xf5602efU, 0x357b027dU, 0xc3c808cU, 0x184341a7U, 0xf0fee168U, 0x34f2b2a5U, 0x1ef619f1U, 0x71fd5552U, 0x2076e3e8U, 0x3ab6b09cU, 0x7f001976U, 0x799655f3U, 0x86c263b2U, 0x4bb1f238U, 0x9388fb54U, 0x89cfe55aU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xf0000000U, 0x28000000U, 0x14000000U, 0x6a000000U, 0x91000000U, 0x5800000U, 0xb5400000U, 0xbba00000U, 0xa7100000U, 0xda980000U, 0x83dc0000U, 0x7e7e0000U, 0xee750000U, 0xf66a8000U, 0x2a794000U, 0xa4782000U, 0x776fb000U, 0xf7fb2800U, 0x2d37b400U, 0xb2c60200U, 0xabf90300U, 0x632c8380U, 0x81c043c0U, 0xdb74a0a0U, 0x91fff050U, 0xa3789a8U, 0xa8444644U, 0xc8378a16U, 0xed4445d5U, 0x47b78b6eU, 0x3904465cU, 0xd1978a4aU, 0x3f54469fU, 0xdaaf8971U, 0x8a98456dU, 0x7bc98b47U, 0x527144a8U, 0x487d08e1U, 0x316d0740U, 0xc0f7aac5U, 0xefa7f426U, 0xed0aa228U, 0x5b8af184U, 0x5e5d08b6U, 0xf73d0685U, 0x2bcfa946U, 0xaa6bf7d8U, 0x646ca2fcU, 0x9763f01aU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x10000000U, 0x48000000U, 0xac000000U, 0x8e000000U, 0xe5000000U, 0x4e800000U, 0x97c00000U, 0xe5600000U, 0x3e900000U, 0xfd80000U, 0xe17c0000U, 0xc920000U, 0x2cd10000U, 0xe6e98000U, 0x5bc3c000U, 0xbb6da000U, 0x73905000U, 0xfd593800U, 0xb0b50c00U, 0xa0e98200U, 0xd2c3c300U, 0x9beda380U, 0x11505040U, 0x1eb93920U, 0xb5e50eb0U, 0xc4518038U, 0xe82fc094U, 0xd627a2baU, 0x4b3d521fU, 0x11a2bab5U, 0xfc67ce4aU, 0x960da007U, 0x21005311U, 0x9c813a88U, 0xa4c90eacU, 0xaafb832eU, 0xc5d2c025U, 0x1664236aU, 0x9103919fU, 0xe48c9bddU, 0xb0c95e9eU, 0xd0fabab5U, 0x4adbce4aU, 0x9fffa007U, 0x23415311U, 0x3db0ba88U, 0xb276ceacU, 0x9304232eU, 0x7f939025U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0xc8000000U, 0x4000000U, 0xa000000U, 0x1b000000U, 0xeb800000U, 0x57400000U, 0xfe00000U, 0x63900000U, 0xf3580000U, 0xb5ec0000U, 0x608a0000U, 0xd4c10000U, 0xecac8000U, 0x7e6b4000U, 0x47d26000U, 0xa329f000U, 0x932da800U, 0x4b299c00U, 0xe72c8200U, 0x392b4300U, 0xe0326180U, 0x14b9f340U, 0xa275ab20U, 0xe1c59c10U, 0x66268228U, 0xa1aa436cU, 0xe8fee22eU, 0x5e02b21dU, 0x191fcb1fU, 0x94906d9eU, 0x66d929e5U, 0x8baeddbbU, 0x83f4e1acU, 0xcd83b24eU, 0x5253492dU, 0x5d6b2f27U, 0x10534bdaU, 0x826b2f27U, 0x91d34bc8U, 0x1e2b2f0eU, 0xbdb34b1fU, 0x2efb2d9eU, 0x4b0b49e5U, 0xe3872dbbU, 0x335949acU, 0xd5ea2e4eU, 0xb09fcb2dU, 0x1cd06c27U, 0x80000000U, 0x40000000U, 0x20000000U, 0x10000000U, 0xb8000000U, 0x94000000U, 0x12000000U, 0xdd000000U, 0x86800000U, 0xe0400000U, 0xd2a00000U, 0xb2900000U, 0xa2480000U, 0x97a40000U, 0xb0120000U, 0xe81f0000U, 0xc168000U, 0x96004000U, 0x770ca000U, 0xcf825000U, 0x74de4800U, 0xefe1f400U, 0xe6b68200U, 0xf0904100U, 0xe744a080U, 0x95265040U, 0xfa4c4ae0U, 0x73bef650U, 0x2a000248U, 0x9000274U, 0xb480029aU, 0x2d4003c1U, 0xec2001aaU, 0xc6d0009aU, 0x62e802c1U, 0xf834012aU, 0x94da00daU, 0x9ffb0021U, 0x6ea4837aU, 0xcc8f4092U, 0xd9522355U, 0xce261160U, 0xb3c0eb13U, 0xc87ca41fU, 0x9e7e49aaU, 0x8971f49aU, 0x76fe80c1U, 0xaa34402aU, 0x69d6a05aU, 0x9795061U, 0x36fac99aU, 0x8a2eb6c2U, 0x80000000U, 0x40000000U, 0x60000000U, 0x30000000U, 0xf8000000U, 0x74000000U, 0x66000000U, 0x13000000U, 0x9b800000U, 0x8a400000U, 0xf6200000U, 0x5f900000U, 0x54480000U, 0xf12c0000U, 0x92160000U, 0x35170000U, 0xe8828000U, 0x21cac000U, 0x847d6000U, 0xddadf000U, 0x6dc58800U, 0xb678a400U, 0xf8a28200U, 0x2d5ac100U, 0x2bb56180U, 0x96c1f0c0U, 0xf1f38be0U, 0xa8ffa5d0U, 0x22680398U, 0xeebc014cU, 0xa65e03eeU, 0xf43b02e9U, 0x82948038U, 0x60ddc0aeU, 0xaffe0c9U, 0xef673388U, 0x7238e826U, 0xe19556fdU, 0x63470a7aU, 0xc4b264f9U, 0x875fe0c0U, 0x4ab73172U, 0x4850e99fU, 0xb29571dU, 0x3b190838U, 0x678964aeU, 0x4b62c9U, 0xc72af288U, 0x490f09a6U, 0x229e663dU, 0x70c9e19aU, 0xa2e03129U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x50000000U, 0x28000000U, 0xdc000000U, 0x22000000U, 0x27000000U, 0xed800000U, 0xa7c00000U, 0xbf200000U, 0x9900000U, 0x51d80000U, 0xd63c0000U, 0x991a0000U, 0xc89d0000U, 0xdd478000U, 0x8d6e4000U, 0xe571e000U, 0x196e3000U, 0x8b64b800U, 0xd46d0400U, 0xcde78200U, 0x943e4300U, 0x2e09e380U, 0xed023140U, 0xf686b8a0U, 0x385c0770U, 0x17e20288U, 0x8731039cU, 0xdd858036U, 0x1fcf43dfU, 0xab2c625cU, 0xa79d7356U, 0x7cd2d9cfU, 0xc0ad77c4U, 0xf152dbd2U, 0xf76d76bdU, 0x8672d809U, 0x72fd7453U, 0xddaadbf2U, 0x5fc1760dU, 0x8b30d9e1U, 0x179c75dfU, 0x4d75a5cU, 0x34a23756U, 0xf5ebbcfU, 0xf26004c4U, 0x4cf80052U, 0x38ac03fdU, 0xc54202a9U, 0xe9610023U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x10000000U, 0x8000000U, 0x8c000000U, 0x5e000000U, 0x1b000000U, 0xda800000U, 0x62c00000U, 0xcc600000U, 0x2e900000U, 0xe8c80000U, 0xed7c0000U, 0x2d120000U, 0x1d890000U, 0xe4d8000U, 0x29a9c000U, 0x6e726000U, 0x3392d000U, 0x4d539800U, 0x9724ec00U, 0xcead8200U, 0xb2f9c100U, 0x2e5a6380U, 0x99bed040U, 0x96699820U, 0xa781ee30U, 0x975a0378U, 0x5e35016cU, 0x513f80eaU, 0x11b0c1cbU, 0x5a77e311U, 0x1987128aU, 0x9c53fadbU, 0x8caf3fd9U, 0xbffb99deU, 0x83c8ecfdU, 0x6ff78288U, 0x2bccc15cU, 0x13e5e1baU, 0x6dce110bU, 0x8cfe78d9U, 0x6556fc76U, 0xab21fb11U, 0x68b63e8aU, 0x3dfe18dbU, 0x2edd2ed9U, 0x3277e25eU, 0xc58710bdU, 0x2a53f8a8U, 0xbaf3e6cU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x30000000U, 0x68000000U, 0x5c000000U, 0x56000000U, 0x87000000U, 0xa3800000U, 0x22c00000U, 0x30a00000U, 0x95900000U, 0xd5c80000U, 0x1b3c0000U, 0xdb560000U, 0xdb650000U, 0x55a78000U, 0xfb14c000U, 0x6589e000U, 0x1dc5f000U, 0x97259800U, 0xd5407400U, 0x686f8200U, 0xfc28c100U, 0x8dfe380U, 0x71a0f0c0U, 0x90219a0U, 0x5094b570U, 0x6b466358U, 0xf37d331cU, 0xe9b2790eU, 0x9d1c844bU, 0x8a9b9b62U, 0xe2497626U, 0xe3f6038fU, 0x62f503b0U, 0x5e6f83c3U, 0xb28c256U, 0x235fe16cU, 0x3f60f2d6U, 0x7a21917U, 0x1e04b68cU, 0x4b0e617dU, 0x4d8133e5U, 0xa1c478e2U, 0xf12986e6U, 0x3a541a2fU, 0x97f1b6c0U, 0x88e1e09bU, 0xbf69f14aU, 0x47bb9862U, 0xfe19769dU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0x48000000U, 0x64000000U, 0xb6000000U, 0x19000000U, 0xd6800000U, 0x36c00000U, 0x40200000U, 0xd0900000U, 0xa7d80000U, 0x12bc0000U, 0x60560000U, 0xb6f10000U, 0x70a08000U, 0x4758c000U, 0xfd6e2000U, 0x16fc5000U, 0x60b71800U, 0xdf5aa400U, 0xe1788200U, 0x8ce4c300U, 0xabb82380U, 0xa6cd50c0U, 0x18379920U, 0x2c926590U, 0xdcea0d8U, 0x91a49364U, 0x7dd938daU, 0xf9a6f41bU, 0xc9cf9a20U, 0x37be65d2U, 0xfcc0a1c7U, 0x332993eeU, 0x650fb87bU, 0xbc9f3750U, 0x55d9393aU, 0x6da6f4abU, 0xd7cf9968U, 0x7abe676eU, 0xd440a2f9U, 0x78e9906fU, 0x45afb9a0U, 0x43cf3512U, 0x64a138e7U, 0x994af67eU, 0x506198a3U, 0xe636434U, 0x636e21e0U, 0x9bfc50b0U, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0x68000000U, 0x74000000U, 0xee000000U, 0xc9000000U, 0x8a800000U, 0x27400000U, 0xff600000U, 0x8c900000U, 0xda480000U, 0xfbec0000U, 0x32da0000U, 0xc7a50000U, 0x24328000U, 0xf9efc000U, 0x79c02000U, 0x4631d000U, 0xe2e22800U, 0x90574c00U, 0xf4fa8200U, 0x6543c100U, 0xd47a2180U, 0x5d04d140U, 0x7498a9a0U, 0xe6548dd0U, 0x51e0a1b8U, 0x2dd71224U, 0x982a8baaU, 0x13fc5dddU, 0x6c2085dU, 0x49b69ee2U, 0xbd30ab51U, 0x1b688c8bU, 0x2a92a0c1U, 0x574e1213U, 0xa76a08f5U, 0xc08a9e61U, 0x2842a8bcU, 0xa8f18d9eU, 0x9f5222afU, 0xa378d094U, 0x768aa9ddU, 0xad5d8fa2U, 0xd06822f1U, 0xeb0dd15bU, 0xf1902979U, 0x9ece4c37U, 0x25ba015fU, 0x7f3502bcU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x30000000U, 0xe8000000U, 0xe4000000U, 0x1a000000U, 0x11000000U, 0x53800000U, 0xb8c00000U, 0x80e00000U, 0xd1900000U, 0xc5d80000U, 0xbd740000U, 0xba560000U, 0xba50000U, 0x79b88000U, 0x4cad4000U, 0xa5232000U, 0x3cecf000U, 0x7935800U, 0x8ad9bc00U, 0xd5e08200U, 0xa8194300U, 0x84152280U, 0x8a19f0c0U, 0xc913dba0U, 0x5f90ff90U, 0x46cda268U, 0x8be4b344U, 0x9308fbceU, 0x2e980e23U, 0x8550fba3U, 0xeb2c0fd6U, 0x1fe6fbffU, 0x1190d71U, 0x4b867887U, 0x14c04e9dU, 0x4ef358adU, 0x3289be60U, 0x63588385U, 0x4c3d40f1U, 0x937b20f2U, 0x958f0b4U, 0xd5255923U, 0xb4ecbf16U, 0x7380005fU, 0x48c002e1U, 0xc8e002efU, 0x59001d9U, 0x37d80163U, 0x48740343U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0xe8000000U, 0x54000000U, 0xbe000000U, 0x1b000000U, 0x7f800000U, 0xa9c00000U, 0xbf600000U, 0x3d900000U, 0xf8d80000U, 0x55ec0000U, 0x48da0000U, 0x2de50000U, 0x94d68000U, 0x97e5c000U, 0xd9c26000U, 0xa7777000U, 0xb183f800U, 0xaacc0c00U, 0x4cee8200U, 0xc659c300U, 0x5ea06180U, 0xe6ee7140U, 0xc3577ba0U, 0xa20cd50U, 0x88a060f8U, 0x69ee736cU, 0x62d7787eU, 0xe8e0cfe7U, 0xa040635dU, 0xa9be72a6U, 0x9b6f789bU, 0x9b9ccc7bU, 0x6fc2617dU, 0x78777040U, 0xf803fbd6U, 0x1c0c0f85U, 0xda0e80daU, 0x1d09c33dU, 0xd8986260U, 0x3c5273c6U, 0xb3b57addU, 0xe679cfe6U, 0x1314e13bU, 0xbb92b22bU, 0x9fc19805U, 0xa07b7e6cU, 0x140d7a08U, 0x1e05ce32U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xf0000000U, 0x48000000U, 0x14000000U, 0x2a000000U, 0x47000000U, 0x1e800000U, 0xf0400000U, 0x96200000U, 0x8900000U, 0xb9580000U, 0x4dbc0000U, 0x454e0000U, 0xa3b10000U, 0x704e8000U, 0x56234000U, 0xe88de000U, 0x49475000U, 0x5ae4800U, 0x5156a400U, 0x89b68200U, 0x374f4300U, 0x48bbe380U, 0x18da53c0U, 0xdf76c920U, 0xd38e450U, 0xe81be2a8U, 0xc40a521cU, 0x720ecbfaU, 0xeb14e401U, 0x688de178U, 0x89475372U, 0xe5ae49cdU, 0xa156a7eaU, 0xc1b6824fU, 0x234f421fU, 0x62bbe0b1U, 0x5fda53a6U, 0xc1f6c81dU, 0xfd78e782U, 0x7e3be1f3U, 0xcc9a51f5U, 0xcb56caf8U, 0xa6a8e4b2U, 0x2dc3e2edU, 0x2af650baU, 0x95e0cb67U, 0xf775e7c3U, 0x293b606bU, 0x6a0810f7U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0x78000000U, 0xe4000000U, 0x42000000U, 0x5d000000U, 0xe5800000U, 0xd8c00000U, 0x1be00000U, 0xb900000U, 0xebd80000U, 0xd740000U, 0x65ca0000U, 0x4e770000U, 0xdb588000U, 0xbc2a4000U, 0xd8e0a000U, 0x75123000U, 0xb9905800U, 0xdeda5c00U, 0xd4e08200U, 0xcb0e4300U, 0x3292a280U, 0x8c413340U, 0x28bad9e0U, 0x4ba31f90U, 0xe52aa308U, 0xcf653274U, 0xf8c8d916U, 0xbf01c23U, 0xd380238fU, 0xdfdc70beU, 0x3762f827U, 0xdccb6e01U, 0xe9e259e1U, 0x5e895ecaU, 0x424a028aU, 0xbb703eaU, 0x8538803aU, 0xbf7a4252U, 0x50d8a3f6U, 0x97f63088U, 0x7582590fU, 0xc0d95ffeU, 0x8ff203c7U, 0xe1930291U, 0x2aca8069U, 0x4ee943feU, 0xa212207cU, 0xed1f7359U, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0x88000000U, 0xac000000U, 0xfe000000U, 0xbf000000U, 0x21800000U, 0x2c400000U, 0x86200000U, 0x5e900000U, 0x6dc80000U, 0x7a640000U, 0xa0ae0000U, 0x17490000U, 0x45b98000U, 0x9bd5c000U, 0x2970e000U, 0x5f34b000U, 0x7409c800U, 0x6a05e400U, 0x45178200U, 0x3c9cc100U, 0xc4c96080U, 0x98e173c0U, 0x2b792a20U, 0x263156b0U, 0xee9e49f8U, 0xc5d927fcU, 0x267ee206U, 0xd6adb271U, 0x45848b8U, 0x9a24240aU, 0x881626fU, 0x8ec570a5U, 0x2df7297cU, 0x9fe855d0U, 0x4eefcba8U, 0x8868e414U, 0x51a00272U, 0x21d001d3U, 0x146800c3U, 0x47b401ddU, 0xe2c60140U, 0xb3fd03f6U, 0xf0ff8069U, 0x1768c2d4U, 0x802f61c4U, 0x858c71daU, 0x3e4ea9c7U, 0xe73d94b1U, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0xb8000000U, 0x1c000000U, 0x2a000000U, 0xc7000000U, 0x25800000U, 0x49400000U, 0xc9600000U, 0xf2900000U, 0x44c80000U, 0xf4240000U, 0x45ee0000U, 0xff4f0000U, 0x646f8000U, 0x300f4000U, 0xd819e000U, 0xcc143000U, 0x6211e800U, 0x63138c00U, 0x13818200U, 0xa4404100U, 0x2bf66080U, 0x9e5b73c0U, 0xc4e80ae0U, 0xcfd7bc70U, 0xf3b86aa8U, 0x4fa7ce1cU, 0xd5b1e216U, 0x8aa033e5U, 0x4337e945U, 0x98788c7aU, 0x8a00015bU, 0x770001bcU, 0xbd8001a9U, 0xa5400204U, 0x5b6000c2U, 0x2990025fU, 0x4b4801feU, 0x7a640036U, 0xa90e011aU, 0x449f0084U, 0xe9c783edU, 0x36bb4266U, 0xd93fe34dU, 0xc77f3259U, 0x439068ecU, 0xac53ce7eU, 0xaff7e199U, 0x585b33e3U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xd0000000U, 0x78000000U, 0x9c000000U, 0x2a000000U, 0x95000000U, 0x20800000U, 0xb9400000U, 0x27e00000U, 0xb9900000U, 0xebd80000U, 0xa7bc0000U, 0x3cea0000U, 0x9a070000U, 0xfd178000U, 0x24834000U, 0xdf47a000U, 0xe0f89000U, 0x9011e800U, 0x580b1c00U, 0xac1d8200U, 0x82144300U, 0x71082380U, 0x9687d340U, 0x65c49e0U, 0x92648e70U, 0x2043eaa8U, 0x75601d54U, 0x39d80102U, 0x6ebc02a5U, 0xd66a02ffU, 0x664703d6U, 0x827782e7U, 0xb85342baU, 0x397fa0d9U, 0x6bd492d9U, 0x67a3ebe9U, 0xdcf01c91U, 0x4a00024dU, 0x850000fbU, 0xb880029cU, 0xf54002d6U, 0x75e00057U, 0xb0900282U, 0xe15801e5U, 0x8bfc031fU, 0x3b8a01a6U, 0x9ad7024fU, 0x312f80eeU, 0x3aaf405bU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0xb8000000U, 0x34000000U, 0xca000000U, 0x59000000U, 0x8a800000U, 0x81c00000U, 0x58e00000U, 0x37900000U, 0x9580000U, 0xec3c0000U, 0xabe60000U, 0x941f0000U, 0x5a028000U, 0xb1134000U, 0xb68a2000U, 0xc7c0d000U, 0xffeff800U, 0x2e097c00U, 0x5b048200U, 0xbf9c4300U, 0x4550a380U, 0xf22f92c0U, 0x88e3dae0U, 0xff86acd0U, 0x6551f928U, 0xa22a7e64U, 0x80e003aaU, 0x739003c7U, 0x9b580003U, 0x313c02ceU, 0x536601edU, 0x78df0204U, 0x426283adU, 0x5e434133U, 0x6db22221U, 0x9dacd01dU, 0x5b1fb9cU, 0x61ba7c71U, 0xa3b80375U, 0x76ac0258U, 0x23e012bU, 0x10e300aaU, 0x9b848047U, 0xa75c42c3U, 0x7730a02eU, 0xf47f913dU, 0x615bd92cU, 0x102aaec9U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xf0000000U, 0x98000000U, 0x6c000000U, 0xaa000000U, 0xcb000000U, 0xdc800000U, 0x18400000U, 0xece00000U, 0x93900000U, 0x5ad80000U, 0x19bc0000U, 0x32ee0000U, 0x5e9b0000U, 0x7498000U, 0xe6774000U, 0x82c46000U, 0x55bd1000U, 0x88f7c800U, 0xfd87bc00U, 0x2fc78200U, 0x383c4300U, 0xf35e380U, 0xd1a653c0U, 0x16e5aa60U, 0x108dadb0U, 0x624fc8a8U, 0xafebbc2cU, 0x4b1182f2U, 0x1c8b40a1U, 0xf84a6253U, 0x1cf6103eU, 0xb8649a3U, 0x36dcfefaU, 0xb3b5e311U, 0xf9e65137U, 0x8205ab5cU, 0x1f1dae76U, 0xa97c8b3U, 0x1157bdceU, 0xf7f80abU, 0x91504106U, 0xcf63e2fbU, 0x71515012U, 0x3f7a2951U, 0xe94ded5bU, 0x53742ac2U, 0x4346eec9U, 0x9865aa9fU, 0x9fcdae3cU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0xe8000000U, 0x64000000U, 0x2a000000U, 0x9b000000U, 0x5800000U, 0x2fc00000U, 0x18a00000U, 0xd4900000U, 0x61580000U, 0xcae40000U, 0x5ff60000U, 0xb750000U, 0xaa208000U, 0x40cf4000U, 0x2f346000U, 0xcc433000U, 0x26f3800U, 0x68b0b400U, 0xdc8e8200U, 0x155e4300U, 0x38e2e080U, 0x48f970c0U, 0x40fbdba0U, 0x34fcc590U, 0xc6f5daa8U, 0xd1fdc56cU, 0x9a7b5a96U, 0x4a3877fU, 0x8299b942U, 0x7c5af502U, 0x2a62600dU, 0x2ca63317U, 0xc697bae1U, 0x665bf7aeU, 0x596ce3d4U, 0x4d387212U, 0xc3555965U, 0xe5f2855bU, 0x886f3927U, 0x3b0b7d9U, 0x110e836aU, 0x6e9e40aeU, 0xe242e13bU, 0x636971f8U, 0xe23d90bU, 0x4ad8c7c0U, 0x8423d94fU, 0x21d8c67aU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x50000000U, 0xd8000000U, 0x2c000000U, 0xa2000000U, 0x65000000U, 0xe4800000U, 0xa8c00000U, 0xd2e00000U, 0x2b900000U, 0x9d480000U, 0xf0bc0000U, 0xc6ba0000U, 0x3da30000U, 0x26218000U, 0x737a4000U, 0x97d9a000U, 0x8f7c1000U, 0xadd9d800U, 0x267e3c00U, 0xbb538200U, 0x33a54100U, 0xa1222380U, 0x12f55140U, 0x8b89fb60U, 0x2d546cb0U, 0x78a1f888U, 0x32b86c94U, 0xb3b3fa12U, 0xe1376ee3U, 0xf2e079abU, 0xdb922c5eU, 0xf5425a1dU, 0x54a77ea6U, 0x90aba0e0U, 0xd6a31331U, 0x5a25a29U, 0x5a377fa4U, 0x963a31bU, 0xdedf13d6U, 0xc9f85a09U, 0x60047d74U, 0x100a22a3U, 0x3819518aU, 0x7c1bfb6fU, 0x7a1b6cf5U, 0x491279c3U, 0x468d2ffbU, 0xcdd9d826U, 0x367e3ee1U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x50000000U, 0xc8000000U, 0x14000000U, 0x82000000U, 0xc1000000U, 0x14800000U, 0x8dc00000U, 0x61a00000U, 0xe3900000U, 0x4a580000U, 0xd1e40000U, 0x5f7a0000U, 0xfb10000U, 0xcc8e8000U, 0xb1c64000U, 0x87af2000U, 0x38831000U, 0x43c27800U, 0xdea2d400U, 0xf00c8200U, 0x58034300U, 0xfc03a080U, 0xc6105140U, 0x8b19db20U, 0xc1968450U, 0x1b4f5808U, 0x2d74c404U, 0x96ba7ad2U, 0x2416d477U, 0xfa0e8026U, 0x6d06419eU, 0x1a8f2081U, 0x12d31153U, 0x223a7807U, 0x39d6d55dU, 0x73ae82eeU, 0xca96437aU, 0x1ad72263U, 0x1637135cU, 0xebc07bfdU, 0x7aa7d7ddU, 0xca0000aeU, 0x150000daU, 0xb6800373U, 0x1cc00274U, 0xbd2000a9U, 0x7a500187U, 0xa9f8039dU, 0xf374020eU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x50000000U, 0x58000000U, 0x3c000000U, 0xe2000000U, 0x4d000000U, 0xcd800000U, 0xadc00000U, 0x8ae00000U, 0x66900000U, 0x43580000U, 0x6da40000U, 0xf53a0000U, 0x49630000U, 0xfc4b8000U, 0x552a4000U, 0xd97ca000U, 0x84573000U, 0x39397800U, 0x637d3c00U, 0xf5498200U, 0x16bd4300U, 0x83b52080U, 0xb22a7140U, 0xddec5960U, 0x4a074cf0U, 0xb91dd988U, 0x6b8e0e34U, 0x6ecaf9b6U, 0xb0637cf7U, 0x77d721cbU, 0x4bed732aU, 0x611ddb65U, 0x978e0d32U, 0xaccaf80aU, 0xad637d56U, 0xe25723e4U, 0xda2d710dU, 0x9fdda95U, 0xbc1e0d3aU, 0x2212f8feU, 0x6d077e40U, 0x9d8d20c3U, 0xf5de705eU, 0xb6ee59b3U, 0x84904e35U, 0xe5458c9U, 0xa0334d08U, 0x58ffda57U, 0xc3890f38U, 0x80000000U, 0x40000000U, 0x60000000U, 0x90000000U, 0x58000000U, 0xd4000000U, 0xee000000U, 0xab000000U, 0x1b800000U, 0x4a400000U, 0x3fa00000U, 0xca500000U, 0x7fa80000U, 0xaa5c0000U, 0xefba0000U, 0xf2570000U, 0x3ba08000U, 0x1c4ac000U, 0x90b5e000U, 0x7c9b000U, 0xdafca800U, 0x386e4400U, 0x10b5e200U, 0x47c9b100U, 0xbafca980U, 0xa86e4640U, 0x48b5e360U, 0x93c9b250U, 0x54fcaa38U, 0x36e44ecU, 0x5335e30eU, 0xd989b379U, 0x6b5caac6U, 0xc93e47c5U, 0x2c9de2f0U, 0x73d5b1d0U, 0x84e6a978U, 0x3b69440cU, 0x173d621eU, 0x6f9f71a1U, 0x14534b3aU, 0x3ca0f413U, 0xcdc1c975U, 0x57f13540U, 0x4e6a978U, 0x7b69440cU, 0x773d621eU, 0xff9f71a1U, 0x4c534b3aU, 0xe8a0f413U, 0x23c1c975U, 0xfcf13540U, 0x80000000U, 0x40000000U, 0x20000000U, 0x10000000U, 0x58000000U, 0x9c000000U, 0xe2000000U, 0x8b000000U, 0x52800000U, 0x56c00000U, 0x4a600000U, 0xb6d00000U, 0x3a680000U, 0xded40000U, 0xee6a0000U, 0xf8df0000U, 0x1b798000U, 0xc3434000U, 0x9428e000U, 0x8d691000U, 0x3e523800U, 0x4bb85c00U, 0x6c28e200U, 0x41691100U, 0xa4523880U, 0x4cb85c40U, 0x84a8e360U, 0xa91370U, 0x5eb23b08U, 0x27a85e6cU, 0xa620e22aU, 0x3e6d122bU, 0xc0d03a21U, 0xb7735cb7U, 0x695b62c3U, 0xdb255150U, 0xa1eb5998U, 0x1860f54U, 0xd8583aaeU, 0xdeb75e5dU, 0x67b961c8U, 0x863e5061U, 0x2e70d8d7U, 0x98de4e33U, 0x2b6b5998U, 0x8b460f54U, 0x50383aaeU, 0xf3675e5dU, 0x575161c8U, 0x922a5061U, 0x687ad8d7U, 0x5dd14e33U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0x48000000U, 0x44000000U, 0xca000000U, 0xd000000U, 0x28800000U, 0x51400000U, 0xd8a00000U, 0x59500000U, 0xbcb80000U, 0xc34c0000U, 0x49ae0000U, 0xe7c50000U, 0x96e68000U, 0xf87c4000U, 0xea372000U, 0x3d015000U, 0xa0910800U, 0xf5444400U, 0xa2b72200U, 0x1c415300U, 0xd0310b80U, 0x581446c0U, 0x9c0f2320U, 0x960d5210U, 0x7b1f08a8U, 0xe39146f4U, 0xfac9a382U, 0x66611355U, 0xf5302bcaU, 0x448c1791U, 0xaf4ea970U, 0xb7ac5458U, 0x88cf88ecU, 0x4774070eU, 0x3ae00abU, 0x2ac50179U, 0x5e668064U, 0x193c41eaU, 0x7a972081U, 0x20515358U, 0xd62908ecU, 0x3b08470eU, 0xc39920abU, 0xaac45179U, 0x9e778864U, 0xf93805eaU, 0xca800281U, 0x68400058U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0xa8000000U, 0xac000000U, 0xe6000000U, 0x9000000U, 0x38800000U, 0xe2c00000U, 0x50a00000U, 0xead00000U, 0x2cb80000U, 0x84d40000U, 0x99ba0000U, 0xf2410000U, 0xde6f8000U, 0x7c7dc000U, 0xdf7ea000U, 0x38e2d000U, 0x53a6f800U, 0xdd4ac400U, 0xcffea200U, 0xb622d300U, 0xc506f880U, 0x2e9ac440U, 0x73c6a0a0U, 0x7c36d1b0U, 0xea1cfb18U, 0x3f0bc464U, 0xb9912042U, 0x665f123bU, 0xfc785a5aU, 0x1f7817cfU, 0x18e058f0U, 0x43bc1428U, 0x75425a3cU, 0x63f91706U, 0x502fdb09U, 0xcc11d599U, 0x1604fbe1U, 0x910fc555U, 0x2c9321dfU, 0xca12c8U, 0x13adda3cU, 0x3d44d706U, 0xfff17b09U, 0xe230599U, 0xc11a03e1U, 0x64910155U, 0x9cd783dfU, 0x4da9c1c8U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x30000000U, 0x48000000U, 0x64000000U, 0xea000000U, 0xc5000000U, 0x4f800000U, 0x75c00000U, 0x3b600000U, 0xa1d00000U, 0xd9680000U, 0xe0cc0000U, 0x4cee0000U, 0x18050000U, 0x5c028000U, 0x26084000U, 0x7b122000U, 0x289db000U, 0x9b5a9800U, 0xeb33dc00U, 0x2a722200U, 0xc4db100U, 0xedb29b80U, 0x4e3fdcc0U, 0x15fc2320U, 0xd198b090U, 0x82d81828U, 0x4dfb9fd4U, 0x6d80021eU, 0x94c00147U, 0x7ee000c5U, 0x21100153U, 0xe588037bU, 0x50dc03c4U, 0x44e60276U, 0x9c1901f3U, 0x8604832bU, 0xab0142ccU, 0x509ea032U, 0xb740f245U, 0x65223878U, 0x56a2cb7U, 0x86d49a76U, 0xd7e6ddf3U, 0x98a12bU, 0x8f49f3ccU, 0xa92ebbb2U, 0xbb776e85U, 0xe1cc3b58U, 0x396f2c27U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x90000000U, 0x58000000U, 0x54000000U, 0x72000000U, 0xcf000000U, 0xf2800000U, 0x99400000U, 0xcfa00000U, 0xfb500000U, 0x98b80000U, 0x7dd40000U, 0xe3ea0000U, 0x257f0000U, 0xbe308000U, 0x56894000U, 0xc35d6000U, 0xbcad1000U, 0xe7c94800U, 0xb0f06400U, 0xa9e56200U, 0xce791300U, 0xd6a34880U, 0x9ccf6640U, 0x8075e360U, 0x37a05250U, 0xff462948U, 0x92b6757cU, 0x76d6a8aaU, 0x3b6f3435U, 0x2733c876U, 0xf1162591U, 0xfb908248U, 0x66d94382U, 0xa3656099U, 0x53391354U, 0x13034bf8U, 0x6c9f64a4U, 0xc04de3beU, 0x483453d3U, 0x538c2b71U, 0x1ad975a6U, 0x6d7e2819U, 0x72227514U, 0x509ca898U, 0xee4036f4U, 0xd93b4af6U, 0xd80b66afU, 0x9407e3dbU, 0x521b5193U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0xd8000000U, 0xdc000000U, 0x62000000U, 0xdf000000U, 0x2c800000U, 0x15400000U, 0xbe600000U, 0x2b500000U, 0x43680000U, 0x38cc0000U, 0xaa60000U, 0x4bf70000U, 0x438d8000U, 0x41c34000U, 0xe7326000U, 0x5f2cd000U, 0xb321c800U, 0xe9219c00U, 0x9a3a6200U, 0xcb0d100U, 0x1aefcb80U, 0xea1a9dc0U, 0xb11e160U, 0xda849270U, 0xdc502a08U, 0x2bf50ebcU, 0x738249d2U, 0x79c9de25U, 0x4b2b82f1U, 0xe5344311U, 0xb03fe15fU, 0xa7af9206U, 0x5073a83bU, 0x9e5d4d8eU, 0x24f3ab39U, 0x171d4fcdU, 0x1893a87dU, 0x934d4c6bU, 0xaf7baad6U, 0x62c14d5dU, 0x79bdabbbU, 0xdd664c4eU, 0x55d82859U, 0xb1290cbdU, 0x62c49f5U, 0x8ea2df17U, 0xb5e80264U, 0x1e8c0108U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x30000000U, 0x98000000U, 0xa4000000U, 0x5a000000U, 0x33000000U, 0xdf800000U, 0x4ac00000U, 0xa9600000U, 0xa4d00000U, 0x28680000U, 0xd4440000U, 0x732e0000U, 0xc6f70000U, 0x360a8000U, 0x85044000U, 0x1a80e000U, 0xf045b000U, 0x6928b800U, 0x55e11c00U, 0xd988e200U, 0x57d1b100U, 0x17eeba80U, 0xe921cc0U, 0x724c6060U, 0x5e32f390U, 0xe06cdbe8U, 0x3847ec0cU, 0x85223b1eU, 0xa3e55ebbU, 0xbc88034dU, 0xdd54039fU, 0x4fa6033fU, 0x5ba3002aU, 0xd9ac8061U, 0xeea743d4U, 0x5b2c626fU, 0xbae2f0a2U, 0x6804d87dU, 0xdc03ef62U, 0x6e0c3978U, 0xc1125f81U, 0xd08282e1U, 0x6b504314U, 0x8aa6e00fU, 0xe126b232U, 0x19e43915U, 0x1f965faeU, 0xaacc8206U, 0x397742aaU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0x8000000U, 0x84000000U, 0xea000000U, 0x8f000000U, 0x9c800000U, 0x2ec00000U, 0x86200000U, 0x18d00000U, 0xaf380000U, 0x45540000U, 0xa8620000U, 0xf6350000U, 0xc28000U, 0x3204000U, 0xfb4f6000U, 0xc56dd000U, 0x61b1b800U, 0x589c9400U, 0x24d76200U, 0xf929d300U, 0x5c4bb880U, 0xded9740U, 0xad6fe220U, 0xd5b89110U, 0x4a9c5b28U, 0xf7c1057cU, 0x3b1b852U, 0x939c95abU, 0x72576330U, 0x88e9d21fU, 0x4eebb86eU, 0xbffd94feU, 0x6e77e131U, 0x73c9097U, 0xd1465be5U, 0x6a6004deU, 0x2d313b06U, 0x7e59d505U, 0x26e28009U, 0xbf04264U, 0x7c7761b1U, 0xd439d3d7U, 0x2bd3bbc5U, 0xa5a996ceU, 0x5295e0aeU, 0x5bc99339U, 0xbda4d87bU, 0xfe9045dfU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0x28000000U, 0x2c000000U, 0x82000000U, 0x61000000U, 0xbc800000U, 0x5e400000U, 0xbba00000U, 0x88500000U, 0x8ca80000U, 0x43cc0000U, 0xf9660000U, 0xfda90000U, 0xe7538000U, 0x43214000U, 0x980ba000U, 0xa404d000U, 0x3e1b6800U, 0xbb1b2400U, 0xd983a200U, 0x4cd8d100U, 0x6f56b80U, 0xee6e25c0U, 0xe63e22a0U, 0x2a8c91b0U, 0x89434988U, 0x3eb444U, 0xd5936852U, 0x1ec724c9U, 0xdfeda166U, 0x26edd365U, 0x3e68ebe0U, 0x5e2a6506U, 0x5e8001a3U, 0xf4001e3U, 0xcf2002d5U, 0x8a10013eU, 0x9d080139U, 0x869c028eU, 0x4b4e01b1U, 0x8125014aU, 0x19158223U, 0x68984023U, 0x48502275U, 0x2cb9918eU, 0xd3decb31U, 0xa17af70aU, 0xf9ad4943U, 0x494bb533U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0xa8000000U, 0x8c000000U, 0xbe000000U, 0x41000000U, 0x31800000U, 0x5c00000U, 0x9ae00000U, 0xe4d00000U, 0x7b780000U, 0x69140000U, 0x7d9a0000U, 0x9bd10000U, 0xcbf38000U, 0x7d52c000U, 0xf2a1a000U, 0x4de5f000U, 0xd8429800U, 0xd13c6c00U, 0xa73ba200U, 0x9a34f300U, 0x8db11880U, 0xfd6eac40U, 0xcc1a00a0U, 0x5e110130U, 0x71138278U, 0x8982c144U, 0x21d9a266U, 0xa8f1f227U, 0x1bd89893U, 0xbed6e97U, 0x5d48232bU, 0xe2a632b3U, 0xe5f0bb1dU, 0x545b5dbcU, 0x6f209a62U, 0xe6396d61U, 0xabb22244U, 0x8867311cU, 0x679b3aa8U, 0x28cd9cd6U, 0x25633965U, 0x18199cf8U, 0xf4193804U, 0xba189f46U, 0x6312bad7U, 0x669e5f8bU, 0xf9491983U, 0x10baae65U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0x18000000U, 0x94000000U, 0xbe000000U, 0xa7000000U, 0x39800000U, 0x6a400000U, 0x6c600000U, 0x55500000U, 0x81e80000U, 0x21040000U, 0xda9a0000U, 0x55d70000U, 0xa5208000U, 0xa6a4c000U, 0x8dfe6000U, 0x4b1cf000U, 0x6397a800U, 0x5b4fbc00U, 0xeee46200U, 0x348bf100U, 0xad72a80U, 0x38bb7e40U, 0xfaf20260U, 0xca930350U, 0xdda8078U, 0x9123c0dcU, 0x88b6e086U, 0x32fc33f9U, 0xe693cb49U, 0xb7d44fc9U, 0x903b48e1U, 0x82248c2dU, 0xdf372a5bU, 0x47ab7f42U, 0xb77a0073U, 0x2ec7030eU, 0x4ea88145U, 0x71f0c2f7U, 0x490c6164U, 0x668ff292U, 0xf7cd2a23U, 0x302c7f9eU, 0x123280f5U, 0xc727c0f7U, 0xd3ace20cU, 0x96b313eU, 0x89d34b85U, 0x77208fbfU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0x8000000U, 0x94000000U, 0x36000000U, 0xbd000000U, 0x28800000U, 0xa9c00000U, 0x60a00000U, 0x2cd00000U, 0xc4380000U, 0x4f1c0000U, 0x6b820000U, 0xc84d0000U, 0x7e88000U, 0x50b7c000U, 0x34cd2000U, 0x3837d000U, 0x3d049800U, 0xe88a0400U, 0xc9cf2200U, 0xb0bad300U, 0x24cc1980U, 0x502dc740U, 0x791a0220U, 0xd6810150U, 0xe0d28158U, 0xae26c1b4U, 0x3007a082U, 0x181d10f7U, 0xfc19395aU, 0x72161647U, 0x830499b2U, 0x18a049bU, 0xb74f23acU, 0x747ad3d2U, 0x64ec1aafU, 0x413dc56eU, 0xeb820385U, 0x84d0065U, 0x67e88111U, 0x80b7c1f3U, 0x3ccd22f4U, 0xac37d266U, 0xb049a2dU, 0x558a0599U, 0xe14f22dfU, 0x197ad222U, 0x446c1aa3U, 0x7cfdc668U, 0x80000000U, 0x40000000U, 0x60000000U, 0xb0000000U, 0x8000000U, 0xf4000000U, 0xc6000000U, 0xe9000000U, 0xd6800000U, 0xf2400000U, 0x6200000U, 0x4f500000U, 0x86a80000U, 0x8c1c0000U, 0x1a1e0000U, 0xb0d0000U, 0x41888000U, 0x31d9c000U, 0x10e3a000U, 0x94321000U, 0xf05b6800U, 0x613e1400U, 0xe4dda200U, 0xd46f1100U, 0x997be980U, 0x71fbd6c0U, 0xf6a00220U, 0xa41002d0U, 0x3e080298U, 0x750c0164U, 0x5496037aU, 0xd5410019U, 0xcdbe8300U, 0xad88c299U, 0x9bd52140U, 0x13f6d1f9U, 0x21b84870U, 0x799c511U, 0x98d3691cU, 0xa67217f7U, 0xd66ba3abU, 0xfe7e11bcU, 0xda6d6b67U, 0xa46f1453U, 0xb16b22e8U, 0x55ebd075U, 0x88b8c866U, 0xb10c06eeU, 0xda86c92bU, 0xa85105e5U, 0x6d264807U, 0xbed4c77aU, 0x80000000U, 0x40000000U, 0x20000000U, 0x70000000U, 0xc8000000U, 0xfc000000U, 0xc6000000U, 0xa5000000U, 0x7a800000U, 0xc6400000U, 0x8ee00000U, 0x2f500000U, 0x9a680000U, 0xe0140000U, 0x10060000U, 0x981d0000U, 0x44118000U, 0xf201c000U, 0x9f0b2000U, 0x19979000U, 0x19cc6800U, 0x323e8c00U, 0x67ed2200U, 0x3bda9100U, 0x5535e880U, 0x6a6b4dc0U, 0x68000120U, 0xcc0002f0U, 0x2e000398U, 0x29000354U, 0x748002caU, 0x9f4000e9U, 0x32600123U, 0x4c100229U, 0x6e080383U, 0x9040099U, 0x48e027bU, 0x575902ddU, 0xce7f8379U, 0x8a08c048U, 0xcb1ca23cU, 0x738b5206U, 0xc2d6c977U, 0xd9a8df00U, 0xe12a69e3U, 0x10738d89U, 0x2b14a3b3U, 0x638f51a1U, 0x5ad8cb9fU, 0x9db1ddefU, 0x1335ebd4U, 0x8f6b4d69U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xb0000000U, 0x58000000U, 0xac000000U, 0x6e000000U, 0x41000000U, 0x23800000U, 0x46c00000U, 0x22200000U, 0x33d00000U, 0x23a80000U, 0x4a040000U, 0x8b1e0000U, 0xe89f0000U, 0xe438000U, 0x9c66c000U, 0xf7ada000U, 0x7811b000U, 0x5c1cf800U, 0x96023400U, 0x5d13a200U, 0x159eb100U, 0xabd77a80U, 0x6fb0f6c0U, 0x34080360U, 0x221403b0U, 0x3f160338U, 0x8a8b03c4U, 0x915581eeU, 0xa6edc3abU, 0x3ef82130U, 0x72fc71cbU, 0xce4d800U, 0xa5fe4433U, 0x727778a4U, 0xf6a0f66dU, 0xfb800037U, 0xaac00099U, 0xec200212U, 0xc2d00232U, 0x58280191U, 0xa0c4039dU, 0xc73e039cU, 0x9a4f01a9U, 0xe6b83d9U, 0x90a2c232U, 0x5e93a1a2U, 0xa35eb139U, 0x71f778f1U, 0x4060f51eU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0x48000000U, 0xc000000U, 0xca000000U, 0xfb000000U, 0xb1800000U, 0x5ec00000U, 0xc9600000U, 0xc1d00000U, 0xaee80000U, 0x46040000U, 0x71020000U, 0xea9d0000U, 0xbf4b8000U, 0xdfb04000U, 0x4aee000U, 0xa5377000U, 0x13f8b800U, 0x86891c00U, 0xc54ce200U, 0x9cba7100U, 0xa13b3a80U, 0x75ed5d40U, 0xe7880320U, 0xc7d40130U, 0x7fea01a8U, 0xfc9902acU, 0x864983e6U, 0x392d414bU, 0x71e5600dU, 0x818730ebU, 0xa6d6587dU, 0x7d7e6c63U, 0x1fd458e1U, 0xdbe36dadU, 0xca9fd8c6U, 0xaf532e26U, 0x37b13876U, 0x58a45d4eU, 0x2729803aU, 0xe4fd42f8U, 0xfd0d6149U, 0x60833301U, 0xe4545920U, 0x3e236e6dU, 0x127fdafbU, 0x60432ce5U, 0x18393967U, 0xd3705eabU, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0xa8000000U, 0xfc000000U, 0xaa000000U, 0x63000000U, 0x18800000U, 0xbb400000U, 0xa6e00000U, 0x7a500000U, 0x91680000U, 0xfb940000U, 0xe3d60000U, 0x3db10000U, 0x2cb18000U, 0x43384000U, 0x96efe000U, 0xb2545000U, 0xbd7c0800U, 0x9974c00U, 0xd4d1e200U, 0x73315100U, 0x5efb8880U, 0x9e4e0fc0U, 0x4f6780a0U, 0x3e8942f0U, 0x9a5e6228U, 0x16c124cU, 0x8393eac2U, 0x47c31d1dU, 0xc3adea33U, 0x19a61d65U, 0x92aa68a7U, 0x563f5fc3U, 0xb77c0934U, 0xda974c2fU, 0x4451e07fU, 0xc471525eU, 0xfa1b893eU, 0x7b1e0d6eU, 0x6c8f82b6U, 0x1d5d4152U, 0xc7e8639cU, 0xfdcd11a3U, 0x98aa6a1dU, 0x853f5db3U, 0x27fc0925U, 0x6dd74e47U, 0xe0b1e2d3U, 0x2121528cU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xd0000000U, 0xd8000000U, 0x24000000U, 0xf2000000U, 0x2b000000U, 0x7f800000U, 0xb2c00000U, 0x24200000U, 0x3d00000U, 0xbca80000U, 0xb0840000U, 0xdf520000U, 0xcdef0000U, 0x506e8000U, 0xf1bd4000U, 0xfe0de000U, 0xb517b000U, 0xfa863800U, 0xe04ef400U, 0xe877e200U, 0xe5bcb100U, 0xa41aba80U, 0xb20cb740U, 0x8b1c8160U, 0xaf824190U, 0x6acb6148U, 0x2ef3ecU, 0xf1d9da9eU, 0x97b6465bU, 0xcf1f5958U, 0x6d8f05a3U, 0xe9c0bb8cU, 0x53b7b649U, 0x4d08000dU, 0x4e9401e8U, 0x6a5a019bU, 0x377b0278U, 0xb03481d3U, 0x19c64314U, 0x1bb9600dU, 0x1111f22fU, 0x489f5bc5U, 0x6b4f0544U, 0x47e0ba65U, 0x8f67b5b3U, 0xa42001c3U, 0x43d0015bU, 0x1ca8031fU, 0x6084033dU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x50000000U, 0xd8000000U, 0x4c000000U, 0x22000000U, 0xdf000000U, 0x26800000U, 0x8ec00000U, 0xb0e00000U, 0xefd00000U, 0x73780000U, 0xf4940000U, 0x19d20000U, 0x227f0000U, 0x5f138000U, 0xe6874000U, 0xaed66000U, 0xe0ea9000U, 0x37c13800U, 0x3f634c00U, 0xd69c6200U, 0xc6d19300U, 0x4f8b880U, 0xd1cf0d40U, 0x566b8160U, 0x41134230U, 0x93846008U, 0xc355923cU, 0x26b2bbfaU, 0xf4f40f0bU, 0x99d2004bU, 0xe27f03c3U, 0x7f1381d7U, 0xb68740a9U, 0x76d661c4U, 0xacea9206U, 0x15c13839U, 0xe0634f34U, 0xf01c6046U, 0x48119231U, 0xb418bbe0U, 0x3e1f0d98U, 0x2513814cU, 0xb587417aU, 0x8a5660a3U, 0xe12a910fU, 0x79a13885U, 0x12734e8eU, 0x370460adU, 0x295900aU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x30000000U, 0x68000000U, 0xec000000U, 0xfa000000U, 0xfb000000U, 0x61800000U, 0x89c00000U, 0xd9200000U, 0x34d00000U, 0x1a80000U, 0x33840000U, 0x7ece0000U, 0xd2b90000U, 0x1e0b8000U, 0x3d1a4000U, 0x9896e000U, 0xa7557000U, 0x4f635800U, 0x893a9400U, 0x8cd0e200U, 0x15b87100U, 0x7d8eda80U, 0xfbddd4c0U, 0x5e2383a0U, 0xf75e42b0U, 0xf778e168U, 0x9d3c732cU, 0xc2c0d826U, 0x90a4d597U, 0xf108028cU, 0x1294023fU, 0x94460300U, 0xf2ed0229U, 0x92ed833fU, 0x42e74029U, 0xbaf36396U, 0xee633d6U, 0x70f63a1fU, 0x9de1a7f0U, 0xfd635821U, 0xee3a9703U, 0xdf50e0d7U, 0xbb7873c5U, 0x572eda10U, 0x51cdd5f1U, 0x1d2b837bU, 0x82ca4223U, 0x30bee0a7U, 0xc111720dU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xf0000000U, 0x68000000U, 0x6c000000U, 0x62000000U, 0x69000000U, 0xc2800000U, 0xf2c00000U, 0x5e600000U, 0x7dd00000U, 0x3bf80000U, 0x269c0000U, 0xccc60000U, 0x5d610000U, 0x4a438000U, 0x1b94000U, 0x8f3ca000U, 0x4fe21000U, 0x809a7800U, 0xcbd41c00U, 0x64e2a200U, 0x7b0f1300U, 0x387f980U, 0x3c405fc0U, 0x3ea383a0U, 0x22a942b0U, 0xe8a4a008U, 0x8dae1264U, 0xdd247aaaU, 0x2ee91e7bU, 0xde0722f1U, 0x33075353U, 0x3f80da65U, 0xa6470c91U, 0xa3a359eaU, 0x862e4e32U, 0x7d67fbceU, 0x1a505df8U, 0xf9bb8025U, 0x7b2542f1U, 0x29faa3faU, 0xe783110aU, 0x259f862U, 0x3dad5f96U, 0x153e00c4U, 0xd2fd0233U, 0x2405835cU, 0x5e184006U, 0xf31f2295U, 0x5f8b5250U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xf0000000U, 0xb8000000U, 0xac000000U, 0x46000000U, 0x6b000000U, 0xdf800000U, 0xbec00000U, 0x1fa00000U, 0x37d00000U, 0x99380000U, 0x87840000U, 0x82c60000U, 0xb1a30000U, 0xb8db8000U, 0x14a7c000U, 0xb85ce000U, 0x6ff53000U, 0x8c29b800U, 0x5f1b8400U, 0x582e200U, 0x8bc23300U, 0xf72c3a80U, 0xa88b47c0U, 0xff5b80e0U, 0x3667c1b0U, 0xf9fce398U, 0x6f25326cU, 0x3491b99eU, 0xa15f844bU, 0x164e366U, 0xd8713273U, 0x16efbb9aU, 0xb2b88725U, 0x43596295U, 0x5865f3a9U, 0xd6f0db1fU, 0x12be7420U, 0xb3523b74U, 0xe06c4432U, 0x7ae60135U, 0x54b3009dU, 0xd843838dU, 0x3ff3c205U, 0xc422e061U, 0x4b1232dbU, 0xef94390aU, 0xa6cf47edU, 0x43bd81d1U, 0xc9d4c143U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xb0000000U, 0xa8000000U, 0xc000000U, 0x22000000U, 0x27000000U, 0xf8800000U, 0x65c00000U, 0x4c600000U, 0xdd500000U, 0x49b80000U, 0x81240000U, 0x8cfe0000U, 0x6c890000U, 0x23db8000U, 0xe5734000U, 0x90d66000U, 0x5bf7d000U, 0x5c099800U, 0x5a183c00U, 0x930de200U, 0xce849300U, 0xc4dffa80U, 0xbdefeec0U, 0x450478a0U, 0xbf9caf30U, 0x8d521808U, 0x31ab7d5cU, 0x353b81c2U, 0xbae34067U, 0xcd8e6199U, 0xd243d119U, 0x7d2f98ecU, 0x66e53f3fU, 0x57906268U, 0xe15ad0ccU, 0x3ac19faU, 0xa227db3U, 0xe66000c7U, 0x8650029cU, 0x9b3800e2U, 0x7fe40317U, 0xb21e03f1U, 0xff1901d5U, 0xfc838116U, 0xfbc7428cU, 0xe17062afU, 0xecad250U, 0xf6f41918U, 0x8f967ea4U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xd0000000U, 0x78000000U, 0x7c000000U, 0xe2000000U, 0x11000000U, 0xb800000U, 0x7ec00000U, 0xf9600000U, 0x25500000U, 0xbfa80000U, 0x402c0000U, 0xa8e20000U, 0x968b0000U, 0x9f418000U, 0xa2b54000U, 0xe1a8a000U, 0x1325b000U, 0x827a3800U, 0x4bde3c00U, 0x1ce92200U, 0xe090f100U, 0x88529b80U, 0xf63b8f40U, 0x1ff31be0U, 0xf21eccf0U, 0xc913ba08U, 0x47877e04U, 0x34c3804eU, 0xec6e424bU, 0xb0c1220dU, 0x327cf261U, 0xa3d098b8U, 0xf8e08d4fU, 0xae9a98e0U, 0x3478e70U, 0x90b91ac8U, 0x88b9cca4U, 0x64b0385eU, 0x1eb93c33U, 0xa3aaa3c1U, 0x323eb30bU, 0x21f3baedU, 0x31177c11U, 0x7b8b8270U, 0x36d241ebU, 0x2d6b20beU, 0xc34bf243U, 0x30bb1909U, 0xb8a2cfafU, 0x80000000U, 0x40000000U, 0xe0000000U, 0xf0000000U, 0x18000000U, 0x3c000000U, 0x3e000000U, 0x99000000U, 0xd3800000U, 0x13c00000U, 0x3ee00000U, 0x58500000U, 0x51280000U, 0xb8ac0000U, 0x60660000U, 0x22070000U, 0xf70d8000U, 0x4286c000U, 0x1449a000U, 0x37393000U, 0xfda11800U, 0x7df14c00U, 0xb0c42200U, 0x267ff100U, 0x3708bb80U, 0xe2987fc0U, 0x44d3a60U, 0xdf22bdf0U, 0xd9aa9978U, 0x7fe08ca4U, 0x17c802aeU, 0x6cfc027fU, 0xf74e03e3U, 0xcfab0035U, 0x62eb8292U, 0xd641c039U, 0x302422ccU, 0xa72ff3c2U, 0x55a0b92dU, 0xb9f47ec6U, 0x42cb3a6fU, 0x9975bed7U, 0x418f196fU, 0x1cca4c57U, 0xb067a12fU, 0x6a0233f7U, 0xc3029bbfU, 0xa88c8effU, 0x974e00a3U, 0x7fab0115U, 0x9aeb8242U, 0x1a41c391U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x90000000U, 0x98000000U, 0x64000000U, 0x2e000000U, 0xab000000U, 0xfc800000U, 0xe6c00000U, 0xf8a00000U, 0x26500000U, 0xf4680000U, 0x2bec0000U, 0x8daa0000U, 0x39d70000U, 0xf22a8000U, 0xef88c000U, 0x4e50e000U, 0xd879d000U, 0x19e2f800U, 0xfcbb2400U, 0xd85a6200U, 0x27611100U, 0x237a1b80U, 0xdd7ef640U, 0xe7a9860U, 0x6e13490U, 0x5620f938U, 0x618025ecU, 0x955ae012U, 0x2cfed14bU, 0x3207abaU, 0x4e1fe5e5U, 0x7b0080fbU, 0x849fc108U, 0x12da611eU, 0x4ea11309U, 0xe95a1a69U, 0x26eef583U, 0x66329984U, 0x899d341cU, 0xf942f83aU, 0xfeeb24dfU, 0xe23263a4U, 0x378d12ecU, 0xca501892U, 0x6669f58bU, 0x2af01b1aU, 0x6439f555U, 0x10981833U, 0x74d5f4ccU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0xa8000000U, 0x6c000000U, 0xf2000000U, 0xdf000000U, 0x42800000U, 0x15c00000U, 0x57200000U, 0x63500000U, 0x4e80000U, 0xed640000U, 0x5c2a0000U, 0x57d90000U, 0xf0238000U, 0x45dd4000U, 0x1f396000U, 0x3f4a9000U, 0xcef09800U, 0xf6761400U, 0x80bae200U, 0x6f07d100U, 0x3a81fa80U, 0x71c88640U, 0x592878a0U, 0xe65cc4b0U, 0xf57a9b48U, 0x483f143cU, 0xc1d1632aU, 0x212e92a7U, 0x825a9ab4U, 0xfb6f1501U, 0xcd396271U, 0x304a902eU, 0x8470986eU, 0x1fb615b9U, 0x8d9ae325U, 0xbf57d3c8U, 0x8ee9f90bU, 0x566c86a6U, 0x10a27832U, 0xc715c4c3U, 0x56911adaU, 0x83d654b8U, 0x862a0354U, 0xa4d902e6U, 0xe0a383e5U, 0x1f1d415fU, 0xa29961b7U, 0x25da92bbU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0x48000000U, 0x4c000000U, 0xd6000000U, 0x63000000U, 0x9f800000U, 0xbf400000U, 0xb6a00000U, 0x76d00000U, 0x2ae80000U, 0xffe40000U, 0xb3720000U, 0x2ba50000U, 0x764f8000U, 0x6425c000U, 0xc102e000U, 0x3e8bb000U, 0x31d5c800U, 0x3f700400U, 0x1da56200U, 0xe54a7100U, 0xe3a52a80U, 0x7a5eb540U, 0x123f2b20U, 0xf21fb430U, 0xe902abd8U, 0xc29f75ccU, 0x5fcfcbdeU, 0x871078dU, 0x5038e022U, 0xa31ab127U, 0x7f804a2dU, 0x4f54c4feU, 0xaeba0211U, 0x72d10234U, 0xb0f5800eU, 0x4af4c185U, 0x4ff760e6U, 0xb7f71bdU, 0x7fa2aafaU, 0xa44f766bU, 0x9d27c8b3U, 0xeb950653U, 0x7d4ae103U, 0xa7bfb14bU, 0x404fc92fU, 0xf7310645U, 0x4698e12aU, 0x85cab063U, 0x80000000U, 0x40000000U, 0x60000000U, 0x30000000U, 0x98000000U, 0x64000000U, 0x6000000U, 0x65000000U, 0x55800000U, 0xb6400000U, 0x17600000U, 0x15d00000U, 0x7c280000U, 0x633c0000U, 0x71be0000U, 0x91670000U, 0x30de8000U, 0x49b1c000U, 0xe5692000U, 0xfecbf000U, 0xe0a12800U, 0x4af2bc00U, 0x4f9fa200U, 0xc1463100U, 0xd9f60980U, 0xc71e4cc0U, 0x16800860U, 0xd6d54c90U, 0x5ca88b98U, 0x48ef8c54U, 0x1c8928b6U, 0x69cebe89U, 0x5e21a1a5U, 0x60213193U, 0x71288b5eU, 0xeaaf8f91U, 0xf5e928b5U, 0x4d1ebdcfU, 0xe989a3a0U, 0xb45d3270U, 0x44768948U, 0xbd588fecU, 0xfbffab52U, 0xc4037e97U, 0x16168090U, 0xad1dc09cU, 0x999f209eU, 0x4c40f171U, 0x1069aa65U, 0x23587e77U, 0xfaf60044U, 0x978b026eU, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0x68000000U, 0x5c000000U, 0xaa000000U, 0x5d000000U, 0x91800000U, 0x34400000U, 0x4a00000U, 0xf7d00000U, 0x19e80000U, 0xf4fc0000U, 0x3d7a0000U, 0x4d390000U, 0xc79d8000U, 0xf35e4000U, 0xd0232000U, 0x7613f000U, 0xb716e800U, 0xac8bc400U, 0xb5d6a200U, 0x58f1b100U, 0xaf6fc980U, 0x44313440U, 0xb015cba0U, 0x58083470U, 0x44084928U, 0x8e167434U, 0xc30b6866U, 0x3a9584e1U, 0x52d5809aU, 0xfc72429bU, 0x56b120a9U, 0xded6f346U, 0x1e7169a9U, 0x27ac863eU, 0x9d480185U, 0x432c0364U, 0x44920006U, 0xa9c50071U, 0x92e780e2U, 0xe2674137U, 0xbdbea0b3U, 0xd84db0e5U, 0xf6b5ca8cU, 0xeed83452U, 0x6604887U, 0x3aa767bU, 0x3516b01U, 0xe83c87b2U, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0xc8000000U, 0x64000000U, 0x9a000000U, 0xfd000000U, 0xa6800000U, 0xecc00000U, 0x86200000U, 0x8500000U, 0xabe80000U, 0xcef40000U, 0x74660000U, 0x8ea50000U, 0xfb8e8000U, 0xfa584000U, 0x82f02000U, 0x1a7c1000U, 0xf1bcf800U, 0xfc187400U, 0x8616a200U, 0xeb105100U, 0x558ad880U, 0xe55167c0U, 0x556cd920U, 0x5e346490U, 0x344258e8U, 0x4dfc2534U, 0xf5fa7b3aU, 0x19e434e3U, 0xc7e881d0U, 0x50fd4085U, 0xc37ea1fdU, 0xed24512cU, 0x1dccd81bU, 0x6ea467ccU, 0x6b8a59abU, 0xe25825b4U, 0xdef47b77U, 0x2c75343aU, 0xf2a000eeU, 0x3d900269U, 0x3148014bU, 0x27640089U, 0x372e0176U, 0xc0c10008U, 0x38208384U, 0x4f5942c2U, 0x70a07fU, 0x4cb5523eU, 0x80000000U, 0x40000000U, 0x60000000U, 0x90000000U, 0x88000000U, 0x74000000U, 0x6e000000U, 0x2f000000U, 0x7f800000U, 0x4c400000U, 0xfea00000U, 0xc9d00000U, 0x23e80000U, 0x8ffc0000U, 0x3dea0000U, 0xf8e50000U, 0xde688000U, 0x3ebac000U, 0xe9dc6000U, 0xd3ebb000U, 0x97f02800U, 0xc1ed8400U, 0xe2fce200U, 0x9f7d7100U, 0x6e2e4980U, 0xda1f3640U, 0x610e4820U, 0xa08f34d0U, 0x2bc64a38U, 0x4ee337fcU, 0x2d64485eU, 0xab2a37a1U, 0xfc8ecbe2U, 0x81c9f50bU, 0x77f02969U, 0x11ed8522U, 0xafce2ebU, 0x7b7d73d9U, 0x882e4beaU, 0x811f37ffU, 0x708e4843U, 0xc3cf34e9U, 0xaae64962U, 0xcb7337cbU, 0xf02c4889U, 0xed063492U, 0xe28cc8a3U, 0xf6d0f70dU, 0x9472a910U, 0xd7b2468cU, 0x3d4802f6U, 0x962c0345U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0xe8000000U, 0xfc000000U, 0x12000000U, 0x67000000U, 0xf4800000U, 0xeac00000U, 0xbe600000U, 0x40500000U, 0xf9b80000U, 0x89bc0000U, 0x31ba0000U, 0x45b90000U, 0x3ba98000U, 0xa6a94000U, 0xc9386000U, 0xc5685000U, 0xf6c77800U, 0xfc637c00U, 0xaf49e200U, 0x612d1300U, 0x997d1980U, 0x14ce2e40U, 0xe37d19a0U, 0x4fce2cf0U, 0x65fd1bc8U, 0x520e2cdcU, 0xc71d1bf2U, 0x49e2d1bU, 0x92c51a91U, 0xaa722e2dU, 0xae47185cU, 0x8cb72ea1U, 0x1a349985U, 0x2ff76c90U, 0x111d7a4bU, 0xc58a7d3aU, 0x1f586147U, 0xb93851a3U, 0x7d7f7b56U, 0x82df7cddU, 0x8273e294U, 0x325410fdU, 0xeb499b7U, 0x95376c6bU, 0x277d7a8aU, 0xe9da7fafU, 0x1ce0634fU, 0xab84500cU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xf0000000U, 0x38000000U, 0x7c000000U, 0xb2000000U, 0xaf000000U, 0xb8800000U, 0x54c00000U, 0x4a600000U, 0x8a500000U, 0x77b80000U, 0xc1ac0000U, 0x80b60000U, 0x35330000U, 0xbe658000U, 0x5c5b4000U, 0x6a76000U, 0xac3bd000U, 0x87f7b800U, 0x5d017c00U, 0x379ae200U, 0xfc5c9300U, 0xd6bedb80U, 0x8435afc0U, 0x33e6dae0U, 0xab09aef0U, 0x5688db48U, 0x59c6ae7cU, 0x95e35b82U, 0x2202ec63U, 0xa717ba81U, 0x1c917da5U, 0x6ac2e094U, 0x6f6091d9U, 0xe1d0d861U, 0x29faaf22U, 0x700d58c4U, 0xf80ded41U, 0x9c1c3b45U, 0x42053c64U, 0x970e0191U, 0xc49f019dU, 0xe6d38160U, 0xe5684147U, 0x32c2e0b0U, 0x23609168U, 0x8bd0dbecU, 0xafaaefaU, 0x428d5a37U, 0x7fcded4fU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xd0000000U, 0xc8000000U, 0x14000000U, 0x8e000000U, 0xcf000000U, 0x7d800000U, 0x5bc00000U, 0x53200000U, 0x49500000U, 0x85780000U, 0xb9ac0000U, 0x93120000U, 0x279d0000U, 0xfac48000U, 0x31b2c000U, 0xa7126000U, 0x9984f000U, 0x2ddf5800U, 0x90263400U, 0x66c4e200U, 0x8bab3300U, 0xd609bb80U, 0x33100740U, 0xd789d920U, 0x2c9f750U, 0x3db203b8U, 0xf50d037cU, 0xcc9c8156U, 0x114ec27fU, 0x79786054U, 0x13b5f249U, 0xca09d9dbU, 0x4909f4b5U, 0x469200f6U, 0x785d03d4U, 0xfe48332U, 0x73e2c045U, 0x19ea61e5U, 0xa0e8f04eU, 0x1e6d5b28U, 0x6a2b3524U, 0x37d8631aU, 0x1125f2e1U, 0x3451dbbfU, 0x7df5f68fU, 0x16f80147U, 0x3d6c01d3U, 0x95b201c1U, 0xf10d01d4U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x30000000U, 0xa8000000U, 0x64000000U, 0x96000000U, 0x23000000U, 0xf800000U, 0x50400000U, 0xc8600000U, 0xcd00000U, 0x9fb80000U, 0xa0fc0000U, 0x550e0000U, 0xdc810000U, 0x97c68000U, 0xcc21c000U, 0xfaade000U, 0xd477b000U, 0xa6d8a800U, 0x86ae9c00U, 0x4e656200U, 0x17d77300U, 0xc33c980U, 0x9ab8ecc0U, 0xe47028a0U, 0xede5e90U, 0xe2b601d8U, 0xd87d034cU, 0x34c8831eU, 0x3a0c011U, 0xcaeb63d9U, 0x2c16712fU, 0x2154818U, 0x7d092f4eU, 0x7885c84bU, 0x61c5ed00U, 0xdf38a880U, 0x5d3e9e40U, 0xe03d61e0U, 0xf8bb70f0U, 0xa965c8e8U, 0xde55ef84U, 0xe760aa4aU, 0x91529f63U, 0x4aeb6386U, 0xec16711fU, 0x62154a72U, 0x4d092cdfU, 0xd085c870U, 0x5c5ee8aU, 0x80000000U, 0x40000000U, 0x20000000U, 0x90000000U, 0x58000000U, 0x4000000U, 0x82000000U, 0x5000000U, 0x5800000U, 0x52400000U, 0x42e00000U, 0xcad00000U, 0x71280000U, 0xe8740000U, 0x340a0000U, 0xa070000U, 0x79168000U, 0x13894000U, 0x8d4b2000U, 0x46707000U, 0x1f0aa800U, 0x64804c00U, 0x65d7a200U, 0xddbe3100U, 0xd1b70880U, 0x6fa97e40U, 0x5cbe2b60U, 0x163a0d10U, 0x18e00088U, 0x8bd00354U, 0xd6a801f6U, 0x2f340319U, 0x2b6a0263U, 0x9697032fU, 0xc8de83daU, 0x342d42fcU, 0xcde921cdU, 0xf643724aU, 0x10f6292bU, 0xb7de0cc4U, 0xe0a20121U, 0x60330390U, 0x77fc81c8U, 0x475e43b4U, 0x5f75a326U, 0xbc8d3231U, 0x21cb8b07U, 0x7fb73d21U, 0x44ab8a8fU, 0x32273ef5U, 0xae38939U, 0xd6c33c8cU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x30000000U, 0x98000000U, 0x34000000U, 0x22000000U, 0x2b000000U, 0xbd800000U, 0x79400000U, 0x2fe00000U, 0x57d00000U, 0xaf280000U, 0x1b640000U, 0xf81e0000U, 0xe40f0000U, 0x2a148000U, 0xb7114000U, 0x3390e000U, 0x44557000U, 0x9b6e0800U, 0xb8072c00U, 0x441a6200U, 0x1a0b3100U, 0x2f0a6a80U, 0x7931cc0U, 0x664c8860U, 0xb07d6dd0U, 0x5800008U, 0x3d40016cU, 0x35e00216U, 0x78d001f5U, 0xa8a80257U, 0x7d240123U, 0x487e00c2U, 0xe19f0124U, 0x175c81a9U, 0x82e5432aU, 0x4b46e2abU, 0xecee73eeU, 0xe64c8992U, 0xf07d6eecU, 0xa5800325U, 0xd4002acU, 0xade003f6U, 0x4cd00365U, 0x8aa8007fU, 0x5624033fU, 0xf5fe026cU, 0x98df00e5U, 0x38bc834cU, 0xd5354166U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0x68000000U, 0x24000000U, 0xaa000000U, 0x93000000U, 0xf4800000U, 0xc4c00000U, 0x8da00000U, 0xb7500000U, 0xcff80000U, 0x51240000U, 0x37920000U, 0x98410000U, 0xcd6a8000U, 0x40f24000U, 0x83b3e000U, 0x4e535000U, 0x869b800U, 0xb16e4400U, 0x16eb6200U, 0x86b01300U, 0x1fc8da80U, 0x4d2b5740U, 0x11833ba0U, 0x255c0790U, 0xd0f88228U, 0x8bb3420cU, 0x1a5960f2U, 0x1a6110c3U, 0x6e7a593eU, 0x6c6d1401U, 0x7b7ad845U, 0xf5fa571bU, 0xca31b9baU, 0x971a47efU, 0x4e81631cU, 0x9fd5124aU, 0x8d305867U, 0xb1981780U, 0xf55a5910U, 0xb8fd1768U, 0xafa2daacU, 0xb04e55e2U, 0x897bb9abU, 0x9aef4692U, 0xa8a1e263U, 0xf6d2532eU, 0x42a339e9U, 0x5cc05a9U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0x28000000U, 0xcc000000U, 0x4a000000U, 0x81000000U, 0x61800000U, 0x4a400000U, 0xdee00000U, 0x2ed00000U, 0x83380000U, 0x69740000U, 0x678a0000U, 0x41590000U, 0x1e7f8000U, 0x151e4000U, 0x3f94a000U, 0x5558f000U, 0x80722800U, 0x2a12cc00U, 0x71012200U, 0x798fb300U, 0xbe410880U, 0x70f07c40U, 0x29d5aaa0U, 0x29a88c30U, 0xc3a783a8U, 0x92ba4144U, 0xfb26a1a6U, 0x6d75f259U, 0xd187aaf3U, 0xb2558d8fU, 0x1aea00a2U, 0xb8c90188U, 0x602783e3U, 0x45fa40d7U, 0x646a1aeU, 0x54e5f27aU, 0x8fdfaa44U, 0xf2b18ff1U, 0xb380060U, 0x757403d0U, 0x258a02b8U, 0x1c59001cU, 0x1dff82aaU, 0x125e42abU, 0xcaf4a3d4U, 0xb0c8f2e9U, 0xbc2a29ccU, 0x27f6cf12U, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0x98000000U, 0xe4000000U, 0x76000000U, 0xb5000000U, 0xe3800000U, 0xae400000U, 0xfe200000U, 0x94d00000U, 0x9e80000U, 0x1bbc0000U, 0x57860000U, 0x90570000U, 0xa72e8000U, 0x8d53c000U, 0x18b12000U, 0x21123000U, 0x4d9ba800U, 0x9f4a1400U, 0x9bb9a200U, 0x1786f100U, 0xf04c0980U, 0x5727e7c0U, 0x155d2860U, 0xfca5d690U, 0x570e8258U, 0xf883c014U, 0x7cd9206eU, 0x35ee32e9U, 0xe9bda840U, 0x648d1717U, 0x5edf2071U, 0xef93103U, 0xab3328a8U, 0xc74ed56bU, 0x5fa60123U, 0xf1870298U, 0x2d468143U, 0xc8afc3bfU, 0x2917231aU, 0xc1953320U, 0x955d2ab0U, 0xbca5d668U, 0x370e833cU, 0x883c072U, 0xe4d9202bU, 0xd1ee3203U, 0x9fbda828U, 0xd18d172bU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x10000000U, 0xd8000000U, 0x24000000U, 0x82000000U, 0x91000000U, 0xa2800000U, 0x2f400000U, 0x19200000U, 0xed00000U, 0x1df80000U, 0x5e2c0000U, 0xb74a0000U, 0x1d3f0000U, 0x7cca8000U, 0x44f14000U, 0xa1a000U, 0x3e0a9000U, 0x17188800U, 0x419fd400U, 0xd4d92200U, 0x68e8d300U, 0x9eb9ab80U, 0x191b0440U, 0x7e8a8960U, 0x795cd790U, 0xc221a388U, 0xc14a9104U, 0x36388a6aU, 0x7b4fd46dU, 0x9321230cU, 0x83c4d1efU, 0x973ab75U, 0xba6407c1U, 0xb9e00953U, 0x1c3d9762U, 0xc6580268U, 0xafbc0154U, 0x8b9200c2U, 0x79c30199U, 0x8c78827eU, 0xb2e2428eU, 0xeba12257U, 0xd984d3c9U, 0xd0d3aa17U, 0x1af40568U, 0xc7b80915U, 0x47819610U, 0xf7ca0109U, 0x737f0076U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xf0000000U, 0xf8000000U, 0x5c000000U, 0x26000000U, 0x5000000U, 0xf2800000U, 0x91400000U, 0x43600000U, 0x8d00000U, 0x61b80000U, 0x82740000U, 0x90560000U, 0xfbe30000U, 0x62818000U, 0x795dc000U, 0x37702000U, 0x7adf1000U, 0xe6b14800U, 0xfe91c00U, 0xd09fa200U, 0xde55d300U, 0x4af6e880U, 0xc218cfc0U, 0x9f0749e0U, 0x19a1e70U, 0x6ec62218U, 0x84ac10d4U, 0xa0e8c8aaU, 0x910dcf5U, 0x1c818075U, 0x105dc247U, 0x3bf02254U, 0x429f1398U, 0x89514b66U, 0xcf791cf9U, 0x26c7a399U, 0xc0b1d0dbU, 0xaf8e850U, 0x221fcd88U, 0x4f08c8bcU, 0x980dc66U, 0xcad9818bU, 0xfeb9c1aaU, 0x83fe2087U, 0xfe9811c6U, 0x7f5ec95bU, 0xc263dfe2U, 0x705803dbU, 0x2be400d0U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xd0000000U, 0x58000000U, 0x3c000000U, 0x82000000U, 0x53000000U, 0x5c800000U, 0xd3c00000U, 0x67e00000U, 0xb6500000U, 0x4fa80000U, 0x58ec0000U, 0x70c20000U, 0x137f0000U, 0x31918000U, 0x1e494000U, 0x5bbae000U, 0x8ef65000U, 0x15d35800U, 0xfafe8c00U, 0x53c16200U, 0x27ec1100U, 0x565a3b80U, 0x9fae9f40U, 0xf15b60U, 0x4cd18df0U, 0x9178e388U, 0x6289530cU, 0x42c2db92U, 0x8877ccffU, 0xe91b80f7U, 0xa38a4265U, 0xb54161c4U, 0xb2c1020U, 0x573a384eU, 0x453e9d2bU, 0xae39586fU, 0x1ead8f8fU, 0x1772e161U, 0x1f8a521aU, 0x77595a2dU, 0xb83d8eb6U, 0xdbbae0b1U, 0xcef65302U, 0xf5d35959U, 0x2afe8ea0U, 0xbc16250U, 0x1bec1258U, 0xd45a3a14U, 0xccae9ce6U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x70000000U, 0x38000000U, 0xdc000000U, 0x92000000U, 0xf000000U, 0x97800000U, 0x7fc00000U, 0xee200000U, 0x49500000U, 0x8b780000U, 0xa8240000U, 0x50460000U, 0x8deb0000U, 0x95718000U, 0xbd334000U, 0x8cc16000U, 0x5bb93000U, 0xa1915800U, 0x5ec45400U, 0x34aee200U, 0xe6157300U, 0x691fba80U, 0x3e8125c0U, 0xe1495ae0U, 0x7f705470U, 0xe30e2c8U, 0x594a72fcU, 0x6370383eU, 0x3c2d674fU, 0x2647bb10U, 0xccf52569U, 0x9ff75abbU, 0x5a7f55a3U, 0x8aa760c7U, 0x8302335dU, 0x8d98dbe8U, 0x34d317fdU, 0x47a983a9U, 0x9387404aU, 0x21df60bcU, 0x9b26309eU, 0x45dedb9fU, 0x15381508U, 0x78d8018dU, 0xfdb40261U, 0xa89e0036U, 0xb05f0142U, 0x9def8331U, 0x7d6c41ffU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x90000000U, 0x38000000U, 0x54000000U, 0x5a000000U, 0xf000000U, 0xc6800000U, 0x60400000U, 0x4aa00000U, 0x17d00000U, 0xd1780000U, 0x38a40000U, 0xb4da0000U, 0xb9eb0000U, 0x9dfc8000U, 0xff64000U, 0x5cf06000U, 0x3c771000U, 0x652fa800U, 0xe813e400U, 0xc0ee200U, 0x3e1e5300U, 0xfd014a80U, 0xa59db640U, 0xa8d7aae0U, 0x7ff7e650U, 0x94f4e1e8U, 0x6065517cU, 0xc325c97aU, 0xd11ff691U, 0xcb85caa2U, 0xcdcff633U, 0x1e7dc9b7U, 0x5e2bf41fU, 0x4487c883U, 0xcb50f729U, 0xde234910U, 0x8492b4aeU, 0x6b512af7U, 0x4e3aa759U, 0xbc800208U, 0x3f40008aU, 0x14200149U, 0xb3900226U, 0xf9d8013dU, 0x74740370U, 0xf92203beU, 0xee0f017fU, 0xa5068135U, 0xc18d40faU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0xb8000000U, 0x34000000U, 0x92000000U, 0xdd000000U, 0xff800000U, 0xdcc00000U, 0x9e200000U, 0xee300000U, 0x76280000U, 0x92340000U, 0x88320000U, 0xd9250000U, 0x80a38000U, 0x1371c000U, 0xafca6000U, 0x62a59000U, 0x56760800U, 0xb441cc00U, 0xa4760a00U, 0x9941cf00U, 0x3f60980U, 0x4181cfc0U, 0xb7d60b60U, 0x46b1cf10U, 0xac7e0928U, 0xd545cc64U, 0x45ec0ad6U, 0x3e90cf17U, 0x2d4788aeU, 0x51e50cafU, 0x7c97e976U, 0x78519ee7U, 0x22706356U, 0x6449183U, 0xa96f8b54U, 0xeed10eceU, 0x5325e86bU, 0x79b49c84U, 0x16f3e052U, 0x12055245U, 0x1d0de86bU, 0x1f809c84U, 0xecc1e052U, 0x26205245U, 0xda2e686bU, 0xe4315c84U, 0x4f2b8052U, 0x77b5c245U, 0x80000000U, 0x40000000U, 0x60000000U, 0xb0000000U, 0x8000000U, 0xcc000000U, 0x92000000U, 0xb9000000U, 0x10800000U, 0xf3c00000U, 0xb4200000U, 0xe4300000U, 0x1c380000U, 0xb8340000U, 0x56220000U, 0x75230000U, 0x10ba8000U, 0x61e8c000U, 0x9f1fe000U, 0xdf8df000U, 0xd45b8800U, 0xc4610c00U, 0xce5b8a00U, 0xf1610d00U, 0x2cdb8b80U, 0xba10fc0U, 0x807b8ba0U, 0xd0510cf0U, 0xba6389e8U, 0x35550e14U, 0xe0f989aaU, 0xb820ddbU, 0x12410b7aU, 0xfb79ce4bU, 0x81dc6b0aU, 0xfd28fcabU, 0x9cba0252U, 0x93e7017fU, 0x96008010U, 0xc70fc1f8U, 0xeb9f63ecU, 0xe2423046U, 0x9364e89dU, 0xfdd33c67U, 0x672763ecU, 0xe9b63046U, 0x1166e89dU, 0xdcc03c67U, 0x63a5e3ecU, 0xfc6af046U, 0x4a5b089dU, 0xcf6ecc67U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0x98000000U, 0xec000000U, 0x2a000000U, 0x27000000U, 0xa9800000U, 0x9400000U, 0x11e00000U, 0x99f00000U, 0x2de80000U, 0x8be40000U, 0x16f60000U, 0x650000U, 0x4cb88000U, 0x7e1dc000U, 0xd1092000U, 0xcc841000U, 0x63c93800U, 0xef390400U, 0x60493a00U, 0x1790700U, 0xb8293b80U, 0x1c90540U, 0x1c2139e0U, 0xffdd06f0U, 0xd3f3948U, 0x535c066cU, 0xfef1bbeeU, 0x2464c649U, 0x72a01ba9U, 0xf0d142eU, 0xed88031eU, 0xa7540201U, 0xf8fe0145U, 0x49710100U, 0x6c2681f7U, 0x37dcc2b8U, 0x1927a0d3U, 0x54cd23aU, 0x6bf099f4U, 0x46f4d51aU, 0xf87720d3U, 0x30b5123aU, 0xcc0fb9f4U, 0x1a15c51aU, 0x4f0698d3U, 0x4d91d63aU, 0x574fa3f4U, 0xf0e8d21aU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x10000000U, 0xf8000000U, 0x84000000U, 0x26000000U, 0xa7000000U, 0x3a800000U, 0x9ec00000U, 0x4fe00000U, 0x87f00000U, 0x4bf80000U, 0xe1e40000U, 0xce60000U, 0xcb790000U, 0x6a298000U, 0x8d4000U, 0xcbc9a000U, 0xec66f000U, 0x10b92800U, 0x7e5ad400U, 0x94392a00U, 0x939ad500U, 0xdf592980U, 0xb9aad540U, 0x3fc12a60U, 0x627ed750U, 0x2bbf2af8U, 0xf6d3d5ccU, 0x73e8aa12U, 0xc5f397b7U, 0xdaf68b2dU, 0x847525a8U, 0x2cb18202U, 0x3c59422fU, 0x537a031U, 0xf60bf002U, 0xff0eaa19U, 0x4e8a9440U, 0x50df08d6U, 0x94f864e1U, 0x1f78238cU, 0x543fb3c4U, 0x338e88d6U, 0x2f5124e1U, 0x51b7838cU, 0x43d043c4U, 0xc06620d6U, 0xaaa2b0e1U, 0x6b41098cU, 0xd7a566c4U, 0x80000000U, 0x40000000U, 0x20000000U, 0x30000000U, 0x28000000U, 0x34000000U, 0x76000000U, 0x53000000U, 0xb1800000U, 0x57400000U, 0xf5e00000U, 0x4bf00000U, 0x7cf80000U, 0x837c0000U, 0xab3a0000U, 0x855f0000U, 0x88e98000U, 0x957f4000U, 0xe8392000U, 0x2ccd1000U, 0xc3b4f800U, 0x2291c400U, 0x86ccfa00U, 0xb2adc500U, 0xa616fa80U, 0x2b02c5c0U, 0xbd877a20U, 0xd418510U, 0xcce45bf8U, 0xeb63945cU, 0xbf21213eU, 0xc3411101U, 0xf3f6f8e9U, 0x10f2c52eU, 0xc97f7b9aU, 0x8a3d86e3U, 0x39de5916U, 0x93c94e6U, 0xf048a24dU, 0x527e532fU, 0x5fafd8f3U, 0x208fd68dU, 0x83d3806cU, 0x602043b5U, 0x68d0a273U, 0xbdb2534dU, 0x758dda4cU, 0x695cd6a5U, 0x82f8018bU, 0x947c0311U, 0x64ba0172U, 0x851f02a4U, 0x80000000U, 0x40000000U, 0x20000000U, 0x50000000U, 0x98000000U, 0xc000000U, 0x6a000000U, 0x85000000U, 0x30800000U, 0xd7c00000U, 0x7ae00000U, 0x9cf00000U, 0x33f80000U, 0xa67c0000U, 0x11360000U, 0x24050000U, 0xce148000U, 0xb11c000U, 0x1b856000U, 0x9c497000U, 0x7ea08800U, 0xee5e5400U, 0xb7b88a00U, 0x94d25500U, 0xb5768a80U, 0x46ab5440U, 0xf25408e0U, 0x65bf9470U, 0x4dc5e948U, 0x77e72664U, 0x1860018aU, 0xd230013bU, 0xab980261U, 0x344c0248U, 0x9aae022eU, 0x40490191U, 0xccba800aU, 0x4758c131U, 0xbd3fe29aU, 0x5e11b309U, 0xf31f6a36U, 0x678fe627U, 0x3e47e027U, 0x6fadb2edU, 0xb8c968b6U, 0x8f7ae667U, 0x5bab62c7U, 0xcec0739dU, 0xd87a0b7eU, 0xb2369443U, 0xdb9f6badU, 0xfc4fe6d6U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0x48000000U, 0xa4000000U, 0xb6000000U, 0x69000000U, 0x56800000U, 0x18400000U, 0x4e200000U, 0xcc300000U, 0xbb280000U, 0xd0ac0000U, 0xb0760000U, 0x631f0000U, 0xa59b8000U, 0x15d54000U, 0xffc6000U, 0xeddcb000U, 0xd3feb800U, 0x47cffc00U, 0x30f6ba00U, 0x2253ff00U, 0x528ba80U, 0xfda0fc40U, 0xa0e53ba0U, 0x8a5abed0U, 0x512ad978U, 0xd3bf4f74U, 0x25fe0022U, 0xcec30315U, 0x9665831aU, 0xa2164325U, 0xa719e176U, 0x238af327U, 0xc4c75a97U, 0x65750c3bU, 0xaf99e0d9U, 0xe6caf2c8U, 0x2675b3cU, 0xac050d5eU, 0xf211e2ebU, 0x2f16f1a1U, 0xa79959bcU, 0xa2c60d1eU, 0x4474634bU, 0x5d00b071U, 0x4880ba44U, 0x254cfe2aU, 0x36b338c9U, 0x5175bdb4U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x30000000U, 0x38000000U, 0xc4000000U, 0xe6000000U, 0x85000000U, 0x23800000U, 0x39c00000U, 0x84e00000U, 0x5ef00000U, 0x19f80000U, 0xc96c0000U, 0x5e2a0000U, 0x3c8d0000U, 0xfd458000U, 0x5db14000U, 0x7545e000U, 0xe1bf9000U, 0xf753a800U, 0xb2b1b400U, 0x69cbaa00U, 0x6cedb500U, 0x32f9a880U, 0x33fcb5c0U, 0x566e2860U, 0xdaacf6d0U, 0x45c44bf8U, 0xe6ef24c4U, 0x9df78376U, 0x8f604023U, 0xeb326365U, 0x271fd058U, 0x81c982U, 0x3f5e67bdU, 0xaeb2621aU, 0xdbdfd15fU, 0x7e1caf7U, 0x686e67fdU, 0xbaa63ccU, 0x8843d24cU, 0xa633c9faU, 0x188f6539U, 0x8b45e34cU, 0xd0bf938cU, 0xaad3ab9aU, 0xfa71b6e9U, 0x10aba834U, 0x4addb688U, 0x6a61aa8cU, 0x18a0b51aU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x50000000U, 0x88000000U, 0xac000000U, 0x5e000000U, 0x2d000000U, 0xf8800000U, 0x88c00000U, 0x5ea00000U, 0x13b00000U, 0xfb380000U, 0x1be40000U, 0xb94e0000U, 0x7cef0000U, 0x6c28000U, 0xbbad4000U, 0xa726e000U, 0x7df6f000U, 0xe0556800U, 0xfe6bfc00U, 0x511b6a00U, 0x6e84fd00U, 0xe9d9e980U, 0xa829bc40U, 0x3e7f0ba0U, 0xf11f4ef0U, 0xde8a62d8U, 0x31c4b244U, 0x8c290b3aU, 0xcc644d67U, 0x821ee3c0U, 0xb12f169U, 0x419b6b8cU, 0x5a44fff6U, 0x8179ebb1U, 0x6a99bc41U, 0xebc70890U, 0xe33b4fc8U, 0x9fe463ccU, 0xfb5bb256U, 0xd7f38a41U, 0xf75d0e19U, 0x39ee0114U, 0x25f0012U, 0xe57a817bU, 0x7889437eU, 0xc8c8e2d4U, 0xbea9f17bU, 0x43afeaf7U, 0x7322bc88U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xf0000000U, 0xa8000000U, 0xf4000000U, 0xf6000000U, 0xbf000000U, 0x7c800000U, 0x7c00000U, 0x4ee00000U, 0x81f00000U, 0x95680000U, 0xc6bc0000U, 0x8e420000U, 0x18a70000U, 0x5518000U, 0x32334000U, 0x4d86a000U, 0xa85e3000U, 0x3fa74800U, 0x85c1d400U, 0xc7e54a00U, 0xe266d700U, 0x1e34c880U, 0x279594c0U, 0xb5526a20U, 0xfa3ba710U, 0xe99d21f8U, 0x64671ecU, 0xdcba6a0aU, 0xfb47a6f3U, 0x893f23b1U, 0x6f117034U, 0xe483ebc4U, 0xfbc8e43eU, 0xbcfb8005U, 0x60e841b0U, 0xa2f5201aU, 0x4bfa708bU, 0x78786a1dU, 0xab20a6deU, 0x160ea307U, 0x2f1233e7U, 0x848d4be5U, 0xabdad732U, 0xe4f6c90dU, 0x3cf29514U, 0xa0e3e854U, 0x2f8e706U, 0xbbf382c9U, 0xd064412aU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x90000000U, 0x88000000U, 0x1c000000U, 0x16000000U, 0xb9000000U, 0x3f800000U, 0x2a400000U, 0xf3e00000U, 0x62f00000U, 0xf1680000U, 0x35340000U, 0x7bc60000U, 0xa4a70000U, 0xcc8c8000U, 0x9ada4000U, 0x2f3b6000U, 0x9cd39000U, 0xde3e5800U, 0x5f446400U, 0x72785a00U, 0x9da36700U, 0x3314d980U, 0x50892540U, 0x4cc7bba0U, 0x762eb530U, 0x335fe3f8U, 0x7c7dd3d4U, 0xb0a33906U, 0x680f47dU, 0xd5c28349U, 0x39b940b6U, 0x119e32cU, 0x1b9ad152U, 0xd84fbb3bU, 0x58eab714U, 0x6671e08fU, 0x57aed042U, 0x7c09badaU, 0x460db4b7U, 0xd11d62f6U, 0xb384910cU, 0xb45ad922U, 0x56ea2763U, 0x4b653bf0U, 0x6227f571U, 0xf94e026bU, 0x336303d5U, 0xa62282dcU, 0x9b494323U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xd0000000U, 0x58000000U, 0x2c000000U, 0x12000000U, 0x31000000U, 0xe800000U, 0x1f400000U, 0x62e00000U, 0x1bf00000U, 0x81780000U, 0xd02c0000U, 0x19d60000U, 0x49ad0000U, 0xe7108000U, 0x699ec000U, 0x36dee000U, 0xf43a3000U, 0x3fdd5800U, 0xe6a5c400U, 0x1a8b5a00U, 0x1148c500U, 0x69fbd880U, 0x80660640U, 0xf6bd39e0U, 0xa28036f0U, 0x4d4e61a8U, 0xf3e4f234U, 0xc563bb92U, 0xc62ff749U, 0x9ece0299U, 0x10310166U, 0xf9de817cU, 0x39afc0d6U, 0x6f0062b3U, 0x1d95f2c4U, 0x8dd383dU, 0xd730376bU, 0x56631fU, 0xf778f16dU, 0x672db8d4U, 0x685ef7e5U, 0xf37082b7U, 0xd12ec359U, 0x3f46e346U, 0xf2e630acU, 0xe3f3582eU, 0x7d64c63fU, 0x9a2dd83aU, 0x4cb057aU, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0xf8000000U, 0xa4000000U, 0x1a000000U, 0xa7000000U, 0x88800000U, 0x6b400000U, 0x7200000U, 0x8300000U, 0x6cb80000U, 0x61fc0000U, 0x8fc20000U, 0x4a6d0000U, 0xc6018000U, 0x591ec000U, 0x15982000U, 0xb4cc3000U, 0x1cf4d800U, 0xc04cfc00U, 0x79b6da00U, 0xa261fd00U, 0xa175a80U, 0xcf0f3ec0U, 0x4977960U, 0xdd4f0c50U, 0xe639a108U, 0x99a2f2ccU, 0x3274f92aU, 0x220cce61U, 0x631803b6U, 0x428c0081U, 0xc45a0364U, 0xd3a10156U, 0xdd7b8253U, 0xd68fc3b3U, 0x465ba0e1U, 0xbff376U, 0x47ed7ae1U, 0x46de0eb4U, 0x77fa231eU, 0xded130bfU, 0x3ed5be9U, 0xccde3c78U, 0xf8f4fa34U, 0xfa4ccedeU, 0x2eb8005fU, 0xd2fc00f9U, 0xc5420350U, 0xd22d0288U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x30000000U, 0xd8000000U, 0x1c000000U, 0x46000000U, 0xd1000000U, 0x20800000U, 0x42400000U, 0xae200000U, 0xfb300000U, 0xe1a80000U, 0xa4fc0000U, 0x135a0000U, 0x4eb10000U, 0x197a8000U, 0x7f9e4000U, 0x87c66000U, 0xeee77000U, 0xac53b800U, 0xdb233c00U, 0x11a9ba00U, 0xdce23f00U, 0x3f5b3880U, 0xd0b07fc0U, 0xd46f5be0U, 0x191a0fb0U, 0x149c62f8U, 0x605670f4U, 0x1529387aU, 0x94bd7efdU, 0x4e6fda42U, 0x2e054ed1U, 0xd5088024U, 0xda9340f2U, 0xe546e011U, 0x87b831fcU, 0x85e75b6eU, 0x4bd60e8fU, 0x20ee622bU, 0x295b70a1U, 0x49a9b83cU, 0xe23e36U, 0xd95b38d3U, 0x31b07c55U, 0x2cef5a46U, 0x475a0fcbU, 0xfcbc6211U, 0x4a667144U, 0xd4013b82U, 0x72017f89U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0xf8000000U, 0x4c000000U, 0x6a000000U, 0x8f000000U, 0x43800000U, 0x2400000U, 0x7fa00000U, 0xf4b00000U, 0x59280000U, 0xfa6c0000U, 0x47560000U, 0xa3390000U, 0x6d788000U, 0xb8c9c000U, 0xe3762000U, 0x29d35000U, 0x29e99800U, 0x5d14ac00U, 0x609f9a00U, 0xdbddaf00U, 0xdaef1a80U, 0x7c886c40U, 0x89c73960U, 0x39fe3d70U, 0x850820c8U, 0xfc86534cU, 0x49c71bc6U, 0x19e46c45U, 0x551138b8U, 0x4873fd7U, 0x5d0a2bcU, 0x73ff924eU, 0xda193be9U, 0x471b3cceU, 0x78ea07aU, 0xc5a9058U, 0x2ebfba67U, 0x1e37fe54U, 0xfdfe0292U, 0x4b150057U, 0x8d8e82afU, 0x7340c118U, 0x4526a354U, 0xa8769312U, 0xa449b897U, 0x5abefe8fU, 0x182e8288U, 0xc8f0c32cU, 0x80000000U, 0x40000000U, 0xe0000000U, 0xd0000000U, 0xf8000000U, 0x14000000U, 0xe6000000U, 0x99000000U, 0x47800000U, 0xef400000U, 0x4de00000U, 0x12f00000U, 0xbc780000U, 0xdca40000U, 0x421e0000U, 0x17110000U, 0xd29b8000U, 0x8adb4000U, 0x25b26000U, 0x95959000U, 0xe052f800U, 0x5b738400U, 0x8634fa00U, 0x14c68500U, 0xe8b17980U, 0xd40cc640U, 0x46189a60U, 0xa9021610U, 0x6f9801f8U, 0x3540074U, 0xbfe602e6U, 0x6df502c9U, 0x62e58051U, 0x747a41c2U, 0xe0b1e140U, 0x481ad2e0U, 0x7c069bd0U, 0xea1314d8U, 0xbb038384U, 0xc08f404eU, 0x25d463a5U, 0x3209013U, 0x29577ab5U, 0xa4f9c51cU, 0x9d7d1bddU, 0x6f385627U, 0x9b49e233U, 0x3bfed1c5U, 0x93f89a74U, 0x3ff21791U, 0x2de00195U, 0x82f001ecU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xb0000000U, 0xc8000000U, 0x4c000000U, 0x3a000000U, 0x1f000000U, 0x94800000U, 0xebc00000U, 0x37600000U, 0x82700000U, 0x31f80000U, 0x6aac0000U, 0x701a0000U, 0x28130000U, 0x5c128000U, 0x4201c000U, 0x9b142000U, 0xe29fb000U, 0xcecb4800U, 0xbceae400U, 0xfd294a00U, 0xed55e500U, 0xdfa1c880U, 0xc38727c0U, 0x73476ba0U, 0x46a956f0U, 0x1a000348U, 0xef00028cU, 0xfc80031aU, 0x17c00023U, 0xc5600147U, 0xd17000eaU, 0x9f7802a0U, 0x9e6c0070U, 0xd3fa0388U, 0x41a300acU, 0x5a8a80aaU, 0xaaddc20bU, 0xdaf6221bU, 0xa020b388U, 0xe2c3c9e7U, 0xd6f824d1U, 0x3a2fe9d3U, 0x4dcb96c4U, 0x8a7ea15dU, 0x9df27202U, 0x40a56bdcU, 0x171654a2U, 0x388880e7U, 0xc1d2c251U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0xa8000000U, 0x2c000000U, 0xfe000000U, 0x51000000U, 0xef800000U, 0x6400000U, 0x57600000U, 0x10700000U, 0x22e80000U, 0x5240000U, 0xfd0e0000U, 0xd18b0000U, 0x37568000U, 0xe8e54000U, 0xbe356000U, 0x59859000U, 0xeb5cd800U, 0x8efbf400U, 0x3b3ada00U, 0xcc14f700U, 0x6e025b80U, 0x990ab640U, 0x9389b920U, 0x504e66f0U, 0x2a6e02d8U, 0x1fb03b4U, 0x75be8366U, 0xbdc140adU, 0xeb3b63bbU, 0xa40e91acU, 0x220a5990U, 0x371eb508U, 0x6a8fbb9cU, 0x93d1640aU, 0xd23e817fU, 0x78142f0U, 0x8a5b627aU, 0x997e9067U, 0xb9625b24U, 0x497ab64cU, 0xd161bb22U, 0x56a6593U, 0x7f600162U, 0xfc700011U, 0xbce80241U, 0x424038bU, 0xba8e0194U, 0xfbcb02b4U, 0x80000000U, 0x40000000U, 0x60000000U, 0xb0000000U, 0xc8000000U, 0x7c000000U, 0xc2000000U, 0x13000000U, 0x61800000U, 0xc3400000U, 0x58200000U, 0xa1300000U, 0x5fb80000U, 0x97740000U, 0xd3020000U, 0x418b0000U, 0x134c8000U, 0x2038c000U, 0x153ca000U, 0xe1a19000U, 0x467a7800U, 0xa19f3c00U, 0xe3407a00U, 0x88203d00U, 0xd92efb80U, 0xeba3ffc0U, 0x2966d8a0U, 0x20eae30U, 0x330203a8U, 0xb18b027cU, 0xbb4c802eU, 0xec38c071U, 0x1f3ca0ceU, 0x8ea19035U, 0xe5fa7a90U, 0x71df3f98U, 0xdae078d4U, 0xea503fd2U, 0xdeb6f89fU, 0xdde7fe9fU, 0xa5dcda8bU, 0xd4f1ae6dU, 0xf34c81e4U, 0xd038c2faU, 0xbd3ca2a3U, 0x2da193d1U, 0x4c7a796aU, 0xce9f3cbbU, 0x40c079c5U, 0x58603d98U, 0xe08ef9d4U, 0x89d3fe52U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0xf8000000U, 0x2c000000U, 0x96000000U, 0xcf000000U, 0x62800000U, 0xdd400000U, 0xfea00000U, 0x4bb00000U, 0x90380000U, 0x10ec0000U, 0xf9860000U, 0x45c90000U, 0xdae48000U, 0x48924000U, 0x9c59a000U, 0x8f36f000U, 0xca66d800U, 0xa8d6cc00U, 0x7d78da00U, 0xa643cd00U, 0x96225880U, 0xc7f48c40U, 0x47197b60U, 0xa6993cf0U, 0x3f428138U, 0xdbab43ccU, 0x882522b2U, 0xccf8b1b9U, 0xc7817bc8U, 0x5ec53dd7U, 0x27c8068U, 0xccce4024U, 0xcf67a156U, 0x7b53f24fU, 0x79a45ad7U, 0xd3d8de8U, 0x5f7df8e4U, 0x634b7c76U, 0xa5bb20dfU, 0x332db39fU, 0x447bf95cU, 0xbbc27ffaU, 0x21ffa30dU, 0x600ff3d6U, 0xb01a5b2cU, 0x8188da1U, 0x841f7ab7U, 0x42103ebbU, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0x48000000U, 0x5c000000U, 0x3a000000U, 0xe7000000U, 0x99800000U, 0x4400000U, 0xbb200000U, 0xa300000U, 0x46b80000U, 0x407c0000U, 0xec8a0000U, 0xf6d30000U, 0xc4f08000U, 0xf643c000U, 0x40312000U, 0x89b71000U, 0x15e61800U, 0x2acd3c00U, 0xbef41a00U, 0x31523d00U, 0x69b69a80U, 0xc5feffc0U, 0xf2dd3ba0U, 0x1ae92eb0U, 0x1f428348U, 0xe8acc12cU, 0x816ba32eU, 0x8817d03dU, 0x3c1fb942U, 0xaa05eed5U, 0x1f092378U, 0x8d8b13a4U, 0x624c1aa2U, 0x662e3c23U, 0x74bc9877U, 0xdb6dfd5bU, 0xff0dbad3U, 0x5d9aef79U, 0xba4ba030U, 0xc227d02eU, 0x5aa7bb1bU, 0x5a79ed95U, 0xbb8322beU, 0x275813a3U, 0x9cbc9b91U, 0x776dfdacU, 0xad0db948U, 0x569aee8aU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xb0000000U, 0x58000000U, 0xac000000U, 0xde000000U, 0xe9000000U, 0x99800000U, 0x82c00000U, 0x9d600000U, 0x3e700000U, 0x6cf80000U, 0x8ac0000U, 0x239a0000U, 0xb1c10000U, 0x67fc8000U, 0xe234000U, 0x85c06000U, 0xf5fc5000U, 0x29378800U, 0x1d48e400U, 0x1ab58a00U, 0x4495e500U, 0x894b0880U, 0x38aba7c0U, 0x3b95e9e0U, 0xbdd9b570U, 0x9e48298U, 0xbf3f42d4U, 0xb04262feU, 0xa92151dfU, 0x5d490a0bU, 0xbab6a7e6U, 0xf48b68d8U, 0xd157f474U, 0x94a261aeU, 0xe59153d7U, 0x54d10937U, 0x906aa654U, 0x3de96aadU, 0x2d3af51eU, 0x9744e23cU, 0x31b31332U, 0xb20de8b5U, 0xd705b40aU, 0x60868322U, 0xf352429dU, 0xeba4e0a6U, 0xd10312f8U, 0x6595eae4U, 0x14d9b746U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x50000000U, 0x8000000U, 0x54000000U, 0xd6000000U, 0xe5000000U, 0xab800000U, 0xe9400000U, 0x1b200000U, 0x70b00000U, 0x39f80000U, 0x92c40000U, 0xba7e0000U, 0xdf870000U, 0xcf498000U, 0x462d4000U, 0xd736e000U, 0x5aaa1000U, 0xeefa7800U, 0x525ffc00U, 0x41b3fa00U, 0x472bd00U, 0x7e851980U, 0x5ad8ac40U, 0x4e7f61a0U, 0xb9875110U, 0x724c98f8U, 0xb1b5ef84U, 0xbc6983d6U, 0x729d4061U, 0xd0cee21aU, 0x296e10b3U, 0x21047a05U, 0xd598fd7cU, 0xe85a7b3aU, 0x3eaffe63U, 0x20ebfa1dU, 0xb46bfc8U, 0x38231b44U, 0xd62bafdeU, 0x7f30e1c5U, 0xbea911f4U, 0x60edf95eU, 0xeb45bf6dU, 0x68349bc0U, 0xde31ec88U, 0x2b378264U, 0x68aa410eU, 0x85ff61ddU, 0x40c75340U, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0x18000000U, 0x54000000U, 0xfa000000U, 0x83000000U, 0xca800000U, 0x95c00000U, 0xb7a00000U, 0x2d300000U, 0x70f80000U, 0x1b5c0000U, 0x307a0000U, 0x75810000U, 0x89578000U, 0x9f72c000U, 0x8103a000U, 0xcd9d7000U, 0x2d550800U, 0x5d745c00U, 0xe6028a00U, 0xe5069d00U, 0x6f812a80U, 0xda5befc0U, 0xddf422e0U, 0xe8dfb290U, 0xcc2eab08U, 0x2d752d9cU, 0x9e0d82a2U, 0x2103c00bU, 0x3d8c229cU, 0x1543b22fU, 0xb974a857U, 0x4042fdeU, 0x32020234U, 0x5f1d0203U, 0xcc8d808dU, 0xa0c3c351U, 0x502c225eU, 0xb73b179U, 0x1b0caabfU, 0xde982e5fU, 0x4fd800c2U, 0x84ac0356U, 0xffa202e8U, 0xb12d0181U, 0x56f582f6U, 0x9e5fc155U, 0xcff62265U, 0x7c2b2d0U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x50000000U, 0x48000000U, 0x9c000000U, 0x42000000U, 0x51000000U, 0xc2800000U, 0x25c00000U, 0x65600000U, 0x9ff00000U, 0xfe280000U, 0xad5c0000U, 0xeda60000U, 0x8a070000U, 0xd088000U, 0x2086c000U, 0x24dbe000U, 0xeff33000U, 0x26354800U, 0xd9500400U, 0x63bdca00U, 0xd116c700U, 0x2862880U, 0x85d5f640U, 0x357b61a0U, 0xd7e9f030U, 0x6228aaa8U, 0xef543674U, 0xbca80122U, 0x489c00a3U, 0x28c60117U, 0x45f702ecU, 0xbb208047U, 0x11dac22dU, 0x8b7de0d3U, 0x34f433a6U, 0xe9bdcb70U, 0xdc16c488U, 0x22062884U, 0xa115f46aU, 0xda9b6347U, 0xf1d9f0adU, 0xbb60a993U, 0x8cf83686U, 0x6da60300U, 0x4a070280U, 0xad088140U, 0x7086c120U, 0x6cdbe270U, 0x73f33108U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0x38000000U, 0x4000000U, 0x76000000U, 0xdf000000U, 0x84800000U, 0x84400000U, 0xfca00000U, 0x5c300000U, 0x7e780000U, 0xf5c40000U, 0x617a0000U, 0xd1450000U, 0x75218000U, 0x65e54000U, 0x1503a000U, 0x6996b000U, 0x49c97800U, 0x53784c00U, 0x9848fa00U, 0x5ead0d00U, 0x5d335980U, 0x69ffbcc0U, 0xbf002160U, 0xb482f0d0U, 0x5c495ab8U, 0x88babeacU, 0x1221a12aU, 0xa567b07dU, 0x74afbb8U, 0x3a2c0dddU, 0xa968daf9U, 0xad5ffda6U, 0xe72203d6U, 0xbcf1025eU, 0x768380daU, 0x6d5442c4U, 0x472022cfU, 0x2cf2f168U, 0x3e915a94U, 0x514ebfc6U, 0x3523a177U, 0x85e6b0b5U, 0x65117a6dU, 0x518c4f60U, 0x4dcafb21U, 0x256c0e2bU, 0x4748dbd7U, 0xda2ffd74U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0x48000000U, 0x5c000000U, 0xaa000000U, 0xb5000000U, 0x17800000U, 0x42400000U, 0x6200000U, 0xddb00000U, 0x8de80000U, 0xacc0000U, 0x6fa0000U, 0x9e5b0000U, 0x6c3c8000U, 0x48a3c000U, 0xaa666000U, 0x841000U, 0x5ccd9800U, 0xe9f43c00U, 0x54d11a00U, 0x55e7ff00U, 0xeedf7a80U, 0x98efefc0U, 0xed48e3a0U, 0x2cb0d2b0U, 0xf46d7b08U, 0x5388ef64U, 0x2c4661d6U, 0x1d3411adU, 0xf1259a6eU, 0xd3383c6bU, 0x1a2b1951U, 0x97bcfc24U, 0x28e3fa1cU, 0x654c2c30U, 0x50ae8062U, 0x6e74c0c9U, 0xae80e012U, 0x67ccd34bU, 0xf57f7b8bU, 0x421fec01U, 0x1900e27cU, 0xd58cd320U, 0x9b5f78daU, 0xf3afef25U, 0x76e8e2e0U, 0x3640d0d0U, 0x20257b18U, 0x9ab4ed5cU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xb0000000U, 0x98000000U, 0x5c000000U, 0x12000000U, 0x7000000U, 0x4e800000U, 0x4ac00000U, 0xf7e00000U, 0x2b700000U, 0xa6a80000U, 0xbfdc0000U, 0x6e7a0000U, 0xa7210000U, 0x6f868000U, 0xb556c000U, 0xaaab2000U, 0xe5de7000U, 0xbd60e800U, 0x8fb3b400U, 0xf44e6a00U, 0x45397700U, 0x909f4880U, 0xb7c605c0U, 0xda7922e0U, 0xd12370b0U, 0x969c68a8U, 0x76c477acU, 0xf5e3c912U, 0x471c747U, 0x2c34822dU, 0xbb1bc05aU, 0x8c9fa09fU, 0xc5c5b0c9U, 0xcd7f4ad4U, 0xb7b605a2U, 0x185121efU, 0xcf3f7081U, 0xcb866ac8U, 0xeb557498U, 0x97ad48c4U, 0x684b075eU, 0xf72da065U, 0x2788b102U, 0x614bcabbU, 0xccadc727U, 0x34ce8219U, 0xbafac30cU, 0x9ef92246U, 0xe370e1U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x50000000U, 0x78000000U, 0x14000000U, 0x2a000000U, 0x69000000U, 0xe800000U, 0x54c00000U, 0x82200000U, 0xc6b00000U, 0x4b680000U, 0xcfcc0000U, 0x61b60000U, 0xeef10000U, 0xb08f8000U, 0xd7d4c000U, 0xc5a4e000U, 0xccfcb000U, 0xe583e800U, 0x9f40cc00U, 0xc6646a00U, 0x3580f00U, 0x10768a80U, 0xc55be40U, 0x19fae360U, 0x6d01b210U, 0xbc9a69c8U, 0x59d50cb4U, 0x8ea70b72U, 0x977c7fa7U, 0xf9c7801aU, 0x1ea8c1adU, 0xcf7ae27fU, 0xbdc1b066U, 0x4cba6bebU, 0xb2650e6aU, 0x994f08fbU, 0x71707c2cU, 0x3ed180e0U, 0xb29c3deU, 0xb83d6007U, 0x37a97324U, 0x21e08a7aU, 0x9914bc33U, 0xe69d6118U, 0x18d97152U, 0xec288859U, 0xfda8beedU, 0x38e36291U, 0xbf9472d9U, 0x80000000U, 0x40000000U, 0x20000000U, 0x10000000U, 0x28000000U, 0x84000000U, 0x82000000U, 0x55000000U, 0x37800000U, 0xb0400000U, 0x3be00000U, 0x6700000U, 0x37380000U, 0xb15c0000U, 0xc66e0000U, 0x57330000U, 0x814f8000U, 0xfe69c000U, 0xfb3c6000U, 0x87431000U, 0x2963d800U, 0x99a14400U, 0x945a00U, 0xa2d48500U, 0xa4263a80U, 0x31d49540U, 0x24b26220U, 0xd3001350U, 0xa0945a28U, 0xf2d48704U, 0xac263876U, 0xa5d49485U, 0x8eb260b9U, 0x20012ccU, 0x151458cdU, 0x1794864dU, 0xa0463b82U, 0x13e495c4U, 0x826a6196U, 0xb52c12b5U, 0xe4425ae1U, 0xf1fb8430U, 0xe767b9d7U, 0xbabe571aU, 0xf81980d8U, 0xcc06c3bcU, 0x361de33aU, 0xef19d207U, 0xce903972U, 0x81cb957cU, 0x5cabe0daU, 0x5f06d137U, 0x80000000U, 0x40000000U, 0x20000000U, 0x70000000U, 0x48000000U, 0x8c000000U, 0x9a000000U, 0x57000000U, 0x4b800000U, 0x50400000U, 0xca00000U, 0x65300000U, 0xe6780000U, 0x975c0000U, 0x1f220000U, 0xa1730000U, 0xc4ce8000U, 0xfb67c000U, 0xf3d22000U, 0xe0ffd000U, 0x9b851800U, 0x28462c00U, 0xe8b39a00U, 0x33ded00U, 0x6363ba80U, 0x7c13cc0U, 0x9ef023a0U, 0xaa8cd2f0U, 0xe6cb9bc8U, 0x2861eeacU, 0x8e41b866U, 0xdb23f2dU, 0xc3bea1f4U, 0xdaab1149U, 0xc839bb25U, 0xaaee3d78U, 0xb49ca29fU, 0x87d81320U, 0xdef73b30U, 0x8a89fee8U, 0x96ce829cU, 0x6067c10eU, 0x25223f1U, 0x97bfd39aU, 0x94a519e8U, 0x91362c87U, 0x986b9b74U, 0xa651ec12U, 0xd1b9b8bfU, 0x61ae3d0bU, 0x49bca222U, 0x95a810d7U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x70000000U, 0x88000000U, 0x4000000U, 0x66000000U, 0xc5000000U, 0x57800000U, 0xcac00000U, 0x99a00000U, 0x6c300000U, 0xe5f80000U, 0x3ecc0000U, 0x37b20000U, 0xd3b0000U, 0xa4678000U, 0xb9114000U, 0xfd86e000U, 0xcdd59000U, 0x1d348800U, 0xbc6ddc00U, 0xe50b0a00U, 0x67809d00U, 0xe2c7e880U, 0xeda20cc0U, 0x8226e2a0U, 0x24e590d0U, 0xf4c8938U, 0x3861dec4U, 0xc31908e6U, 0x28b9d2fU, 0xc5586a20U, 0xaf7f4d4fU, 0x1f92020fU, 0x2ecb02b0U, 0x2fbf8017U, 0x512d43bbU, 0x3e6ce33eU, 0x96129204U, 0xd190b19U, 0xf38b9c68U, 0xdcd86bbcU, 0xd4bf4c42U, 0x3fb201b9U, 0x493b01e7U, 0x62678113U, 0xc114322U, 0x2206e016U, 0x3159058U, 0xe294886bU, 0x155ddcd9U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xf0000000U, 0xb8000000U, 0x94000000U, 0xaa000000U, 0xb9000000U, 0x77800000U, 0x87c00000U, 0x5b600000U, 0xc2f00000U, 0xbe280000U, 0x97c40000U, 0xd36a0000U, 0x8ef50000U, 0x70338000U, 0x3cd4c000U, 0x89fae000U, 0xd4b99000U, 0x159aa800U, 0xd2d1a400U, 0x72e12a00U, 0xa6316700U, 0x93d9cb80U, 0x3179f4c0U, 0x1bfae160U, 0x39b99290U, 0xa81aa9c8U, 0x1c11a774U, 0xe6012b96U, 0x770165abU, 0xdc91c99bU, 0xdd4df730U, 0x138e32bU, 0xa74891dbU, 0x50232910U, 0x6cc0641bU, 0xa1e04be3U, 0x8a8353cU, 0x939b8131U, 0x55d0c2aaU, 0x1670e29aU, 0xef7c9231U, 0x38e12b2aU, 0x2f31655aU, 0x3c59cad1U, 0xd2b9f67aU, 0x529ae072U, 0xd64992f5U, 0xcbb2abc4U, 0xb515a47dU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x70000000U, 0x38000000U, 0xdc000000U, 0xde000000U, 0x6d000000U, 0x90800000U, 0x6dc00000U, 0x1e600000U, 0x34f00000U, 0xf6280000U, 0xebcc0000U, 0x3f720000U, 0x127d0000U, 0x62fa8000U, 0x5f2b4000U, 0x94fe000U, 0xd9b17000U, 0x2d948800U, 0x754d2400U, 0xb7a60a00U, 0x589a6700U, 0x49d3ea80U, 0x3c6a16c0U, 0xf7e7e260U, 0x33bd71b0U, 0xca868b18U, 0x92c02704U, 0x55f48bdaU, 0x30bd2473U, 0x2f0e0bc3U, 0xc3966610U, 0xc041eb83U, 0xab27177bU, 0xa3556244U, 0xdeaa3331U, 0x9a136bf4U, 0xdf005429U, 0x3b8882f0U, 0x3c5642f3U, 0x5356303U, 0xf65a3170U, 0x923b6bb3U, 0x29cc5623U, 0xac7a80e0U, 0x9feb40bbU, 0xa7afe06fU, 0xf08170d6U, 0xfddc88aeU, 0x76712651U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xb0000000U, 0x88000000U, 0xd4000000U, 0x46000000U, 0xd9000000U, 0x81800000U, 0xd5400000U, 0xd0600000U, 0xc0f00000U, 0xe0380000U, 0xf3040000U, 0x2820000U, 0xffdb0000U, 0xabbd8000U, 0x15534000U, 0x70616000U, 0x90efd000U, 0xd83fb800U, 0xaf059400U, 0x90803a00U, 0x60cdd500U, 0xf33cd980U, 0x418147c0U, 0x755a03a0U, 0x806f0090U, 0xf8e780b8U, 0xbc3c42f4U, 0x6106e13eU, 0x9d939361U, 0xa759585fU, 0xff660732U, 0x106160c7U, 0x60efd29aU, 0xb03fbb4bU, 0xcb0595f0U, 0x5e803904U, 0x6dcdd636U, 0x34bcdbfdU, 0x4dc1454dU, 0x24ba01a9U, 0x95df036fU, 0xc8bf831aU, 0x8fc8408bU, 0x83bce050U, 0x914c9294U, 0xe66d80eU, 0x15ee4649U, 0xcbbd8393U, 0xe5534338U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x90000000U, 0x8000000U, 0xfc000000U, 0xae000000U, 0x11000000U, 0x24800000U, 0x8d400000U, 0x88600000U, 0x45f00000U, 0x68280000U, 0x870c0000U, 0x918e0000U, 0xd3d70000U, 0xd62c8000U, 0x5e1b4000U, 0x69106000U, 0x60977000U, 0x47451800U, 0xc3653400U, 0x22679a00U, 0x7ee97700U, 0xb7bb7a80U, 0xf5d54540U, 0xfb2602a0U, 0xf49b02b0U, 0x65428218U, 0xc47c41f4U, 0x73f4e20aU, 0x8d303181U, 0xf193780bU, 0xa3d94766U, 0x6e280113U, 0x3a0c023eU, 0x330e0147U, 0x23970204U, 0xdccc809eU, 0x7bab43dbU, 0x3d86202U, 0x3e2b73f1U, 0x12031b73U, 0x5f0e35c2U, 0x858d1811U, 0x31d93563U, 0xf121986aU, 0x9f82767dU, 0x92d1f95dU, 0xdaa50401U, 0xbf5ce3e7U, 0x477c3098U, 0x80000000U, 0x40000000U, 0x60000000U, 0x30000000U, 0x58000000U, 0xa4000000U, 0x2000000U, 0x39000000U, 0x93800000U, 0x41c00000U, 0x80a00000U, 0x3e300000U, 0xf6780000U, 0xca140000U, 0xd5020000U, 0x3d810000U, 0xb6d98000U, 0xd43fc000U, 0x7363e000U, 0x9f8d1000U, 0x9fd96800U, 0x4fa05c00U, 0xfea2ea00U, 0xe12e9d00U, 0x3ee08b80U, 0x11484dc0U, 0xdff802e0U, 0x66d40350U, 0xfc2200e8U, 0xef7102b4U, 0x9818326U, 0xfcdbc373U, 0x4139e044U, 0x2ee8111bU, 0x195aeb95U, 0x13fa9ed7U, 0x98c2888fU, 0x63394e26U, 0x47f981d6U, 0xe2cfc14eU, 0xae3be0a2U, 0xbe691388U, 0x66036801U, 0x1b055e64U, 0xfa81680eU, 0xba445c27U, 0x3d78eab2U, 0x188b9ec0U, 0xf3430b45U, 0x96e28edaU, 0xcd406211U, 0x29e7d209U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x10000000U, 0xd8000000U, 0xb4000000U, 0xda000000U, 0xa1000000U, 0xcd800000U, 0x69400000U, 0xae600000U, 0x7ef00000U, 0x8c380000U, 0x340c0000U, 0x9a1e0000U, 0x10d0000U, 0xdd8f8000U, 0xb156c000U, 0x1a79e000U, 0xa4e6d000U, 0x2d38b800U, 0xf98d5400U, 0xf3493a00U, 0xaf669500U, 0xa3675880U, 0x3d6a8540U, 0x2e6003e0U, 0x3ef00390U, 0x2c380288U, 0x240c0014U, 0x421e033eU, 0xb50d01f1U, 0x78f82e7U, 0x1056c2daU, 0xd7f9e3bfU, 0xcda6d08eU, 0x8358bae1U, 0x877d552fU, 0x7f71392eU, 0x9b6a9711U, 0x397959f7U, 0x3c678512U, 0xf3ef804bU, 0x8fa6c020U, 0x3641e198U, 0x80ead3dcU, 0x6f26bacaU, 0x4c80545fU, 0xf4c6b91eU, 0xbf305569U, 0x749eb9bbU, 0xf0cc5550U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xb0000000U, 0xc8000000U, 0x8c000000U, 0x5e000000U, 0xbf000000U, 0xa9800000U, 0x68400000U, 0xd7e00000U, 0x15700000U, 0xbea80000U, 0x41c0000U, 0xb21a0000U, 0xf11b0000U, 0x6e9e8000U, 0x85c34000U, 0x6dada000U, 0x23991000U, 0xbd57d800U, 0x7b76c400U, 0x9b35a00U, 0x819e8700U, 0x34487880U, 0x51e8d5c0U, 0x5e6003a0U, 0xd3003f0U, 0x14800d8U, 0x2d6c020cU, 0x9ab200feU, 0xc607016dU, 0x2b048081U, 0xa3984308U, 0x7d532303U, 0xdb6a51e4U, 0xb9b27b6dU, 0x4983d781U, 0xb8568388U, 0xfef42c3U, 0xe17fa044U, 0xa4ae139dU, 0x691b59d9U, 0xfa828544U, 0x8fd2781dU, 0x78b3d699U, 0x2f1e8024U, 0x118342cdU, 0x8c4da371U, 0xb5e913d0U, 0x3c7fd90fU, 0x242ac51aU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xf0000000U, 0xa8000000U, 0x4000000U, 0xba000000U, 0xfb000000U, 0xaf800000U, 0x36400000U, 0xdce00000U, 0x42700000U, 0xc8b80000U, 0x298c0000U, 0xcb420000U, 0xce7f0000U, 0xc6bb8000U, 0x609ac000U, 0x6bd4a000U, 0x45b7d000U, 0xd3175800U, 0xeb952400U, 0x2c56da00U, 0xd7fce500U, 0x45fbf880U, 0xfaeef6c0U, 0x4f638220U, 0x7226c2d0U, 0xa94ea2c8U, 0xd974d03cU, 0x7736daf6U, 0xe7cce725U, 0x4ba3f925U, 0x9a12f73cU, 0x4b19826fU, 0xa795c3b6U, 0xc257235cU, 0xcee11146U, 0xbd61fb5dU, 0xdd2df5e1U, 0xe4c203ceU, 0xb83f0198U, 0xba5b82b4U, 0xd2eac12aU, 0xb6ca0a3U, 0x683bd058U, 0xa255580dU, 0xdeea2769U, 0x456d5812U, 0x8126261eU, 0xf2cf5bc9U, 0xfd29261bU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xb0000000U, 0x18000000U, 0x1c000000U, 0x96000000U, 0x9b000000U, 0x9c800000U, 0x34c00000U, 0x3d600000U, 0x94f00000U, 0xaba80000U, 0x60840000U, 0xd2c20000U, 0xde790000U, 0xa4668000U, 0x117a4000U, 0xdae62000U, 0x4ca03000U, 0xda176800U, 0x65102400U, 0x639bea00U, 0x92576700U, 0x1cb94b80U, 0xb20415c0U, 0x10683e0U, 0x598a41b0U, 0x874e23b8U, 0x72430dcU, 0x8c55684aU, 0x93a926cfU, 0x6c9d6adfU, 0x8cdd27ecU, 0xf1776ba9U, 0xaae026c2U, 0x34b3eaf0U, 0x76136518U, 0xeb1b4accU, 0xe48d1562U, 0x98c8017bU, 0xb3740101U, 0x13ea03adU, 0xa13d02bfU, 0xcf44839cU, 0x733343f1U, 0x7e48a3aeU, 0x32ae7302U, 0xe51b480bU, 0xa38d15d9U, 0xf2480081U, 0xacb4016dU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0x58000000U, 0x24000000U, 0xca000000U, 0xa1000000U, 0xe2800000U, 0xe4400000U, 0x85600000U, 0x44f00000U, 0x3f280000U, 0x62840000U, 0x245e0000U, 0xe56d0000U, 0x14f58000U, 0x673ec000U, 0x468de000U, 0xee4f3000U, 0x4479f800U, 0xf665f400U, 0x837a7a00U, 0xc3f23700U, 0xaabc1b80U, 0x7b5ec640U, 0x94f582e0U, 0xa73ec2d0U, 0x268de3c8U, 0xbe4f3354U, 0x1c79f9c2U, 0xd265f585U, 0x497a78b7U, 0x62f23706U, 0x483c1ae3U, 0x9f1ec548U, 0x11958098U, 0xe3cec1dcU, 0x19a5e3f6U, 0xdccb30d7U, 0x3827f81aU, 0x3708f435U, 0x5d8ff8efU, 0x5ccf6faU, 0xeb1f8e5U, 0x7151f627U, 0x55ec792eU, 0x15ab34e7U, 0x9adf9b02U, 0x1f3907a9U, 0x929be3f9U, 0x4c5633fdU, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0x78000000U, 0xb4000000U, 0xfe000000U, 0x8d000000U, 0x51800000U, 0xb5c00000U, 0xc7a00000U, 0xd1300000U, 0x6780000U, 0xc8940000U, 0x2a460000U, 0xf7610000U, 0x9b0b8000U, 0x508e4000U, 0xce54e000U, 0x11665000U, 0xb2122800U, 0x871afc00U, 0x4287aa00U, 0x7951bd00U, 0x5be6cb80U, 0x174cad40U, 0xeeed8260U, 0x92df4390U, 0xb5276398U, 0xa07c10a4U, 0x8180cb5eU, 0xedddae33U, 0x3be03a0U, 0x473502a7U, 0x476d83c1U, 0xd31f42f1U, 0xec87624eU, 0xec4c116bU, 0xae78c924U, 0x2489af89U, 0x105802baU, 0xec64010dU, 0x8b9e0103U, 0xfec5001fU, 0xcf358102U, 0xdb7b424eU, 0x811961fcU, 0x3b89124dU, 0xb6cd48f4U, 0x7332ec66U, 0xf9616227U, 0x3e1d1296U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x70000000U, 0x8000000U, 0x84000000U, 0x7e000000U, 0x49000000U, 0x24800000U, 0x55400000U, 0xd3600000U, 0x64f00000U, 0xf2280000U, 0x1840000U, 0x3bda0000U, 0xd9230000U, 0x2e0f8000U, 0x91064000U, 0xb89a6000U, 0xd74c7000U, 0x68661800U, 0xf374d400U, 0xb4fb9a00U, 0xea259700U, 0xfd9c7b80U, 0xc9c8a6c0U, 0x6a3583a0U, 0x3d9540d0U, 0xa9dde058U, 0x1a3e32f4U, 0x358e794aU, 0x2ddfa661U, 0x64280027U, 0x7c8402e2U, 0x95a0197U, 0x31630100U, 0xafef804aU, 0x6db640e1U, 0xc3526267U, 0xae787002U, 0x56741a27U, 0x1a63d728U, 0x80661ab6U, 0xc774d447U, 0xa2fb99d8U, 0x572595feU, 0xaf1c7bcbU, 0x5188a4f6U, 0xe3d5826dU, 0x452543c9U, 0xac15e2d1U, 0x2a0a3345U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0x78000000U, 0x9c000000U, 0x6a000000U, 0xeb000000U, 0x26800000U, 0x18c00000U, 0x76a00000U, 0x15300000U, 0x26680000U, 0x379c0000U, 0xcd560000U, 0xa4e10000U, 0xb9568000U, 0x4ae9c000U, 0xd447a000U, 0x4576f000U, 0xe511a800U, 0xfb989c00U, 0x1f592a00U, 0x73fc5f00U, 0x25d60880U, 0xc12e6c40U, 0x18688160U, 0x2294c230U, 0x5ec722c8U, 0xffbe329cU, 0xeca088d2U, 0x9637adbfU, 0x44e722e8U, 0x94e309bU, 0x42e88b59U, 0xe05bafa9U, 0xcb792196U, 0xf8033369U, 0x5c000a61U, 0xca0f6f8aU, 0x3b1e01fbU, 0x5e8d03beU, 0x84c880d2U, 0x1ca4c368U, 0xfe2f215bU, 0xe231f9U, 0x2f568839U, 0xbbe6ac4eU, 0xb1d9a06dU, 0x9f3bf0d7U, 0x7d792ab3U, 0x190c5ce2U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xd0000000U, 0xf8000000U, 0x44000000U, 0xc2000000U, 0xd000000U, 0x6b800000U, 0x4b400000U, 0xf0e00000U, 0x9bb00000U, 0xfb580000U, 0x38fc0000U, 0x57be0000U, 0x555d0000U, 0x4beb8000U, 0xb72ec000U, 0xba84e000U, 0x96c75000U, 0xfcbad800U, 0x61db9400U, 0x3e3e3a00U, 0xf31cc500U, 0xa084e080U, 0x4fc75240U, 0xd3ad960U, 0xb39b9650U, 0x9f5e3ae8U, 0x6aecc424U, 0x2bce226U, 0xaacb5359U, 0x3abcdb0dU, 0xeca9513U, 0x88b3bac6U, 0x2bd306a9U, 0x5f358095U, 0xe683c2efU, 0x60d7637cU, 0x1ba5929aU, 0xbb583b03U, 0x98fdc72eU, 0x87b1630dU, 0xad449273U, 0xfedbb96U, 0x753e05c1U, 0xb7860071U, 0xfd5100e9U, 0xb7ed8095U, 0x913fc2efU, 0xa589637cU, 0x848929aU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x10000000U, 0x8000000U, 0x94000000U, 0xb6000000U, 0x5d000000U, 0xdc800000U, 0x3ec00000U, 0x8d600000U, 0xcbb00000U, 0x8ad80000U, 0x8b740000U, 0x6eae0000U, 0xda5b0000U, 0x9fa78000U, 0x9cca4000U, 0x26766000U, 0xaa2fb000U, 0x78820800U, 0x30de1400U, 0xbc746a00U, 0x2d31a500U, 0xc3166180U, 0xa59fb140U, 0xac5a0ba0U, 0x62aa1610U, 0xb05a68f8U, 0xaaa624U, 0xbb51e02aU, 0x9125f0cfU, 0x51146ae7U, 0xb681a5c5U, 0xa1ce60e6U, 0xaaebb327U, 0x7cf409bbU, 0x71f1148bU, 0x457de8a3U, 0xffa0e59fU, 0xccc781a1U, 0xce7a41ecU, 0x2e2e6238U, 0xc69bb1c4U, 0xf9cc081aU, 0xd6f51567U, 0x4eebea9bU, 0x92ffe45bU, 0x50f601bbU, 0xabef008bU, 0x226982a3U, 0x5421409fU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x90000000U, 0xc8000000U, 0x14000000U, 0xd2000000U, 0x45000000U, 0x28800000U, 0xebc00000U, 0xb6600000U, 0xc9b00000U, 0x6dc80000U, 0x1640000U, 0xd43e0000U, 0xf6830000U, 0x80df8000U, 0x6df6c000U, 0xc5e9e000U, 0x81fe3000U, 0x7bf4a800U, 0xbaff5400U, 0x887d4a00U, 0x32b16700U, 0x7e41e180U, 0x192a3140U, 0xea02a8a0U, 0xc9185610U, 0xc69cca68U, 0xf8c4a644U, 0xc1f7826aU, 0x5be2c3fbU, 0xcaffe2dbU, 0xd0693299U, 0xeebd2b06U, 0xb85e9667U, 0x8e3d2b0dU, 0x879e9664U, 0xa5d2aa8U, 0x9b2e97a4U, 0x871528daU, 0x658a9583U, 0x374b29f7U, 0x1fb99737U, 0xf2dcabd7U, 0x98eb57e7U, 0x556b495fU, 0x26266793U, 0xc388628dU, 0xf04bf324U, 0x5a22c808U, 0xb587a6b4U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0xf8000000U, 0xac000000U, 0x1a000000U, 0xd1000000U, 0xd800000U, 0xfe400000U, 0x3ea00000U, 0xccf00000U, 0x78480000U, 0xcda40000U, 0x5c7a0000U, 0x21810000U, 0x244e8000U, 0xfbcc000U, 0x71606000U, 0x7e191000U, 0x5f0cb800U, 0x8a8b7c00U, 0x88ccda00U, 0xe4626f00U, 0xad886180U, 0x6e4d11c0U, 0x96beb860U, 0x28ee7c70U, 0x36585988U, 0xaaafaef4U, 0x9aee81deU, 0x34cc17dU, 0xe92860acU, 0x3bd10baU, 0xfb76ba93U, 0x70a7df1U, 0xb6825aceU, 0x3adeac0dU, 0xd16800acU, 0xee1401b2U, 0xf712002fU, 0x6e9501b3U, 0xc6dc83a1U, 0x8369c196U, 0x6b1ce2e1U, 0x4c80d1beU, 0x5bd8590dU, 0x24efaf24U, 0xbc4e834eU, 0xd3bcc1cdU, 0x736062ccU, 0xb31912c2U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xf0000000U, 0x8000000U, 0x84000000U, 0x3e000000U, 0xe9000000U, 0x50800000U, 0x7ec00000U, 0x30600000U, 0xfab00000U, 0x5cd80000U, 0xdb740000U, 0x11320000U, 0xd1870000U, 0x1a458000U, 0x98b54000U, 0x57d5e000U, 0xc0eeb000U, 0x947e8800U, 0x94b53400U, 0xadcb6a00U, 0xf7eb8500U, 0xddede180U, 0xb2eab2c0U, 0x67748ba0U, 0x33635d0U, 0x9284ead8U, 0x65ddc4b4U, 0xd3f7803aU, 0xf3f2409fU, 0xa3f06223U, 0xbbebf3c1U, 0xc7f3696aU, 0x75ef8533U, 0x26e7e28dU, 0xa169b374U, 0x663b0a2eU, 0x780074f5U, 0xcc1e8aa4U, 0x5a0536f6U, 0x27136b41U, 0xb19f841eU, 0xaa5fe029U, 0x70adb182U, 0x23d10b6fU, 0xf6f375ebU, 0xf9690b0dU, 0xfa3775b4U, 0x3a030b8eU, 0x97047425U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0x28000000U, 0xd4000000U, 0x42000000U, 0xb1000000U, 0xfb800000U, 0x9cc00000U, 0xf0e00000U, 0xd0300000U, 0x16c80000U, 0x5f40000U, 0x21b60000U, 0xbf070000U, 0x648b8000U, 0x854c000U, 0xe0b16000U, 0x9c86d000U, 0x34462800U, 0x16bfe400U, 0x3f974a00U, 0x56c93700U, 0xa5f96380U, 0x11b2d240U, 0xc7102920U, 0x9888e610U, 0x9e54cba8U, 0x13a9f694U, 0xd61e0166U, 0x530302f7U, 0x7a95810dU, 0x1f57c323U, 0x9024e230U, 0xb6d112c3U, 0x35e2ca3bU, 0x59aef65cU, 0x43158339U, 0xf297c0eeU, 0xfb44e008U, 0xaa211044U, 0xfbcacb2eU, 0x586af793U, 0x366b8233U, 0xf964c218U, 0x45f96217U, 0x81b2d07dU, 0x8f1029bbU, 0x1c88e41cU, 0xf454ca19U, 0x76a9f6feU, 0x80000000U, 0x40000000U, 0xe0000000U, 0xb0000000U, 0x38000000U, 0xf4000000U, 0xee000000U, 0x1f000000U, 0xe4800000U, 0x39400000U, 0xea600000U, 0x2f300000U, 0xa7580000U, 0x6d740000U, 0x6fba0000U, 0xf8090000U, 0x540d8000U, 0xbe094000U, 0x970f2000U, 0x2886f000U, 0x2358f800U, 0x1b644400U, 0xd4b7da00U, 0x7a92b500U, 0xbe572180U, 0xaaf2f3c0U, 0x7062fb60U, 0x9e2d4510U, 0xbcda5958U, 0xabf6acU, 0x848001aaU, 0xc9400359U, 0x3260035bU, 0x6b300149U, 0x7158026cU, 0x867402a5U, 0x653a0309U, 0xde4902ccU, 0x5aed80d5U, 0xa8794141U, 0xda372238U, 0x6ac2f353U, 0xebbaf9f2U, 0x8e19469aU, 0xef005931U, 0x3c92f59fU, 0x7d558327U, 0x3c7d42dbU, 0xc4352289U, 0xadcff10cU, 0x4b357bb5U, 0x615d0451U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xf0000000U, 0x98000000U, 0x14000000U, 0x6a000000U, 0xc9000000U, 0x4e800000U, 0xdd400000U, 0x84200000U, 0x53700000U, 0xe580000U, 0xdbbc0000U, 0x74ba0000U, 0xcd350000U, 0x5dfd8000U, 0x731dc000U, 0xaf856000U, 0xbfcb7000U, 0xd770b800U, 0xec5ecc00U, 0xceadda00U, 0x2c29bd00U, 0x3f676080U, 0x204272c0U, 0x10b738e0U, 0x7f360f90U, 0x20f539c8U, 0xa78f0e74U, 0x23cab812U, 0x616bce91U, 0x335059caU, 0xaf347ca8U, 0x8e20161U, 0x8b890397U, 0xadc78199U, 0x5a68c39bU, 0xa0d8e047U, 0x56e6b3b4U, 0x988dd972U, 0x1259bd41U, 0x2dbf6122U, 0xbbe722cU, 0x5cad386bU, 0xe1330c1aU, 0xd3f0b985U, 0x481ece08U, 0x3c0dd8d1U, 0x4619bf2fU, 0x471f60b5U, 0x758e72b5U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x90000000U, 0x8000000U, 0x8c000000U, 0x66000000U, 0x71000000U, 0x7c800000U, 0x6a400000U, 0x7e200000U, 0xa2700000U, 0x85480000U, 0xa7a40000U, 0xb6be0000U, 0x9a3b0000U, 0x18648000U, 0x7a5b4000U, 0xb635e000U, 0xce6f3000U, 0x73449800U, 0xdeb4ec00U, 0x46397a00U, 0x967fdf00U, 0x1743e180U, 0xa4b03140U, 0x593e1ba0U, 0x17e4ac70U, 0x67801bb8U, 0xc1dfacf4U, 0xf9e499eaU, 0x5a84ed2dU, 0x3b5179aaU, 0x72abdc50U, 0x5035e3d5U, 0x7f6f32a3U, 0xefc49b05U, 0x24f4ecebU, 0x30197909U, 0xb80fdc55U, 0xf40be0beU, 0x721433eaU, 0x93001870U, 0xe79fafe5U, 0x1c49a3bU, 0x19f4ee41U, 0xca997ad9U, 0x334fdfc0U, 0xfeabe13dU, 0x3624315fU, 0xe681b43U, 0x934bad08U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x70000000U, 0xa8000000U, 0xd4000000U, 0x4a000000U, 0x9b000000U, 0x3b800000U, 0x56400000U, 0x4ee00000U, 0xdab00000U, 0x6b480000U, 0xc86c0000U, 0xca6a0000U, 0x95730000U, 0x9cf38000U, 0x5da1c000U, 0x1edd2000U, 0x97399000U, 0x58017800U, 0xbc00b400U, 0x3e145a00U, 0xa1152700U, 0x89f2080U, 0xb9d692c0U, 0x52b0f820U, 0xf4e7690U, 0x8a78f988U, 0xf562763cU, 0x4cf2f946U, 0x85a175f5U, 0x62c97bf5U, 0x92cb7a3U, 0x891e5b9eU, 0x1c9627b7U, 0x53c4a162U, 0xb9ab53d1U, 0x9ccfd987U, 0x828e5ecU, 0xf18003f8U, 0xd400004U, 0xd56001e2U, 0xfcf00047U, 0x8da8021aU, 0xc6dc0115U, 0xeb220045U, 0xc61f033bU, 0x6d19806aU, 0x9e92c32dU, 0xcccea2e1U, 0x10285189U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x70000000U, 0x78000000U, 0x7c000000U, 0xda000000U, 0x45000000U, 0xfb800000U, 0x94c00000U, 0xeae00000U, 0x4c300000U, 0xf7c80000U, 0x4e6c0000U, 0xc66a0000U, 0x2690000U, 0x47c8000U, 0xeb66c000U, 0x2deee000U, 0x3ea55000U, 0x9a842800U, 0x795ea400U, 0x3922ca00U, 0x1457f700U, 0x76ace080U, 0xfe9052c0U, 0xf5aab60U, 0xae3d6430U, 0xaedaa888U, 0xbffd67e4U, 0x1fbaa806U, 0x170d6587U, 0x7a92a925U, 0x69516453U, 0x9130aa7cU, 0x6054662dU, 0xa8a62920U, 0x1d9ba547U, 0x6bd44945U, 0x846836e3U, 0x2b768134U, 0x8dffc329U, 0x4eba6256U, 0xe29f9268U, 0x548c894U, 0xe33ef4aeU, 0x51506073U, 0x8d3690bbU, 0x6a544928U, 0xe5a83463U, 0xe2168023U, 0x590fc054U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x10000000U, 0xc8000000U, 0x8c000000U, 0x82000000U, 0x83000000U, 0xc9800000U, 0xb0400000U, 0x3ee00000U, 0xc8b00000U, 0xbb480000U, 0xdb740000U, 0x8afe0000U, 0xdeb30000U, 0x9e4c8000U, 0x8ff7c000U, 0x3a272000U, 0x968bd000U, 0x93c3f800U, 0xf1ae7400U, 0x65ccda00U, 0x4a1a700U, 0x99592380U, 0x2878d340U, 0x9b6f7aa0U, 0x2ae9b670U, 0xaea3fb28U, 0x465e773cU, 0xcbe4daaeU, 0x3425a78dU, 0x978f237dU, 0xd94fd093U, 0x8875fabeU, 0xeb697433U, 0xf2fe58c8U, 0xeaa565eaU, 0x48528207U, 0xcaf4c1eaU, 0x7ea3a101U, 0xee48109bU, 0x57fadbb2U, 0x7e26a695U, 0x988ba249U, 0x92cc1231U, 0xbb2cd915U, 0x1c11a60fU, 0x8a1123e0U, 0x6f0cd2d6U, 0x5b9178a9U, 0xfb5ab667U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x70000000U, 0x98000000U, 0x84000000U, 0x16000000U, 0x99000000U, 0x16800000U, 0x9e400000U, 0x3e600000U, 0x9a300000U, 0x17480000U, 0xe40000U, 0xf8620000U, 0xcb350000U, 0x8dd78000U, 0xe4b84000U, 0x5500e000U, 0x4c847000U, 0x9d4c5800U, 0xcbfb6400U, 0x81e4ba00U, 0xaaeb1700U, 0xa362e180U, 0x5ab172c0U, 0xf01bd9e0U, 0x580327d0U, 0x64045838U, 0x661f6774U, 0x106b982U, 0x929e16ddU, 0x88556343U, 0xa77930c1U, 0x8cb3391cU, 0x891357dfU, 0x3e8203deU, 0x62450222U, 0xdc7f82adU, 0x8d2c430bU, 0x1ccae1fdU, 0x9e2570a2U, 0xc151d83cU, 0x79e2253eU, 0x9ef9dba3U, 0xcd762440U, 0x37b3d971U, 0x689726e5U, 0xdb4e5be6U, 0x5afe6556U, 0xfb7b3b2fU, 0x3eb755d6U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0x58000000U, 0xc000000U, 0x3a000000U, 0x5d000000U, 0xf3800000U, 0x8400000U, 0x57e00000U, 0x81b00000U, 0x75480000U, 0x54740000U, 0xe1f60000U, 0x26a90000U, 0xbbce8000U, 0xffb8c000U, 0xe651e000U, 0xfced5000U, 0x752eb800U, 0x83849400U, 0xa0575a00U, 0x33edc700U, 0xbfa7e380U, 0x46445240U, 0xcce038e0U, 0x7d3c5570U, 0xd786bb88U, 0x96409644U, 0x54e958a6U, 0x1130c715U, 0xbd9f6071U, 0x93559057U, 0xab7f5882U, 0x2369c753U, 0xb779e214U, 0xe16953aeU, 0xd670ba91U, 0x20e99577U, 0xd727d952U, 0xb288044bU, 0x39ce8228U, 0x3eb8c104U, 0x17d1e0c6U, 0xf5ad51a5U, 0xb34eba59U, 0x5b749603U, 0x4b7f599cU, 0xb369c5eaU, 0x8f79e237U, 0xbd695262U, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0xa8000000U, 0xd4000000U, 0xd6000000U, 0xb3000000U, 0xc1800000U, 0xe7c00000U, 0xdba00000U, 0xf700000U, 0x55580000U, 0xdde40000U, 0xa3020000U, 0xd9830000U, 0xfbc38000U, 0x29be4000U, 0xc269a000U, 0xf3ccd000U, 0x2dba0800U, 0x2c73ec00U, 0xccd1aa00U, 0x463c3d00U, 0x7aa82380U, 0xb3f192c0U, 0xdc102b20U, 0xd2017c90U, 0x5d0203f8U, 0xfe83009cU, 0x8c4381deU, 0x8d7e4293U, 0x7049a2c8U, 0xcf7cd0f2U, 0x75420963U, 0x4de7ed86U, 0xfb0baadfU, 0xa59b3e8eU, 0xf9c9a18dU, 0x4cbcd13dU, 0xb0e20a93U, 0xd597ec8eU, 0x11d3aacbU, 0xf8bf3c84U, 0x96eba3b4U, 0xce8fd29cU, 0x4598a98U, 0xc97daf2aU, 0xfe400befU, 0x64eee0U, 0xb6c82930U, 0xcf257e28U, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0xa8000000U, 0xb4000000U, 0x66000000U, 0x93000000U, 0x57800000U, 0x4f400000U, 0x2d200000U, 0x99700000U, 0x77d80000U, 0xd7e40000U, 0xc6120000U, 0xc3130000U, 0xef8f8000U, 0x23544000U, 0x572ba000U, 0xd87e1000U, 0xd557d800U, 0x5c3a2c00U, 0xf3ee7a00U, 0x38173d00U, 0x2c162380U, 0x1a0950c0U, 0x310bfb20U, 0xa847f10U, 0x3fd80138U, 0x53e4019cU, 0x68120146U, 0x941302b1U, 0x760f834aU, 0x4b144188U, 0x4b8ba0f3U, 0x9d4e1376U, 0xd82fdb99U, 0x5dee2d6eU, 0x6f047a12U, 0xb5903ce4U, 0x7253a0bdU, 0x2daa1073U, 0x4fbdda31U, 0x32bd2e0dU, 0x522bfa1cU, 0xf4f47c81U, 0x19800165U, 0x28400058U, 0x7ca001ebU, 0x3530017aU, 0xa57801a7U, 0xb5d40023U, 0x80000000U, 0x40000000U, 0x20000000U, 0x70000000U, 0x38000000U, 0x34000000U, 0x1e000000U, 0xf3000000U, 0x86800000U, 0xc6c00000U, 0xf5a00000U, 0x68700000U, 0x7580000U, 0xebec0000U, 0x881a0000U, 0x6c010000U, 0x7a058000U, 0xa50b4000U, 0x799aa000U, 0x6a483000U, 0xde6bc800U, 0xe8480c00U, 0x2f6b6a00U, 0xdfc13d00U, 0xfe252280U, 0x8b3270c0U, 0xfaace860U, 0xbce77d10U, 0x38800298U, 0x5c0021cU, 0x6b2002e2U, 0xeab00117U, 0xd4f8012cU, 0x449c026aU, 0x17c203b3U, 0xb22d01c2U, 0x813f8027U, 0x67ba4104U, 0xf167201eU, 0x4cdf7285U, 0x28b36813U, 0x5ed3c92U, 0x31f22bfU, 0xfe8372b8U, 0xd2d16aacU, 0x9bb03f8aU, 0xa378a043U, 0xb5d5312aU, 0x332c4b93U, 0x8eae4d72U, 0x82ee4b4fU, 0xbb834f50U, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0x98000000U, 0x84000000U, 0x72000000U, 0x73000000U, 0xdd800000U, 0x86400000U, 0x4e600000U, 0xff300000U, 0x3ed80000U, 0x4a40000U, 0x61960000U, 0x510000U, 0xe76f8000U, 0x1da4c000U, 0xb0b2000U, 0x49815000U, 0xc433800U, 0xe96e6400U, 0xc8be1a00U, 0x4f8e3500U, 0xe54aa380U, 0x6be09040U, 0xad699be0U, 0x9abef750U, 0xc8f81a8U, 0xf0d4c2dcU, 0xf1b3233eU, 0x15155295U, 0x648d382fU, 0x9cdb67f5U, 0xafa79a0aU, 0x580bf722U, 0xa416018bU, 0x4211024aU, 0xbb0f80c2U, 0xc194c0dbU, 0x705320e2U, 0x4f65529eU, 0x51b53b25U, 0x650f6557U, 0xcc8998c1U, 0xd0cef608U, 0xc1b782d9U, 0xdd00c219U, 0x789d238cU, 0x6ad05323U, 0xaeacb816U, 0xf68aa73cU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0x18000000U, 0x9c000000U, 0x32000000U, 0x3d000000U, 0x5c800000U, 0xb3400000U, 0x83200000U, 0x59700000U, 0x90c80000U, 0x19f40000U, 0xd18e0000U, 0xc7c90000U, 0x447c8000U, 0xfc57c000U, 0x42bae000U, 0x46a3b000U, 0x28a1b800U, 0x47a6ac00U, 0xb6355a00U, 0x41fc1f00U, 0xed806380U, 0x5c97140U, 0xf169d9e0U, 0x24dbdc30U, 0x5ff282a8U, 0xca9ec184U, 0x1046603aU, 0x38b47079U, 0x9fbb5b1eU, 0x4a351dd8U, 0xe3fce287U, 0xc89eb2f6U, 0xc55339f7U, 0x70386ff5U, 0x9af33a3bU, 0x5a086cfbU, 0xe91b3910U, 0x8a8c6f38U, 0xb05d387cU, 0xc8b16ee6U, 0x17afba4fU, 0xce2fad49U, 0x4de9d87dU, 0xc79bdd64U, 0xa4d283c1U, 0x9feec2e9U, 0xaa8e6166U, 0x80407244U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0x38000000U, 0x94000000U, 0xd6000000U, 0x99000000U, 0x3800000U, 0x43400000U, 0xc5a00000U, 0x59f00000U, 0x2ec80000U, 0x4be40000U, 0xa9ca0000U, 0x9d790000U, 0x9b198000U, 0x6c964000U, 0x9d2e000U, 0x8d67d000U, 0x7305d800U, 0xf0897c00U, 0x73d53a00U, 0x5673af00U, 0x3f836180U, 0x295593c0U, 0xf6bd3b60U, 0x8967ae90U, 0x8d0161b8U, 0x15889334U, 0x3a4eb8d6U, 0xf638efa9U, 0x22a201f8U, 0x7f6d013aU, 0xc41b8375U, 0x1e0b42ecU, 0xd50162f2U, 0x71889007U, 0x344eb885U, 0xcb38ecc4U, 0xcf2200feU, 0x312d00a5U, 0xd43b83daU, 0x9dbb4225U, 0x3de96234U, 0x20dc9056U, 0x76ecb8e9U, 0x4455efd8U, 0xd339828aU, 0x8b2642fdU, 0xef3ae090U, 0xe133d0b8U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x30000000U, 0x38000000U, 0xa4000000U, 0xb6000000U, 0x29000000U, 0x48800000U, 0x7a400000U, 0x9ba00000U, 0x16f00000U, 0xd80000U, 0xeef40000U, 0x4ca0000U, 0x88e90000U, 0x25df8000U, 0x5c6c4000U, 0x4d98e000U, 0x58d6b000U, 0x3aeb9800U, 0x6adb9c00U, 0x35e17a00U, 0xe3502d00U, 0xab3f6180U, 0x28bef1c0U, 0x1d617b60U, 0xe9102e50U, 0xe89f6038U, 0xaa4ef334U, 0x93b9787aU, 0x8ae42d8dU, 0x12d561acU, 0x71e7f222U, 0x6546fb35U, 0xba386f84U, 0xc43583d2U, 0xd13543e1U, 0x5bbf63b2U, 0xb6fef36dU, 0xd0c17860U, 0xe6e02cd0U, 0x98c76378U, 0x9afaf314U, 0xbad37a0aU, 0x3dfd2dc5U, 0x7f52e3d0U, 0xb93fb3a4U, 0xb7b41bfeU, 0x7cf7dc03U, 0xdbd999e7U, 0x9769fb9U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0x38000000U, 0x1c000000U, 0xd2000000U, 0x51000000U, 0xc9800000U, 0x65c00000U, 0x23600000U, 0x21b00000U, 0xb4580000U, 0x8abc0000U, 0x48d60000U, 0x48fd0000U, 0x1d608000U, 0xeab3c000U, 0x38db6000U, 0x40fe9000U, 0xa97ec800U, 0x1cac7400U, 0xa7cbaa00U, 0xa63e500U, 0x543be080U, 0x938d5340U, 0xc0c5aa60U, 0xbce2e630U, 0x4b6d61a8U, 0xe5b39034U, 0x4a464aeeU, 0xa1a3b693U, 0xf446c94bU, 0x2aa07461U, 0xd8c5a994U, 0x70e2e4a8U, 0x16d60b4U, 0x38b391aeU, 0x69c648f3U, 0x8963b57bU, 0xcca6c8c9U, 0x3fd07520U, 0x867dab06U, 0xbe2ee747U, 0xde836155U, 0xdb4293faU, 0x8828c97bU, 0xa191779fU, 0xa1cb29ffU, 0xdd6025cfU, 0xab88167U, 0x8cfc1d3U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x90000000U, 0xd8000000U, 0xdc000000U, 0x3a000000U, 0x4d000000U, 0x60800000U, 0xf0c00000U, 0x76a00000U, 0xe5700000U, 0xc0580000U, 0xfe740000U, 0x3fde0000U, 0x57210000U, 0x772c8000U, 0x4736c000U, 0xef31e000U, 0x7b283000U, 0x45384800U, 0xee2fec00U, 0xf9afaa00U, 0x24e2dd00U, 0xc21d6180U, 0xa11ef340U, 0xf289a8e0U, 0x29c7dd30U, 0x2837e188U, 0xbebd3344U, 0xa16acaeaU, 0xc6482cb7U, 0x196ac938U, 0xca482e26U, 0x1b6acbb3U, 0xcb482e18U, 0x99eac89cU, 0xaa882d56U, 0xb5cacaf1U, 0xf2382ed1U, 0x63b2caebU, 0x19fc2dceU, 0xea94c807U, 0x55d92e5aU, 0x623e4a7fU, 0xbbbaec9cU, 0xc5fd2afcU, 0xd0851c0cU, 0x18d801a4U, 0x2b40370U, 0x4b7e0142U, 0xb35100c9U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x30000000U, 0xc8000000U, 0xcc000000U, 0xd6000000U, 0x3f000000U, 0xc9800000U, 0xe5400000U, 0x65e00000U, 0xb9300000U, 0x11980000U, 0x915c0000U, 0x17f20000U, 0xac2f0000U, 0xf9188000U, 0x4e9f4000U, 0x88cf2000U, 0xaaa1d000U, 0xfdd51800U, 0x923b5400U, 0x7a02ba00U, 0x3905c500U, 0xae988080U, 0x18df41c0U, 0x52af21a0U, 0xf9d1d3f0U, 0x882d1878U, 0x931757ccU, 0xcf88ba7eU, 0x8246c669U, 0x986a0231U, 0x8e7300b1U, 0x516a8071U, 0x8f04351U, 0x15b7a061U, 0x744e9339U, 0xd7623bc5U, 0x2ff684e3U, 0x483da176U, 0x730d93e1U, 0x5f90ba85U, 0x7a5ac483U, 0x9c780326U, 0x946c0069U, 0xb86a0131U, 0xfe730331U, 0x396a8231U, 0xf4f040b1U, 0xbb7a071U, 0x874e9351U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x30000000U, 0x38000000U, 0xf4000000U, 0x26000000U, 0x33000000U, 0xe4800000U, 0x95c00000U, 0x42e00000U, 0xbbb00000U, 0xe0980000U, 0x2bd40000U, 0x55fa0000U, 0x71310000U, 0x8a418000U, 0x5fae4000U, 0x6e88a000U, 0x4d3f000U, 0x6b6ba800U, 0x3df6a400U, 0xcd228a00U, 0x804b1500U, 0x8ea18180U, 0xa71e41c0U, 0xb290a360U, 0x7ec7f310U, 0x6271a878U, 0x3077a71cU, 0x657b090aU, 0x52f1579bU, 0x13b32319U, 0xfc8cb179U, 0xf1c289e9U, 0x8cfb1551U, 0x74b980adU, 0xee0a4377U, 0x5f0aa3f4U, 0xe686f2e1U, 0x88c829eaU, 0x597de604U, 0x18f1a806U, 0x22b7a769U, 0x51b0a5eU, 0x7f81540aU, 0x6d4b221bU, 0xd28b0d9U, 0x20408b19U, 0x5eae1579U, 0xaf1a03e9U, 0x7e810051U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x10000000U, 0xb8000000U, 0xcc000000U, 0xd2000000U, 0x99000000U, 0x77800000U, 0x35c00000U, 0xe6e00000U, 0x50b00000U, 0x5d880000U, 0x40c40000U, 0xb37e0000U, 0x54650000U, 0xb8e68000U, 0x3bb7c000U, 0x431f6000U, 0xaa8cd000U, 0x1458c800U, 0xfc2ca400U, 0xfec12a00U, 0xc867b700U, 0xf2ee8180U, 0x9eb3c340U, 0x4e816160U, 0x7259d370U, 0x9b3649a8U, 0xd25f6554U, 0xab204896U, 0x9a4e65b3U, 0xcf30cbc5U, 0x3c58a6d5U, 0x4837298dU, 0xc6b431U, 0x93760393U, 0xa4610246U, 0x10f883d8U, 0x4fa2c07cU, 0x5d11e002U, 0xe18f1285U, 0xfad1a926U, 0xbe7177a8U, 0x2de96054U, 0x7e2dd216U, 0xffc04973U, 0x83fe64e5U, 0xbd38ca45U, 0x955ca595U, 0x77a928edU, 0x5113b741U, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0xd8000000U, 0x5c000000U, 0x9e000000U, 0x31000000U, 0xf7800000U, 0xb400000U, 0xf1e00000U, 0x29300000U, 0x61980000U, 0xfe440000U, 0xa4660000U, 0xdd610000U, 0x8ee88000U, 0x77ac4000U, 0xa14be000U, 0xcaedd000U, 0x95b91800U, 0x3e4e1400U, 0x847a7a00U, 0xed7f8500U, 0x6f08380U, 0xf3a84040U, 0x634de2e0U, 0x65fcd030U, 0x53299918U, 0xc29655b4U, 0x7ecf9ba6U, 0x35b755e9U, 0x4e471b99U, 0x6c6b14c9U, 0x3974faa1U, 0x1cf2c66dU, 0xb3e18fU, 0x3bd9d178U, 0xa8271becU, 0x5e1b1672U, 0x110cfbbfU, 0xc786c6c8U, 0x834de0b4U, 0x75fcd026U, 0xeb2999a9U, 0xce965779U, 0x38cf9bf9U, 0x58b75539U, 0x27c71819U, 0x562b1489U, 0x3f14f841U, 0x3e82c65dU, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0x58000000U, 0xbc000000U, 0x6e000000U, 0x85000000U, 0xf7800000U, 0xf9c00000U, 0xb6a00000U, 0x9ef00000U, 0x40980000U, 0x354c0000U, 0xf5f20000U, 0x720d0000U, 0x1b148000U, 0xa9e4000U, 0x24b6000U, 0x79655000U, 0x11464800U, 0x47ec2c00U, 0x901aa00U, 0x819b3d00U, 0xe0de8280U, 0x9f2f43c0U, 0xba35e1e0U, 0xbdba1030U, 0x3c6ba8d8U, 0x86da3ce4U, 0x2e380066U, 0x57bc00f3U, 0xfb6a0184U, 0x7241035cU, 0x416682b8U, 0x3d53405eU, 0xc1ffe36dU, 0x680b1309U, 0xa4152865U, 0xf2057e05U, 0x5b15e0bfU, 0x2a8a12b4U, 0xb253a9ceU, 0x21663eefU, 0xad5200d6U, 0x29fd0121U, 0x8c0c82f3U, 0x76124084U, 0x191963dcU, 0x29985078U, 0x24cac93eU, 0xfd3e6d9dU, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0xd8000000U, 0xcc000000U, 0xba000000U, 0x11000000U, 0xb1800000U, 0xbec00000U, 0xd1600000U, 0x98300000U, 0xa4980000U, 0x11440000U, 0xb0b20000U, 0x6fd50000U, 0x40ea8000U, 0xb6f2c000U, 0x5df36000U, 0x9d7b1000U, 0x62326800U, 0xd58bb400U, 0x50d38a00U, 0xd6766500U, 0x72b88380U, 0x62d7c2c0U, 0x361e2e0U, 0xfd3dd0f0U, 0x930b0988U, 0xdc91a774U, 0xd41622eU, 0x42ae13bfU, 0x9ad8e803U, 0x5f79775bU, 0x6f20e8b7U, 0x960d7415U, 0x1b0ae938U, 0x189c777eU, 0x335269e7U, 0xdbbb46fU, 0x944b8939U, 0x3732677aU, 0x1a0a82a3U, 0xc102c229U, 0xf98b6382U, 0x5acf119fU, 0x7f786b13U, 0xff2ab7a3U, 0xbe13098bU, 0xf15a42fU, 0x6e936099U, 0x984b12aaU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0x8000000U, 0xc000000U, 0x9e000000U, 0x77000000U, 0xf9800000U, 0x4400000U, 0x7c600000U, 0x83b00000U, 0xea880000U, 0xbfdc0000U, 0x89220000U, 0x45570000U, 0xef88000U, 0xc8664000U, 0xd9b32000U, 0x2f9cd000U, 0x9f443800U, 0xbffc400U, 0xc8e79a00U, 0x6b695700U, 0xaa3a8280U, 0xf6c143c0U, 0xf7a3a0a0U, 0x909690f0U, 0x4add1a58U, 0xa1a815ecU, 0xcb99239eU, 0x1d57d2cdU, 0xdafeba97U, 0x427e86dfU, 0x4a4387bU, 0x3b0fc7c1U, 0x878f9976U, 0x634555f6U, 0xbdf08359U, 0x83fa41d5U, 0x4f12074U, 0xd57bd0bdU, 0xed34bb0fU, 0x7458793U, 0xfff6b915U, 0x72e28454U, 0xbe663a8dU, 0xb2a8c677U, 0x701f18cfU, 0xe80f1733U, 0x1c09a1e5U, 0xa61d920cU, 0x80000000U, 0x40000000U, 0x20000000U, 0x10000000U, 0x78000000U, 0xac000000U, 0x5a000000U, 0x11000000U, 0x53800000U, 0xf3400000U, 0x63e00000U, 0xed300000U, 0xca980000U, 0x4cc0000U, 0x2ea60000U, 0x1dd0000U, 0xeb328000U, 0x898ac000U, 0xa2436000U, 0x10635000U, 0xe739800U, 0xd16e5400U, 0x45fa7a00U, 0xbe3bc500U, 0x14148280U, 0x9617c140U, 0x7b11e160U, 0x2a9992f0U, 0x74c8f888U, 0x66b106f4U, 0xc5d7e226U, 0x65349289U, 0x6e827841U, 0xbac7c439U, 0xa1aa8145U, 0xcd46c017U, 0xace56278U, 0x1be5010U, 0x9d411bb8U, 0xf4e4975cU, 0xbdb91bc2U, 0xbf589497U, 0x49e71a54U, 0xb439959aU, 0x5d0b9b7bU, 0x799255feU, 0xaa447bc9U, 0xf46ac521U, 0x906000c9U, 0x4e7002cdU, 0xf1780363U, 0x55fc029eU, 0x80000000U, 0x40000000U, 0x20000000U, 0x30000000U, 0xd8000000U, 0xc4000000U, 0xb2000000U, 0x1d000000U, 0xf1800000U, 0xe4400000U, 0xfce00000U, 0x34300000U, 0xbd180000U, 0x818c0000U, 0x1c420000U, 0x8fd0000U, 0x5e338000U, 0x6416c000U, 0xc219e000U, 0xe51f9000U, 0x59fb800U, 0x8e409400U, 0x25f7da00U, 0x77b4c500U, 0x44420280U, 0x8cfd01c0U, 0xcc3383e0U, 0x4916c3d0U, 0xeb99e1a8U, 0xc55f9364U, 0x4b7fb90eU, 0xa77097e5U, 0x696fda35U, 0x1278c641U, 0xa4e00387U, 0xb0300316U, 0x2f180165U, 0xac8c01f5U, 0x35c200a1U, 0x28bd02d7U, 0x10d3837eU, 0x4d26c1e1U, 0x8e81e32bU, 0x80d392ecU, 0xe53db986U, 0xb28d9531U, 0xc6dc5903U, 0x922e04c8U, 0x9a19e1a8U, 0x611f9364U, 0x979fb90eU, 0xa34097e5U, 0x80000000U, 0x40000000U, 0x60000000U, 0x30000000U, 0x28000000U, 0x2c000000U, 0x96000000U, 0x7000000U, 0x14800000U, 0xd4c00000U, 0x4c600000U, 0x23300000U, 0xc3180000U, 0x8e840000U, 0x15ca0000U, 0x47e30000U, 0xe7708000U, 0xe1af4000U, 0x70c62000U, 0xe6607000U, 0xca270800U, 0xe48d9400U, 0xdcdbaa00U, 0x3061a500U, 0xad2a0380U, 0xc01301c0U, 0x20088120U, 0x501b4070U, 0x181422f8U, 0x40770acU, 0xba1d8a0aU, 0x9101d74fU, 0x138d0b63U, 0xc05e96dfU, 0x98b329bdU, 0x6f4ae776U, 0xe026207bU, 0x4d907255U, 0x9b5f08b2U, 0x523996f5U, 0xa089aaf4U, 0x6c6a6e0U, 0x91708250U, 0x96af4208U, 0x2c462314U, 0x2ea072c6U, 0x38470955U, 0xecbd94c4U, 0x9d43aaf8U, 0x6d25a4acU, 0xe000000aU, 0x7000024fU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0x38000000U, 0xe4000000U, 0x4e000000U, 0x7b000000U, 0x80800000U, 0x46c00000U, 0x3f600000U, 0xda300000U, 0x17080000U, 0xd29c0000U, 0xb7c20000U, 0xbae10000U, 0x5f6b8000U, 0xa3d4000U, 0x3f0aa000U, 0x3e857000U, 0x25ddc800U, 0x6bf2b400U, 0xeafeea00U, 0xb76b8700U, 0xc6220280U, 0x9d1103c0U, 0xd7838060U, 0x74514350U, 0x98a0a1d8U, 0x68c8727cU, 0x947c4b3aU, 0x72b2f4f7U, 0xbdddc8ffU, 0x7ff2b573U, 0xbcfeea21U, 0x186b87e2U, 0x30a200e3U, 0x44d101f1U, 0x266382faU, 0x93a1407fU, 0x3048a25bU, 0x26a473b5U, 0xbd64bacU, 0xc0fff6caU, 0x427c4b9fU, 0x1db2f54bU, 0x6b5dc84dU, 0x9632b5a0U, 0x751ee9d8U, 0x1b9b867cU, 0xd64a013aU, 0x71bd03f7U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xb0000000U, 0xd8000000U, 0x5c000000U, 0xe2000000U, 0xe5000000U, 0x5d800000U, 0x4ac00000U, 0x10a00000U, 0xcaf00000U, 0xe9080000U, 0x17940000U, 0x4bda0000U, 0x432d0000U, 0x5f208000U, 0x1d3fc000U, 0x2824e000U, 0x1da51000U, 0xd36be800U, 0x7dc9cc00U, 0xb0358a00U, 0xe1be1f00U, 0xe17a0380U, 0xf0dd01c0U, 0x69a882e0U, 0x156bc3b0U, 0xf6dee0e8U, 0x82b812e4U, 0x97e36afeU, 0x58920ebfU, 0x67436b34U, 0xe2620d00U, 0x364b6866U, 0x19f60eb5U, 0x47916a6bU, 0xe3db0de2U, 0xa731eb3bU, 0x5124ce5cU, 0xc2350bc2U, 0xccb1de0dU, 0xe8f6e1b1U, 0x6c1c10a5U, 0xfa116a75U, 0xd91b0c0bU, 0xf91e812U, 0x77d4cef3U, 0x113d08e8U, 0x6225dee4U, 0x1cace0feU, 0x80f111bfU, 0x80000000U, 0x40000000U, 0x60000000U, 0xd0000000U, 0x48000000U, 0xfc000000U, 0xca000000U, 0x4d000000U, 0xe1800000U, 0x2a400000U, 0x2a200000U, 0xf0f00000U, 0x2b180000U, 0x6e840000U, 0x1ad60000U, 0xfbf30000U, 0xf5868000U, 0xec4ec000U, 0x553ce000U, 0x387f9000U, 0x9ec87800U, 0x15fb8c00U, 0xa6841a00U, 0xa6c9dd00U, 0x51ee0380U, 0x68870240U, 0x45c880a0U, 0x8379c0b0U, 0xd84c6208U, 0x233252c4U, 0xdf6a18aeU, 0xe24edd9dU, 0x9626812eU, 0x5afec26aU, 0xb604e184U, 0xc70b9139U, 0xcc8679e7U, 0x1bcc8da5U, 0x48749a95U, 0x26c41c6aU, 0x11ec6284U, 0x88251b9U, 0x95d21b27U, 0xcb7adfc5U, 0x24488045U, 0xe939c0b2U, 0x926c6298U, 0x3c2520bU, 0xbc721988U, 0x70cadc84U, 0x46f0820eU, 0xec0dc02dU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0x18000000U, 0xec000000U, 0x5a000000U, 0xc3000000U, 0x72800000U, 0x67c00000U, 0x33200000U, 0x59700000U, 0xcd080000U, 0x17840000U, 0x445a0000U, 0x21650000U, 0xd10e8000U, 0xb58ec000U, 0x5b4f2000U, 0x11f03000U, 0x99d1a800U, 0xae2f1c00U, 0xa6ea0a00U, 0x9d44ef00U, 0xb0f20180U, 0x145103c0U, 0xc97c83e0U, 0xc51fc370U, 0x3393a108U, 0xda5ff0bcU, 0x4c6a08a2U, 0xd684ee93U, 0x39d20306U, 0xbe2103faU, 0x6ef48078U, 0x595bc1fbU, 0x1ee9a245U, 0x614af36bU, 0x22ec8b3dU, 0x134e2d5fU, 0x15e721e3U, 0xd7c4300eU, 0xeb23a846U, 0x557e1f5aU, 0xa71689a8U, 0xcc9b2c23U, 0xdac1a1a1U, 0x1cbef26dU, 0x213e8888U, 0x9e6f2f7cU, 0xf193a142U, 0x355ff2e3U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x30000000U, 0x58000000U, 0x4c000000U, 0x8e000000U, 0x5d000000U, 0x15800000U, 0xd6400000U, 0x2e200000U, 0x84f00000U, 0x5b080000U, 0xc8c0000U, 0xc9d20000U, 0xf6d0000U, 0x78528000U, 0x83204000U, 0x697e6000U, 0xf1471000U, 0xf4bf7800U, 0x5c348c00U, 0xcfe19a00U, 0xff8edf00U, 0x715a0080U, 0x34a103c0U, 0xfc2083e0U, 0xfffd41f0U, 0xa784e358U, 0x3d5b5044U, 0xbabb1a6eU, 0xa1229e2dU, 0xea7662eeU, 0x71cb124aU, 0x136d7b54U, 0x3e598ee1U, 0xfa33192bU, 0xe6ee9e3fU, 0xb804607eU, 0x1c161085U, 0x4617fbf2U, 0x7905cf60U, 0x8f977b97U, 0x49488fe2U, 0xe8bb9b6fU, 0x1a2fdf51U, 0xb6fa80d3U, 0x701c40abU, 0x380463d8U, 0xdc161384U, 0xe617f98eU, 0x4905cfddU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x90000000U, 0x98000000U, 0x84000000U, 0xe6000000U, 0x13000000U, 0x78800000U, 0xafc00000U, 0x1ee00000U, 0xccb00000U, 0xde080000U, 0x27040000U, 0x768e0000U, 0x30c10000U, 0x9c638000U, 0x127c4000U, 0x4d76a000U, 0x2ff97000U, 0x613ce800U, 0x6a432400U, 0xe6afca00U, 0x17031700U, 0x5e880180U, 0x5cc40140U, 0xf66e01e0U, 0xfb710050U, 0x44eb81f8U, 0xdb8425cU, 0xbb98a27aU, 0x6f4872f3U, 0x45376999U, 0x3c4b658dU, 0x1dbf6903U, 0xe38f64aeU, 0xb516b22U, 0x333e651fU, 0xb75ae84bU, 0xe13627daU, 0xaa4a4b3cU, 0x6ba57eaU, 0x8713212bU, 0xc68030b5U, 0xd8c7c9ffU, 0x10771464U, 0xe86e03f9U, 0x3c710162U, 0xa26b8180U, 0xa5784140U, 0xa3f8a1e0U, 0x9b387050U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xb0000000U, 0x28000000U, 0x8c000000U, 0x2a000000U, 0x9b000000U, 0xe7800000U, 0xfb400000U, 0x86200000U, 0x43f00000U, 0xae080000U, 0x4d0c0000U, 0xde820000U, 0xbbd30000U, 0x98f48000U, 0x2984c000U, 0xa64e2000U, 0xc0bb9000U, 0x5c259800U, 0x90e2ac00U, 0xd5953a00U, 0x442ff00U, 0x67a80080U, 0xb9bc01c0U, 0x7caa0220U, 0x9e2f00f0U, 0x27fe8008U, 0xa81bc05cU, 0x4c18a336U, 0x8a1c5181U, 0x2b173986U, 0xcf91fee2U, 0x775c82a0U, 0xac38c33bU, 0xd8e42342U, 0x4994911bU, 0xb65b19b9U, 0x58b96c79U, 0xf82d9a52U, 0x36eeaec8U, 0x649738f7U, 0x78d1ff6cU, 0x7b7c801eU, 0xc4c8c0adU, 0xb96c22f8U, 0x73d8915fU, 0xc4f91880U, 0x3b9a6dc0U, 0x29511820U, 0xa9266ff0U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0xc8000000U, 0x3c000000U, 0xda000000U, 0x53000000U, 0x2e800000U, 0x11400000U, 0x94a00000U, 0x7e700000U, 0xac080000U, 0x2040000U, 0x771a0000U, 0x309f0000U, 0x6c5e8000U, 0xf3cc000U, 0xc8a12000U, 0x5467b000U, 0xd713f800U, 0x2092bc00U, 0x745e5a00U, 0xcb22cf00U, 0xe6a00180U, 0xe17003c0U, 0x708800a0U, 0x4c440030U, 0xdf3a0048U, 0x30af01bcU, 0xa07683d2U, 0x3108c109U, 0xa99322e8U, 0x9ccb1bcU, 0xf4ff78e2U, 0x63457df1U, 0xbb3f96cU, 0xa2e2bfcaU, 0xe25659edU, 0xaa26cf3eU, 0x773a0033U, 0xfcaf025dU, 0x527683b6U, 0x6e08c0afU, 0x9513227fU, 0x778cb257U, 0x94df7bcbU, 0x5f757c59U, 0x1d9bf800U, 0xcfd6bc00U, 0xade45a00U, 0xe6cdcf00U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x70000000U, 0x28000000U, 0x54000000U, 0xba000000U, 0x85000000U, 0x43800000U, 0x29c00000U, 0x70e00000U, 0x81b00000U, 0x4c080000U, 0xa60c0000U, 0xbb1a0000U, 0x248b0000U, 0x934f8000U, 0xf4bdc000U, 0xe797e000U, 0x7bc0d000U, 0x1f94800U, 0x8352400U, 0xc8d32a00U, 0xc17f3700U, 0xa9600080U, 0x9d7002c0U, 0xf7680220U, 0x2a7c0090U, 0x15f20248U, 0xd2370344U, 0x9ddd83e6U, 0xdafac2b3U, 0xfca260cdU, 0x38612a1U, 0x49c928f3U, 0xa0f4349eU, 0xd9af81dcU, 0x300dc10aU, 0x481fe221U, 0x840cd280U, 0xe2034973U, 0xf90e276dU, 0xad94ab71U, 0x16cef4dbU, 0xb66de2aaU, 0xebfbd142U, 0x153eca65U, 0x5744e7e6U, 0x76bec800U, 0xce84e400U, 0x8e5eca00U, 0x6b34e700U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0x18000000U, 0xec000000U, 0xf2000000U, 0xa1000000U, 0x8e800000U, 0xcbc00000U, 0xdd200000U, 0xe7900000U, 0x2a080000U, 0xed040000U, 0xec8e0000U, 0x2c70000U, 0xa7a18000U, 0x325ec000U, 0xa4272000U, 0x251e1000U, 0x83cee800U, 0xf92fbc00U, 0x71925200U, 0xfd0fb900U, 0xc4880080U, 0x16c40040U, 0xc9ae00e0U, 0x79570070U, 0x67a98018U, 0x925ac0ecU, 0x342920f2U, 0x4d1910a1U, 0x77cf688eU, 0xe7217ccbU, 0x229d72ddU, 0xd285a9e7U, 0x81c0e8aaU, 0x28bcadU, 0xf313d20cU, 0xb4c17972U, 0xa0a7203fU, 0x93de109eU, 0xda6ee8b6U, 0xe87fbcf4U, 0xe23a5215U, 0x715bb9deU, 0xa3ae00deU, 0x745700fbU, 0xfb298080U, 0x889ac040U, 0x7f8920e0U, 0x8d491070U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0x18000000U, 0xbc000000U, 0xce000000U, 0xab000000U, 0xbe800000U, 0x98400000U, 0x17200000U, 0x17500000U, 0xe2080000U, 0xbd0c0000U, 0x89820000U, 0xf8c10000U, 0x3c618000U, 0x2fbc000U, 0xa314e000U, 0xe32eb000U, 0x9d55e800U, 0xb028400U, 0x6e8df200U, 0xa0493500U, 0xbb280080U, 0xc15c00c0U, 0xf50a0020U, 0xcd8d0010U, 0xbac38018U, 0x516ac0bcU, 0xb37d60ceU, 0xf7d970abU, 0x94308beU, 0x88ad3498U, 0xd8999a17U, 0xbee07117U, 0x94b91262U, 0x3f37857dU, 0x5af5e829U, 0xff128428U, 0x1d25f204U, 0x3e5535aeU, 0x118200f5U, 0x84c10034U, 0xd26180cdU, 0xb9fbc028U, 0x594e0dfU, 0xc76eb093U, 0x4475e880U, 0xb75284c0U, 0x3205f220U, 0x85053510U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xf0000000U, 0xb8000000U, 0x84000000U, 0xd6000000U, 0x83000000U, 0xdc800000U, 0x6f400000U, 0x56200000U, 0x80b00000U, 0x5a080000U, 0xc90c0000U, 0x9d860000U, 0xaecf0000U, 0x5aeb8000U, 0x37584000U, 0xb6d56000U, 0x1a1c3000U, 0x3dffc800U, 0x992bf400U, 0x763be200U, 0x844acb00U, 0xe6a80080U, 0x95fc00c0U, 0x952e0060U, 0xfc3300f0U, 0xa54580b8U, 0xd72b4084U, 0x2130e0d6U, 0xa6c77083U, 0xc6e728dcU, 0xf550846fU, 0xabd2ca56U, 0x79994f80U, 0xdc374adaU, 0xf5420f09U, 0xff2faa7dU, 0xed397f9eU, 0x4cc68202U, 0x17eafb83U, 0x7cd9c838U, 0x9b14f42dU, 0x9c7862efU, 0x65ee8b01U, 0x79d36012U, 0xec9330acU, 0xe3b44880U, 0xb683b4c0U, 0x7e468260U, 0xbfaafbf0U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xb0000000U, 0x38000000U, 0xd4000000U, 0xca000000U, 0xa7000000U, 0xd9800000U, 0xc8c00000U, 0x9ce00000U, 0xec500000U, 0x76080000U, 0xf10c0000U, 0x38860000U, 0x184b0000U, 0xd8a38000U, 0x12fd4000U, 0xddf4a000U, 0x987e7000U, 0x16bf9800U, 0x83558c00U, 0xe3834e00U, 0xf7c10500U, 0x41680080U, 0x669c00c0U, 0xa1ee0060U, 0xdad700b0U, 0xeb4d8038U, 0xb2a40d4U, 0x1d3920caU, 0x289430a7U, 0x84e6b8d9U, 0x2851bcc8U, 0x540df69cU, 0xa0cb9ecU, 0xc70bf6f6U, 0x6987b931U, 0xf0c876d8U, 0x48eaf968U, 0x2654d600U, 0xd10889b6U, 0x28854ecfU, 0xf04a059bU, 0x84ab80ddU, 0x34f14048U, 0x64f2a034U, 0x2cf57010U, 0xa0fc1880U, 0xef8ccc0U, 0x5bffee60U, 0xf17375b0U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xb0000000U, 0x78000000U, 0xec000000U, 0x52000000U, 0x13000000U, 0x43800000U, 0xd0c00000U, 0x9de00000U, 0x1f900000U, 0x5b080000U, 0x97840000U, 0xceca0000U, 0x6ceb0000U, 0x37178000U, 0x2446c000U, 0x88a12000U, 0x5fbb3000U, 0x6bf73800U, 0x2b568c00U, 0xe0e11e00U, 0x3511d900U, 0x5f4a0080U, 0xef2b0040U, 0x497780a0U, 0x5b16c0b0U, 0x36492078U, 0x3baf30ecU, 0xac353852U, 0xc3398c13U, 0x5abc9e43U, 0xad7c19d0U, 0x7d1ca01dU, 0x8b46f05fU, 0xf12998fbU, 0xb87f7c27U, 0x739506b6U, 0x49036580U, 0x2489a6e5U, 0x3d459577U, 0xc4203eebU, 0x46fae97fU, 0x69d538aeU, 0xc0a98c28U, 0x8bb49e31U, 0x75f819edU, 0xda56a078U, 0xc86df0ecU, 0x4a5e1852U, 0x4069bc13U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xb0000000U, 0xa8000000U, 0xc4000000U, 0x2e000000U, 0xdb000000U, 0x3f800000U, 0xf0400000U, 0x85200000U, 0x18100000U, 0xdd080000U, 0x60840000U, 0x1ce0000U, 0x1e6b0000U, 0xaba8000U, 0xf1544000U, 0x16aee000U, 0xa257b000U, 0xfd2ef800U, 0x841a8400U, 0x7f089200U, 0xe1802100U, 0x63460080U, 0xceaf0040U, 0x6e5480e0U, 0x472f40b0U, 0x691c60a8U, 0xf787f0c4U, 0xc44e182eU, 0xe32634dbU, 0xb71cea3fU, 0x648ee5f0U, 0x8fc07205U, 0x95689158U, 0x2d3478bdU, 0x6d1ec490U, 0x798e7249U, 0x4f43916aU, 0xc4aef80cU, 0x2b5a84aeU, 0xba892e7U, 0x62d02139U, 0xacee006fU, 0x827b00e8U, 0x19b280e9U, 0xfad040f2U, 0x80e0e028U, 0x887cb084U, 0x5cb478ceU, 0xb65ec46bU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xf0000000U, 0x38000000U, 0xbc000000U, 0xea000000U, 0xd9000000U, 0x16800000U, 0xb6c00000U, 0xcce00000U, 0x2dd00000U, 0x3f080000U, 0x7d8c0000U, 0x954a0000U, 0x4eaf0000U, 0xaf38000U, 0x9eb3c000U, 0xea9aa000U, 0xd4a39000U, 0x2bf86800U, 0x9435ec00U, 0x465f8e00U, 0xf94a3d00U, 0xaca20080U, 0xf7f300c0U, 0x2e3180a0U, 0x5750c0f0U, 0x6bc32038U, 0x4c6f50bcU, 0x81948eaU, 0xcc69bcd9U, 0xc8174616U, 0x6c6341b6U, 0x381e664cU, 0x546311edU, 0x8414ae1fU, 0xbe696d4dU, 0x5d11488dU, 0xa8e5bcc2U, 0xebdd4678U, 0x640c410bU, 0xc60de6aeU, 0x5b00d1c7U, 0xbb860e3bU, 0xce46fde6U, 0xf52320bbU, 0xc4bf5093U, 0x6b9148b8U, 0x2e25bc7cU, 0xbf3d464aU, 0x5dc4129U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xb0000000U, 0xd8000000U, 0xe4000000U, 0xb6000000U, 0x57000000U, 0x28800000U, 0x8c00000U, 0x9ea00000U, 0x3ef00000U, 0x8880000U, 0x18c40000U, 0x16ae0000U, 0xb2fb0000U, 0x82858000U, 0x1dca4000U, 0xdf256000U, 0xc5be7000U, 0x3c670800U, 0xb55acc00U, 0x77f48a00U, 0xeb019f00U, 0x3a858080U, 0x9ca4040U, 0x512560e0U, 0xc6be70b0U, 0x7ae708d8U, 0xe9acce4U, 0x77d48ab6U, 0x8a319f57U, 0x842d80a8U, 0x273e4048U, 0xd1a3607eU, 0x5271708eU, 0xe64488d0U, 0xb96f8cfcU, 0x3cda6aa0U, 0xe0beafe5U, 0xe5ea682aU, 0x4a10bc55U, 0x451582a1U, 0xc994534bU, 0x97528a6cU, 0xeefe9f09U, 0x208e00b7U, 0xc4cb00feU, 0xf4ad80a8U, 0x8bfe4048U, 0x1903607eU, 0x8b81708eU, 0x80000000U, 0x40000000U, 0x60000000U, 0xb0000000U, 0x78000000U, 0x94000000U, 0x6a000000U, 0xdb000000U, 0x60800000U, 0xea400000U, 0xed600000U, 0xe9500000U, 0x8880000U, 0x96440000U, 0xbb660000U, 0x45b0000U, 0x350f8000U, 0x398d4000U, 0x6dc0a000U, 0x51a6b000U, 0xb3718800U, 0x493fe400U, 0x4c547600U, 0x99092500U, 0xa78f8080U, 0x6ccd4040U, 0x9220a060U, 0xadb6b0b0U, 0x24198878U, 0x936be494U, 0x185a766aU, 0xd30625dbU, 0xac8e00e0U, 0xc44f00aaU, 0x9461808dU, 0xbed24059U, 0x7c492070U, 0x2060f002U, 0x4d6a8d1U, 0x6f4014dfU, 0xaceb5e55U, 0x109f71d3U, 0x332bfe00U, 0xfe39c1f8U, 0x92da765bU, 0xa246252fU, 0x416e006fU, 0x775f00f9U, 0x98980e0U, 0x55c640aaU, 0xa5a7208dU, 0x697ff059U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x30000000U, 0x68000000U, 0x2c000000U, 0x36000000U, 0x13000000U, 0x63800000U, 0x62400000U, 0x78a00000U, 0x89300000U, 0xf880000U, 0x344c0000U, 0xfbaa0000U, 0xb2b30000U, 0x29ce8000U, 0x56eec000U, 0x57996000U, 0xcdba3000U, 0x1c44b800U, 0xb7a2e400U, 0x14bdea00U, 0x62c42300U, 0x716e8080U, 0x2fdec0c0U, 0x901160a0U, 0xe5f63030U, 0xb9eeb868U, 0x3a11e42cU, 0x68f36a36U, 0x456ae313U, 0x3dd7e0e3U, 0x914f0a2U, 0xfb7dd8d8U, 0xef28d4b9U, 0x59715267U, 0xde2ac718U, 0xcbf96a4dU, 0x8ee9e361U, 0xd391606aU, 0x77b630c4U, 0x94eb8e7U, 0xaf21e458U, 0x397b6a4dU, 0x4e26e3bcU, 0x93fde03aU, 0xcae7f061U, 0xc99358e3U, 0x52b614a2U, 0x79c032d8U, 0xaeecf7b9U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0x28000000U, 0x4000000U, 0x4a000000U, 0xad000000U, 0xce800000U, 0xffc00000U, 0x45200000U, 0x19900000U, 0x92880000U, 0x79cc0000U, 0xb6220000U, 0x28130000U, 0x22ca8000U, 0x43ac4000U, 0xf256a000U, 0x85a1d000U, 0xe1526800U, 0xa425bc00U, 0x491ff200U, 0xb243c900U, 0x436a8080U, 0xf8fc40c0U, 0xe37ea020U, 0x2e3dd030U, 0xe2d86828U, 0x456abc04U, 0xcbff724aU, 0xf2f089adU, 0xae74a04eU, 0xf0b2d03fU, 0x518e865U, 0x2c49fc29U, 0x9c6952baU, 0x8772197dU, 0xb430e87cU, 0x77d5fc45U, 0x97e352ccU, 0x523d198cU, 0x54d0681fU, 0x9e66bc58U, 0xfe7d7219U, 0x8b38940U, 0x39162099U, 0x7a4290a1U, 0x5764484eU, 0xaaf72c3fU, 0x6273ba65U, 0xaeb8e529U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x70000000U, 0x78000000U, 0x74000000U, 0xf6000000U, 0x5f000000U, 0x7f800000U, 0x5d400000U, 0xe0e00000U, 0xf0100000U, 0x99880000U, 0xea4c0000U, 0xc3620000U, 0x27570000U, 0xdc6f8000U, 0xb8db4000U, 0xd1256000U, 0x503ef000U, 0x2d3a7800U, 0x4bb19400U, 0x6e70ee00U, 0xa85cb100U, 0x6be78080U, 0xc99740c0U, 0xc3c76020U, 0x7129f070U, 0xe035f878U, 0x753ad474U, 0x4fbd8ef6U, 0xe07e415fU, 0x8357f8ffU, 0xe26dd49dU, 0xcbd20ec0U, 0x5ca50180U, 0xdc729861U, 0x9953245eU, 0x6f687615U, 0x15549508U, 0x2d62765bU, 0x9c5f9551U, 0x7de7f667U, 0xc69fd54fU, 0xb44f1613U, 0x206d6538U, 0x82df8e63U, 0x2c2941e4U, 0xf6b8787fU, 0x28f6945dU, 0xfd976ee0U, 0xd5cbf1f0U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0xa8000000U, 0xe4000000U, 0x66000000U, 0x11000000U, 0xff800000U, 0x30c00000U, 0x90a00000U, 0x72700000U, 0xd1880000U, 0x75cc0000U, 0xd12a0000U, 0xcfbd0000U, 0x94a28000U, 0xa4724000U, 0x18846000U, 0x16401000U, 0xcbef7800U, 0xcc104c00U, 0x6e5dea00U, 0xabbc7700U, 0x32aa8080U, 0x157e40c0U, 0x370e60a0U, 0x8e8d10d0U, 0xbf45f8a8U, 0xd86e0ce4U, 0xaed38a66U, 0x21f16711U, 0xd34f787fU, 0x4a604cf0U, 0xd1d5ea30U, 0xfb7077a2U, 0xd20080f9U, 0x1f034051U, 0xaa8ce017U, 0x794f500eU, 0x196998c3U, 0xf9521c70U, 0xf53ef2eeU, 0x25e02b75U, 0x29121265U, 0xffdf7b49U, 0xbe738a0fU, 0x93816706U, 0xa2c778ffU, 0xefac4c30U, 0xa8ffea90U, 0xd0cd7772U, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0xe8000000U, 0x4c000000U, 0xe000000U, 0x49000000U, 0x93800000U, 0x81c00000U, 0x49600000U, 0xdc300000U, 0x51880000U, 0x86c40000U, 0xb3e20000U, 0x3e7f0000U, 0x71268000U, 0x5f90c000U, 0x305ae000U, 0xa0379000U, 0xd789b800U, 0x53c5dc00U, 0x3667f600U, 0x52bc1300U, 0xe9ce8080U, 0x4564c040U, 0xf230e020U, 0xe88c90f0U, 0xfd4d38e8U, 0x7e2a1c4cU, 0x791b960eU, 0xe41b4349U, 0x9d9dd813U, 0x37568cc1U, 0x5abeae69U, 0x35c55f2cU, 0x736c4e39U, 0xef36cf8aU, 0xd107f61dU, 0x778c13c7U, 0xe3c680aaU, 0xfe60c022U, 0xeeb2e0bfU, 0xfc39089U, 0x4063b8f3U, 0x6fbedc51U, 0x20437651U, 0x27a3d378U, 0x23dae093U, 0x61f79081U, 0xbee9b849U, 0x7ff5dcdcU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xd0000000U, 0x68000000U, 0x8c000000U, 0xe6000000U, 0xbf000000U, 0x3d800000U, 0x85c00000U, 0x59a00000U, 0x67d00000U, 0x47880000U, 0x54c40000U, 0x272a0000U, 0x819d0000U, 0xc0ee8000U, 0x3d3cc000U, 0xdbbc6000U, 0x49faf000U, 0x6c935800U, 0x6b9c00U, 0xf07e7a00U, 0xb35ccd00U, 0x18c68080U, 0x2128c040U, 0x4e9e60a0U, 0x4563f0d0U, 0x5cf7d868U, 0xe81a5c8cU, 0x77249ae6U, 0xa99efdbfU, 0xece3b8bdU, 0xb34acc5U, 0xcb5c2f9U, 0xf87c61b7U, 0xf5142afU, 0xe6cda198U, 0xaa2ba2e1U, 0x711f91aeU, 0x15a69ab5U, 0x61d7fda4U, 0x888f382cU, 0xd1416c8dU, 0x46e52238U, 0xb2335132U, 0xfe32fabdU, 0xf8390da3U, 0x373e603dU, 0xb2b3f085U, 0xd37fd859U, 0xe0de5c67U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0xb8000000U, 0x54000000U, 0x5e000000U, 0xfb000000U, 0xbd800000U, 0xe6400000U, 0x8be00000U, 0x12900000U, 0xa6880000U, 0xcbcc0000U, 0xb5a60000U, 0x9d750000U, 0x52138000U, 0xc2414000U, 0x9defe000U, 0x359cb000U, 0xf90d5800U, 0x648ca400U, 0x72ce1e00U, 0x712e7900U, 0xdfb58080U, 0xcb3440c0U, 0xf1fc6060U, 0x5cddf050U, 0x6162b8b8U, 0xe3501454U, 0x5e23465eU, 0xfc32ddfbU, 0xb6739e3dU, 0x97963926U, 0x100fe06bU, 0x180cb082U, 0x6405587eU, 0xb600a4cfU, 0x17081e53U, 0xb78b7932U, 0x434e0031U, 0xcd69001fU, 0x495d80cbU, 0xcb284091U, 0x52b2606cU, 0x1b4f0e9U, 0xf03f383fU, 0x2c7854dcU, 0xea912685U, 0x52862d72U, 0xa5cca635U, 0xa6ae6d79U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0xe8000000U, 0xd4000000U, 0xf2000000U, 0xc9000000U, 0x43800000U, 0x30400000U, 0x41600000U, 0xb7f00000U, 0xf6880000U, 0xf5cc0000U, 0xba260000U, 0x4190000U, 0xeb68000U, 0x54694000U, 0x82752000U, 0x75cb9000U, 0x7a2fb800U, 0x6416c400U, 0x9eb77600U, 0xbc624f00U, 0x56708080U, 0x87c040c0U, 0xb32ba060U, 0x279ed090U, 0xaef498e8U, 0xfd0854d4U, 0xe1884ef2U, 0x7144cbc9U, 0x46e456c3U, 0x9db0dff0U, 0xaae9b8a1U, 0xf3bfc4e7U, 0xb5e9f67eU, 0xf3370fb1U, 0x332ba020U, 0xe79ed0d9U, 0xcef498dfU, 0x6d08543dU, 0x9884e68U, 0xa544cb26U, 0xb4e456bfU, 0x54b0df2fU, 0xe969b871U, 0xc3ffc42dU, 0xf489f62bU, 0x44c70f24U, 0xc5a3a053U, 0x1252d02eU, 0x80000000U, 0x40000000U, 0x20000000U, 0x70000000U, 0xe8000000U, 0xb4000000U, 0xfa000000U, 0x9000000U, 0x31800000U, 0xd8c00000U, 0x35200000U, 0x25900000U, 0xda880000U, 0xfc440000U, 0xb2620000U, 0x4b770000U, 0x1ab68000U, 0x5e174000U, 0x8341a000U, 0x1ce19000U, 0x2d389800U, 0xf1d74c00U, 0xbce53200U, 0x1d302900U, 0x39dc8080U, 0x78e44040U, 0xf352020U, 0x84d1d070U, 0xb367b8e8U, 0xdef59cb4U, 0x80760afaU, 0x4e35f509U, 0x3155aab1U, 0x59a36598U, 0x26dbb295U, 0x86636915U, 0xf17f2092U, 0x33b2d078U, 0x1f9b3880U, 0xb381dc86U, 0x9dcb2a39U, 0xf2a0253bU, 0x225012fdU, 0x7121f9a8U, 0x779b3853U, 0x4781dcc0U, 0x47cb2a29U, 0x8ba0254bU, 0xfbd012d9U, 0x1de1f96cU, 0xb8bb384fU, 0x6b11dc6cU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x90000000U, 0x68000000U, 0x3c000000U, 0x86000000U, 0xb5000000U, 0x36800000U, 0x49400000U, 0xa3200000U, 0xc0700000U, 0x9d880000U, 0xeecc0000U, 0xbee20000U, 0xdd190000U, 0xaf5e8000U, 0xc3f7c000U, 0x224e6000U, 0x24ac5000U, 0x4dbee800U, 0xe8e0d400U, 0xe01b1200U, 0x15d6f700U, 0xf4b48080U, 0x6062c0c0U, 0x6852e020U, 0xaa729090U, 0x26860868U, 0xe147443cU, 0xbf219a86U, 0xd67f73b5U, 0x4085fab6U, 0xe4462389U, 0x71a79203U, 0xcb383790U, 0x59a46055U, 0x17395082U, 0x6fa26870U, 0x5a3e14c4U, 0xd23f277U, 0xa9716703U, 0x9d0e08b1U, 0xea8b44d8U, 0x7f439a65U, 0xee26731fU, 0xa2fb7a88U, 0x6ec1e31aU, 0x7ee1f25eU, 0xfd186775U, 0x3f5888a5U, 0xabf084b5U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0x28000000U, 0x8c000000U, 0x1e000000U, 0xd1000000U, 0x98800000U, 0x15c00000U, 0x5fe00000U, 0xaeb00000U, 0x65c80000U, 0x27ec0000U, 0x6ab60000U, 0x67c10000U, 0xc0ee8000U, 0xaf3ec000U, 0xf480e000U, 0x5bc39000U, 0xc6e74800U, 0x2a39bc00U, 0x46026e00U, 0x2507a300U, 0x4280e080U, 0xc6c390c0U, 0x20674860U, 0x7ef9bc90U, 0xa9626e28U, 0x1277a38cU, 0x66a8e09eU, 0x9e9f9011U, 0xb79948f8U, 0x2b14bc85U, 0x5cdaee77U, 0x74386322U, 0x370e80fbU, 0x4d8ec036U, 0xef48e092U, 0x3d2f90e2U, 0x1cd148b7U, 0xd438bc8dU, 0xc70cee8fU, 0xf58963adU, 0x4b4800b4U, 0xaf2c0098U, 0xd3d600b9U, 0x9db100b4U, 0x4a4680fbU, 0xbfa2c036U, 0xba1ee092U, 0x645e90e2U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xb0000000U, 0xd8000000U, 0xe4000000U, 0xe2000000U, 0x7b000000U, 0x59800000U, 0xa0c00000U, 0x12a00000U, 0x20b00000U, 0xbcc80000U, 0x4ac0000U, 0xb1b60000U, 0x12430000U, 0x23e18000U, 0x7ed84000U, 0xe0dd2000U, 0x3dde3000U, 0x2d59d800U, 0xc71d2c00U, 0x10f21a00U, 0x842d5300U, 0x93fd2080U, 0x29ae30c0U, 0xd931d860U, 0xcc012cb0U, 0x7e0c1ad8U, 0xad0253e4U, 0xa88aa062U, 0xbe4570bbU, 0xede57839U, 0xbdb5c10U, 0xac56e2caU, 0x619e4fc4U, 0xbbbee2deU, 0x95424fbfU, 0x1c60e208U, 0xf71d4fc2U, 0x8ff6209U, 0x2a0fcaU, 0xc1f5c286U, 0x8aaf7fd6U, 0x64b0ba1fU, 0x8ec4239aU, 0x17ae58a2U, 0xd4366c95U, 0xb486badeU, 0xa84723bfU, 0x7cefd808U, 0xa55e2cc2U, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0x58000000U, 0x44000000U, 0x86000000U, 0xdf000000U, 0x1f800000U, 0xa4400000U, 0x29e00000U, 0xced00000U, 0xa8480000U, 0x3e40000U, 0xebd60000U, 0x5ac70000U, 0xb9218000U, 0xe2f24000U, 0x803f6000U, 0x8d147000U, 0xb1efb800U, 0xaadf2400U, 0xbe4bee00U, 0x74e7d500U, 0xe85f6080U, 0x3c847040U, 0xc9c7b860U, 0xecab24f0U, 0x93b5ee58U, 0x354d544U, 0xbd00e006U, 0x9685309fU, 0xacc7587fU, 0x7e2e1454U, 0xd972b671U, 0x527ac18aU, 0x23f256aeU, 0x24bff19cU, 0x20d50e14U, 0x4b41e54eU, 0x4e6fb828U, 0xbe9f24d8U, 0xafabee96U, 0xe37d5e5U, 0x9e17601bU, 0xa460708fU, 0xbb91b8d7U, 0xcd2c24d3U, 0x1cf46eaeU, 0x8b36959cU, 0xbc978014U, 0xd6a5404eU, 0x80000000U, 0x40000000U, 0x20000000U, 0x90000000U, 0xc8000000U, 0x74000000U, 0xda000000U, 0x9f000000U, 0x13800000U, 0x80400000U, 0x47600000U, 0x6e100000U, 0xce480000U, 0xf2640000U, 0x9a920000U, 0x71810000U, 0x53488000U, 0x82e54000U, 0x8754a000U, 0x63ad7000U, 0x3eb27800U, 0xc57fa400U, 0xa6588600U, 0xbd255900U, 0x667ca080U, 0x5bd97040U, 0x58687820U, 0x3d9aa490U, 0x6e0206c8U, 0x25011974U, 0x3c80805aU, 0xcbc140dfU, 0x7b26a033U, 0x877c7010U, 0xe552f88fU, 0xb0aee41aU, 0xfb362614U, 0x2c3d296dU, 0xbbc5809U, 0x71f694b1U, 0x3996de34U, 0x8c02cd7cU, 0xb60afe01U, 0xd90afda5U, 0xb28c26deU, 0x1ec829fbU, 0x3faed88eU, 0x60b6d41bU, 0xf878fe94U, 0x6dbfd2dU, 0x48eca629U, 0x90596921U, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0x28000000U, 0xfc000000U, 0x96000000U, 0x13000000U, 0xe3800000U, 0x96400000U, 0xf600000U, 0x2b300000U, 0x14480000U, 0x56640000U, 0x3db60000U, 0x4a890000U, 0xf8c68000U, 0xe5a9c000U, 0xff986000U, 0x615bb000U, 0xeffdf800U, 0x47ea0400U, 0xcaf2c600U, 0x87610b00U, 0xe7306080U, 0xda4fb040U, 0x8163f860U, 0x9c370410U, 0xa5ca4628U, 0x9125cbfcU, 0xa8588016U, 0x9174c053U, 0x8520e083U, 0xe25f7086U, 0x64751827U, 0x4da174d7U, 0x4399de82U, 0x975d7f45U, 0xecf13e5eU, 0x8c660f9cU, 0xa0b22617U, 0x1e0e7b9eU, 0xdf0d7823U, 0x2d8ac49bU, 0x414c260cU, 0xaee37bf2U, 0xc47df8efU, 0x7daa045bU, 0x1b92c602U, 0x53510b05U, 0xaef8603eU, 0xf56bb08cU, 0x80000000U, 0x40000000U, 0x20000000U, 0x30000000U, 0xa8000000U, 0x14000000U, 0x5a000000U, 0xa9000000U, 0xbc800000U, 0x80400000U, 0xf3e00000U, 0xa0500000U, 0xb6480000U, 0xece40000U, 0x43d20000U, 0xf58b0000U, 0x6cce8000U, 0xcba34000U, 0xdfb6a000U, 0xf0181000U, 0xbda68800U, 0xe0bba400U, 0x239cae00U, 0x56644d00U, 0x749ea080U, 0xf1ec1040U, 0xd55c8820U, 0x54c4a430U, 0x7a82ea8U, 0x19b80d14U, 0x271c80daU, 0x5a2840e9U, 0x6178209cU, 0xb6bb50b0U, 0x2c90285bU, 0x2de3b4b4U, 0x8b5a26ecU, 0x3fcfe945U, 0xae2a0e7fU, 0x6b7c5d35U, 0xa7b8283fU, 0x1c17b41bU, 0x4ba026e1U, 0x9fb0e938U, 0xd01e8e8cU, 0x8da01de8U, 0x48ba0809U, 0x3793e4c4U, 0xc648e6cU, 0xdd9f1d05U, 0x4d6e885fU, 0x551fa405U, 0x80000000U, 0x40000000U, 0x60000000U, 0xb0000000U, 0x18000000U, 0x84000000U, 0xee000000U, 0x45000000U, 0x7e800000U, 0xe2c00000U, 0x64a00000U, 0x5a900000U, 0xbc80000U, 0x28240000U, 0xf7560000U, 0xae30000U, 0xb3f58000U, 0x80764000U, 0x1039e000U, 0x345fd000U, 0x8d6ea800U, 0x95b84c00U, 0x51eda00U, 0x89826100U, 0x934fe080U, 0x83ecd040U, 0x4f732860U, 0x35ba0cb0U, 0x95193a18U, 0x418ab184U, 0xbf4ac86eU, 0xf1e5dc05U, 0x6077921eU, 0xe032fd52U, 0x4c5412fcU, 0xb967bd9eU, 0x63b87205U, 0xc41e2d9dU, 0x19073a71U, 0x348db19cU, 0x99c948c1U, 0xf7209cebU, 0x5ad3f2f3U, 0xe7af6d8fU, 0xbd1d5a16U, 0x9d8721a6U, 0xb54b80a9U, 0xeae1402cU, 0x43f2601dU, 0xf87e9019U, 0x243cc81fU, 0xc256dc99U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xd0000000U, 0xf8000000U, 0x3c000000U, 0x22000000U, 0x7000000U, 0xf9800000U, 0xf400000U, 0x55e00000U, 0x74b00000U, 0xaa480000U, 0xeb640000U, 0x227a0000U, 0x20e50000U, 0x323b8000U, 0xc081c000U, 0x43cb2000U, 0xfc25f000U, 0x3b915800U, 0x5e555400U, 0x5b7aee00U, 0xcc6cf300U, 0x4bf92080U, 0x77a4f040U, 0x8bd0d8a0U, 0x6e3194d0U, 0xd28a4ef8U, 0xccc8c33cU, 0x11a358a2U, 0xd2d45447U, 0x12bb6e59U, 0xf34833dfU, 0x97e9802dU, 0x3b0c008U, 0x7bc2a028U, 0x2025303cU, 0x699bf823U, 0x71546413U, 0x66fb1645U, 0xdd2d97b3U, 0x3b11b690U, 0xfd9ca758U, 0xd7584e6cU, 0xdff9c39aU, 0xd1aad81bU, 0x32d4944bU, 0x62b1ce50U, 0xdb490340U, 0x53e87821U, 0x1db1a484U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0x88000000U, 0x84000000U, 0x92000000U, 0x4d000000U, 0x95800000U, 0x3cc00000U, 0x50200000U, 0x92900000U, 0x13c80000U, 0x20ac0000U, 0xefde0000U, 0xd5230000U, 0xa3148000U, 0xed0e4000U, 0x58e2000U, 0xe4c25000U, 0xec2a1800U, 0xc926c00U, 0x48c19200U, 0x6a255100U, 0xb982080U, 0x2c4d50c0U, 0x5d6098e0U, 0x3c7f2cb0U, 0xa47b3288U, 0x38794184U, 0xf6741812U, 0x95716c8dU, 0xd3f51275U, 0x21bb118cU, 0x7de0058U, 0x212300d6U, 0x59148061U, 0x940e40ddU, 0x8a0e20f2U, 0x1102506dU, 0xbb8a1861U, 0xefc26c32U, 0x9ea99283U, 0xe4d951f8U, 0xa7ae20d3U, 0x4b52508bU, 0x2621818U, 0x24fe6c17U, 0xed3f9269U, 0xe4965199U, 0xbcc4a000U, 0x902f1050U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xb0000000U, 0x48000000U, 0x8c000000U, 0x3e000000U, 0xeb000000U, 0xb3800000U, 0xa1c00000U, 0x2f600000U, 0x48900000U, 0x82480000U, 0xd6a40000U, 0xf3fe0000U, 0x80d30000U, 0x45e88000U, 0xcfd2c000U, 0xb46ee000U, 0x13153000U, 0xff817800U, 0x3fce3c00U, 0x94652600U, 0x312c100U, 0xe7866080U, 0x4bc7f040U, 0x6e6f98e0U, 0x5a1b0cb0U, 0x81045e48U, 0xb28cfd8cU, 0x534b46beU, 0x9c2131abU, 0x64bff8d3U, 0xaefbfc51U, 0xf4554687U, 0x39a23174U, 0x527f7874U, 0xa41d3cf1U, 0xca0da69eU, 0x5100017aU, 0xa888011U, 0x7742c0eaU, 0x9e26e0c7U, 0xf9b130d6U, 0x7a7f7875U, 0xd81d3c44U, 0x5c0da633U, 0x860001efU, 0xcf0880a7U, 0xb182c0a0U, 0x3cc6e019U, 0xfbe1300eU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xf0000000U, 0xf8000000U, 0x64000000U, 0xa000000U, 0x43000000U, 0x10800000U, 0xb400000U, 0x36a00000U, 0xfe300000U, 0xf3c80000U, 0x91ec0000U, 0x3e960000U, 0xd0f70000U, 0xc3ab8000U, 0x93bc4000U, 0xc901a000U, 0x9388b000U, 0x7bcec800U, 0xcde95400U, 0x30987a00U, 0x69f49b00U, 0x682a2080U, 0xec74f0c0U, 0xfeef6860U, 0x1811e4f0U, 0x66beb2f8U, 0xa481cf64U, 0xa94c5a8aU, 0x79ab6b83U, 0x88b0c8f0U, 0x2d82543bU, 0x9acdfaaeU, 0x9263db6aU, 0x4d5e0081U, 0x811b0076U, 0x9d3d8044U, 0xb34b4068U, 0xf2aa201dU, 0x6434f002U, 0xb8cf6806U, 0x1d61e4bfU, 0x5bd6b2a6U, 0xaf5dcf87U, 0x6e125a7bU, 0x7bb06b14U, 0x650d4871U, 0x6589144dU, 0xa6c7daeaU, 0x6c672b02U, 0x80000000U, 0x40000000U, 0x60000000U, 0xb0000000U, 0x38000000U, 0x44000000U, 0x4a000000U, 0x57000000U, 0xa6800000U, 0x3f400000U, 0xbda00000U, 0xb6900000U, 0x5dc80000U, 0x88e40000U, 0x3c360000U, 0xfdd30000U, 0xd26f8000U, 0x4d764000U, 0x3d71a000U, 0x2571f000U, 0xb177a800U, 0x73721400U, 0x58788a00U, 0xf0f2b100U, 0xd2be2080U, 0x9e97b040U, 0xb1ce0860U, 0x6ee7e4b0U, 0xed392238U, 0x3a53a544U, 0x12a92acaU, 0x74134117U, 0xf8818846U, 0xea41a4cfU, 0x502082e5U, 0x91565542U, 0xfa2082afU, 0x365655dbU, 0x4a08230U, 0xfd165565U, 0xcb008211U, 0x58865570U, 0x7a48824fU, 0xb82255f8U, 0x5d5e82e4U, 0xcc2155daU, 0x6f59023fU, 0xbf23152aU, 0x33d6a2e9U, 0xef65e514U, 0x6cf88ad5U, 0x2cb2b127U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xf0000000U, 0x38000000U, 0x3c000000U, 0xd6000000U, 0xbd000000U, 0x4c800000U, 0xc0400000U, 0xbe200000U, 0xd6300000U, 0xf8c80000U, 0xec640000U, 0xdf1e0000U, 0xf9770000U, 0x1d6f8000U, 0x3d99c000U, 0x58346000U, 0xc9cb5000U, 0xaeee8800U, 0x6e53a400U, 0xe5d9d200U, 0x8a1e3b00U, 0xe1fbe080U, 0x1f229040U, 0x1cb2e8e0U, 0xad8cf4f0U, 0xeac15a38U, 0x1b6e9f3cU, 0xe89bb256U, 0xb66bfdU, 0x2b8ce82cU, 0x7fcbf470U, 0xa3e6da66U, 0xfad35f1aU, 0xe991d296U, 0xda3a3b2dU, 0xb6c5e025U, 0x7d659034U, 0x8d956837U, 0x803134e7U, 0x5cb3af0U, 0x40e2cf72U, 0xef52ba93U, 0x7f580f46U, 0xf75f5ab5U, 0x13599fe8U, 0x95432baU, 0x5a5fab5dU, 0x97d08843U, 0xcd14a42eU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0x28000000U, 0xf4000000U, 0xe2000000U, 0x25000000U, 0x92800000U, 0x62400000U, 0xe200000U, 0x2b00000U, 0x1cc80000U, 0xe26c0000U, 0x679a0000U, 0x47f50000U, 0x15668000U, 0x48194000U, 0x1b312000U, 0x9709d000U, 0x5f82e800U, 0xa4c04400U, 0x5e631200U, 0x1969300U, 0x78f7a080U, 0x7ee090c0U, 0xaedbc8a0U, 0xb05594d0U, 0x2c13fa28U, 0xb13fd7f4U, 0x36003262U, 0xd70643e5U, 0x3f89c8b2U, 0xd4cc9472U, 0xa66f7a86U, 0xdd939726U, 0x6ef79256U, 0xb9e6d3f3U, 0x19520037U, 0x40990010U, 0x407c8001U, 0xbdac400cU, 0x2877a0c3U, 0x29a090a6U, 0xba7bc854U, 0xf4a59446U, 0xf4fbfab0U, 0x80e3d76eU, 0x3dd232e4U, 0x35df4381U, 0xd1d548b1U, 0xbbd0d436U, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0xe8000000U, 0xac000000U, 0xd6000000U, 0x1f000000U, 0x53800000U, 0x24c00000U, 0x25a00000U, 0x3fd00000U, 0xf1480000U, 0x46640000U, 0x2df20000U, 0x60570000U, 0xb3828000U, 0xb4ccc000U, 0x1da06000U, 0x8bd07000U, 0x63497800U, 0x2361ec00U, 0xb77cca00U, 0x8103500U, 0xe16ae080U, 0x8a78b040U, 0xf69b1820U, 0x3269cf0U, 0xf99732e8U, 0x28ad19acU, 0x495e4a56U, 0x6f0cf55fU, 0xfb8280f3U, 0xa8ccc094U, 0x3a060edU, 0xc8d07063U, 0xec978cfU, 0xb4a1ecf5U, 0x175ccaa8U, 0xc00355bU, 0x6602e045U, 0xd70cb0efU, 0xf8118e9U, 0x1ac59c02U, 0x96afb257U, 0xba52d9a9U, 0xca8eaa7fU, 0x30474583U, 0x36e918bcU, 0xb4b19c21U, 0xca35b265U, 0x6871d9c8U, 0x80000000U, 0x40000000U, 0x20000000U, 0xd0000000U, 0x18000000U, 0x4000000U, 0x46000000U, 0x5d000000U, 0x61800000U, 0x2d400000U, 0xfd600000U, 0x5d300000U, 0x96c80000U, 0x8f240000U, 0xfad20000U, 0xa350000U, 0xb04d8000U, 0xfce64000U, 0x807b6000U, 0xa3a15000U, 0xce13d800U, 0x2e1cf400U, 0x9e1f6600U, 0x76199b00U, 0xba1ee080U, 0xe0131040U, 0xff12b820U, 0x859ca4d0U, 0x945b3e18U, 0x25f22f04U, 0xa8e566c6U, 0x9e789b1dU, 0xdaa960c1U, 0x399450bdU, 0x465e58c5U, 0x6fab489U, 0x406406c8U, 0x8cb8cbd6U, 0x538d385dU, 0xbe4fe43aU, 0xfdedde0cU, 0x83f53f5cU, 0x45edde73U, 0x17f53f35U, 0x3bedde44U, 0x9ef53f66U, 0x46dde0dU, 0xeab53f39U, 0xde8dde89U, 0xc7c53f2bU, 0xd4a5deb8U, 0x38913f63U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x30000000U, 0x68000000U, 0x84000000U, 0x9a000000U, 0xc7000000U, 0x4c800000U, 0x37400000U, 0xd4600000U, 0xe5700000U, 0x64c80000U, 0x83ac0000U, 0x78560000U, 0x38db0000U, 0xe1928000U, 0x60fa4000U, 0xba08a000U, 0x5703f000U, 0x748f0800U, 0xeb471400U, 0xa2665600U, 0x3c770f00U, 0x754c2080U, 0x3f62b0c0U, 0xd7f52860U, 0x3e8ea430U, 0xb449fe68U, 0x62efeb84U, 0x253b7e1aU, 0x9425ab07U, 0xd59bdeacU, 0x52fa5bc7U, 0x990ad65cU, 0xb18a4f91U, 0xecc80076U, 0xf7ac0030U, 0xea5600a6U, 0x4bdb007cU, 0x5f12808bU, 0x14ba40f1U, 0xb8e8a0dcU, 0x4233f0c1U, 0x88a708f0U, 0xbadb1482U, 0x6a98568bU, 0x62700f02U, 0x8840a0b2U, 0xe4eff073U, 0xf43908e0U, 0x31ac14eaU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0x38000000U, 0xc4000000U, 0xf6000000U, 0x9b000000U, 0xf7800000U, 0xaa400000U, 0x66600000U, 0x32900000U, 0x42c80000U, 0xadac0000U, 0x15ba0000U, 0x9b50000U, 0x8bb78000U, 0xaeb24000U, 0xee3c6000U, 0xb9f93000U, 0xdcd3b800U, 0x12a90400U, 0xa4347600U, 0x70fa4100U, 0x3651e080U, 0x3c6e70c0U, 0x639058a0U, 0xbc4e74d0U, 0x4d61ae38U, 0x8d1f75c4U, 0xc481ae76U, 0xc1cf755bU, 0x8e29aed7U, 0xd1f375baU, 0xe0dbae7eU, 0x80aa75e6U, 0x19362eacU, 0x247d35e2U, 0xaf95ce0cU, 0x64a45ecU, 0xac6816f4U, 0x3b937179U, 0x84a58d3U, 0x536b74c3U, 0xea1e2e74U, 0x10135a1U, 0x687cea7U, 0x84c3457dU, 0xbead9643U, 0x6e38319cU, 0x79fbb804U, 0x7cd50451U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xf0000000U, 0xd8000000U, 0xf4000000U, 0xea000000U, 0xbd000000U, 0x5b800000U, 0xddc00000U, 0x4d200000U, 0xfd500000U, 0xbf480000U, 0x396c0000U, 0x84ba0000U, 0x4eb70000U, 0xc3b98000U, 0xe0314000U, 0x39ffa000U, 0x46d75000U, 0xf2867800U, 0xfc48bc00U, 0xa5e66200U, 0x37f2dd00U, 0x59dc2080U, 0x680110c0U, 0x4c0858a0U, 0x4e02acf0U, 0x7f05bad8U, 0xca8a31f4U, 0x984dba6aU, 0xc7e6317dU, 0x56f7ba7bU, 0xc45131edU, 0x16ce3ab5U, 0xda07139U, 0x88119aadU, 0xb272140U, 0x9e5fe2cdU, 0x13c39deaU, 0xf22380c7U, 0x97d640b9U, 0xd70e2002U, 0x268a10e6U, 0x2643d8edU, 0x60e8ece2U, 0x68799aa1U, 0xb61b213dU, 0x6c2de20eU, 0xd89d59U, 0x91800012U, 0x50c000aeU, 0x80000000U, 0x40000000U, 0x20000000U, 0x70000000U, 0xf8000000U, 0xec000000U, 0xfa000000U, 0xeb000000U, 0xc2800000U, 0x5c400000U, 0x37e00000U, 0x40f00000U, 0xd7e80000U, 0x50f40000U, 0x7fea0000U, 0x34f30000U, 0x91e58000U, 0xc9fdc000U, 0x426a2000U, 0xbc337000U, 0xeb460800U, 0x9766b400U, 0x4bbd7600U, 0x508ebb00U, 0xb3460880U, 0x4b66b440U, 0x69bd7620U, 0x278ebb70U, 0x73c60878U, 0x1026b4acU, 0x66dd76daU, 0xd03ebb9bU, 0x514e08baU, 0x5c62b4f0U, 0xf93f76edU, 0xf4c9bbdbU, 0x68a9886dU, 0xf19874a0U, 0x555ad692U, 0xb5f40befU, 0x506020fcU, 0x13307069U, 0xb7cb88d0U, 0xce2f7453U, 0x43dd5697U, 0x9fbecbbeU, 0x268d803bU, 0xf249c033U, 0xeae020fcU, 0xe3707069U, 0x5a2b88d0U, 0x15df7453U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0x28000000U, 0x9c000000U, 0xe6000000U, 0x59000000U, 0x7c800000U, 0x5e400000U, 0x35e00000U, 0xea300000U, 0x1e80000U, 0x503c0000U, 0x1ee20000U, 0x65bd0000U, 0x14208000U, 0x9214c000U, 0x2dfee000U, 0x20c95000U, 0xad2800U, 0x3052b400U, 0x4e117600U, 0xabf19700U, 0xc9cd2880U, 0x4422b4c0U, 0xda1976a0U, 0x1fd9710U, 0xfec728a8U, 0xeda3b45cU, 0x36dbf646U, 0xaf545749U, 0xbb9948d4U, 0x13e2402U, 0x2e683e73U, 0x55ffb3a3U, 0xf4cd16d5U, 0xcaa10752U, 0xb75660edU, 0xdf919006U, 0xf339c8e1U, 0x1d6ae410U, 0xbe76dec8U, 0x1306e36aU, 0x3b883e0fU, 0x6fcfb335U, 0x7d251614U, 0x169d078aU, 0x67b460e1U, 0x7f2c9010U, 0x7d9948c8U, 0x883e246aU, 0x80000000U, 0x40000000U, 0x20000000U, 0x50000000U, 0x38000000U, 0xbc000000U, 0x76000000U, 0x9d000000U, 0x26800000U, 0x6f400000U, 0x57600000U, 0xd6f00000U, 0x33680000U, 0x2cf40000U, 0x906a0000U, 0x43710000U, 0x2ba98000U, 0x2c5ac000U, 0x67bee000U, 0x1d0b1000U, 0x66808800U, 0x4f43e400U, 0x766fe00U, 0xeefa0b00U, 0x8f608880U, 0x5af3e440U, 0xd6efe20U, 0x65fe0b50U, 0x44e288b8U, 0x7b36e4fcU, 0xb14d7e56U, 0x2e65cbcdU, 0x4a7de89eU, 0xdf233493U, 0x44111601U, 0xc5583f1bU, 0xa3301eadU, 0x3d451bbfU, 0x106a0011U, 0x3710018U, 0xba98026U, 0x7c5ac083U, 0x5fbee0eeU, 0xa10b10a9U, 0x1080882eU, 0xd243e4bdU, 0x21e6fe81U, 0x81ba0b09U, 0xd8008826U, 0x8c03e483U, 0x3e06feeeU, 0x490a0ba9U, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0x58000000U, 0x54000000U, 0x26000000U, 0x4b000000U, 0x5800000U, 0x95c00000U, 0xc4e00000U, 0x2df00000U, 0x12e80000U, 0x4ef40000U, 0x2b6e0000U, 0xa1310000U, 0x8e8b8000U, 0xb0444000U, 0x6121e000U, 0xe114f000U, 0x331fb800U, 0x2e14ac00U, 0x8947600U, 0xc4d03300U, 0xbff7b880U, 0x6fe0ac40U, 0x387a7660U, 0xbf213350U, 0x8e1c38d8U, 0x7894ec14U, 0xacd39646U, 0xe3f1c31bU, 0x45e580ddU, 0x1754081U, 0xd7aa6082U, 0x5550b036U, 0x2c3e584fU, 0xd0005c8fU, 0x180bcec9U, 0x34049fc7U, 0x7603ce19U, 0x13009f2bU, 0x5185ce6eU, 0xb3c59f7dU, 0x8fe04e17U, 0x2870df94U, 0x872a2edcU, 0x8a106f8bU, 0x69c7699U, 0xb3d4336bU, 0xc071b80eU, 0x9b25ac2dU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x30000000U, 0x98000000U, 0x34000000U, 0x52000000U, 0x45000000U, 0x63800000U, 0x23c00000U, 0xdc200000U, 0xc8f00000U, 0x6280000U, 0xd1fc0000U, 0x3ba20000U, 0xe13f0000U, 0xb0b8000U, 0x188c4000U, 0xc346a000U, 0xbb641000U, 0x899a9800U, 0x66bd2c00U, 0xb2cada00U, 0xbdace300U, 0xa6329880U, 0x25812cc0U, 0xc4c8daa0U, 0xc2a3e330U, 0x8cb11818U, 0x33c16cf4U, 0xb4247af2U, 0xc4f4f375U, 0x502a007bU, 0x5ef300d7U, 0x2921802eU, 0xf37f40bdU, 0xb1e720fdU, 0x6fdb50c6U, 0x2e5db8b5U, 0xb0967c6cU, 0xab3f626eU, 0xba069feaU, 0x890ffaa4U, 0x9588b352U, 0x9cc4a0a4U, 0x56ab105fU, 0xeeb91872U, 0xeecd6ce3U, 0xe3ae7aeeU, 0xb537f32aU, 0xc9038004U, 0xf5804062U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x70000000U, 0x98000000U, 0xac000000U, 0x32000000U, 0x29000000U, 0x14800000U, 0x2c00000U, 0xcde00000U, 0xadf00000U, 0xb3e80000U, 0xa6fc0000U, 0xc6620000U, 0xf4bb0000U, 0xf4b8000U, 0x23a1c000U, 0x1ed0a000U, 0x9f75000U, 0xa5efe800U, 0x59fe7c00U, 0x8debb600U, 0xcdfae300U, 0x63e7e880U, 0x4ef27cc0U, 0xf261b6a0U, 0x6abde370U, 0x144e6818U, 0x1e28bc6cU, 0x89a9692U, 0xc6db7359U, 0xc5f9200cU, 0x47ed906eU, 0x98f4c85fU, 0xad68ecf4U, 0x5134fe3fU, 0xb503cf08U, 0xde8bb6b9U, 0x57cae3b0U, 0x36fe888U, 0xb23e7c37U, 0xf48bb62dU, 0x12cae38cU, 0x85efe833U, 0xe9fe7c99U, 0xb5ebb6d3U, 0x11fae36bU, 0xc9e7e808U, 0xcbf27cf7U, 0xd4e1b68dU, 0x417de3fcU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x90000000U, 0x98000000U, 0xb4000000U, 0xde000000U, 0x61000000U, 0xca800000U, 0x63c00000U, 0x39200000U, 0xc9300000U, 0x6b280000U, 0x923c0000U, 0xa6aa0000U, 0x7e750000U, 0x70c38000U, 0x38ae4000U, 0xff766000U, 0xa4c5000U, 0x5364c800U, 0xea596c00U, 0xa973da00U, 0x87413f00U, 0xd3ecc880U, 0xa6956cc0U, 0xa3d1da20U, 0x53383f90U, 0x3c2d4818U, 0xa5b22c74U, 0x6dee3afeU, 0xb79f2ff1U, 0x415460d2U, 0x8cf55017U, 0xf70548c7U, 0x678e2c38U, 0x73443a39U, 0xedea2f45U, 0x7797e0c1U, 0x615b1016U, 0x1cf328f1U, 0x6f027c59U, 0xd380f2f8U, 0xad434309U, 0x8cec3a16U, 0xbd162fe1U, 0x29de09aU, 0x25de10c0U, 0xa638a871U, 0xb8a03c99U, 0x3f7492d8U, 0x2a461399U, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0xb8000000U, 0x3c000000U, 0x82000000U, 0x79000000U, 0x1d800000U, 0xf6400000U, 0x67a00000U, 0x8d300000U, 0x82a80000U, 0x22b40000U, 0xc5ee0000U, 0xcc950000U, 0xb8958000U, 0xee9ec000U, 0xf199a000U, 0x3b1f5000U, 0x93d97800U, 0x5abbb400U, 0xd9ecc200U, 0x3e934700U, 0x69977880U, 0x771eb440U, 0xb9d14260U, 0xa7b98710U, 0x7a60d838U, 0x33d4e47cU, 0x6abdbae2U, 0x11ecf369U, 0xaa9dba25U, 0x6f9cf38aU, 0xb015ba05U, 0x5f58f3a4U, 0x3573bac7U, 0xf609f3b8U, 0x2f003a78U, 0x2863354U, 0x3cca1afdU, 0xcf66a32fU, 0x44514294U, 0x1f98799U, 0xc5c0d809U, 0x92e4e4f8U, 0xd215ba4fU, 0x7658f3c5U, 0xf0f3bac5U, 0x2c49f353U, 0x72a03a76U, 0xcab633f0U, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0x88000000U, 0x34000000U, 0xd6000000U, 0xe5000000U, 0x25800000U, 0x89c00000U, 0xa2600000U, 0x93b00000U, 0xe3680000U, 0xd8340000U, 0x53ae0000U, 0xcdd30000U, 0xf2d68000U, 0x78584000U, 0xc31fe000U, 0x6301000U, 0xc2aab800U, 0x5e580c00U, 0xee17de00U, 0x77b25700U, 0xed64b880U, 0x913b0c40U, 0x6c295e60U, 0xcb1e1770U, 0x72355808U, 0x74a81c74U, 0xcb5d66b6U, 0x439a5b95U, 0xca7b662dU, 0x990d5bfdU, 0xe78be694U, 0xaac21b46U, 0x9ae486aeU, 0x83fd4b55U, 0x2ac15e4fU, 0xdaea17bfU, 0xe3fb588aU, 0x5acb1cc8U, 0x52e3e629U, 0xd7f61b70U, 0x8cca868aU, 0xb7ee4b75U, 0xf277de2cU, 0x50257abU, 0x158cb882U, 0x61cf0cbcU, 0xe6675e9fU, 0xcdbd17e5U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0xa8000000U, 0xe4000000U, 0x2e000000U, 0xc7000000U, 0xfe800000U, 0x22c00000U, 0xfae00000U, 0xf2300000U, 0x7be80000U, 0xcfb40000U, 0x79a20000U, 0x28910000U, 0xc3f88000U, 0x49874000U, 0x64466000U, 0x342d3000U, 0x92d28800U, 0xc8d29c00U, 0x69d0e600U, 0x44559f00U, 0x4e188880U, 0x1d379c40U, 0x216a66a0U, 0x6373df50U, 0x144e6828U, 0x8c29eca4U, 0x7edc8e8eU, 0x52dd7397U, 0x28d486d6U, 0x99d9af86U, 0xbc5a80f4U, 0x2164025U, 0xd73ee08dU, 0xc86a7059U, 0x5af4e805U, 0xc80facf9U, 0x540a6e68U, 0x76030363U, 0xdb026e99U, 0x9c87038cU, 0x2fc86ef0U, 0xed6203acU, 0xe972ee87U, 0x5d444363U, 0xe5a40ec0U, 0xa9a3387U, 0x6ef2e6b7U, 0xe049f4bU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0x98000000U, 0xd4000000U, 0x1e000000U, 0xe5000000U, 0x6b800000U, 0xb9400000U, 0x56e00000U, 0x33700000U, 0xed680000U, 0x423c0000U, 0x678a0000U, 0x93470000U, 0x3deb8000U, 0x95f64000U, 0x73a06000U, 0x679f1000U, 0xf91d5800U, 0xc3dac400U, 0x407c5600U, 0x5fe8e300U, 0xe2f6d880U, 0x172c84c0U, 0xfe5c3620U, 0x37f3b0U, 0xa08b8018U, 0x6fc64014U, 0x7028603eU, 0x72d31055U, 0xf5ff58f3U, 0x23a1c46dU, 0x6f9dd648U, 0x519a3d6U, 0x91dd3806U, 0x6f75d43bU, 0xcf690e11U, 0xd53e2710U, 0x93088ec8U, 0x228f67c3U, 0x88c36eaaU, 0x3ca63761U, 0xa71e5697U, 0xc6d3e34bU, 0xbbf75843U, 0xceadc44aU, 0xf81fd63bU, 0xee52a3aeU, 0xe834b8e2U, 0xcc8894b7U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x10000000U, 0xe8000000U, 0xc000000U, 0x22000000U, 0xa3000000U, 0xd0800000U, 0x8bc00000U, 0x44a00000U, 0x13f00000U, 0xc280000U, 0xac3c0000U, 0x6e860000U, 0x22cd0000U, 0xdb208000U, 0x7ab1c000U, 0x8844a000U, 0x27e6f000U, 0xd8912800U, 0x657b8c00U, 0xdae3c200U, 0xb11b4300U, 0x9931a880U, 0xfb0a4cc0U, 0x48762e0U, 0xbdcdb310U, 0x31a88068U, 0xa67dc0ccU, 0xda6aa0c2U, 0x32d7f0b3U, 0xc197a838U, 0x22f74c87U, 0xa7afe266U, 0xe37073b0U, 0x77e2205cU, 0x109a30e7U, 0x997508caU, 0xecbc21U, 0xf6164a3fU, 0x67b63fdaU, 0xf1cb4244U, 0x33a68366U, 0xf57b08b3U, 0xf2edbc44U, 0x5d18ca1eU, 0xab36ff99U, 0xb0096207U, 0xd80cb35dU, 0x14060022U, 0xd60d00d6U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0x88000000U, 0x24000000U, 0x5e000000U, 0x85000000U, 0xb6800000U, 0x1c00000U, 0xf2200000U, 0x42f00000U, 0x6aa80000U, 0x5e3c0000U, 0xa20a0000U, 0xb7010000U, 0x698a8000U, 0xbc4f4000U, 0x486d6000U, 0x239a1000U, 0x85b68800U, 0x14c4c00U, 0x62ea4a00U, 0x205b3300U, 0xd0940880U, 0x823f0cc0U, 0x400d2a20U, 0xe00023d0U, 0xf0080008U, 0x580c00e4U, 0xac02007eU, 0x7a0d0055U, 0xdb08803eU, 0x33824025U, 0xb745e0acU, 0xf3e850c7U, 0xb0db68dcU, 0x28581c5fU, 0x349b2250U, 0xfc322ff5U, 0x150daa83U, 0xde8e6322U, 0xd5cfe04aU, 0xf4295084U, 0x6bf1e844U, 0xa6275c49U, 0x84fe42fcU, 0x63a43fa2U, 0x42b9223dU, 0xf0cf2fc7U, 0x52ad2ac6U, 0xc2302393U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x70000000U, 0x98000000U, 0x94000000U, 0x6e000000U, 0xa3000000U, 0x96800000U, 0x3e400000U, 0x56200000U, 0x91700000U, 0xbba80000U, 0xcdbc0000U, 0x6dc20000U, 0x41eb0000U, 0xdd938000U, 0xf3b64000U, 0xe6cb6000U, 0x7b657000U, 0x69d28800U, 0xf09f5400U, 0xd638ca00U, 0x60b5300U, 0x6f030880U, 0xcc8214c0U, 0x83402aa0U, 0xfba86370U, 0xadb2e018U, 0xbdc43054U, 0xa9e868ceU, 0xd19764d3U, 0x9baa20eU, 0x2bcb37aaU, 0x4ee82ab8U, 0xc11463f2U, 0x98f0e00dU, 0x116f3043U, 0x2cdbe803U, 0x19112434U, 0x6cf9c290U, 0xaf624709U, 0x67d0a2f3U, 0x839c3767U, 0xa8b9aa54U, 0x3449231cU, 0xc3280065U, 0x90fc0005U, 0xd620086U, 0x9edb00f7U, 0xa81b8085U, 0x3b7a4046U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0x58000000U, 0x5c000000U, 0x7a000000U, 0xcd000000U, 0x80800000U, 0x5e400000U, 0x4ce00000U, 0x5b100000U, 0x5b680000U, 0x58dc0000U, 0x31420000U, 0x9d610000U, 0x5fdf8000U, 0x54c0c000U, 0x97ae2000U, 0x33731000U, 0xa83aa800U, 0xa058b400U, 0x23070600U, 0x538cf500U, 0x45cf2880U, 0xad2574c0U, 0x34a6a0U, 0xb45e25d0U, 0xfd0420d8U, 0x688e109cU, 0x2a4728daU, 0xe2e9741dU, 0xe81ea6d8U, 0x30e32502U, 0x3119a0b6U, 0x6e6fd056U, 0x5456887bU, 0x4d0aa4d6U, 0x40822e25U, 0xfe44819aU, 0x9cee0efeU, 0x3169101U, 0x76b2606U, 0x22dee5e0U, 0xfc4a00c3U, 0x1ded00e3U, 0x195806dU, 0x182dc079U, 0xccbba07eU, 0x681ed05fU, 0xf0e108caU, 0x9116647bU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0xb8000000U, 0x94000000U, 0x1a000000U, 0x4b000000U, 0xa5800000U, 0x7bc00000U, 0x48600000U, 0xd2700000U, 0xe4e80000U, 0xa33c0000U, 0x60c20000U, 0x35ed0000U, 0x8db18000U, 0x1e804000U, 0x16462000U, 0xafa7f000U, 0xbc1af800U, 0x4b908c00U, 0x27539e00U, 0x4cb53b00U, 0x88017880U, 0xfc01ccc0U, 0x96063ea0U, 0xd50f8b10U, 0x4c842038U, 0x14af054U, 0x8c2b78baU, 0xaad0cc5bU, 0xdb75be1dU, 0xee62cbefU, 0x6f7380d2U, 0x246d4059U, 0x3c77a0e1U, 0x5e7b0c8U, 0xe5bcd890U, 0x92877c73U, 0x88416673U, 0x46a9b7f6U, 0xc698e653U, 0x8fd5f721U, 0x5ffcc659U, 0x732f0757U, 0xc55fbe4dU, 0xf3b3cb04U, 0x878000d6U, 0x64c0008dU, 0x57e0009bU, 0xf2b00033U, 0x80000000U, 0x40000000U, 0x20000000U, 0x90000000U, 0x8000000U, 0x5c000000U, 0x62000000U, 0x81000000U, 0xed800000U, 0x87c00000U, 0x6e600000U, 0x9e300000U, 0x58e80000U, 0xf1740000U, 0x4aca0000U, 0xa9ed0000U, 0xe4f28000U, 0x2904c000U, 0x6182a000U, 0xcdcfd000U, 0x2361f800U, 0x19b0ec00U, 0x225fe00U, 0x1093bf00U, 0xd2317880U, 0x72ed2c40U, 0xc7fde20U, 0x5545af90U, 0xa728a088U, 0x3b12d01cU, 0x52fb7842U, 0xd6002c11U, 0x4f0d5ee5U, 0xb6816fdbU, 0x2f4a008cU, 0x322d005fU, 0xc8928095U, 0xa634c0e6U, 0xdceaa02cU, 0xe77bd06bU, 0x65cbf8deU, 0xaf6dec59U, 0x53bf7ec6U, 0x4f237fe3U, 0x9719d829U, 0x88fffceeU, 0x9304a61bU, 0x948583bcU, 0x8e45fe33U, 0x4fa3bfdeU, 0x47597828U, 0x94592c3dU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x50000000U, 0xb8000000U, 0xec000000U, 0x66000000U, 0x23000000U, 0xab800000U, 0xadc00000U, 0x1b600000U, 0x17100000U, 0x9e80000U, 0xc5c0000U, 0xabca0000U, 0x88690000U, 0x74998000U, 0xa023c000U, 0x2531e000U, 0x15d6f000U, 0x6f0dd800U, 0x5d8d6c00U, 0x16c2ce00U, 0xce34d00U, 0x64d65880U, 0xdd8bacc0U, 0xd6c8ae20U, 0x2ce37d50U, 0x34d9e038U, 0x658af02cU, 0x3ac7d846U, 0x4ae46c73U, 0x17db4e13U, 0xce008d41U, 0x9707b8fdU, 0x518d5cf4U, 0xcd7682U, 0xc7e211f1U, 0x9b592e88U, 0xfa4cbdb3U, 0x88aa00bbU, 0xb379001fU, 0x3b7180bdU, 0xdf7fc08cU, 0x9d7be0deU, 0xdc7ff025U, 0x66f458f7U, 0xc9beac9bU, 0x919b2e10U, 0xb8a9bdb2U, 0xbb718026U, 0x1f7fc05bU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x10000000U, 0xd8000000U, 0x44000000U, 0x7e000000U, 0x61000000U, 0x23800000U, 0x7ec00000U, 0xf1200000U, 0x26500000U, 0x1fe80000U, 0xcf7c0000U, 0x1dbe0000U, 0xbe950000U, 0x6bcf8000U, 0xc4af4000U, 0xd59d6000U, 0x3f46d000U, 0x14e01800U, 0x8bf45c00U, 0x15f5da00U, 0xa4f82100U, 0x3f7d7880U, 0x15b28cc0U, 0x4295c260U, 0x41cc7d10U, 0x3a8a258U, 0xd31aad84U, 0x1c00ba9eU, 0xfa02f1b1U, 0x7f03601bU, 0x5283d0eaU, 0x85479837U, 0xcbe71c13U, 0xa976ba9aU, 0x58bbf194U, 0xf31ae031U, 0xac059047U, 0x520b78c6U, 0xf30b8c43U, 0xb08c42feU, 0xde4a3d2cU, 0xf7644283U, 0x95363d9fU, 0xf4da4275U, 0x5aa33d4fU, 0x6495c25cU, 0xa4cc7dd7U, 0x3e28a2cfU, 0xdcdaad6bU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x10000000U, 0xa8000000U, 0x7c000000U, 0x16000000U, 0x6d000000U, 0x7b800000U, 0x66400000U, 0xe3200000U, 0x87d00000U, 0xf3680000U, 0xf9f40000U, 0x17320000U, 0xa8dd0000U, 0xcfec8000U, 0x3f38c000U, 0x94d8e000U, 0x79e69000U, 0x42359800U, 0x47551400U, 0x63a9ba00U, 0xb71c3100U, 0xad857880U, 0xeb478440U, 0x28ae22a0U, 0x59942510U, 0xc4404228U, 0x1423753cU, 0x9f53ba36U, 0x47a5313dU, 0xc513f8f3U, 0x1286444aU, 0x3fc042fdU, 0x32637586U, 0xdc73bab6U, 0xd07531ceU, 0x9e7bf8b9U, 0x97724474U, 0x3ef242acU, 0xf7be754bU, 0x681f3aadU, 0x890df1feU, 0xe9831824U, 0x6944d472U, 0x8fafdabfU, 0x491f61d4U, 0x1c84809aU, 0x96ccc0c5U, 0x8beae0b4U, 0xbd3b909aU, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0xb8000000U, 0x24000000U, 0xe000000U, 0xd1000000U, 0x96800000U, 0x5c00000U, 0x12600000U, 0x69b00000U, 0x41a80000U, 0x3ed40000U, 0x689e0000U, 0x7fb30000U, 0x64a18000U, 0x8e5f4000U, 0xd05a6000U, 0x6957d000U, 0xf3da4800U, 0x941aec00U, 0xc57b3e00U, 0xc14e7f00U, 0xcca82880U, 0xa2593c40U, 0x225f7660U, 0x625793f0U, 0x25a9638U, 0xf25c0364U, 0x4a533eeeU, 0x6e5a7f61U, 0x605628ceU, 0xb15a3c91U, 0x27d6f6c4U, 0x221cd36cU, 0x307ef6e1U, 0x59c8d38eU, 0x1860f602U, 0x26bbd372U, 0x4e2176f9U, 0x31949348U, 0x553316bdU, 0xdb674304U, 0xb3f5e7eU, 0x626aaf1bU, 0x91b3e0cbU, 0x5ac9070U, 0xc0d62898U, 0x19a3c86U, 0xcd36f6dfU, 0x6f6cd386U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x50000000U, 0x28000000U, 0x4c000000U, 0x4a000000U, 0xe5000000U, 0x7c800000U, 0x45400000U, 0x8b600000U, 0x90500000U, 0x7c280000U, 0xda340000U, 0x76f60000U, 0x1c590000U, 0x96208000U, 0x8f3bc000U, 0x72752000U, 0x3d111000U, 0x1b472800U, 0xb0656400U, 0x97dc0e00U, 0xdeef8900U, 0xa39a0880U, 0xb7007440U, 0xed8d26e0U, 0xf7c3ed50U, 0x7d2e86a8U, 0xe0b03d0cU, 0x7cbc0e2aU, 0x5ebf89f5U, 0x17b20834U, 0x71347419U, 0xf97b2609U, 0x429aed69U, 0xdd8e06e2U, 0xcfcbfd76U, 0xf9292eabU, 0xb6be993cU, 0xfbbd2055U, 0x8b3510dcU, 0x64792871U, 0x5a186492U, 0x9ec28e99U, 0xeba94915U, 0xf0f1a838U, 0xf357a400U, 0xefa1ae37U, 0xe6f159eaU, 0x945e003aU, 0x6a2d00feU, 0x80000000U, 0x40000000U, 0x20000000U, 0x50000000U, 0x28000000U, 0xfc000000U, 0xa000000U, 0xf9000000U, 0x8e800000U, 0x6bc00000U, 0x2ae00000U, 0x9a300000U, 0xe4280000U, 0x24540000U, 0xe4da0000U, 0xc8190000U, 0x137c8000U, 0xe704c000U, 0xe1812000U, 0x6645d000U, 0x4ea00800U, 0x8194cc00U, 0xc932b600U, 0x83a4c700U, 0xc91b2880U, 0x9f81c40U, 0x5ac63e20U, 0x6860cb50U, 0xa3f2bea8U, 0xb3c00bbcU, 0xeee19eaaU, 0x6438dbe9U, 0xbb2f1606U, 0x71d5d787U, 0x49200a8U, 0xdbd008fU, 0x316e8068U, 0x3d79c01aU, 0xd00fa062U, 0x680c103cU, 0xdc07a859U, 0x5a0cdccbU, 0xd10f1e45U, 0x72811b7bU, 0x61c0b6f7U, 0xd3e9c750U, 0x14bda89bU, 0x8fe5dcfeU, 0xebb9e99U, 0x7ee1db6dU, 0x2c33968dU, 0x372117aeU, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0x38000000U, 0xb4000000U, 0x46000000U, 0x4b000000U, 0xfc800000U, 0x86400000U, 0x3a00000U, 0xb6700000U, 0x52e80000U, 0x73540000U, 0xc3da0000U, 0xd7970000U, 0x493d8000U, 0xc0ce4000U, 0x64eae000U, 0x60557000U, 0x1b506800U, 0x9fdc7400U, 0x8d9a6200U, 0x78391b00U, 0xbd408880U, 0xa72e0440U, 0x143f8a20U, 0x9f4f2fb0U, 0x2220ab8U, 0x9fb16ff4U, 0x2f80eae6U, 0x3ec01fbbU, 0xdbe28264U, 0xfadf6bc2U, 0x661f60ddU, 0x58ff30b9U, 0x9a888f0U, 0x6f7a04baU, 0x33658a42U, 0xca982f18U, 0x36bf8a22U, 0x160f2f88U, 0xa3020aaaU, 0xe0816f04U, 0xfc48ea58U, 0x82a41f09U, 0xf3f082efU, 0x252c6b73U, 0x4130e06aU, 0xcc270c6U, 0xb6ede80eU, 0xdd5234a7U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xf0000000U, 0x58000000U, 0x9c000000U, 0x1e000000U, 0x3f000000U, 0x83800000U, 0x2400000U, 0x18e00000U, 0x1bd00000U, 0xe1280000U, 0xad7c0000U, 0x4120000U, 0x48b0000U, 0x8dc38000U, 0xcacc000U, 0x83b6000U, 0xa377b000U, 0xf3141800U, 0x130c3400U, 0xa5834600U, 0xf1492100U, 0x2d6cf880U, 0xe29744c0U, 0xf84c3ea0U, 0x95e2a5f0U, 0x4153a6d8U, 0x33ee515cU, 0x7251803eU, 0xa667c00fU, 0x7b18e07bU, 0xe70b706eU, 0xdf87785eU, 0xbc4784b8U, 0xd7e55e7cU, 0xc05e1590U, 0x7f643e1fU, 0xab9ea5ddU, 0x20c1a654U, 0x6625518aU, 0x22f20095U, 0x105b00a6U, 0x176b809cU, 0xcf90c048U, 0x52c960e5U, 0x1f2cb0ffU, 0x27f9853U, 0x8f9cf474U, 0x32ca26d4U, 0x4f2591c3U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x30000000U, 0xd8000000U, 0xfc000000U, 0x6a000000U, 0xab000000U, 0x71800000U, 0xfc00000U, 0x83200000U, 0x33b00000U, 0x95680000U, 0x5b5c0000U, 0xd3fe0000U, 0xc870000U, 0x1f478000U, 0x66ac000U, 0x26d82000U, 0xe30f000U, 0xe8aa7800U, 0xef76ec00U, 0xcbc89a00U, 0xe5265f00U, 0x4ab5d880U, 0x83ecdcc0U, 0x971ac260U, 0x8104330U, 0xa79f3a58U, 0x1d506f3cU, 0x3af1808aU, 0x9201c05bU, 0xc709a0c9U, 0x938130c3U, 0xb0cbd831U, 0xbcabdc64U, 0x17d428eU, 0xa6ca83ffU, 0xbdaf1aa1U, 0xbbfc9ff0U, 0xe885f8e9U, 0xe9402c9eU, 0xf76ebad8U, 0x2451af95U, 0x8c782016U, 0xe40f072U, 0xf4e27889U, 0x1c9aec79U, 0x24de9aaeU, 0x413d5fa2U, 0x6f2c5848U, 0x11b11c01U, 0x80000000U, 0x40000000U, 0x60000000U, 0xd0000000U, 0x38000000U, 0x2c000000U, 0xe6000000U, 0xb7000000U, 0x59800000U, 0xea400000U, 0xdf200000U, 0x17d00000U, 0x4ae80000U, 0xb5b40000U, 0x6b9e0000U, 0xeac10000U, 0x5fe18000U, 0xe939c000U, 0xc558e000U, 0x7263000U, 0xabdb3800U, 0xf4e8b400U, 0xfeb99a00U, 0xec150100U, 0x9b8a5880U, 0x3f434440U, 0xa3a44260U, 0x91a85d0U, 0x4f097ab8U, 0x5587316cU, 0xbc4f6006U, 0x802af027U, 0x5a5c5801U, 0x6aa64416U, 0x3b93c201U, 0x92c6458cU, 0x13e61a75U, 0xdf3dc1a8U, 0x4a5b380dU, 0x72a8b487U, 0xa7999a92U, 0x9cc501b7U, 0xb0e258baU, 0x4cb74483U, 0xf11a4240U, 0x430b857aU, 0x380fa5aU, 0xe34af193U, 0xcda98066U, 0x7a1dc049U, 0xe48ee0d6U, 0xc2c33058U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0x68000000U, 0x3c000000U, 0xd6000000U, 0x51000000U, 0x1a800000U, 0x49c00000U, 0xdf200000U, 0xead00000U, 0xfa680000U, 0x5d3c0000U, 0x9d1a0000U, 0x884f0000U, 0x5b688000U, 0xcfbac000U, 0x78d8e000U, 0x59645000U, 0xb4b10800U, 0xc55dec00U, 0xeb20ca00U, 0x50d0d900U, 0x85696880U, 0xf2bf7cc0U, 0x4c532220U, 0xa5a665b0U, 0xf3102ae8U, 0xdd4889fcU, 0x53e26076U, 0xe57d9021U, 0x6e736852U, 0x5bf07cc5U, 0x45bba261U, 0xafdca587U, 0xeae8cab6U, 0x3fcd985U, 0xd1bb68f8U, 0x65dc7c5bU, 0xdde9a236U, 0x207fa5f4U, 0xbef24a21U, 0x25351921U, 0xb911081eU, 0x2a4deceaU, 0x5068ca45U, 0x3a3cd9e9U, 0x469b6852U, 0x30c7c74U, 0x9981a298U, 0x1043a54dU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0x58000000U, 0x14000000U, 0xda000000U, 0xf3000000U, 0x1800000U, 0x7e400000U, 0x28600000U, 0x55d00000U, 0x21a80000U, 0x2efc0000U, 0x4c9e0000U, 0x12490000U, 0x966f8000U, 0x94da4000U, 0x4f2d2000U, 0xc737f000U, 0x27b2f800U, 0x477c7400U, 0x6eda2e00U, 0xcc2ce100U, 0x2eb85880U, 0xc5fdc4c0U, 0xf913f660U, 0x60265d0U, 0xc5090ed8U, 0x8c8211d4U, 0xdecd203aU, 0xe8a7f0e3U, 0xcc7af839U, 0xb5074baU, 0x806c2eaaU, 0x69d9e1b2U, 0x7a9d87aU, 0x9bfe8463U, 0x28195605U, 0x5083d5e9U, 0xe8c0d647U, 0x65ac953bU, 0x6cfc7618U, 0xcb982518U, 0x19c42e44U, 0x4325e1bbU, 0xa937d8fdU, 0xbeb7843dU, 0x3df6d684U, 0x5d199522U, 0x540df6d7U, 0x7a0b6593U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xb0000000U, 0xa8000000U, 0xcc000000U, 0x22000000U, 0xb1000000U, 0xbe800000U, 0xea400000U, 0x9de00000U, 0xf3100000U, 0x48280000U, 0x523c0000U, 0x609e0000U, 0xe6ef0000U, 0x90908000U, 0xeee9c000U, 0x8c9fa000U, 0xd4e35000U, 0x59920800U, 0x84631400U, 0x20d2e600U, 0x160cdd00U, 0x87032880U, 0x298684c0U, 0xbbcfce60U, 0xf22559b0U, 0x473c6628U, 0x501a1d0cU, 0x2fa408c2U, 0xaaf014c1U, 0x853c6676U, 0x911a1d96U, 0x59240897U, 0x3cb0144eU, 0x92dc66b4U, 0x1f0a1db9U, 0x8d8c086bU, 0x35cc14f3U, 0xd1226607U, 0xe0b51d4eU, 0xc8d48832U, 0x7a09d486U, 0x750bc676U, 0x80854d7eU, 0x614800e2U, 0xf66c0098U, 0x49d600edU, 0xac83006dU, 0x3346800cU, 0x8f6ac0faU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x90000000U, 0xd8000000U, 0x64000000U, 0xaa000000U, 0xc1000000U, 0x47800000U, 0x8f400000U, 0x94a00000U, 0xbb300000U, 0x49680000U, 0xc55c0000U, 0x34b20000U, 0xba2d0000U, 0x3ffb8000U, 0x748d4000U, 0xadc22000U, 0x566dd000U, 0xf1d19800U, 0xf97bc400U, 0xdc436200U, 0x862b9f00U, 0x31fa3880U, 0xbf8654c0U, 0xbb435aa0U, 0x46accb90U, 0x8e38e258U, 0x7ce6dfa4U, 0xef18188aU, 0x4d9b8491U, 0x4f5ac23fU, 0xa5bb0f7bU, 0x85a18066U, 0x44bc40deU, 0x922ba004U, 0xb3fd901bU, 0xf280383fU, 0x7ac754eaU, 0x1ee2da48U, 0x52108bcbU, 0x64134217U, 0x3b1b4f66U, 0x6f98204eU, 0x925cd0dcU, 0xbc38187fU, 0xb9eb8495U, 0x3292c22bU, 0x4bd70f0fU, 0x207b80c4U, 0x5fcd40c3U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xb0000000U, 0x68000000U, 0x24000000U, 0xa2000000U, 0x15000000U, 0x4f800000U, 0xee400000U, 0xb600000U, 0x6d700000U, 0xb3a80000U, 0x21dc0000U, 0x9cf20000U, 0x76ef0000U, 0x8e308000U, 0x1b4b4000U, 0x94eba000U, 0xfb3f9000U, 0x44cf9800U, 0xa2af1400U, 0xbc5d5e00U, 0xafb5eb00U, 0xa606b880U, 0xc704c4c0U, 0x9281e6a0U, 0x35c22fb0U, 0x2f25dee8U, 0x5712abe4U, 0x33571882U, 0x69385465U, 0xf9c4fe87U, 0x69257b7aU, 0x4019a041U, 0xd9d0909cU, 0xa0ff18feU, 0x38e4546aU, 0xad36feb0U, 0x8bca7bd1U, 0x4292014U, 0xf39bd082U, 0xd994b854U, 0x389bc4f2U, 0xad196635U, 0xaa556f86U, 0xbc7e37U, 0x10823bbbU, 0x50c80085U, 0xa8ac0076U, 0x2d5a0027U, 0xf23300daU, 0x80000000U, 0x40000000U, 0x60000000U, 0x30000000U, 0xd8000000U, 0xf4000000U, 0x16000000U, 0xfd000000U, 0xc3800000U, 0x53400000U, 0x8a200000U, 0x27b00000U, 0x5be80000U, 0x17540000U, 0x323e0000U, 0xd5af0000U, 0xeff8000U, 0xaec24000U, 0x286be000U, 0xdc1b1000U, 0x2c191800U, 0xd41a0400U, 0x701e0a00U, 0x8e131700U, 0x5f137880U, 0x7e9c5440U, 0xc6db7260U, 0x72744330U, 0xc5098a58U, 0x478557b4U, 0xfd4698f6U, 0xb328448dU, 0x2a3dea7bU, 0x1ac0797U, 0x48fc60c4U, 0xbbcd506eU, 0xc7ecf8eeU, 0x6d5e1489U, 0x4d3092a3U, 0xcd2f5355U, 0xbb309249U, 0x402f5323U, 0xc0b09262U, 0xd76f533dU, 0x849092a2U, 0xf9df530cU, 0xaf89223U, 0x40cb5392U, 0x71669284U, 0xe1945389U, 0xae5112f3U, 0x7fb2138bU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xf0000000U, 0x48000000U, 0xe4000000U, 0xbe000000U, 0x51000000U, 0xd1800000U, 0xb7c00000U, 0x1f600000U, 0x47500000U, 0x16280000U, 0xaf7c0000U, 0x485e0000U, 0xa6ab0000U, 0xe13e8000U, 0xf4ff4000U, 0x8946000U, 0x54dd000U, 0x222db800U, 0x9780c00U, 0x25543e00U, 0x95273100U, 0x15f15880U, 0x311d9cc0U, 0xc68d6660U, 0x3b46adf0U, 0xb3223ec8U, 0xb8f03124U, 0x6291d85eU, 0xc249dc61U, 0xb6a786f9U, 0x99343da3U, 0x38fbe669U, 0xa295ed32U, 0xa2405e99U, 0x46aae179U, 0xd13ce02eU, 0xdcf59082U, 0x1c91587eU, 0xf34d9c59U, 0x97256671U, 0x66faad0eU, 0xc39c3e7bU, 0x5bcb313aU, 0xe56758f4U, 0x385a9c0bU, 0x2ea5e656U, 0x653eed67U, 0xbafede08U, 0x1195a12fU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0xf8000000U, 0x9c000000U, 0x76000000U, 0xd000000U, 0x9f800000U, 0xc9c00000U, 0x9b200000U, 0x98100000U, 0x76180000U, 0x971c0000U, 0xb6960000U, 0x865f0000U, 0x90f08000U, 0x26294000U, 0x2f962000U, 0x7bdaf000U, 0x763d0800U, 0xad829400U, 0xfec5a600U, 0x27ae6700U, 0xcf5da680U, 0x35726740U, 0xcceba620U, 0x2a3d67d0U, 0x3b8326d8U, 0xc3c8274cU, 0xd02306aeU, 0x629dd741U, 0x44568e31U, 0x2ffa0388U, 0xceab08aaU, 0xfadd9410U, 0x27b5265cU, 0x554727c7U, 0x1c6b86caU, 0x83789791U, 0x21eeae02U, 0x85b3f3bbU, 0x9a4880a3U, 0x3ce54051U, 0xa23820bcU, 0x6f89f078U, 0x41c388e6U, 0xcf28d49eU, 0x1a15063cU, 0x6912d738U, 0xef9e0ec6U, 0x9bdf434eU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0xd8000000U, 0x34000000U, 0xd6000000U, 0x8d000000U, 0xd3800000U, 0xea400000U, 0xfd600000U, 0xca100000U, 0x74180000U, 0x85140000U, 0xc920000U, 0xd9d70000U, 0x743a8000U, 0x3ee9c000U, 0x585ca000U, 0x8d707000U, 0x11074800U, 0x1982ec00U, 0x6d49ba00U, 0xc9eddb00U, 0x44d1ba80U, 0xdfb9dbc0U, 0xd0a3bae0U, 0xfb3edb90U, 0x26613a38U, 0x54931ba4U, 0x2dd79aeeU, 0xc2306b29U, 0xe3e0523dU, 0x53d847c3U, 0x533dc8c0U, 0x3a6b2c09U, 0x5e951a34U, 0xcaddab4cU, 0xa6b6f2d8U, 0xb52b3705U, 0xcc720014U, 0xd087005fU, 0x40c280c2U, 0x72adc0abU, 0x36a0b6U, 0x48e37085U, 0xe557c82dU, 0xd6f82c58U, 0x17459a36U, 0x6e76b45U, 0xfc5ad2cdU, 0xe37187c8U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0x48000000U, 0x64000000U, 0xfa000000U, 0x17000000U, 0xdd800000U, 0xd0c00000U, 0x9ba00000U, 0x34f00000U, 0xebf80000U, 0x92740000U, 0xd8b20000U, 0xc41b0000U, 0x656f8000U, 0x3a51c000U, 0xc98a6000U, 0x32c91000U, 0xc0a7c800U, 0xe7714400U, 0x9e3b3e00U, 0xa7591100U, 0x1b093e80U, 0x738211c0U, 0x85c6bee0U, 0xed23d150U, 0xefb4dea8U, 0x299ec134U, 0xda11652U, 0x1df48523U, 0x2b75a88fU, 0x503c54f3U, 0x6256f694U, 0x25875507U, 0xcccf809fU, 0xbda1c0c5U, 0x65f260efU, 0xf77d1035U, 0x1635c858U, 0xa35a44ecU, 0x710cbefeU, 0x2c8cd17dU, 0x3c495e02U, 0xc7e401a9U, 0x631cf651U, 0xc0e855e8U, 0x369200aaU, 0x142b009dU, 0xc7378003U, 0x7fd5c0cbU, 0x80000000U, 0x40000000U, 0xe0000000U, 0xf0000000U, 0x88000000U, 0x44000000U, 0xa6000000U, 0x6b000000U, 0xcd800000U, 0x47400000U, 0x69e00000U, 0x62300000U, 0xa1380000U, 0x78bc0000U, 0x1f20000U, 0x3f1d0000U, 0xfaa58000U, 0x95d9c000U, 0x840fa000U, 0x60b1000U, 0x7b02c800U, 0xb58f3c00U, 0x8b4a6200U, 0x8beae100U, 0xaf386280U, 0x7b7e140U, 0xf27de260U, 0x2f5e21b0U, 0x34ca42e8U, 0x39a931f4U, 0x4c5a8a4eU, 0xfd4b0d9fU, 0x38ed6883U, 0xbeb42cd8U, 0xdaf0aa6aU, 0x9a99ddfaU, 0x9e000abU, 0xd2300032U, 0xc9380042U, 0xccbc00f9U, 0x2ff20076U, 0x101d00b3U, 0x91258011U, 0xb999c0ddU, 0x206fa068U, 0x237b1026U, 0xb3dac8e6U, 0xaf033cf0U, 0x2b806280U, 0xcc4be1d2U, 0x546fe2a8U, 0xad73216fU, 0x80000000U, 0x40000000U, 0x60000000U, 0xd0000000U, 0xe8000000U, 0xf4000000U, 0x4a000000U, 0x51000000U, 0xae800000U, 0xb5c00000U, 0xb5a00000U, 0x7a500000U, 0x67580000U, 0xdfdc0000U, 0xe51a0000U, 0x35370000U, 0xed298000U, 0xd09ec000U, 0x3f766000U, 0x23c17000U, 0x7aa89800U, 0x7fd44400U, 0x1510de00U, 0x6d359b00U, 0x212ade80U, 0x86929b40U, 0xd07b5ee0U, 0x96405b90U, 0x30ef3e08U, 0xd13a2b64U, 0x6f2c2642U, 0xc59baf35U, 0xe3f918ecU, 0xdb068480U, 0xdf84bed9U, 0xab4febbaU, 0x3869c65eU, 0xd3f31ff5U, 0xa30e6033U, 0xa38d70e4U, 0xc54a98fcU, 0xcb6f44d1U, 0xd87b5e47U, 0xf2405bc6U, 0xf2ef3e4eU, 0xa43a2bc2U, 0x63ac26a3U, 0xd55baf8bU, 0xb2d91846U, 0x459684a6U, 0xa3fcbee1U, 0xbb03ebbeU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0xf8000000U, 0x34000000U, 0x76000000U, 0x4d000000U, 0x88800000U, 0x93c00000U, 0x9e200000U, 0x5fd00000U, 0x40d80000U, 0x9b540000U, 0x511a0000U, 0xde710000U, 0x7b4e8000U, 0x7de5c000U, 0xd9fea000U, 0x9b0c7000U, 0x558bf800U, 0xb34f4400U, 0x71e0e600U, 0x7bf6fb00U, 0x1002e680U, 0x6803fbc0U, 0x9c0e6660U, 0xa033b70U, 0xf7044698U, 0x878b8b44U, 0x20479eeeU, 0xc8697f09U, 0xdab02066U, 0x12e9b09aU, 0x1a755878U, 0xd5433405U, 0x54eb1ed8U, 0x6f79bf2eU, 0x89c200f1U, 0x1250004U, 0x4454809cU, 0x6a94c044U, 0xa43020d5U, 0xc29b0c8U, 0xecd55890U, 0xa953345dU, 0x72131e5fU, 0x9ffdbf63U, 0xee000088U, 0x90000d9U, 0xe68000d1U, 0x5ac0001aU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0x68000000U, 0x44000000U, 0x32000000U, 0x19000000U, 0x5d800000U, 0x52400000U, 0x2b600000U, 0x5c100000U, 0xd9980000U, 0x7dc0000U, 0xcab20000U, 0xa5a50000U, 0x14bb8000U, 0x6aa3c000U, 0xf232e000U, 0x64667000U, 0xfa902800U, 0x3752cc00U, 0x7f7c9a00U, 0xf1802b00U, 0x64471a80U, 0xe063eb40U, 0x6895fa60U, 0xbe559b30U, 0x3afdd208U, 0x8fcb5774U, 0x392b483aU, 0x97727c6dU, 0xf585d2e7U, 0xb647577fU, 0x896148acU, 0x5d1b7c13U, 0xa814527dU, 0x239d9760U, 0xcada288dU, 0xbd3bcca8U, 0xc2ed1afeU, 0x145aebfdU, 0x4ffc7a40U, 0x44435bfaU, 0x306cb2afU, 0x9092e7e9U, 0xe25b80efU, 0x24f3c0e9U, 0xe0cae048U, 0x4faa7096U, 0x81ba2843U, 0xd12bccfaU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x70000000U, 0x28000000U, 0xcc000000U, 0x4a000000U, 0x63000000U, 0x6e800000U, 0x26400000U, 0x3ee00000U, 0xa1700000U, 0x4bf80000U, 0x5bb40000U, 0x845a0000U, 0x94ad0000U, 0xf5978000U, 0x198f4000U, 0x26c1e000U, 0x1da2d000U, 0xa81fb800U, 0xe94c9c00U, 0xaa619200U, 0x2c37d500U, 0xa7961280U, 0xbe8895c0U, 0x5e4ff260U, 0x4aee45b0U, 0x7f724a48U, 0x86fbd97cU, 0xd03e5802U, 0xe59e4c1fU, 0x81862aecU, 0x22cf49f9U, 0xebad80b2U, 0xa91240e8U, 0x28ce60b1U, 0xa8a990cfU, 0x579c58b7U, 0x56874c84U, 0x724baa4eU, 0x70ed0914U, 0x347be0f2U, 0x247fd02dU, 0xbc703821U, 0xb877dca8U, 0x4e7a72b2U, 0x4f780556U, 0x8efe2acdU, 0x8c3b4951U, 0xf7978000U, 0x68f40beU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0x98000000U, 0x6c000000U, 0x16000000U, 0x45000000U, 0x5a800000U, 0x77c00000U, 0x93e00000U, 0xc9d00000U, 0x5580000U, 0xf7940000U, 0x1ef60000U, 0x70eb0000U, 0x7e5a8000U, 0x2c184000U, 0x21b72000U, 0xe3cc7000U, 0xd9e55800U, 0xf2d16400U, 0x3ed5fa00U, 0x38dd5700U, 0xc5d77a80U, 0x235117c0U, 0xda965aa0U, 0x60766710U, 0xe5298238U, 0xd2bf437cU, 0xec4b582eU, 0x4cae6439U, 0xaaf97af4U, 0xeaee178eU, 0xdd5adac7U, 0x7b952757U, 0xf8fc227aU, 0x7def731cU, 0xd0d720eaU, 0x21dc7045U, 0xe15d5858U, 0x3595649bU, 0xf1fbfa90U, 0xe1625716U, 0x7a1bfac7U, 0x84b25776U, 0x4943fad4U, 0xe626575cU, 0x9535fab3U, 0x8d0d5738U, 0x6e8f7ab3U, 0x2dc5171bU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0xb8000000U, 0x54000000U, 0xce000000U, 0x93000000U, 0xa1800000U, 0xe3400000U, 0x76600000U, 0x13b00000U, 0xc8380000U, 0x66740000U, 0xfa920000U, 0x2fef0000U, 0x4fc8000U, 0xc05dc000U, 0x8ecb2000U, 0x7f211000U, 0x30d18800U, 0xd50f7c00U, 0xce88ba00U, 0xcdd100U, 0x4c2c3a80U, 0x215411c0U, 0x5e4d1ae0U, 0x54ee0110U, 0x89721258U, 0xd913bd44U, 0x75ad0896U, 0xe612bcd7U, 0xee239ab7U, 0xe85cc1f4U, 0xc2c5b221U, 0x552f6df7U, 0x5d7a031U, 0xb8cd015U, 0x1642a83dU, 0xc8ea6c3dU, 0x1b733236U, 0xb819ad5dU, 0x652a0057U, 0xaddb0046U, 0x878e80f7U, 0x5c42c065U, 0x2defa072U, 0x7df8d04bU, 0x34d0a8c0U, 0x63056c51U, 0x698fb2b3U, 0xbf446dacU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0xb8000000U, 0x4000000U, 0x3e000000U, 0x3b000000U, 0x2e800000U, 0x80400000U, 0x5a00000U, 0x8df00000U, 0x51780000U, 0x88340000U, 0xb2160000U, 0x1c250000U, 0x61368000U, 0xf592c000U, 0x1bef2000U, 0x43559000U, 0x6a0bf800U, 0x6d0e3c00U, 0xb980c600U, 0x1cc2c900U, 0x3cee4680U, 0xa7d409c0U, 0x774f66a0U, 0x492099f0U, 0x1cbc1e18U, 0xf75d65f4U, 0x2c0b7826U, 0x7209fccfU, 0x99016688U, 0x1f81998fU, 0x13c49e2dU, 0x946ea5f2U, 0x189cd8e4U, 0x626fac4eU, 0x7f9d3e50U, 0x66e9f5adU, 0x72d80081U, 0xcac40013U, 0x6bee00a9U, 0x1b5100a9U, 0x7e008031U, 0xdb07c0ceU, 0x3e81a0c3U, 0x84350f9U, 0xb9aad839U, 0xb7faac81U, 0x5473be4eU, 0x9dbf35fbU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0x38000000U, 0xac000000U, 0xda000000U, 0x3b000000U, 0x73800000U, 0xa400000U, 0xbd600000U, 0x95100000U, 0x8d980000U, 0xac540000U, 0x77e0000U, 0xdd0f0000U, 0x6a848000U, 0x4ec24000U, 0xea5e000U, 0x21375000U, 0x7a6be800U, 0x64958c00U, 0xa0ddfa00U, 0x90b01b00U, 0x37277a80U, 0xe87d5bc0U, 0xb8861a20U, 0x31c84bd0U, 0x93281218U, 0x767a977cU, 0x6d8600c2U, 0x1f4b0047U, 0x33e28031U, 0x25d9408dU, 0xe63f602cU, 0x8bea1008U, 0x49d28899U, 0x9c349c08U, 0xa0edf244U, 0x25dc7eeU, 0x3a75e8ddU, 0xc78a8c6aU, 0xac417a4eU, 0xc4665b0eU, 0x619c9aa1U, 0x16550bbaU, 0x8c717244U, 0x868b8770U, 0xf4ce0888U, 0x85a2dc4bU, 0x7ab612aaU, 0xe425973fU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x50000000U, 0xf8000000U, 0xe4000000U, 0x62000000U, 0xdf000000U, 0x8d800000U, 0xfd400000U, 0x1600000U, 0x2bd00000U, 0xe5580000U, 0xd3940000U, 0xb2b60000U, 0x9a830000U, 0xdcc48000U, 0xf226c000U, 0xdbb2e000U, 0xe2021000U, 0x1f014800U, 0xad8edc00U, 0xad4fea00U, 0xf96a2700U, 0xcfdd6a80U, 0x875fe7c0U, 0xc930aa0U, 0x3f3f3790U, 0x67cea258U, 0xdda4fb74U, 0xd9f2803aU, 0x3ee5c0abU, 0x31966037U, 0xadb4d096U, 0x370ba816U, 0x7188ccedU, 0xb40a20bU, 0x1463fbdaU, 0x6558005bU, 0x1394005fU, 0x92b600aaU, 0xca8300c0U, 0x24c480a8U, 0x1626c0bdU, 0xb9b2e0c8U, 0x3d0210f8U, 0x92814838U, 0x50cedcb9U, 0xac2feaa7U, 0xd2ba271aU, 0x2a856a14U, 0x54cbe7ffU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x10000000U, 0x98000000U, 0xd4000000U, 0x6e000000U, 0x1f000000U, 0xf800000U, 0x4ac00000U, 0x3de00000U, 0x2b500000U, 0x47d80000U, 0x709c0000U, 0x9ab60000U, 0x36870000U, 0xf6468000U, 0x72afc000U, 0xa5732000U, 0xdebd000U, 0xe35ea800U, 0xabd14400U, 0xda9b7a00U, 0x73babf00U, 0xf20bfa80U, 0xdd027f40U, 0x1a865a20U, 0xbc4a6f50U, 0x2ba5d2b8U, 0xe9fbfb84U, 0x6aa880d6U, 0x3174c09bU, 0xc3e3a059U, 0xec531091U, 0x3c5308c4U, 0x445954aaU, 0x2058f21bU, 0xc65b2b0eU, 0x955ea86fU, 0x20d14467U, 0x1b1b7ab6U, 0x367abf0fU, 0x586bfa96U, 0x68927fadU, 0xebe5a64U, 0xf8866fadU, 0xf94bd2ddU, 0xe520fb69U, 0x3bb80085U, 0x5e0c00b8U, 0xd70e00cfU, 0xe38b0058U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0x28000000U, 0x84000000U, 0x9a000000U, 0xfd000000U, 0xd5800000U, 0xc5c00000U, 0x5b600000U, 0x3fb00000U, 0x9d380000U, 0x98740000U, 0x37520000U, 0x9c4b0000U, 0xb0a18000U, 0xdbd5c000U, 0xb6026000U, 0x2300b000U, 0xd2856800U, 0x7d4e7400U, 0x6329e200U, 0x251f0900U, 0x63e26280U, 0xc7f5c9c0U, 0xe79382e0U, 0xf6abb950U, 0x40d50ac8U, 0xc880bdd4U, 0x4043e052U, 0xd6a57029U, 0x70df0807U, 0x108ac42cU, 0x7c468a3cU, 0xe0ae7d83U, 0x93d80009U, 0xa204005fU, 0x910a0044U, 0xab8f006eU, 0x32cb8069U, 0x5beac064U, 0xabf1e036U, 0x999e7001U, 0x1a68836U, 0x405b04dcU, 0x5cceeaecU, 0x44e1cd9fU, 0x4f76e879U, 0x7d0b4e4U, 0xd00a0262U, 0x880a7965U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0x8000000U, 0x24000000U, 0xee000000U, 0xcb000000U, 0x1a800000U, 0xdb400000U, 0xd5600000U, 0xdab00000U, 0xf5380000U, 0x67f40000U, 0xf5a0000U, 0xa9c10000U, 0x5a298000U, 0x9d7c000U, 0x708f2000U, 0x6e4c9000U, 0x5cefb800U, 0x87754c00U, 0x39157a00U, 0x692aa100U, 0x1f5efa80U, 0x31c861c0U, 0x26225a60U, 0x7bd23170U, 0x798b4268U, 0x75cc2d54U, 0xb826a086U, 0x58db509fU, 0xf700981cU, 0x4889dc84U, 0x8242c229U, 0x76ebedeeU, 0x12718054U, 0xe093c06dU, 0x8ced20d5U, 0xff79907fU, 0xf51c387dU, 0x13238c39U, 0x3253da3eU, 0xc441f162U, 0x9e662e3U, 0xbef5bd52U, 0x6cda98faU, 0x8108dc23U, 0xff8b4217U, 0xeacc2d42U, 0xa4a6a035U, 0xdc9b5022U, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0x68000000U, 0x9c000000U, 0x6e000000U, 0x9f000000U, 0xd3800000U, 0x1c400000U, 0xcea00000U, 0xd7f00000U, 0xc9780000U, 0xa7bc0000U, 0x41da0000U, 0x134d0000U, 0x45238000U, 0x5fbe4000U, 0x85d6a000U, 0xe94c5000U, 0x5829e800U, 0x1532ec00U, 0x49106600U, 0x862e2900U, 0xc231e680U, 0x16916940U, 0xec66c6e0U, 0x67927930U, 0xe0e00e88U, 0xc85f85acU, 0x420ca0e6U, 0xb9015033U, 0xc08a68b5U, 0xb9ccac6fU, 0xb9e6c61bU, 0x38d279c8U, 0xf3c00e3aU, 0xecef85b3U, 0xfe54a075U, 0x490d504fU, 0xe888680bU, 0x45cdacd0U, 0xa7e7464eU, 0xcfdd3901U, 0xbc4f2ee4U, 0x9ea09573U, 0xaff0682cU, 0x4d71acdeU, 0x3dbd4659U, 0x2cd039f0U, 0x31ccae31U, 0x15eed515U, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0xa8000000U, 0xbc000000U, 0x66000000U, 0x3b000000U, 0x1b800000U, 0x66c00000U, 0x74600000U, 0xfb00000U, 0x51780000U, 0x111c0000U, 0xf4aa0000U, 0xd70000U, 0x25418000U, 0x76a04000U, 0x39d12000U, 0x47c31000U, 0x12eae800U, 0x79f9a400U, 0xa05bf200U, 0x1804e100U, 0x40ad280U, 0x1207f140U, 0xb1003ae0U, 0xee8e5510U, 0xfa43c848U, 0x6f26b4acU, 0x261b1aaeU, 0x312a45d7U, 0x2910a055U, 0xc0a350a1U, 0xeadbc869U, 0x804ab402U, 0x42291a96U, 0x9e9145c4U, 0x8632037U, 0x49b81065U, 0x5a7968fbU, 0xf292e451U, 0x86615234U, 0xaeb0b182U, 0x77f09ab9U, 0x75d0522U, 0x55800084U, 0xa1c00050U, 0x69e0002fU, 0x27000e6U, 0x969800b3U, 0xc46c0035U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0xf8000000U, 0x64000000U, 0xa2000000U, 0x73000000U, 0xca800000U, 0x3bc00000U, 0x5ca00000U, 0x1c700000U, 0x33b80000U, 0x15140000U, 0xce6a0000U, 0x5d510000U, 0x9c8a8000U, 0x2c6c000U, 0xa92de000U, 0xe3385000U, 0x19d63800U, 0x2a4a6400U, 0xc1e2fe00U, 0xa51d8100U, 0xf66f1e80U, 0xd955d1c0U, 0xe812660U, 0x89cbb5f0U, 0x7a9d898U, 0x7af73494U, 0x367446baU, 0xfcb02527U, 0xc9928010U, 0xeca2c0ecU, 0x247fe0d4U, 0xb7bd5064U, 0x8716b85dU, 0x456da456U, 0xf3dd9e03U, 0x5471127U, 0x2d66c62bU, 0x7fd2e5b1U, 0xeb4d60c7U, 0x506f9050U, 0xf8515807U, 0xaf04f48aU, 0x2c8126e5U, 0x3acbb526U, 0x2d29d85aU, 0x713734dcU, 0x92d446e6U, 0x84c02501U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x10000000U, 0xf8000000U, 0xc000000U, 0xca000000U, 0x53000000U, 0xef800000U, 0x7ac00000U, 0xde600000U, 0x8b100000U, 0xc5d80000U, 0x3dbc0000U, 0x9fa60000U, 0xeff0000U, 0x520c8000U, 0xaf0a4000U, 0x6d89e000U, 0xcdc85000U, 0xfe8e800U, 0x64dca400U, 0x6d301200U, 0x70ebcb00U, 0x1159f280U, 0x1cf39b40U, 0x5d091a20U, 0xd2833f50U, 0x584708d8U, 0xce2bf45cU, 0xa1347a92U, 0x5aed2f4fU, 0xf258005dU, 0x1b7c0065U, 0xd3c6005bU, 0xcaef00b2U, 0x4a54800cU, 0xb77640c0U, 0x9cfe04eU, 0x61e750ebU, 0xa9dc68e7U, 0x7bae4e6U, 0x84a7f27eU, 0x5709be7U, 0x16c39a75U, 0xe4667f7bU, 0x901a68b0U, 0xce55e487U, 0x79737279U, 0xd4c6dbbbU, 0xf36c7afeU, 0x51912f6cU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x30000000U, 0x48000000U, 0x94000000U, 0xd6000000U, 0xa1000000U, 0x65800000U, 0x7dc00000U, 0x5fe00000U, 0xd6b00000U, 0x59780000U, 0xf9940000U, 0x1fa20000U, 0xb8990000U, 0x8a298000U, 0xed52c000U, 0x71cea000U, 0xa5e13000U, 0x1db3a800U, 0xeff9d400U, 0xded99a00U, 0x6d0e1900U, 0xff8f3a80U, 0x86cb29c0U, 0xa16692e0U, 0x65fffdf0U, 0xfdd488a8U, 0x1f8a2464U, 0x76c492feU, 0x8966fd05U, 0xc1fd087bU, 0x63d8e488U, 0x2a8a328cU, 0xc547cd3aU, 0x55aea0abU, 0xfb913006U, 0xc8aba8afU, 0x2c1dd406U, 0xea639ae1U, 0x13731945U, 0xba9cbaedU, 0x5d24e947U, 0x79dbb23aU, 0x11810dd3U, 0x5bc2005aU, 0xd6e9002dU, 0x17318011U, 0xbab6c015U, 0x9374a015U, 0x7a9c30dbU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x90000000U, 0x8000000U, 0x6c000000U, 0x7a000000U, 0x77000000U, 0x74800000U, 0x9c00000U, 0xabe00000U, 0xff900000U, 0x51580000U, 0xa6340000U, 0x4c6a0000U, 0x54db0000U, 0x1e7f8000U, 0x61cb4000U, 0x97e3e000U, 0x6d911000U, 0xda561800U, 0xa0b2e400U, 0x5ea60a00U, 0xf1be0b00U, 0x9f2fea80U, 0xeff41bc0U, 0xc7867260U, 0xdb4dbf50U, 0xd7239868U, 0xa3f2a43cU, 0xcd826a92U, 0x34405b8bU, 0xc7a81286U, 0xbc38efd2U, 0x6b63e0c5U, 0xc85110d1U, 0xebb61866U, 0xb822e4acU, 0x737e0ac4U, 0x324a0b16U, 0x2a5ea8dU, 0x33bf1b2dU, 0xfc21f27aU, 0x1572fffeU, 0xa74a78c1U, 0x6528b4c9U, 0x58f3f29cU, 0x530dff45U, 0x4287f8cfU, 0x74ccf459U, 0x306592caU, 0xe6dcafd8U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0x8000000U, 0x7c000000U, 0x5a000000U, 0x33000000U, 0xb8800000U, 0x92c00000U, 0x2fe00000U, 0xafd00000U, 0xdc180000U, 0x447c0000U, 0x3be60000U, 0xf9d70000U, 0x8d1b8000U, 0x2bf24000U, 0x3fa4e000U, 0x51f65000U, 0xdca69800U, 0x417bd400U, 0xa260ba00U, 0x3c9d7f00U, 0x42ba5a80U, 0x2002f40U, 0xa7014220U, 0xae8ebbd0U, 0x63c69828U, 0xd06bd4acU, 0xa398baf2U, 0x8317fdfU, 0x4fc45a6aU, 0x626b2f9dU, 0xdc9cc2edU, 0x72bbfbdeU, 0x9a01f863U, 0xd303c4d5U, 0x8884c23aU, 0xac7fbcdU, 0x5be7f800U, 0x89d4c40bU, 0xb51f42e4U, 0xcff5bb1dU, 0x11a318adU, 0x44f2947eU, 0xd21da73U, 0x58326f9dU, 0xa7c5a266U, 0x2e68eb47U, 0x1e98009bU, 0x35bc005fU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x50000000U, 0xf8000000U, 0x1c000000U, 0x62000000U, 0x77000000U, 0xf3800000U, 0x93c00000U, 0xcb600000U, 0x3500000U, 0x19980000U, 0xf4740000U, 0x6a0000U, 0xe2d70000U, 0xb55c8000U, 0x789f4000U, 0x16f26000U, 0x392f9000U, 0xa4f6e800U, 0x762c3400U, 0xab7bd200U, 0xd7ecaf00U, 0xef1bb280U, 0x3b303fc0U, 0x743da60U, 0x73204b90U, 0xf7fce898U, 0x1bab348cU, 0x7dbf527aU, 0x6007ef3bU, 0x9003d2e9U, 0x1808af38U, 0x4c09b23aU, 0x9a033f77U, 0x6b0d5ab9U, 0x918c0be8U, 0xe4c00828U, 0x38e8e4eeU, 0x90955a25U, 0xd2f80bc6U, 0xf72a0881U, 0x19ffe498U, 0x16a9daa4U, 0xb5374b74U, 0x9a406840U, 0xa3a474c2U, 0x41b53205U, 0xb20c7fd0U, 0x4f073a72U, 0xf879b87U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x10000000U, 0x48000000U, 0xbc000000U, 0x2000000U, 0xdf000000U, 0xb8800000U, 0xb1c00000U, 0xc8600000U, 0x77d00000U, 0x8f180000U, 0xcefc0000U, 0xc5620000U, 0xf85b0000U, 0xca538000U, 0xed524000U, 0x51dd6000U, 0x6151000U, 0xe771d800U, 0x49212400U, 0x12787200U, 0xc2a57700U, 0xb13f1280U, 0xc8076740U, 0xfc074a60U, 0xe2030350U, 0xcf0bd828U, 0xf08624ecU, 0xdc9f2aaU, 0xca6c3773U, 0xa8d1f272U, 0x37903792U, 0x7f33f212U, 0xd0b3749U, 0x8f8072d7U, 0x454977e4U, 0x23a512a8U, 0x94b06772U, 0xfe4eca12U, 0x2d264359U, 0xa47f3804U, 0x43a674e6U, 0xc4b4ca29U, 0x564143d9U, 0x812eb854U, 0xee7f345eU, 0x20a22a56U, 0x7e3a1391U, 0x38800036U, 0xf1c0000fU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x30000000U, 0xa8000000U, 0x94000000U, 0xde000000U, 0x11000000U, 0xf1800000U, 0xb8c00000U, 0x95200000U, 0xad700000U, 0x94380000U, 0x71d40000U, 0x4d8e0000U, 0x32c50000U, 0xfa238000U, 0x7df0c000U, 0x75762000U, 0xc831b000U, 0xabdde800U, 0x1a888400U, 0xee424600U, 0xf962c900U, 0x9f17e680U, 0xada3b9c0U, 0xb83c2e20U, 0x63da8df0U, 0x1e838088U, 0xa840c064U, 0xd46e20d6U, 0x2495b0b5U, 0xda6be887U, 0xcd99843dU, 0x87efc6baU, 0xa7570904U, 0xe1c24670U, 0xa0a2c9a4U, 0xf3b7e66cU, 0x1c13b91eU, 0xcf242eabU, 0x3a7e8d5aU, 0xe8b58094U, 0x4291c0f2U, 0x763a003U, 0x7e1070a2U, 0x54264822U, 0xa4fcf4bbU, 0x80f20ef4U, 0x36ff3d3bU, 0x13f068f4U, 0xc7d44a1U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x70000000U, 0x88000000U, 0x2c000000U, 0x66000000U, 0x75000000U, 0xe3800000U, 0x2fc00000U, 0xbaa00000U, 0xeed00000U, 0xea980000U, 0xf3f40000U, 0xd1820000U, 0x58cd0000U, 0x6298000U, 0x419d4000U, 0x61742000U, 0x47c7f000U, 0x26a50800U, 0x60da9400U, 0xc390ee00U, 0xfe79fb00U, 0xa74d4e80U, 0x67e34bc0U, 0xb23c66e0U, 0xf22e2fb0U, 0x53918068U, 0xc679409cU, 0x634e208eU, 0x5deef029U, 0x2936880dU, 0x48aed476U, 0xf9d74e3fU, 0x261a4bb4U, 0xd4b7e633U, 0x766e6ff2U, 0x8af42061U, 0x8407f0f5U, 0x9a0508d5U, 0x8b0a94b6U, 0x4288ee58U, 0xe4dfb07U, 0xaa6f4e44U, 0xa4fe4bfcU, 0xbd0de63dU, 0x6f876fa8U, 0x59c7a07aU, 0x37a3b078U, 0xa95aa863U, 0x8f5d24e9U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0xb8000000U, 0x9c000000U, 0xc6000000U, 0xb5000000U, 0xab800000U, 0x79400000U, 0xc600000U, 0x78b00000U, 0xe2780000U, 0xc35c0000U, 0x65860000U, 0x38470000U, 0xe5e88000U, 0x7efb4000U, 0x8e962000U, 0x4022f000U, 0x9f538800U, 0x438d7c00U, 0xbd4b6a00U, 0x66689900U, 0x23b5ca80U, 0xd8f12940U, 0x4b906220U, 0x63aea5d0U, 0x52108098U, 0xade7404cU, 0x2af020deU, 0x5c95f0b9U, 0x872308d5U, 0x63da3c50U, 0x7e434a61U, 0x10e169b4U, 0x7570c2c5U, 0x67dc1582U, 0xf443a8abU, 0x7be88c53U, 0x67f0627aU, 0xcb1ea589U, 0xa86880f0U, 0x62bb406fU, 0x31762039U, 0x4dd2f021U, 0xf4b88b3U, 0xd1617cf8U, 0x57356a29U, 0x513399f3U, 0x43b4a79U, 0x9fbd691fU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x70000000U, 0xe8000000U, 0xc4000000U, 0x3e000000U, 0x47000000U, 0xf4800000U, 0x83c00000U, 0xdc600000U, 0xb5d00000U, 0x74980000U, 0x38340000U, 0x23060000U, 0x7a890000U, 0xccb8000U, 0x9ce5c000U, 0xe0112000U, 0x2bf3d000U, 0x476cd800U, 0x935d0400U, 0x6a57b200U, 0x19d32700U, 0x4e951280U, 0x613137c0U, 0xe08eeaa0U, 0xe5c6e3b0U, 0x97660048U, 0xcb590074U, 0x665380f6U, 0x93d1c0f3U, 0xdf972022U, 0x16bad000U, 0xa9c75816U, 0xfd68c471U, 0xa5e925cU, 0x89d4f70eU, 0xf69fca0bU, 0x3d353337U, 0xf28ad8fbU, 0x58c4046eU, 0x1ae43207U, 0xfb12e779U, 0xcd7a32fdU, 0x79afe767U, 0xc2b7b2a7U, 0xefc327d5U, 0xc66d1203U, 0x9cd537a9U, 0x5f10ea1aU, 0x637be323U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xb0000000U, 0x28000000U, 0x14000000U, 0x92000000U, 0xbd000000U, 0xa0800000U, 0xe400000U, 0x94e00000U, 0xe6500000U, 0x5d980000U, 0x33bc0000U, 0x7d460000U, 0x5f650000U, 0x5f938000U, 0x56b0c000U, 0x41c6e000U, 0x672db000U, 0xcc79f800U, 0xb960bc00U, 0x20946200U, 0x733daf00U, 0x63070280U, 0x5385df40U, 0x85cb9a20U, 0x8d2813f0U, 0x5d78e008U, 0x7e4b0e4U, 0x3dd4781aU, 0x7c597c19U, 0x49f021aU, 0x8939dfa7U, 0x6a0d9a26U, 0xd10d1315U, 0x1e8b6049U, 0xad44702bU, 0x276a983cU, 0x7398cc2eU, 0x48b8fac5U, 0x52c06393U, 0xfcac78d1U, 0x4db57c9dU, 0x3e410246U, 0xfce0dfd0U, 0x52581accU, 0x7f98d32cU, 0xa6be001dU, 0xc9c900b8U, 0xc32d80ccU, 0x7679c00eU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xf0000000U, 0x68000000U, 0xb4000000U, 0xfa000000U, 0xcf000000U, 0xb9800000U, 0x67c00000U, 0x27600000U, 0x3d700000U, 0xf8380000U, 0xeb1c0000U, 0x61c60000U, 0x16610000U, 0x79f38000U, 0xad7ac000U, 0x803e6000U, 0x671e1000U, 0xb7c1c800U, 0xff669400U, 0x41775200U, 0x4632bd00U, 0xb61cb280U, 0xa3476d40U, 0x32289a20U, 0xf65929b0U, 0xee66048U, 0x22b21004U, 0x535fc832U, 0x6b948bU, 0x70fad22bU, 0xc5f57d1cU, 0xf37752e4U, 0x8d32bdd5U, 0x3d9cb246U, 0x4f876d01U, 0x3ec89af6U, 0xd7e929c4U, 0x923e6052U, 0x5c1e109bU, 0x5441c813U, 0xa7a69430U, 0xb7975242U, 0xa882bd14U, 0x9344b26aU, 0xba2b6de0U, 0x12569a67U, 0x6ce4290dU, 0x31b3e04aU, 0xa4d9d07aU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0xc8000000U, 0xec000000U, 0x42000000U, 0x1f000000U, 0x77800000U, 0xe5c00000U, 0xe8600000U, 0xa9500000U, 0x70180000U, 0x9c340000U, 0x71c20000U, 0x1e6f0000U, 0xb05f8000U, 0xe69f4000U, 0x9b726000U, 0xf8e91000U, 0x8f1da800U, 0x7bbf5400U, 0x3c04e200U, 0x4a062f00U, 0x930b0280U, 0x658f7fc0U, 0x32c34ae0U, 0x73e27b90U, 0xe926028U, 0x8779107cU, 0x42e5a8eaU, 0xe41b54a3U, 0x6a3ee2fdU, 0x68cd2f16U, 0x88ee825dU, 0xb71b3f93U, 0x6fb4aa0fU, 0xa0f2b40U, 0x330028c1U, 0x558f1457U, 0xaac9025bU, 0x57e07fc7U, 0xa09cca27U, 0xda7d3bd6U, 0x2a600099U, 0x765000a6U, 0x6798006fU, 0x29f400a5U, 0x51a20043U, 0x5b3f008cU, 0x82478019U, 0x65ab40c2U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0xd8000000U, 0xf4000000U, 0x2e000000U, 0x73000000U, 0x1e800000U, 0x67400000U, 0x9f600000U, 0xde700000U, 0x7ab80000U, 0x2f140000U, 0xb7ce0000U, 0x3b2b0000U, 0xf79a8000U, 0x3f87c000U, 0xc8cc2000U, 0xefa09000U, 0xb5d93800U, 0xe9652c00U, 0x997d2a00U, 0xea328500U, 0xeb5d8a80U, 0xee2ad5c0U, 0x761c1220U, 0x3c43a910U, 0xbdeea0f8U, 0x1b3350e4U, 0x9cdb1856U, 0x6aeebc57U, 0x33be92e8U, 0xdc9069e0U, 0x150c802fU, 0x2188c00aU, 0xd3c0a05bU, 0xad285046U, 0x99988aU, 0x70d7c3eU, 0xf084b214U, 0xb44ff958U, 0x51e13816U, 0x61312c4cU, 0x11d32ab5U, 0xdf698537U, 0xbe7f0ac6U, 0xab915f7U, 0x271e327eU, 0x9bc839b5U, 0xe12d1815U, 0xaa91bc84U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xf0000000U, 0x28000000U, 0xec000000U, 0xca000000U, 0x51000000U, 0x17800000U, 0xf1c00000U, 0x65200000U, 0xc7500000U, 0xd2180000U, 0xcc740000U, 0x524a0000U, 0x5aed0000U, 0x35738000U, 0x69cb4000U, 0x812ce000U, 0xf1597000U, 0x911fc800U, 0x4efdf400U, 0x920cf600U, 0x55049b00U, 0xd1819680U, 0x9acfabc0U, 0xbab3e60U, 0xcd1d6f30U, 0x8cff6048U, 0x3f0230dcU, 0x508b2802U, 0xb540844dU, 0xce613ef5U, 0xa6306f4cU, 0x3cace038U, 0x619970a7U, 0x2bbfc840U, 0x646df40aU, 0xc734f6cdU, 0xe3209bbdU, 0x8c5396ffU, 0xac96ab6eU, 0x1e32be91U, 0xc8ab2f03U, 0x8f980008U, 0xacb400cdU, 0xc0ea0052U, 0x9c7d006bU, 0xaa4b8075U, 0x8eef4097U, 0xcb7ee0c5U, 0x36c0700cU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xb0000000U, 0xf8000000U, 0x3c000000U, 0x4e000000U, 0x19000000U, 0x56800000U, 0x7e400000U, 0x65200000U, 0xa7500000U, 0xe2780000U, 0xb52c0000U, 0xf5e0000U, 0x36790000U, 0x8f288000U, 0x9c524000U, 0xbfe2000U, 0xf0edf000U, 0xc8b6b800U, 0xe14cac00U, 0xaea44600U, 0x5d9e9f00U, 0x1e12fe80U, 0xc0d23340U, 0x5eb6b820U, 0x344cacf0U, 0xee244658U, 0xb6de9f8cU, 0x9bb2fe36U, 0x3cc23365U, 0xc16eb838U, 0x4170ac97U, 0x30a2466bU, 0xec9b9f55U, 0x9c9c7eb1U, 0x84957377U, 0xa89e18d5U, 0xae9a1c14U, 0x739c5eebU, 0x571183ffU, 0x7e582035U, 0x54f8f01bU, 0xdb603896U, 0x2277ec45U, 0x552ae62dU, 0x1f5d2ff3U, 0x7e7c667dU, 0x4b266fbaU, 0xee52c618U, 0x5cf5dfe8U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0x98000000U, 0x34000000U, 0xbe000000U, 0x59000000U, 0xff800000U, 0x1fc00000U, 0xae600000U, 0xb7700000U, 0x1180000U, 0xc26c0000U, 0xdd7e0000U, 0xd61b0000U, 0x6cec8000U, 0x9134c000U, 0xedb3a000U, 0x92f2f000U, 0x81d6a800U, 0xce89a400U, 0x3c4bea00U, 0x93a23900U, 0xc21d4280U, 0x2eb9d40U, 0xf036a820U, 0xb639a4d0U, 0xab33ea38U, 0x42be39a4U, 0x387b42a6U, 0x7b9c9d2dU, 0x242861U, 0xb7d66496U, 0x7b8cca69U, 0xe9c8090cU, 0xfb664a09U, 0x52fbc958U, 0x61df6abdU, 0xfe8af982U, 0x3448e258U, 0x3fae6d0bU, 0x48128028U, 0xe5efc0cbU, 0x56bf20c9U, 0x567630aaU, 0x1a9d087bU, 0x5ba754dfU, 0x8e1b4291U, 0xb8ec9da1U, 0x1f3c2853U, 0xbcba6414U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0xf8000000U, 0xb4000000U, 0x12000000U, 0x39000000U, 0x2d800000U, 0x4bc00000U, 0xa1e00000U, 0xc8f00000U, 0xf1180000U, 0x3dec0000U, 0xd6fe0000U, 0xce170000U, 0x6b668000U, 0x71bac000U, 0xbdbd6000U, 0x5bb43000U, 0xd0b38800U, 0x943f0400U, 0xa709200U, 0x54501900U, 0x2f431a80U, 0x2faf1d40U, 0xced38820U, 0x6e0f0410U, 0xd7089258U, 0xba8c19e4U, 0x51451a6aU, 0xa0a41dcdU, 0x9053081fU, 0xd54ec462U, 0xfaad72d4U, 0x1555e967U, 0xf6cd723aU, 0xd665e938U, 0x6357238U, 0x7379e991U, 0xd9d372e9U, 0x3482e998U, 0x764bf24cU, 0xb22f2942U, 0x8d1012adU, 0xd3e1d9eaU, 0x41fefa21U, 0xd49aed61U, 0x6a25e044U, 0x2919f072U, 0x99e8686dU, 0x9cf1f423U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x30000000U, 0x98000000U, 0x3c000000U, 0xe2000000U, 0xbb000000U, 0x6c800000U, 0x7a400000U, 0xa0a00000U, 0x70b00000U, 0xcc180000U, 0xcea40000U, 0x71ba0000U, 0x479d0000U, 0xa6e8000U, 0x88504000U, 0xc700e000U, 0x2e831000U, 0x91413800U, 0x642f8c00U, 0xaef1be00U, 0xb2bbb900U, 0xe7108680U, 0x6a2435c0U, 0x9ff938e0U, 0xa13b8cf0U, 0x1fd3bef8U, 0x71c2b90cU, 0xa46406faU, 0xe9597547U, 0x7c8f586eU, 0x724cdc31U, 0x54a86634U, 0x6b32506U, 0x311a0096U, 0xc72d00f9U, 0x3e768053U, 0x4af44078U, 0xccbae02fU, 0xee1e10f9U, 0x15afb843U, 0x2d3fcca3U, 0xa5d15e87U, 0x96c8a9b9U, 0x1ae9be64U, 0xb01fb9a9U, 0x8caa86a8U, 0x9ab93540U, 0x8317b827U, 0xd42bcc0aU, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0x68000000U, 0x74000000U, 0x72000000U, 0x8b000000U, 0x7f800000U, 0x31400000U, 0x43200000U, 0x88700000U, 0x49580000U, 0x722c0000U, 0x38f20000U, 0x6d9f0000U, 0x874b8000U, 0xe223c000U, 0x10f76000U, 0x79901000U, 0xe5428800U, 0x1268c00U, 0x1b7fb600U, 0x3adc7d00U, 0x2d653e80U, 0xf6d6f140U, 0x636888e0U, 0xbd58c50U, 0x9de63608U, 0xd210bd64U, 0x9601de9aU, 0xd10921bfU, 0xe08f60edU, 0x2ccc10eaU, 0x91688834U, 0xc0d58cddU, 0x82663610U, 0xf350bd05U, 0xbd21defcU, 0x2d7921e5U, 0xdbd76063U, 0xd5e01066U, 0xd61a8895U, 0x9c0a8c05U, 0x460db69eU, 0x99037d98U, 0xe48ebeccU, 0x26c5314eU, 0x667e87dU, 0xb9599cbeU, 0x4a2ebeb9U, 0x44f5311bU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xf0000000U, 0x58000000U, 0x1c000000U, 0x6a000000U, 0xff000000U, 0xe9800000U, 0x2400000U, 0x5ea00000U, 0xc5f00000U, 0x4580000U, 0x38240000U, 0xb63e0000U, 0x64b50000U, 0x397e8000U, 0xd0924000U, 0xad4e6000U, 0xdf2dd000U, 0xa3b82800U, 0xdcfb5c00U, 0x30dcde00U, 0xb8e9bd00U, 0xdd5af680U, 0x2ca7e1c0U, 0xc6f8a8a0U, 0x57dc1c30U, 0x6d6c3e78U, 0x45162decU, 0xd50cbeb2U, 0xf6816d23U, 0x3bc45e23U, 0xf4eafdcdU, 0xdf54164fU, 0xb7ad71ebU, 0xa97060c8U, 0x9898d02eU, 0x3946a849U, 0x1291c4dU, 0x72b2be0aU, 0xbc746d90U, 0x4e1adecdU, 0xf288bdcfU, 0xadc276abU, 0xb1e4a1a8U, 0x61d648beU, 0x18668c01U, 0x839cf6d9U, 0x96c6e1d4U, 0xee6028c1U, 0xd69f5cedU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xf0000000U, 0xa8000000U, 0x34000000U, 0x12000000U, 0xbd000000U, 0xb3800000U, 0x50c00000U, 0x6200000U, 0x14d00000U, 0xd7f80000U, 0xbca40000U, 0x259a0000U, 0x5c110000U, 0xedd18000U, 0x1e7bc000U, 0x56f6000U, 0x72357000U, 0xd082800U, 0xbb85d400U, 0xf4c05e00U, 0x4c2ca700U, 0x35d27680U, 0x427873c0U, 0x4363a8e0U, 0x2d3f1430U, 0xab86bec8U, 0x6cc617c4U, 0xb02f3e3aU, 0xe3d9d749U, 0x457a5e41U, 0x79eda7ddU, 0xdc7bf6fdU, 0x4067b340U, 0xcdb6c88bU, 0x23cb6411U, 0x8ea7169bU, 0xc89c03c9U, 0xd79a0047U, 0xd111004fU, 0x965180f8U, 0x8abbc0d9U, 0xb94f60e7U, 0xefe57059U, 0x7b7028f2U, 0xeae1d4a0U, 0x64fa5e68U, 0x542da7d2U, 0x9dbf630U, 0xf477b330U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0x38000000U, 0x94000000U, 0x2a000000U, 0x77000000U, 0xc8800000U, 0x27400000U, 0xcf600000U, 0x42d00000U, 0xeb80000U, 0xdee40000U, 0x58120000U, 0xa51d0000U, 0x8a9c8000U, 0xd50c000U, 0xf97ae000U, 0xf2c75000U, 0x77a83800U, 0x32739c00U, 0x2c429200U, 0xf1e74300U, 0x7498aa80U, 0x7059dfc0U, 0x16feb860U, 0x950a5c70U, 0x338ef2d8U, 0x1c9d324U, 0x3d24f292U, 0x9e30d323U, 0x1daa7282U, 0x657d1320U, 0xb4cc125fU, 0x5eaa8381U, 0x17fecab3U, 0x8c8e4f0fU, 0x454c60ecU, 0xf46e90cfU, 0x845c5827U, 0x4cf90c9eU, 0x3a0cca68U, 0xdf034fa7U, 0x3488e075U, 0x114a5069U, 0x3e6cb860U, 0x43575c60U, 0xbc72728aU, 0x894913d3U, 0x3a66129aU, 0x15383e4U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x70000000U, 0x88000000U, 0x84000000U, 0xe6000000U, 0xe5000000U, 0x4a800000U, 0x25c00000U, 0xfd600000U, 0x11700000U, 0xb5180000U, 0xe4ec0000U, 0x233e0000U, 0x8b350000U, 0x3f338000U, 0xf136c000U, 0xe0372000U, 0xc4b9b000U, 0x807b3800U, 0xd1995400U, 0x2c7a00U, 0x2d39900U, 0xd2894280U, 0xb9cfcd40U, 0xc76eb820U, 0x6e769430U, 0xf096da28U, 0xca9e9f4U, 0xb216daeeU, 0xed69e921U, 0x976da8cU, 0x6919e9f0U, 0x7eeeda1fU, 0x2c35e980U, 0x46b0da06U, 0x5370e9a4U, 0x861b5a92U, 0x636a291bU, 0xb8727ae5U, 0x3d96991fU, 0xb222c293U, 0xf9d50db4U, 0x7107980fU, 0xb48a241fU, 0x1cc66250U, 0x2dea7d68U, 0x3bb380c2U, 0x85f6c0f4U, 0x99d7202dU, 0xe109b0fdU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xf0000000U, 0x28000000U, 0xc4000000U, 0x9a000000U, 0x9b000000U, 0xbf800000U, 0x60400000U, 0xf8200000U, 0x3b100000U, 0xe2380000U, 0x4dac0000U, 0xf85e0000U, 0x199d0000U, 0x90f18000U, 0xf48c000U, 0x15a4e000U, 0x54579000U, 0xe79b8800U, 0x61f69c00U, 0x3c3d600U, 0xe66db00U, 0x563e5e80U, 0xbfa14740U, 0x7520820U, 0xcc125cb0U, 0x43b93688U, 0x8cec4b34U, 0xd4f45632U, 0xd54f1b1fU, 0x2ead3e05U, 0x1bdf174bU, 0xafdae04fU, 0x5dda902fU, 0xa2d20808U, 0x77525cd9U, 0xa4193617U, 0x27bc4b6bU, 0xe6ec5635U, 0x67f31b96U, 0xaecb3e00U, 0xd4ee17fdU, 0x78f56018U, 0x2b4f502eU, 0xdfa7687cU, 0x175d0c9bU, 0xb41e5e25U, 0x5fb147ccU, 0xfaea086eU, 0x11fe5cc9U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0x38000000U, 0xdc000000U, 0xaa000000U, 0x29000000U, 0xb2800000U, 0x83c00000U, 0xd6600000U, 0x65300000U, 0x80580000U, 0x86e40000U, 0xbf20000U, 0x42b50000U, 0xeb148000U, 0x22444000U, 0xe6266000U, 0xb616b000U, 0xceccf800U, 0xd2ebf400U, 0x85feaa00U, 0xfdb32d00U, 0xea985280U, 0x209d9c0U, 0xdd007860U, 0x2c8bb4f0U, 0xd4cacad8U, 0x3e09decU, 0xb782a12U, 0xe4726d35U, 0x2df2b278U, 0x9bf295aU, 0x7498e03cU, 0x5503f0caU, 0x88c1824U, 0x42cc0426U, 0xb0e0b2abU, 0xa8fa29b2U, 0x93460aeU, 0xd253b06fU, 0x93e07809U, 0x237bb4c4U, 0xd072ca4dU, 0x53f49d19U, 0x6eb22a01U, 0x99136d20U, 0xe74c32bbU, 0xc6aa695aU, 0xc0d8007aU, 0x240021U, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0xa8000000U, 0xb4000000U, 0xe6000000U, 0x15000000U, 0x63800000U, 0xf1c00000U, 0xc5a00000U, 0xedf00000U, 0x6b580000U, 0x682c0000U, 0xfd320000U, 0x4b7f0000U, 0x71178000U, 0x984bc000U, 0x8b662000U, 0xc4d2b000U, 0x43efa800U, 0xf928400U, 0x8e093600U, 0x810e8d00U, 0xf58c9e80U, 0x5ccf0940U, 0xba2028e0U, 0x4e354450U, 0x5dfd16c8U, 0xf3533da4U, 0x42cb6ceU, 0x173a4de1U, 0xa47d3e65U, 0x559679b4U, 0xf909a0eeU, 0xc98570f8U, 0x7ec38880U, 0xf1233434U, 0x24bb1ebbU, 0x9db4c973U, 0x343e084cU, 0x5afbf49aU, 0x3d8be57U, 0x9362b938U, 0xe8d800b3U, 0xc9ec00f1U, 0xf09200acU, 0x28f0030U, 0x544f80b7U, 0x5167c08fU, 0xf3d420d5U, 0x6b6db0b9U, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0xa8000000U, 0x9c000000U, 0xea000000U, 0xbf000000U, 0x54800000U, 0x12400000U, 0x33a00000U, 0xd5900000U, 0x47380000U, 0x2f2c0000U, 0x6bd20000U, 0x56990000U, 0xa9b18000U, 0x3a694000U, 0x48f26000U, 0x4f46d000U, 0x142ef800U, 0xc15f8c00U, 0x9dd18e00U, 0x4398fb00U, 0x22357680U, 0xca27740U, 0xc11f78e0U, 0x3576cc30U, 0x6c83eec8U, 0x164e2becU, 0x8da38ec2U, 0x6c91fb63U, 0xeebcf65eU, 0x4ae7379dU, 0xf4bf182fU, 0x1de91c6bU, 0x5c3c9656U, 0x95a8e7a9U, 0x789860baU, 0x88b3d008U, 0xc7ed782fU, 0x2b3fcc64U, 0x2d2a6e69U, 0x28db6b01U, 0x981bee29U, 0xacf22bddU, 0xc1498eb8U, 0x6524fbe3U, 0x84df764eU, 0xba177715U, 0xfffcf8f3U, 0xd7c68cb1U, 0x80000000U, 0x40000000U, 0x20000000U, 0xd0000000U, 0x8000000U, 0x7c000000U, 0x72000000U, 0xc3000000U, 0x73800000U, 0x50400000U, 0x2de00000U, 0x40300000U, 0xfe580000U, 0x5e2c0000U, 0x75960000U, 0xcf870000U, 0x42498000U, 0x1ee54000U, 0xebbde000U, 0xda139000U, 0x7dc0c800U, 0x84a31c00U, 0x8154ea00U, 0x3fa46500U, 0x16dda280U, 0x49e23940U, 0x2634a8a0U, 0xc355cc90U, 0x44a9c228U, 0xe154e9acU, 0xcfa980faU, 0xced540ffU, 0x3de5e021U, 0x283f9043U, 0x7256c856U, 0xf4241c6cU, 0xc29d6aa1U, 0xb20125ddU, 0xa3004278U, 0x8381a981U, 0x884c60baU, 0x59ead001U, 0x4e33287fU, 0x4f5b8c36U, 0xeeaba299U, 0x5655392eU, 0xb225283fU, 0x2f9c8c76U, 0xa0822202U, 0x4bc0796cU, 0xf1a0c816U, 0xc7d31c2cU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0x58000000U, 0x74000000U, 0x5e000000U, 0xa1000000U, 0x23800000U, 0x68c00000U, 0xd7200000U, 0x1b500000U, 0xdbf80000U, 0xd6640000U, 0xabb20000U, 0x2d050000U, 0x198a8000U, 0x1fccc000U, 0x49a1a000U, 0x221a7000U, 0xef176800U, 0xc6955400U, 0x815bee00U, 0xbcf7ff00U, 0xc0e60680U, 0x8efe6bc0U, 0x6be44860U, 0x8277e4f0U, 0xe9a726b8U, 0x3219db44U, 0x67120086U, 0xda950015U, 0xf352809dU, 0x37f8c0f9U, 0x1c6ba0acU, 0x64bb7007U, 0xf78fe852U, 0x26cc946cU, 0xfe28ce53U, 0x24d54f93U, 0xc13acee5U, 0x8a404fe9U, 0x6c684eebU, 0x1cb88f1bU, 0x5383ee35U, 0x10c3ff4dU, 0x732c0611U, 0x2d5f6b40U, 0x56fcc84dU, 0xdfee245dU, 0x3c740656U, 0x78ab6b5cU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x30000000U, 0x58000000U, 0x24000000U, 0x56000000U, 0x41000000U, 0x4e800000U, 0x400000U, 0xe7600000U, 0x33700000U, 0xc980000U, 0xdeac0000U, 0xabda0000U, 0x2e450000U, 0x12628000U, 0xa3f9c000U, 0x1dc2000U, 0x5d48f000U, 0xabe8b800U, 0x9c3c8c00U, 0xf074e200U, 0xad126900U, 0x2566da80U, 0x3c7b2540U, 0xc7141860U, 0xf664bc70U, 0x55f8fab8U, 0x90dad514U, 0x7bc4208eU, 0xd7a4f025U, 0x952b8f8U, 0xd4098c71U, 0xae0e62f1U, 0xb507a917U, 0x7080fa3dU, 0x3d46d5ecU, 0xdbe62089U, 0x243df080U, 0xe47238e6U, 0xa3194caaU, 0x406ac211U, 0x24f39945U, 0x8656e299U, 0x5f8b69eeU, 0x66c65a80U, 0x7b2be5d1U, 0x9610b807U, 0x70e08c75U, 0xf9b6e200U, 0x6dbb69f3U, 0x80000000U, 0x40000000U, 0x20000000U, 0x50000000U, 0xa8000000U, 0x3c000000U, 0x3e000000U, 0x65000000U, 0x92800000U, 0x4ac00000U, 0xfe00000U, 0x52900000U, 0xd9f80000U, 0xd8ac0000U, 0x82360000U, 0x77cf0000U, 0x196b8000U, 0x925b4000U, 0xe11d2000U, 0xebb33000U, 0xda82b800U, 0x46cd6400U, 0xe9ef8200U, 0xf390bf00U, 0xe17eba80U, 0xf56a9b40U, 0x445a18a0U, 0x98161410U, 0x17359a88U, 0x5d46ab6cU, 0xe7ab2016U, 0xcfbc3019U, 0x4089388cU, 0xf9c6247fU, 0xe46aa235U, 0xe4df8f24U, 0x51d20268U, 0x2b54ffafU, 0x7d901a69U, 0x1c7eebf5U, 0x83eb809cU, 0xf49b409bU, 0x58fd2097U, 0xb02330a8U, 0x7fab8bdU, 0x8da164c9U, 0xc8b98289U, 0xf90fbf5aU, 0xbc8d3a2dU, 0xa7cddb6dU, 0xf169388bU, 0x8e5624c6U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x10000000U, 0xd8000000U, 0x4000000U, 0x16000000U, 0xe5000000U, 0x78800000U, 0xb0400000U, 0x5600000U, 0x5c300000U, 0x3fd80000U, 0x4aac0000U, 0xea9a0000U, 0x77470000U, 0xe6e88000U, 0x5df3c000U, 0x28782000U, 0x8cbeb000U, 0x39b9800U, 0x65ceec00U, 0x51a38200U, 0x1b10dd00U, 0x85889a80U, 0x6cc1f140U, 0x53293860U, 0x74589c50U, 0xc76aba38U, 0xd7384114U, 0x565a204eU, 0x5c65b0a1U, 0x66b1188eU, 0x44962c45U, 0xc64922a5U, 0xb06aade8U, 0x1cbba2acU, 0x9b9e6db3U, 0x81cb02cdU, 0x57a31dddU, 0x2610bab1U, 0xf90f4122U, 0xca8aa05fU, 0xb34a702aU, 0x50eb3897U, 0x48f39cdfU, 0x98f83a07U, 0xe0fc812eU, 0x14f28028U, 0xcaf4c0f8U, 0xf3f0a09dU, 0x997d70bcU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x10000000U, 0x28000000U, 0x3c000000U, 0x92000000U, 0xb7000000U, 0x60800000U, 0xdc00000U, 0xa8200000U, 0x3100000U, 0x2db80000U, 0xea640000U, 0xe2720000U, 0xfd470000U, 0x4def8000U, 0x773f4000U, 0xaca3e000U, 0x58dcd000U, 0x5498b800U, 0x80faf400U, 0xaf89ae00U, 0x594c7b00U, 0xfbe69680U, 0xb63dcfc0U, 0xed26d860U, 0x49e64d0U, 0x88fd76c8U, 0x63851f2cU, 0xf34c603aU, 0x58e3904bU, 0x78bb5812U, 0xc5e624aaU, 0x7b3116e0U, 0xe6a68f32U, 0xebd73897U, 0xb215b49eU, 0x94324e4fU, 0x4224ab0aU, 0x80142eafU, 0x13343b75U, 0xfaaaf63eU, 0x89de5fa2U, 0x3d1d8032U, 0xe0b840c4U, 0xe1ec6044U, 0xd339036U, 0xc7a3580fU, 0xba5224dbU, 0xc65b16faU, 0x74558f76U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x30000000U, 0x98000000U, 0xc000000U, 0x6e000000U, 0x15000000U, 0x54800000U, 0xa5c00000U, 0xd1600000U, 0x8900000U, 0x78780000U, 0x71a40000U, 0x857a0000U, 0x112d0000U, 0x12b68000U, 0x13474000U, 0xcfa92000U, 0xf8783000U, 0xb1afd800U, 0xe57c7400U, 0x2128da00U, 0x8ab13700U, 0x1f4b8280U, 0xa1a703c0U, 0xed7cf8e0U, 0xe52944f0U, 0x40b182f8U, 0xf04a033cU, 0x822a7876U, 0x673e04d9U, 0xd000a25aU, 0x68063380U, 0xf407a09dU, 0x520b7061U, 0xe304f8a7U, 0x4d8d445cU, 0x9f4b8231U, 0x61a703c9U, 0x8d7cf8a8U, 0xd52944dfU, 0xd8b18291U, 0xfc4a030fU, 0xec2a7832U, 0x723e04c8U, 0x8480a2f4U, 0xcdc63328U, 0x2567a038U, 0x5a9b70abU, 0x9b7cf88eU, 0x3c29449fU, 0x80000000U, 0x40000000U, 0x20000000U, 0xd0000000U, 0x38000000U, 0x54000000U, 0x8a000000U, 0x43000000U, 0xba800000U, 0xf1400000U, 0x9f200000U, 0x8e700000U, 0xb8d80000U, 0x56c0000U, 0xa7d60000U, 0xe9e70000U, 0x39a8000U, 0xb94cc000U, 0x6324e000U, 0x487d1000U, 0xf5dfd800U, 0x4ee39c00U, 0xfb119600U, 0xb7051d00U, 0xa082ce80U, 0xaa4d4140U, 0xa1ad38a0U, 0xcd398c90U, 0x30f4ce18U, 0xbb9a4184U, 0xad4fb832U, 0xc9294c57U, 0xdb7e2e10U, 0x775c5162U, 0xeba4e09dU, 0xee3d106bU, 0x7a7fd88dU, 0xa2d39c18U, 0x5e69969dU, 0x99591d49U, 0xaaacce31U, 0x8bb641ddU, 0x7b9b8c2U, 0x69be4c95U, 0x68bcaeb6U, 0x2d3c91e5U, 0x80f60087U, 0x73970012U, 0x1142808fU, 0x2f20c0deU, 0x4672e0eaU, 0x4da10bbU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0xa8000000U, 0x5c000000U, 0x22000000U, 0x2b000000U, 0xaa800000U, 0xd3400000U, 0x3a200000U, 0xd1b00000U, 0xf0d80000U, 0x774c0000U, 0x3c2a0000U, 0xbcb90000U, 0xd7558000U, 0xf3834000U, 0x2acde000U, 0x27e99000U, 0x9ed59800U, 0xe640dc00U, 0xa9ad7600U, 0xcb702900U, 0x9f350e80U, 0xc5996540U, 0x506de060U, 0x62199030U, 0x94ad9848U, 0x94fcdc2cU, 0x7fff768aU, 0x75752977U, 0x36328e08U, 0xd41f25b8U, 0xf1a780f0U, 0x7f764032U, 0x1326082U, 0xbc93d08aU, 0x79edf846U, 0x47da0cbcU, 0x5fcd0e63U, 0x546565b7U, 0xf41fe0edU, 0x21ac9096U, 0x4772189eU, 0x85369c17U, 0x6a9f1653U, 0x2ce3f9baU, 0xe458f67fU, 0xd03692aU, 0x1780eef8U, 0xccccf590U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x50000000U, 0xc8000000U, 0x14000000U, 0xa2000000U, 0x65000000U, 0x74800000U, 0x22c00000U, 0x2ce00000U, 0x80900000U, 0x96b80000U, 0x26c40000U, 0x26e60000U, 0x19f0000U, 0xd8318000U, 0xbd09c000U, 0xc88d6000U, 0x64c37000U, 0x73e89800U, 0x4d18a400U, 0x76f38200U, 0xefe2b700U, 0x9b167a80U, 0x41f963c0U, 0x666d6020U, 0x11537090U, 0xf9d09868U, 0xd1ca444U, 0x16f5826aU, 0x1fedb771U, 0x31ffa56U, 0x9df4a387U, 0xd0660078U, 0xd65f0032U, 0xe85180d2U, 0x5b59c0e2U, 0x18d560daU, 0xb3977056U, 0x15369828U, 0x2d83a4fbU, 0xd0440248U, 0xf124777bU, 0x31f29a81U, 0x3e67d34fU, 0x6d569895U, 0x1fd3a415U, 0x21c027bU, 0x13707756U, 0xebac9a07U, 0x683cd338U, 0x80000000U, 0x40000000U, 0x60000000U, 0xb0000000U, 0x78000000U, 0x9c000000U, 0x6e000000U, 0x3000000U, 0xeb800000U, 0xbf400000U, 0x8ee00000U, 0xf6500000U, 0x4bf80000U, 0xb54c0000U, 0x3fe20000U, 0x10dd0000U, 0xac348000U, 0x17624000U, 0x641d2000U, 0x4d93d000U, 0xa7de0800U, 0x3db10c00U, 0x412d3a00U, 0x407fdb00U, 0xfa0e1280U, 0xa90d0740U, 0xca8520e0U, 0xf1cfd0f0U, 0x3d240818U, 0xde700c2cU, 0xe103ba16U, 0x6e8c9b9fU, 0x63c5b205U, 0xe02197fcU, 0x4ef28885U, 0x29cf4cb9U, 0x312a1addU, 0x187d0b6fU, 0xb6069ae2U, 0xf034b7aU, 0x2d81baf6U, 0xe8419b4bU, 0xef693235U, 0xb81fd77fU, 0x4395a8f0U, 0x14dd9c5cU, 0xae3a920fU, 0x626f4748U, 0xa09800dbU, 0xf5c0078U, 0x97a00d8U, 0xc081004dU, 0x80000000U, 0x40000000U, 0xe0000000U, 0xf0000000U, 0x48000000U, 0xe4000000U, 0xa2000000U, 0x4f000000U, 0x6b800000U, 0x6c400000U, 0x29a00000U, 0xf0f00000U, 0x77180000U, 0x514c0000U, 0x152a0000U, 0x4b310000U, 0xccf38000U, 0xc916c000U, 0xf0466000U, 0x87abd000U, 0xe9f7c800U, 0x499dbc00U, 0xb588be00U, 0x7d470500U, 0x13211680U, 0x463d6940U, 0x18746060U, 0x86d6d0b0U, 0x51ae48a8U, 0xfcfa7c14U, 0x211d5eeaU, 0x44a15abU, 0x9da8be49U, 0xaf70563U, 0x64191622U, 0x34c1692cU, 0x70666076U, 0xe41bd0f5U, 0x74cfc868U, 0x9061bc41U, 0x141abe58U, 0x3cca0545U, 0x7460965cU, 0xb616a9ddU, 0x73cb804cU, 0x1feac0b3U, 0xda5460bfU, 0x5a66d0caU, 0xef1648e2U, 0xad467c43U, 0xb2f5eebU, 0xfa3715e6U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0x98000000U, 0xb4000000U, 0xa6000000U, 0x1f000000U, 0x68800000U, 0x5ac00000U, 0x57a00000U, 0x51700000U, 0xe2180000U, 0xfcc0000U, 0xd22e0000U, 0x2a3f0000U, 0x50f48000U, 0x175ec000U, 0x7e272000U, 0x78309000U, 0x49f9f800U, 0x30d8e400U, 0xd46e7600U, 0xc15bbd00U, 0xe928ae80U, 0x9cbfc940U, 0x51312020U, 0x46739010U, 0x469b7838U, 0xb70524e4U, 0xf48bd63eU, 0x20c6edabU, 0x92acf64eU, 0xacf67d05U, 0xdd550e1fU, 0xd32e991bU, 0xf9bb780dU, 0xfcb524faU, 0xe133d6aeU, 0x2e7aeddeU, 0x3a9af654U, 0x3d057d8cU, 0xf98f8e97U, 0xf14f596bU, 0xbfe8d852U, 0xc91b74e8U, 0x814d0e64U, 0x37e2997eU, 0x4515788bU, 0xc34a24deU, 0x16e7567dU, 0x86942ddbU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x50000000U, 0x8000000U, 0x34000000U, 0x6e000000U, 0xa3000000U, 0xd9800000U, 0xc9c00000U, 0x23e00000U, 0x7ef00000U, 0x6ed80000U, 0x8ec40000U, 0x5c620000U, 0xc03b0000U, 0xaabd8000U, 0x92f7c000U, 0xfcdfa000U, 0x97c3d000U, 0x18e02800U, 0x7b79c400U, 0xad168200U, 0x682ec100U, 0x6c110a80U, 0xd0a0d5c0U, 0x6d5da060U, 0x4a08d090U, 0xe505a8e8U, 0xfe8a0464U, 0x264b2266U, 0x75261197U, 0xde94a237U, 0x14ead1aaU, 0xb976829aU, 0xbc1ec127U, 0x18a90a25U, 0xb954d554U, 0x7407a034U, 0x4e07d049U, 0x130228a9U, 0x8182c45cU, 0xf5cb02caU, 0x79e90125U, 0xb3f6aa9eU, 0x145705b6U, 0x9e87881dU, 0xb64e147aU, 0x9d2caa92U, 0xba98057eU, 0x72e00883U, 0x2e76d486U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x70000000U, 0x18000000U, 0xc000000U, 0x22000000U, 0xc5000000U, 0x13800000U, 0x2a400000U, 0x3d200000U, 0x6e900000U, 0xff80000U, 0x17440000U, 0x92aa0000U, 0x1ed10000U, 0x8bde8000U, 0x50554000U, 0x7e10e000U, 0x53b7000U, 0x98a9e800U, 0x6fdfdc00U, 0xa65b1600U, 0xf5190b00U, 0x81ba1e80U, 0x7c69a7c0U, 0x673ae0e0U, 0xfdaa70b0U, 0x6c576878U, 0xe41a9c7cU, 0xdc33f63aU, 0xc1267bc9U, 0x9499f6b1U, 0xa6f77b2fU, 0x56c776ceU, 0x65e23bf4U, 0x3c7796caU, 0xed094bc5U, 0xa7867e47U, 0x14429770U, 0xb22f68d0U, 0xac1e9c1dU, 0x1839f681U, 0xe7277ba8U, 0x179f767dU, 0x46763b30U, 0x8405964fU, 0x860c4ba2U, 0x930afee7U, 0x8882d728U, 0xc6cb0869U, 0xcde1accaU, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0xe8000000U, 0xac000000U, 0xae000000U, 0xa1000000U, 0x90800000U, 0x54c00000U, 0x9a200000U, 0x93100000U, 0xcf80000U, 0xd4c0000U, 0xb2620000U, 0x93f30000U, 0xf4c38000U, 0xea204000U, 0x4b162000U, 0x18fdf000U, 0xe7419800U, 0x11648400U, 0xc750e00U, 0x91890300U, 0xb440b680U, 0x16e37740U, 0x1d37a0e0U, 0x75eeb010U, 0xa2b43888U, 0x20a934fcU, 0x44dab646U, 0x395c770dU, 0x431620beU, 0xa4fdf0b5U, 0xc141986aU, 0x4c648497U, 0xdaf50e7eU, 0xc8490332U, 0x10e0b690U, 0x7033777fU, 0x1b6fa036U, 0xbf72b03dU, 0x860e38adU, 0x2d06349dU, 0xe8336e6U, 0x4dc33709U, 0x4ea180e7U, 0xc5d340a6U, 0x99d5a026U, 0xafddb0faU, 0x7ad7b89cU, 0x50597449U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0xa8000000U, 0x24000000U, 0x9a000000U, 0x1000000U, 0xe2800000U, 0x29c00000U, 0xcd600000U, 0x8b300000U, 0x90980000U, 0xf440000U, 0x2eaa0000U, 0x8f5f0000U, 0x4d2b8000U, 0x8414c000U, 0xc985e000U, 0x524cb000U, 0x7a22b800U, 0xe997f400U, 0xc1c56a00U, 0x496a3500U, 0xe1303280U, 0xa99a71c0U, 0x61ce60e0U, 0xb9687050U, 0xd93f58c8U, 0x259f44b4U, 0xdfcdd232U, 0x2262c125U, 0x3abed8f8U, 0xeed484e8U, 0x3b63b24fU, 0x643ab132U, 0x21198075U, 0x710fc060U, 0x1a846044U, 0xc5c77011U, 0xe36cd829U, 0xb83f8406U, 0x571a32d3U, 0x5e05715cU, 0xcb05e041U, 0x2b8cb05dU, 0x7f42b838U, 0xd6a7f434U, 0x635d6a55U, 0x632e354fU, 0xb71a327dU, 0xe05710cU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x10000000U, 0x78000000U, 0x1c000000U, 0x86000000U, 0x21000000U, 0x60800000U, 0x3c400000U, 0x80e00000U, 0x92300000U, 0xb6180000U, 0xc48c0000U, 0x64a0000U, 0xd7ef0000U, 0xbbb68000U, 0x8ede4000U, 0xe225a000U, 0xb3907000U, 0xb2431800U, 0x95e74c00U, 0xf0b38a00U, 0x21518d00U, 0xfbe3b280U, 0xf5b8f140U, 0x3bd68060U, 0x70ae4050U, 0x4cdda098U, 0xe92c700cU, 0xfc1118feU, 0xbb844c3dU, 0xabcf0ae6U, 0x6520cd1dU, 0x42109260U, 0x6686c1eeU, 0x5d483856U, 0x657c06U, 0xbe7f3228U, 0x4ef9b11fU, 0x4abda0c3U, 0x365c7024U, 0x3269185fU, 0xdd784c30U, 0x657d0ac8U, 0xd973cd94U, 0xaf741272U, 0xe67b8183U, 0xe2f118bbU, 0x44b44cabU, 0x63570a65U, 0xb0eccd42U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0x8000000U, 0xfc000000U, 0x5a000000U, 0x41000000U, 0x84800000U, 0xa5400000U, 0x6a200000U, 0x7bb00000U, 0xc8580000U, 0x68840000U, 0x874e0000U, 0xff290000U, 0xe93b8000U, 0x7e174000U, 0x3b2e6000U, 0x873fb000U, 0xb91d5800U, 0x14ad9c00U, 0xeffdb600U, 0xefa7900U, 0xfa750e80U, 0x773f15c0U, 0x511b80a0U, 0x78a74070U, 0xdf66028U, 0xbbfbb04cU, 0xd8f35852U, 0xc9749cbdU, 0xfebe36deU, 0x22d939e4U, 0xacd6e6eU, 0xc2eda51eU, 0xec535802U, 0x96849c63U, 0xf8463667U, 0x24ad39dbU, 0x27fb6ebcU, 0xd2f0a5fcU, 0x107ed8acU, 0x3e3edc6dU, 0x299dd644U, 0x87ecc901U, 0x26d3d626U, 0x44c5c974U, 0xb5e85624U, 0xcbd2897aU, 0x2463683U, 0x15ad39dcU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0x98000000U, 0xc4000000U, 0x6000000U, 0xb000000U, 0x4f800000U, 0x35400000U, 0x52600000U, 0xb1700000U, 0x3dd80000U, 0xdd840000U, 0x604e0000U, 0xf2ef0000U, 0x1db48000U, 0xc9fdc000U, 0xb5182000U, 0xdfa6d000U, 0x4bd74800U, 0x5e892c00U, 0x53c2b200U, 0xd5a99100U, 0xdad95a80U, 0xf80badc0U, 0xf40c80a0U, 0x6e09c010U, 0x870e20b8U, 0x158dd014U, 0xfc4dc89eU, 0x10ebeccfU, 0xc0b61249U, 0x1576813eU, 0xbd8329dU, 0xbe8b5144U, 0xa3cdfacfU, 0x9da4bd7cU, 0x86d5e865U, 0x3a0d3cfbU, 0xf9015ac3U, 0x2a8fad24U, 0xfdc280f9U, 0x72a6c02cU, 0x1f5aa0c5U, 0x9c4010deU, 0x20ede8a0U, 0xa8b93c16U, 0x99775a80U, 0x51d4adb8U, 0x778000a1U, 0xe1400085U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xb0000000U, 0x48000000U, 0x74000000U, 0x36000000U, 0xe3000000U, 0x7e800000U, 0x70400000U, 0xaf600000U, 0xd6300000U, 0xfd980000U, 0x95840000U, 0x1ac60000U, 0xf9210000U, 0x625f8000U, 0x692bc000U, 0x5a582000U, 0xf52f5000U, 0xa85ed800U, 0x68266c00U, 0x41ddb200U, 0x50e27500U, 0x7dfcca80U, 0x573489c0U, 0x26198020U, 0x904ac070U, 0x7f67a0e8U, 0x8e3490c4U, 0x719ef87eU, 0x9f8d3c97U, 0xbbc56a48U, 0x52a51993U, 0x8f9ef851U, 0xc88d3c66U, 0x53456af2U, 0x71e519f3U, 0x167ef82fU, 0x1afd3cd8U, 0x37bd6aeeU, 0xd15119c3U, 0x8fa0f88eU, 0x6183c58U, 0xe044eacbU, 0x976bd918U, 0x4a3f58a2U, 0xf98ac69U, 0x884121fU, 0xf343e57bU, 0xc1e3b272U, 0x5e7775ffU, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0x38000000U, 0xc000000U, 0x9a000000U, 0x8f000000U, 0x8a800000U, 0xc2c00000U, 0xbb600000U, 0x1db00000U, 0xc9980000U, 0x530c0000U, 0x8820000U, 0x31c70000U, 0x83e28000U, 0x64734000U, 0x6e716000U, 0x997d5000U, 0x7ffa5800U, 0x373f8400U, 0x3b5f1a00U, 0xa0622d00U, 0x3134a280U, 0x5654b940U, 0xc9e200e0U, 0xf3770050U, 0x98fa8058U, 0xe9bf401cU, 0x7f9360a2U, 0x360a5083U, 0x2500d810U, 0x4d80c44dU, 0x6c4c7a31U, 0xd7a87ddfU, 0xbfd47af2U, 0x4ba47d0eU, 0x5dd67a21U, 0xa8a37d32U, 0x5d54fa53U, 0xdd603d09U, 0x60bd9aafU, 0x98116d2eU, 0x9d45c2d9U, 0x5c29e9bfU, 0x9e985837U, 0x8588849bU, 0x8459a30U, 0x19ad6de9U, 0xb6dfc22aU, 0xec22e9dbU, 0x80000000U, 0x40000000U, 0x20000000U, 0x50000000U, 0x58000000U, 0x5c000000U, 0xae000000U, 0x83000000U, 0xc4800000U, 0xd4400000U, 0x18200000U, 0xc7500000U, 0xd8b80000U, 0xdd0c0000U, 0xf860000U, 0x34c70000U, 0x6e608000U, 0xaa704000U, 0x4672000U, 0xbb76d000U, 0x9dee7800U, 0x20b00c00U, 0x91034600U, 0xd9893700U, 0xbbcc9e80U, 0x5ce8ab40U, 0xa13e00a0U, 0x76cb0010U, 0x2b668078U, 0x99f7400cU, 0xeea7a0f6U, 0x5e1690dfU, 0xf711586aU, 0x29adc57U, 0x1f533edcU, 0xc4b23b13U, 0x53095840U, 0xdc86dc5aU, 0xa84d3ef7U, 0xe6293bb9U, 0x1c57d8b9U, 0x403d9c82U, 0xa74c9ee4U, 0x94a8abc2U, 0x371e0085U, 0x629b0053U, 0x6f5e809aU, 0xccbb40edU, 0x5701a06eU, 0x2e8190d0U, 0x8549d8a3U, 0xa1a69c5aU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xb0000000U, 0x18000000U, 0xc000000U, 0xb2000000U, 0x9000000U, 0xe0800000U, 0x3cc00000U, 0xbba00000U, 0x6cb00000U, 0x86580000U, 0x5b040000U, 0x39860000U, 0xd4410000U, 0x236a8000U, 0x71114000U, 0x5de3e000U, 0x86d7b000U, 0xb7cc9800U, 0x8a2ac400U, 0x1cf3f600U, 0x33eb100U, 0x9d100e80U, 0x3fe385c0U, 0x87de0020U, 0xf3450070U, 0x10ec80b8U, 0x105040bcU, 0x340960aaU, 0xce06f005U, 0x30f7852U, 0x558d7435U, 0x76476e5bU, 0x82607550U, 0x859df8bdU, 0xdf2834f7U, 0x867a8e1fU, 0x32f2c53fU, 0xd03de082U, 0xc092b069U, 0xeda0186cU, 0xa3ba844eU, 0xc1da9612U, 0x9448413cU, 0x43677622U, 0x611af12cU, 0xf5e76ec7U, 0x92d0752bU, 0x9c5f8a0U, 0x312c3408U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x90000000U, 0xe8000000U, 0x74000000U, 0xe2000000U, 0xf000000U, 0x20800000U, 0x98c00000U, 0x10e00000U, 0xe6700000U, 0xb3d80000U, 0xda040000U, 0x730e0000U, 0x68b0000U, 0xdc78000U, 0xa369c000U, 0xc8396000U, 0xd6f6d000U, 0x316f800U, 0x9eed8400U, 0xe77f8200U, 0x5252e900U, 0x83419a80U, 0xaaaf7dc0U, 0xd15800a0U, 0x1dc40050U, 0x8b6e00c8U, 0x9c3b00e4U, 0xa4ff800aU, 0xe41dc07bU, 0xca6f60c2U, 0x9db9d097U, 0x4dbf7830U, 0x45bf447eU, 0x81b962a3U, 0x1bb9f93cU, 0x88b80240U, 0x3e3b291cU, 0x4bf8fadeU, 0x7499adf5U, 0x2aaef88dU, 0x11598451U, 0x3dc982e1U, 0x1b6de9a3U, 0x74301a4eU, 0xd0f9bdefU, 0x610e016U, 0xc56410d9U, 0xbd301819U, 0xd57694f7U, 0x80000000U, 0x40000000U, 0x20000000U, 0x90000000U, 0xa8000000U, 0x4c000000U, 0x4e000000U, 0x97000000U, 0xc5800000U, 0x7d400000U, 0xa7600000U, 0x3bf00000U, 0x55280000U, 0xf8040000U, 0x84020000U, 0xb2010000U, 0xe1048000U, 0xb6854000U, 0xbac26000U, 0x3227000U, 0xce14b800U, 0xd61e2c00U, 0x770fea00U, 0xe0933b00U, 0x58dadf80U, 0xfe2b2940U, 0x2b800020U, 0x3a400010U, 0xeae00008U, 0x9ab00024U, 0x1448002aU, 0x18f40013U, 0x5aaa0013U, 0xa0450025U, 0x7e68031U, 0x4234401fU, 0xa98ee029U, 0x7653300eU, 0xa5fcd815U, 0x9f395c3eU, 0xdc1dd221U, 0x3209572cU, 0x7413d5b8U, 0xab1f226dU, 0x78c078eU, 0x11577550U, 0x787b521bU, 0x967d1701U, 0xd17d35bfU, 0x9cfc124fU, 0x3db8df8fU, 0x7cda2959U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x10000000U, 0x38000000U, 0x8c000000U, 0x5a000000U, 0x21000000U, 0x3b800000U, 0x38400000U, 0xcbe00000U, 0x69f00000U, 0x2d980000U, 0x2c040000U, 0x6a060000U, 0xe9070000U, 0x9f808000U, 0xd641c000U, 0x3ce46000U, 0x2972d000U, 0xf590800U, 0xe425dc00U, 0xf057c200U, 0x66895f00U, 0xf7efcf80U, 0xbddaacc0U, 0x93e00020U, 0x35f00030U, 0xaf980038U, 0x91040004U, 0x3386000eU, 0x7c470023U, 0x35e08016U, 0xa6f1c008U, 0xe11c600eU, 0x54c6d00eU, 0x83270832U, 0x48d6dc1aU, 0x2849420bU, 0x75cb9f0bU, 0x3e8d2f9aU, 0xabeebcfaU, 0x3fdde807U, 0x2ee6cc05U, 0x6c72aa37U, 0x3ada530eU, 0x3b67058dU, 0x43312fdaU, 0xa1b88d8aU, 0x485233e1U, 0x2a8bafabU, 0x4de87cd5U, 0x80000000U, 0x40000000U, 0x20000000U, 0x30000000U, 0xc8000000U, 0xdc000000U, 0x4a000000U, 0x4f000000U, 0x53800000U, 0xe2c00000U, 0x86600000U, 0x10f00000U, 0x7ed80000U, 0xb4040000U, 0xe6020000U, 0xed010000U, 0xf0818000U, 0x33464000U, 0xf7a6e000U, 0x8f125000U, 0xc3ea7800U, 0x1f3e9c00U, 0xa0311600U, 0xf3bf3300U, 0xb9740780U, 0x5b1e36c0U, 0x9de00020U, 0x6e300010U, 0x92b80008U, 0xdbf4000cU, 0x35a0032U, 0x67c50037U, 0xdae38012U, 0x81b74013U, 0x2a7f6014U, 0xea901038U, 0x542e9821U, 0x6dddcc04U, 0xed82ee1fU, 0x6bc3ef2dU, 0x8e1f1b9U, 0xcab255fbU, 0x17ffff9cU, 0x1956eadcU, 0x58cff615U, 0xc969633fU, 0xeb7c7f8aU, 0xf811aafcU, 0xe4689628U, 0x7bfd7308U, 0xdb50e7a0U, 0xebcd66f1U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0x28000000U, 0x34000000U, 0x6a000000U, 0xa5000000U, 0xda800000U, 0x10c00000U, 0xd5200000U, 0xc6900000U, 0xfcf80000U, 0x2040000U, 0xf1060000U, 0xc0850000U, 0x4dc68000U, 0x13a14000U, 0x8851a000U, 0xe6db5000U, 0xbb112800U, 0xc7b8d400U, 0x7618600U, 0xaf762900U, 0xe94a7480U, 0x3b6cc7c0U, 0x6780020U, 0x2c40030U, 0xac260028U, 0xe2150034U, 0xf33e800aU, 0x80a5400dU, 0xc9d7a01aU, 0x939e5029U, 0xf977a836U, 0x2499404U, 0xa6e82635U, 0x8d397931U, 0x5fa55cbfU, 0x3e5513c0U, 0xbdd9061cU, 0x7e966900U, 0x80fb54bbU, 0x2c03d7f0U, 0xc6060808U, 0xa302c404U, 0xd9810e1cU, 0x1945ad2cU, 0xe462dabdU, 0x16f63ae2U, 0x800df2b5U, 0x270feee6U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0xd8000000U, 0xe4000000U, 0xbe000000U, 0x37000000U, 0xdd800000U, 0x3d400000U, 0xf3200000U, 0x6bd00000U, 0x3c480000U, 0xba040000U, 0x99060000U, 0x52830000U, 0xd4c68000U, 0xa866c000U, 0x4bf72000U, 0x341df000U, 0x8c0db800U, 0xda4ec00U, 0x9d14ea00U, 0x492a1900U, 0xad771e80U, 0x46de0240U, 0x97680020U, 0xf5d40030U, 0x7b4e0018U, 0xf870034U, 0x48408036U, 0x23a5c039U, 0xd211a02fU, 0xc0ab300dU, 0x26329837U, 0xbefd1c0fU, 0x7b3f523cU, 0x7dddf51aU, 0xd8ed748fU, 0x1d96db6eU, 0xe8ee3e86U, 0xd594f264U, 0xb4ed380dU, 0x5f912c2eU, 0xe5ed4a3cU, 0x51152900U, 0xbb2b86baU, 0xa8741e77U, 0xfe5fd21fU, 0xc2a83520U, 0x8b34d4b8U, 0x8a79eb70U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x90000000U, 0x28000000U, 0x84000000U, 0xda000000U, 0x23000000U, 0x31800000U, 0xcec00000U, 0x2aa00000U, 0x96100000U, 0x4b580000U, 0xae040000U, 0xa1060000U, 0xe810000U, 0x19448000U, 0xb1614000U, 0xf0342000U, 0xdb0ed000U, 0x13bd1800U, 0x4cf38c00U, 0x96a97600U, 0x4e28d500U, 0x7a6b7080U, 0xb8c3ac0U, 0x33f80020U, 0xcf140030U, 0x9de0008U, 0x59450024U, 0x5162800aU, 0x40304021U, 0x6308a036U, 0xbfbb9008U, 0x12f7380cU, 0x6fa85c33U, 0x5caeee0aU, 0x852f1925U, 0xefeca692U, 0x8f4e7febU, 0x1258c888U, 0xec8526f3U, 0x5642ce2eU, 0xfee5c938U, 0x57f7bebeU, 0xcb2cf3f3U, 0xfeed3e98U, 0x39c8b3caU, 0xa71b9eb7U, 0x3e623fcU, 0x5f7626baU, 0x376a3fe1U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0x38000000U, 0x84000000U, 0x56000000U, 0x27000000U, 0x2b800000U, 0xc7c00000U, 0x4f600000U, 0xd9900000U, 0xdfb80000U, 0x77040000U, 0xf3820000U, 0x73c50000U, 0xb1648000U, 0x4291c000U, 0x263c2000U, 0xc1c6b000U, 0xb0633800U, 0x46145c00U, 0xe67abe00U, 0xa367bb00U, 0xd390ec80U, 0x1ab94dc0U, 0x85820020U, 0x84c50010U, 0x2e48028U, 0x9151c024U, 0x75c200eU, 0xbb56b021U, 0x125b3815U, 0xd1d05c09U, 0x7118be0aU, 0xcef2bb31U, 0xf22c6c93U, 0xf6bc8df6U, 0x8f842017U, 0x41c2b00dU, 0xf0613814U, 0xe6115c38U, 0x767e3e22U, 0x9b667b31U, 0x5794cc9cU, 0x4cbbfdf9U, 0xa2833806U, 0xaf445c30U, 0xc522be02U, 0xde33bb3aU, 0xdecaec8dU, 0x64e84dfaU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0xf8000000U, 0x3c000000U, 0x5a000000U, 0x1b000000U, 0xa8800000U, 0x1c400000U, 0x7b600000U, 0x81100000U, 0x4f080000U, 0xab040000U, 0x80860000U, 0xf8410000U, 0xd608000U, 0x3817c000U, 0xc089e000U, 0x45c6d000U, 0xfca6d800U, 0xaab44400U, 0xdf386200U, 0xa7781b00U, 0x6a1fe880U, 0x720ba840U, 0xa2860020U, 0x1f410030U, 0xdfe08008U, 0x2f57c004U, 0xeb69e03eU, 0xe496d00fU, 0x92ced816U, 0x9ba04406U, 0xb836622aU, 0xe87d1b07U, 0x9c99689eU, 0x334d6860U, 0x20676033U, 0xc994101aU, 0x6349b828U, 0x3864543aU, 0xc597da3dU, 0xd14d4f01U, 0xe760b2a6U, 0xb152757U, 0x8c0952b5U, 0x2f83f75dU, 0x3ec78a81U, 0xa423b37dU, 0x7ef1e89fU, 0x705ea84dU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0x28000000U, 0x3c000000U, 0xd2000000U, 0x7b000000U, 0xef800000U, 0x48400000U, 0xc9200000U, 0x88100000U, 0x90a80000U, 0xa3040000U, 0x8b820000U, 0xbe450000U, 0xe4248000U, 0xda914000U, 0xa269e000U, 0x64e29000U, 0x1671d800U, 0xc81a7c00U, 0xdefac200U, 0x23890900U, 0x2c16a080U, 0x86a99540U, 0xbe020020U, 0x61050010U, 0x98848028U, 0xcdc14024U, 0xee61e00aU, 0x40b6900fU, 0xf9fbd834U, 0x6e0b7c1eU, 0x754423bU, 0x24094912U, 0xb851c0b2U, 0xad8b4562U, 0xf514b804U, 0xa2dac38U, 0x9dc0fa0aU, 0x2664e50bU, 0x4cb13ab3U, 0x93ffa079U, 0x10d82bcU, 0x6d60c57U, 0xc54f78b6U, 0xe5f7e954U, 0x825ac207U, 0xe4d90911U, 0xe81ea0b9U, 0xefd957cU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xb0000000U, 0xf8000000U, 0xbc000000U, 0xc2000000U, 0x57000000U, 0xc0800000U, 0x30c00000U, 0x82200000U, 0x28b00000U, 0x66380000U, 0xcb040000U, 0x72860000U, 0x3fc50000U, 0x4ea58000U, 0x2277c000U, 0xf1de000U, 0xe1321000U, 0x737cb800U, 0xb6670400U, 0x24520600U, 0xf9aed100U, 0xa20d2580U, 0xd7f8e1c0U, 0x88a60020U, 0x6b750030U, 0x4a9d8028U, 0xe73c02cU, 0x451be03eU, 0x5237102fU, 0x7df93830U, 0xeba0c415U, 0x8df7e630U, 0xe358c10cU, 0x21d79da0U, 0x76eae5caU, 0x84698639U, 0x7ba81102U, 0x950b45b4U, 0x77c31e3U, 0xf064d80dU, 0xad52d417U, 0x1c2b5e1bU, 0xfd4fc501U, 0x199d9b92U, 0xd0f034ceU, 0xf0daa3b9U, 0xf91f0d1U, 0xe10ec589U, 0x417bf1d7U, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0x88000000U, 0xc000000U, 0xca000000U, 0x37000000U, 0x2b800000U, 0x9d400000U, 0xd2e00000U, 0x56b00000U, 0x55c80000U, 0xeb040000U, 0x39820000U, 0x3e430000U, 0xc7638000U, 0xb2f44000U, 0x5da86000U, 0xf6725000U, 0x3f6bb800U, 0xe7d65c00U, 0xb23d6a00U, 0xb62dd700U, 0x4b375580U, 0xfd89be40U, 0x49620020U, 0x63f30010U, 0x9b2b8018U, 0x8fb0401cU, 0xdf4a6022U, 0x38c15003U, 0x9ea03832U, 0x42d61c0dU, 0x7abf0a0aU, 0x5ee88727U, 0xd956db4U, 0x2b5ca255U, 0xdde8a35U, 0x441fc72aU, 0x4c3e8d96U, 0xef2ab253U, 0x81b55233U, 0x4e4fcb3fU, 0x9e425fbdU, 0x9766396cU, 0x2af6ed87U, 0xa9a8e24dU, 0xb876ea12U, 0xce6d9739U, 0x315535b7U, 0x33fcee7dU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x50000000U, 0x38000000U, 0x54000000U, 0x12000000U, 0xed000000U, 0x9c800000U, 0x89400000U, 0x8a600000U, 0x7500000U, 0xc1380000U, 0x91040000U, 0x82860000U, 0xd2450000U, 0x81e28000U, 0x9391c000U, 0x189aa000U, 0x6a749000U, 0xbf096800U, 0x90ede400U, 0x507cca00U, 0xdf629300U, 0xfd31a80U, 0xfa78d9c0U, 0xa6660020U, 0x21550030U, 0xce3a8028U, 0x8885c014U, 0xfb44a00eU, 0x97659015U, 0xf3d5e804U, 0x247d243bU, 0x5d62ea27U, 0x7ad2c322U, 0x62fa52a2U, 0x5246dc1U, 0x12370210U, 0x47efe714U, 0x2df8b888U, 0x7ca6aee0U, 0x9bf5508eU, 0x6acf8ac1U, 0x33c9ba8aU, 0x8d4c49c5U, 0x210f680eU, 0xbe8e437U, 0xfbfe4a14U, 0x1ba3530cU, 0xee71ba9eU, 0x550849d6U, 0x80000000U, 0x40000000U, 0x60000000U, 0x90000000U, 0x48000000U, 0x14000000U, 0x6e000000U, 0xc9000000U, 0xf3800000U, 0xd4c00000U, 0x89e00000U, 0xbb100000U, 0x7eb80000U, 0xe5040000U, 0x11820000U, 0x4fc30000U, 0x59648000U, 0x73524000U, 0xd18a000U, 0x9eb77000U, 0x400c4800U, 0x15089c00U, 0xbc8c2600U, 0x3f4b0f00U, 0x542cf880U, 0x947b45c0U, 0xcde20020U, 0xbd130010U, 0x53bc8018U, 0xa0864024U, 0x5042a012U, 0x4fa07005U, 0x91b2c81bU, 0xbe8ddc32U, 0x744a063cU, 0xaca93f35U, 0xd83e90a2U, 0x9845e9eeU, 0x1ba64e3fU, 0x9fb1a329U, 0xe78ab69cU, 0xcfcae6f7U, 0x6c68b6a4U, 0x3fd9e6c9U, 0xea5436a0U, 0x969fa6e1U, 0xae769686U, 0x7fefd6c1U, 0x3b1c5ebcU, 0x4bb60ae2U, 0xa98c5887U, 0xf6c835eaU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0xf8000000U, 0x4c000000U, 0x76000000U, 0x7000000U, 0xb5800000U, 0x5f400000U, 0x91e00000U, 0x80900000U, 0xb2980000U, 0xb1040000U, 0x52820000U, 0xdac50000U, 0xa6a48000U, 0xa577c000U, 0x80a6000U, 0x729fb000U, 0x51063800U, 0x6282ac00U, 0xb2c37a00U, 0x12a7cf00U, 0x9f71a480U, 0x790c44c0U, 0xc01a0020U, 0xbbc10010U, 0xac268028U, 0xa3b2c024U, 0x20aee03eU, 0x9ce87013U, 0x9a8c581dU, 0x485d1c01U, 0xc7a5422dU, 0xaff56317U, 0xecadea4U, 0x5a3f8be0U, 0xbf71a48cU, 0xa90c44fcU, 0x981a001cU, 0x67c10002U, 0x2226803fU, 0xe8b2c01eU, 0xe32ee021U, 0xc4a8700eU, 0xbeec5824U, 0x978d1c0eU, 0xe4dd4225U, 0x9e616333U, 0xeed0deafU, 0x31fe8bd2U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xf0000000U, 0xb8000000U, 0xfc000000U, 0x26000000U, 0xe3000000U, 0xc1800000U, 0xcec00000U, 0x3ce00000U, 0x41900000U, 0xe9780000U, 0xb5040000U, 0x5a860000U, 0x93430000U, 0x24278000U, 0x2675c000U, 0x956fe000U, 0xb4bd3000U, 0x30651800U, 0x49d30c00U, 0x90daf600U, 0x8bb7a700U, 0xa80e2c80U, 0x5bee9bc0U, 0x15fe0020U, 0x5470030U, 0xdf218018U, 0x8bf6c03cU, 0x35a8602eU, 0x2f58f03fU, 0x6a72f809U, 0xab6a3c38U, 0x3bb9ee30U, 0x9fe7ab33U, 0x20135a8fU, 0xb7bcfcd0U, 0xc1e7cc9aU, 0x5f10abddU, 0xa03c982eU, 0x5421cc28U, 0x5e74963fU, 0x96c570aU, 0x62bb5482U, 0x6b6167eaU, 0x74500e15U, 0x78199b29U, 0x5451c283U, 0x281a30fdU, 0x7c52da91U, 0x9c1a3ce4U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x50000000U, 0xb8000000U, 0x64000000U, 0x7a000000U, 0xf5000000U, 0xb5800000U, 0xd7c00000U, 0x78600000U, 0xdff00000U, 0xca580000U, 0x6b040000U, 0xfa860000U, 0xb7410000U, 0x4a228000U, 0xc855c000U, 0x9cb2000U, 0x4afd000U, 0xaedda800U, 0x9346ac00U, 0xd0233e00U, 0x4d558300U, 0x544a9f80U, 0xf6f62c0U, 0xc8be0020U, 0xc3b50030U, 0x5afc8008U, 0x4410c014U, 0x16fa02eU, 0x1fbb1019U, 0x9734081eU, 0xaabcbc3dU, 0xc2b5b62dU, 0xd7cff35U, 0x52d4099eU, 0xe8c4df7U, 0x868fa192U, 0xea8be1eaU, 0x3c8e1f96U, 0x3f8ba2c9U, 0xd90fa014U, 0x504b100fU, 0xc56c083aU, 0xf5b8bc31U, 0xfa33b636U, 0x2b3dff35U, 0xd7768999U, 0xe4198decU, 0x42a481b4U, 0xe61431ebU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x10000000U, 0x28000000U, 0x6c000000U, 0xa2000000U, 0x55000000U, 0x89800000U, 0xc400000U, 0x1d600000U, 0xcdb00000U, 0x25580000U, 0x73040000U, 0xf2820000U, 0xc2c50000U, 0xf5a08000U, 0x11114000U, 0x37cb6000U, 0x71891000U, 0xb5eca800U, 0xe3df4c00U, 0xa7c3e200U, 0x4262b00U, 0xf951cd80U, 0xf4ae9ac0U, 0x633a0020U, 0x20310010U, 0xb71a8028U, 0x11604004U, 0x9fb1e00aU, 0xe859501bU, 0xae854828U, 0x18c21c15U, 0x44a4aa22U, 0x46913703U, 0xe48de787U, 0xdc6aedf3U, 0x5f9e87a9U, 0x82a7fdccU, 0x8d902fb4U, 0x120db1e4U, 0x70ab4dbfU, 0x4d3edacbU, 0x6733e027U, 0x539c5006U, 0xd0a5c805U, 0x40935c31U, 0xcf8fca2eU, 0x9ae8273fU, 0xcb594fbaU, 0xd401a1c4U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x70000000U, 0xb8000000U, 0xd4000000U, 0xaa000000U, 0x6b000000U, 0xff800000U, 0xc2c00000U, 0x9e200000U, 0x44500000U, 0xf5980000U, 0xaf840000U, 0x4ac20000U, 0x52250000U, 0x4a538000U, 0x8c9dc000U, 0xef02a000U, 0xdd875000U, 0x65c65800U, 0x6fa47c00U, 0xff93d600U, 0x2b3a5100U, 0x7c937280U, 0x88bef4c0U, 0xd8538020U, 0x739dc010U, 0x1a82a028U, 0x447501cU, 0xbc66582eU, 0x3d347c35U, 0x3e2bd62aU, 0xabee511aU, 0x3c4972bfU, 0xb7dff4f0U, 0x46e20007U, 0xe9750001U, 0x4a4b8015U, 0xfad9c037U, 0x7c60a03cU, 0xdd325021U, 0xee2dd838U, 0x63edbc39U, 0x504b7604U, 0xc9dc0107U, 0x87e4aabeU, 0x7df248caU, 0x77097622U, 0xa6390131U, 0xa6172aa5U, 0x6cff88eaU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x10000000U, 0x48000000U, 0x54000000U, 0x96000000U, 0xdb000000U, 0x1d800000U, 0x79400000U, 0xd9600000U, 0xf0500000U, 0x22a80000U, 0xb5840000U, 0xfd460000U, 0x67630000U, 0x6f508000U, 0xe12a4000U, 0x43c6a000U, 0xafa2b000U, 0x3575d800U, 0x89186c00U, 0xddbd8a00U, 0x454e6b00U, 0x8d123280U, 0x85ca4d40U, 0xbad08020U, 0xc6a4030U, 0x6ca6a018U, 0x94f2b004U, 0x425dd812U, 0x11dc6c15U, 0x6f9b8a25U, 0x97d6b36U, 0xdd6ab287U, 0xa8240d5eU, 0xdd302016U, 0x34fbf00cU, 0x142bf810U, 0x49449c29U, 0x2160f22dU, 0x9c53b70cU, 0xb8ace0beU, 0xe4850a4eU, 0xf9c118b7U, 0x4ea29645U, 0x9f16a83U, 0xacdb616aU, 0x311b2a15U, 0x11bcdb1dU, 0xaf4feab3U, 0x8416215fU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0x68000000U, 0xa4000000U, 0x26000000U, 0x8f000000U, 0x92800000U, 0x61c00000U, 0xfce00000U, 0x6ff00000U, 0x89780000U, 0xa6840000U, 0xefc60000U, 0x77e50000U, 0xcb708000U, 0xfbb4000U, 0x6ce12000U, 0xc7f73000U, 0x8d797800U, 0x90801400U, 0x8c64e00U, 0x4167c700U, 0x8cb2cf80U, 0x7c5b73c0U, 0x91908020U, 0x2f4b4030U, 0xd7192028U, 0x10b33004U, 0xf65f781aU, 0x2c951429U, 0x6ccece09U, 0x67588723U, 0x9d15efa4U, 0xad8943d8U, 0x2b79781fU, 0xdf80142bU, 0x3a464e0aU, 0x30a7c72dU, 0x1852cfa1U, 0xb7ab73f4U, 0x3ee8801bU, 0x6cf4010U, 0xaa5f2017U, 0x696302dU, 0xc1cff806U, 0x4cde5416U, 0x8957ee29U, 0x62bb71aU, 0xffaa97bcU, 0x4aec57daU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xf0000000U, 0xa8000000U, 0x34000000U, 0x2a000000U, 0xc3000000U, 0x6b800000U, 0x67400000U, 0x41600000U, 0x83300000U, 0x49280000U, 0xf840000U, 0x35460000U, 0xe670000U, 0xaeb78000U, 0x5b6d4000U, 0xf865a000U, 0x53b75000U, 0xc9e91800U, 0x6fa0dc00U, 0x82107a00U, 0x72fcab00U, 0xddec980U, 0xef0b1140U, 0xdd78020U, 0x1f5d4030U, 0xb8cda038U, 0x3c73503cU, 0x544f182aU, 0x72b7dc0dU, 0x656ffa0aU, 0x165eb30U, 0xa335699aU, 0x592f4159U, 0x57871830U, 0xa943dc10U, 0x1061fa2aU, 0x47b6eb3fU, 0xf3ece9a7U, 0xf4a1014eU, 0x75933801U, 0xbbecc16U, 0xa5bac21cU, 0xc4bc2731U, 0x48382b88U, 0x36fe2676U, 0x4fda9398U, 0xf80aaa5fU, 0xbc52718cU, 0x131c9d6dU, 0x80000000U, 0x40000000U, 0x20000000U, 0x30000000U, 0xe8000000U, 0xcc000000U, 0x5e000000U, 0x39000000U, 0x43800000U, 0x8fc00000U, 0x75e00000U, 0x68900000U, 0x10e80000U, 0x97840000U, 0x95c20000U, 0xcee10000U, 0x94118000U, 0xc1af4000U, 0xbc226000U, 0x6070f000U, 0xb9f8c800U, 0xb7af9c00U, 0x29253e00U, 0x6df6cf00U, 0xd7393480U, 0xa5cb8f40U, 0x5c718020U, 0x6fff4010U, 0x52aa6008U, 0xeca4f00cU, 0xff32c83aU, 0x735a9c33U, 0x259ebe17U, 0x43fc8f0eU, 0x5ca8d490U, 0x2da53f63U, 0xa8b2a83dU, 0x869b6c0aU, 0xfb7ff60cU, 0xfe85329U, 0xb9058a9fU, 0x3860040U, 0xafc0d492U, 0x45e13f6eU, 0x8090a817U, 0xdcea6c27U, 0xc9867601U, 0xacc31308U, 0x8d65eaa3U, 0x1bd7f043U, 0xb4499cb7U, 0xd4b1e367U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0x48000000U, 0x34000000U, 0xe2000000U, 0xaf000000U, 0xdf800000U, 0x1cc00000U, 0x52200000U, 0xfed00000U, 0xbaa80000U, 0x7d840000U, 0xd3c60000U, 0x3da50000U, 0xba108000U, 0x948a4000U, 0x5555a000U, 0x24691000U, 0x30a47800U, 0xaa907c00U, 0xe7cfa600U, 0x43b7b100U, 0xf49ca680U, 0xa2d80d40U, 0x20b88020U, 0x390e4030U, 0x6e93a028U, 0x3dcc1004U, 0x20b4f812U, 0xa51a3c0dU, 0x8f1a0638U, 0xd41ea12bU, 0x4998deb7U, 0xea587147U, 0x2fff2634U, 0xf9edf10fU, 0xf3610686U, 0xdf351d5bU, 0x69daf806U, 0x353b3c32U, 0xecc863eU, 0x5931e10aU, 0xcddfeb0U, 0xc1bb2143U, 0x778efe00U, 0xc4d49d0eU, 0xa9aad888U, 0xd402d04cU, 0x9201f8afU, 0x57008065U, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0x88000000U, 0xa4000000U, 0x4a000000U, 0x5f000000U, 0x94800000U, 0x90c00000U, 0x71e00000U, 0x89f00000U, 0x4a980000U, 0x9a840000U, 0x55c20000U, 0xa2610000U, 0x11b58000U, 0xcdbc4000U, 0xd3912000U, 0x17285000U, 0x293ff800U, 0xab572400U, 0x52cbc600U, 0xd2ce2f00U, 0x92c9df80U, 0xb2ceccc0U, 0x2cd8020U, 0x8ac84010U, 0x2ecb2008U, 0x64cd502cU, 0x3bc87822U, 0xaf4a6429U, 0x3f8f6612U, 0x4e6a3f17U, 0xc79f07a5U, 0x8d05b8e4U, 0x1783be3cU, 0x42444b32U, 0xe026b99aU, 0xf194f3caU, 0x3c2a8797U, 0xefb9f8d1U, 0xf8929e3eU, 0xd1ac1b18U, 0x7af941bbU, 0x2833d7e4U, 0xfaf94186U, 0x6833d7e6U, 0xdaf94199U, 0xd833d7ddU, 0x52f94182U, 0x7c33d7d7U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x30000000U, 0xb8000000U, 0x2c000000U, 0x2e000000U, 0xe7000000U, 0x2e800000U, 0xa6c00000U, 0x58e00000U, 0x61b00000U, 0xf8c80000U, 0x5c840000U, 0xb7c60000U, 0x2d650000U, 0x4ff18000U, 0x75edc000U, 0x49556000U, 0x417f7000U, 0x184e3800U, 0x4d42f400U, 0xe9a3f600U, 0x4e172700U, 0x55de3d80U, 0xadd85e40U, 0xe1d98020U, 0x5fd9c030U, 0x30db6028U, 0x8a5e700cU, 0x2e99b82eU, 0xbf7a340bU, 0x174f160bU, 0x67c19739U, 0xc563658bU, 0x4bf0da69U, 0xffedce36U, 0x1455d328U, 0x8afdcb96U, 0x590f795bU, 0x7ae7bda3U, 0x58b19e70U, 0x294ae010U, 0xc8c3b018U, 0xdfe4d81fU, 0xdf31443eU, 0xd60f2e35U, 0x90626339U, 0xd4771384U, 0x1caf3d54U, 0xdaf71385U, 0x4a6f3d61U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x30000000U, 0x88000000U, 0xec000000U, 0x1a000000U, 0xb5000000U, 0x46800000U, 0xf7c00000U, 0xe3200000U, 0x1c900000U, 0x35780000U, 0x88840000U, 0x7cc20000U, 0x6a70000U, 0x32d18000U, 0x5a1c4000U, 0x2a736000U, 0x5bcad000U, 0xf1eea800U, 0xa9fdb400U, 0x6a42fe00U, 0x964f900U, 0x55f2f480U, 0x808ea3c0U, 0x38098020U, 0xccc84010U, 0x26696038U, 0xeb9d00cU, 0xe1a52822U, 0x8d52f43bU, 0x215a1e06U, 0x3391692dU, 0x86fcbc91U, 0xd9c287fdU, 0x58273618U, 0x71179d17U, 0xf73ca2b5U, 0xfde0eeeeU, 0x6b300a9dU, 0x672a5aeaU, 0x325b7492U, 0x2216e3e7U, 0x6b8e021U, 0x4da5900cU, 0x77564818U, 0xa4582437U, 0xfd14b622U, 0x9d3cdd0bU, 0x20e642a5U, 0xf1b27ef6U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0xf8000000U, 0xec000000U, 0xa2000000U, 0xcd000000U, 0x7a800000U, 0x86400000U, 0x83200000U, 0x3e500000U, 0x38b80000U, 0x67840000U, 0xc4c60000U, 0x89630000U, 0x4f728000U, 0x33efc000U, 0xc9bb6000U, 0x87071000U, 0x3836800U, 0x82c25400U, 0xc2617200U, 0x1ef4b900U, 0xb42b8280U, 0x355ebdc0U, 0xa9b48020U, 0xb78cc030U, 0x9c49e018U, 0x62a8d014U, 0xb118083eU, 0xd795443bU, 0x5b5a1a28U, 0x36b2ed33U, 0xc80cf09eU, 0x248904e1U, 0xd1cd8280U, 0x8f6dbdffU, 0xc4fe0036U, 0x35a7003dU, 0xea148017U, 0xbe9cc00dU, 0x6751e005U, 0xcc3cd004U, 0xeec60804U, 0xa0624433U, 0xb3f69a3eU, 0x9eaa2d0eU, 0x4b1b109eU, 0xc696d4d1U, 0x2bd90ab2U, 0x69f039c6U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x50000000U, 0x88000000U, 0x34000000U, 0x12000000U, 0x4f000000U, 0x8800000U, 0x2e400000U, 0xa00000U, 0x8a300000U, 0xc3b80000U, 0x6f840000U, 0x62c60000U, 0x4e70000U, 0x29928000U, 0xef0c4000U, 0xeb7da000U, 0x58629000U, 0x85d37800U, 0xc8adc400U, 0xdcbb200U, 0x2f9fe500U, 0x91f06180U, 0x3adf75c0U, 0xabd48020U, 0x61ab4030U, 0xb84f2038U, 0x165ed014U, 0x3f96d822U, 0xaa0b540dU, 0xf0feca04U, 0x8a52113U, 0x7e315382U, 0x31b8d0cbU, 0x708741a0U, 0xe245a5d2U, 0x1ea45828U, 0x3b37143fU, 0x2a3b6a02U, 0x2043b118U, 0x19a42bacU, 0xe7b214e5U, 0x467e739cU, 0xe7e600feU, 0xaf1199bbU, 0x184ef1ffU, 0x665a9209U, 0x792351bU, 0x460a3992U, 0x5efb61deU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xd0000000U, 0x38000000U, 0xd4000000U, 0x7a000000U, 0x91000000U, 0x6800000U, 0x47400000U, 0x96600000U, 0x3b300000U, 0x5ba80000U, 0x1f840000U, 0xbdc60000U, 0xa7270000U, 0x42568000U, 0xb519c000U, 0x40eaa000U, 0xfe1d000U, 0x61f58800U, 0x1509b400U, 0xcf117a00U, 0x9a7dd300U, 0x715fa980U, 0x6d090540U, 0x3b108020U, 0xd07ec030U, 0x85c2038U, 0x87881034U, 0xd257280eU, 0xad1c6435U, 0xa4eaf21eU, 0x9de76724U, 0x1cf65381U, 0xbd8e1651U, 0x63550985U, 0x9b98d57eU, 0xbad080eU, 0xe7837403U, 0x89c35a19U, 0xd26c328U, 0xeb500180U, 0x679fa17cU, 0x7da8522fU, 0x882b706U, 0x5c45db84U, 0x9e0a26eU, 0x46f2f3aeU, 0x1c8cc66aU, 0x8dd001a3U, 0x30dfa155U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x30000000U, 0xf8000000U, 0x4c000000U, 0x8a000000U, 0xd9000000U, 0x17800000U, 0x6e400000U, 0xeca00000U, 0x2a100000U, 0x8b180000U, 0x6a840000U, 0xd7c20000U, 0xb5e70000U, 0x6318000U, 0x3fcfc000U, 0x6bfe6000U, 0x51325000U, 0x8f4bc800U, 0xed3a3c00U, 0xa7533200U, 0x113fc500U, 0x9555e080U, 0x643a80c0U, 0x38d38020U, 0x2b78c010U, 0x8ff7e038U, 0xe529900cU, 0x314fa83eU, 0xb23b6c13U, 0x3d37a22U, 0x81f93936U, 0xf8333285U, 0x80cbd5dbU, 0xff78489bU, 0x39f6ecdaU, 0xae297a3aU, 0x83ca3906U, 0xb9f8b2b3U, 0x143715f2U, 0xdacda8bdU, 0xee787cfaU, 0x9a775225U, 0x66e9525U, 0x3c6da89bU, 0x5d687cf5U, 0xe6ef520cU, 0x32aa9521U, 0xff0fa8adU, 0x8e9f7ccfU, 0x80000000U, 0x40000000U, 0x20000000U, 0x10000000U, 0xc8000000U, 0x24000000U, 0x2e000000U, 0xe1000000U, 0xc0800000U, 0x9d400000U, 0x4b600000U, 0xea300000U, 0x84880000U, 0x8f840000U, 0xfcc20000U, 0x36a10000U, 0x2c108000U, 0xedde4000U, 0xc53d2000U, 0xd9cf7000U, 0xa4e00800U, 0x26f58400U, 0x6a2b2a00U, 0x4f91bb00U, 0x1b1b4180U, 0x3c9e7c40U, 0xd45a8020U, 0x14fb4010U, 0x35efa008U, 0x12b03004U, 0x85cda832U, 0x36e4b409U, 0x25f6020bU, 0x51ab4f38U, 0x155063b0U, 0xc8ba4367U, 0xee0aebb2U, 0x8dc4876aU, 0x7e266189U, 0xb5510c77U, 0x98ba8825U, 0x60ec410U, 0xb9c48a3aU, 0x98218b0eU, 0x7056e9b8U, 0x763ac860U, 0x7a4c8220U, 0x32200f3cU, 0xef57c391U, 0xbfbe7369U, 0x138d4398U, 0x2053342U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x90000000U, 0x28000000U, 0x94000000U, 0x3e000000U, 0xed000000U, 0xd7800000U, 0x13c00000U, 0xbe200000U, 0x1cb00000U, 0x4ed80000U, 0x64840000U, 0x59460000U, 0xe2610000U, 0x9d548000U, 0x6e494000U, 0x71e8a000U, 0x779bf000U, 0xf6e46800U, 0x5c153c00U, 0xa02c5e00U, 0x6eb89100U, 0x5ed6f580U, 0x838f4ec0U, 0x2ca8020U, 0x2cac4030U, 0x83fa2008U, 0x12b3b024U, 0xdbd8480aU, 0x2f078c25U, 0x7080960fU, 0xa7465d3bU, 0x2f66c3b5U, 0xdad6e3c4U, 0x558e2b8fU, 0x5bce9ff7U, 0x552cd5bbU, 0x553cfecdU, 0xef12c834U, 0xeaabcc09U, 0x32fab62aU, 0xdf35ed21U, 0xa31e8bacU, 0x17a16fc7U, 0x276bd88U, 0x977cc2dfU, 0xd3f41609U, 0x15bf1d15U, 0x305663bfU, 0x59c913c7U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0x48000000U, 0xac000000U, 0xd2000000U, 0xb3000000U, 0x2800000U, 0x38400000U, 0x63e00000U, 0x6f100000U, 0x98e80000U, 0x33840000U, 0x31c60000U, 0x5d270000U, 0x7ab18000U, 0xbd1a4000U, 0xd9f96000U, 0x726c9000U, 0xb7c09800U, 0x18209400U, 0x55350200U, 0xd6ddbf00U, 0x7bdec880U, 0xe858af40U, 0xc99f8020U, 0xcb94030U, 0xa20ee038U, 0x2911d00cU, 0x3de87812U, 0x2c06442bU, 0x1204fa34U, 0x5305bb2cU, 0x32855280U, 0x7046844eU, 0xcfe3cab8U, 0xbd11106bU, 0x2bef48beU, 0x3102ef70U, 0x986e006U, 0x3ec5d000U, 0x15a67800U, 0x25f54424U, 0xea7b7a10U, 0x43acfb15U, 0xeae3b281U, 0x6293547fU, 0xe82db28bU, 0xf20545cU, 0x9b232b4U, 0x5f991446U, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0xe8000000U, 0xb4000000U, 0x3a000000U, 0x9f000000U, 0x85800000U, 0x3dc00000U, 0x38e00000U, 0x34f00000U, 0x7a280000U, 0x78840000U, 0x4b420000U, 0x96a30000U, 0xd8d08000U, 0xabf4000U, 0x9f19a000U, 0x6c4fd000U, 0x8e31f800U, 0xcb4dac00U, 0x77b12e00U, 0x889a700U, 0x12559780U, 0x7af9d940U, 0x5e3a8020U, 0xa2584010U, 0x3eb2018U, 0xc2639004U, 0xdcb0d83aU, 0xf7093c2dU, 0xd093760eU, 0xd79cdb27U, 0xbf0fc1a1U, 0x5495924fU, 0x759d19aeU, 0x6c0fae5dU, 0xb716efa6U, 0x5958354aU, 0x746a8e10U, 0xa4a5771cU, 0xa3d4ef9aU, 0x3d3b354cU, 0x99da0e12U, 0x32a370eU, 0xac054f9aU, 0x3600e553U, 0x9901f636U, 0x84809b23U, 0xf546e190U, 0xaba5024bU, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0xc8000000U, 0x54000000U, 0xf2000000U, 0x39000000U, 0xe9800000U, 0x44c00000U, 0x59e00000U, 0x5f100000U, 0xe4b80000U, 0xb6840000U, 0x46420000U, 0xdda30000U, 0x13b38000U, 0x3a8e4000U, 0xf2cea000U, 0x80699000U, 0x195cc800U, 0x9391cc00U, 0xaffee600U, 0xa2af00U, 0xe0300880U, 0x34e9dc0U, 0x8a98020U, 0x3eb94010U, 0xeb872018U, 0xf5c0d01cU, 0x8463e832U, 0x99d51c15U, 0x4c5f0e3cU, 0x5414b30eU, 0x143c86baU, 0xbc46ed1U, 0xe363a6b6U, 0x4750bec7U, 0xe1a4e81U, 0xa3b2a2e1U, 0xd28cc09bU, 0xb6cf51eeU, 0xca6f6632U, 0xbc5fef19U, 0xdc152890U, 0x203d4df6U, 0x89c1e804U, 0x12661c29U, 0xfad48e1aU, 0xb8def339U, 0xc350268eU, 0x641efec9U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0x58000000U, 0x8c000000U, 0xee000000U, 0x7b000000U, 0x28800000U, 0xf4c00000U, 0x94600000U, 0xe2700000U, 0x86280000U, 0xe9840000U, 0x5460000U, 0xfd210000U, 0xe1518000U, 0x747ac000U, 0x61786000U, 0xf2fd7000U, 0xeb8d800U, 0x5e1bc400U, 0x700fe600U, 0x98508300U, 0x19f84380U, 0x8e3ab940U, 0x5edf8020U, 0xb66fc030U, 0xb727e008U, 0x4052b00cU, 0x55ff3816U, 0x40397423U, 0x15d8de3bU, 0xc6edf71eU, 0xcfe69d8aU, 0x3a364e7dU, 0xcc889d85U, 0xee934e48U, 0x89f1d89U, 0x57c88e46U, 0xd0b6fdbfU, 0x5d4f3e60U, 0x517645bdU, 0x8aa98a5cU, 0x7417b97U, 0xb822cd40U, 0xfad6de29U, 0x4c38f713U, 0x3bd91db7U, 0x9de98e68U, 0xd7677d84U, 0x96f5fe6eU, 0x80000000U, 0x40000000U, 0x20000000U, 0x70000000U, 0x78000000U, 0x64000000U, 0xf2000000U, 0xeb000000U, 0xc800000U, 0x79c00000U, 0x6d200000U, 0x6fb00000U, 0x3dc80000U, 0xb9840000U, 0x10420000U, 0x35610000U, 0x66d38000U, 0xbd1bc000U, 0x659f2000U, 0xf6599000U, 0x44785800U, 0xdd4ce400U, 0x6e448e00U, 0x20630900U, 0x3f568d80U, 0xbd5a4640U, 0x78f98020U, 0xfc8ec010U, 0x1766a008U, 0xc5d7501cU, 0x8d9ef81eU, 0xfa5bb419U, 0xfa7a763cU, 0xa848bd3aU, 0x67c4fb83U, 0x2826fb5eU, 0x3e377bbbU, 0x218d3b4bU, 0x32e05ba7U, 0x390ab62U, 0x81fa03b2U, 0xb0d4f58U, 0x4a250d93U, 0xbd318640U, 0x610ea010U, 0xd523500cU, 0x6bb4f823U, 0x9fceb40dU, 0x5a83f62eU, 0xc67d00U, 0xdaa25ba0U, 0x12f1ab73U, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0x18000000U, 0x1c000000U, 0x22000000U, 0x87000000U, 0xac800000U, 0x58400000U, 0x2fe00000U, 0xfab00000U, 0x50680000U, 0x70440000U, 0x6be20000U, 0xe4b10000U, 0x456d8000U, 0x43c4c000U, 0x8322e000U, 0xb1101000U, 0x1739b800U, 0x4599a400U, 0xfb4c2200U, 0x85576f00U, 0x62dd6d80U, 0xb42fa740U, 0x8da2e020U, 0x2e501010U, 0xb459b808U, 0x5769a42cU, 0x9cc42206U, 0x13a36f07U, 0x7b576d88U, 0xa7daa761U, 0xfad600bU, 0xd165d006U, 0x5df6d803U, 0x5f0d7412U, 0x58b77a12U, 0x976edb1bU, 0xfcc0f792U, 0x83a56c58U, 0xd351af9aU, 0xa3d9d856U, 0x31abb583U, 0x7462d36eU, 0x76759a3fU, 0xabcecb36U, 0x2f114fa2U, 0x4238c852U, 0x561f8d8cU, 0xa38fb75dU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xf0000000U, 0xd8000000U, 0x34000000U, 0xc2000000U, 0x7b000000U, 0x20800000U, 0xa8c00000U, 0x76e00000U, 0x50500000U, 0xccf80000U, 0xfcc40000U, 0x84e60000U, 0x13570000U, 0x287f8000U, 0x4e02c000U, 0xbd07a000U, 0xa1811000U, 0x37445800U, 0xe4a7c400U, 0xc174e600U, 0x8cda700U, 0xb3ad5a80U, 0xe2bd63c0U, 0x93e7a020U, 0x5d11030U, 0xd9bc5838U, 0x9363c43cU, 0xbd12e636U, 0x875aa70dU, 0x2f32dab0U, 0x87efa3deU, 0xc2980028U, 0xf054001aU, 0x1cfe0025U, 0x34c30028U, 0x98e18005U, 0x3d51c032U, 0xa57e2011U, 0xd784d01aU, 0x4e447802U, 0x5f201439U, 0xb9311e32U, 0xeec733cU, 0xa11a64beU, 0xbc11c0c6U, 0xd8dfbcb1U, 0x5d77c4f6U, 0xe6cd7abeU, 0xdeaab3e7U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0x38000000U, 0x4000000U, 0x8e000000U, 0x13000000U, 0xa2800000U, 0xbf400000U, 0x2a200000U, 0x4ad00000U, 0x54480000U, 0x23440000U, 0xb0260000U, 0x3fd70000U, 0xe9c98000U, 0x8c85c000U, 0xbc462000U, 0x60a37000U, 0xf9911800U, 0xcc6cd400U, 0xf091da00U, 0xdbeb2100U, 0x1251ce80U, 0x6e083640U, 0x6ce62020U, 0x61337030U, 0xd1f91838U, 0x82f8d40cU, 0x7fda0eU, 0x6f382101U, 0x4d1e4ea3U, 0x3bcaf644U, 0xe5818008U, 0x5bc1c01fU, 0x5a602032U, 0x7874701eU, 0x4d8981bU, 0xe8a91409U, 0x4a77fa0fU, 0x5dd8510bU, 0x3728d692U, 0x74b0e24cU, 0x5239fa05U, 0xec9b513aU, 0xce0f5693U, 0x7ce62277U, 0x89305a3eU, 0xddfae108U, 0x30f9eea5U, 0x99784670U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0xf8000000U, 0x94000000U, 0x16000000U, 0x47000000U, 0x54800000U, 0x46c00000U, 0xa600000U, 0xed900000U, 0xdd580000U, 0x1ac40000U, 0xa0660000U, 0x70950000U, 0x5cd88000U, 0xa183c000U, 0x6b42a000U, 0x9325b000U, 0x67b2b800U, 0xd56d6400U, 0xa7ea9600U, 0x8e2ae300U, 0x1cca5480U, 0x259bcec0U, 0x5ba2a020U, 0x2b75b030U, 0x520ab828U, 0x33f96404U, 0x7c34963eU, 0xdb2be325U, 0x214cd485U, 0x44d90ed1U, 0x45868035U, 0x3542c021U, 0xa824202aU, 0x4937703fU, 0x56ae9809U, 0xa80e1423U, 0x36fa0e2dU, 0xd9b5f70dU, 0x9e6eda82U, 0xc168f9f9U, 0x71ee5ab8U, 0x692f39efU, 0x584afaa6U, 0x9b5f89c7U, 0xc5c0c2b7U, 0xd0e12deeU, 0xc850f4a3U, 0x7dba7ee1U, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0x88000000U, 0x74000000U, 0xa6000000U, 0x41000000U, 0x89800000U, 0xa9c00000U, 0xdaa00000U, 0xfa700000U, 0xf2280000U, 0xcfc40000U, 0xbba20000U, 0xe3f30000U, 0x23ef8000U, 0xe9604000U, 0x93d1a000U, 0xf6de3000U, 0x24a98800U, 0x72860c00U, 0x347ee00U, 0xf5e76500U, 0xc5961b80U, 0xdcbc3d40U, 0x81f9a020U, 0x891a3010U, 0x770b8818U, 0x15750c3cU, 0xea86e22U, 0x2987251dU, 0x79c7bba9U, 0xc2a20d50U, 0xf6702802U, 0xa82c3c3aU, 0x5cc4662eU, 0xd5266902U, 0x82b4759eU, 0xd90c186eU, 0x60739ba7U, 0x412b7d78U, 0x31458012U, 0xa2e7403cU, 0xe5142028U, 0x78f97022U, 0xdc9da83eU, 0x9ccf7c22U, 0x50d24625U, 0xc05c193fU, 0x29ee5dadU, 0x22672459U, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0xa8000000U, 0x2c000000U, 0x52000000U, 0x5f000000U, 0x76800000U, 0x5a400000U, 0xe3600000U, 0xadf00000U, 0x4a780000U, 0x70440000U, 0x18620000U, 0xd5730000U, 0xa5388000U, 0x3ea14000U, 0xe7536000U, 0x2b299000U, 0xb26e7800U, 0xed88f400U, 0xb13eb200U, 0xa8a00b00U, 0xa6535780U, 0x40ae47c0U, 0x69ab6020U, 0xe2d9010U, 0xf7ec7818U, 0xf34bf404U, 0x471e322aU, 0x38b54b0bU, 0x379a3794U, 0xcbf0d7d7U, 0xf37f983dU, 0xffc72406U, 0xada12a20U, 0x93d72f2fU, 0xe66a7db8U, 0x1b8d68d7U, 0xe03b1db2U, 0x6b27f8f2U, 0x5195e58cU, 0xf10a4ccdU, 0x707a3793U, 0x2340d7feU, 0x4ce79838U, 0x6833242fU, 0xb4db2a11U, 0xb7102f11U, 0x4348fd9bU, 0xdf1b28feU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0xe8000000U, 0xe4000000U, 0xde000000U, 0xbb000000U, 0xe8800000U, 0x24400000U, 0x4ba00000U, 0x7c300000U, 0xfd680000U, 0xc2440000U, 0x8ca60000U, 0xa6b70000U, 0xe82d8000U, 0xec634000U, 0x63512000U, 0x2b9f000U, 0x82bc5800U, 0x42ba0400U, 0xa2bb0200U, 0x12bc2d00U, 0xfab9f980U, 0x1eb84f40U, 0xc0b92020U, 0x7bbdf030U, 0x933a5838U, 0xb77d042cU, 0xfcde823aU, 0x80eb6d39U, 0x7d86d9b7U, 0xbfc2bf6eU, 0x3366f81aU, 0x95d7b439U, 0x7dfbfa2aU, 0x919c9933U, 0xf2cf8385U, 0xf0779649U, 0x72cf83b4U, 0x30779677U, 0x92cf8398U, 0x8077966eU, 0x7acf83a8U, 0x6477967aU, 0xa4cf838aU, 0xdf77966bU, 0x4c4f83a4U, 0xfb37966fU, 0x7ef83b9U, 0x87079661U, 0x80000000U, 0x40000000U, 0x60000000U, 0x30000000U, 0x98000000U, 0x3c000000U, 0x6e000000U, 0x53000000U, 0xb2800000U, 0xfa400000U, 0x50600000U, 0x5ed00000U, 0xcc080000U, 0x80440000U, 0x89620000U, 0x8d530000U, 0x89c98000U, 0x53e0c000U, 0xf313e000U, 0xdba87000U, 0x98371800U, 0x7a9b5400U, 0x41293200U, 0x86767300U, 0x18fdae80U, 0x12fc9440U, 0x33fbe020U, 0xec7c7010U, 0x5fbd1818U, 0xe31c540cU, 0x45eab226U, 0xba51b30fU, 0x494dce9bU, 0xc4a32454U, 0xeaf4980cU, 0x69bc942eU, 0xac19520cU, 0xc969c31bU, 0xbb12d695U, 0xfac706fU, 0x3237aa19U, 0x4b9de727U, 0x56af7c96U, 0xa1b69766U, 0x6e5b56aeU, 0xb50cb07eU, 0x43c44a36U, 0x4a59736U, 0xcaf064a0U, 0x39b9c37fU, 0x41864adU, 0x6d6dc34cU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x50000000U, 0xe8000000U, 0x8c000000U, 0x92000000U, 0x17000000U, 0x26800000U, 0x9ac00000U, 0xbe600000U, 0x6bd00000U, 0xfe880000U, 0x5cc40000U, 0xef660000U, 0xdc510000U, 0xf3ca8000U, 0xbfe34000U, 0x8f926000U, 0xce2d9000U, 0x2f763800U, 0x9b387400U, 0x519db600U, 0x7929e300U, 0x99f7a680U, 0xc9ff2040U, 0x33fa6020U, 0x68f99030U, 0xfc783808U, 0x21bd7414U, 0x5159363aU, 0x2c4fa323U, 0xfea146a4U, 0xdeb4f045U, 0xe9dab829U, 0xf38a3416U, 0x51455627U, 0x5927330eU, 0xdbf3fe85U, 0xf6fac474U, 0xb979ee3fU, 0x303c0702U, 0xbd1c28bdU, 0xe0eeb75dU, 0xa7107096U, 0xd9ef537aU, 0x5c95feb8U, 0x66abc450U, 0xf8b36e34U, 0xc8df4708U, 0xfc0e48a3U, 0x38032775U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0x98000000U, 0x5c000000U, 0xe000000U, 0xc5000000U, 0xe0800000U, 0x54400000U, 0x59a00000U, 0xb6900000U, 0x9d80000U, 0x41440000U, 0x61220000U, 0x1ed50000U, 0xe7a8000U, 0xaad0c000U, 0xd478e000U, 0x5d17000U, 0xf3fea800U, 0xe212c400U, 0x8798c200U, 0xb7e77d00U, 0xf031fc80U, 0xf0cefac0U, 0x3b5ae020U, 0x9e047010U, 0xbd042828U, 0x4c820414U, 0x92402226U, 0x58a60d17U, 0x4175483U, 0x96983ef1U, 0x3d602218U, 0x63760d05U, 0x1aef54beU, 0xa00c3ef9U, 0x74ba2204U, 0x82370d17U, 0x2bcfd4b3U, 0x26ddfee2U, 0x26c2423dU, 0x26e7bd38U, 0x3ab11c88U, 0xc38b8ac9U, 0x817e4800U, 0x9d57b43aU, 0xbbc6a04U, 0x7db4b922U, 0x3009bea3U, 0xcb847c4U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x90000000U, 0x38000000U, 0xfc000000U, 0xea000000U, 0x61000000U, 0x30800000U, 0xcb400000U, 0xf0a00000U, 0xb0100000U, 0x31580000U, 0x72440000U, 0xcc260000U, 0x99550000U, 0xf4fc8000U, 0xdcd5c000U, 0x4139e000U, 0xa0365000U, 0x12098800U, 0x7fb94400U, 0x4c773a00U, 0xc12a1500U, 0x396ce880U, 0xa4481ec0U, 0xa59fe020U, 0x5e235030U, 0x64550828U, 0x1e7c8424U, 0xde96da0eU, 0x4518453fU, 0xcd6360baU, 0x58f45ad8U, 0xec6c5a2cU, 0x4ac88502U, 0x11de0094U, 0x4103cac8U, 0x60823222U, 0x53469113U, 0x9ca232a1U, 0x62145bdaU, 0xac5a809fU, 0xa8c20acaU, 0x6665d21eU, 0x5971c108U, 0x8fa93aa2U, 0x1d29dfeaU, 0x836eda88U, 0x5d4e8fedU, 0xf91dd281U, 0x47670bfcU, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0xf8000000U, 0x1c000000U, 0x32000000U, 0xeb000000U, 0x73800000U, 0x21400000U, 0x7de00000U, 0x55b00000U, 0x30880000U, 0x42440000U, 0x8a620000U, 0xcaf10000U, 0xdc6d8000U, 0x6b73c000U, 0xc62ae000U, 0xd149000U, 0xe6d8d800U, 0x96795c00U, 0x342a6a00U, 0x8612bf00U, 0x55b9580U, 0xff3cc840U, 0xadc8e020U, 0xfda59010U, 0xecd55808U, 0x25fa9c2cU, 0x75688a3eU, 0x6bf22f07U, 0x18e94d8cU, 0x2bb0947aU, 0xc18d0a3cU, 0xaec5ef18U, 0xbea1ad97U, 0xab550479U, 0x42b85212U, 0x858f7307U, 0x70c127a6U, 0xbfa32b64U, 0x9fd31fb5U, 0xda7ee745U, 0x2e29ad8aU, 0x19110450U, 0x10da523fU, 0xe37e7306U, 0x66aca78aU, 0x23d0eb57U, 0x1879ffb4U, 0x1d2a7750U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x50000000U, 0x98000000U, 0x1c000000U, 0x5e000000U, 0xab000000U, 0x85800000U, 0x3cc00000U, 0xa6600000U, 0x23700000U, 0xbc880000U, 0xd3c40000U, 0xc1e20000U, 0x5ab70000U, 0xfc6a8000U, 0xcdf0c000U, 0xa5cae000U, 0xf961f000U, 0x8cf5d800U, 0x414fec00U, 0xd1278600U, 0x2ad10300U, 0x101ba380U, 0xe6fdb840U, 0x27c8e020U, 0xac66f010U, 0x12775838U, 0x300b2c14U, 0xcf876626U, 0xedc3f307U, 0x7ae6fb97U, 0xa735946aU, 0x8caf0601U, 0xad96c31fU, 0x31bbc391U, 0x9e6c885cU, 0xc8f7d829U, 0xa348ec23U, 0x9425061fU, 0xcc55c328U, 0x2d5b43b8U, 0x3e5f487bU, 0x57ddb837U, 0x1d1adc0cU, 0xc47abe15U, 0xb8881f3fU, 0xd1c37d8bU, 0xd4e39753U, 0x243625a3U, 0xdd2fbb44U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x10000000U, 0x38000000U, 0xc4000000U, 0x6e000000U, 0x59000000U, 0x36800000U, 0xb7c00000U, 0xb5e00000U, 0xc7900000U, 0xc2f80000U, 0x62c40000U, 0xe1620000U, 0xb550000U, 0x9a988000U, 0xef15c000U, 0xe43c2000U, 0xada27000U, 0x13304800U, 0xb74d7400U, 0xfa4f1e00U, 0x7ac91f00U, 0xe009d480U, 0x256f53c0U, 0xf03e2020U, 0x1ba77010U, 0x3e30c828U, 0xc7ccb404U, 0xe8893e0eU, 0x53aa6f31U, 0xa75b1c9bU, 0x3df6e7d6U, 0xd42f9e2dU, 0x3a18df3dU, 0x25d7f485U, 0xb95823f5U, 0xacf6e81eU, 0xaeafc439U, 0xfdbf60bU, 0x5b33db10U, 0xbb4aa2a5U, 0xd84948e7U, 0xa1c8a2afU, 0x1d8c48dcU, 0x572822b1U, 0xf39d88ccU, 0xb19602adU, 0xffaf8c8U, 0xa246cab3U, 0xdba64cd9U, 0x80000000U, 0x40000000U, 0x20000000U, 0x70000000U, 0x8000000U, 0xf4000000U, 0x12000000U, 0x67000000U, 0x1800000U, 0xe8400000U, 0xb9200000U, 0xb6f00000U, 0x5c680000U, 0x4d440000U, 0xe7a20000U, 0x83310000U, 0x9b0b8000U, 0x3f944000U, 0x9fbda000U, 0x69dd9000U, 0x78eb800U, 0x55574c00U, 0x85586200U, 0x654b9900U, 0xbbb4ef80U, 0x9bce9f40U, 0xbe77a020U, 0x74a89010U, 0x48a73808U, 0x16b20c1cU, 0x314e4202U, 0x99b2493dU, 0xd4cff784U, 0x3bf04359U, 0x86eb7a20U, 0x6281452aU, 0xb3c235a6U, 0xe2624a71U, 0x6c532db5U, 0x6dd9967eU, 0x5d8e7795U, 0xe6510375U, 0xe6df5a0cU, 0xe2099504U, 0xf712ad87U, 0xd778d64fU, 0x3c3a57b0U, 0x8e99d348U, 0x1b2fc21aU, 0x61e3093bU, 0xfb13d7bbU, 0x797c934cU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xd0000000U, 0x88000000U, 0x54000000U, 0x96000000U, 0x31000000U, 0x7f800000U, 0xfec00000U, 0x91200000U, 0x85500000U, 0x24c80000U, 0xbdc40000U, 0xf1a20000U, 0x99150000U, 0xaeae8000U, 0x2c704000U, 0x4d98a000U, 0xa30db000U, 0xe7610800U, 0x6c30bc00U, 0x45fed600U, 0x35bef900U, 0xc5dd4280U, 0x5f6fca40U, 0x37d2a020U, 0xf78cb010U, 0x5d258828U, 0x2f51fc34U, 0xa7caf622U, 0x3d460915U, 0x9de26aa5U, 0x4b76864cU, 0xe31fde3fU, 0x524e452fU, 0xd083948cU, 0xa4413355U, 0x2667e28bU, 0xbb77a6aU, 0xc73d2811U, 0xb69c4c0eU, 0x6f8bfe3eU, 0x6126b515U, 0x9d54bcb0U, 0x58cc7f50U, 0xafc09caaU, 0xdea48f57U, 0x8397b49eU, 0xb9e9c351U, 0x7290ca9dU, 0x266a3663U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0x68000000U, 0x3c000000U, 0x52000000U, 0xf7000000U, 0x69800000U, 0x66400000U, 0x91600000U, 0x20b00000U, 0x52580000U, 0xf7440000U, 0xb1e60000U, 0xf2710000U, 0x5ff98000U, 0x4f574000U, 0xad2fe000U, 0x2a3f9000U, 0x93743800U, 0x377f0c00U, 0x91965200U, 0x9a8adb00U, 0x59291d80U, 0xb4392ec0U, 0x7e71e020U, 0xa5fa9030U, 0xa453b808U, 0xa6ad4c0cU, 0xd37e321aU, 0x57970b0fU, 0x238d4594U, 0xa5aff2fdU, 0x24fdea3aU, 0xdcd39729U, 0x20692facU, 0xb0db25c4U, 0x4a8325aeU, 0xa1c322c2U, 0x72203210U, 0x1f520b3dU, 0x152ac59fU, 0x6e3db2c9U, 0xa5758a21U, 0xc67e4700U, 0x611577b6U, 0x3049f9d8U, 0x30892f8cU, 0xa2b25f4U, 0xfbbb258dU, 0xb13722caU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x70000000U, 0xa8000000U, 0xec000000U, 0xb6000000U, 0x95000000U, 0xef800000U, 0x61c00000U, 0x55200000U, 0x90700000U, 0xc3480000U, 0x36c40000U, 0xfda60000U, 0x41370000U, 0xe32b8000U, 0xacd14000U, 0x2ff96000U, 0x332eb000U, 0x54d52800U, 0xfbfb3c00U, 0xb12cee00U, 0x33d3d900U, 0xdb7b0b80U, 0x1c6b3640U, 0x7db76020U, 0x906db030U, 0x7bb0a838U, 0x4d697c1cU, 0x8300e2aU, 0x32af293bU, 0x2412c3adU, 0xfb5cfa65U, 0x139a461bU, 0x773da528U, 0x1f8885adU, 0xa0615f78U, 0x5a12c3baU, 0x325cfa46U, 0x21a460aU, 0x1ffda519U, 0xbb288591U, 0x28d15f54U, 0x95fac3b9U, 0x6028fa46U, 0x8654462bU, 0x99bea522U, 0x33cd05afU, 0x63831f47U, 0x67c6238cU, 0x88240a6bU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xb0000000U, 0xd8000000U, 0xd4000000U, 0x2a000000U, 0xd3000000U, 0x62800000U, 0xcbc00000U, 0x59e00000U, 0x64500000U, 0x7f80000U, 0x89440000U, 0x62220000U, 0x45b50000U, 0x7ad8000U, 0x7cbac000U, 0xec60a000U, 0x6f165000U, 0x5ade1800U, 0x40745400U, 0x3f4c3e00U, 0xdd6c3f00U, 0xd8df6a80U, 0x7f7073c0U, 0xb3cd2020U, 0x87ac9010U, 0x3cbeb828U, 0x4c62042cU, 0xdf122636U, 0x82d86b35U, 0x9473548aU, 0x154c4cf4U, 0xe6a4ab8U, 0xba58e3e2U, 0xb4b1981eU, 0xea2b9425U, 0xe3f91e1fU, 0x3b44af3bU, 0xc523d2a4U, 0xbd3777d0U, 0xc76a8633U, 0x93da3b09U, 0x69f74c9dU, 0xe20918dcU, 0xd549f497U, 0xee6b1cceU, 0xaa5bd294U, 0xdcb377ccU, 0xe6288609U, 0x1dff3b2aU, 0x80000000U, 0x40000000U, 0x60000000U, 0x30000000U, 0x48000000U, 0x84000000U, 0x76000000U, 0x3000000U, 0xa1800000U, 0x400000U, 0xca00000U, 0x46f00000U, 0xfd480000U, 0x85c40000U, 0x6ae20000U, 0x51530000U, 0xe6398000U, 0xc2ce4000U, 0x12822000U, 0xa9c2b000U, 0xe8e29800U, 0xc56cc00U, 0xf0be6200U, 0x5d0bf500U, 0x99679f80U, 0x3413fe40U, 0x501ba020U, 0xd9fcf010U, 0x5928b818U, 0x97507c0cU, 0xed3efa12U, 0x874e3921U, 0x54c07d9dU, 0xee664b40U, 0x8b961f88U, 0x8759be50U, 0x7adb803bU, 0xd09d400dU, 0x353ba035U, 0x5b4cf00cU, 0xbec0b815U, 0x67647c35U, 0x9314fa0cU, 0xd7993930U, 0xa2bbfdafU, 0x380b0b7bU, 0x23e5bfa6U, 0x69d14e63U, 0xe6f93821U, 0x62aa3c3eU, 0x3616da0fU, 0x4d1b8904U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x10000000U, 0xe8000000U, 0x14000000U, 0x22000000U, 0x8d000000U, 0x19800000U, 0xf7c00000U, 0x69200000U, 0x14700000U, 0x78980000U, 0xaa440000U, 0xf4e60000U, 0x94530000U, 0xaf688000U, 0x541b4000U, 0x1802a000U, 0x2c041000U, 0xbe07e800U, 0xab070c00U, 0x5e805e00U, 0x7742f900U, 0xa565db80U, 0x79760c0U, 0x1c4a2020U, 0x316f5030U, 0x4f1d4818U, 0xde871c04U, 0xb741b63aU, 0xc566f505U, 0x17950588U, 0xf44ad9e3U, 0x256b5ba6U, 0x6d1f20cdU, 0x53800022U, 0xaec00031U, 0x32a0003cU, 0x7eb0002bU, 0xe038000fU, 0x5df40003U, 0xc75e0025U, 0xa767000bU, 0x3a96801aU, 0x9dcc4033U, 0x2aac202bU, 0xf83c5005U, 0x71f5c834U, 0x795c5c12U, 0xc63163fU, 0x6412e531U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x50000000U, 0x58000000U, 0x4c000000U, 0x2e000000U, 0x59000000U, 0x57800000U, 0x2b400000U, 0x14a00000U, 0xb4100000U, 0x3ac80000U, 0x32c40000U, 0xd6e60000U, 0xdf310000U, 0xe19a8000U, 0x26aec000U, 0x6b306000U, 0x139e7000U, 0x29ad4800U, 0x79b0fc00U, 0x195efa00U, 0x34c3500U, 0xa0845880U, 0xe5c60240U, 0x4862e020U, 0xdbf4b030U, 0xc27b2808U, 0xf01f8c14U, 0xf0e93216U, 0x62120913U, 0xbfcac28bU, 0x33444756U, 0xb8a3f0b5U, 0xea164e7aU, 0x6bc9322dU, 0x71420909U, 0x9fa2c290U, 0xbc90474bU, 0x5b0df088U, 0x60a34e42U, 0x6615b20eU, 0x65cdc931U, 0x78402294U, 0x9024f764U, 0xdbd6d8bcU, 0x61acc24aU, 0x8db4800bU, 0xb5bc003U, 0x7c4ce02bU, 0xba01b027U, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0x68000000U, 0xcc000000U, 0xae000000U, 0x27000000U, 0xf7800000U, 0x98c00000U, 0xa7a00000U, 0x5fb00000U, 0xdba80000U, 0x9440000U, 0x64620000U, 0xe9910000U, 0x7df8000U, 0x44cf4000U, 0x41506000U, 0xa87e7000U, 0x77bb800U, 0xacfd7c00U, 0x223ee600U, 0xf69ead00U, 0x54ad7580U, 0x52c5f940U, 0x82a7e020U, 0xf1353010U, 0xbe9d808U, 0x65a20c3cU, 0x66b2de1aU, 0x43289133U, 0x5a01f3abU, 0x9d042449U, 0xfa86ad9dU, 0xda46f576U, 0x29e2be01U, 0x7c56e13bU, 0xe2fa4ba4U, 0x9539584dU, 0xb9184b88U, 0x98685850U, 0xff67cbbfU, 0x98171852U, 0x541fabb6U, 0x4aed6844U, 0xc9261387U, 0xeff11468U, 0x674f7583U, 0x9394f975U, 0x6ad86000U, 0xd64a7018U, 0x80000000U, 0x40000000U, 0x60000000U, 0xb0000000U, 0x68000000U, 0xdc000000U, 0x96000000U, 0xb9000000U, 0x1c800000U, 0xf400000U, 0xefa00000U, 0x80300000U, 0xba680000U, 0xddc40000U, 0xade20000U, 0x59130000U, 0xaa1d8000U, 0x458f4000U, 0x3fd0e000U, 0x387db000U, 0xf85f4800U, 0x64a82400U, 0x4ba0da00U, 0x3231ad00U, 0xf168b980U, 0xea44df40U, 0x25256020U, 0x5676f010U, 0xf94da818U, 0x3ab6942cU, 0x242a121aU, 0x92e2c937U, 0x49283a5U, 0xdddfc26eU, 0x376d11a7U, 0xcb464b53U, 0xeda57203U, 0xa333391cU, 0x51e8abacU, 0xc301166cU, 0x1b8063b4U, 0x16c1725fU, 0xda67d9b0U, 0xb1d52f40U, 0x157f4811U, 0x7ed82426U, 0x9ce8da0cU, 0xb585ad3bU, 0xebc2b9afU, 0x84e3df77U, 0xfd92e004U, 0xa15eb020U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0x38000000U, 0xd4000000U, 0x16000000U, 0xd9000000U, 0x6a800000U, 0xe9400000U, 0x73200000U, 0xe1700000U, 0xa1b80000U, 0x71c40000U, 0xdd620000U, 0x3dd50000U, 0x690a8000U, 0x691dc000U, 0x4f70a000U, 0xecbfb000U, 0xad454800U, 0xbd221400U, 0x1c752a00U, 0xb53f0900U, 0xad84b380U, 0x6c431c0U, 0xfae22020U, 0x8167010U, 0x7a6fe828U, 0xa9cca414U, 0x32f8e20eU, 0x59e5dd35U, 0x3993b985U, 0x96ad48f6U, 0xd0297bbaU, 0x1b6ee5eaU, 0x574d2a14U, 0x6dbb093cU, 0xa3c6b38eU, 0x8a6131fdU, 0xa50a01cU, 0xc4cfb01cU, 0xfe7d482dU, 0xa1a61402U, 0x9c372a1bU, 0x649a090cU, 0x19b6339aU, 0x2e5df1fdU, 0x71508022U, 0xd14cc014U, 0x6cb82032U, 0xed477038U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0x88000000U, 0xd4000000U, 0xce000000U, 0xfb000000U, 0xb8800000U, 0xc3400000U, 0xa4e00000U, 0xe8500000U, 0x8ab80000U, 0x69c40000U, 0x46a60000U, 0xa1330000U, 0xb22a8000U, 0xb4584000U, 0x7494a000U, 0xef9b7000U, 0xe3325800U, 0x1b2d0400U, 0x8ddbfa00U, 0x6a557700U, 0x43bfaa80U, 0x4569c0U, 0xd0662020U, 0xd9173030U, 0x9f58f818U, 0x84117414U, 0x98dd2222U, 0xd9d73335U, 0x807c70b3U, 0x6be02efeU, 0xed5f28eU, 0x5afc6dc0U, 0xf1a3da11U, 0x2bb5471eU, 0xa06bd298U, 0x453f5dfbU, 0x40052220U, 0xa0033313U, 0x300270a9U, 0xd8072ef7U, 0x5c017298U, 0x1a032df4U, 0x3503fa38U, 0x4381773cU, 0x7bc1aa84U, 0x67a269f9U, 0x4cb2a035U, 0x62e87004U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0x8000000U, 0x9c000000U, 0x32000000U, 0xeb000000U, 0xa0800000U, 0xc1400000U, 0x1f600000U, 0xc2700000U, 0xc7e80000U, 0x37c40000U, 0x83260000U, 0x90950000U, 0xf15e8000U, 0x5f8c4000U, 0x7f36e000U, 0x5a8a9000U, 0x66b0d800U, 0xa04dc400U, 0xc013aa00U, 0x281d0b00U, 0x74e99b80U, 0xc3440340U, 0x4c606020U, 0x86f2d030U, 0x70a83828U, 0x65a65434U, 0xa4d3f202U, 0xefbd8f27U, 0x533c518cU, 0x607ed87aU, 0x341f4388U, 0x86ecc740U, 0x88454a0fU, 0x3ce79b34U, 0x4fb1439bU, 0xf3cdc75eU, 0x95d5ca0eU, 0x883adb09U, 0x78ff23b0U, 0x115e1769U, 0xef8d7212U, 0x731cf01U, 0x1e8ab18bU, 0xc0b4485bU, 0xe54f9babU, 0xb9910344U, 0xa2dee002U, 0xa4e900dU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x30000000U, 0xf8000000U, 0x14000000U, 0x32000000U, 0x1d000000U, 0xa2800000U, 0x60400000U, 0xa4200000U, 0x7f00000U, 0x93080000U, 0xffc40000U, 0xf6e20000U, 0xeb970000U, 0xecd98000U, 0xb53bc000U, 0xa12ea000U, 0x6f309000U, 0x2e6c6800U, 0xd4905400U, 0x3b5fe200U, 0x4bf8d100U, 0x8b4e6780U, 0xfe63440U, 0x23152020U, 0x559c5010U, 0x499b4838U, 0x379b040cU, 0xdc9d2a3eU, 0x99181505U, 0xaadded8cU, 0xea3eb147U, 0x6aca588U, 0x89f6b548U, 0x200a0fb1U, 0x7e42605dU, 0x3f20c202U, 0x5a778126U, 0x84ceafb7U, 0x7521f074U, 0x13772a01U, 0xf44b1527U, 0x38666d9dU, 0xedd27149U, 0x87fb85b0U, 0x3d4de546U, 0x8e0c7aaU, 0x4096a44dU, 0x4959480eU, 0xb6fc042aU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xf0000000U, 0x78000000U, 0x6c000000U, 0x1e000000U, 0x55000000U, 0x77800000U, 0x3cc00000U, 0xcc200000U, 0xd9100000U, 0x51e80000U, 0xce440000U, 0x4f620000U, 0x9df50000U, 0xc6df8000U, 0x75bfc000U, 0x9e4d6000U, 0x4993f000U, 0xb1aa2800U, 0x4c26fc00U, 0x9914c600U, 0xf1eb3100U, 0x3e447080U, 0x3762ab40U, 0xf1f0e020U, 0xd8d93010U, 0x20b8c828U, 0xe9cacc3cU, 0x75538e1eU, 0x7d8e3d1bU, 0x95329e87U, 0xc8fb6655U, 0x3faa56bdU, 0x7121aa5fU, 0xaa91d8bbU, 0x372b975aU, 0xad614602U, 0xbef5f104U, 0xa05c90a2U, 0xc4ff9b55U, 0x31aa2815U, 0xc26fc0cU, 0x3914c626U, 0x1eb3102U, 0x46447088U, 0x5b62ab42U, 0xeff0e035U, 0x8dd9301bU, 0x5738c80cU, 0xd50acc37U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x30000000U, 0x48000000U, 0x4c000000U, 0xe2000000U, 0xd000000U, 0x44800000U, 0x29400000U, 0x3200000U, 0xb8d00000U, 0xebe80000U, 0xc8c40000U, 0xd2e60000U, 0x58b30000U, 0x21198000U, 0x757e4000U, 0x99886000U, 0xe7361000U, 0x37dce800U, 0xa09ee400U, 0x94baea00U, 0x31ee2900U, 0x61c05e80U, 0x6864c340U, 0xe6f7e020U, 0x6fbb5030U, 0xe6d0818U, 0xb706b40cU, 0xdd866212U, 0xdbc2dd13U, 0xf1605cb8U, 0x14770e43U, 0x9dfcd4b1U, 0xa2cbfa7aU, 0xc114d6b8U, 0xb78c3752U, 0xc831e210U, 0x1e5b9d1dU, 0xfd5fbc86U, 0xf6d85e4aU, 0xc61fdc93U, 0xd0fa4e77U, 0x464d34b7U, 0xb853aa62U, 0xcca85e8cU, 0x74e0c351U, 0x5bb1e039U, 0xda98502aU, 0x6dbc883dU, 0xf36cf435U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0x58000000U, 0x54000000U, 0x6000000U, 0x61000000U, 0xd0800000U, 0x2dc00000U, 0x96a00000U, 0x59d00000U, 0x7b80000U, 0x88440000U, 0x8de60000U, 0x93b10000U, 0x70498000U, 0xf7eec000U, 0xc6b8a000U, 0xa8c33000U, 0xd8258800U, 0x6114c400U, 0x77988e00U, 0xc550e500U, 0x987d5680U, 0x69e081c0U, 0xdb72020U, 0x654cf030U, 0x116ca808U, 0xd27d340cU, 0xbae3a616U, 0xaa361115U, 0x9109d081U, 0x768a60d8U, 0x62ca5894U, 0x152fa4fbU, 0xcd9b568dU, 0x6e5181eaU, 0x5bfea03fU, 0xc3a2300bU, 0x5f54083cU, 0x37e0425U, 0xf2662e3fU, 0xf3f2d53bU, 0x31a95ea1U, 0x165e85efU, 0xe1f10e06U, 0xb6ae2517U, 0xb7ddf692U, 0x74b7b1edU, 0x1cca82eU, 0x2aad3404U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x30000000U, 0x88000000U, 0x54000000U, 0xfa000000U, 0x37000000U, 0x21800000U, 0x60c00000U, 0x30200000U, 0x91300000U, 0x1bb80000U, 0x92440000U, 0x43620000U, 0x42d70000U, 0x51298000U, 0xc7084000U, 0x8f3ca000U, 0x9806d000U, 0x4c053800U, 0xf603cc00U, 0x21046600U, 0x3080b100U, 0xd8404180U, 0xbc67b9c0U, 0xd7572020U, 0xfbe99010U, 0x48281838U, 0x6b895c0cU, 0x197ffe22U, 0xd962ad15U, 0x5d09fbeU, 0x18a884cdU, 0xc3cda7a8U, 0xcd1f48c8U, 0x6a33c194U, 0x8c3cf9f8U, 0x3380003cU, 0x73c0002dU, 0x83a00034U, 0xa2f00004U, 0x78180000U, 0xb40031U, 0xb37a0019U, 0x16630017U, 0x18538011U, 0xe66b4025U, 0xb6ef2012U, 0x1ead901cU, 0xcaca1834U, 0x799e5c2aU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x50000000U, 0xe8000000U, 0x2c000000U, 0xce000000U, 0xdf000000U, 0x74800000U, 0xa0400000U, 0x10a00000U, 0x19f00000U, 0x28880000U, 0x4fc40000U, 0xe6660000U, 0x18150000U, 0xda5a8000U, 0x427b4000U, 0x1dcb6000U, 0x76e17000U, 0xca577800U, 0x93fb6400U, 0x8c0da200U, 0xc782d500U, 0x7ac22780U, 0x9fe5e840U, 0xc5d7e020U, 0x553f3030U, 0x95ee9828U, 0xa1555414U, 0x7d7fba3aU, 0x5949c10bU, 0xcea47db3U, 0x4ef21977U, 0x800985bdU, 0x99823d58U, 0xedc7478cU, 0x97659862U, 0x43941838U, 0xb69e143cU, 0x369cda18U, 0xf69cb12eU, 0x569d05a2U, 0x6987d44U, 0xee98a78dU, 0xc29ea874U, 0xc9c8029U, 0xd39e403dU, 0xa719e006U, 0x75e303dU, 0x17fa1812U, 0xe0f141eU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xb0000000U, 0x8000000U, 0x24000000U, 0xa000000U, 0xbd000000U, 0x75800000U, 0xfbc00000U, 0xaa600000U, 0xf9100000U, 0x1bc80000U, 0x3f440000U, 0x1a260000U, 0xc7b30000U, 0x1c3d8000U, 0x75dc4000U, 0xfc0b2000U, 0x73215000U, 0x10356800U, 0xaefd6c00U, 0x183f3e00U, 0x6fde6300U, 0x990a5080U, 0x9aa24a40U, 0xcdf0a020U, 0x979e1030U, 0x23abc818U, 0x47547c2cU, 0x826f7602U, 0x28355f09U, 0x42fb8682U, 0x563e056fU, 0x68db6ebdU, 0x598b294eU, 0x30e17092U, 0x96531a62U, 0x79edc83cU, 0xb4f77c1aU, 0x981af61eU, 0xd6d1f3bU, 0xcb6a69aU, 0x82bc5545U, 0x9b86aaU, 0xfb2e0543U, 0x11136e8dU, 0x4fcf2978U, 0x5d477096U, 0x33201a4eU, 0xb0304819U, 0x7efb3c3fU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x90000000U, 0xb8000000U, 0x4c000000U, 0x26000000U, 0xb7000000U, 0x86800000U, 0x64c00000U, 0xcd600000U, 0xde700000U, 0xa2280000U, 0x71440000U, 0xdd260000U, 0xdad70000U, 0x8ebc8000U, 0xac59c000U, 0x4b686000U, 0x90643000U, 0x9f03800U, 0x176a7400U, 0xce640600U, 0x12f6fb00U, 0x27ef1b80U, 0xa5a52d40U, 0x1512e020U, 0xbb5af030U, 0x7decd838U, 0x3ca38424U, 0xa0925e2eU, 0x1b1bbf13U, 0xb149a589U, 0x7433626dU, 0xaf8b1d81U, 0x5053d669U, 0xec7dfbabU, 0xa63fdd63U, 0x3b9e381eU, 0xa289741bU, 0xdfd68628U, 0x853c3b2cU, 0x871dfba5U, 0xf4fdd4cU, 0xff363829U, 0x270d7417U, 0x77908600U, 0xcd9b3b13U, 0x8d897bb1U, 0x65521d4aU, 0xeff8581cU, 0x97e4435U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0xe8000000U, 0xb4000000U, 0x22000000U, 0x45000000U, 0xed800000U, 0x25400000U, 0xa1600000U, 0xa8100000U, 0xee480000U, 0x9bc40000U, 0xcea60000U, 0x64b70000U, 0x1ff98000U, 0xb1bb4000U, 0x65fa000U, 0x558c1000U, 0x8566a800U, 0x7210ac00U, 0x274d4a00U, 0x38437b00U, 0xd0e29880U, 0xfb518640U, 0x18282020U, 0x73545030U, 0x5c2e8838U, 0x5954fc0cU, 0x9d2bc23aU, 0x7ed3872dU, 0x496f5a88U, 0x10350151U, 0x813efa9bU, 0xb29a1179U, 0x97afd2b0U, 0x3312fd56U, 0xc0cab899U, 0xc05d677U, 0x8e06a819U, 0xdb00ac19U, 0xe854a36U, 0x47c77b15U, 0x98a498a0U, 0xe3b6864aU, 0x8779a021U, 0x917b1038U, 0x367f282aU, 0x7efbec1eU, 0x863aea29U, 0xea1b6b2aU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0xd8000000U, 0x94000000U, 0x52000000U, 0x49000000U, 0x7e800000U, 0xfa400000U, 0x35e00000U, 0x45700000U, 0xf6780000U, 0x5bc40000U, 0x82260000U, 0x11570000U, 0xf4298000U, 0xe46ac000U, 0xfc8ea000U, 0xad7f9000U, 0x4c46c800U, 0xd6e5b400U, 0x36f33200U, 0xc8b8df00U, 0x91649380U, 0x4a363fc0U, 0x43192020U, 0x5bf65030U, 0xfc3fe838U, 0x5623e40cU, 0x6354da36U, 0x6d2f3b25U, 0x72ee4994U, 0x4aca04d2U, 0x5e98e9bfU, 0x123194ceU, 0x17182195U, 0xe9f320edU, 0x853a9393U, 0xf0a53fcfU, 0xd16a01aU, 0xacb900fU, 0x7e98c838U, 0xc236b43cU, 0xff1cb20fU, 0xa5f51f33U, 0x433bb3a8U, 0xeba76fdeU, 0x3a974822U, 0x8e0b743fU, 0xb13b9231U, 0xb2a04f24U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x50000000U, 0x18000000U, 0x1c000000U, 0xae000000U, 0x8f000000U, 0x90800000U, 0x7bc00000U, 0x4ee00000U, 0xbc300000U, 0xc0380000U, 0x1e440000U, 0xc0a20000U, 0xc4970000U, 0xa8aa8000U, 0x50ecc000U, 0x1b4ee000U, 0xfd5c7000U, 0xf37f800U, 0xebbc400U, 0x42827e00U, 0x4ac7a700U, 0xa963c980U, 0x1b71edc0U, 0x431e6020U, 0x7f93b010U, 0x82299838U, 0xee287414U, 0xa82be606U, 0x932fd307U, 0xf9a82fabU, 0xa76e3ee3U, 0x440e4f84U, 0x32798eceU, 0xd8e5d78bU, 0xdf36faebU, 0x56bcb1aeU, 0xbe81e9c4U, 0xb4c07e05U, 0x3e60a711U, 0x97f1499bU, 0x96d92dfaU, 0xbe72803cU, 0xae98c03aU, 0x55d4e017U, 0xf88f7002U, 0xefbf7821U, 0xfd000412U, 0x11861e38U, 0xd4471728U, 0x80000000U, 0x40000000U, 0x20000000U, 0xd0000000U, 0x28000000U, 0xb4000000U, 0x22000000U, 0xa7000000U, 0xb800000U, 0xf3c00000U, 0x64200000U, 0x7b700000U, 0xd5880000U, 0x74240000U, 0x33720000U, 0x91890000U, 0xae228000U, 0x8734000U, 0xc0ca000U, 0xd8e39000U, 0xc0d67800U, 0x8f3cfc00U, 0x9a8c0e00U, 0xaba15900U, 0x12b52780U, 0xaaafa240U, 0x42d67820U, 0xb83cfc10U, 0x990c0e08U, 0x3c615934U, 0x7c95278aU, 0xc2dfa26dU, 0xbede7828U, 0x98d8fc39U, 0xc5de0e0aU, 0x25585908U, 0x631fa793U, 0xc5f8e273U, 0x5428d81dU, 0xa5966c24U, 0x9858f606U, 0x339ee52cU, 0x5bbd89b8U, 0xbec96b71U, 0x8a47279eU, 0x58e6a252U, 0x80d4f816U, 0xaf3fbc1fU, 0x4a88ae16U, 0x83a6c92fU, 0xa6b15fb0U, 0x88aa5e45U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0x38000000U, 0x54000000U, 0x4e000000U, 0x17000000U, 0x6a800000U, 0x6b400000U, 0xa2a00000U, 0x80b00000U, 0x6280000U, 0xdaa40000U, 0x34b60000U, 0xd8290000U, 0x45a18000U, 0x3237c000U, 0xa96ba000U, 0xbe03f000U, 0xcf077800U, 0xae80f400U, 0xad44aa00U, 0xd9a46d00U, 0xf035f180U, 0x34691b40U, 0x5877820U, 0xb5c0f430U, 0x17e4aa08U, 0xbd146d2cU, 0x801df18eU, 0xadcd1b55U, 0x15b17833U, 0x11a9f435U, 0x9a652a12U, 0x64d3ad36U, 0x8dfe51a6U, 0x49daeb75U, 0xe8280032U, 0xbda40003U, 0x4636001fU, 0x57690000U, 0x91018037U, 0xf187c039U, 0x8bc3a038U, 0x18e7f01cU, 0x33917824U, 0x9d59f407U, 0x4c6d2a12U, 0xb187ad1aU, 0x6bc05197U, 0x88e7eb54U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xf0000000U, 0x18000000U, 0xe4000000U, 0xf2000000U, 0x85000000U, 0xe800000U, 0xb1c00000U, 0xf5200000U, 0x9c100000U, 0x5e80000U, 0x3d240000U, 0x30160000U, 0x9beb0000U, 0x46238000U, 0xb596c000U, 0xb7ac2000U, 0x7b441000U, 0xe6e2e800U, 0x64345400U, 0x9b7d9e00U, 0x870f4100U, 0x6b11b480U, 0x4e6f3140U, 0xe262e820U, 0x84f45430U, 0xeadd9e18U, 0x3bdf413cU, 0x7f59b486U, 0x3f9b3179U, 0xde3ce81cU, 0x8aeb5411U, 0x62a01e1bU, 0x5568110U, 0x4e0814bbU, 0xcb96e15eU, 0xfcafa01dU, 0x86c2d01eU, 0xdea6c817U, 0xb3544436U, 0xa909762aU, 0xa8101533U, 0xbfefaa90U, 0xd426b070U, 0xc0977c96U, 0xa12b7563U, 0x2e839e32U, 0xe1c04127U, 0x7d2434a8U, 0x9012f147U, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0x58000000U, 0xdc000000U, 0xe6000000U, 0x89000000U, 0x74800000U, 0xa8400000U, 0x7b200000U, 0xb2100000U, 0xb8b80000U, 0x47240000U, 0x44120000U, 0x9bb0000U, 0xbfa68000U, 0x5250c000U, 0x279de000U, 0x9f31b000U, 0xcbac8800U, 0x6f1a4400U, 0xc176f200U, 0x18c5100U, 0x258d5480U, 0x6f89f7c0U, 0x688c8820U, 0x410a4410U, 0xffcef218U, 0x9fa85114U, 0x4d1f5496U, 0x1272f7f7U, 0x4a0a0819U, 0x284a8432U, 0x146b1205U, 0xeffde13eU, 0xb981dc88U, 0xc6c3b3dbU, 0x8c627a37U, 0x3cb21523U, 0x5269a694U, 0x16fea6fcU, 0xa5075c87U, 0xba8373dfU, 0x95479a26U, 0x3da7a510U, 0xf1572eb0U, 0x41fe2d0U, 0x46f72e8eU, 0xd24fe2fdU, 0x5b6f2eb2U, 0x227be2e1U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xf0000000U, 0xe8000000U, 0xb4000000U, 0x2000000U, 0xf1000000U, 0xa4800000U, 0x50c00000U, 0x73a00000U, 0xb0500000U, 0x68180000U, 0xb7a40000U, 0x1a520000U, 0xcd1f0000U, 0xe1238000U, 0x53954000U, 0xae3aa000U, 0x3b39000U, 0xb92ac800U, 0xd4b8400U, 0x213b1600U, 0xb0325500U, 0x466f8680U, 0xd7aa16c0U, 0x488ac820U, 0xc1b8410U, 0xda31638U, 0xa756553cU, 0xc79d86baU, 0x1ee516edU, 0xc3b14820U, 0x192ac42cU, 0x1d4bb611U, 0x393ac528U, 0xec34cea6U, 0xf06bd2c1U, 0x24a8fe3aU, 0x1d0f0101U, 0xf85cf897U, 0x2ec457dbU, 0x64a690beU, 0x1fd743c5U, 0xc15ecea9U, 0x6e40d2fdU, 0xce617e23U, 0x31714125U, 0x8b8fd8aeU, 0x119987f9U, 0x5de77893U, 0x9e3517cdU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x70000000U, 0x68000000U, 0x7c000000U, 0xa2000000U, 0x69000000U, 0x63800000U, 0x24400000U, 0x18600000U, 0x55500000U, 0x9ff80000U, 0x5c640000U, 0xd3520000U, 0xe0fd0000U, 0xf8e78000U, 0x37914000U, 0xaa5ee000U, 0x50129000U, 0xa81a0800U, 0x4771fc00U, 0x31cdb200U, 0x4049cb00U, 0x850fd680U, 0x52e88dc0U, 0x99fa0820U, 0x6361fc10U, 0xd7d5b228U, 0x743dcb1cU, 0xda45d69aU, 0xe3618ddfU, 0x97d78808U, 0xd439bc0aU, 0xaa46d230U, 0x8b671b15U, 0xebd4be9cU, 0x763ea1caU, 0xc341522fU, 0xe8e65b1dU, 0xcf925e84U, 0x6e5831edU, 0x96115a02U, 0x771ea717U, 0x93f26c8dU, 0xbd09bac5U, 0x76edecbcU, 0x8ffcfaefU, 0xa4610c94U, 0x17536adeU, 0x26fc84a6U, 0x27e3d6cdU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0x18000000U, 0xdc000000U, 0x16000000U, 0x1f000000U, 0x3a800000U, 0x55c00000U, 0x9e200000U, 0x72d00000U, 0x4c980000U, 0x10240000U, 0x71d60000U, 0x801f0000U, 0xeae18000U, 0xcd76c000U, 0x7b09e000U, 0x2e593000U, 0xb0823800U, 0x7cc63400U, 0xeba09e00U, 0xb5914900U, 0x437c6280U, 0x36d29ac0U, 0x469a3820U, 0xf9223430U, 0xe4569e38U, 0xf75e492cU, 0xfd05e286U, 0x37805af7U, 0x5a45d825U, 0x48640437U, 0x84b52636U, 0x132ebd39U, 0xf38c9ca1U, 0xde9823ebU, 0xe52382b6U, 0x1254aaf3U, 0x5859800aU, 0xdf82c029U, 0xbe47e023U, 0xd2623034U, 0x25b5b80eU, 0xf2aff43fU, 0x56c8fe3bU, 0x1c7eb92dU, 0x2c57baa9U, 0x435d9ed7U, 0xcf009e1aU, 0x5281492eU, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0xe8000000U, 0xe4000000U, 0x7a000000U, 0xb3000000U, 0xd6800000U, 0x93c00000U, 0x16200000U, 0x79900000U, 0x43780000U, 0x24240000U, 0x7e920000U, 0x17fb0000U, 0x78e78000U, 0xc8354000U, 0xd0ac2000U, 0x323c5000U, 0x63c4d800U, 0xbe209400U, 0xfd97ce00U, 0x4979e900U, 0x7f211880U, 0x4c1075c0U, 0xfe3cd820U, 0xddc49410U, 0x6725ce18U, 0x12e91cU, 0x3e98baU, 0x64c135f9U, 0xeaa2f83eU, 0xa153c43cU, 0xffde962dU, 0xb8733d38U, 0x6cf76bfU, 0x55cb8ce7U, 0xb34ab8aeU, 0xa88965f5U, 0x2aac2012U, 0xc13c502dU, 0xd544d839U, 0x5de09409U, 0x3b7ce00U, 0xd4e9e910U, 0x465918acU, 0xdb3475e2U, 0x562ed831U, 0x59ff940aU, 0x9e24e26U, 0xb1b7a914U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xb0000000U, 0xb8000000U, 0xc4000000U, 0xca000000U, 0x89000000U, 0xa9800000U, 0x50c00000U, 0x81600000U, 0x6d500000U, 0xf1c80000U, 0xf640000U, 0xee560000U, 0x714d0000U, 0x46218000U, 0x87f3c000U, 0x597b2000U, 0x10bfd000U, 0xf05b8800U, 0x11cc6c00U, 0xdf665600U, 0x46530300U, 0xbd4d4680U, 0xf0213840U, 0xf38820U, 0xb3f86c30U, 0x60f85628U, 0x887a032cU, 0xad3ac6aeU, 0xc29ff871U, 0xd5a92812U, 0xadb47c12U, 0x6058fe02U, 0xd9c9bf38U, 0x367188eU, 0xf850976aU, 0x464a38aeU, 0x14a24751U, 0x33b03099U, 0xeb5deb54U, 0x254d4697U, 0x44213857U, 0xd2f3883eU, 0x4ef86c08U, 0xbb785619U, 0x95ba0333U, 0x4fdac6b0U, 0x760ff86cU, 0xc81281dU, 0x9f407c26U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0xa8000000U, 0x8c000000U, 0x6e000000U, 0x4f000000U, 0x9800000U, 0x43400000U, 0x83e00000U, 0xa5b00000U, 0xdd580000U, 0x11e40000U, 0x3cb60000U, 0x9fd90000U, 0x69228000U, 0x75134000U, 0x730d6000U, 0x3509f000U, 0x360d3800U, 0x718f2c00U, 0xadccea00U, 0x8faea700U, 0xe559c180U, 0xd5e320c0U, 0x2eb53820U, 0xc6db2c30U, 0xba2ea08U, 0xddd3a734U, 0x92ad41aaU, 0x55d960e3U, 0x422d83bU, 0x7d959c23U, 0xa6ccb20aU, 0x54287b24U, 0xdf18138aU, 0xe482abcaU, 0x8bc0138cU, 0x7626abe7U, 0x149613a5U, 0x9c4fabf3U, 0x8ec93b8U, 0x74b8ebd3U, 0x2957f3b2U, 0x91681bfdU, 0x7ff84b99U, 0xd6b477dfU, 0x22d9c18aU, 0xc9a320f3U, 0x2cd53829U, 0x7c2b2c31U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xb0000000U, 0x48000000U, 0x24000000U, 0xbe000000U, 0xa7000000U, 0xda800000U, 0x5a400000U, 0x94200000U, 0xff300000U, 0x12d80000U, 0xd6240000U, 0x9a360000U, 0x6d5b0000U, 0x93e18000U, 0xfbd44000U, 0xbb8a2000U, 0x73ec7000U, 0x73fd7800U, 0xe96f400U, 0x712fa200U, 0xb8995900U, 0xaa05cd80U, 0x9101d4c0U, 0x39857820U, 0x8ec2f430U, 0x2161a218U, 0x9596592cU, 0x9aa4d92U, 0xf7da94c9U, 0x69a0d80fU, 0xbff5c419U, 0xbcb97a2eU, 0xd379d3aU, 0x3fdd37b7U, 0x8da209f6U, 0x61f26f8bU, 0xabbc8decU, 0x9fb6b5a8U, 0x419820d1U, 0xa7855a2bU, 0x39c0ed14U, 0x63e1cf8fU, 0x13d0bde5U, 0x4f8fed91U, 0x35eda4deU, 0xb8f8003cU, 0x4e14000cU, 0x326e0019U, 0x513f0001U, 0x80000000U, 0x40000000U, 0x20000000U, 0x70000000U, 0xf8000000U, 0xf4000000U, 0x9a000000U, 0x41000000U, 0xf4800000U, 0xa4400000U, 0x56600000U, 0x97700000U, 0x81980000U, 0xd7640000U, 0x3f20000U, 0x75d90000U, 0x9078000U, 0x9885c000U, 0x9a46a000U, 0x5675000U, 0x2ef5c800U, 0xbf580400U, 0xfe45f200U, 0x7762bb00U, 0x33f21f80U, 0xaddaaec0U, 0x8d07c820U, 0xfa810410U, 0x2f427208U, 0x6be77b1cU, 0xcbb4bfbeU, 0x1dbdfefdU, 0xcd720006U, 0xa0990000U, 0x73e78035U, 0x2fb5c035U, 0x2fbea02bU, 0xf0735018U, 0xc21fc806U, 0xf8a50425U, 0x5650723dU, 0xa90e7b34U, 0x774b3f97U, 0x702c3ec3U, 0xbbdea026U, 0xe2035024U, 0xf507c803U, 0x4e81042eU, 0x95427203U, 0x5ae77b06U, 0xc734bf8cU, 0x4dfdfefaU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x70000000U, 0xa8000000U, 0x94000000U, 0xae000000U, 0xbf000000U, 0x9b800000U, 0x71400000U, 0xfba00000U, 0x33d00000U, 0x51d80000U, 0xdca40000U, 0xf4560000U, 0xca9d0000U, 0xee078000U, 0xdf034000U, 0x4b81a000U, 0xa946f000U, 0xc7a0b800U, 0x9d07c00U, 0x40defa00U, 0xf8262500U, 0x1e934280U, 0x407c04c0U, 0x2676b820U, 0xbd0d7c30U, 0xc6f97a28U, 0x81b5651cU, 0xf96ae2aaU, 0x2d4ef4e5U, 0x71d8000bU, 0x6ca4001fU, 0xfc56000eU, 0x2e9d0000U, 0xe8078014U, 0xf4034029U, 0x7e01a03fU, 0x6706f018U, 0xa780b81bU, 0x4b407c2eU, 0xeaa6fa05U, 0x1752253bU, 0xbb1d4286U, 0x564504ddU, 0x3c27382cU, 0xa8933c00U, 0x637f5a03U, 0xf7f0d515U, 0x754bfabfU, 0x8dd878dfU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0x88000000U, 0xbc000000U, 0x46000000U, 0x65000000U, 0x2800000U, 0xcb400000U, 0x90a00000U, 0x4ff00000U, 0xe6280000U, 0xcda40000U, 0xa9720000U, 0xff6d0000U, 0x52008000U, 0x4f064000U, 0x980e000U, 0x80c6b000U, 0x97676800U, 0xcd15f400U, 0x7dfc6a00U, 0xca3bad00U, 0x10dc6b80U, 0x1f0a6b40U, 0x72956820U, 0x6038f410U, 0x5bdcea28U, 0xf48ded24U, 0xe5548ba2U, 0x6ad8db6fU, 0x7c080031U, 0xb5140009U, 0x39fa0028U, 0x88390016U, 0x97da8006U, 0xa8f403cU, 0x24526028U, 0x1a5df02aU, 0x284f082aU, 0x431040dU, 0xdac9e230U, 0x3775e900U, 0x4e6fe9bbU, 0x9a867253U, 0xbf4789afU, 0xcaa2825cU, 0xfcf20183U, 0x9acc655U, 0xb86183acU, 0xb490df7cU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x30000000U, 0x58000000U, 0x8c000000U, 0xe2000000U, 0xc7000000U, 0xb8800000U, 0xb4400000U, 0x70a00000U, 0x5bf00000U, 0xf3c80000U, 0x43a40000U, 0xfd720000U, 0x9a8d0000U, 0xf0858000U, 0x1040c000U, 0xe6a16000U, 0xc2f69000U, 0x364cf800U, 0x465a400U, 0x6310b200U, 0xc298bd00U, 0x909a9b80U, 0x4f9efc40U, 0xdb1ef820U, 0xbd58a410U, 0x52fd3228U, 0x3d8c7d0cU, 0x9801fb96U, 0x6c016c63U, 0x72058018U, 0xaf00c021U, 0x6c816006U, 0xda469021U, 0x55a4f80aU, 0x2471a435U, 0xff0ab204U, 0x8741bd21U, 0xd6251b91U, 0x32b73c4bU, 0x40e81800U, 0xae93f402U, 0x815d2a2dU, 0xa8fb892cU, 0xd68ed1a4U, 0xf287e544U, 0x4746d1bcU, 0x3623e555U, 0xa2b4d1bbU, 0x28eee552U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x50000000U, 0x48000000U, 0xf4000000U, 0xa6000000U, 0x9d000000U, 0xc3800000U, 0xb8c00000U, 0xf4a00000U, 0x84b00000U, 0x87a80000U, 0xe5a40000U, 0xed360000U, 0xc8690000U, 0x5868000U, 0x95c44000U, 0xf26a000U, 0xd077b000U, 0x690ea800U, 0xae15bc00U, 0x921ef600U, 0xcb8e4d00U, 0x6752b980U, 0x957cbb40U, 0xfd18a820U, 0xa30cbc30U, 0xe9107608U, 0xbe9e0d14U, 0xdbca1992U, 0x3db60b7dU, 0x6a2e8009U, 0x14604017U, 0x2c10a038U, 0x211eb03aU, 0x4108282fU, 0xea11fc1cU, 0xc185608U, 0xba89fd1eU, 0xbed4118bU, 0xe2bd075cU, 0xf1385e1cU, 0xc1fff134U, 0xe15a4faaU, 0x93ebf659U, 0xc1449193U, 0x13604754U, 0xe0907e24U, 0x41580114U, 0x3ec47b0U, 0xa944fa56U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xb0000000U, 0x98000000U, 0x4c000000U, 0xde000000U, 0xe1000000U, 0xbf800000U, 0x36c00000U, 0x7ca00000U, 0x2cd00000U, 0xea880000U, 0xc3a40000U, 0xb2560000U, 0xc3cd0000U, 0x39c18000U, 0x7a22c000U, 0x49976000U, 0xceeb7000U, 0xead7c800U, 0x87899c00U, 0x2264600U, 0xd5976d00U, 0x98ed5a80U, 0x6fd50240U, 0x3209c820U, 0x47e09c30U, 0x29b1c628U, 0xdc78ad2cU, 0x70bbbaa6U, 0x971cb253U, 0x4f496017U, 0xef827008U, 0x7ec04807U, 0xb8a65c21U, 0x96d0a639U, 0x18edd18U, 0xf25f28dU, 0x413ee48U, 0xd72e4623U, 0xe0f36d0dU, 0xf61b5ab9U, 0x30c80279U, 0x7940482eU, 0xb2665c20U, 0xc70a609U, 0x305edd05U, 0x1c2df287U, 0x5c77ee75U, 0x7858463cU, 0xd82e6d2bU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0x68000000U, 0xfc000000U, 0x46000000U, 0x7f000000U, 0x68800000U, 0xcfc00000U, 0x3ea00000U, 0xbc900000U, 0x6d980000U, 0x67a40000U, 0xfb160000U, 0x32d90000U, 0xb2c18000U, 0xab254000U, 0x26d6e000U, 0xe97fb000U, 0xefd4b800U, 0x76faa400U, 0x24914e00U, 0x19998d00U, 0x4da0e080U, 0x1a1172c0U, 0xb15ab820U, 0xaf87a430U, 0x6346ce08U, 0xb365cd2cU, 0x9f37809aU, 0x148b82ffU, 0x6878e031U, 0x3c52b02fU, 0x93bb3812U, 0xc8f2e41fU, 0x5e282e15U, 0xfeee7d10U, 0xb0cd388aU, 0x779c26c6U, 0x2ea62e04U, 0xa4937d0fU, 0xd99ab8abU, 0x6da066e9U, 0xaa114e28U, 0xd9598d2cU, 0x5380e09cU, 0x254172e2U, 0xcc62b805U, 0xf7b3a410U, 0xdb48ce0cU, 0x56d8cd20U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x90000000U, 0xe8000000U, 0x1c000000U, 0x16000000U, 0xa3000000U, 0x28800000U, 0x8cc00000U, 0xb4a00000U, 0xc8f00000U, 0xc7480000U, 0xd1a40000U, 0x8b760000U, 0xf0f0000U, 0x87c08000U, 0xa0214000U, 0x2237e000U, 0xa8ec3000U, 0xc5d65800U, 0xcaffa400U, 0xdf0fd600U, 0x4fc63d00U, 0xcc214380U, 0x4c313c40U, 0xffe85820U, 0xe754a430U, 0xf3395638U, 0xe0287d24U, 0x237623baU, 0x330c4c47U, 0xe1c1e025U, 0x7b233018U, 0xfeb6d832U, 0x2e2ee407U, 0xc4703617U, 0x898e0d35U, 0xbc011bb4U, 0xa601985cU, 0x3b070e08U, 0x4c83d910U, 0x6ec7f5b4U, 0x1da1717eU, 0x557623a3U, 0xc00c4c69U, 0xc141e00eU, 0x7be3300dU, 0xb416d81eU, 0x59dee43bU, 0x3db83629U, 0x77ea0d24U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0xc8000000U, 0xc000000U, 0x4e000000U, 0xc3000000U, 0xf5800000U, 0xb400000U, 0x68e00000U, 0xfb500000U, 0x99180000U, 0xa9e40000U, 0xa3d60000U, 0xf4df0000U, 0x47c18000U, 0xff204000U, 0xbc776000U, 0x16ff000U, 0x5a8c5800U, 0xbc5dcc00U, 0x72072a00U, 0x8501df00U, 0xda84b680U, 0xc732c0U, 0x68a25820U, 0x6a36cc30U, 0x2708aa38U, 0x9b1a9f2cU, 0x4e456b2U, 0xc55782c3U, 0x7218e033U, 0xe064b000U, 0x2e94b805U, 0x53397c2eU, 0x7139228U, 0xae78a33dU, 0x88f724b5U, 0x52af91daU, 0x5fad7cb5U, 0xa92d5dcfU, 0xb7ebd693U, 0x644cc2ddU, 0x3ff80023U, 0x51b40035U, 0x2f4e0027U, 0xe67b000dU, 0x44f78011U, 0xfcaf402fU, 0x2caee02dU, 0x94abb00cU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xf0000000U, 0x68000000U, 0x14000000U, 0x86000000U, 0x8f000000U, 0x3a800000U, 0x7e400000U, 0xa0200000U, 0xe5f00000U, 0xb1f80000U, 0xeaa40000U, 0x33b60000U, 0xe5df0000U, 0x79538000U, 0x654d4000U, 0x21fba000U, 0xb2a1b000U, 0xafb63800U, 0x87d9f400U, 0x18570200U, 0xc4cc9900U, 0xe3396b80U, 0xe3c3b5c0U, 0xd0e5b820U, 0xad94b430U, 0xe32ca238U, 0xf82d293cU, 0x84af539aU, 0x95ea41c5U, 0xff4aba01U, 0xcfc2d13U, 0x923c9b6U, 0x80719ce3U, 0x8d396b92U, 0xb8c3b5ccU, 0x8c65b815U, 0xacd4b415U, 0x118ca220U, 0x779d291fU, 0x1377538dU, 0x15be41c6U, 0x4784ba2bU, 0x7dc72d1aU, 0xe3e649b9U, 0xe513dcc2U, 0x64694ba6U, 0x858b45deU, 0x319e2029U, 0x7c73f038U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x90000000U, 0x48000000U, 0x4c000000U, 0x2a000000U, 0xdd000000U, 0x49800000U, 0xbec00000U, 0x55600000U, 0x8a300000U, 0x12680000U, 0xf4e40000U, 0xc8f60000U, 0x550f0000U, 0x37d08000U, 0xbd1c4000U, 0xa4296000U, 0x14c7d000U, 0x4865a800U, 0x23b3ac00U, 0x3caa6600U, 0xe9806300U, 0xec32d80U, 0x6d65dd40U, 0x1e352820U, 0x3c6fec30U, 0x4fe30638U, 0x7677b324U, 0x7f4e8592U, 0x95f27153U, 0xdc894e2aU, 0x69108f07U, 0x7878abaaU, 0x661a2e4bU, 0x4aaccda7U, 0x96814d41U, 0x36416016U, 0x2023d01eU, 0x6093a80aU, 0xe6bcac0dU, 0x437ae600U, 0x189c2329U, 0x80ea4db5U, 0xa4a20d60U, 0x1fd08007U, 0xa11c4020U, 0x2629602bU, 0x15c7d02eU, 0x63e5a80eU, 0xc73ac25U, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0xa8000000U, 0xbc000000U, 0x6a000000U, 0x6d000000U, 0x95800000U, 0xc9c00000U, 0x90200000U, 0x4b900000U, 0xf8c80000U, 0x1da40000U, 0x86520000U, 0x76eb0000U, 0xbd368000U, 0x441f4000U, 0xe60ae000U, 0x9d07d000U, 0x4d872800U, 0xedc0cc00U, 0xbe22de00U, 0x58974900U, 0xd6484080U, 0x46e5b040U, 0x2731a820U, 0xf11f8c10U, 0x57883e18U, 0x7ac09914U, 0xcea768aaU, 0x88d17c6fU, 0x1da9763aU, 0xe457c50bU, 0xd7ecfebdU, 0xdab56966U, 0xa4d8a0aeU, 0x9dad606dU, 0xa452001cU, 0xb7eb0018U, 0x8ab68036U, 0xcdf4014U, 0x21aae03bU, 0xce57d037U, 0xdaef2838U, 0x1f34cc09U, 0xc518de33U, 0xb1884906U, 0x85c4c09aU, 0x2225f052U, 0x297c833U, 0x43481c3cU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0x48000000U, 0x7c000000U, 0x5a000000U, 0x2b000000U, 0xfc800000U, 0xa1c00000U, 0x8ce00000U, 0xa7900000U, 0x99a80000U, 0x8c640000U, 0x9c560000U, 0xde4f0000U, 0x67718000U, 0xec3c4000U, 0xa2c8e000U, 0x6b55000U, 0x80da1800U, 0xb55a8400U, 0xd71a1e00U, 0x70b99f00U, 0x730b6880U, 0x22508b40U, 0xeb4b9820U, 0x3ef6c430U, 0xc7afe38U, 0x4a68cf2cU, 0x27877092U, 0x35450f5fU, 0x1200636U, 0x89731b3aU, 0x21397687U, 0xcf4d1444U, 0xc0f6f091U, 0x19794f46U, 0x43e8e628U, 0x3fc64b35U, 0xe9e36eb2U, 0x617906cU, 0x4decee9eU, 0x42c0d077U, 0xcc638ebfU, 0xbc56c05cU, 0x8e48f691U, 0x9f715458U, 0xd83e10b5U, 0x84cc1f64U, 0x77b2fe16U, 0x575ccf3cU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xf0000000U, 0xf8000000U, 0xa4000000U, 0x7e000000U, 0x71000000U, 0xc7800000U, 0xb5c00000U, 0x54200000U, 0xa1b00000U, 0xa4580000U, 0xe7a40000U, 0x22720000U, 0x7d7d0000U, 0xab938000U, 0xc4edc000U, 0xdc7c2000U, 0x24127000U, 0x8d2b4800U, 0xa25d9c00U, 0x72a01e00U, 0x3bf4c900U, 0x49bf6180U, 0xc034b4c0U, 0x7498c820U, 0x52005c10U, 0x13043e28U, 0xcc82b93cU, 0x8d4629beU, 0xaf6428e9U, 0x23d3563fU, 0x9a0d550cU, 0xc76d7f99U, 0x7bd7dd1U, 0xa934298bU, 0x471928d1U, 0x91c0d63eU, 0x6a209509U, 0x70b15fafU, 0x93df0de7U, 0xaa6761beU, 0xd250b4fcU, 0xa2cac838U, 0x7ecd5c2dU, 0xe4cfbe19U, 0x4bcb7927U, 0xd4809abU, 0x870b58dbU, 0xc2eb9e0aU, 0x497d093eU, 0x80000000U, 0x40000000U, 0x20000000U, 0xd0000000U, 0x88000000U, 0xd4000000U, 0x46000000U, 0x63000000U, 0x1c800000U, 0x3cc00000U, 0xb4e00000U, 0x77f00000U, 0x58780000U, 0xa4640000U, 0x11320000U, 0x3d990000U, 0x3a128000U, 0x820e4000U, 0xd95ba000U, 0x92f2b000U, 0x47fc5800U, 0x7425c400U, 0xc1131600U, 0xa28d5f00U, 0x879d4b80U, 0x5b104dc0U, 0x138ed820U, 0x9e1b8410U, 0xc850b608U, 0xf2bef34U, 0xb5cb13a2U, 0x153889f5U, 0xe7c54e31U, 0x44659b08U, 0xa136dd8fU, 0x459e52fbU, 0xb610b3afU, 0x980a39f8U, 0x2859162fU, 0xab705f15U, 0x4bdcba9U, 0xe0870dc1U, 0x3ec7f830U, 0x39e77400U, 0xc774e3eU, 0xb63c9b2eU, 0x9b445d9dU, 0x88a012f5U, 0x4dd313b4U, 0x6e6c89f4U, 0x7c6f4e2aU, 0x19689b3fU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0xb8000000U, 0xcc000000U, 0x1a000000U, 0x9000000U, 0x18800000U, 0x70400000U, 0x7ca00000U, 0xc0100000U, 0x89b80000U, 0x86240000U, 0x55560000U, 0xa79f0000U, 0x37718000U, 0xcccbc000U, 0x47ed6000U, 0x843f5000U, 0x3ce08800U, 0xc4b22400U, 0x65ac1200U, 0xa5998d00U, 0x6277b480U, 0x264837c0U, 0xfaa90820U, 0x8e1de430U, 0x53b77238U, 0x3a29dd2cU, 0x425ebcaeU, 0x6d15d3f3U, 0x8f3e7a26U, 0x71643932U, 0x5e71cebeU, 0xa4480ef0U, 0x6faec691U, 0x849aeaf3U, 0x5ef034bcU, 0x880cf7ffU, 0xe10de825U, 0x898d741aU, 0xa1cc9a02U, 0xa16ba91eU, 0xc37ba69dU, 0x8fc1baedU, 0xb66bca5U, 0x2771d3c6U, 0xe4c87a37U, 0x63eb390bU, 0x5a384eb7U, 0x5be7cecfU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x70000000U, 0xb8000000U, 0x84000000U, 0xb2000000U, 0x29000000U, 0xcf800000U, 0xd400000U, 0x57200000U, 0x45900000U, 0x2e880000U, 0xb2a40000U, 0x55d60000U, 0x1c2d0000U, 0x27778000U, 0xe9fbc000U, 0x4b5d2000U, 0x768c1000U, 0x26a38800U, 0x8fd2dc00U, 0x792eba00U, 0x66f59100U, 0xfbbe2080U, 0x48f8e640U, 0xd8dc0820U, 0x9dcd1c30U, 0x22859a28U, 0x10c4811cU, 0xa36228aeU, 0x1535fa61U, 0x5a59920cU, 0xfd099d3aU, 0x39e7b29bU, 0x81f17b5fU, 0x4b3bba9bU, 0xc13c6740U, 0xac3e20afU, 0x71b8e64aU, 0x25fc0800U, 0x55d1c09U, 0xc98d9a36U, 0x220811cU, 0xdc1428a8U, 0x68c8fa59U, 0xcb061236U, 0xee865d0cU, 0x5ec49292U, 0x1c646b41U, 0x31b1b2a9U, 0x99c7b64U, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0x8000000U, 0x34000000U, 0x3a000000U, 0xd000000U, 0x7f800000U, 0xbb400000U, 0x9a00000U, 0xd8700000U, 0x37080000U, 0xb8240000U, 0x74320000U, 0x5c2b0000U, 0xdc978000U, 0xcdda4000U, 0x3bdea000U, 0x70dc5000U, 0x6c5d2800U, 0xef9cdc00U, 0x27faca00U, 0x6ef4500U, 0x61738f80U, 0x328eba40U, 0x6e62a820U, 0x72129c10U, 0x371e6a18U, 0xd63c151cU, 0x978b2782U, 0x75e3264dU, 0xeb51422eU, 0x7fbbc913U, 0x77ce6d87U, 0x18c22372U, 0x8ce66da0U, 0x8ed6236bU, 0xd9fc6dbbU, 0x79e92361U, 0x47f1edb8U, 0xbc4c6378U, 0xd982cd81U, 0xe8457347U, 0x5924c5a8U, 0x5db4bf5eU, 0xfc6a07afU, 0xd1b13676U, 0xda68ca1aU, 0xc2b44506U, 0xeaec0f8fU, 0x3770fa63U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x70000000U, 0x68000000U, 0x3c000000U, 0xba000000U, 0xbf000000U, 0x9a800000U, 0xd9400000U, 0x5c600000U, 0x41100000U, 0x5f680000U, 0xa8e40000U, 0x61560000U, 0xfc8b0000U, 0x65378000U, 0x499d4000U, 0xac5ee000U, 0xfc7c5000U, 0xbc8fb800U, 0xc537b400U, 0x599eda00U, 0xb4593b00U, 0xa8782c80U, 0x3a8fb940U, 0xc0303820U, 0x7c1ef430U, 0xf79e3a18U, 0x2d5a6b1cU, 0x27fe149aU, 0xde4a4d4fU, 0x8b91820eU, 0x3e2ddf1fU, 0xb080cebeU, 0xbe43766aU, 0xf2e1aeadU, 0x6e56666fU, 0x6e0ef681U, 0xf0728269U, 0xc7fe149cU, 0x6e4a4d6aU, 0x83918202U, 0x722ddf0eU, 0x6280ceb6U, 0x3d43765fU, 0xd261ae92U, 0x8166678U, 0xa8eef6bfU, 0x68228270U, 0xc4f6149dU, 0x87be4d61U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0x28000000U, 0x4c000000U, 0xda000000U, 0xd3000000U, 0xad800000U, 0xd1c00000U, 0x6fa00000U, 0xb8300000U, 0xf1b80000U, 0x9c240000U, 0x9cf60000U, 0x629d0000U, 0x3f528000U, 0xc0af4000U, 0xbdeb6000U, 0x210a5000U, 0xd8d8d800U, 0x60368c00U, 0x85bc9e00U, 0x82214500U, 0x9f5dd80U, 0xee1f6bc0U, 0xdc125820U, 0x94dcc30U, 0x68b9fe28U, 0xaaa21534U, 0xdcb1858aU, 0xfeffa7d3U, 0x5fc12616U, 0xb2a49904U, 0x8b51b83U, 0x30fae2c0U, 0xe2c2fbb1U, 0x7226f2cdU, 0x31f5c382U, 0x2a186ed7U, 0x9a10658eU, 0x284eb7fbU, 0x5a3c9e20U, 0xce1453dU, 0xb1d5ddacU, 0x84ef6bc8U, 0xc78a583dU, 0xb099cc0dU, 0xb057fe3cU, 0x3f2b152dU, 0x232d058cU, 0x1129e7c5U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0xd8000000U, 0xc000000U, 0xee000000U, 0x9d000000U, 0xf2800000U, 0x18c00000U, 0xd4e00000U, 0xf3700000U, 0x11e80000U, 0xdb640000U, 0x29360000U, 0xf5c90000U, 0xf8f28000U, 0xf1a8c000U, 0x40456000U, 0x8b27f000U, 0x5a132800U, 0x73d97400U, 0xbd2d7600U, 0xdd802f00U, 0x81407f80U, 0x8fa32140U, 0xf3d7a820U, 0x6bb8b430U, 0x139a9608U, 0xe60f1f34U, 0x5f9637b6U, 0xfe9da543U, 0xdc89f61bU, 0xb351ef17U, 0x187f9fb4U, 0x84f81172U, 0xc13fe023U, 0xc75b300fU, 0xfce84837U, 0xe1e38425U, 0xc5f2de00U, 0x132c9b38U, 0xa084e9b0U, 0x83c13e67U, 0x9f651f88U, 0xf334d162U, 0x7acc8001U, 0x7175c019U, 0x52e9e02bU, 0x9ce2300aU, 0xc772c837U, 0x3ef4418U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0x8000000U, 0x5c000000U, 0xf6000000U, 0x69000000U, 0xf800000U, 0x59c00000U, 0x22600000U, 0x6ef00000U, 0x73280000U, 0xb4e40000U, 0x10b60000U, 0x48f0000U, 0xb6718000U, 0x306e4000U, 0x66c1e000U, 0xd4e43000U, 0x60b40800U, 0xec8f1c00U, 0x5a713e00U, 0xce6ebb00U, 0x53c7bb80U, 0x2d619f40U, 0x50738820U, 0xc16e5c30U, 0x6d415e38U, 0x9f24cb2cU, 0x89d25382U, 0x4efab357U, 0xe01ebe1dU, 0x67abfb2aU, 0x59a1dbbbU, 0x4f94ef7aU, 0x6d5fe02aU, 0x488f303cU, 0xd8738819U, 0x5d6e5c1bU, 0x7b415e05U, 0x4624cb00U, 0x8e525398U, 0x4b3ab34dU, 0x347ebe26U, 0x605bfb3eU, 0x2509dbacU, 0xa2b0ef4dU, 0x5f89e005U, 0x22f03035U, 0x1d2a080cU, 0xd9e41c09U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0xd8000000U, 0x2c000000U, 0xfa000000U, 0x3000000U, 0xce800000U, 0x31c00000U, 0xff600000U, 0xb4f00000U, 0x5c080000U, 0xae40000U, 0xf7b60000U, 0xd0ab0000U, 0x3e768000U, 0xf3c8c000U, 0x98866000U, 0x8c35000U, 0x52e5d800U, 0x1bb59400U, 0x4aa89e00U, 0x6d728300U, 0xe54a0380U, 0x85447640U, 0xda55820U, 0xe5165430U, 0x89387e18U, 0x71891314U, 0x65a1bbb6U, 0x8116b24bU, 0xe73e1e1eU, 0xf48a4330U, 0x8a2463abU, 0x51532658U, 0x1d1e8029U, 0x8ddcc016U, 0x53386031U, 0x828c5016U, 0x43255838U, 0x14d65433U, 0x16587e0eU, 0x95791311U, 0xe1a9bb82U, 0xa7f2b24cU, 0xea881e36U, 0x2721432fU, 0x7ad2e392U, 0x935be671U, 0x7af8e034U, 0x31ef902cU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x30000000U, 0x78000000U, 0xc4000000U, 0xf2000000U, 0x9f000000U, 0x74800000U, 0x87c00000U, 0x18200000U, 0xfa700000U, 0xa080000U, 0x3ba40000U, 0x75360000U, 0xc3eb0000U, 0x84f58000U, 0x16cdc000U, 0xc5012000U, 0xa7801000U, 0xdd443800U, 0x6e40400U, 0x83d06e00U, 0x583a1900U, 0x28cfe780U, 0xb4029640U, 0x2a07b820U, 0xb02c430U, 0xce84ce18U, 0xa4c7c90cU, 0x5aa2ff9eU, 0x10b28271U, 0xf9adee1cU, 0x3293d917U, 0xe0d8c785U, 0x1a19866dU, 0x1be0038U, 0xe48f003fU, 0xf638026U, 0x796c025U, 0x5f5ca01eU, 0x3359d020U, 0x8d5b181bU, 0x3c5b141cU, 0xd1dfd62eU, 0x379cdd06U, 0x87fd29acU, 0x64ee5f4fU, 0x9470c7a3U, 0x330d866dU, 0xa20001eU, 0x95700008U, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0x48000000U, 0xbc000000U, 0xae000000U, 0x1000000U, 0x19800000U, 0xfcc00000U, 0xc7600000U, 0x8bf00000U, 0xca180000U, 0x67e40000U, 0xeab20000U, 0x9bbb0000U, 0x20768000U, 0xe9d84000U, 0xc002e000U, 0x2005f000U, 0x30014800U, 0x1807ac00U, 0xf400d600U, 0x1203d300U, 0xaf01e380U, 0x1881bec0U, 0xe545c820U, 0x3ba4ec10U, 0x4c94b618U, 0x41ee6314U, 0xadfa4b92U, 0x8d57e2efU, 0x710e560bU, 0xbbcf9310U, 0xc9a9039eU, 0x29db4eebU, 0xe0000003U, 0x1000001dU, 0x28000001U, 0xec00000dU, 0xe600002eU, 0xbd000036U, 0xb7800012U, 0xfdc00018U, 0xdee00004U, 0x7730002eU, 0xd780007U, 0xec140002U, 0x20aa0007U, 0xfc5f0027U, 0xcac48021U, 0x72634028U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x90000000U, 0x8000000U, 0x84000000U, 0xae000000U, 0x89000000U, 0xea800000U, 0xbb400000U, 0xb0a00000U, 0x32500000U, 0xd5080000U, 0x67240000U, 0x75960000U, 0xabef0000U, 0xbd508000U, 0x828e4000U, 0xe0e72000U, 0xeb77f000U, 0xe19b0800U, 0x424bf400U, 0x4d82ea00U, 0x18c4ed00U, 0x1603680U, 0xa9b3fa40U, 0x5ffd8820U, 0x47ab430U, 0x69bd4a38U, 0x30595d24U, 0x89aa1e82U, 0x2f70fe61U, 0x6f9cea0bU, 0xbb4fed12U, 0x3f06b682U, 0x2f82ba4aU, 0x9bc2280eU, 0xbce7041dU, 0xe9776226U, 0x329a591fU, 0x17cb7ca5U, 0x1945a765U, 0xd3a71688U, 0x1fd40a7eU, 0x9dce802fU, 0x8e454019U, 0xc821a033U, 0x5216b033U, 0xb42ca820U, 0xafb2443cU, 0xe2fec234U, 0x38f8e936U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0x98000000U, 0xb4000000U, 0xbe000000U, 0xe3000000U, 0xe800000U, 0xa9400000U, 0x9f600000U, 0xd4300000U, 0x8b180000U, 0x2ee40000U, 0xf1f60000U, 0xec390000U, 0x52328000U, 0xcc1ac000U, 0x2660a000U, 0xdfb57000U, 0x5bdad800U, 0x78475400U, 0x68e27a00U, 0x96f74300U, 0x34bda580U, 0xe476cac0U, 0xcffe5820U, 0xb2149430U, 0x98485a08U, 0xe5ccf334U, 0x3a09dda6U, 0x4829eeedU, 0xf57a7a0fU, 0x65534308U, 0xc42ba58bU, 0xef7fcadeU, 0x8054d821U, 0x4daa5428U, 0x6ebefa05U, 0xe1708307U, 0xb6798599U, 0x7bd07afcU, 0xd56ea03cU, 0x1418700eU, 0x72665820U, 0x91b09422U, 0xf0de5a2bU, 0x5ac5f33dU, 0xcba35d83U, 0x54972ee5U, 0xd0cda1bU, 0xc8af332fU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x50000000U, 0x38000000U, 0xfc000000U, 0x42000000U, 0x47000000U, 0xdd800000U, 0x8c400000U, 0xa3e00000U, 0xbfd00000U, 0xd8f80000U, 0x1b640000U, 0xb9120000U, 0xf2df0000U, 0x27168000U, 0x7dbc000U, 0x3594e000U, 0xc21a9000U, 0x9c30f800U, 0x27298c00U, 0x239cb200U, 0xf2744700U, 0x73cdc280U, 0x29cefdc0U, 0x62cc7820U, 0x75494c10U, 0x2a0cd238U, 0xd26a1714U, 0x18ff5a8eU, 0xbb6621ffU, 0x914d230U, 0x9ade1701U, 0xe3155a8fU, 0xb9dd21f7U, 0x30905206U, 0x589ad700U, 0xcdf73a9eU, 0x88c71c3U, 0x3fac4a37U, 0x955dcb30U, 0xb0517089U, 0x8bbabaebU, 0x2901baa2U, 0xa087b1faU, 0xac0aa29U, 0xe0235b0fU, 0xef7388b6U, 0xe54c36f3U, 0xb20b88a9U, 0x9e6836d7U, 0x80000000U, 0x40000000U, 0x20000000U, 0xd0000000U, 0x48000000U, 0x94000000U, 0x2e000000U, 0x45000000U, 0x6800000U, 0x67c00000U, 0xb8e00000U, 0x4ad00000U, 0x1ae80000U, 0xe5640000U, 0x96920000U, 0xef490000U, 0x52928000U, 0xc9484000U, 0xa391a000U, 0x31cdf000U, 0xc9556800U, 0x1ba81400U, 0xca450e00U, 0xfca7cf00U, 0x63705280U, 0x171be140U, 0xd1bde820U, 0x99cd5410U, 0xed542e08U, 0x8dab7f34U, 0x83461a92U, 0x8264565U, 0xfbb42e2bU, 0xc27b7f01U, 0xbf2e1a89U, 0x5a82456dU, 0x9dc62e1cU, 0xf3e27f27U, 0xd9549a85U, 0x33ae055cU, 0xae458e16U, 0x4aa68f17U, 0xfa7372b9U, 0xab9e5145U, 0xdd79201dU, 0x62a8b019U, 0xc6c4483aU, 0x4864a40aU, 0x94134633U, 0xce8a6b08U, 0xeb7194b0U, 0xe319ca71U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0xd8000000U, 0x54000000U, 0x1a000000U, 0xe9000000U, 0x34800000U, 0xc2400000U, 0x2b200000U, 0x98b00000U, 0x22880000U, 0x14a40000U, 0xa3760000U, 0x8d6b0000U, 0xd0728000U, 0x90e8c000U, 0x46b5a000U, 0xa9885000U, 0x2d268800U, 0x47b38400U, 0x10b0200U, 0x19663100U, 0x1b957180U, 0x8639ee40U, 0x702a0820U, 0xc8d44430U, 0xbd9a2218U, 0x58dda134U, 0x747cd9b6U, 0x930efa55U, 0xbc642226U, 0x112a10aU, 0x67785995U, 0x5e8d3a44U, 0xf2a3021cU, 0x6c723103U, 0x16eb7196U, 0x59b6ee4bU, 0xea0e8833U, 0xf0e78436U, 0x27550220U, 0x5e59310cU, 0xa339f1a2U, 0xaaae2e4aU, 0x4993280fU, 0x433bd41eU, 0xbaad8a29U, 0xf195b523U, 0xc73e7383U, 0x78afdf5bU, 0x80000000U, 0x40000000U, 0xe0000000U, 0xb0000000U, 0xb8000000U, 0x34000000U, 0x2a000000U, 0x93000000U, 0x6e800000U, 0x89400000U, 0x9200000U, 0xaa900000U, 0xc4380000U, 0x9aa40000U, 0xec520000U, 0xdddf0000U, 0xfcd18000U, 0x1d9fc000U, 0x5072a000U, 0xd4ced000U, 0x862a5800U, 0x4ad95400U, 0x4051da00U, 0xd3ddf100U, 0xadd43080U, 0xdc1d13c0U, 0x11b1d820U, 0xd9ad9410U, 0xf218fa38U, 0x50b7e12cU, 0xf02f48aeU, 0x8fda57cdU, 0xfbd17a2aU, 0x91c2134U, 0x4237e8a3U, 0x3f6f87ceU, 0xbbf8a20cU, 0x3ec5b537U, 0x8de51283U, 0x1c7366eeU, 0x6acc6aaeU, 0x6f2b22c8U, 0xbf5d48afU, 0x2b9557f5U, 0x4db8fa08U, 0xb767e100U, 0x4f374884U, 0xa8ee57caU, 0x2f3b7a01U, 0x6027210eU, 0x1f1468afU, 0x4fff47f5U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0xc8000000U, 0x6c000000U, 0x1e000000U, 0x2d000000U, 0x71800000U, 0x9c00000U, 0x9600000U, 0x4a700000U, 0x6f580000U, 0xc0a40000U, 0xe3120000U, 0xb52f0000U, 0x17ff8000U, 0x87b04000U, 0x243e6000U, 0x91d07000U, 0xcccea800U, 0xdbcdac00U, 0xb54e5e00U, 0x1e0e9300U, 0x32295780U, 0xc17c88c0U, 0x88f0c820U, 0x7a1ddc10U, 0x5180f638U, 0xd9c33f1cU, 0x516709b2U, 0x9e721bdbU, 0xd5599fa7U, 0x9fa154dbU, 0xa1903e04U, 0xe06ee30eU, 0x66dfff88U, 0xcd6524d5U, 0x874960eU, 0x74584f30U, 0x8024219bU, 0x4d50f7f8U, 0xf48e2189U, 0x3b6bf7faU, 0x865ba18fU, 0xf320b7c1U, 0xf1d041a6U, 0xfccb87feU, 0xf3cd09bfU, 0xa9491bc5U, 0xc80c1faaU, 0x732a14dbU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x70000000U, 0x68000000U, 0xc4000000U, 0xc6000000U, 0xa7000000U, 0x71800000U, 0x3400000U, 0x2c200000U, 0x41700000U, 0xfc580000U, 0xf640000U, 0x5d520000U, 0x752d0000U, 0x473f8000U, 0xfc354000U, 0x4b792000U, 0x8594b000U, 0x1f4ff800U, 0xeaefec00U, 0x8cdd8a00U, 0x4aa22900U, 0xbbb61f80U, 0xc73f84c0U, 0xbc36d820U, 0xeb7b5c10U, 0xf5927228U, 0x774dc51cU, 0x2eeb959aU, 0x4addadf1U, 0xeda0c791U, 0xca34d8f9U, 0xc47caa14U, 0x9012990cU, 0xaa0be7b9U, 0x9cd68fdU, 0x782cd234U, 0x73b8350bU, 0x3ff74d92U, 0xaa9ff1e8U, 0x360735bcU, 0x8f055dceU, 0x15839f9fU, 0xb543c4d7U, 0xe3227821U, 0xf4f7ac19U, 0x391b2a2dU, 0x8443d924U, 0x6da0c7a5U, 0x8a34d8f4U, 0x80000000U, 0x40000000U, 0x60000000U, 0xd0000000U, 0xf8000000U, 0x24000000U, 0x36000000U, 0x7000000U, 0xe6800000U, 0xb8400000U, 0xc2e00000U, 0xcab00000U, 0x1a80000U, 0x2a40000U, 0x6c520000U, 0x9d1b0000U, 0xd40a8000U, 0x7071c000U, 0x6d082000U, 0xbdf03000U, 0x69cb7800U, 0xfa56d400U, 0x6a19d200U, 0x7a8f5f00U, 0xc430f980U, 0x45ed8b40U, 0x62435820U, 0xbfe6e410U, 0xa132aa18U, 0x9a698b34U, 0x57812bbeU, 0x19c6d449U, 0xfc21a1adU, 0x60106f51U, 0xf1fb7201U, 0xedbeaf0aU, 0x595ba196U, 0xf4ef6f4fU, 0xc3c3f213U, 0x81246f18U, 0xb9101b7U, 0x6a3a9f7cU, 0xb89aaa22U, 0x2ccd8b19U, 0x95d32bbeU, 0x77ddd468U, 0xab21a6U, 0x8b21af6eU, 0x8e935231U, 0x25be9f32U, 0x1558d980U, 0x7eedbb71U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0xa8000000U, 0xa4000000U, 0xc2000000U, 0xa5000000U, 0x55800000U, 0xcd400000U, 0x49600000U, 0x85900000U, 0x47a80000U, 0x90240000U, 0x76f60000U, 0x4b390000U, 0xf40c8000U, 0xe4974000U, 0x202a2000U, 0x60639000U, 0x7616e800U, 0xcdebcc00U, 0x39c1da00U, 0xc3a23300U, 0x2cb78880U, 0x6ad86b40U, 0xf55cc820U, 0xe9185c30U, 0xbfff3208U, 0xe62dff04U, 0xd76052aaU, 0xe935869U, 0xe12fc090U, 0xd7e37759U, 0xe57da3dU, 0x790b3307U, 0xd51308b0U, 0xf6b2b4cU, 0x9c00e82bU, 0xe02cc14U, 0xe3055a30U, 0x2281730cU, 0x95c3a890U, 0x75a6fb42U, 0xc3b0a01bU, 0x2e5dd004U, 0x798480cU, 0x6c3b1c32U, 0xe48b1216U, 0x4c536f13U, 0x1c0c3a9fU, 0xa096d476U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0x88000000U, 0xa4000000U, 0x3a000000U, 0xbb000000U, 0x2b800000U, 0x95c00000U, 0xb7600000U, 0x57300000U, 0xb9580000U, 0xdea40000U, 0xa6560000U, 0xd3690000U, 0x51798000U, 0x6bb64000U, 0x591a2000U, 0x5d015000U, 0x66821800U, 0xb413c00U, 0xb025de00U, 0xc915f300U, 0x794b1d80U, 0x936de8c0U, 0xb1783820U, 0xfbb06c30U, 0x611fc608U, 0x7100cf2cU, 0xf880c3a2U, 0x8a451be9U, 0x20a4a5aeU, 0x7756c4deU, 0x5bea5e22U, 0x733ab339U, 0x5f10bd87U, 0x9c4ef8d0U, 0x19ee0022U, 0x43d0000U, 0x7a978025U, 0xb08b4013U, 0x120da011U, 0x734a1003U, 0x606fb81bU, 0x1efb2c1bU, 0xe4726614U, 0xe57adf24U, 0xa9b77bbcU, 0xee1a37c9U, 0x5880c392U, 0xfa451beeU, 0x80000000U, 0x40000000U, 0x20000000U, 0x90000000U, 0x48000000U, 0xc4000000U, 0xb2000000U, 0xcd000000U, 0xcc800000U, 0x71400000U, 0x7a00000U, 0x78300000U, 0x27480000U, 0x94e40000U, 0x9a920000U, 0xe7f90000U, 0xa8e88000U, 0x48d44000U, 0xbfdd2000U, 0x661c1000U, 0x72fea800U, 0xa86d0400U, 0x6f93ba00U, 0x577e0500U, 0x57ae2d80U, 0x2c77a440U, 0xf86b8820U, 0x47951410U, 0x237f1208U, 0x3daa0124U, 0x6d751792U, 0x42ede171U, 0x49d0858cU, 0x255aa063U, 0xf858321bU, 0x3cdb1128U, 0xa9993f9bU, 0x8c39a54bU, 0x710c9f97U, 0x5ec1f577U, 0x9671791U, 0x5954e162U, 0xa1805a2U, 0xf4fee055U, 0x2f6d1231U, 0x72130114U, 0xd4bd97b6U, 0x9a49a14cU, 0xe065a5bbU, 0xd7d2b06eU, 0x4e5c9a2fU, 0x23db1520U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0x48000000U, 0xac000000U, 0xb2000000U, 0x8f000000U, 0xd7800000U, 0x14c00000U, 0x9b600000U, 0x70300000U, 0x70780000U, 0x35a40000U, 0xe8560000U, 0xb5cf0000U, 0xa61d8000U, 0x75104000U, 0x276c6000U, 0xc5cf1000U, 0xce1db800U, 0x9149c00U, 0xed68d600U, 0xaecdf300U, 0x79de580U, 0x20d229c0U, 0x2e89d820U, 0x1dbf8c30U, 0xf8436e38U, 0xfe266f0cU, 0xc690b392U, 0xedab9aebU, 0x83ae5d8cU, 0xd6adb5d3U, 0xf22a8e2dU, 0xfb6d3f39U, 0x1fcf6b8cU, 0x3d1b16fbU, 0x1490b382U, 0x92ab9af5U, 0xfc2e5dbbU, 0x5e6db5f7U, 0x934a8e30U, 0xa85d3f13U, 0xa376bb5U, 0x937f16e4U, 0xb026b3beU, 0x43949adfU, 0xb12bdd8fU, 0x6ee9f5ddU, 0x2c08ee24U, 0xedf92f27U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0x18000000U, 0x64000000U, 0x76000000U, 0xdb000000U, 0x15800000U, 0x37c00000U, 0x63a00000U, 0xa5b00000U, 0xbbf80000U, 0x6a640000U, 0xa1160000U, 0xb9cd0000U, 0x9b5a8000U, 0x7e52c000U, 0xfb282000U, 0xbb0c3000U, 0x927a9800U, 0x2fa44c00U, 0x1fb4ae00U, 0x1afd3500U, 0x7ee23980U, 0x52529dc0U, 0x312ab820U, 0xd20c7c30U, 0xfaf83628U, 0xcee47934U, 0x3a541786U, 0x9d2968d9U, 0xd80ea1bdU, 0x33fbd1c6U, 0x7664960dU, 0xc3138909U, 0xdcca2fb6U, 0x29ded4c4U, 0x4e123795U, 0x24c58c5U, 0xb398b9b8U, 0xae705dd1U, 0xaa5a9835U, 0x12d44c26U, 0x1c6cae3bU, 0x8de93506U, 0x7c2c39bcU, 0xac8b9dddU, 0xb0be3829U, 0x3687bc15U, 0xf644961cU, 0x4a63892fU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xf0000000U, 0x38000000U, 0xdc000000U, 0x82000000U, 0xcf000000U, 0x6a800000U, 0x4dc00000U, 0xa0e00000U, 0x4f500000U, 0xca180000U, 0xc3240000U, 0xdab20000U, 0x5ccd0000U, 0x5c7b8000U, 0x3b7c000U, 0xdf49e000U, 0x4a3a9000U, 0x39163800U, 0xe0bb7400U, 0x94d61e00U, 0x105b2f00U, 0x13817680U, 0x3e401ac0U, 0x8ea7d820U, 0xa9f5e410U, 0x77ea2628U, 0xd2c95b3cU, 0x997ee88eU, 0xe231f5f7U, 0x560cce80U, 0xd21caee3U, 0xaf202612U, 0xc0b05b3fU, 0xbfcf688eU, 0x8cff35d8U, 0x5d74aebcU, 0x9728fee4U, 0x87ae7e04U, 0x396f7f1bU, 0x210f2e83U, 0x249f3ecbU, 0xc0e79e23U, 0x5f55ef25U, 0xa2191698U, 0xd7244ac3U, 0xbcb18018U, 0xcdcec034U, 0x7bf86036U, 0xebf45031U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0xa8000000U, 0xe4000000U, 0x3e000000U, 0xb7000000U, 0xaf800000U, 0xd6400000U, 0x71e00000U, 0x69300000U, 0xdf980000U, 0x75a40000U, 0xe5d60000U, 0x682f0000U, 0x98f98000U, 0xea574000U, 0x2e6e2000U, 0x111f7000U, 0x7f677800U, 0x83f61c00U, 0x9bae200U, 0xbc330700U, 0x251fed80U, 0x9960e2c0U, 0x98f15820U, 0xcc3d6c30U, 0x4b739a38U, 0xa87e1b2cU, 0xb7928faaU, 0x57cfa5f9U, 0xecf15afU, 0xce4abeddU, 0x1b8a1a33U, 0xd6295b29U, 0xeffcaf8eU, 0xa5d0d5cfU, 0x48286db2U, 0xc8fca2f9U, 0xf250f805U, 0x626a5c1eU, 0xcb1b4203U, 0xf6643700U, 0x9b773585U, 0x707aced7U, 0x1b94e215U, 0x3dc8070fU, 0x2fc86d92U, 0x32cca2ccU, 0x5c48f805U, 0xc68e5c16U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xb0000000U, 0xd8000000U, 0x4000000U, 0x2a000000U, 0x2f000000U, 0xc1800000U, 0x5fc00000U, 0xc7200000U, 0x7300000U, 0x76e80000U, 0x9ee40000U, 0x79160000U, 0xa15d0000U, 0x1b498000U, 0x4d94c000U, 0xa81b2000U, 0x562dd000U, 0x90403800U, 0xede3ec00U, 0x56930e00U, 0x5b9d5100U, 0x82edad80U, 0xce43540U, 0x42131820U, 0x22da3c30U, 0xb78d3628U, 0x6537bd2cU, 0xf5e923b6U, 0x964a441U, 0x97d215aaU, 0x7afe197bU, 0xa93ab638U, 0x481a7d0bU, 0x862d83afU, 0x5840b46cU, 0x81e08d81U, 0xa094e55dU, 0x5a9aa02cU, 0x466d1028U, 0xbda51819U, 0x1b773c28U, 0xbd0cb63aU, 0x1777d39U, 0x8a0c039dU, 0x64f07468U, 0x4fcdadacU, 0x54d4354bU, 0x8d7b1828U, 0x57fe3c3fU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0x68000000U, 0x5c000000U, 0xae000000U, 0xad000000U, 0x5a800000U, 0x9ac00000U, 0xcea00000U, 0xf5b00000U, 0xbdc80000U, 0x99640000U, 0x91960000U, 0x8ab90000U, 0xce0c8000U, 0x67414000U, 0xf9e5e000U, 0x8454f000U, 0x559ea800U, 0x1aff7400U, 0x12694600U, 0x30556d00U, 0x679f9180U, 0x39fd2c40U, 0xf5ed4820U, 0x98128430U, 0x6ffb6e08U, 0xaceb5904U, 0x1093379aU, 0xe63cb157U, 0xfdcc718bU, 0x7960dc5bU, 0xa197603eU, 0xf2b8b012U, 0xfa09c821U, 0x9547c42eU, 0xfae08e1eU, 0x73d2a91aU, 0x95df1f99U, 0x4e9f856fU, 0x297a57b6U, 0x78290172U, 0x4337398aU, 0x310b584eU, 0xeec08e2cU, 0xdca2a921U, 0xc6b71faaU, 0x324b854fU, 0x6d245793U, 0x37f4015cU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x50000000U, 0x88000000U, 0xac000000U, 0x4a000000U, 0x3d000000U, 0x99800000U, 0x9b400000U, 0xdf200000U, 0x3700000U, 0x3980000U, 0x31640000U, 0x49d20000U, 0x61af0000U, 0x8de8000U, 0xc6424000U, 0x56a06000U, 0xf037d000U, 0x20bf2800U, 0xf011ec00U, 0xdb49ea00U, 0x834e4100U, 0xe749bf80U, 0xe14d4ac0U, 0xc64d4820U, 0xeac93c10U, 0x44084238U, 0x4a6ded14U, 0xab3835a2U, 0x3250dbebU, 0x9be9dfb2U, 0x3c7a9adfU, 0x1772603eU, 0x7d98d022U, 0x8261a82dU, 0x5b53ac3fU, 0x9c698a30U, 0x44399128U, 0x52d697a6U, 0x2f2ca6f1U, 0x871ca233U, 0xc3a37d07U, 0x35b3fd9aU, 0xc9ffa7e4U, 0x6633fd98U, 0x2fbfa7d3U, 0xc093fdacU, 0xe78fa7c2U, 0x942bfdb2U, 0x799ba7fcU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xf0000000U, 0xc8000000U, 0xf4000000U, 0xf6000000U, 0xf000000U, 0x76800000U, 0xa7c00000U, 0xb8200000U, 0x1d300000U, 0x3b980000U, 0xa8e40000U, 0x2f960000U, 0x636f0000U, 0x225b8000U, 0x2bc44000U, 0x5226a000U, 0x373000U, 0x8c19b800U, 0x4aa65400U, 0x44f32e00U, 0x98bd0900U, 0xc550a580U, 0x74cf16c0U, 0xf1291820U, 0x413e6430U, 0xc4111638U, 0xb32f1d3cU, 0x983d2bb2U, 0xad912ffdU, 0x5a6e059dU, 0xbbdc26f3U, 0xa86a005U, 0x85c73025U, 0x5121b824U, 0x5cb25406U, 0xd6dd2e01U, 0xb5060914U, 0x738525abU, 0x3c4056f2U, 0x6062381bU, 0xb3521414U, 0xbbcd8e0cU, 0x67ae3911U, 0x16ff1d94U, 0xb43642ddU, 0x5a19b60fU, 0x55a32d07U, 0xa711388U, 0x3783bc2U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x50000000U, 0xe8000000U, 0xe4000000U, 0x96000000U, 0xed000000U, 0x2a800000U, 0xaec00000U, 0x13e00000U, 0xdf900000U, 0x95180000U, 0xdc240000U, 0xd4f20000U, 0x7f4f0000U, 0xcd5e8000U, 0xbb014000U, 0x67822000U, 0x34413000U, 0x522a800U, 0xc0713400U, 0x388ee600U, 0x323f4700U, 0xcf56c080U, 0x2ffd8ac0U, 0xf328820U, 0xba2f0410U, 0x960ace38U, 0x1afb3314U, 0x39b006baU, 0x6ee8fdf9U, 0x4aea6085U, 0x7cedfaebU, 0x21ea0012U, 0xb36b002fU, 0x11ac8006U, 0x704e401aU, 0xd4dca03aU, 0x86407035U, 0xde20881aU, 0xb7f0040fU, 0x4cc4e3dU, 0x831e7332U, 0x712026b8U, 0x1e76cdcdU, 0x818e48b1U, 0x36b98ec8U, 0x8094c610U, 0x649a7739U, 0x566689bU, 0xfb53bec5U, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0xc8000000U, 0x4c000000U, 0x66000000U, 0x1000000U, 0x49800000U, 0x7c00000U, 0x6fe00000U, 0xa3900000U, 0x13880000U, 0xd240000U, 0x7ff20000U, 0x88d90000U, 0xdc98000U, 0x7d004000U, 0xa7816000U, 0x6ac7b000U, 0xf063c800U, 0x6d566c00U, 0x79e96e00U, 0xcf744700U, 0x29d5880U, 0x6fefee40U, 0x6670a820U, 0x9718dc10U, 0x762b2608U, 0x8c966b2cU, 0x570f56b2U, 0x5611953U, 0xa6d5b8b9U, 0xc5281e50U, 0xf612003aU, 0x6a49003dU, 0x77c18021U, 0xc7e44017U, 0x7f93602fU, 0xd8eb010U, 0x88224814U, 0x1c722c23U, 0xe81a0e0aU, 0x2aaaf736U, 0x90d710b6U, 0xdc29c271U, 0xab90a607U, 0x3f8f2b2aU, 0xfb27b68aU, 0x6f6e962U, 0x455f10b8U, 0x200dc25dU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x50000000U, 0xe8000000U, 0x3c000000U, 0xe6000000U, 0xaf000000U, 0xc5800000U, 0x61c00000U, 0x8ea00000U, 0x72300000U, 0x24e80000U, 0xa4640000U, 0x9b160000U, 0x4a1f0000U, 0xeeae8000U, 0x48054000U, 0x4c00e000U, 0xbe02b000U, 0x2b00b800U, 0xf7808c00U, 0x14c5de00U, 0x2263d00U, 0x7970c580U, 0xe0c0540U, 0x39365820U, 0x436d3c30U, 0xb8a3e638U, 0xf537f114U, 0x3d6bfbbaU, 0x73a3884fU, 0x52b6a599U, 0xc1aff55bU, 0x4d800029U, 0xcdc0003cU, 0x60a00021U, 0xb1300007U, 0xef68000aU, 0x56a4000dU, 0x3636002eU, 0xf6ef0021U, 0x81668029U, 0xff914016U, 0x7d5ee039U, 0x2249b01aU, 0x7a503825U, 0x51fecc06U, 0x2d7dbe18U, 0xbe3ecd00U, 0xf0de1db6U, 0xf8b797eU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x70000000U, 0x88000000U, 0x1c000000U, 0x16000000U, 0xc1000000U, 0x2c800000U, 0x3cc00000U, 0x46200000U, 0xecb00000U, 0x8e380000U, 0xede40000U, 0x27160000U, 0xa2cd0000U, 0xe13f8000U, 0xf4664000U, 0xed53e000U, 0xf72e3000U, 0x322dc800U, 0x8cafc400U, 0x236eb600U, 0x7ac80900U, 0xc538c980U, 0xd664d3c0U, 0x56502820U, 0x84a8f430U, 0xff6afe28U, 0xcccc8d1cU, 0x743a1fa2U, 0x72e4aac7U, 0x7696c9a5U, 0xd48dd3c0U, 0xd2d9a803U, 0x6e73b423U, 0xa51e9e1bU, 0x13d0fd20U, 0x38ea3784U, 0xbb8c5eccU, 0xcb5c37a7U, 0xa4315ee7U, 0xf0fbb7aaU, 0xc0c31ee5U, 0x402657a3U, 0x75b42ed6U, 0x46ba1f89U, 0x5324aaebU, 0xaa36c99dU, 0xb5fdd3dfU, 0xbe41a807U, 0x4fe7b41aU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0x38000000U, 0xe4000000U, 0xe000000U, 0x7d000000U, 0xc9800000U, 0xecc00000U, 0x9da00000U, 0x19900000U, 0xfc980000U, 0x16640000U, 0xe6b60000U, 0xc9490000U, 0xd4198000U, 0x3923c000U, 0x74d02000U, 0x71fcf000U, 0xc853a800U, 0x48beac00U, 0x73353600U, 0xf8cf500U, 0x1ab9a880U, 0x24366ec0U, 0x950d8820U, 0xf2ff5c30U, 0xa4d11e08U, 0x19fc992cU, 0x84533e8eU, 0x2abcabf9U, 0xdc3628a3U, 0x510caeefU, 0x4cfc281aU, 0xe1d46c27U, 0x347c9621U, 0x6693c513U, 0xca1a20b2U, 0xc2432e3U, 0x41531628U, 0xc7390526U, 0x1ef380a8U, 0x1ab02dfU, 0xa4e89e2bU, 0x158f5916U, 0xb1bb1ebfU, 0xe4b45bd6U, 0x364b808cU, 0x229f02cdU, 0x3669e22U, 0x6332591eU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xd0000000U, 0xa8000000U, 0xfc000000U, 0xe6000000U, 0xe9000000U, 0x73800000U, 0xe6400000U, 0xda600000U, 0xe3300000U, 0x4eb80000U, 0x47240000U, 0x29d20000U, 0x3f4d0000U, 0x833a8000U, 0x8c634000U, 0x9230e000U, 0x193cb000U, 0xc3608800U, 0xa8b33c00U, 0x5cfae200U, 0x57442b00U, 0x6de48d80U, 0x17743bc0U, 0xb7da6820U, 0x70968c10U, 0xe7aaea28U, 0xd1cd5734U, 0x9cfe0faaU, 0xb746e0ffU, 0x1de60d99U, 0x6f737beaU, 0xe3d88814U, 0x6a973c1dU, 0xe8a8e234U, 0x4b492b33U, 0x93e0d80U, 0x8b677bd4U, 0x24b2880fU, 0xc2fe3c1cU, 0xea406222U, 0x4676b16U, 0xfe346dabU, 0xf7388bd0U, 0x662e030U, 0x9531b01eU, 0xafba0809U, 0x18a07c34U, 0x81920203U, 0xf02c9b27U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xb0000000U, 0x18000000U, 0x6c000000U, 0x1e000000U, 0x5b000000U, 0xfc800000U, 0x93c00000U, 0xb5600000U, 0xf2900000U, 0x5da80000U, 0x2240000U, 0x58320000U, 0x145d0000U, 0x5e198000U, 0x8f3ec000U, 0xaf886000U, 0xe2167000U, 0x90689800U, 0x4c40c400U, 0xe6204e00U, 0xc2312300U, 0x855cb880U, 0x3b9f7f40U, 0xbd797820U, 0x42a87410U, 0xd4a0b628U, 0x42f7972cU, 0xa8bc6e86U, 0x80ca985bU, 0x64b78ea7U, 0x679b2846U, 0xfb7cf6b7U, 0xd5ae5c58U, 0x8625c0a3U, 0x92370b5bU, 0x8d59ce1eU, 0xff9fe331U, 0xd77cd880U, 0x6bad0f40U, 0x6d23e024U, 0x76b5b026U, 0x72997801U, 0x54f8741aU, 0x7ee8b631U, 0xca839715U, 0xfcc66e85U, 0x9be3987cU, 0x94540e83U, 0x574ce864U, 0x80000000U, 0x40000000U, 0x60000000U, 0xb0000000U, 0xa8000000U, 0x24000000U, 0xda000000U, 0x99000000U, 0x9e800000U, 0x85400000U, 0x4a200000U, 0xf7f00000U, 0x57680000U, 0x45e40000U, 0xa920000U, 0x37bb0000U, 0x11f98000U, 0xac5b4000U, 0x886c2000U, 0x84665000U, 0xe550800U, 0x195e1400U, 0x78ef1a00U, 0x3a222900U, 0x7ff17380U, 0xa36efd40U, 0x87e0a820U, 0x1f930410U, 0x573e3218U, 0xd7be6d2cU, 0xe1f961aaU, 0x6459c049U, 0x1c6f4196U, 0xf6609076U, 0xb351c99fU, 0x5ddec45dU, 0x64ab7380U, 0xee81fd48U, 0xd432831U, 0xbe274402U, 0x35f19221U, 0x426c7d2fU, 0x2563c9adU, 0xccd5c458U, 0x7a1af394U, 0xfdcebd5aU, 0x34550819U, 0x705e143aU, 0x2e6f1a2dU, 0x2b622921U, 0x47d173b2U, 0xe99efd51U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0x48000000U, 0xe4000000U, 0xf2000000U, 0xf5000000U, 0x6d800000U, 0xd8c00000U, 0x78e00000U, 0x31700000U, 0xddb80000U, 0xf1a40000U, 0x6f560000U, 0xc72b0000U, 0xefea8000U, 0xaf084000U, 0x827e2000U, 0xd1c01000U, 0x8b666800U, 0x6ab38c00U, 0x1fdab600U, 0xc8929f00U, 0x9b4bff80U, 0x55dc7fc0U, 0xe192c820U, 0x18cbdc30U, 0xf61afe18U, 0x5ff50334U, 0x7ff92192U, 0xe1026cf9U, 0xa787019cU, 0x31c27ccdU, 0x9b6169a3U, 0x42b1f0f2U, 0x2bdbdfb4U, 0x72936ff1U, 0x8a482021U, 0xca5b103cU, 0xcc54e836U, 0xdafcc37U, 0x1faa9610U, 0xfaad8f15U, 0xbf2917aeU, 0x53e8b3cfU, 0x910ade2bU, 0xb17a131dU, 0xf343c996U, 0x2f22a0ecU, 0x551117a3U, 0x7b8cb3ceU, 0x80000000U, 0x40000000U, 0x20000000U, 0x90000000U, 0xe8000000U, 0x54000000U, 0xc6000000U, 0x23000000U, 0xbb800000U, 0xefc00000U, 0x29200000U, 0xff700000U, 0xe0180000U, 0xcb640000U, 0x2920000U, 0x81c90000U, 0xd1c88000U, 0x59c94000U, 0xbdcda000U, 0x3cdb000U, 0x9ccdd800U, 0xb54bbc00U, 0xbf8f2e00U, 0xe280100U, 0xa51b6f80U, 0x83e4eac0U, 0x9ed0f820U, 0x832b4c10U, 0x299d5608U, 0x31a70d24U, 0xeb3119baU, 0x6fe17d5U, 0x8d311991U, 0xf5fe17d8U, 0xfeb11986U, 0xde3e17cfU, 0xf9911998U, 0x564e17deU, 0x6409199bU, 0x51ea17dbU, 0xf43b198dU, 0xc09317f2U, 0xeccb99b3U, 0xad4e57fbU, 0xb38c3990U, 0xe42ee7dfU, 0xfc1b6198U, 0x89651bd2U, 0x2f916fa4U, 0xdd49eaeaU, 0xab8a780dU, 0xe82b0c09U, 0x80000000U, 0x40000000U, 0x20000000U, 0x90000000U, 0x58000000U, 0x44000000U, 0x22000000U, 0x61000000U, 0x2c800000U, 0x21c00000U, 0x4ee00000U, 0xee100000U, 0x65a80000U, 0xd9a40000U, 0x54320000U, 0x23d90000U, 0x9ed88000U, 0xb45cc000U, 0x669d2000U, 0xadfa9000U, 0x52aa4800U, 0x3e220400U, 0x4777e00U, 0x967d0f00U, 0x4ec6c80U, 0x7887bf40U, 0x1bc7e820U, 0x4be05410U, 0x70921608U, 0x7d6c9b24U, 0xffc1da96U, 0xb9e07451U, 0x6993daa8U, 0x85e97448U, 0xa4035aa3U, 0xd201b47cU, 0x89047aadU, 0xa086245eU, 0x1fc4b2afU, 0x49e1e04bU, 0x81966ca8U, 0x9eabf7dU, 0x9a056809U, 0xd5019423U, 0xe685b60eU, 0xccc3cb03U, 0x5c66329eU, 0xc8d0204bU, 0x44c9cc9aU, 0x5bf1ef4dU, 0x72388003U, 0x7b4cc021U, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0xa8000000U, 0xcc000000U, 0xb6000000U, 0xf9000000U, 0xe5800000U, 0xc8400000U, 0x5ea00000U, 0x93100000U, 0x3f880000U, 0x3d640000U, 0x28f20000U, 0xe5b90000U, 0x2abb8000U, 0x763b4000U, 0x7bf96000U, 0x1d1d3000U, 0x78aa0800U, 0x18348c00U, 0xacdc5200U, 0x40492d00U, 0x68836c80U, 0x6fc2ca40U, 0x6de0e820U, 0xf336fc10U, 0xaa5d3a08U, 0xf289913cU, 0xbae6b6aaU, 0xebb02b73U, 0x2d9cb68dU, 0x736d2b6eU, 0xfd53691U, 0x10ef6b5eU, 0xf697d695U, 0xb7c91b7bU, 0x43c4bea0U, 0x4be0a76eU, 0x7232e49cU, 0xdbdd066aU, 0xe8cdda0bU, 0x6746e12aU, 0xd2265eb0U, 0xc6d6d76fU, 0x3d698c92U, 0x22d0ba7bU, 0x769800fU, 0x4dd2403fU, 0xebeae007U, 0xc812702eU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x90000000U, 0xb8000000U, 0x74000000U, 0x9a000000U, 0x35000000U, 0xc7800000U, 0xbfc00000U, 0xe3200000U, 0x87b00000U, 0x32e80000U, 0xa5640000U, 0xac560000U, 0xe0fd0000U, 0xda788000U, 0x9e3fc000U, 0xa4dca000U, 0x334f5000U, 0x2297e800U, 0x165fdc00U, 0x2b0ace00U, 0x4e728100U, 0x5aca1980U, 0x52510d40U, 0x37fbc820U, 0xfcfb4c30U, 0xec7f8628U, 0x753b0d24U, 0xe459bfaeU, 0xb20e905dU, 0x57f73f86U, 0x620c507dU, 0x8ff31fb9U, 0x260cc07bU, 0x3df0579eU, 0xdf084c68U, 0x1473718cU, 0xcfcc116dU, 0x5d5261aU, 0x30395d13U, 0x6bded79fU, 0xf1ca8c5dU, 0x72d75184U, 0x86bc814bU, 0xa19e6e08U, 0x5429d103U, 0x3fc3f194U, 0x2327d152U, 0x27b7863eU, 0xa2ef0d2fU, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0xe8000000U, 0x14000000U, 0x56000000U, 0x79000000U, 0x8800000U, 0xd6c00000U, 0xb8e00000U, 0xec900000U, 0xcf880000U, 0xca40000U, 0x99b20000U, 0x8c7b0000U, 0x30fe8000U, 0xc0394000U, 0xd9dda000U, 0x91cd3000U, 0x22830800U, 0xadc42400U, 0xff626600U, 0x1bd1df00U, 0x4129b880U, 0x9a155640U, 0x54482820U, 0xdac45410U, 0x62e6ce18U, 0xf97cb14U, 0x440c56baU, 0x1e6ed45U, 0xc412d6b5U, 0x294fad4eU, 0xc4776baU, 0x89269d71U, 0x1f67eacU, 0x1359b97aU, 0x280a98a4U, 0x8be1265cU, 0xcf168033U, 0xb6cd4009U, 0x5707a017U, 0xad823031U, 0xac478806U, 0xf9226432U, 0xd9f34624U, 0xbf5eaf1bU, 0x8209908aU, 0xb0e50258U, 0xe894e631U, 0x118c9f39U, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0x38000000U, 0xf4000000U, 0x5a000000U, 0x6d000000U, 0xb9800000U, 0xd0400000U, 0xb600000U, 0x9900000U, 0x8e480000U, 0x4a40000U, 0x69b20000U, 0x963b0000U, 0xadbf8000U, 0xd4ffc000U, 0x641aa000U, 0x54cc5000U, 0xa642800U, 0x4e112c00U, 0x410ab200U, 0x67400300U, 0x9fe05880U, 0x522440U, 0x25690820U, 0x3e56bc10U, 0x1a6e3a18U, 0x46d27f1cU, 0xadab428eU, 0x92f3cb7dU, 0x8fdcc2b6U, 0x26e80b4bU, 0xb3146296U, 0xf08f5b78U, 0x1b07cab4U, 0x4a85b773U, 0x6c5d883U, 0x8ba2e46bU, 0x9362814U, 0xc5fa2c3bU, 0x6b9d3207U, 0x578bc339U, 0xc780f88eU, 0x8f417444U, 0x3e0a021U, 0x8653500aU, 0xae69a836U, 0x7cd5ec22U, 0xb0af9220U, 0x1373933bU, 0x80000000U, 0x40000000U, 0x60000000U, 0xb0000000U, 0x38000000U, 0xdc000000U, 0xa2000000U, 0x7b000000U, 0xc2800000U, 0x22c00000U, 0xf1a00000U, 0x37b00000U, 0x37e80000U, 0xaae40000U, 0x6520000U, 0x33b0000U, 0xd3198000U, 0x48efc000U, 0xe663e000U, 0xa5919000U, 0x271c9800U, 0x9ee8b400U, 0xb652600U, 0xea16a500U, 0xfa5fe180U, 0x8a0d2540U, 0xf434f820U, 0x80ade410U, 0x4103de18U, 0xf580412cU, 0xaa45bf8eU, 0xfc62a477U, 0x4292a788U, 0x279ed04eU, 0x772de188U, 0x462574U, 0x2365780aU, 0x9e162406U, 0x6c5a3e33U, 0x70ed12fU, 0xbb2a797U, 0x65eed061U, 0x89e5e1b0U, 0xa8d22559U, 0xbbff7800U, 0x85b9243aU, 0x1fd9be2fU, 0x884e111bU, 0x3c52c79cU, 0x343f806bU, 0x5b99198aU, 0x452bc15fU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xf0000000U, 0xc8000000U, 0x44000000U, 0xba000000U, 0xa5000000U, 0xfb800000U, 0xb3400000U, 0xc2200000U, 0x5c300000U, 0x32d80000U, 0x67e40000U, 0x52d60000U, 0x458f0000U, 0x9e2b8000U, 0x685c4000U, 0xb5272000U, 0x96b35000U, 0x181be800U, 0xcf803c00U, 0x1422a00U, 0xc323c900U, 0xedb24580U, 0xec98b8c0U, 0x1a414820U, 0x7a02c30U, 0x10756238U, 0x5e7ce53cU, 0xbb14a7b2U, 0x556c1dd1U, 0x67ccf8eU, 0x71461d9U, 0x836fc5a6U, 0xad7bf8e0U, 0x2b95e81aU, 0x2aab3c0aU, 0x9d9faa28U, 0xa3c0891dU, 0x7de6e5b6U, 0x27d3a8c5U, 0x660b8027U, 0x516c4038U, 0x9c7f2017U, 0xb217503bU, 0x40ede81cU, 0x923f3c3dU, 0x17b1aa11U, 0x699b890bU, 0xf1c3659bU, 0x8ce4e8f9U, 0x80000000U, 0x40000000U, 0x20000000U, 0xd0000000U, 0x68000000U, 0xfc000000U, 0x1a000000U, 0xe1000000U, 0xb2800000U, 0x8ec00000U, 0x4200000U, 0xfe900000U, 0x76980000U, 0xa5640000U, 0x9cf20000U, 0xc3e90000U, 0x4bca8000U, 0x575d4000U, 0x74c0e000U, 0x55255000U, 0xd413c800U, 0xbc5fb400U, 0x2f440600U, 0x65621900U, 0xfcf4b880U, 0x33ebdec0U, 0xf3cba820U, 0xc35ea410U, 0x92c5ae08U, 0xae21bd34U, 0x8791969aU, 0x801a23ffU, 0xa5a25ea6U, 0x9fd597e8U, 0x74fe5884U, 0xe0138ec7U, 0xca58e033U, 0x9c415024U, 0x1ae1c809U, 0xb2b6b41aU, 0xa40e8617U, 0xa1ff5914U, 0x249458b9U, 0xf79e8ef1U, 0xe7e0600dU, 0xaa351030U, 0x53cba806U, 0x535ea43dU, 0xdac5ae39U, 0x8221bd2aU, 0xf5919691U, 0x9d1a23c4U, 0x80000000U, 0x40000000U, 0x60000000U, 0xb0000000U, 0x8000000U, 0x7c000000U, 0xd6000000U, 0x91000000U, 0xcb800000U, 0xf0400000U, 0x3ea00000U, 0xbab00000U, 0x3380000U, 0xd0640000U, 0x5dd20000U, 0x2c6b0000U, 0x6bc98000U, 0x96fe4000U, 0xdb86e000U, 0x68423000U, 0x9aa24800U, 0xa8b07c00U, 0x303a9200U, 0x20e42d00U, 0x2113b180U, 0xb80e4fc0U, 0xd41f2820U, 0xe1970c10U, 0x8ccfba18U, 0x5c7c212cU, 0x38478b82U, 0x62a72edfU, 0xbcb7c395U, 0x2a3c52f4U, 0x6fe4d18aU, 0x7963fc0U, 0x55c98035U, 0x8bfe400dU, 0xae06e02fU, 0xc5023023U, 0xb1824812U, 0xf407c0cU, 0x10229212U, 0x2b702d13U, 0x8ad9b18bU, 0xef14ffcU, 0xdf9ca81eU, 0x31d64c2bU, 0x626ada19U, 0x5ecf513eU, 0x4f78a3b1U, 0x18c022c5U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x10000000U, 0xb8000000U, 0xfc000000U, 0x62000000U, 0xc1000000U, 0x56800000U, 0x46400000U, 0x3200000U, 0x9a100000U, 0xb9380000U, 0x90e40000U, 0xf8f20000U, 0x78cf0000U, 0xa2ac8000U, 0x6e1bc000U, 0x6cf6e000U, 0xfece9000U, 0xda84800U, 0x339e1400U, 0xf9320200U, 0x732f6100U, 0x71dd3c80U, 0x8417e7c0U, 0x5a382820U, 0xe7604410U, 0xf8322a38U, 0x85ab2504U, 0xc79d16aeU, 0x2f33c2ffU, 0x8429beb8U, 0xc05846e0U, 0xcbd5748dU, 0xead9f3c5U, 0xaf922a36U, 0xc8fb250dU, 0x730516a0U, 0x8f87c2efU, 0x1cc3bebdU, 0x8f6346d0U, 0x1c33f4bdU, 0xeba933c8U, 0xcc9a4a16U, 0xfcb17507U, 0xaef3e9dU, 0x263886dbU, 0xc5651485U, 0xd937a3f3U, 0xc32a0204U, 0x39db6108U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x10000000U, 0x8000000U, 0x4000000U, 0xaa000000U, 0x4d000000U, 0x88800000U, 0xad400000U, 0x2ba00000U, 0x4d700000U, 0x8cb80000U, 0x39640000U, 0xa6120000U, 0x3baf0000U, 0xcc4c8000U, 0x341e4000U, 0x43912000U, 0xae68d000U, 0xb2a9a800U, 0x4ecaa400U, 0x24595a00U, 0xf8b7c500U, 0x425cd780U, 0xbbb4c3c0U, 0xddde0820U, 0xcb773410U, 0xdfbf5238U, 0xaee4f104U, 0xd2d18582U, 0x93cf32c1U, 0xe4db0d8aU, 0xb1f246c3U, 0xd3ff7fbaU, 0xb3c567ffU, 0xdde1d210U, 0xf555b106U, 0x1f0c25b3U, 0x50b9a2d8U, 0x3f638583U, 0xb51032e7U, 0x4c2f8da9U, 0xa88806f2U, 0x947c5f81U, 0x6f02b7c8U, 0x8184fa1cU, 0x6fc15506U, 0xdbe45f82U, 0xe656b7ceU, 0x688efa3aU, 0x347a553cU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xb0000000U, 0x38000000U, 0xf4000000U, 0x12000000U, 0x79000000U, 0xc800000U, 0x59400000U, 0xb4600000U, 0x19500000U, 0xf4980000U, 0x62a40000U, 0x1df20000U, 0xc26d0000U, 0x75498000U, 0x8d7fc000U, 0x9a34a000U, 0xb64a1000U, 0xc4fe8800U, 0xb1f58400U, 0x746b3a00U, 0x364ddb00U, 0x84f9b680U, 0x11f3a2c0U, 0xc469a820U, 0xe495410U, 0x70fa9228U, 0x3f08f2cU, 0xbd69248eU, 0x2ca2dfdU, 0x29bb0ca4U, 0xb791b9ceU, 0xa43cbe8bU, 0xf654e6eaU, 0x4b1fb22bU, 0xaa615f07U, 0x66510c9fU, 0x8318b9d7U, 0xc6673eaeU, 0x305626d5U, 0xd01a923fU, 0x47e08f11U, 0x77912493U, 0x443e2df4U, 0xe6510c8cU, 0xc318b9f1U, 0x66673eb5U, 0x805626f2U, 0xe81a9235U, 0xb3e08f2bU, 0x80000000U, 0x40000000U, 0xe0000000U, 0xd0000000U, 0x58000000U, 0xd4000000U, 0x16000000U, 0xcf000000U, 0x48800000U, 0x34c00000U, 0xd4e00000U, 0x43900000U, 0x42280000U, 0x55a40000U, 0x1a320000U, 0xda1f0000U, 0xb6ba8000U, 0xfb0cc000U, 0x557a000U, 0x87cb3000U, 0xfdb13800U, 0x365aa400U, 0xee9e7600U, 0x687e4f00U, 0x4aed5080U, 0x8b46ab40U, 0xeca61820U, 0xdb65410U, 0x1e586e38U, 0x52981b34U, 0x227d3e96U, 0x1feab075U, 0xcec126a5U, 0x49e7e463U, 0x6a11c88aU, 0xf56c3f69U, 0xb301d63bU, 0xa2817f01U, 0x51c668bbU, 0x19670f67U, 0x6ad0ee27U, 0xe78bdb2dU, 0x67901eb7U, 0x7c2d4064U, 0x26a7be80U, 0x18b6704cU, 0xbbde8681U, 0x27d8d469U, 0x1ddaf09cU, 0x20dd9b5bU, 0x395f2006U, 0x618f039U, 0x80000000U, 0x40000000U, 0x60000000U, 0xb0000000U, 0xd8000000U, 0x5c000000U, 0x26000000U, 0x9000000U, 0x94800000U, 0x45c00000U, 0xb9200000U, 0x8e100000U, 0xc7980000U, 0x43640000U, 0xd5720000U, 0x6eeb0000U, 0xdb898000U, 0x6ff8c000U, 0x1197e000U, 0xf5ddb000U, 0xc040800U, 0xe070400U, 0xed043e00U, 0x5e83d100U, 0xb2c76c80U, 0x78a21ec0U, 0x79506820U, 0x327d7410U, 0xe0d45618U, 0xd93ea52cU, 0x53333ab6U, 0xc38cbbd7U, 0x13fb52a9U, 0xe795cfd2U, 0x94dd049dU, 0x1c806aedU, 0x31c7be20U, 0x7b241108U, 0x4d130c96U, 0xa4186ee9U, 0xc720000fU, 0x9b10000fU, 0x1518002cU, 0xbfa40007U, 0x20d20008U, 0xf93b0008U, 0x83318020U, 0xab8cc029U, 0x97fde02cU, 0x9d92b016U, 0xbbdf8805U, 0x8104c400U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0x78000000U, 0xb4000000U, 0x6000000U, 0x29000000U, 0x98800000U, 0x15c00000U, 0xe2e00000U, 0xd8500000U, 0xa7280000U, 0xf8540000U, 0x572e0000U, 0xb0570000U, 0xcb2c8000U, 0x7a54c000U, 0x50292000U, 0xcdd4f000U, 0xf4686800U, 0xa2703400U, 0xdb18c600U, 0x3fef2300U, 0x5c320480U, 0x37b81a40U, 0x4318c620U, 0x1bef2330U, 0x42320498U, 0xfab81a54U, 0xa598c63eU, 0x932f231dU, 0x3e520499U, 0x1e281a5eU, 0x78d0c618U, 0xa6eb2318U, 0x2cb404a1U, 0x8e7b1a68U, 0x43fa4631U, 0x94bce326U, 0xe09fa4b4U, 0x89ac2a44U, 0x2c978e03U, 0x814ce738U, 0x9fc62aa0U, 0xd9e7cd77U, 0x5fd524beU, 0x2b6bea50U, 0x5bf42e36U, 0xca5fd708U, 0x2cde291U, 0xfd84c979U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0x48000000U, 0x94000000U, 0x9e000000U, 0x7d000000U, 0x81800000U, 0x8c400000U, 0x87e00000U, 0xffb00000U, 0x18c80000U, 0xe7b40000U, 0x4ce0000U, 0x8db70000U, 0x37c88000U, 0x39354000U, 0xae0c2000U, 0xac91b000U, 0xab5fc800U, 0xca6dbc00U, 0xd867aa00U, 0xaef38300U, 0xaea95780U, 0xc44c540U, 0x47e7aa20U, 0x9fb38330U, 0xc8c95798U, 0xafb4c574U, 0x90cfaa32U, 0x13b78315U, 0x4acf57bfU, 0xb8b7c56bU, 0x22492a12U, 0x2b75c336U, 0x54ebf79eU, 0xd2a33554U, 0x3fd2c214U, 0xaa3dcf0fU, 0x231d959fU, 0x3b8a0a77U, 0x7ed4bf99U, 0x31bfc941U, 0x645f4814U, 0x4ecfc2cU, 0x5aa58a0bU, 0xcbd53337U, 0xe43e1f88U, 0x161c3966U, 0x2e0c202dU, 0x6c91b00aU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x70000000U, 0xf8000000U, 0xdc000000U, 0xe000000U, 0x91000000U, 0xad800000U, 0xe8400000U, 0x49a00000U, 0xadf00000U, 0xb8880000U, 0xc5f40000U, 0x8c8e0000U, 0x3ff10000U, 0x478d8000U, 0x2976c000U, 0x414b6000U, 0xba16b000U, 0x71dfe800U, 0xa30bdc00U, 0xb4aa00U, 0xb6ab9100U, 0x6342c580U, 0x3f20d540U, 0x7b34aa20U, 0xa3eb9130U, 0xd162c5a8U, 0x4790d55cU, 0xd19caa1eU, 0x6eaf9107U, 0xf44c5abU, 0x6925d578U, 0x46372a35U, 0xf86c513dU, 0x742425b9U, 0xadb0a553U, 0x528221bU, 0x3202fd0cU, 0x8f07879aU, 0x1481985cU, 0x11c7458aU, 0x8be21546U, 0xa751ca2aU, 0x27fc2102U, 0xa9b8ad9eU, 0x4519c942U, 0xbf6d603cU, 0x24a3b004U, 0xbe74683bU, 0x99c81c1eU, 0x80000000U, 0x40000000U, 0xe0000000U, 0xf0000000U, 0x18000000U, 0x64000000U, 0x2000000U, 0xb5000000U, 0x6800000U, 0x3cc00000U, 0x51a00000U, 0x8bb00000U, 0xe8a80000U, 0x2fb40000U, 0x4aaa0000U, 0x8ab30000U, 0xa42d8000U, 0xca73c000U, 0x938ea000U, 0xf6c3d000U, 0xc8a30800U, 0xe337e400U, 0xef68ee00U, 0xb3966900U, 0x28593380U, 0xbefeec40U, 0xdec8ee20U, 0x88266910U, 0x38f133b8U, 0x54aec7cU, 0x8e62ee26U, 0xd3956909U, 0x985cb3b8U, 0x46f92c51U, 0x4acc4e27U, 0x9226b906U, 0xe9f7bbacU, 0x1cac873U, 0x7a6a01dU, 0x84b7d00dU, 0x2f29083eU, 0xfff4e411U, 0xeecd6e14U, 0x3021a92fU, 0x4cf593a2U, 0xef4a3c50U, 0x47646600U, 0xb3154d1eU, 0x1398fda1U, 0xa4db956dU, 0xfb39f58dU, 0x17eb7167U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x50000000U, 0x88000000U, 0xd4000000U, 0x82000000U, 0x7000000U, 0x10800000U, 0x91c00000U, 0xaa600000U, 0x52100000U, 0x48780000U, 0x8e140000U, 0xde7e0000U, 0xab110000U, 0x99fc8000U, 0xa2554000U, 0x765a2000U, 0xd8215000U, 0x6b321800U, 0xecdd400U, 0xaa9c9600U, 0xd1c78700U, 0xca638680U, 0xa21404c0U, 0x907c9620U, 0xd2178730U, 0x887b86a8U, 0x2e1004d4U, 0x8e7a9602U, 0x23128705U, 0x4df90688U, 0x205444d5U, 0x715c3606U, 0xc8a69721U, 0xfaf13ea2U, 0xa4a8c0c1U, 0xf88ab814U, 0x99b8c402U, 0x44702e15U, 0x7c6a432bU, 0x3b692892U, 0x4bee07daU, 0x2a2d1e80U, 0x584c90f9U, 0x565a2022U, 0x48215008U, 0x43321820U, 0x8acdd41dU, 0xa09c961eU, 0x2c78714U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x70000000U, 0xd8000000U, 0xbc000000U, 0xc2000000U, 0xc9000000U, 0x5d800000U, 0x50400000U, 0x7e00000U, 0x5eb00000U, 0xf7680000U, 0xab40000U, 0xf16e0000U, 0xadb70000U, 0xfed8000U, 0xd71c000U, 0x7bc86000U, 0xf67d000U, 0x41762800U, 0xa1c93c00U, 0x1a66aa00U, 0xaef40300U, 0xe088df80U, 0xfc04f840U, 0x6206aa20U, 0xd9040330U, 0xf580df98U, 0x3440f85cU, 0x79e0aa16U, 0x55b7031fU, 0x63eb5fa8U, 0x772386eU, 0xa6cb4a01U, 0xf4e6130bU, 0xa63097a9U, 0xf0a91479U, 0x8015a83cU, 0x53bffc09U, 0xe32b4a15U, 0xa3561312U, 0x6cd8979fU, 0xda5d147aU, 0xae9ba833U, 0x1cb8fc3dU, 0xd9aeca21U, 0x6d93d321U, 0xbbfef793U, 0x28cdc47bU, 0xe7e00006U, 0xeeb00014U, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0xb8000000U, 0x24000000U, 0x6000000U, 0xa5000000U, 0x1e800000U, 0x4c00000U, 0xdfa00000U, 0xec700000U, 0x5ee80000U, 0xc0740000U, 0xd4ea0000U, 0x9f770000U, 0x1d688000U, 0x9e32c000U, 0x5989a000U, 0xb1a2f000U, 0x95748800U, 0x26e0400U, 0x37b2ae00U, 0x8c9f900U, 0x4d444d80U, 0x9ee44e40U, 0xc892ae20U, 0x2179f910U, 0xb48c4d98U, 0x43204e54U, 0x3bb0ae0eU, 0xb2caf919U, 0xfa46cd99U, 0xcb618e7dU, 0xebd38e09U, 0xc699c918U, 0x209965aeU, 0x9598ba46U, 0x531c881eU, 0x23da0428U, 0x4278ae1bU, 0x2f0ef921U, 0x6964cdb9U, 0x8d28e5fU, 0x1d190e35U, 0x6ad80909U, 0xf6fa45aaU, 0x44cb8a42U, 0x97432017U, 0x79e3302bU, 0x2517a83fU, 0x263d340dU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0x78000000U, 0xac000000U, 0xfa000000U, 0xbf000000U, 0x21800000U, 0x44400000U, 0xc1e00000U, 0x8b300000U, 0xa4280000U, 0xd1340000U, 0xb2e0000U, 0xa8b50000U, 0x33688000U, 0xeb56c000U, 0xab5de000U, 0x94f91000U, 0x812c1800U, 0x7fb61c00U, 0xe6eb3a00U, 0x29109300U, 0x57bda380U, 0x2d4e5240U, 0xbac33a20U, 0x94249330U, 0x8693a388U, 0xeafb5274U, 0xd02bba3eU, 0x9732531bU, 0x162e43b6U, 0x4a32425bU, 0xd4afa236U, 0x7df04f0aU, 0x3a0b7986U, 0x40a7d179U, 0x1452819fU, 0x6adcdd7eU, 0x20bba3a4U, 0xe8cf5263U, 0x2085ba1bU, 0x14c75330U, 0xbd26c3b0U, 0xc214825dU, 0xe03a420dU, 0xc0d5f34U, 0x35a1619fU, 0x2d0cd6dU, 0xb1f3b96U, 0x8b1f8e72U, 0x80000000U, 0x40000000U, 0x20000000U, 0xd0000000U, 0xc8000000U, 0xd4000000U, 0xd6000000U, 0x21000000U, 0x95800000U, 0x3e400000U, 0xb8600000U, 0x8b900000U, 0x1c580000U, 0x69940000U, 0x5b5a0000U, 0xe5150000U, 0x3c9c8000U, 0xa9334000U, 0x2c6a2000U, 0x5c7df000U, 0xd3672800U, 0x7d175c00U, 0x6099da00U, 0x8b331f00U, 0xb6e4680U, 0x20fc9dc0U, 0xaca1da20U, 0x2d371f10U, 0x726c4688U, 0x897d9df4U, 0x40e75a12U, 0xaa515f25U, 0x997ae6bdU, 0xe8e32dfcU, 0x8e525237U, 0x577ff32aU, 0xd5e61493U, 0x19d66edeU, 0x9e3b4eb0U, 0xd90231f0U, 0x39852825U, 0x4465c37U, 0x83675a17U, 0xf5115f3eU, 0x949ae6b4U, 0x8d332df1U, 0xe26a520cU, 0x617bf338U, 0x44e41486U, 0xb4576ed5U, 0x6c7dce82U, 0xab6471e0U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0xb8000000U, 0x94000000U, 0xaa000000U, 0x11000000U, 0x67800000U, 0xa0c00000U, 0x53200000U, 0xb7500000U, 0xa2780000U, 0x11540000U, 0x5d7e0000U, 0xd5d10000U, 0xf3e8000U, 0x53b4c000U, 0xce8a2000U, 0xd8399000U, 0x7b36a800U, 0x2c8ac00U, 0xf558ae00U, 0x7403b500U, 0xda025480U, 0x1900c6c0U, 0x5b80ae20U, 0x26c7b530U, 0x7c2454a8U, 0x6bd5c6c4U, 0x74382e0eU, 0x85367515U, 0x19cef482U, 0x93d996c0U, 0xb422617U, 0xbde7893dU, 0x5774d296U, 0x5faa1fedU, 0xf268f4bfU, 0x90cc96f9U, 0xb05aa621U, 0x19864928U, 0x7bc672b4U, 0x95a24fd9U, 0xd814fc94U, 0x7d986affU, 0xcb20000eU, 0xf3500008U, 0x10780012U, 0x8454003aU, 0x28fe0013U, 0xf011001aU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0xc8000000U, 0xe4000000U, 0x76000000U, 0x29000000U, 0x7800000U, 0xbbc00000U, 0x5de00000U, 0x6d500000U, 0xdc680000U, 0x24540000U, 0xebea0000U, 0xb7930000U, 0x22098000U, 0x64c54000U, 0x3366a000U, 0x3112f000U, 0x4a4de800U, 0xdce1cc00U, 0xbed1b600U, 0x39ae6300U, 0xc4b07c80U, 0x3f387040U, 0x1d3bb620U, 0x2a3d6310U, 0x70b9fcb8U, 0x2fd305cU, 0xe1dd1612U, 0x44ef9329U, 0x111414a5U, 0x9a4cfc56U, 0x84e4a013U, 0xe2d5f007U, 0x63ae6832U, 0x7fb78c0dU, 0x67be9604U, 0x8879d31eU, 0xcb9b34b0U, 0xfbcb4c7cU, 0xee27e81eU, 0x74b2cc2eU, 0x57383619U, 0x693b2326U, 0xe43edc9fU, 0x75be805eU, 0x977c5e24U, 0x51faf35U, 0x3789ca92U, 0xc0021353U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x10000000U, 0x68000000U, 0x64000000U, 0xfe000000U, 0x5d000000U, 0x8c800000U, 0x99400000U, 0x6d600000U, 0x8af00000U, 0xc6480000U, 0xe3f40000U, 0x7cce0000U, 0x33b70000U, 0x1b2e8000U, 0x71044000U, 0xa685a000U, 0x2247b000U, 0xa0e14800U, 0x6d30d400U, 0xf56d0200U, 0x2be4ff00U, 0x78b47580U, 0x6eaa3d40U, 0xfac30220U, 0x1fa3ff30U, 0x2152f598U, 0x111a7d44U, 0xdbe8a23aU, 0xbda34f29U, 0x2e553da7U, 0x2a9ae953U, 0x152e0019U, 0x9407000fU, 0x4606803cU, 0x31004031U, 0x683a008U, 0x5244b007U, 0xd8e1c83bU, 0x61339439U, 0x6f6e2214U, 0x88e30f02U, 0xa9369dadU, 0x7b6e5966U, 0xee7c83fU, 0xf830940fU, 0x6deea213U, 0x34a04f0aU, 0x44d5bdaaU, 0xf2d9a945U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x30000000U, 0xe8000000U, 0xdc000000U, 0x9e000000U, 0xf9000000U, 0x15800000U, 0x4f400000U, 0x42a00000U, 0x3e300000U, 0x3e380000U, 0xb340000U, 0x2dba0000U, 0x29710000U, 0x89b8000U, 0xd7064000U, 0x44856000U, 0x26c6b000U, 0xa3e0a800U, 0x6d931c00U, 0xc98b5200U, 0xe44a4900U, 0x9d2a4380U, 0x2f7848c0U, 0x50915220U, 0x960b4910U, 0x8009c3a8U, 0x750a08ccU, 0x868e321aU, 0x34ccf927U, 0xc9eaeb8fU, 0x39b54f2U, 0xd82001fU, 0x9b450034U, 0x90a1801fU, 0x8137403dU, 0xe6bee030U, 0x13f0f026U, 0x475dc83cU, 0xb961ac3bU, 0x5251fa08U, 0xefe85524U, 0x1e9a918aU, 0x220441ccU, 0xb7067185U, 0x9481b1fcU, 0x5ec239a0U, 0xa7e35de6U, 0xc79723bfU, 0x728af8ceU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xf0000000U, 0x88000000U, 0xc4000000U, 0x9e000000U, 0x1f000000U, 0x60800000U, 0x3a400000U, 0xb3a00000U, 0xa3700000U, 0x19980000U, 0x20740000U, 0xfb1e0000U, 0x47370000U, 0x15398000U, 0x73834000U, 0xa0c7a000U, 0x98e3b000U, 0x17515800U, 0xac2bb400U, 0xea0b0a00U, 0x4ab86900U, 0x79453180U, 0x3124d5c0U, 0x34350a20U, 0x7fbf6930U, 0xd0c4b198U, 0xd0e395fcU, 0xb354aa02U, 0xc22fd901U, 0x7d0a69bfU, 0xee3861fbU, 0xdd07801aU, 0x9d84400fU, 0xf7c62013U, 0x5c64f013U, 0x4310f83cU, 0x888b0437U, 0xedfdd235U, 0xf7679d3eU, 0xf5901b9bU, 0x9cc4cdaU, 0x50dec39aU, 0xf957b8efU, 0xfb2de9beU, 0x2e8c21f3U, 0x1ef9a036U, 0x5de4b018U, 0x36d0d803U, 0x89ecf431U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xf0000000U, 0xc8000000U, 0xc000000U, 0xf6000000U, 0x91000000U, 0xbc800000U, 0x2400000U, 0x38e00000U, 0x4a700000U, 0x7b880000U, 0xfd740000U, 0x2e0a0000U, 0x27b10000U, 0x1ead8000U, 0xfa274000U, 0xed5e000U, 0x341cf000U, 0x760f6800U, 0xf3b21400U, 0x7cabfa00U, 0xa9251300U, 0x11550980U, 0xe1dcdf40U, 0x9729fa20U, 0xaee01310U, 0xcb7289a8U, 0x5f0a9f7cU, 0xcb319a12U, 0x24eba313U, 0x6c00195U, 0xbea07b58U, 0x2897083dU, 0xa6f9a413U, 0x6379721bU, 0x61bff70aU, 0xc51b9b83U, 0xda8ad87cU, 0x69f28998U, 0x704a9f6fU, 0xd1519a3eU, 0x1dba32dU, 0xc728019cU, 0x96e47b69U, 0xf75082bU, 0xa50ca40aU, 0xac36f22dU, 0x96db736U, 0xb801fb8dU, 0x8404686bU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x30000000U, 0x78000000U, 0x4c000000U, 0x52000000U, 0xe7000000U, 0x28800000U, 0x62400000U, 0x600000U, 0x1300000U, 0x4b480000U, 0xec340000U, 0x38ce0000U, 0x2cf10000U, 0xc1ef8000U, 0x2f22c000U, 0x42d5e000U, 0xf2bc5000U, 0x1258d800U, 0x852a1400U, 0x70014a00U, 0x18015700U, 0xdc036380U, 0x1a033d40U, 0xd3074a20U, 0x36845730U, 0xd742e3a8U, 0xcfe0fd4cU, 0x4bf52a3eU, 0x296ec723U, 0xed61dbbcU, 0x72b7b975U, 0x8b8b3834U, 0x1513443bU, 0x3b18123cU, 0xafc88335U, 0x1c704986U, 0x7fa8fa70U, 0x354711baU, 0x90e02e42U, 0x8f73bba0U, 0x292d2954U, 0x72000008U, 0x17000018U, 0xf0800004U, 0x1e400037U, 0x2a600002U, 0xaa300003U, 0x31c8001dU, 0x6974000dU, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0xd8000000U, 0xac000000U, 0xe2000000U, 0xb3000000U, 0x3800000U, 0xd5400000U, 0x76600000U, 0xaab00000U, 0x9480000U, 0x93b40000U, 0xfdca0000U, 0xa3770000U, 0x6bea8000U, 0x5921c000U, 0xe3d7e000U, 0x327ad000U, 0x34bc7800U, 0x6f9fcc00U, 0x6f4b5200U, 0xe6b13f00U, 0xbb492780U, 0x98b7c540U, 0x42495220U, 0x4c323f10U, 0x289a798U, 0x12110544U, 0x8cdc3216U, 0xd42d2f3bU, 0xb6803fa0U, 0xb3c71968U, 0x3da39816U, 0x4b111c0eU, 0x685d2a3dU, 0x3ce9f302U, 0x8ca0f5b4U, 0xab933a7aU, 0x69d95baU, 0x23c82a7eU, 0x6a760da0U, 0x176d3653U, 0x7de12794U, 0x2bf3c571U, 0x412b5223U, 0xa0013f3aU, 0x3001278aU, 0xa803c56bU, 0x6403520aU, 0x96053f23U, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0xe8000000U, 0x9c000000U, 0x6a000000U, 0xbf000000U, 0xdd800000U, 0xac400000U, 0x42200000U, 0xd0100000U, 0xe8380000U, 0x59140000U, 0x80ba0000U, 0x7d50000U, 0xeb5f8000U, 0x4da24000U, 0x67536000U, 0xf99d1000U, 0x34409800U, 0x5620fc00U, 0xb6157a00U, 0x653a2d00U, 0x4f955a80U, 0x77d5cc0U, 0x3cb77a20U, 0x1beb2d10U, 0x448da88U, 0x381e1cecU, 0xb2019a1aU, 0x8b017d37U, 0xb84a292U, 0xc941b0c3U, 0xc8a7182dU, 0x3dd6bc1cU, 0x6c5c1a02U, 0x74223d37U, 0x651242b7U, 0x1abbe0daU, 0x70d3600aU, 0x1add100aU, 0x63e0983fU, 0x670fc02U, 0x9e0d7a13U, 0xcf3e2d2cU, 0x90975a97U, 0x4afc5cffU, 0xc8f2fa03U, 0x2dcc6d1dU, 0x225c3abcU, 0x5254cdfU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x50000000U, 0x18000000U, 0x74000000U, 0x26000000U, 0x43000000U, 0xdc800000U, 0x1c400000U, 0x76a00000U, 0xad100000U, 0x82480000U, 0x6c140000U, 0xe3ce0000U, 0x7bd30000U, 0x23ac8000U, 0xe723c000U, 0xd2d72000U, 0x9e2ef000U, 0xeae73800U, 0x1bb11400U, 0xcf5e5a00U, 0xbe5ae100U, 0x97dd5280U, 0xec1fe340U, 0x7e785a20U, 0x878de130U, 0xe977d2b8U, 0x50bb2354U, 0x26dfa26U, 0x5c43d12dU, 0x56a34ab1U, 0x1d130744U, 0xca4db811U, 0x15d42aU, 0xb1cbfa2cU, 0x1ed4d12fU, 0xbc29ca91U, 0x27e7c741U, 0xb830180cU, 0x459fe415U, 0xc5b96227U, 0xf5ebf531U, 0x40830897U, 0x2645024fU, 0xcfa508bbU, 0x28920244U, 0x4b8f8890U, 0xcb76c275U, 0x9dba2894U, 0xa1e8f256U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xb0000000U, 0x58000000U, 0xdc000000U, 0xaa000000U, 0xa9000000U, 0x6b800000U, 0xcbc00000U, 0x64600000U, 0x92900000U, 0x7bf80000U, 0xe5940000U, 0xf77e0000U, 0x8ad10000U, 0xd85b8000U, 0xf163c000U, 0x83156000U, 0x513a9000U, 0xde722800U, 0x802acc00U, 0x4a4cf600U, 0xc7daaf00U, 0x74a24280U, 0x2873c0c0U, 0x432af620U, 0x28cfaf30U, 0xd79fc2a8U, 0x830500ecU, 0x2821636U, 0x43ff07U, 0x1fa50a82U, 0xaef39cc6U, 0x356c282cU, 0x346bcc35U, 0xbbef761bU, 0x162d6f22U, 0x99492292U, 0x4d5850fcU, 0xe0e35e2eU, 0xa9d6a31cU, 0x6ade549aU, 0xa9213fdbU, 0x40b47cb2U, 0x55cff3d5U, 0x421e8abdU, 0xdfc05cd3U, 0x3a61480bU, 0xb5955c1eU, 0x7f7b5e11U, 0x1ed2a303U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x90000000U, 0x28000000U, 0xb4000000U, 0xde000000U, 0x5000000U, 0xd1800000U, 0x5dc00000U, 0x25e00000U, 0x6bd00000U, 0x8c480000U, 0xaa540000U, 0xb98a0000U, 0xdbb30000U, 0x9c5e8000U, 0x7afa4000U, 0x538f2000U, 0x40b6b000U, 0xa8dc0800U, 0x66bebc00U, 0x3aca600U, 0xba84b300U, 0x91434880U, 0x45a7d940U, 0xc1f22620U, 0x857ef310U, 0xf34c68b8U, 0xc8d16964U, 0x64ce2e2aU, 0x3c104f3dU, 0xa2a8ce8fU, 0xdd01da65U, 0x9d87669eU, 0xffc4966aU, 0xdae468a6U, 0x4955696fU, 0xb10c2e05U, 0xddf74f24U, 0xaf7c4ea2U, 0xc8489a64U, 0x8c56c6adU, 0xc088665fU, 0xf03740a8U, 0x329d655eU, 0x3f9c8001U, 0x6a1d4039U, 0xb1dba015U, 0x9d3ff030U, 0x656da82dU, 0xdbe24c31U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xf0000000U, 0xe8000000U, 0xac000000U, 0x9e000000U, 0x13000000U, 0xb800000U, 0x68400000U, 0x2fa00000U, 0x21d00000U, 0x99d80000U, 0x3a540000U, 0x899e0000U, 0x1f10000U, 0x82498000U, 0x512e4000U, 0x9298e000U, 0x3674b000U, 0xcc097800U, 0xd98d6c00U, 0x62cc7a00U, 0xe6e8f100U, 0x5f7bc480U, 0x10647c0U, 0xb685fa20U, 0x38c6b130U, 0x106324a8U, 0x1032f7fcU, 0x28ac821aU, 0x17dbdd1bU, 0x51575e8fU, 0x961e06f8U, 0x43b14698U, 0x64e89ac1U, 0x5a7d24a4U, 0xe583f7c0U, 0x53450216U, 0x28259d33U, 0x2797be9cU, 0x4d7eb6dbU, 0xbc063eb9U, 0xe604f6dfU, 0x700dea0U, 0x218146d7U, 0xa140268eU, 0x5226ad9U, 0xcf14bca6U, 0xc6be2bd1U, 0x57e60017U, 0x76750015U, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0x18000000U, 0x7c000000U, 0xea000000U, 0x27000000U, 0x3a800000U, 0x4c400000U, 0x99600000U, 0x4c700000U, 0x4780000U, 0xeef40000U, 0x743a0000U, 0xfd970000U, 0xef4d8000U, 0xdb6fc000U, 0x31fa6000U, 0xdc329000U, 0xa71c5800U, 0xd86c400U, 0xdec5fa00U, 0xd1226f00U, 0xb3120980U, 0x9d0b94c0U, 0x8b087a20U, 0x60daf10U, 0x7b886998U, 0xfd4904fcU, 0x306c2226U, 0x997f6b0fU, 0x3b7793a2U, 0xf6fc6bf5U, 0x56b3aba8U, 0x935b3fdcU, 0x18e589a4U, 0x60b354f6U, 0x8e5f9a31U, 0x8d60ff1bU, 0x8276519fU, 0xd57950c6U, 0xe9778028U, 0x3df8c018U, 0x6e37e01bU, 0x9c1d503dU, 0x2d06383dU, 0xad845411U, 0xec1a23bU, 0x5920ab1dU, 0x2715f3acU, 0x130afbc5U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0x28000000U, 0xbc000000U, 0xae000000U, 0xef000000U, 0x5a800000U, 0x58400000U, 0xc3200000U, 0xcf100000U, 0x3c080000U, 0xed940000U, 0x104a0000U, 0xcb10000U, 0x265e8000U, 0x11384000U, 0xdb0f6000U, 0xdb173000U, 0x6e091800U, 0xc936400U, 0x35cf9a00U, 0x26741d00U, 0x13dd280U, 0xb30f6540U, 0xc7111a20U, 0x500c5d10U, 0xcb92b2a8U, 0xd3485564U, 0xd030022aU, 0x2d1b393fU, 0x269f2883U, 0xa359485fU, 0x7eb950bcU, 0x14cd1c69U, 0xe3f7d293U, 0x1bfe657cU, 0x2c6f9a1bU, 0xf1241d36U, 0x5e15d2bdU, 0x18b6540U, 0xc3531a11U, 0xd295d2dU, 0x53863297U, 0x21c1154fU, 0x77e1e211U, 0xbf744926U, 0x50b95083U, 0xbbcd1c6bU, 0x1977d2a5U, 0xd3be657aU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x10000000U, 0x18000000U, 0x3c000000U, 0x6a000000U, 0xdd000000U, 0xdc800000U, 0xf6c00000U, 0xf9a00000U, 0x9e100000U, 0xfbd80000U, 0x2e940000U, 0xdf1e0000U, 0x46370000U, 0xff8e8000U, 0xb22fc000U, 0xa23b6000U, 0xb2e29000U, 0xe7f28800U, 0xd7aef400U, 0x7e7cfe00U, 0x7a815900U, 0x89c21e80U, 0xbc20cfc0U, 0xf2527e20U, 0x5bbe9930U, 0x74a17e98U, 0xfa965fc4U, 0x411ef626U, 0xb5376d3fU, 0xb80b0082U, 0x376cc6f3U, 0x90d98891U, 0x951232c2U, 0x505d769cU, 0xb9d76be4U, 0x1cf96837U, 0xcf44a40dU, 0x5fe3960dU, 0x9376fd0aU, 0x756908aaU, 0xd9daf2e2U, 0x779096acU, 0x259e3be0U, 0xff68009U, 0x23abc03cU, 0x507d601eU, 0xe1819004U, 0xfa420831U, 0x77663414U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xb0000000U, 0x78000000U, 0xe4000000U, 0xde000000U, 0x8b000000U, 0x44800000U, 0xdcc00000U, 0xeb200000U, 0xb0700000U, 0xb0e80000U, 0x8f40000U, 0xa62a0000U, 0x2ed30000U, 0x8ddf8000U, 0xa078c000U, 0xddcca000U, 0xc7843000U, 0xa443f800U, 0x5de59400U, 0xc653de00U, 0x531f6d00U, 0x1a5aed80U, 0xcc3c5240U, 0x1c2c5e20U, 0x3bd7ad10U, 0xa25e4db8U, 0x883c626cU, 0x922da63eU, 0x78d53929U, 0x7ad8138fU, 0x6ef8cf4eU, 0x2c0c6bafU, 0x7219b5eU, 0x52711595U, 0x51edc672U, 0xd175803bU, 0x296bc030U, 0x67b32002U, 0x5f4cf010U, 0x84475837U, 0x4de5a406U, 0xee522602U, 0x7f1df903U, 0x585cb38dU, 0x7d38ff66U, 0xdad9399U, 0x28930f50U, 0xd13f4b91U, 0xfad6b79U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x50000000U, 0xa8000000U, 0x2c000000U, 0xa000000U, 0xd000000U, 0xd800000U, 0xf3400000U, 0x49600000U, 0x53300000U, 0x2ae80000U, 0x6ab40000U, 0x67ae0000U, 0x50d10000U, 0xea1c8000U, 0x7fc4000U, 0x1c09e000U, 0x83c21000U, 0x8fa08800U, 0xcd12fc00U, 0x46b95200U, 0xbc6a5700U, 0xb765b80U, 0xa9084840U, 0x6a45d220U, 0xaae61730U, 0x7b77bba8U, 0x910e5854U, 0x4e435a0aU, 0xdce1eb3bU, 0xd47469aaU, 0xbd8d4f57U, 0xba866189U, 0x6bc2f347U, 0xc3a25398U, 0x3712f473U, 0xb3bb602bU, 0x35ef5009U, 0xde35e80bU, 0xe76cac1cU, 0x39f03a1bU, 0x7ecabb2fU, 0xabe7818dU, 0xecf4e35fU, 0x674cdba2U, 0x76a10870U, 0xde96b21fU, 0x96fd4731U, 0x838c538aU, 0x983f449U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xb0000000U, 0xe8000000U, 0xcc000000U, 0xba000000U, 0x1d000000U, 0x6c800000U, 0x37400000U, 0x6e00000U, 0x9ad00000U, 0x3dd80000U, 0xcc540000U, 0x579a0000U, 0x46330000U, 0x4a0f8000U, 0x950c4000U, 0xd08de000U, 0x454b9000U, 0x47ea0800U, 0x345d7400U, 0xa394f200U, 0xa83f2300U, 0xe907f480U, 0x28125c0U, 0x54437220U, 0xb1676310U, 0x8e1014b8U, 0xb1f9b5ecU, 0xb1a6fa1aU, 0xdc365723U, 0x47090696U, 0x418d06ebU, 0x73cb0681U, 0xddaa06eeU, 0xb63e86b7U, 0xc20546ddU, 0x2904e6b6U, 0xa28696f1U, 0x4410e98U, 0xe96772ffU, 0xaa12748aU, 0xc7fe65d3U, 0x16a11237U, 0xadb0b323U, 0x1ccffcbaU, 0x702b51e8U, 0xeffa0028U, 0x7aa30016U, 0x47b7802fU, 0x59c8400aU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0x18000000U, 0x2c000000U, 0x62000000U, 0x4b000000U, 0xbd800000U, 0x5cc00000U, 0xb4200000U, 0x31900000U, 0xee880000U, 0x7e140000U, 0x414e0000U, 0xebb70000U, 0x86188000U, 0xce1fc000U, 0x3a1de000U, 0x141ad000U, 0xed1cb800U, 0x399bc00U, 0xcede9e00U, 0x443d7d00U, 0x8a8c0280U, 0xe8105140U, 0x244e1e20U, 0xaf36bd30U, 0x345fe298U, 0xb77d8174U, 0x816a2626U, 0x3420c13bU, 0xf1949c80U, 0x8e8e2c66U, 0xae149c89U, 0x594e2c6cU, 0xc7b49c8dU, 0xe41e2c5aU, 0x851c9caaU, 0x879a2c47U, 0x48da9c9bU, 0x59392c6bU, 0x320c1c93U, 0x2051ec66U, 0x3a297cbaU, 0xcbc4fc79U, 0x3a02485U, 0xa253906aU, 0x612c02b2U, 0xe405177U, 0xa3661e37U, 0x6c72bd2aU, 0x80000000U, 0x40000000U, 0x20000000U, 0xd0000000U, 0x98000000U, 0xb4000000U, 0xb2000000U, 0xf9000000U, 0x2d800000U, 0xa2400000U, 0xd3e00000U, 0x39300000U, 0xaf980000U, 0x9eb40000U, 0xd0da0000U, 0x6ad50000U, 0xd6ac8000U, 0x1129c000U, 0x9e6d2000U, 0x220e5000U, 0x87be800U, 0x7581bc00U, 0x76463a00U, 0x91e48300U, 0x88316380U, 0xae19b7c0U, 0x3af2ba20U, 0x48394310U, 0x87664388U, 0xf6f2e7f4U, 0xfe3dd206U, 0xa4653f3dU, 0xde7759a4U, 0xeffd34caU, 0x2ac3d98dU, 0x5220f4d5U, 0xf94f9b0U, 0x47cba4d4U, 0x54db91aeU, 0xf0d7d8c6U, 0xf3aa8ba2U, 0x72a80be3U, 0x5b2c8037U, 0x2369c03cU, 0xf58d202eU, 0x7f3e5013U, 0x8de3e829U, 0xa635bc0bU, 0x391c3a36U, 0xa0718309U, 0xa0fde3b5U, 0x244077e9U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x70000000U, 0x38000000U, 0x74000000U, 0x2000000U, 0x4d000000U, 0x9c800000U, 0xdfc00000U, 0x40e00000U, 0x30300000U, 0x9380000U, 0x82b40000U, 0x7dfe0000U, 0x79d50000U, 0x7f8d8000U, 0x3d4cc000U, 0x692a2000U, 0xeadad000U, 0xa5014800U, 0x6081b400U, 0xb1c47600U, 0xbe71300U, 0xdbb76780U, 0x737f72c0U, 0x8311f620U, 0x9fefd330U, 0x9cbb4788U, 0x1bf4a2dcU, 0x8bdb3e2eU, 0xdf83a72dU, 0x98469188U, 0x1ca0a1cfU, 0x3692b189U, 0x76af71daU, 0x529e79b8U, 0xc9a205f3U, 0x6e102f83U, 0xb36fc6e6U, 0x5b7e0029U, 0x5f150030U, 0x81ed803cU, 0xefbcc00aU, 0x8472203cU, 0xf39ed011U, 0x93274803U, 0xe6d0b41fU, 0x260ff61cU, 0x120ad33dU, 0xf00ec78dU, 0xed0c62f9U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xf0000000U, 0x28000000U, 0xc000000U, 0x2000000U, 0x39000000U, 0xa5800000U, 0x1b400000U, 0x3ca00000U, 0xb2500000U, 0xd5780000U, 0x61d40000U, 0xe13e0000U, 0xc7f50000U, 0x2aa98000U, 0x83ec4000U, 0x4e4de000U, 0x859a5000U, 0x91a52800U, 0xd1d4fc00U, 0x293eb200U, 0x1bf67900U, 0xf0abb080U, 0x9eeedac0U, 0xe5cf3220U, 0xa5de3930U, 0x31805088U, 0xdd458afcU, 0xdba59a2aU, 0xf4d78533U, 0x76bc8288U, 0xedb4e3f2U, 0x4f896283U, 0xfab3f5U, 0x92924aa7U, 0xf19b4feeU, 0x87a578beU, 0xeed176d1U, 0x4bbb2815U, 0xb631fc1cU, 0x47cf3214U, 0xacde390fU, 0x9c005087U, 0x3a058af7U, 0xcd059a1dU, 0x73878518U, 0x44482baU, 0xae20e3d8U, 0x379762baU, 0x6e1fb3c5U, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0x88000000U, 0xc000000U, 0x46000000U, 0x63000000U, 0x7a800000U, 0xf2c00000U, 0x68e00000U, 0x9cd00000U, 0x57980000U, 0x5540000U, 0x9fda0000U, 0xbf750000U, 0x9bed8000U, 0xfc394000U, 0xc521e000U, 0x20b57000U, 0x868df800U, 0x7eae2400U, 0x139eae00U, 0x2f55c300U, 0x6aded880U, 0xdef7f7c0U, 0x97a92e20U, 0x2c198310U, 0x1412b888U, 0xf27bc7fcU, 0x5c053602U, 0x7e02d713U, 0xc701ee99U, 0xc08020e4U, 0x5fc5409cU, 0x7d60e3efU, 0x52961823U, 0xaebe5413U, 0x8be6d621U, 0xa656a702U, 0x855b968eU, 0x9db244d3U, 0x8b0f8e9cU, 0xe4ed10caU, 0xd8bed8baU, 0xe7f7d0U, 0xd12e02U, 0x499d8329U, 0x1250b8bcU, 0x275ac7caU, 0x64b2b637U, 0xac8e970fU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x30000000U, 0x48000000U, 0x94000000U, 0x72000000U, 0xfb000000U, 0xa2800000U, 0x4f400000U, 0x42200000U, 0x52100000U, 0xc7580000U, 0x3940000U, 0x1e9e0000U, 0x2cf70000U, 0x8daf8000U, 0xc73d4000U, 0xe0272000U, 0x1114d000U, 0xd9d9f800U, 0x9ad14400U, 0x9dbd4200U, 0xb3673500U, 0xd5332280U, 0x32cfa7c0U, 0x4c0cc220U, 0xe7ed7530U, 0xd29b8298U, 0x12f637ccU, 0x88aa1a32U, 0xbce115U, 0x58e13884U, 0xa3f746f2U, 0xad2bfa9aU, 0x5b7933c6U, 0xa481f834U, 0x36454416U, 0x33a34213U, 0x1bd0353aU, 0xf03ca299U, 0x7ca2e7c4U, 0x5b53e206U, 0x5c7da52cU, 0x70047a9fU, 0xe80473c4U, 0xc406d806U, 0xa019416U, 0x2702ba2dU, 0x44857111U, 0xc647e09dU, 0x1ba6d2e6U, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0xc8000000U, 0xec000000U, 0x2000000U, 0x77000000U, 0x2f800000U, 0x3c00000U, 0x63600000U, 0x94700000U, 0xc9f80000U, 0x14f40000U, 0x51ba0000U, 0x82550000U, 0x7ad8000U, 0xa15b4000U, 0x6fe6e000U, 0xde355000U, 0x105a5800U, 0x4964ac00U, 0x9f708600U, 0xfc7c1700U, 0xb4349580U, 0x3b5bd0c0U, 0x8ce70620U, 0xf7b25710U, 0x7a9ff588U, 0xb885c0fcU, 0xbc43be12U, 0x78a7ab2bU, 0x23172b88U, 0x7b8c7be1U, 0x44082d99U, 0x1fca2cebU, 0x88add830U, 0xcadaec14U, 0x5223e603U, 0xf0560702U, 0xf8aa2dbeU, 0x42db2ce3U, 0x9e225818U, 0x250ac20U, 0x47aa8614U, 0x8159170eU, 0x9fe1159dU, 0x163490e1U, 0xfc5be63aU, 0x4b620720U, 0xe8702dbfU, 0xd3fe2ce8U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x50000000U, 0x8000000U, 0xc4000000U, 0xea000000U, 0x15000000U, 0x17800000U, 0x2cc00000U, 0x6be00000U, 0x5500000U, 0x34280000U, 0xf3d40000U, 0x5d6e0000U, 0x1df50000U, 0x525c8000U, 0x334d4000U, 0xd2c6a000U, 0x5ce01000U, 0xe3d50800U, 0xb56d2c00U, 0xa9f3ae00U, 0xe05c9300U, 0xea4bb480U, 0xeb426a40U, 0x8f212e20U, 0x8ab4d330U, 0x8b799488U, 0xdafb3a54U, 0x7d3c8622U, 0x865cef01U, 0x314bb2b2U, 0x73c3c551U, 0xf9643ca7U, 0x1613064aU, 0xe70ea008U, 0x7f641020U, 0xbd130802U, 0x278c2c12U, 0xc5212e35U, 0xfb4d332U, 0xb4f994a6U, 0x623b3a7eU, 0xf4dc861cU, 0x520cef2aU, 0xf8e3b2b3U, 0xb9d7c548U, 0xd86a3ca6U, 0x22760655U, 0xea9a2013U, 0xbaad503dU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0x48000000U, 0x94000000U, 0x26000000U, 0xdd000000U, 0xe3800000U, 0xf3400000U, 0x47600000U, 0x59300000U, 0x19880000U, 0x1bb40000U, 0xab4e0000U, 0xcc930000U, 0x679f8000U, 0x66e94000U, 0xbe872000U, 0xd0c27000U, 0x5424c800U, 0x2e55ec00U, 0x8bf9200U, 0x963cb700U, 0x96f88b80U, 0xbade0340U, 0x488e1220U, 0xf236f730U, 0x9f082bb8U, 0x3771334cU, 0x9d6bfa32U, 0x61c66b15U, 0x8da2f1b1U, 0x5212287bU, 0x675c438aU, 0x4acbef69U, 0x4cd18000U, 0x6a7a401dU, 0x3918a014U, 0x862b3013U, 0xa2a3e820U, 0x6a979c37U, 0x7a9b5a2eU, 0x65695b14U, 0x7dc719acU, 0xdfa2b46dU, 0x991699bbU, 0x11d8f472U, 0xce0e3999U, 0xdef3c458U, 0xa92dd189U, 0x9a245856U, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0x88000000U, 0x24000000U, 0x86000000U, 0xd5000000U, 0x3f800000U, 0xddc00000U, 0xa2600000U, 0xb6100000U, 0xe8d80000U, 0xa0940000U, 0x909a0000U, 0x350000U, 0x3c6d8000U, 0x67b94000U, 0xc500a000U, 0x27837000U, 0xa1c10800U, 0x78660c00U, 0x49152600U, 0xa059ff00U, 0x11d5c680U, 0x5bf01c0U, 0xf602a620U, 0x1d05bf10U, 0x3b80e688U, 0xabc131fcU, 0xff610e02U, 0xad91c319U, 0xb31b48a9U, 0xd7f682c9U, 0x190ece8dU, 0x352c0deeU, 0x3e9a0021U, 0x41350034U, 0x2ded801fU, 0xbb79402aU, 0x56e0a00fU, 0xbd537011U, 0x52f9081bU, 0x66220c33U, 0xacb72632U, 0x6b28ff13U, 0xf79a46b5U, 0x74b741c2U, 0x772d861dU, 0xfd9e8f19U, 0xf3b6ce8fU, 0x93a80dfaU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0xd8000000U, 0x6c000000U, 0x52000000U, 0x2b000000U, 0x55800000U, 0x9bc00000U, 0x56600000U, 0x18700000U, 0x98a80000U, 0x74f40000U, 0x9dee0000U, 0x1cd50000U, 0x40388000U, 0x7e6bc000U, 0x8a17e000U, 0x76db5000U, 0x159b800U, 0x799a7c00U, 0xee7b2600U, 0x83cc6f00U, 0xec049580U, 0x9201a240U, 0xb05a620U, 0x8586af30U, 0x43c5f588U, 0x3a643274U, 0x4a737e16U, 0xb3ac432bU, 0x21708b9cU, 0x629717eU, 0x4ab57583U, 0x584bf24dU, 0xe6c29e29U, 0xfee61308U, 0xeb37b38dU, 0x1d89cd54U, 0x39a733b0U, 0x90160d60U, 0x9ded39fU, 0x9ad85d6aU, 0x935feb9bU, 0x7299e165U, 0x6bfb2da9U, 0xc00ade4fU, 0xd6600007U, 0xd8700014U, 0xb8a80026U, 0xa4f40027U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0x88000000U, 0x44000000U, 0xf6000000U, 0xef000000U, 0x47800000U, 0x38c00000U, 0x8fe00000U, 0x20700000U, 0xcc780000U, 0x96f40000U, 0x283e0000U, 0xe8550000U, 0x4c688000U, 0xf6394000U, 0x5356a000U, 0x55ecf000U, 0xb5fed800U, 0xe5354c00U, 0xe65fde00U, 0x47e05300U, 0x8474cd80U, 0xca7838c0U, 0x21f15e20U, 0xa3b81330U, 0x6294ed88U, 0xda8888f4U, 0x7ec9a602U, 0xe06cef21U, 0x743d4bb5U, 0x325467cfU, 0xe16ced93U, 0xf0bc88efU, 0xf17a636U, 0x1749ef37U, 0x3badcb88U, 0x2e5927ceU, 0xe3e44d96U, 0x827578e8U, 0x7d79fe24U, 0xaa71e329U, 0x297ab586U, 0xf47084ccU, 0x527ed811U, 0xcdf54c33U, 0xc1bfde30U, 0xf390531aU, 0x360ccd85U, 0xf78c38dbU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x50000000U, 0x38000000U, 0xfc000000U, 0xc2000000U, 0x27000000U, 0x32800000U, 0x8ac00000U, 0x84200000U, 0x17d00000U, 0xf6980000U, 0x44540000U, 0x77de0000U, 0x2d330000U, 0x136c8000U, 0x341ac000U, 0x86976000U, 0x87fed000U, 0x6ce75800U, 0xc4f2c400U, 0x5bcc4e00U, 0xac0ac500U, 0xb1a80080U, 0x5439d9c0U, 0x1f46ce20U, 0xfc670530U, 0xf935e0b8U, 0x356ac9d4U, 0x9d1c762eU, 0x3916d10fU, 0xdcbb1688U, 0x6e85d8ddU, 0x38c480a2U, 0x2b2319edU, 0xb151ae09U, 0x7a59d528U, 0xd972b887U, 0xb7880dd8U, 0x44e83822U, 0x6b581408U, 0x5af5163dU, 0xcecb0123U, 0x3188ce9fU, 0x9de9dcf2U, 0x5cd9ae93U, 0x95b00cd1U, 0xcaac7683U, 0xd4bb08d6U, 0x3a83d899U, 0xdec1ddfcU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0x18000000U, 0x6c000000U, 0xaa000000U, 0x81000000U, 0x50800000U, 0xdac00000U, 0xf3200000U, 0xdd500000U, 0x15b80000U, 0xf2d40000U, 0x8fe0000U, 0x18b10000U, 0x51ce8000U, 0x1b39c000U, 0xaf11e000U, 0x205e9000U, 0xdea6e800U, 0x25119400U, 0x715c7e00U, 0x3627ad00U, 0x83d7a480U, 0x307fd8c0U, 0x674fe20U, 0x6ceb6d30U, 0x996ec4a8U, 0xad2d88c4U, 0x73cb7626U, 0x2e38a92bU, 0x99953282U, 0xc19de1e4U, 0xe40124b2U, 0x1e0218ddU, 0xe7031e1eU, 0x6b80fd23U, 0x1340acbfU, 0x1560dcd5U, 0x5eb66832U, 0xbac9543aU, 0x6abb1e07U, 0x3554fd28U, 0x11beac87U, 0x9cd1dcd4U, 0x47f8e810U, 0x17309414U, 0x9c8afe0cU, 0x495a6d0dU, 0x8a2044bbU, 0x91d448e9U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0xa8000000U, 0xec000000U, 0x32000000U, 0xb7000000U, 0x11800000U, 0x6400000U, 0x7b600000U, 0x5b300000U, 0x5a80000U, 0x1d740000U, 0xdece0000U, 0x76470000U, 0x23648000U, 0x2f364000U, 0x23ade000U, 0xdc70d000U, 0xa64cd800U, 0xe4861c00U, 0xf8c10a00U, 0x18a51700U, 0x170b80U, 0xe4ff2640U, 0x3b6cea20U, 0x54d5c730U, 0x6e5bd398U, 0xbc793a54U, 0x59ade00aU, 0x1770d00bU, 0x4dccd814U, 0xe9c61c39U, 0x8210a2eU, 0x1ed5173aU, 0x5d5f0b92U, 0x13fb267bU, 0x8aeaea25U, 0x6296c736U, 0xed3953b1U, 0xa34c7a5fU, 0x82028003U, 0x8f054007U, 0x3587602bU, 0x88419013U, 0x5665b80fU, 0x11b08c08U, 0x20683224U, 0xd757db0aU, 0xef1cd9acU, 0x2e9f2d46U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0x8000000U, 0x3c000000U, 0xfe000000U, 0xed000000U, 0xae800000U, 0x54400000U, 0xba600000U, 0x94f00000U, 0xf4180000U, 0xf0b40000U, 0xf67e0000U, 0x20410000U, 0x18608000U, 0xf7f54000U, 0x6f9f6000U, 0x3e73b000U, 0xda588800U, 0x1dd38400U, 0x3b0d4a00U, 0x999e700U, 0x87736580U, 0xc6dec3c0U, 0x82922a20U, 0xf6ea5730U, 0xa5abeda8U, 0x8e4d47f4U, 0x5b7f6022U, 0xeec3b03fU, 0x3c208817U, 0x9597840fU, 0xcf6b4a29U, 0x86ce71aU, 0x39ede591U, 0xa82a83deU, 0xe18dca36U, 0xffdca719U, 0x5e1405bbU, 0xc9a973d9U, 0xb84ca219U, 0x2a7cd33eU, 0x6e4027b1U, 0x8d64e0c8U, 0xbd75e5b9U, 0xf1de83d0U, 0xab13ca0cU, 0xf32da717U, 0xfe0c85abU, 0x8b1833e4U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x50000000U, 0xf8000000U, 0x14000000U, 0xda000000U, 0x33000000U, 0xcc800000U, 0xb7400000U, 0xae600000U, 0xc8700000U, 0xbd080000U, 0xf7340000U, 0x6f6e0000U, 0xa9410000U, 0x7f648000U, 0x83f2c000U, 0x4cca2000U, 0x25151000U, 0xd1ff3800U, 0xb179b400U, 0xa83ca200U, 0x1f5bd700U, 0x80aed980U, 0xaa640b40U, 0x8a768220U, 0x6a0ec730U, 0x49b1e1a8U, 0x72dbf54U, 0x5a2201eU, 0xe9511035U, 0x6f19381eU, 0x84cb418U, 0xee56220dU, 0xe9981728U, 0xd408799dU, 0xc8b7db7eU, 0xb4ad9a3cU, 0xe0636320U, 0xe176fb98U, 0xe28d1c4cU, 0xdcf27baeU, 0x8e4fdc68U, 0xdb505bb6U, 0xd01ecc4bU, 0xfac963aeU, 0x18127840U, 0x547f4192U, 0xa9ba6f51U, 0x859f3808U, 0xda09b43bU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x70000000U, 0x68000000U, 0x8c000000U, 0xe2000000U, 0x19000000U, 0x83800000U, 0x61400000U, 0x25600000U, 0x9d900000U, 0x37b80000U, 0xf0d40000U, 0xb0da0000U, 0xd4410000U, 0x74e18000U, 0x2dd64000U, 0x6d5fe000U, 0x86005000U, 0x3706a800U, 0xd8860c00U, 0x8bc04200U, 0xafa67700U, 0x55b38680U, 0x6d4f86c0U, 0x43ffa220U, 0xf4362710U, 0xf50d2ea8U, 0x351d8adcU, 0x10e5e03aU, 0x3d15033U, 0x365f2810U, 0x6c844c1aU, 0xbdc5a23aU, 0x10a7273bU, 0xd134aeb1U, 0x1c8fcae1U, 0x1158000dU, 0x4c040034U, 0x202000dU, 0xc905000eU, 0x9b83800aU, 0x85434014U, 0x4b64600fU, 0x66971012U, 0xad38c830U, 0x12101c25U, 0xf4f90a30U, 0x6cb02b2dU, 0xdecd6c95U, 0xeabbfdd1U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0x78000000U, 0xbc000000U, 0xc2000000U, 0x49000000U, 0x1b800000U, 0x12c00000U, 0xe200000U, 0xa8700000U, 0x1ff80000U, 0x3eb40000U, 0x4fde0000U, 0x4dc30000U, 0xcaa38000U, 0xbe34c000U, 0xe7986000U, 0xdea1d000U, 0xc831a800U, 0x4899cc00U, 0x42235e00U, 0x32756d00U, 0xbaff3580U, 0x2f371ec0U, 0xd01b3e20U, 0x2664bd30U, 0xfb169db8U, 0xfd6ad2ecU, 0x781e603eU, 0x9266d01fU, 0x1d142808U, 0x7a6a0c3eU, 0x909ebe18U, 0x6e277d2bU, 0xd8737db3U, 0x87fcc2f8U, 0x32b42821U, 0xf5da0c3bU, 0xb8c6be28U, 0x13237d15U, 0xe5f57dabU, 0xf23bc2cfU, 0x6411a83aU, 0xd9e9cc06U, 0xde5b5e3eU, 0x12016d15U, 0x410135b4U, 0x3f841efeU, 0xdcc0be0bU, 0xfd247d34U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0x18000000U, 0x34000000U, 0x8a000000U, 0xd3000000U, 0x90800000U, 0x78c00000U, 0xa6e00000U, 0x31300000U, 0x15280000U, 0xc5f40000U, 0xddce0000U, 0x95c50000U, 0xaf668000U, 0x2a71c000U, 0x4b892000U, 0x32e09000U, 0x6b313800U, 0xfe29d400U, 0x7171de00U, 0x370f7300U, 0xd426ef80U, 0x84d74e40U, 0x9498fe20U, 0xb81fe330U, 0xa6dfd788U, 0x4d3a9a44U, 0xa58f2026U, 0x93e1903dU, 0x2cb1b82aU, 0x94691430U, 0x50507e22U, 0x8e5b2313U, 0xd1f8778bU, 0xb16fca78U, 0x55d13801U, 0x3b19d41fU, 0xce59de16U, 0x31fb732dU, 0x8168efa8U, 0x5dd24e76U, 0x171e7e27U, 0x705e232dU, 0x68fef79dU, 0xc2ee0a6fU, 0xb5901801U, 0xc93d4430U, 0xe78ee600U, 0x4ce3a71fU, 0x80000000U, 0x40000000U, 0x60000000U, 0x30000000U, 0x88000000U, 0x1c000000U, 0x4a000000U, 0x4d000000U, 0xfc800000U, 0x22400000U, 0x8b200000U, 0x15900000U, 0x5cf80000U, 0xadd40000U, 0x62da0000U, 0xb0c70000U, 0x7a638000U, 0x19374000U, 0xa0a96000U, 0x61ca1000U, 0x937c8800U, 0x7810b400U, 0xe83bfa00U, 0x19b17d00U, 0xb8ee9e80U, 0x4fef4ec0U, 0x566a9a20U, 0xc4af6d10U, 0x9fc81698U, 0xd878faccU, 0x3b92e002U, 0xeff95017U, 0x1a57e80aU, 0x319a41fU, 0x3c26f21dU, 0x6c15890fU, 0xfe3d84b0U, 0x7eb063d6U, 0x39686c88U, 0x192ac7f3U, 0xe30f1e82U, 0x101b0ef5U, 0x9ba27a13U, 0xd5d13d36U, 0xd6dc7e98U, 0xb6c61eecU, 0xc5657215U, 0x3cb2c914U, 0x286ce485U, 0xcfae73ccU, 0xbc4ee482U, 0xefbd73fcU, 0x80000000U, 0x40000000U, 0x20000000U, 0xd0000000U, 0x18000000U, 0x2c000000U, 0xbe000000U, 0xc7000000U, 0xe2800000U, 0x1b400000U, 0x3be00000U, 0xe8d00000U, 0x7780000U, 0x31940000U, 0x1d9a0000U, 0xf0c50000U, 0x8d248000U, 0x3ef1c000U, 0x8d0fe000U, 0x84d93000U, 0xca215800U, 0x9c71e400U, 0xb6496200U, 0x6f3c8b00U, 0x3af03c80U, 0xb70e74c0U, 0x39de8220U, 0xb5a1bb10U, 0x28b36488U, 0x216e90f4U, 0x3cc96026U, 0xd079f01bU, 0xab103827U, 0xdadc1405U, 0xbd235a3eU, 0x96f59f0dU, 0x490fe6a1U, 0xdede2bcbU, 0x87248499U, 0x2bf3a0daU, 0x368a3821U, 0x6a191422U, 0x1007da2cU, 0x78045f3cU, 0xdc00068dU, 0x76071be7U, 0xf305dca6U, 0x708244cfU, 0x62435a10U, 0x1e659f22U, 0x1117e6bdU, 0x27da2bc3U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xf0000000U, 0x98000000U, 0xd4000000U, 0x6000000U, 0x91000000U, 0xb3800000U, 0xd7c00000U, 0x2b600000U, 0xef900000U, 0x5f180000U, 0x3a540000U, 0x2b7a0000U, 0xab430000U, 0xaa258000U, 0xb6b3c000U, 0xb5292000U, 0x5e38f000U, 0xa4642800U, 0x5910ac00U, 0xdd5ab600U, 0xa7f38700U, 0xc409a280U, 0x180e33c0U, 0xe20b9620U, 0xd90f7710U, 0xd98f8ab8U, 0xb2c99ffcU, 0xb8eea006U, 0x1e5c3025U, 0xc3728839U, 0xd1489c18U, 0xa72a3e0aU, 0x693c1b00U, 0x96e41c8bU, 0x5556e8dfU, 0x6df92a9bU, 0xb101afebU, 0xe3862818U, 0x5fc7ac3dU, 0x97653623U, 0xa593472aU, 0x1c1d0280U, 0x1ed103ecU, 0xde3c9e0eU, 0xe4642b3aU, 0xb9149484U, 0x2d5974ccU, 0x3ff49483U, 0x100974c0U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xf0000000U, 0xc8000000U, 0xfc000000U, 0xfe000000U, 0x81000000U, 0x3e800000U, 0x30c00000U, 0x13600000U, 0x8a300000U, 0xfec80000U, 0xf0f40000U, 0x2eaa0000U, 0xdb430000U, 0xaf258000U, 0xfe914000U, 0xd4186000U, 0xbc4db000U, 0x7e35e800U, 0x5ccb0400U, 0x9ff10e00U, 0xa92aaf00U, 0xe1077780U, 0x8e82fd40U, 0x18c16e20U, 0x1f631f10U, 0xbc309fb8U, 0x83cef97cU, 0x3077e012U, 0x9f6ff02fU, 0xf6a00807U, 0x15d3f41cU, 0x133e863dU, 0xaedb1b33U, 0x6c2c11bbU, 0x55811642U, 0xdd42f790U, 0xba23bd60U, 0xd2110e17U, 0xa3daaf38U, 0x24af779eU, 0xf846fd40U, 0xfea36e13U, 0x49d41f16U, 0xfd3f1fbcU, 0x17dcb978U, 0x66aa000bU, 0x67430004U, 0xb125801bU, 0x8f914036U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xd0000000U, 0x48000000U, 0xc4000000U, 0xf2000000U, 0x73000000U, 0x24800000U, 0x1dc00000U, 0xe7600000U, 0x2d700000U, 0x1780000U, 0x5eb40000U, 0x4b1a0000U, 0x22430000U, 0x6a248000U, 0x5dd54000U, 0xe468a000U, 0x2839d000U, 0x4c13b800U, 0x750bb400U, 0x644ef600U, 0xcaecdf00U, 0x5afce580U, 0x11f100c0U, 0xd0be5620U, 0x6fd10f10U, 0x376d5db8U, 0x3cbdb4f4U, 0xc9d62032U, 0x1e6f9021U, 0x7f3f9804U, 0x4a972428U, 0x53cdee1bU, 0x63aabb36U, 0x85bab85U, 0xcfe56bd7U, 0x46b0c5a9U, 0x871d90c0U, 0xf4454e33U, 0x3b236b27U, 0x425013b0U, 0x192adfc5U, 0x209c33a5U, 0xf5064fffU, 0x7d872ba4U, 0x26442bf5U, 0x3822659aU, 0x1ed740e1U, 0x58ea760aU, 0xb9f99f0cU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0x68000000U, 0x2c000000U, 0x8e000000U, 0x7000000U, 0x16800000U, 0x93c00000U, 0x10a00000U, 0x96700000U, 0xadd80000U, 0xffb40000U, 0x607e0000U, 0xd2470000U, 0x3de08000U, 0x59104000U, 0x750fe000U, 0xab1b3000U, 0x8935800U, 0x5049c400U, 0x987d2600U, 0x3647f100U, 0x2fe70d80U, 0x68157bc0U, 0x208ac620U, 0x8c58c130U, 0x2f25598U, 0xc71fbff4U, 0x2691603aU, 0xe74c703bU, 0x36fc383bU, 0xe182b435U, 0x9d419e1fU, 0x7765052fU, 0x9cd173a7U, 0xf6af4ee4U, 0xe1eeed8eU, 0x938d4bebU, 0x20df1e24U, 0xec324515U, 0xdc3e13a6U, 0xf8a43ed6U, 0x7a72559cU, 0x43dfbfe4U, 0x28b16013U, 0x1efc7023U, 0x6d843838U, 0xa346b419U, 0xc8679e1fU, 0xce56051eU, 0x80000000U, 0x40000000U, 0x20000000U, 0xd0000000U, 0xb8000000U, 0x74000000U, 0xae000000U, 0x59000000U, 0xfa800000U, 0x11c00000U, 0xdbe00000U, 0x45f00000U, 0x15780000U, 0xd9340000U, 0xa1a0000U, 0x4c050000U, 0x9a048000U, 0xd704c000U, 0x73852000U, 0x5340b000U, 0xbe216800U, 0x3012a400U, 0x98a4600U, 0x36cd0b00U, 0xc2eca180U, 0x9df974c0U, 0x93f56620U, 0x5878bb10U, 0x7db14988U, 0x2adb10f4U, 0xa160000eU, 0x1430000dU, 0xee980023U, 0x4cc40022U, 0xa7620010U, 0xe1310019U, 0x3e1e801dU, 0xc201c007U, 0x1301a03bU, 0x95847032U, 0x16444834U, 0x26a21402U, 0xa2d32e23U, 0xdfebaf03U, 0xc17ce79eU, 0xe7317fc7U, 0xcb1d47a9U, 0x12850fe9U, 0x9dc10fb6U, 0x21e31bfdU, 0x62f02199U, 0xef9b4d2U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0x68000000U, 0x1c000000U, 0x1a000000U, 0xb7000000U, 0x1a800000U, 0xedc00000U, 0xeaa00000U, 0xf9700000U, 0xd3980000U, 0x4fb40000U, 0x11ba0000U, 0x10030000U, 0x58018000U, 0x94044000U, 0x76036000U, 0xc5039000U, 0xb1855800U, 0xed400400U, 0xb062d600U, 0x9578100U, 0xc728a580U, 0x768dc9c0U, 0xa77bb620U, 0xd2271110U, 0x7b47db8U, 0xddbd8ddcU, 0xf200003aU, 0xeb000017U, 0xe080003eU, 0x2ac00031U, 0x9820001cU, 0x8b0003cU, 0x2338003cU, 0x1c40013U, 0xd8a20032U, 0xb2770028U, 0xa31b803eU, 0x7d77403aU, 0xfd9ae022U, 0x1eb3d036U, 0xd63c3819U, 0x38409435U, 0x59e60e3aU, 0x7013c51eU, 0x14913b1U, 0xbad9d8f3U, 0xd1d64bbdU, 0x49eadcf6U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0x38000000U, 0x4000000U, 0x36000000U, 0x2f000000U, 0x1e800000U, 0x5400000U, 0x72e00000U, 0x3c100000U, 0x22180000U, 0xaa540000U, 0xbc7e0000U, 0x6a030000U, 0x6d038000U, 0xdf86c000U, 0x80c5a000U, 0x67207000U, 0x60b15800U, 0x44694400U, 0x9e1d5200U, 0x58516300U, 0x4578ca80U, 0xeb8407c0U, 0x4ec6f220U, 0xac221330U, 0xf83212b8U, 0x562f83ecU, 0xf678002eU, 0x57040031U, 0x3a860035U, 0x63470027U, 0xd5e58009U, 0x1e91c000U, 0x15582011U, 0xc1b5b004U, 0xb1ef780fU, 0x53dbf42bU, 0xb0f7aa33U, 0x2d0b5715U, 0xf4cf4093U, 0x826ee0ddU, 0xa918caafU, 0x12d407f3U, 0xfe3ef21bU, 0x8a66133aU, 0x5e5412b1U, 0x927883e2U, 0x1105802aU, 0xcd81c011U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x50000000U, 0x8000000U, 0x6c000000U, 0x2000000U, 0x5000000U, 0x1f800000U, 0x27400000U, 0xa2200000U, 0x41900000U, 0xb8280000U, 0x41d40000U, 0x908e0000U, 0x90810000U, 0x91c48000U, 0x38e54000U, 0x91f1e000U, 0x4c185000U, 0xf32f4800U, 0xc952ec00U, 0x54a1200U, 0x36666d00U, 0x5f37f680U, 0xa7ef040U, 0x341df220U, 0x72b3d30U, 0xf523ea8U, 0x3e485c54U, 0x26e28022U, 0xef0402bU, 0x929b6028U, 0xf5ec1015U, 0x43322805U, 0x907bfc12U, 0xf51aba28U, 0x26add111U, 0x27162ca9U, 0xeaef3159U, 0x5db1f6acU, 0x36bbf044U, 0x2f7f7202U, 0xbb9b7d3aU, 0x88695eaaU, 0x91744c78U, 0x75d8a83aU, 0xf7cfbc16U, 0x52a7da0aU, 0x2054c102U, 0xd8ce8486U, 0xb4208d72U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x90000000U, 0x98000000U, 0x84000000U, 0x22000000U, 0x85000000U, 0xd4800000U, 0xc7400000U, 0xd7200000U, 0x9900000U, 0x3b80000U, 0x51d40000U, 0xb11e0000U, 0x81830000U, 0xabc28000U, 0xe463c000U, 0xf4b0a000U, 0x932dd000U, 0x20ec0800U, 0x808db400U, 0xb63f1200U, 0x30119d00U, 0x5c7f3680U, 0x9fb1c4c0U, 0xdca9b220U, 0x602b4d30U, 0xeb6fbeb8U, 0xe24cb0e4U, 0x58dc8006U, 0xb0e0c011U, 0xf3f22030U, 0xa40e1005U, 0xb97ca813U, 0x1b306410U, 0x63eb1a3dU, 0xa3082923U, 0x58fe24b5U, 0xe0f359e5U, 0xff8c04b9U, 0x43bd49d2U, 0x71d0acb2U, 0xc11d2df9U, 0x8983b6afU, 0xb7c104f1U, 0x42639214U, 0x53b15d0dU, 0xc2ad16b3U, 0x332fd4fdU, 0x90ed1a11U, 0x688f2904U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x70000000U, 0x68000000U, 0x94000000U, 0x2000000U, 0xd7000000U, 0xfe800000U, 0xfac00000U, 0x7a00000U, 0x93100000U, 0xeab80000U, 0xe4d40000U, 0x989e0000U, 0xf5870000U, 0x42458000U, 0x50604000U, 0x31372000U, 0x83eb5000U, 0xb20e1800U, 0xc37de400U, 0xc7f06e00U, 0xba494900U, 0x1c8e80U, 0x724108c0U, 0x98614e20U, 0xb5311930U, 0x99e91698U, 0x990bacdcU, 0xabfb803aU, 0xe8374015U, 0x946aa018U, 0x974f1029U, 0x659f3825U, 0xe805b41bU, 0x5405f601U, 0x6203ed11U, 0xa7064085U, 0x968751c7U, 0x6ec2f887U, 0x5a5a5e9U, 0x4415ae92U, 0x143d58c1U, 0x1e12d608U, 0x9f38bd14U, 0x669058beU, 0xa8feb5e8U, 0xb4b496b8U, 0xa9afecd0U, 0x766aa02aU, 0xf04f102fU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x10000000U, 0xe8000000U, 0x4c000000U, 0x3e000000U, 0x4f000000U, 0x63800000U, 0x8ac00000U, 0x97200000U, 0x64300000U, 0xbe480000U, 0x3f40000U, 0x73ea0000U, 0x7d830000U, 0x75c28000U, 0xeca04000U, 0x5af2e000U, 0xb36eb000U, 0x5ac41800U, 0xdf20ec00U, 0xd8312e00U, 0x784f2500U, 0xe8f43780U, 0x62692b40U, 0x8641ce20U, 0xce669510U, 0x61d0afb8U, 0xf95e8744U, 0x438a801aU, 0xf3544003U, 0x1f18e037U, 0xddedb017U, 0x9a869822U, 0xba40ac31U, 0x4863ce2aU, 0x6ad1950aU, 0xf8d82fb7U, 0x504dc762U, 0x4f2e019U, 0xac6eb016U, 0x3144180aU, 0x9e0ec3fU, 0x99112e30U, 0x1f7f2520U, 0xb3c3784U, 0xa45d2b5fU, 0x10bce18U, 0x5d159500U, 0x3d7a2fb1U, 0x723ac772U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0x28000000U, 0x7c000000U, 0xde000000U, 0x7f000000U, 0xa6800000U, 0x6b400000U, 0xe8e00000U, 0xf5500000U, 0xa9180000U, 0x2b140000U, 0xda7e0000U, 0x82850000U, 0x11468000U, 0x2de04000U, 0xb6d36000U, 0x91dfb000U, 0xd3341800U, 0xab0dc400U, 0x84eda200U, 0x4338f300U, 0x366b080U, 0x71966fc0U, 0xaf38c220U, 0x35664330U, 0x52922888U, 0xc7baebc4U, 0x926802aU, 0x60f0402fU, 0x87ab603fU, 0x37dbb01bU, 0x18321823U, 0x9f8cc405U, 0x76ad220dU, 0x2659b322U, 0x99f55083U, 0xfa289fd0U, 0x401f3a2cU, 0x7e95772dU, 0xd1b872a6U, 0x3a212cc5U, 0x20726ab1U, 0xc7e9e8ebU, 0xdbb948afU, 0x27215bcaU, 0x7f49807U, 0x652c8405U, 0xd69e423bU, 0x2dd6030fU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x50000000U, 0x28000000U, 0x14000000U, 0xf6000000U, 0xbf000000U, 0x17800000U, 0xf8400000U, 0x21a00000U, 0xfd300000U, 0x41f80000U, 0x92f40000U, 0xd81a0000U, 0xae630000U, 0x34d08000U, 0x556e4000U, 0x6a3e2000U, 0xd510f000U, 0x4f885800U, 0xa32e8c00U, 0x889ffa00U, 0x3da15100U, 0xef30bb80U, 0x90fd8ac0U, 0x56715a20U, 0xfddfe110U, 0x2a86c3b8U, 0xb6c3f6d4U, 0xb966f82aU, 0x77503c15U, 0xbb298205U, 0xa49f2d3bU, 0x17a7198fU, 0xe23257fbU, 0xe67e1b95U, 0x12b33ac0U, 0xc5bf220dU, 0xb1559d1eU, 0x3c2b618cU, 0x6f1f2bc5U, 0x5de1398aU, 0xa296a7cbU, 0xa7cc438cU, 0x4a8eb6cbU, 0x31a85801U, 0xa25e8c3dU, 0xd6c7fa2fU, 0xa965511fU, 0xbf52bbbcU, 0xff2a8ad7U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xf0000000U, 0x8000000U, 0x24000000U, 0xae000000U, 0x5000000U, 0x17800000U, 0x73c00000U, 0x6c200000U, 0x71500000U, 0xe5e80000U, 0x3d140000U, 0x6e0a0000U, 0x26610000U, 0x2bb58000U, 0x4f1d4000U, 0x2a6aa000U, 0xd2d33000U, 0x202e0800U, 0x28334c00U, 0x7ade7600U, 0x374bbd00U, 0xe205c480U, 0x9f065640U, 0xe4815620U, 0xbd45cd10U, 0x8a616ca8U, 0xe1b62a7cU, 0x44192822U, 0xc8e93c19U, 0xbe90de03U, 0x1bcac13dU, 0x9b403a87U, 0xeb63e755U, 0xf8304490U, 0xc2db164dU, 0xbb4bf634U, 0x9806fd3fU, 0x3c0764aaU, 0xd2016660U, 0x77055e3aU, 0x90878104U, 0xeb429a97U, 0xa364d75cU, 0x7c344cbeU, 0x9cd95a40U, 0xb6480015U, 0xab840007U, 0xe1c2003dU, 0xbb250002U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0xb8000000U, 0xfc000000U, 0xf6000000U, 0x53000000U, 0xff800000U, 0xc2400000U, 0x7e00000U, 0x50500000U, 0x8dc80000U, 0xd1940000U, 0x5e6e0000U, 0xc5250000U, 0xf4778000U, 0x1f3cc000U, 0x766a6000U, 0x71207000U, 0x66727800U, 0x7638cc00U, 0x94ecca00U, 0xe3e7e300U, 0xaa53c080U, 0xb0c9f940U, 0xb1112a20U, 0x2dab5330U, 0xaf83d888U, 0xaa45454cU, 0x53e1980eU, 0xd2517c0fU, 0x6ccb5235U, 0x77179f18U, 0xc6a91291U, 0xac03a64fU, 0x9e03d89cU, 0x7054570U, 0x7d819834U, 0x23417c38U, 0xa1635230U, 0xc8939f16U, 0xe4ef128dU, 0xbbe2a658U, 0x465258a8U, 0xcec88579U, 0xa6127832U, 0xd828cc02U, 0xc8c4ca3cU, 0x123e337U, 0x3e75c094U, 0x9a38f95fU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x70000000U, 0xd8000000U, 0x64000000U, 0x3e000000U, 0x41000000U, 0xdc800000U, 0x84400000U, 0xe2e00000U, 0x76500000U, 0xa180000U, 0xaa940000U, 0xe2be0000U, 0xc7270000U, 0x56758000U, 0x5edc000U, 0xd9bca000U, 0xb4a53000U, 0x87b42800U, 0x73cf9400U, 0x4b4f6a00U, 0x310e1300U, 0xf2ec4080U, 0x283e3fc0U, 0x7e664a20U, 0x5216e330U, 0xf8fcc898U, 0x74c09bdcU, 0x54a30816U, 0x37b06429U, 0xcbca6217U, 0x5f4d770cU, 0xd70da281U, 0xd7e988f8U, 0xcabac897U, 0xbb239bfdU, 0x6c70880dU, 0xaeea427U, 0x9c3d422eU, 0x88628729U, 0xdf10aaaeU, 0xa67eece2U, 0xeb852a96U, 0x15c32cddU, 0x58218a83U, 0x7bf21ccdU, 0xe52ba290U, 0xab1a88e3U, 0xc61148a6U, 0xdef95be8U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x50000000U, 0x58000000U, 0x4c000000U, 0xe000000U, 0x5000000U, 0xc6800000U, 0xcac00000U, 0x5e600000U, 0xb4300000U, 0x83c80000U, 0x4740000U, 0x316e0000U, 0x4f230000U, 0x8a148000U, 0x1d5dc000U, 0x60ece000U, 0xd060b000U, 0x71334800U, 0xa54bc400U, 0x9eb23e00U, 0x370a6700U, 0xb712e780U, 0x7da3540U, 0x1c2a5e20U, 0x97071730U, 0x55854fb8U, 0xa5454154U, 0xc252836U, 0x7d95b423U, 0xe319163bU, 0xf74cd315U, 0xedb771a7U, 0x88f2661U, 0xbd57cfb4U, 0x827f815cU, 0x72fb4809U, 0x613fc417U, 0x4fdc3e35U, 0x28296739U, 0x65066797U, 0x5687f554U, 0x72c6be06U, 0x4267a724U, 0xe23607a0U, 0xcace8565U, 0xccf7163eU, 0xfeafd336U, 0xd7c3f1a6U, 0xf4e2e66fU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0x48000000U, 0x54000000U, 0x1a000000U, 0x7000000U, 0x87800000U, 0x86c00000U, 0xdd200000U, 0xcab00000U, 0xa6680000U, 0xb7f40000U, 0x838e0000U, 0x5650000U, 0xa3d08000U, 0x13bb4000U, 0x85482000U, 0x18409000U, 0x49659800U, 0x65d36c00U, 0x7ab8ce00U, 0xcfce3500U, 0x56021380U, 0xc1043240U, 0xee806e20U, 0xcc45e530U, 0x9367ab88U, 0x42d3ce74U, 0x2d3b3832U, 0x109bc25U, 0xdf23f60eU, 0x11b78935U, 0x4fe9e5b3U, 0xfc37bb74U, 0x962f8b91U, 0x9a935e43U, 0x445ea020U, 0xb4dad008U, 0xed9b380dU, 0x8a79bc12U, 0x3ebf615U, 0x3a33893dU, 0xff2fe5a6U, 0xd016bb67U, 0xa190b8cU, 0x3cb91e7eU, 0x66c80009U, 0x3c84002eU, 0x5f460014U, 0x2ee10024U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x10000000U, 0xf8000000U, 0x34000000U, 0x5e000000U, 0x83000000U, 0x5a800000U, 0x72400000U, 0xc2e00000U, 0xa6700000U, 0xcfe80000U, 0x10b40000U, 0x5c4a0000U, 0xdea30000U, 0xaf928000U, 0xf18c000U, 0x2f1d2000U, 0x9f1b3000U, 0x971cb800U, 0x4b19a400U, 0xd919ca00U, 0x301b2300U, 0xb79bb180U, 0x1c596040U, 0xf67e6a20U, 0xe0acd310U, 0x4bd029b8U, 0x32f8f444U, 0xb1e9981eU, 0x23b6941dU, 0xecf722fU, 0x70e18724U, 0xff70fba8U, 0x406a8351U, 0x6770fb87U, 0x246a8359U, 0x2170fbbdU, 0x836a834cU, 0xddf0fb81U, 0x462a8347U, 0x1b90fba9U, 0x111a837eU, 0x4c18fbbbU, 0xd59e8375U, 0x1d5afb99U, 0xbdf9835dU, 0x216a7b99U, 0x7cf64363U, 0xfdafdbbbU, 0x3256b36aU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x70000000U, 0xe8000000U, 0xdc000000U, 0x32000000U, 0xcb000000U, 0xd1800000U, 0x16c00000U, 0x36a00000U, 0x48700000U, 0xb1d80000U, 0x4d340000U, 0x72be0000U, 0x5e670000U, 0xdfd58000U, 0xb72c4000U, 0xa5a96000U, 0xeecd000U, 0x9489b800U, 0x8d5d9c00U, 0x7f732e00U, 0x82581900U, 0x68f64580U, 0xd19fd3c0U, 0x6d7ce20U, 0x7dac8930U, 0x9ae89d98U, 0x6a899fdcU, 0xec58d81aU, 0x51f54c07U, 0xab1c9614U, 0xb196852eU, 0xb5ceeb8eU, 0x383c8af2U, 0xa1256ba1U, 0xdbb7cad0U, 0xbff98ba0U, 0x91075afaU, 0x6815393U, 0x954216deU, 0x9b65c595U, 0x475093d7U, 0x336d2e0fU, 0xf84f1938U, 0xbcfbc585U, 0x4c8793c0U, 0xda40ae35U, 0x2ce75912U, 0x494a5a2U, 0xc54843eaU, 0x80000000U, 0x40000000U, 0x60000000U, 0xd0000000U, 0xe8000000U, 0x4c000000U, 0x8e000000U, 0xd9000000U, 0xa8800000U, 0x52400000U, 0x3ea00000U, 0x3ab00000U, 0x44e80000U, 0x32740000U, 0x70a0000U, 0x83e70000U, 0x91948000U, 0x269c4000U, 0x9d78e000U, 0xa8ed3000U, 0x4c71a800U, 0x860eb400U, 0x5f629a00U, 0xe9d51100U, 0x3391780U, 0x58498a40U, 0xcfc6fa20U, 0xba606110U, 0xd7525f98U, 0x9c790e74U, 0x346b481aU, 0x54308403U, 0x73adb23bU, 0x7250e502U, 0xc2ffed90U, 0x7b29eb47U, 0xd014a58cU, 0xa4596f68U, 0x35991783U, 0xbef98a7cU, 0x8d2efa0cU, 0xcd146119U, 0x1ed85fb4U, 0xd8de0e54U, 0xbddfc835U, 0xc35cc42bU, 0x3c1d5229U, 0x8039d530U, 0xf3cc45beU, 0x76045f55U, 0x5d00bf8fU, 0xda833e73U, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0x8000000U, 0x6c000000U, 0x22000000U, 0xc9000000U, 0x30800000U, 0x47400000U, 0x9ea00000U, 0xfcb00000U, 0x44f80000U, 0x7d740000U, 0x221a0000U, 0xd0e70000U, 0x72928000U, 0x8f0b4000U, 0xbf2fe000U, 0xc7df5000U, 0xf8002800U, 0x34011400U, 0x2607b200U, 0x9706d100U, 0xd387ef80U, 0xd2c2eac0U, 0xcb62d220U, 0xec56c110U, 0x166a2798U, 0x827faec4U, 0x8535c822U, 0x7339440bU, 0xc4951a10U, 0x500c8536U, 0x60afbd8eU, 0x271b6bcaU, 0xf265158fU, 0x84d53fddU, 0x552f47a5U, 0x42dfbedaU, 0x9a800015U, 0xa2400004U, 0xec20001fU, 0x62f00011U, 0xe2d80021U, 0xaa84003dU, 0xda420001U, 0x98230032U, 0x24f0801cU, 0x65d84025U, 0x71076034U, 0x6483102dU, 0x80000000U, 0x40000000U, 0x20000000U, 0x10000000U, 0x18000000U, 0xa4000000U, 0x1a000000U, 0xc7000000U, 0x46800000U, 0x20400000U, 0xbd600000U, 0xc3900000U, 0xba880000U, 0xc2540000U, 0x312a0000U, 0xa4e50000U, 0x41528000U, 0x1da9c000U, 0x6ba1a000U, 0x16b21000U, 0x587a1800U, 0x154e6400U, 0x8cf1fa00U, 0x7219ff00U, 0xa85a4e80U, 0xa2384740U, 0xf28da20U, 0x39e72f10U, 0xe0d37688U, 0x6b6df344U, 0xee829826U, 0xcc42a439U, 0x3b62da0eU, 0xaa922f35U, 0x3909f697U, 0xc7903361U, 0xf0893809U, 0x3d55b411U, 0xc3aa4237U, 0x86a58b3cU, 0x9f31aca5U, 0x82bfdc70U, 0x366b6e98U, 0x2f029756U, 0x8a83e22fU, 0xb6439b30U, 0xcc61b4a7U, 0xe414b85fU, 0xa54814b7U, 0xc4f2a861U, 0xee180c8fU, 0x659cc69U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0x18000000U, 0x44000000U, 0xee000000U, 0x29000000U, 0x87800000U, 0xe9400000U, 0x6da00000U, 0x2bd00000U, 0x44a80000U, 0x54140000U, 0x33ce0000U, 0xfd270000U, 0xd4128000U, 0xf3cbc000U, 0x9d22a000U, 0x4411b000U, 0xebc86800U, 0xd923cc00U, 0xaa10c200U, 0xc2ce7100U, 0x5ea1e480U, 0x4356c040U, 0xaf6ee220U, 0x75730130U, 0x7f9ac98U, 0xfb7f7c64U, 0x46bce826U, 0xfadb0c21U, 0x2f6ee223U, 0xb573012eU, 0x67f9aca7U, 0x6b7f7c6bU, 0x5ebce800U, 0xbedb0c30U, 0xc16ee228U, 0x9c73010bU, 0xe079ac91U, 0x823f7c64U, 0x331ce83fU, 0x950b0c13U, 0x85c6e212U, 0xc8670130U, 0xd3b7ac92U, 0x7f187c51U, 0xe70e6807U, 0x66c0cc0eU, 0x18e44218U, 0x8c76b107U, 0x80000000U, 0x40000000U, 0x20000000U, 0x70000000U, 0x78000000U, 0xbc000000U, 0x6000000U, 0xc3000000U, 0x39800000U, 0xcd400000U, 0x5aa00000U, 0x34b00000U, 0xbdb80000U, 0xcb740000U, 0xb7da0000U, 0x82250000U, 0xa9718000U, 0xfedac000U, 0x26a26000U, 0x52b1f000U, 0x2ebaf800U, 0xfaf67c00U, 0xbe99b200U, 0x6283f900U, 0x58c67f80U, 0xb9e3e0c0U, 0x19105220U, 0x728dc910U, 0xc28f6788U, 0xda8eacdcU, 0x3689783eU, 0x388dbc3fU, 0x3f885209U, 0xbc09c92cU, 0xb44d6790U, 0x146facdcU, 0xd41af837U, 0xfe467c2dU, 0x5b21b229U, 0x65f7f91dU, 0x911c7fa5U, 0x44c6e0c2U, 0x8fe1d224U, 0x8217092dU, 0x870d07a2U, 0x71cf5cdbU, 0xff2b8009U, 0x3dbfc033U, 0x8b73e000U, 0x97db3012U, 0xf2209820U, 0xd1738c2cU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xf0000000U, 0x88000000U, 0x84000000U, 0xaa000000U, 0x41000000U, 0x94800000U, 0x8ec00000U, 0x8c600000U, 0xab700000U, 0xb2f80000U, 0xa4340000U, 0x36de0000U, 0xe0e10000U, 0xe9b18000U, 0xb0994000U, 0x1447a000U, 0xd9a71000U, 0xda932800U, 0x77ce7400U, 0x366e3e00U, 0x70fee700U, 0xf1337d80U, 0xd05f7cc0U, 0xd3261e20U, 0x5751b730U, 0xfa2e75a8U, 0x555b58fcU, 0x8da2a802U, 0xc8973411U, 0x9ac99e02U, 0x7ce9f72cU, 0x9d385587U, 0x2cd508c2U, 0xcb6e2029U, 0x227a500aU, 0x40f28821U, 0x5bbc6436U, 0x2f12960cU, 0x5d88d333U, 0x1ccb63bcU, 0x23efcbd5U, 0xcab9eb8dU, 0x393afddU, 0x7f4b7da7U, 0x4eab7cd7U, 0xeb981e0eU, 0x29c0b72eU, 0x17e7f5a7U, 0xa3618dcU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xb0000000U, 0xd8000000U, 0x3c000000U, 0x4a000000U, 0xeb000000U, 0xcf800000U, 0x49400000U, 0xb3e00000U, 0xab300000U, 0x82580000U, 0xe2f40000U, 0x217a0000U, 0x2610000U, 0xf7778000U, 0xab3bc000U, 0x3a006000U, 0xd3069000U, 0xe383b800U, 0x6b41ac00U, 0xbce3d200U, 0x12b20300U, 0x6a1d4380U, 0x7592d5c0U, 0xc8e3220U, 0x7a9e5310U, 0xd511ba8U, 0xa32a29ecU, 0x58cc3816U, 0xe7fe6c1fU, 0x6ba1b23aU, 0xa4519316U, 0x33ab7b85U, 0x600db9ddU, 0xe858001eU, 0xf9f40000U, 0x96fa003bU, 0xc7210006U, 0xd6978012U, 0xd70bc025U, 0x3dd8600fU, 0x93b29028U, 0xbe99b835U, 0x8b50ac26U, 0x7a2c5229U, 0xf04dc31aU, 0xf33f2381U, 0x460145c8U, 0x39000a0aU, 0xb8853f17U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x70000000U, 0x8000000U, 0xdc000000U, 0x8e000000U, 0x23000000U, 0x99800000U, 0x2c00000U, 0x32200000U, 0x75900000U, 0x1d280000U, 0xbbd40000U, 0x834e0000U, 0xd5230000U, 0x6158000U, 0x86ef4000U, 0x11716000U, 0xc89a3000U, 0x9e6cf800U, 0xef313c00U, 0x7ef84e00U, 0xbc9b3d00U, 0x9c6e0a80U, 0xda33c040U, 0x607aae20U, 0x7dd94d30U, 0xdd8812b8U, 0xa9048c5cU, 0xb082f822U, 0x72423c07U, 0xa065ce1bU, 0xa5f07d14U, 0xb0d96aa4U, 0xd70ef077U, 0xda45d60fU, 0x2c603125U, 0xb3f2bc99U, 0x37ddc172U, 0x148aea8eU, 0xa986b06fU, 0x2ac7363dU, 0x7e22412bU, 0x8394a4b8U, 0xea2a8d6cU, 0x7052bcabU, 0x2c8dc148U, 0x5d82ea81U, 0xe8c2b057U, 0xab213610U, 0xed15413eU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0xa8000000U, 0x94000000U, 0x6000000U, 0xb1000000U, 0x3b800000U, 0x54c00000U, 0x45e00000U, 0xf9700000U, 0x6b680000U, 0x15340000U, 0x86ce0000U, 0xffe50000U, 0x1a738000U, 0xc7ec4000U, 0x7b752000U, 0x46b7000U, 0x83b42800U, 0xcb8a6c00U, 0xf1c76e00U, 0xb864d300U, 0x3cb11d80U, 0xa50ddc40U, 0x1087ce20U, 0x3c42e330U, 0x15a59588U, 0x46d1806cU, 0x16bc280aU, 0xb30e6c15U, 0x79816e09U, 0x1bc5d300U, 0x63649da4U, 0x1c309c70U, 0xf14f6e30U, 0xb120d322U, 0xcc971d9cU, 0x1a1cdc7cU, 0x5a5a4e3aU, 0x3dfba314U, 0x5c2b3595U, 0xd812b074U, 0x385b203bU, 0xc2fe703eU, 0xd2afa83eU, 0xa9522c3dU, 0xa47c4e1cU, 0xd7eaa31aU, 0xa376b59eU, 0x186bf076U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0x88000000U, 0x44000000U, 0xc2000000U, 0x77000000U, 0x96800000U, 0x2a400000U, 0x13a00000U, 0xcc300000U, 0x46a80000U, 0x79f40000U, 0xc0ce0000U, 0x3a70000U, 0x84328000U, 0x62af4000U, 0x2bf2a000U, 0x3fcc5000U, 0xd1269800U, 0x6c702400U, 0x60daa00U, 0x71468900U, 0x53236380U, 0xbb703040U, 0x608b8a20U, 0x43069930U, 0x8c83db98U, 0xf1400464U, 0x93269802U, 0xdb702421U, 0xf08daa28U, 0xcb068939U, 0xc8836387U, 0x3340305bU, 0xe4238a14U, 0x4df2991eU, 0xdacddbacU, 0xd8a70470U, 0x4b41836U, 0x75ef6412U, 0x9dd70a18U, 0x8d3ed93fU, 0xd96bfbbdU, 0x5c971454U, 0x661ca001U, 0x5e1b501dU, 0xa21c1827U, 0x5c1b6423U, 0xb5190a36U, 0x5a99d917U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0xe8000000U, 0xc000000U, 0xde000000U, 0x65000000U, 0xb1800000U, 0xd9400000U, 0x2ee00000U, 0xa3100000U, 0xe6880000U, 0x3df40000U, 0x9d9e0000U, 0xcf7f0000U, 0xa6e8000U, 0xde64000U, 0xc391e000U, 0xd44e3000U, 0xed548800U, 0xf2ea5c00U, 0x8b247200U, 0x4933a300U, 0x9c393680U, 0x4b8de540U, 0xb070fa20U, 0x82d9ff30U, 0xf09d4498U, 0x22fe4664U, 0x8529cc9aU, 0xda041a73U, 0xe705be8fU, 0x8283b94dU, 0x91c2882eU, 0x70215c21U, 0x3db4f21eU, 0x4fae316U, 0xc42e5698U, 0xd9819563U, 0x15439217U, 0x90e69304U, 0x56153e84U, 0xbf0af976U, 0xe8b5e83fU, 0x6d7d2c12U, 0x96f9a08U, 0x5d618f3eU, 0xe9502ca1U, 0x70ee2a62U, 0xb82736b2U, 0x1b2e559U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x90000000U, 0x38000000U, 0x54000000U, 0xf6000000U, 0x63000000U, 0xab800000U, 0xad400000U, 0xf0e00000U, 0x64500000U, 0x99d80000U, 0x40b40000U, 0xcb8e0000U, 0x1a690000U, 0xb0be8000U, 0x44a6c000U, 0xe352000U, 0x664ff000U, 0xb048f800U, 0x834b8c00U, 0xb0cc6200U, 0xd98df300U, 0xe76a4c80U, 0xb43b9fc0U, 0x70649a20U, 0xfe967f30U, 0x6e7e2ea8U, 0xbd026ce4U, 0x6480d6aeU, 0x4c4e0e5U, 0x58a434b5U, 0x6432d3ccU, 0xaf4bd82cU, 0x72c97c2aU, 0x7c8c1a27U, 0x87edbf30U, 0xdefb8ebfU, 0x8fc25cf6U, 0xff238eb9U, 0x5b765cdcU, 0x62ad8e94U, 0xb21f5ce7U, 0x41930eadU, 0xff99cd7U, 0x49462eafU, 0x6ee66cfeU, 0xcb56d6a0U, 0x59e0caU, 0x40f4b497U, 0xa7ed13eeU, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0x68000000U, 0x7c000000U, 0xc6000000U, 0x11000000U, 0x25800000U, 0x60400000U, 0xc0600000U, 0x61100000U, 0xdd280000U, 0x4d740000U, 0x323a0000U, 0xcd5f0000U, 0xa4cc8000U, 0x9a264000U, 0x36706000U, 0xe8bcf000U, 0x859ea800U, 0xb769bc00U, 0x22135a00U, 0x13aa1700U, 0xbfb76e80U, 0xf69ae440U, 0x41edf220U, 0xc4d3ab10U, 0x6d0c3498U, 0xe404f354U, 0xa2009cbaU, 0xf3064f4fU, 0xb6854689U, 0x86c51840U, 0x2ea6c82bU, 0x33b14c03U, 0x289ff203U, 0x74e8ab17U, 0x6352b495U, 0xce49b350U, 0xaae67ca4U, 0x51d3ff67U, 0xba8f0e9fU, 0x1f421471U, 0xa8e15a24U, 0xd2d11719U, 0x5409ee80U, 0xdd87a464U, 0x54431222U, 0x4a621b38U, 0x8e147cbaU, 0xfda8ff5cU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0xf8000000U, 0x8c000000U, 0xd6000000U, 0xb000000U, 0xcb800000U, 0xfec00000U, 0xa4a00000U, 0xe0900000U, 0xe1180000U, 0x78340000U, 0xbf8e0000U, 0x862f0000U, 0x6388000U, 0xe266c000U, 0x6833e000U, 0xe788f000U, 0x3a2d7800U, 0x78394c00U, 0x9d647e00U, 0xf9b21100U, 0xc448b680U, 0x5e0ea7c0U, 0xade90620U, 0x261b5d30U, 0xc5b4c898U, 0x7a48b6d4U, 0x410fb09eU, 0x6c6afad3U, 0xfddd4e8dU, 0x2d912be6U, 0x799e9834U, 0xf171bc38U, 0x9be9063aU, 0xbd1b5d0dU, 0x9634c881U, 0x5888b6c0U, 0xcbafb0a1U, 0xbfafad4U, 0x1454e9aU, 0xa0652bc5U, 0xa9309822U, 0x690ebc39U, 0xd869860bU, 0xc7d99d2cU, 0xa09128aaU, 0x411b46c0U, 0x483448aaU, 0x178a76fdU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0x88000000U, 0x84000000U, 0xc6000000U, 0xf5000000U, 0xc8800000U, 0xef400000U, 0x13a00000U, 0x79d00000U, 0x31180000U, 0x96740000U, 0xf2ce0000U, 0x286f0000U, 0x433c8000U, 0xc2654000U, 0xe837a000U, 0xffeff000U, 0xa3fd4800U, 0xfd021400U, 0x8c87c200U, 0x4942c100U, 0x36a79880U, 0x39504bc0U, 0x5a5a8a20U, 0x43d0d530U, 0x7e185a98U, 0xd1f68af4U, 0x3a0b1282U, 0x230b9ed1U, 0xb9885089U, 0x8dc81ff9U, 0xf7ee6828U, 0xe7fca41eU, 0x5b032a0fU, 0xa9802536U, 0x9c192adU, 0x5de5dec2U, 0xecf5709bU, 0xd689afe2U, 0xba4e0012U, 0x72f0034U, 0x309c8034U, 0x6bb5401bU, 0x512fa01bU, 0xed9bf03cU, 0x97334836U, 0x206d1411U, 0x73b4239U, 0x6467811bU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0xd8000000U, 0x3c000000U, 0x16000000U, 0x6d000000U, 0xd6800000U, 0x4cc00000U, 0xeee00000U, 0xa8d00000U, 0x1ae80000U, 0xd0340000U, 0x1f3e0000U, 0x3c5d0000U, 0x33cf8000U, 0x1585c000U, 0x9b436000U, 0x2aa2f000U, 0x33f1c800U, 0x78592400U, 0x69cc5e00U, 0x96801b00U, 0xacc5fc80U, 0x7ee7f240U, 0xc0d59620U, 0xfeed3f30U, 0xfa37a288U, 0x643ae96cU, 0x87dfea96U, 0xa98f0d7fU, 0xb7a154adU, 0xdd752647U, 0x9899802bU, 0xf92cc000U, 0xb752e000U, 0x4aaa3012U, 0x99152800U, 0x8a8a1433U, 0xf020f60cU, 0x7136cf2dU, 0xe7bfea84U, 0xb19f0d48U, 0x75a954bcU, 0x7891266bU, 0x93cf8029U, 0x6585c03cU, 0x63436009U, 0xa6a2f006U, 0xfdf1c83eU, 0x2959241aU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xd0000000U, 0x68000000U, 0x8c000000U, 0x6e000000U, 0xff000000U, 0x9b800000U, 0xef400000U, 0xe1600000U, 0xa7100000U, 0xa2580000U, 0xd8740000U, 0x24a0000U, 0xa5a90000U, 0x7788000U, 0xbf804000U, 0xed45e000U, 0x63b000U, 0x7b965800U, 0x32988c00U, 0x34539200U, 0xd53d5f00U, 0xc4606680U, 0x9953fc0U, 0x6b9dca20U, 0xcd1d310U, 0xa7f9f4a8U, 0xb94160f4U, 0xba652cbaU, 0x7e94acf3U, 0xc19de93U, 0x359703dbU, 0x5d988034U, 0x67d0403cU, 0x667de011U, 0x2307b001U, 0xdd84580fU, 0x3c458c11U, 0xc4e11205U, 0xdf541f04U, 0x54bd06b7U, 0xfe26cfcbU, 0xbe76720bU, 0x414eef26U, 0x482e3e9fU, 0x2339b3c8U, 0x4f64580dU, 0xb8158c00U, 0x49d91226U, 0x8f301f2aU, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0x98000000U, 0xc000000U, 0xb2000000U, 0x25000000U, 0x69800000U, 0xc3c00000U, 0xa9600000U, 0xdef00000U, 0xdef80000U, 0xd1940000U, 0xdb0a0000U, 0xd1ed0000U, 0x35db8000U, 0x91c3c000U, 0x5c66e000U, 0xbf75d000U, 0x39380800U, 0x5ef67c00U, 0x9ef8c600U, 0xf197bf00U, 0x6b0d0d80U, 0x49ef2ec0U, 0x39d8ce20U, 0x23c5c310U, 0x7967cb88U, 0xd6f191ecU, 0xfafc4386U, 0xf7902dd3U, 0x40086584U, 0x2f6f42f5U, 0xba9ee014U, 0x92e1d00fU, 0xe8320828U, 0x161b7c11U, 0xe8a34627U, 0x8a947f0eU, 0x458bedaaU, 0xceaafefaU, 0x1ef8c62aU, 0xb197bf07U, 0x4b0d0db4U, 0xf9ef2ef4U, 0xa1d8ce04U, 0x2fc5c320U, 0xcb67cbafU, 0xf3f191e6U, 0x937c4392U, 0x34502dedU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0xa8000000U, 0xc4000000U, 0x9e000000U, 0x11000000U, 0xfe800000U, 0x52c00000U, 0x16e00000U, 0xef700000U, 0x1ab80000U, 0x78940000U, 0x434a0000U, 0x4e90000U, 0x4b3c8000U, 0xd5d64000U, 0xf1eba000U, 0x3bba3000U, 0x9e176800U, 0x8d8f6400U, 0xb00b4e00U, 0x474afb00U, 0x7aeaf180U, 0xaa3e50c0U, 0xd3562620U, 0xcf2c9f10U, 0x775d3fa8U, 0xfe62ebd4U, 0x78b7778aU, 0x64d8ffe1U, 0x402471afU, 0x879510c0U, 0x14cb061dU, 0x64a9ef21U, 0x51d77a0U, 0xb41ffdaU, 0x2fa0f194U, 0x6bd750efU, 0xf0eaa605U, 0xcd3adf2eU, 0x58d69facU, 0xad68dbe1U, 0x8a781f82U, 0x3d739bcfU, 0x41bd3fb3U, 0x112ebddU, 0x6a0f778aU, 0x884cfff1U, 0x356e7191U, 0x567c10e6U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x50000000U, 0xe8000000U, 0x4c000000U, 0xaa000000U, 0x6d000000U, 0x34800000U, 0x82c00000U, 0x69a00000U, 0xd3900000U, 0xe9a80000U, 0xe7340000U, 0x76be0000U, 0xc85b0000U, 0x4e288000U, 0x42724000U, 0x7a59e000U, 0xf72b9000U, 0xc8f6c800U, 0xcb98d400U, 0xc909ce00U, 0x26231100U, 0x3ad46680U, 0x4f4b0240U, 0xb5410620U, 0xc4e0c530U, 0xc37528b8U, 0x94da5354U, 0x40ec809aU, 0x61d05763U, 0x94cae6b2U, 0xc206427fU, 0xe106662fU, 0x7e861517U, 0xbfc480b2U, 0xb5245768U, 0x1d54e687U, 0x2a0d4261U, 0x59a6e638U, 0xab905519U, 0xadab60bcU, 0x5130c77aU, 0x59bcae93U, 0xddd8d67aU, 0x52684839U, 0xc4159436U, 0xf4eeae37U, 0x4fd5c105U, 0xafcdce81U, 0x89810649U, 0x80000000U, 0x40000000U, 0x20000000U, 0x70000000U, 0xc8000000U, 0x44000000U, 0xfa000000U, 0x83000000U, 0x1a800000U, 0xbd400000U, 0x1fa00000U, 0xbad00000U, 0x5bd80000U, 0x4e740000U, 0x8f8a0000U, 0xbaed0000U, 0x695d8000U, 0xa7314000U, 0xf22aa000U, 0x7f3f1000U, 0x5e05f800U, 0x69006400U, 0x1868200U, 0x5bc62100U, 0xd4e09080U, 0x9872edc0U, 0x82897a20U, 0x316b4510U, 0x799b9288U, 0x2d558cdcU, 0x2d1b4a92U, 0x6112b8c1U, 0xcf3d1096U, 0xf603adecU, 0x7d03da1cU, 0x43845532U, 0x54c66a83U, 0x7061e8c3U, 0x5c37c8bcU, 0x4a999ddU, 0x2c780034U, 0x80a40003U, 0xc6520037U, 0x43990036U, 0xce578002U, 0x679c403dU, 0x64572000U, 0x5c9e5001U, 0xf2d75804U, 0x5fdb740fU, 0x94717a15U, 0x7c8f4537U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0x98000000U, 0x5c000000U, 0xd2000000U, 0x27000000U, 0xaf800000U, 0xa9400000U, 0x1a600000U, 0x19100000U, 0xfd380000U, 0x38740000U, 0x39ae0000U, 0xbb0f0000U, 0xbc3e8000U, 0xf6f5c000U, 0x6e6b6000U, 0x9ea9d000U, 0xd4899800U, 0x757ccc00U, 0x7c958200U, 0xef7f4700U, 0x3f946680U, 0x3efd3cc0U, 0x6bd21a20U, 0x681c8b30U, 0xfa076498U, 0xd303bbe4U, 0x49831c86U, 0x84767e7U, 0x84e2668cU, 0xb6d63cddU, 0x149a9a35U, 0x1ac24b29U, 0xc124848cU, 0xd474abfcU, 0x43a964a6U, 0xa80cbbcaU, 0x95bd9cafU, 0x6eb2a7dfU, 0x728906a3U, 0x747fecdcU, 0x12130206U, 0x48be870bU, 0x1231068aU, 0x924becd0U, 0x665d023aU, 0x8fe1870dU, 0x35786b0U, 0x3eda2cc7U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0x28000000U, 0x2c000000U, 0x22000000U, 0x3000000U, 0xca800000U, 0x75400000U, 0xc4200000U, 0xb3100000U, 0x61e80000U, 0xa8340000U, 0x627e0000U, 0xb990000U, 0xf2ea8000U, 0x8ab64000U, 0x9b3ae000U, 0xfdb9d000U, 0x6afab800U, 0xdd86400U, 0x644c4200U, 0x58e7bd00U, 0x18f3de80U, 0xeb9c6040U, 0x82e8fa20U, 0x12b6d930U, 0x8f3d1ca8U, 0xdbb99d44U, 0x67ffc4aaU, 0xe65a697bU, 0xd88dde80U, 0x23056074U, 0x1a827a30U, 0xfd409922U, 0xf827fc9bU, 0xb9104d63U, 0x4eed7c88U, 0x40b60d4cU, 0x143f9c9bU, 0x53bdd47U, 0x34bb24a5U, 0x2f7ab946U, 0x801de69dU, 0xfe2b4444U, 0xc954d81eU, 0x9d4ef42bU, 0xe5669a32U, 0x31304937U, 0x6fffc49fU, 0x1a5a6974U, 0x80000000U, 0x40000000U, 0x60000000U, 0xd0000000U, 0x78000000U, 0x14000000U, 0xea000000U, 0xb3000000U, 0x45800000U, 0x24400000U, 0x3ba00000U, 0x47100000U, 0x4f480000U, 0x93b40000U, 0x5bda0000U, 0xadbf0000U, 0x2b488000U, 0xf1b6c000U, 0x34df2000U, 0xbe3d1000U, 0x3a0e7800U, 0xc2931c00U, 0x4b0cca00U, 0x18137900U, 0xb4cb4e80U, 0x8ef39940U, 0x46f8b220U, 0xf36f6510U, 0x6fe70498U, 0xf4b22074U, 0xd45edcbeU, 0x8afaec55U, 0xfd6b4e82U, 0xfee39948U, 0xbe30b237U, 0x339b6528U, 0xd81d04b2U, 0x9d5d204cU, 0x247e5c86U, 0x38a82c54U, 0xa3066e8bU, 0x1d85897bU, 0x80444a20U, 0x79a5b921U, 0x98146ebaU, 0xf4ce896cU, 0xeef6ca14U, 0x96fc7933U, 0x8b6bcebeU, 0x7be1597eU, 0x1eb59216U, 0x67597529U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x90000000U, 0x28000000U, 0x54000000U, 0x12000000U, 0x5d000000U, 0x69800000U, 0xf0c00000U, 0x96e00000U, 0xd0f00000U, 0x99780000U, 0x69140000U, 0xad0a0000U, 0xa12b0000U, 0x663a8000U, 0x70304000U, 0x879b2000U, 0x9de65000U, 0x9e778800U, 0xe93f3c00U, 0xe4b7de00U, 0x6edec300U, 0x43c10580U, 0xa462a6c0U, 0xe6b25620U, 0x5bdeff10U, 0x9e465bb8U, 0xd6a725e4U, 0x552f3aaU, 0xb6aa49c5U, 0xe5f8a59cU, 0x7450b6e3U, 0x112cfe08U, 0x7e38931dU, 0x7c368d93U, 0x799d9ad2U, 0xaee58812U, 0xecf03c34U, 0x3f7f5e28U, 0xb6118313U, 0xb18aa58aU, 0x6c6fb6dbU, 0x121c7e2dU, 0x6b23d326U, 0xa7972d91U, 0x9d4b8accU, 0xcc892025U, 0x35e95039U, 0xbadf0815U, 0x11c07c01U, 0x80000000U, 0x40000000U, 0x20000000U, 0x90000000U, 0x68000000U, 0xac000000U, 0x22000000U, 0x35000000U, 0x28800000U, 0xc6400000U, 0xc4600000U, 0x9db00000U, 0x73180000U, 0xa6d40000U, 0x1f2a0000U, 0x390d0000U, 0x1eda8000U, 0x3f744000U, 0xa33ae000U, 0x1203d000U, 0x8d010800U, 0xcc877400U, 0xd8476a00U, 0xbb649f00U, 0x2c375380U, 0xbfdbddc0U, 0x91f46220U, 0x6e7aeb10U, 0x11e0b988U, 0xf7602e4U, 0x1b3b51baU, 0xf602a6fbU, 0x930533a0U, 0xb3854df9U, 0x69c70a38U, 0x77a30f2eU, 0x1b14bbabU, 0xce8b79e5U, 0xb9180024U, 0x7fd4002eU, 0x35aa003cU, 0x5a4d0031U, 0x9a3a803aU, 0xc884401bU, 0x3642e00aU, 0x1c67d009U, 0xc9b30835U, 0x951e742aU, 0x1dd7ea2fU, 0x20addf0cU, 0xe2cf339bU, 0x34784dfeU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0xc8000000U, 0x54000000U, 0xa000000U, 0x3b000000U, 0xf4800000U, 0xf6c00000U, 0xf2a00000U, 0xab00000U, 0xbbc80000U, 0x21140000U, 0x5afe0000U, 0xea9f0000U, 0x88c8000U, 0x2af74000U, 0xc0a92000U, 0x8f879000U, 0xa245b800U, 0xb4601400U, 0xe0121e00U, 0x2d7ff900U, 0xc4df3f80U, 0x4ae80940U, 0x7fe1a620U, 0xe054ed30U, 0x261fa198U, 0x124fb074U, 0xfe533992U, 0xb7183465U, 0x6dcc9fbaU, 0xe413d94aU, 0x2f7fbe37U, 0xcbdb292cU, 0x646da794U, 0x7a208d6dU, 0xb2728003U, 0xd068401eU, 0x6025a00dU, 0x2170d03fU, 0xa0ec981fU, 0x54e78428U, 0xbcd7a636U, 0x54dfed1dU, 0x22ed21afU, 0x9be7f068U, 0xf2569980U, 0x8118e46aU, 0xb8c807bdU, 0x39905d5aU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x70000000U, 0x8000000U, 0x9c000000U, 0xb2000000U, 0xab000000U, 0xc9800000U, 0x74c00000U, 0xdce00000U, 0xd5f00000U, 0x57380000U, 0xc140000U, 0x924e0000U, 0x2d6f0000U, 0x8ff98000U, 0xcaf14000U, 0x60ba6000U, 0x79d15000U, 0xc82c7800U, 0x63d87c00U, 0xf5e60e00U, 0x1f752300U, 0x667a7d80U, 0x6e33e4c0U, 0xa45c7620U, 0x48265f30U, 0xb913f398U, 0xeacc87dcU, 0xb72beba2U, 0x245aabd7U, 0x88201d94U, 0xd912b4c6U, 0x9ac80e08U, 0xbf2a2316U, 0xb85bfd81U, 0x3a26a4e4U, 0x72101629U, 0x534c0f23U, 0xcbe80b95U, 0x64babbd5U, 0xefd60591U, 0x252b98ceU, 0x5f5a780aU, 0x59a37c25U, 0x49d18e08U, 0x602b6304U, 0xefd99dbbU, 0x3fe3f4d8U, 0x20726e3bU, 0x81fb732bU, 0x80000000U, 0x40000000U, 0x60000000U, 0x90000000U, 0x98000000U, 0xc4000000U, 0xb6000000U, 0x7d000000U, 0x51800000U, 0xfd400000U, 0xb200000U, 0xb2100000U, 0xd4080000U, 0x16340000U, 0x4c9a0000U, 0x7bff0000U, 0x314a8000U, 0x9911c000U, 0x288ba000U, 0x42f2f000U, 0xeeff8800U, 0xeccadc00U, 0xee551200U, 0xbca94d00U, 0xf266be80U, 0x2f346f40U, 0xeb189a20U, 0x9bb89110U, 0xfbeb2c98U, 0x4e47e264U, 0x33a50486U, 0x50d0ce61U, 0xb6d1e95U, 0xd0869f6bU, 0x6ec7120aU, 0x55624d3aU, 0x59b63e91U, 0x20daaf66U, 0x3b59ba0aU, 0x791ba104U, 0x80bf04b0U, 0x2f6fce76U, 0xb6879ea9U, 0xebc75f51U, 0x50e4b23bU, 0x8af4bd0cU, 0x92fbb6bbU, 0x6ecb736cU, 0x2d542807U, 0xcc282c15U, 0x2ca29a15U, 0x12579107U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0x48000000U, 0x2c000000U, 0x1e000000U, 0xf1000000U, 0x15800000U, 0x4a400000U, 0xd6e00000U, 0x60500000U, 0x38e80000U, 0x25b40000U, 0xa3a0000U, 0xaf990000U, 0x60aa8000U, 0xcc514000U, 0x66eae000U, 0x74b73000U, 0x8fba2800U, 0xadda7c00U, 0x9a4eca00U, 0xb2002300U, 0xaf049480U, 0x4486be40U, 0xcfc6e220U, 0xd4a75f10U, 0x9ab2dea8U, 0x46badd64U, 0xec5816b2U, 0x3a0e915bU, 0xefe6748fU, 0x19d58e48U, 0xccaeca1fU, 0x9250232dU, 0x37ec9488U, 0xf132be4bU, 0x8dfce23eU, 0x573e5f3cU, 0xe4185e9dU, 0x7beb9d79U, 0x9f32f694U, 0x4f9a16bU, 0xb6bc5cafU, 0xd45ff26fU, 0x6e080028U, 0x5e40017U, 0x92d2002dU, 0x1a2d0022U, 0x22908017U, 0x4fc84038U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xf0000000U, 0xe8000000U, 0x5c000000U, 0xce000000U, 0xef000000U, 0x5f800000U, 0x8400000U, 0x82600000U, 0xe4100000U, 0xcd980000U, 0xa9f40000U, 0xf9ce0000U, 0xb20b0000U, 0xd62d8000U, 0x4f5a4000U, 0x21506000U, 0xf97fb000U, 0xb9265800U, 0x37f0ac00U, 0x2ecbea00U, 0x498e8700U, 0x5469d680U, 0x583859c0U, 0xe7c03220U, 0x42246b30U, 0x2a725cb8U, 0xff896efcU, 0x3f6fbc9aU, 0x9dbc9ee7U, 0x628184abU, 0x56c782f7U, 0x2aa236b5U, 0x29b2a9d9U, 0x17ad8a31U, 0x901e3719U, 0x58b40e95U, 0x9f2db5f8U, 0x63d83820U, 0x58941c0bU, 0x6c58323aU, 0x68d06b05U, 0x4a3c5c88U, 0x6c26ed4U, 0x12a23ca5U, 0x8db6deeaU, 0x9da9e4b4U, 0x51c32f7U, 0x7a326ebaU, 0xe9ed05f8U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0xa8000000U, 0xcc000000U, 0xf6000000U, 0x37000000U, 0x6f800000U, 0xa1400000U, 0xb6e00000U, 0xfb500000U, 0xb8180000U, 0x9a340000U, 0x460e0000U, 0xcecf0000U, 0x766e8000U, 0xc05c4000U, 0x2053e000U, 0x119b7000U, 0x54711800U, 0x6b6d6c00U, 0x6df2200U, 0x75902300U, 0xfbfe480U, 0x278259c0U, 0x3d40ba20U, 0x88e10f30U, 0x90532698U, 0x89990ae4U, 0xc076468aU, 0x696a3ac3U, 0xa3dabe85U, 0x171326d9U, 0x7a0489U, 0x68a229cfU, 0xbe312202U, 0xdc0f2314U, 0xffc964baU, 0x16ea19d4U, 0x6a9d5a10U, 0xdf57f2bU, 0x9d2cbea0U, 0x4fb826e9U, 0x8782848bU, 0xcd4569c4U, 0xb0e2421fU, 0xf4571318U, 0xb39d1c82U, 0x17445c3U, 0x31ee8008U, 0x6d1c4024U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x70000000U, 0x18000000U, 0xa4000000U, 0x36000000U, 0xeb000000U, 0xc3800000U, 0x4bc00000U, 0xfca00000U, 0xc7300000U, 0xedb80000U, 0xac140000U, 0xf4a0000U, 0x52090000U, 0xe1ed8000U, 0x83bc000U, 0x84d5a000U, 0x5c6df000U, 0x24f83800U, 0x91f7cc00U, 0xd99e5600U, 0x3360b100U, 0x3d95d380U, 0x798b72c0U, 0x562bee20U, 0xc69cbd10U, 0xeee625a8U, 0x815233dcU, 0xa4ac05a6U, 0x1fd903f9U, 0x5b061d85U, 0x3b81fff6U, 0x3fc053beU, 0xa2a4b2f7U, 0x90344e3cU, 0xbc384d2eU, 0x3ad39da8U, 0xdb6e3ff6U, 0x1d7ff3a7U, 0xbb3042f4U, 0x9fb9f609U, 0xa110413cU, 0x4fca6bb8U, 0x664e7efeU, 0xc48d981dU, 0xeeaa3c2bU, 0x86de6e02U, 0x95837d12U, 0x30c18595U, 0xf722c3f1U, 0x80000000U, 0x40000000U, 0x20000000U, 0x90000000U, 0x28000000U, 0xc4000000U, 0x62000000U, 0x1d000000U, 0xbc800000U, 0x3ec00000U, 0xebe00000U, 0x3f900000U, 0x28a80000U, 0xdcf40000U, 0x93fa0000U, 0x5ebd0000U, 0xd21a8000U, 0x482e4000U, 0xbc35a000U, 0xcb1dd000U, 0xf6ae0800U, 0x2ff31400U, 0x247e6e00U, 0x1bfee300U, 0x4abdd680U, 0xb81a8040U, 0x12ae620U, 0x4ab3b710U, 0x2cde1888U, 0xc3cdb364U, 0x33a338aaU, 0x5bb72361U, 0xc65810b0U, 0x1a0aa773U, 0x5c7568dU, 0x6864c04aU, 0x80d74600U, 0xd10a670dU, 0x1e4210bfU, 0xab27a76aU, 0xf775d683U, 0xa8be8071U, 0xe518e61bU, 0x9daab716U, 0xe4769896U, 0xef3af347U, 0x385e18afU, 0x790db350U, 0x9a4338a3U, 0xe927237aU, 0x7a7010a7U, 0x3c3ea757U, 0x80000000U, 0x40000000U, 0x60000000U, 0x30000000U, 0x68000000U, 0xa4000000U, 0x36000000U, 0x2f000000U, 0x6f800000U, 0x5c00000U, 0x40a00000U, 0xc9b00000U, 0xd2580000U, 0x8a940000U, 0x9c2a0000U, 0x396f0000U, 0x638f8000U, 0xe75e4000U, 0x2811a000U, 0xe76a7000U, 0xa8899800U, 0xdedb2c00U, 0x32d38600U, 0xa04c1100U, 0xc0f81780U, 0x7a275dc0U, 0x5ef59e20U, 0x81b97d10U, 0x76c23198U, 0xc5253cccU, 0x497611baU, 0x187e0cf9U, 0xfc61a9b5U, 0xd99110d7U, 0x49aa17b9U, 0xe1ac5df4U, 0x65a81e3fU, 0x3ac3d0cU, 0x74ae11a0U, 0xd72a0ccdU, 0x40eba99bU, 0x194e10cfU, 0x907d9792U, 0x28661dffU, 0xe793be30U, 0xf2a94d13U, 0xd02809beU, 0xeb6f60feU, 0x1a898fa1U, 0x97d871f7U, 0x2a541811U, 0x60e6c03U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x10000000U, 0xf8000000U, 0x64000000U, 0x5e000000U, 0x9000000U, 0xff800000U, 0x9bc00000U, 0xffe00000U, 0x4ef00000U, 0x2f380000U, 0x2940000U, 0x980a0000U, 0x114b0000U, 0x94ee8000U, 0x573ec000U, 0x2692a000U, 0x2608b000U, 0x84f2800U, 0x936f6c00U, 0xa8fb8600U, 0x87701b00U, 0x61f9ad80U, 0xd8f28cc0U, 0xa3a2e20U, 0xcf11b710U, 0xd8c88bb8U, 0xda2e27c4U, 0x8d5eab9eU, 0xb4a357c9U, 0xf855a38fU, 0x446e4bd6U, 0x1e79ad99U, 0x3328cebU, 0x15da2e0eU, 0x91e1b71cU, 0xff08ba5U, 0xbcba27f9U, 0x4b54abafU, 0xace857faU, 0x933b23a1U, 0x88908bf6U, 0xc70b0d82U, 0x6bca3cf5U, 0x32ad0604U, 0x1adb29U, 0x3f010d85U, 0x2a813cc0U, 0xbe438619U, 0x23241b34U, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0x78000000U, 0x5c000000U, 0x6a000000U, 0x1000000U, 0x82800000U, 0x94c00000U, 0xaa00000U, 0xf100000U, 0xdc380000U, 0xd340000U, 0xf6ea0000U, 0x412f0000U, 0xcc098000U, 0x735ec000U, 0xd2006000U, 0x7d061000U, 0x7885a800U, 0x1dc1e400U, 0xac26de00U, 0xadd5f900U, 0xbd9b9280U, 0x81a20ec0U, 0x3c92f620U, 0xd27edd10U, 0x3f572c98U, 0xe15ee7fcU, 0xcf054cbeU, 0xf583f7c7U, 0x1d4364a2U, 0xede3d3ecU, 0x6bf45a86U, 0x114afadeU, 0xbeb8003eU, 0x29f40038U, 0xe44a000bU, 0xe23f000dU, 0x231801bU, 0x236ac021U, 0xcc6a603cU, 0xa9e91039U, 0x3cac281cU, 0xf54f242aU, 0xa8bebe25U, 0xd2f7e90bU, 0xefcc3aa6U, 0xd078eafbU, 0xaa57a82bU, 0x4ddae424U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xb0000000U, 0x88000000U, 0x14000000U, 0xa2000000U, 0x49000000U, 0x4a800000U, 0xc3400000U, 0xfe600000U, 0xc5b00000U, 0x84b80000U, 0xab540000U, 0xf74e0000U, 0xfd0f0000U, 0x89ef8000U, 0xef1d4000U, 0x25c42000U, 0xc321d000U, 0xa4d02800U, 0x508e2400U, 0x6729a200U, 0x3fb85f00U, 0x50d43b80U, 0x828d50c0U, 0xc62e0a20U, 0xd13f3b30U, 0xb997b998U, 0x21ebdfecU, 0xeb1d9982U, 0xdfc50ff5U, 0xa6223190U, 0xd0566bceU, 0x6ccfb388U, 0x38cfe4e9U, 0x3acba00dU, 0xa3cc903aU, 0xd14c0821U, 0x8e0bf421U, 0xc66f8a1aU, 0xe8dd7b29U, 0x6fe41986U, 0x4d734fc2U, 0x871f9198U, 0x41c1fbd4U, 0x89223b90U, 0x49d650d7U, 0x300f8a34U, 0xf96d7b08U, 0x295c19b9U, 0x1f274ffbU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x70000000U, 0xe8000000U, 0xec000000U, 0x62000000U, 0x4f000000U, 0xc6800000U, 0xe1400000U, 0x8a200000U, 0x88f00000U, 0xc4280000U, 0xea540000U, 0xd09e0000U, 0x55db0000U, 0xe1f98000U, 0x4c0a4000U, 0x9da1e000U, 0xda36d000U, 0xc2ced800U, 0x31428400U, 0x32204200U, 0x1cf36d00U, 0xd22f9180U, 0xc3527640U, 0xd71f1a20U, 0x5f1fa930U, 0x31833b8U, 0x6918cb5cU, 0xba19d39aU, 0xf69e1b4bU, 0xb4df0b80U, 0x9a789f7fU, 0xbcc94993U, 0x3444f26fU, 0xb7a15818U, 0x2937c426U, 0x1e4e221aU, 0xeb00fd36U, 0x18872985U, 0xb4476267U, 0x77a1e022U, 0xc936d010U, 0x6e4ed809U, 0x302841fU, 0xf4804215U, 0xd6436d29U, 0x38a7918eU, 0xfb6765eU, 0x8f091a3eU, 0x8920a904U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xb0000000U, 0x68000000U, 0x6c000000U, 0x32000000U, 0xad000000U, 0x35800000U, 0x12400000U, 0x9e200000U, 0x24900000U, 0xa4180000U, 0x59340000U, 0x11ce0000U, 0xc18f0000U, 0x3aaf8000U, 0x97ba4000U, 0xcbe7e000U, 0xa5f25000U, 0xfb2bc800U, 0x13f99c00U, 0x76c64a00U, 0xf3e7c500U, 0xd1f26280U, 0xad2b47c0U, 0x50fa0220U, 0xb4401930U, 0x1525c898U, 0x5a15d2ecU, 0xa8da28baU, 0x7bd382ebU, 0x7fbfe0b4U, 0x67e51ef7U, 0xf7f62aafU, 0xe6289bc3U, 0x4e7ba809U, 0x8858c25U, 0x5fc4622aU, 0x5863090eU, 0x3cb060b8U, 0x1b8f5ecdU, 0x3ba9caa1U, 0xf03ecbe5U, 0xc4a6600dU, 0x6657101eU, 0xa1fba838U, 0x1bc58c39U, 0xa664621aU, 0x73b30926U, 0x5b0860b3U, 0x186b5efcU, 0x80000000U, 0x40000000U, 0xe0000000U, 0xf0000000U, 0xe8000000U, 0x5c000000U, 0x92000000U, 0xe5000000U, 0x75800000U, 0xddc00000U, 0xb7a00000U, 0xfe900000U, 0x50f80000U, 0xa9b40000U, 0xae2a0000U, 0x2f2b0000U, 0x2ca98000U, 0x226e4000U, 0xd34c6000U, 0x469d5000U, 0x22840800U, 0x1d401c00U, 0xe7e07600U, 0xd0f78900U, 0x3fccae80U, 0x2cdf20c0U, 0x55e7fe20U, 0x65f2d510U, 0xb24938b8U, 0xb51bb9fcU, 0xc443389aU, 0xb060b9c7U, 0xe032b8bcU, 0x51eaf9d5U, 0x758cd8bfU, 0xbb8a9ccU, 0xd55350abU, 0x7459f5fdU, 0xf1a4c68fU, 0x65926cdfU, 0x5a7b801dU, 0x48f14001U, 0xcbcfe009U, 0x2d81038U, 0xd2e1e825U, 0x1d730c16U, 0x46081e28U, 0x4d7ac51fU, 0x6870d089U, 0x6b8cb5c4U, 0xc4b9268aU, 0xe1d57cdbU, 0x80000000U, 0x40000000U, 0x60000000U, 0x90000000U, 0x88000000U, 0x3c000000U, 0xa6000000U, 0xad000000U, 0x67800000U, 0xdbc00000U, 0xd4a00000U, 0x5e500000U, 0x580000U, 0x70740000U, 0xda4a0000U, 0x3b4f0000U, 0xa2ca8000U, 0x94000U, 0xb9286000U, 0xbfb8f000U, 0x9dc14800U, 0xa9a62c00U, 0xd1d4a600U, 0x779ce100U, 0x8ad6e880U, 0x1518fdc0U, 0xfa956e20U, 0xa47c8d10U, 0x6960ae98U, 0x7f5ace4U, 0xc98aae82U, 0xb3eaacdfU, 0xca982e91U, 0x2557ecdfU, 0x92da4e83U, 0x18301ccdU, 0xdf298686U, 0x32bb70c7U, 0xa4740aaU, 0x6a6461faU, 0xb1706029U, 0xb3ccf03fU, 0x818b4817U, 0xafe92c3dU, 0x9c9e263fU, 0x9055a138U, 0x415e88bcU, 0x59f00df2U, 0x8c2608U, 0xa66ea111U, 0xb65e0898U, 0x15764de1U, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0x28000000U, 0x94000000U, 0x82000000U, 0xa1000000U, 0x13800000U, 0x69400000U, 0x90200000U, 0x7d700000U, 0xa7580000U, 0x6bd40000U, 0x52ea0000U, 0x8cef0000U, 0x2bec8000U, 0x536c4000U, 0x4cab2000U, 0xc4ad000U, 0xbd5f6800U, 0x66d6ec00U, 0x1f6c3200U, 0x2ad6500U, 0xa3484580U, 0x61db95c0U, 0x8315da20U, 0x4288c910U, 0xb63bd798U, 0x328460d4U, 0x3ac3d7aaU, 0x996060f5U, 0xbd51d798U, 0xf22b60ecU, 0x588f57b6U, 0xbb3c20fbU, 0x7f02f7b6U, 0xb485b0d6U, 0x11c23fbfU, 0x8fe1ccc9U, 0x3d9045a6U, 0x164f95efU, 0xb05fda11U, 0x2b57c902U, 0x912f57bcU, 0x8a0c20e6U, 0x91faf7b2U, 0xae61b0ecU, 0xcdd03f9bU, 0x49eaccc7U, 0xe26ec5b1U, 0x1728d5cbU, 0x80000000U, 0x40000000U, 0xe0000000U, 0xb0000000U, 0xb8000000U, 0x94000000U, 0xa000000U, 0xb000000U, 0x4800000U, 0x7cc00000U, 0x2200000U, 0x9d00000U, 0xb3980000U, 0xe0740000U, 0xd00a0000U, 0xe20b0000U, 0x3d0b8000U, 0xd38cc000U, 0x14482000U, 0xaae91000U, 0x4bfdb800U, 0xf0459400U, 0x12e20e00U, 0x75f3dd00U, 0xb4f6480U, 0xe46b27c0U, 0xdc3e3620U, 0x46e18910U, 0xdff6cab8U, 0x50492aecU, 0xe8eeca8eU, 0x8cfd2af5U, 0xdac4ca9aU, 0xd7262afeU, 0xec574ab7U, 0x70deeac6U, 0x22156ab4U, 0x333cfad9U, 0x50635299U, 0x6c35aefcU, 0x54e97c81U, 0xbaff63feU, 0xa7c3a016U, 0x4ea5d00aU, 0xb9159808U, 0x9fbc843cU, 0x50a7b628U, 0xf8124932U, 0x703f6a95U, 0x98e7fadcU, 0x3ef0d2a3U, 0xefcd6ed6U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xd0000000U, 0xc8000000U, 0x24000000U, 0x62000000U, 0x7000000U, 0x13800000U, 0xec400000U, 0xa8a00000U, 0x6df00000U, 0x2d080000U, 0x5dd40000U, 0xe93e0000U, 0x793b0000U, 0x913c8000U, 0x853b4000U, 0xff3aa000U, 0x143ed000U, 0x41bcd800U, 0xc8ff6c00U, 0x74d8aa00U, 0xe6ea1100U, 0x8f035980U, 0x17801b40U, 0xbe46f220U, 0xb7a53d30U, 0x9275d3b8U, 0x874b9a74U, 0x9075d392U, 0x904b9a79U, 0xabf5d380U, 0x880b9a45U, 0xa955d3aeU, 0xc6fb9a76U, 0xf5ddd398U, 0x706f9a57U, 0xa7c3d3bdU, 0x88e49a60U, 0xb35753a6U, 0x3dfbda72U, 0x885bf3b3U, 0xd2a0a5aU, 0xb1e5ab92U, 0x39d52660U, 0xab3b2199U, 0x4e3aa776U, 0x9abe002bU, 0x857b0038U, 0x119c8025U, 0x1ccb4006U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x30000000U, 0xa8000000U, 0x3c000000U, 0xe2000000U, 0x51000000U, 0x84800000U, 0xd1400000U, 0x29a00000U, 0xe2900000U, 0xbfa80000U, 0xb40000U, 0x5bfa0000U, 0x2790000U, 0x5dbf8000U, 0x685e4000U, 0xf5eb6000U, 0x8090d000U, 0xaea8a800U, 0x24371400U, 0xbabc3200U, 0x83dd5100U, 0x832e4280U, 0x35f5c640U, 0xa4591a20U, 0x5fe90510U, 0x7d9490a8U, 0x502b074cU, 0x3071108aU, 0xc99c475fU, 0x30df0b0U, 0xc0a6d748U, 0x82143883U, 0xb8e81367U, 0x96172290U, 0x26e8167fU, 0x85143214U, 0xc3695133U, 0x78d44287U, 0x78cc65bU, 0x51e69a21U, 0xbb7451dU, 0x6a7ff0bfU, 0x81bbd774U, 0x1a59b8a4U, 0x3ceb5340U, 0x9011c287U, 0xa1eb866aU, 0xbe927a1bU, 0x8da9d519U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0x68000000U, 0x6c000000U, 0x92000000U, 0x6d000000U, 0x94800000U, 0x51c00000U, 0x25600000U, 0xcb500000U, 0xd9680000U, 0x1b40000U, 0x847e0000U, 0xe7fd0000U, 0x73bf8000U, 0xf9984000U, 0x9f6de000U, 0xaab15000U, 0x7bf9c800U, 0x69b89400U, 0x689ad600U, 0x41e95700U, 0x92726880U, 0x341ff240U, 0xc2a9e20U, 0x6d108330U, 0x4e4cde88U, 0xbbc6b56cU, 0x3c655ebaU, 0xe9d7f56bU, 0xaba93e8cU, 0x2753e547U, 0x8b6a9697U, 0x4cb66153U, 0xa0fa689fU, 0xde3bf26eU, 0x3adc9e05U, 0xa0c98308U, 0x2b055ebbU, 0x3f87f573U, 0xae413e98U, 0xab27e568U, 0xd0749690U, 0x611b6172U, 0xcade88bU, 0x1ad7b27cU, 0x902f7e29U, 0x7715d313U, 0xdf4b1685U, 0x65432142U, 0x80000000U, 0x40000000U, 0x60000000U, 0xd0000000U, 0x98000000U, 0x9c000000U, 0xf6000000U, 0x49000000U, 0x20800000U, 0x1400000U, 0x84a00000U, 0x88b00000U, 0x9df80000U, 0xa7940000U, 0x1f8a0000U, 0x440f0000U, 0x66c88000U, 0xcca9c000U, 0xe07f6000U, 0x5450f000U, 0x96de800U, 0x9f9f1400U, 0x1f455200U, 0x39a1f900U, 0xea31d380U, 0xf7be7cc0U, 0xb8b23a20U, 0x95fc2d10U, 0xc3916198U, 0xa58db5f4U, 0x630be186U, 0x934f75f7U, 0x1b6e0185U, 0x2c9d45f6U, 0x78c60996U, 0x1d6061c3U, 0x21535382U, 0x2fe8bcf3U, 0xffddda0cU, 0x6f611d38U, 0x4251e9adU, 0xd06951f2U, 0x4719dbacU, 0x520358ddU, 0xd3076034U, 0xb784f039U, 0xbcc7e82cU, 0x5760141dU, 0x2e55d23cU, 0xe6c3907U, 0xda1cb38cU, 0x80858cd6U, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0x58000000U, 0x7c000000U, 0x2a000000U, 0x73000000U, 0xe2800000U, 0xd6400000U, 0x58e00000U, 0x1ef00000U, 0x11280000U, 0x30540000U, 0x673a0000U, 0x178f0000U, 0x72468000U, 0x4ee3c000U, 0x27f06000U, 0x90ab1000U, 0x5c96b800U, 0x959fa400U, 0x7b9b7a00U, 0xe98cb00U, 0x8d1e9180U, 0xa6da9c40U, 0xb8fda220U, 0x27ac7f10U, 0xb8135398U, 0x22ddf344U, 0xdef849b6U, 0x56ae284fU, 0x1d906032U, 0x181b1008U, 0x755eb836U, 0xab3ba42eU, 0x55897a0aU, 0x5543cb04U, 0xb26211b6U, 0x8cb65c65U, 0xfcb4217U, 0x2fa4af27U, 0x9b958b96U, 0x3919475cU, 0xe8dd8ba2U, 0xfdfd4762U, 0x8c2f8ba0U, 0xa7d6477bU, 0x32fb0b9dU, 0x64ae874aU, 0x7297eb8fU, 0xc0995778U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x70000000U, 0x78000000U, 0x74000000U, 0x9e000000U, 0x67000000U, 0x17800000U, 0xb2400000U, 0xd8e00000U, 0xc3100000U, 0xc5880000U, 0x91b40000U, 0x8a7e0000U, 0x992b0000U, 0xb1418000U, 0x9962c000U, 0xfa572000U, 0x90ecb000U, 0x61e75800U, 0x9391ec00U, 0xf04d5a00U, 0xf312c300U, 0x9d8ef680U, 0x75b5d940U, 0x1c7d2220U, 0xf22f9f30U, 0x4cc4f4b8U, 0xd226f65cU, 0x52368ebeU, 0xf63c856dU, 0xcec9203fU, 0x19d7b035U, 0x7caed823U, 0x3e072c2dU, 0x37047a0fU, 0xff857334U, 0xce402e93U, 0x4ae2f551U, 0x4e115831U, 0x2b0eec0aU, 0x5372da13U, 0xf75b032eU, 0x309856b3U, 0x6f3ba97bU, 0xe4d5a11U, 0x2412c30dU, 0x120ef693U, 0xc3f5d94eU, 0x229d2209U, 0x223f9f00U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0xe8000000U, 0x24000000U, 0xc2000000U, 0x21000000U, 0xeb800000U, 0xb0400000U, 0x29200000U, 0x5dd00000U, 0x2a280000U, 0xcb40000U, 0x6ada0000U, 0xf1490000U, 0x19448000U, 0x56a04000U, 0x3796a000U, 0xbe0bd000U, 0xb4e36800U, 0x37b26c00U, 0xdc5f9a00U, 0x54899d00U, 0xff217080U, 0xe6d3ba40U, 0xdcaa5220U, 0x9702110U, 0xdcbd82a8U, 0xa9384b54U, 0xd67cb89aU, 0x23de0659U, 0x7ecca038U, 0xcb02d00cU, 0xe87e828U, 0x69c22c31U, 0x613a00U, 0x53764d16U, 0x21b81880U, 0xecb8d667U, 0xf139480aU, 0xea7dfc17U, 0x7dd8522eU, 0x51cd2115U, 0xe78302a7U, 0xb6410b59U, 0x3a2698a1U, 0x2f51967cU, 0xbdeb680eU, 0x73d66c07U, 0xfd2d9a07U, 0x4c349d11U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x10000000U, 0xa8000000U, 0x24000000U, 0xde000000U, 0xd1000000U, 0x23800000U, 0xbc00000U, 0x3d600000U, 0x85f00000U, 0x38280000U, 0x7540000U, 0x36be0000U, 0x2f8f0000U, 0xe4428000U, 0x6ca04000U, 0xc792a000U, 0xf75b3000U, 0x9b3ee800U, 0xfd4ccc00U, 0xaea12600U, 0x8493ff00U, 0x9fdbad80U, 0xac789440U, 0x916d6e20U, 0x1a740330U, 0xd1ec6398U, 0xc933a744U, 0x3c9e58aU, 0xbce06879U, 0xdd30200fU, 0xc5cb7000U, 0x91e4483aU, 0xbcb3fc0fU, 0x4d09ce12U, 0xa404331cU, 0x1e060bb1U, 0xb1042b77U, 0x3386e3aaU, 0xa3c7e758U, 0x19654580U, 0x5bf4584fU, 0xe92c4820U, 0x24d7fc0aU, 0x3d7fce17U, 0x12ef3316U, 0x61b28bb6U, 0x548f6b78U, 0xc0c0c3a0U, 0xc1e7974eU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x30000000U, 0x58000000U, 0x9c000000U, 0x2a000000U, 0x87000000U, 0xde800000U, 0x40c00000U, 0x4be00000U, 0xee300000U, 0xaa480000U, 0x7f140000U, 0x109e0000U, 0x19ef0000U, 0x9f038000U, 0xe287c000U, 0x3ac66000U, 0xa4e21000U, 0xf4b21800U, 0x5c8b4400U, 0x99f36e00U, 0xa72e9300U, 0x2de48380U, 0xeb328b40U, 0x57cf1620U, 0x6753c730U, 0xeebbf598U, 0x79b85c4cU, 0x6f3b7bb6U, 0xbbf81f57U, 0x2e1e0032U, 0xa92f001dU, 0xece38039U, 0xa0b7c03bU, 0xe28e600eU, 0xc0f6103dU, 0x10ac1817U, 0x82a4442eU, 0x9390ee21U, 0xeb59532dU, 0xf68ae39fU, 0xdef49b5cU, 0x19ab0e00U, 0x5d238300U, 0xf8d51b86U, 0x25fe0f65U, 0xe71a1839U, 0x16af442fU, 0xb7a56e2aU, 0x36159329U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x90000000U, 0x58000000U, 0x64000000U, 0xe2000000U, 0xfb000000U, 0xc5800000U, 0x4f400000U, 0x27a00000U, 0x5b00000U, 0x3dd80000U, 0x3f540000U, 0x8cca0000U, 0x8ebb0000U, 0x8f028000U, 0x3f87c000U, 0x3040a000U, 0x90215000U, 0xe9f63800U, 0xbbfa1c00U, 0x97a6b200U, 0x6db2c900U, 0x71db7b80U, 0x715229c0U, 0xa9c82a20U, 0x363d8510U, 0x1cc1f1b8U, 0x69e1fce4U, 0x989763b6U, 0xc0aaa5c9U, 0xc96a0020U, 0x300b000aU, 0x975a801fU, 0xdf93c02eU, 0xc32aa027U, 0x7f2a5026U, 0xb92cb806U, 0x4029dc22U, 0xeeac121bU, 0x3c689931U, 0x308fc3a5U, 0xf09ff5c1U, 0x33f63800U, 0xf4fa1c18U, 0x826b202U, 0x2df2c926U, 0x29fb7b9cU, 0xa4a229e9U, 0x94302a32U, 0xb8998538U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x90000000U, 0x18000000U, 0x54000000U, 0xce000000U, 0x85000000U, 0xc2800000U, 0xebc00000U, 0x9a600000U, 0x6d500000U, 0xdcb80000U, 0x1af40000U, 0x28e0000U, 0x439d0000U, 0xec068000U, 0xca07c000U, 0x73072000U, 0x83823000U, 0xff464800U, 0xa0a2c400U, 0xfbb50600U, 0xdf2eef00U, 0x9eae2080U, 0x9eef68c0U, 0x7cc6e20U, 0xd83a1b30U, 0xf8336e88U, 0xe06e43e4U, 0x1e09c8a6U, 0xf5585ce5U, 0xc0e0001bU, 0x12900035U, 0xa8d8003eU, 0x62a4000bU, 0x4b60013U, 0xe6a9002fU, 0xbae88034U, 0x61cac01dU, 0x8139a016U, 0xb8b1f031U, 0x14af682aU, 0xdedf42fU, 0x344dce2bU, 0xaf7feb36U, 0x14920684U, 0x81deb7caU, 0x8a2286b9U, 0x2c7077d5U, 0x774d26acU, 0x64f887fbU, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0x8000000U, 0x2c000000U, 0xa000000U, 0xf000000U, 0xf8800000U, 0x77400000U, 0x3be00000U, 0xc0700000U, 0xd9c80000U, 0x1ed40000U, 0x395a0000U, 0xb1ef0000U, 0xd0058000U, 0x58014000U, 0x3401e000U, 0x5e039000U, 0x21015800U, 0xd186f400U, 0x8ac39200U, 0xbb266300U, 0x74527d80U, 0x551cab40U, 0x3c8b2a20U, 0x3e370710U, 0x4faab798U, 0x46633c5cU, 0xb745a2U, 0xde88f5bU, 0xe200003aU, 0x1300000fU, 0x9a800024U, 0x2440000aU, 0xc160000eU, 0x94300038U, 0x10a8000aU, 0xa6e40019U, 0x23f2003eU, 0x180b0001U, 0xb77800cU, 0x374a4021U, 0x4966035U, 0xa939d03cU, 0xfc5f3832U, 0x666b240eU, 0x4fc6aa1bU, 0x6ca2472fU, 0xeb915798U, 0x61bfac76U, 0x80000000U, 0x40000000U, 0x60000000U, 0x30000000U, 0x78000000U, 0x9c000000U, 0xd2000000U, 0x83000000U, 0xed800000U, 0x74400000U, 0x16a00000U, 0x36100000U, 0x77280000U, 0x9af40000U, 0x469a0000U, 0xd54f0000U, 0x2878000U, 0x13c2c000U, 0x2de66000U, 0x5734d000U, 0x527b3800U, 0x58f91c00U, 0xcf3f2a00U, 0x9cdec100U, 0xe2e9fe80U, 0x4217ee40U, 0x512a7220U, 0x7ff70d10U, 0x2e1fec98U, 0xf98b334cU, 0x40e126beU, 0xfbb3e277U, 0x60bd800cU, 0x39dc03cU, 0xadc9e03dU, 0x6421036U, 0x85a7582fU, 0xf392cc0aU, 0xd76b9212U, 0xba511d1bU, 0xbd8ab4afU, 0x1ee2ff65U, 0x82b734b8U, 0xda3f3f7fU, 0xac5ed4bfU, 0x22d2f5aU, 0x9a718ca3U, 0xde5be35cU, 0x91281eaaU, 0x5ff1fe6dU, 0x7e1f2a0eU, 0xb18ec115U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x90000000U, 0x98000000U, 0xfc000000U, 0xf6000000U, 0x83000000U, 0xcf800000U, 0x83400000U, 0x39200000U, 0x9a700000U, 0x61f80000U, 0x7a140000U, 0x8faa0000U, 0x411b0000U, 0x26828000U, 0xe9c1c000U, 0x8ee46000U, 0x8397f000U, 0x2fef3800U, 0xc7ba2c00U, 0x37b1b200U, 0xd51ead00U, 0x64813580U, 0x18c49cc0U, 0x5862ea20U, 0x22577110U, 0x250dbfb8U, 0xde2f1de4U, 0xf55aed86U, 0xa22780efU, 0xe9f08025U, 0xf4bec014U, 0x5034e02dU, 0x4259303bU, 0x5fa3d815U, 0x93b71c39U, 0x7f186a16U, 0x6182b11eU, 0x5c43df9eU, 0x70a3edd6U, 0x923755bfU, 0xf35c6cd2U, 0x69255200U, 0xa2779d1aU, 0xedfaedbfU, 0x841780c0U, 0x68a8801cU, 0x849ac020U, 0xd0c6e007U, 0x9c663033U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xf0000000U, 0xc8000000U, 0x8c000000U, 0xf6000000U, 0x2d000000U, 0xaa800000U, 0xc9400000U, 0x3ca00000U, 0xfd100000U, 0xdcc80000U, 0x75f40000U, 0xaffe0000U, 0xc96b0000U, 0x78658000U, 0x71774000U, 0x3fbce000U, 0xd4a7000U, 0xeb314800U, 0x289f8400U, 0x759c1200U, 0xd71e1900U, 0x725bd680U, 0x48f81940U, 0x50efba20U, 0xaaa0ed30U, 0xe0130cb8U, 0x5e4ec47cU, 0xc0b49e92U, 0xad5c9d53U, 0x957e2825U, 0xf82db407U, 0xe0c23a20U, 0x663ad2dU, 0xf071ec80U, 0x733fb457U, 0xd1085680U, 0x39105954U, 0x66c8da16U, 0x4ef6dd33U, 0xd87b24acU, 0x62ac7061U, 0x18524bcU, 0x46c77074U, 0x3360a480U, 0xef03051U, 0xf87c4483U, 0x72aa4048U, 0x39850c86U, 0x2c1c45dU, 0x80000000U, 0x40000000U, 0x20000000U, 0x50000000U, 0xe8000000U, 0x24000000U, 0x5e000000U, 0xe3000000U, 0x19800000U, 0xd8c00000U, 0xea200000U, 0x63900000U, 0x46f80000U, 0xda740000U, 0xb2ca0000U, 0x59dd0000U, 0x77648000U, 0xa3744000U, 0x264aa000U, 0xe39b3000U, 0xc0077800U, 0x60001c00U, 0x7000ae00U, 0xb8054500U, 0xcc037680U, 0x7a0070c0U, 0xbd077620U, 0xfa836910U, 0xc1402088U, 0x32e169d4U, 0x89b60e9aU, 0x25696cd9U, 0x9c89583fU, 0x68bf6c3cU, 0xeb157634U, 0x2eba692bU, 0xd416a097U, 0x853c29e9U, 0xc5d22ea0U, 0x239b1ce8U, 0xa0000038U, 0x1000003cU, 0xc8000004U, 0x7400001bU, 0xb6000019U, 0xc7000029U, 0x47800010U, 0x3bc00028U, 0xf3a00034U, 0xbb500010U, 0xacd80021U, 0xb9e40010U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xf0000000U, 0xf8000000U, 0x24000000U, 0x8e000000U, 0x75000000U, 0x8e800000U, 0xb1c00000U, 0x68a00000U, 0x59b00000U, 0xc4180000U, 0x2dd40000U, 0xf8a0000U, 0x67bb0000U, 0xd7e18000U, 0xc0d2c000U, 0x1509a000U, 0x40783000U, 0x1e434800U, 0x61e42400U, 0x31d2d600U, 0x58cd900U, 0x8cb9d780U, 0x2463bbc0U, 0x23923e20U, 0x666bcd10U, 0x8a69c9b8U, 0x786986fcU, 0xb7689f9eU, 0xcae89fd9U, 0x5cab683bU, 0xa14ed431U, 0xda983e25U, 0xd410cd19U, 0x5b284987U, 0x640b46c2U, 0x10f93f91U, 0x3284afeaU, 0xabc22022U, 0x8ba1f00fU, 0x76336818U, 0x8d5ad418U, 0xa5b23e2aU, 0x3e1bcd16U, 0x3ed1c9b1U, 0xd80d86c0U, 0xafa9fa5U, 0xd1879fcbU, 0x8440e812U, 0xc2e71430U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0x28000000U, 0x4c000000U, 0x9e000000U, 0x19000000U, 0x96800000U, 0x67c00000U, 0xe9e00000U, 0x28500000U, 0x65980000U, 0x27740000U, 0x86ae0000U, 0xd77d0000U, 0xf6a28000U, 0x67764000U, 0x66abe000U, 0xe7793000U, 0xcea1e800U, 0x3752400U, 0xb4ae8600U, 0x607ef300U, 0x4127e880U, 0xf236cdc0U, 0x3a8a8e20U, 0xa1cfe730U, 0xcea0688U, 0xb0db5ac4U, 0x9b5000aaU, 0xf01ae9e3U, 0x2d30880fU, 0x210e5432U, 0x9a8a8e27U, 0x71cfe70eU, 0x4ea0697U, 0xecdb5adfU, 0x2d5000bbU, 0xa51ae9e6U, 0x25b08816U, 0x5fce5412U, 0xe5ea8e1cU, 0x3e5fe70dU, 0x8892068cU, 0xe3ff5ad0U, 0xce66008dU, 0x5513e9c3U, 0x55bc083eU, 0xefc5141fU, 0x75e3ee1bU, 0xbe509711U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0x88000000U, 0xcc000000U, 0xc6000000U, 0xb9000000U, 0xdf800000U, 0xac00000U, 0x41600000U, 0xdb00000U, 0xd680000U, 0x43140000U, 0x303e0000U, 0x2c0d0000U, 0x9ea38000U, 0xa5534000U, 0x1b1ee000U, 0x2c9ff000U, 0x3a5de800U, 0x253dac00U, 0xe5892e00U, 0xb567ff00U, 0x4fb26780U, 0x9e6ea640U, 0xd3942620U, 0xd478a330U, 0x742d2188U, 0x1eb3b54cU, 0x5def8f82U, 0x87530a43U, 0x581d0819U, 0x241f5c12U, 0xaa1f461dU, 0xff1d133dU, 0xd69ba983U, 0xed5ba95eU, 0xbfb829a5U, 0x7ec8e94cU, 0x8bc6c983U, 0x1ae71976U, 0x2d7321beU, 0x30eb575U, 0xa0240fb2U, 0x24144a71U, 0xe2bde829U, 0x5b4dac08U, 0x56012e24U, 0xc103ff1fU, 0xbb8467acU, 0x30c7a669U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0xe8000000U, 0x34000000U, 0x66000000U, 0x5d000000U, 0x3800000U, 0xf8c00000U, 0x5ea00000U, 0xbc900000U, 0xd6880000U, 0xdbf40000U, 0x853e0000U, 0x822d0000U, 0xb0648000U, 0x47304000U, 0x959e2000U, 0x77bef000U, 0xd36e0800U, 0xd1018c00U, 0x79879e00U, 0xd7c0c100U, 0xb6225e80U, 0xf2d65740U, 0x4769b620U, 0xa702bd30U, 0xec874888U, 0x30435a74U, 0xc0e4569aU, 0xc573db7dU, 0x9e782831U, 0xd44b7c13U, 0x6a579632U, 0xf12c4d07U, 0xcae140b4U, 0x1276d675U, 0x8afdc88cU, 0x180e1a6fU, 0x28b6f69eU, 0xe7596b75U, 0x3e1e001cU, 0x5b7d0001U, 0x1bcc801aU, 0x8944025U, 0x7088201aU, 0xa6f7f021U, 0x56bc8819U, 0x92e8cc3fU, 0xdac33e1eU, 0x9da37132U, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0x38000000U, 0x64000000U, 0x96000000U, 0x11000000U, 0x4d800000U, 0xf5400000U, 0x99e00000U, 0x4cd00000U, 0x3e580000U, 0x1d740000U, 0x2cea0000U, 0x19bf0000U, 0xaca18000U, 0xf530c000U, 0xe28fa000U, 0xeb2ef000U, 0x6d9c6800U, 0xc750fc00U, 0x321d1200U, 0x5176b00U, 0xaf78c080U, 0x6503c7c0U, 0x5384da20U, 0xd8466710U, 0xd6603a98U, 0x69090fcU, 0x9f3ca8aeU, 0x7f673bc9U, 0x6f13c81dU, 0x9c7e0c28U, 0x7817a05U, 0x56479718U, 0x3365d28dU, 0x1514acceU, 0x277c1a99U, 0x5905a0eeU, 0x5184e086U, 0x6746f7c4U, 0xeee49234U, 0x2853ab1cU, 0xe29d608fU, 0xe7d237daU, 0xe8d93223U, 0x26b65b3aU, 0x7aca8897U, 0x5d4d0bd0U, 0x9b0a001cU, 0x606f0032U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x30000000U, 0xd8000000U, 0xb4000000U, 0x8e000000U, 0x49000000U, 0x70800000U, 0xbec00000U, 0x2f200000U, 0x47300000U, 0x59780000U, 0x19d40000U, 0x34ee0000U, 0xbbd90000U, 0x7ea38000U, 0x2575c000U, 0x52992000U, 0x86c73000U, 0xcb272800U, 0x81375400U, 0x4c7a4e00U, 0x8b527500U, 0xf92feb80U, 0x237b34c0U, 0xbed24620U, 0x9d6f1130U, 0x9d9f0da8U, 0x8342d5ccU, 0x77654396U, 0x8bd0a0ddU, 0xffeaa82bU, 0x285b942eU, 0x9fe0ee02U, 0xe110850eU, 0xcec9e39eU, 0xce6f50eeU, 0xda192009U, 0x7c07300bU, 0x12072832U, 0xb07541cU, 0x33824e34U, 0xd1467533U, 0x1c61ebacU, 0x285234dbU, 0xc6a9c61cU, 0x583ed118U, 0x8db02dbbU, 0xe0b8e5d7U, 0xaf77eb98U, 0x8d9f34d2U, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0x8000000U, 0x9c000000U, 0x8a000000U, 0x71000000U, 0xe800000U, 0x5cc00000U, 0x83600000U, 0x31900000U, 0x75280000U, 0x51340000U, 0x865a0000U, 0x50cf0000U, 0x90668000U, 0x82114000U, 0xc56f6000U, 0x73909000U, 0xb82d2800U, 0xa5b7c400U, 0xb39fbe00U, 0x4928a700U, 0xeb317e80U, 0x8f584440U, 0xda4ff620U, 0xd2a4f310U, 0x66776898U, 0x17d6744U, 0x25fad6a2U, 0x383ec077U, 0xcddf281aU, 0x248cc408U, 0xccc33e19U, 0xcb66e734U, 0xcd909e80U, 0xef2d9477U, 0x2837be1cU, 0x14dca70fU, 0x860b7e9aU, 0x6207444bU, 0xbd01763bU, 0xec81b30fU, 0xa1c208b7U, 0xfe2f744U, 0x80517e8aU, 0x72c8447dU, 0x4d67f603U, 0x7e90f32aU, 0x6cad68a1U, 0xe0726776U, 0x80000000U, 0x40000000U, 0x60000000U, 0xd0000000U, 0xb8000000U, 0xf4000000U, 0x36000000U, 0xb7000000U, 0x99800000U, 0x6bc00000U, 0xa8200000U, 0xac500000U, 0x7df80000U, 0x92b40000U, 0xbd0a0000U, 0x1c5f0000U, 0xad208000U, 0xfcd4c000U, 0xc4ba2000U, 0x62d6f000U, 0x1fbdd800U, 0x8955dc00U, 0x9d7bd600U, 0x43f6f500U, 0x169d080U, 0x7cee80c0U, 0xb92e2e20U, 0xe20ed910U, 0x89dd5e98U, 0x64e269f4U, 0x5f4888eU, 0xfe6f9cedU, 0x196fd835U, 0x78eedc09U, 0x87295610U, 0xc9093513U, 0x6a597089U, 0x7a23b0fbU, 0xb5515614U, 0x177d3503U, 0x3ef370bbU, 0x85ecb0c2U, 0x43a9d610U, 0x964df51dU, 0x953b5094U, 0xb51140e2U, 0x7d9e8e2bU, 0x3803e92dU, 0xb4022682U, 0x560185c5U, 0x6702a681U, 0x218545f6U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x50000000U, 0x28000000U, 0xec000000U, 0xea000000U, 0xc5000000U, 0x97800000U, 0xb4400000U, 0x6da00000U, 0x2d300000U, 0x32080000U, 0x3540000U, 0x56de0000U, 0xb9cb0000U, 0xf6b08000U, 0x1c484000U, 0x33f6e000U, 0x786a9000U, 0x11830800U, 0x5b400c00U, 0xdf229a00U, 0x5ef41900U, 0xc3ee6780U, 0xafc21740U, 0xa3e7f220U, 0x4d96c530U, 0x34b915b8U, 0x471c9254U, 0x112807aaU, 0xbfa0c74bU, 0xc321a22U, 0x138c5915U, 0xe0108797U, 0xadfc8742U, 0xb13afa0bU, 0x325dc931U, 0xd0b0fabU, 0x59d0cb48U, 0x29188001U, 0xf22c4003U, 0xb720e028U, 0x92f59029U, 0x99ed883aU, 0x12c34c26U, 0xf064fa0dU, 0xffd6c905U, 0x761b8fafU, 0x38a88b63U, 0xe66016U, 0x6512d036U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0xd8000000U, 0x84000000U, 0xc6000000U, 0xed000000U, 0xf2800000U, 0xb1c00000U, 0x53200000U, 0xc0500000U, 0x9f880000U, 0x40340000U, 0xa53e0000U, 0x68c90000U, 0x6cd28000U, 0x274dc000U, 0x9795a000U, 0xf1ae7000U, 0xae48800U, 0x1f730400U, 0x65df1600U, 0x60bac500U, 0xe48ee880U, 0xe7b7a340U, 0xd27cbe20U, 0x842a7130U, 0x4ea0d6a8U, 0xc8101244U, 0xd2e9c896U, 0x58041351U, 0x44059639U, 0x6603050fU, 0xfd0548a2U, 0x2a80d349U, 0x35c2b633U, 0x9520b51aU, 0x2d546082U, 0x6d0da743U, 0xf1f12817U, 0xf61d7417U, 0xa89b9e31U, 0xf359c116U, 0x6779fea1U, 0x32a9667bU, 0x996456b5U, 0x6630d26fU, 0x3838e8b4U, 0xf24aa365U, 0x91103e1dU, 0xee6eb13dU, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0x68000000U, 0x24000000U, 0xce000000U, 0xc9000000U, 0xb800000U, 0xedc00000U, 0xfda00000U, 0xa500000U, 0x41680000U, 0xf9b40000U, 0x3f5a0000U, 0xe12f0000U, 0x54d68000U, 0x52a4000U, 0xbad6a000U, 0xbc2fb000U, 0xc9532800U, 0x1ded8c00U, 0xdef31600U, 0x10ba5900U, 0x5d1d5080U, 0xf4b6040U, 0x72201e20U, 0x19922510U, 0x6dcbce98U, 0xa4630544U, 0x11f570baU, 0xc63a9059U, 0x6d5f960bU, 0x8a2f1926U, 0xc557080U, 0x9c6a9076U, 0x24379636U, 0x479b1929U, 0x950f70b9U, 0x90459073U, 0xb5611608U, 0x66715918U, 0xd9f9d091U, 0xcbfa204bU, 0xc0fa3e09U, 0x8878d50bU, 0x7938c6bcU, 0xc3db794aU, 0xf66beea4U, 0x6336f576U, 0xe518f8b0U, 0x634cac77U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0x28000000U, 0x74000000U, 0x6e000000U, 0x55000000U, 0x6e800000U, 0xa9400000U, 0x4c600000U, 0xe1d00000U, 0x8eb80000U, 0xa2740000U, 0x4e4e0000U, 0xb7790000U, 0x5a548000U, 0x897a4000U, 0xe7542000U, 0x33fab000U, 0xf0114800U, 0x29b2400U, 0xb44d200U, 0x4b609f00U, 0xb0560080U, 0x8a7cd4c0U, 0x20d53a20U, 0x3e3b4b30U, 0x637baa8U, 0xe0addff4U, 0xcdeea0aaU, 0xd78824edU, 0x9f5e5213U, 0xb563df11U, 0xad56a0b9U, 0xe0fc24c3U, 0x1f905222U, 0x7b5adf00U, 0x9362208bU, 0xfc5664e3U, 0x187c7231U, 0xbfd46f12U, 0x43bd6895U, 0xe0f440d3U, 0x50c2038U, 0x9c1eb00eU, 0x9a074819U, 0xfb062416U, 0x9b86521fU, 0x17c7df23U, 0xcd20a0b2U, 0xd9b124eeU, 0x80000000U, 0x40000000U, 0x20000000U, 0x10000000U, 0x38000000U, 0xf4000000U, 0x12000000U, 0xe9000000U, 0x82800000U, 0x8c400000U, 0x77200000U, 0xfb700000U, 0x4c580000U, 0xbe940000U, 0xe24a0000U, 0x799d0000U, 0x4e768000U, 0x50dac000U, 0x1dd22000U, 0xfcebd000U, 0x5d2c2800U, 0x8fcda400U, 0xfc5d7a00U, 0xd690c500U, 0xe4d7d80U, 0x8f9911c0U, 0x8d75f220U, 0xcf5c7110U, 0x1160f88U, 0xee8ba0c4U, 0x53fbddaeU, 0xb4a101edU, 0x79b77a2cU, 0x713dc52eU, 0xd9c3fda6U, 0x6e7d1daU, 0x7195d237U, 0xfbcea129U, 0xae5ea7bfU, 0x1f95c4f2U, 0x9cc807abU, 0x3bddd4eeU, 0xe528fb1U, 0x262860ebU, 0xa44d7daaU, 0xd29911c4U, 0x3df5f203U, 0xba1c7104U, 0xccb60f9aU, 0x6dbba0d1U, 0x7a83ddbcU, 0x184501ebU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0x8000000U, 0x44000000U, 0xce000000U, 0x47000000U, 0x6f800000U, 0x35400000U, 0x68200000U, 0x6d300000U, 0xdab80000U, 0x11d40000U, 0x6dee0000U, 0xc1ff0000U, 0x2ef48000U, 0x75d4000U, 0xba03a000U, 0x9106b000U, 0x4835800U, 0xc1ac00U, 0xdc65a200U, 0x69902500U, 0x234fcf80U, 0xd10a06c0U, 0x16a9da20U, 0x2ede7930U, 0x4c449598U, 0x38a23ff4U, 0xcbf46fa2U, 0xd5d8b6e1U, 0xd1c4820bU, 0x78e0d515U, 0xd955b781U, 0x272f5ae8U, 0xf498000bU, 0xbfe4002bU, 0x76d60006U, 0x726b002cU, 0x4cba8018U, 0xdad24037U, 0xe86f2014U, 0xadbff00fU, 0x6656f818U, 0x74ac1c1dU, 0xf3dc7a0bU, 0xc2c3c92aU, 0xb1654da4U, 0x3f15d3fbU, 0xe688ed9cU, 0xafec63d0U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xf0000000U, 0xc8000000U, 0xd4000000U, 0x72000000U, 0xbb000000U, 0xc800000U, 0xadc00000U, 0x96e00000U, 0xff900000U, 0x59e80000U, 0xa340000U, 0x8e5e0000U, 0xb2290000U, 0xc5d58000U, 0x5e4d4000U, 0xa6802000U, 0x9ac45000U, 0xa4603800U, 0x7752d400U, 0x168d6600U, 0x49e3ab00U, 0x29176680U, 0xcb2bce40U, 0xda50fe20U, 0x7b0c6f30U, 0xd7a418a8U, 0x54b7e17cU, 0xa89f4692U, 0x404b9e45U, 0xb386c614U, 0x2b43bb22U, 0x3c22fe99U, 0x33f00a62U, 0xabd802bU, 0xa6b94014U, 0xa8be2021U, 0xe5bd503bU, 0x183db837U, 0x1e7b940dU, 0x8fdb461eU, 0x826afb04U, 0x574de9fU, 0x8795a63U, 0xeede383eU, 0xb1ebd429U, 0xee30e623U, 0x945aeb1dU, 0x2d29469bU, 0x73569e50U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x10000000U, 0x38000000U, 0x7c000000U, 0xae000000U, 0x81000000U, 0xf6800000U, 0x81c00000U, 0xc2600000U, 0x48300000U, 0x90e80000U, 0x23140000U, 0x727a0000U, 0x6b2b0000U, 0xca768000U, 0x7fccc000U, 0xb3806000U, 0xe5463000U, 0x8ca12800U, 0xedd1a400U, 0x979cb600U, 0x8c5a4f00U, 0x753a8b80U, 0x408b9240U, 0xe4237e20U, 0x65151b10U, 0x177d75b8U, 0xbfad4944U, 0x4cb2ebaeU, 0x8e29a24fU, 0x5ef05633U, 0x190bbf34U, 0x5265438bU, 0x3034c67bU, 0xcec8035U, 0x9d17c03dU, 0xcb7ee00aU, 0xe1aef00cU, 0xe5b3481fU, 0x3ca89437U, 0xd311e0dU, 0xf46c2b25U, 0x6dd0dda9U, 0xd79b2d4bU, 0x6c58bd9dU, 0x65391d7cU, 0x788b9587U, 0x9827b959U, 0xcb13a398U, 0x967e3643U, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0xa8000000U, 0x44000000U, 0x2e000000U, 0x1d000000U, 0x9800000U, 0x3fc00000U, 0x73e00000U, 0x6ff00000U, 0x60a80000U, 0xdc540000U, 0xf27a0000U, 0xe36d0000U, 0xddb18000U, 0x628e4000U, 0xd40a000U, 0xaca1b000U, 0x8c568800U, 0xea7c9c00U, 0x2f692600U, 0x47b71b00U, 0xf988bd80U, 0x5dc30c40U, 0xb4e68e20U, 0xdd707710U, 0xffedb388U, 0x1ff43b7cU, 0x88a81d8aU, 0xb852bc41U, 0x2c780623U, 0x5668eb2bU, 0x903695a0U, 0x734a2062U, 0x63a3201dU, 0xcad6f01dU, 0xd33da819U, 0x45ce6c03U, 0xb2e68e08U, 0xc470773dU, 0xf86db3b8U, 0xcd343b73U, 0x5ac81d85U, 0xac62bc7bU, 0x1130061cU, 0xf8cceb2dU, 0xb649585U, 0x73b32078U, 0x3f88a023U, 0x24c5b038U, 0x80000000U, 0x40000000U, 0x60000000U, 0x90000000U, 0x88000000U, 0x84000000U, 0xbe000000U, 0x81000000U, 0x57800000U, 0x73400000U, 0x23e00000U, 0xa4900000U, 0x48a80000U, 0xa5b40000U, 0x819a0000U, 0x7fef0000U, 0x18528000U, 0x540d4000U, 0x78c7a000U, 0xc2a73000U, 0xcc776800U, 0x9cbfec00U, 0x44da2200U, 0x190d8b00U, 0x3544f280U, 0x7ee14840U, 0x21106a20U, 0x10ec1710U, 0x66d41898U, 0x4cb1f64U, 0x8e635282U, 0xc8d67871U, 0x4dcf0217U, 0x3de7fb14U, 0x95943aafU, 0x67299459U, 0x4af52025U, 0x107a7038U, 0x6078c830U, 0x387cdc31U, 0x547f4a1fU, 0xfe79670bU, 0x497e50b3U, 0x1bfa8375U, 0x813bb899U, 0x50982f4aU, 0x806e3aa5U, 0x1f169470U, 0xd1efa001U, 0x5153301fU, 0xe78d6815U, 0x2580ec32U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x70000000U, 0xb8000000U, 0x4c000000U, 0x7e000000U, 0xd1000000U, 0x7c800000U, 0x91c00000U, 0xaba00000U, 0x7f700000U, 0x45880000U, 0x2b940000U, 0x1f9e0000U, 0xf490000U, 0xdfb18000U, 0x82aec000U, 0xad20e000U, 0x75b3b000U, 0xd1ac2800U, 0x66a5f400U, 0x75f23600U, 0x514f5100U, 0xbeb0e180U, 0xe62eb740U, 0xe77e20U, 0x1813d530U, 0x33d81fa8U, 0x21aaa25cU, 0x1ea6018eU, 0x99f00763U, 0x5f4cd617U, 0xd7b5e118U, 0xd6ad4999U, 0xef25836bU, 0x62b5a83bU, 0x302f3408U, 0xf5e4d639U, 0x9e91e106U, 0xf91b499cU, 0x1588836bU, 0x23922833U, 0x4b9cf431U, 0x4d4bb60aU, 0xc8b5912cU, 0x632e0180U, 0x3e640776U, 0x9ed2d62fU, 0x79fce127U, 0xcd9cc980U, 0xb04b4346U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0x28000000U, 0x4c000000U, 0x9e000000U, 0xf1000000U, 0xe5800000U, 0x58c00000U, 0xb5e00000U, 0xcf100000U, 0x71b80000U, 0xc5b40000U, 0xd48e0000U, 0xf67f0000U, 0xdcd08000U, 0xa2dc4000U, 0xe8e7e000U, 0x24913000U, 0x907fa800U, 0x89d73c00U, 0xf55efe00U, 0x8f206b00U, 0xadf3e280U, 0xae292cc0U, 0x8b4e3620U, 0xbb1e2730U, 0x835498U, 0xb7444bd4U, 0xd62202aaU, 0xc4731ce3U, 0x8ef1e1fU, 0x9faa5b18U, 0xb98acaabU, 0x65f950d1U, 0x5911a820U, 0x3cb83c2cU, 0xa6367e1aU, 0x49482b0fU, 0x5c1a02abU, 0x68071ccbU, 0xec011e01U, 0xae055b26U, 0x89024ab2U, 0x818110c7U, 0x8ac04821U, 0xdae20c27U, 0xdb975613U, 0xccfc571bU, 0x28939cb3U, 0xae7a07f8U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x90000000U, 0xa8000000U, 0xa4000000U, 0xc2000000U, 0x77000000U, 0x40800000U, 0xc0400000U, 0xc0a00000U, 0xda700000U, 0xf1e80000U, 0x25140000U, 0x1ffa0000U, 0x846b0000U, 0x92d28000U, 0xbf984000U, 0xcefaa000U, 0xd1e9d000U, 0x1512d800U, 0xc7f8b400U, 0x18696a00U, 0x5cd55900U, 0xae99a580U, 0x3b788040U, 0x26299220U, 0x55777d10U, 0x1d6a37b8U, 0xf354fd64U, 0x5259258aU, 0x659fc079U, 0x85fbb228U, 0x2f6ded29U, 0xfc50cf82U, 0xfeddd97dU, 0x53d8378aU, 0x585bfd52U, 0x6699a584U, 0x4f788050U, 0xac299215U, 0x16777d3aU, 0x37ea378aU, 0xe014fd40U, 0x107925a2U, 0x8afc048U, 0xf433b22eU, 0x1049ed10U, 0xd2e2cf9fU, 0x85d2d94eU, 0x2f18b7acU, 0x46bcbd71U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xb0000000U, 0x48000000U, 0x74000000U, 0x46000000U, 0xff000000U, 0x46800000U, 0xea400000U, 0xdc600000U, 0x2900000U, 0x2b880000U, 0x99340000U, 0xefba0000U, 0xd10b0000U, 0x1738000U, 0x6adf4000U, 0xda1d2000U, 0xce3bf000U, 0xb1cf1800U, 0xad572400U, 0xc9285a00U, 0x44844f00U, 0x5b412280U, 0xf1e3c540U, 0x5853e220U, 0xaaacdb10U, 0x7540c0b8U, 0x6ae01e6cU, 0x40d2a2b2U, 0x33ec854dU, 0x95a6c209U, 0x4f332b03U, 0x48bdd8bbU, 0xfb883a4bU, 0x21337894U, 0x33bc8a72U, 0x53094092U, 0xf0745e5fU, 0xa75c0297U, 0x30d8356fU, 0x71cfa26U, 0x29bbff22U, 0x6e089aadU, 0xa7f45155U, 0x309b8012U, 0x4e7b400dU, 0xb8af2001U, 0xdc44f037U, 0xcb669809U, 0x60136411U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x10000000U, 0x68000000U, 0xcc000000U, 0x7a000000U, 0x9d000000U, 0x58800000U, 0xd3c00000U, 0xe4a00000U, 0xdd300000U, 0x8e80000U, 0x53d40000U, 0x983e0000U, 0x786b0000U, 0x6c128000U, 0xf69a4000U, 0x405de000U, 0x987a1000U, 0xc08cc800U, 0xdbc2f400U, 0xf8a36600U, 0x2f33a900U, 0x49ecc380U, 0x1957e440U, 0x1afece20U, 0xbe4a0d30U, 0xffe40db8U, 0x4252e944U, 0x1d7e43baU, 0xec0da443U, 0x36032e06U, 0x27001d13U, 0x2580c5b4U, 0x9b441d43U, 0x5f63259dU, 0xf5950d53U, 0xafdd6d92U, 0xc63db973U, 0x936beb8bU, 0x3390005aU, 0xf0dde03cU, 0x47ba103eU, 0xbe2cc81eU, 0x8bf2f408U, 0xc0cb6626U, 0x6327a902U, 0x4f72c386U, 0x210ce460U, 0x26844e19U, 0xc8c44d2fU, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0xa8000000U, 0x34000000U, 0x12000000U, 0x37000000U, 0xc6800000U, 0x4c00000U, 0xbae00000U, 0x4e700000U, 0xe2180000U, 0x1dd40000U, 0xb2ca0000U, 0xa9d0000U, 0xb8118000U, 0x63ae4000U, 0x75ab2000U, 0x98ac5000U, 0x8d2a5800U, 0x56f8400U, 0x104cce00U, 0x45e3b00U, 0x89f09180U, 0x3d5ba9c0U, 0x1e763620U, 0xfa1eaf10U, 0xa1d4a788U, 0x64cc06fcU, 0x8799118aU, 0x7d91e9ddU, 0xb3ef162cU, 0xfc8bff21U, 0xaabd7f93U, 0x2584c2f0U, 0x40457fa0U, 0xf120c2c3U, 0x5e177fa5U, 0x26a9c2e7U, 0x542cffb1U, 0x2ea82f1U, 0xaf0e5fbeU, 0xd7fc92e0U, 0x992527beU, 0xa1246ceU, 0xe4aa31b8U, 0x3b29b9e5U, 0x586f4e16U, 0x8dc97b06U, 0x481831b1U, 0x26d0b9c3U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0xc8000000U, 0x94000000U, 0x6a000000U, 0xed000000U, 0x9f800000U, 0x31400000U, 0x21a00000U, 0x4b500000U, 0x2e680000U, 0x13340000U, 0x1f5a0000U, 0x356b0000U, 0x3fb58000U, 0xa69b4000U, 0xef0c2000U, 0xa7809000U, 0x2d408800U, 0x3fa78c00U, 0xbc507200U, 0x94e87900U, 0x29f4dc80U, 0x65bfcc40U, 0xb29b5a20U, 0xc50b2510U, 0xaa8786b8U, 0xc2c0e95cU, 0xc6e6dc92U, 0x9f0cc75U, 0xb5bcda02U, 0xea9f6537U, 0xe90c26adU, 0x9c843975U, 0xd1c5f480U, 0xde67905cU, 0x4a35802eU, 0x3adb403fU, 0xb12c2022U, 0xad90902aU, 0xea888824U, 0xf3c38c21U, 0xe762720aU, 0x5fb77917U, 0x969b5cacU, 0xc70f8c75U, 0x4382fa38U, 0x8f40f523U, 0x46a32e8eU, 0x49d3f56aU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xf0000000U, 0xb8000000U, 0x44000000U, 0x46000000U, 0xf7000000U, 0xa1800000U, 0xc9c00000U, 0x1d200000U, 0xe6100000U, 0x89b80000U, 0x4a740000U, 0xa1ca0000U, 0x4ab90000U, 0x55f18000U, 0x7b0ac000U, 0x401ca000U, 0x35267000U, 0xa175800U, 0x63bf9c00U, 0xf7758600U, 0x4d4fbd00U, 0xd7fd6280U, 0x9196e2c0U, 0x1f7dfe20U, 0x5ad19110U, 0xc4189ca8U, 0x932373fcU, 0xad17628eU, 0x8a3fe2c1U, 0xc2b47e19U, 0x526f5111U, 0x80ee3caeU, 0x4eac03dfU, 0x3d49ba98U, 0x2ffebec5U, 0x75975813U, 0xa97f9c31U, 0x15d58601U, 0x219fbd34U, 0x1ce5628fU, 0x4732e2d9U, 0xcdaffe03U, 0x82cc9112U, 0x53b1cb8U, 0xc734b3e3U, 0x8da84293U, 0x22ce52eaU, 0xf53c0634U, 0x7f317d20U, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0x48000000U, 0xec000000U, 0xaa000000U, 0x69000000U, 0xf6800000U, 0xbec00000U, 0xcce00000U, 0x18700000U, 0x2d580000U, 0x13d40000U, 0x228a0000U, 0x935f0000U, 0x54d58000U, 0xeb0b4000U, 0x201be000U, 0x1d729000U, 0x31df6800U, 0xa4110400U, 0x68e82e00U, 0x7de8bb00U, 0x596d3180U, 0x4aaba3c0U, 0x46cb2620U, 0x6b7b6f10U, 0xf9461798U, 0x10a0ccdcU, 0x45531b2U, 0xa6cfa3ebU, 0x5b792612U, 0xd1406f16U, 0x8ca197b7U, 0xe6508cc8U, 0x23c951abU, 0x7fd73f7U, 0x6822e24U, 0xb6c7bb3dU, 0x40e0b18cU, 0xc274e3eaU, 0xc5ac635U, 0x956ff09U, 0x364cff84U, 0x36ba88ceU, 0xba26ffadU, 0x789588f5U, 0xff2b7fadU, 0x278ac8f6U, 0x8fda9f86U, 0xe31758c4U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x90000000U, 0x78000000U, 0x84000000U, 0xa000000U, 0xfd000000U, 0x40800000U, 0x9c400000U, 0xbee00000U, 0xae900000U, 0xbd480000U, 0xcfb40000U, 0xaefe0000U, 0xdf4f0000U, 0xeb68000U, 0x7ec000U, 0x240fa000U, 0x75d51000U, 0xf62d0800U, 0xb1e5f400U, 0x57121a00U, 0xb8cfb00U, 0x80176280U, 0x860e8740U, 0xd4d03220U, 0xc8a9df30U, 0x32a75098U, 0xa8775864U, 0xf7df62beU, 0xe8fa8751U, 0xe44e323aU, 0xb536df2bU, 0x47b9d096U, 0x4d2d9862U, 0xca66c293U, 0x70d49745U, 0xf2abba05U, 0x47a2eb3fU, 0x84f2ea92U, 0x9d9ab37eU, 0x251b083fU, 0xfd5ef436U, 0x29ba9a07U, 0xea2d3b25U, 0x6fe642b4U, 0xb8115776U, 0xa20c9a3dU, 0x2ed63b08U, 0xddaec298U, 0x8e209757U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0x38000000U, 0xbc000000U, 0x2a000000U, 0xa1000000U, 0x75800000U, 0x14c00000U, 0x31a00000U, 0xdeb00000U, 0xba080000U, 0x21540000U, 0xd35e0000U, 0x860d0000U, 0xcb528000U, 0x525ec000U, 0xe3886000U, 0xe7921000U, 0xdffe2800U, 0x173a9c00U, 0xfc9fbe00U, 0x8b280900U, 0xd0a2cf80U, 0x4b36e340U, 0x9ecd7620U, 0x38f74530U, 0x89efb988U, 0xaa01a644U, 0x6102cfaeU, 0x5586e35fU, 0x4c57622U, 0x9a3451cU, 0x62b1b99bU, 0x900ca66eU, 0x80504fa8U, 0xa6d82340U, 0x92cd1611U, 0xfaf15511U, 0x8cef91a3U, 0x59863a78U, 0xc6c7f1b4U, 0xca42a5cU, 0x9131d99dU, 0x37cab649U, 0xd9706786U, 0x332fbf59U, 0xaca0283bU, 0x41379c03U, 0x2fcd3e30U, 0x7576c901U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0x18000000U, 0xa4000000U, 0x32000000U, 0x75000000U, 0xbb800000U, 0xc2c00000U, 0xa2200000U, 0xe8300000U, 0xfda80000U, 0xd8540000U, 0xa5fe0000U, 0xbdab0000U, 0xf8578000U, 0xf5f9c000U, 0x15aba000U, 0x4456d000U, 0x63ff4800U, 0x52afec00U, 0x8ad36e00U, 0x1abf8500U, 0x324ebb80U, 0xc0c19240U, 0xf260620U, 0x17b07930U, 0xbd68bdb8U, 0x1771eb6cU, 0x524ebba6U, 0xb0c19259U, 0xf7260614U, 0x3b07901U, 0x9768bd90U, 0xc671eb75U, 0xdbcebb82U, 0x701927eU, 0xee860605U, 0x29407907U, 0xc8e0bd91U, 0xf615eb60U, 0x8398bb83U, 0x62fe9275U, 0xb32f8629U, 0x6112b939U, 0x251c9db7U, 0x47bafb49U, 0xf5cc53a4U, 0x7407ae62U, 0x5a03a03dU, 0x2902d01dU, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0xf8000000U, 0x4c000000U, 0xce000000U, 0xad000000U, 0xed800000U, 0x2f400000U, 0xfe600000U, 0xb6900000U, 0x22980000U, 0x829c0000U, 0xd29e0000U, 0x3a9d0000U, 0xfe9e8000U, 0x84994000U, 0xab9b2000U, 0x251d5000U, 0x4ad83800U, 0x767f5400U, 0x11ce2e00U, 0x7ba1dd00U, 0x6d306980U, 0x1fab7d40U, 0x753069a0U, 0x63ab7d50U, 0x233069b8U, 0xf2ab7d4cU, 0xf8b06986U, 0x3ceb7d5fU, 0x255069b5U, 0x83b7d74U, 0x1428698eU, 0x13777d7fU, 0x1a4e69b1U, 0x1de67d52U, 0x14d6e9b9U, 0x217e3d72U, 0x934d498dU, 0xba672d7cU, 0x8c90d1b2U, 0x6d9c695dU, 0x7c1de798U, 0x455fb054U, 0x4a3b980aU, 0x572a4409U, 0x43f5b62eU, 0x508b9907U, 0x78c5dfadU, 0xde20e45cU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x30000000U, 0xc8000000U, 0x1c000000U, 0xba000000U, 0xff000000U, 0x99800000U, 0x1c400000U, 0xeca00000U, 0x8b900000U, 0xd8380000U, 0x703c0000U, 0x1c3e0000U, 0x8e390000U, 0x5d388000U, 0xb6bec000U, 0x49fe2000U, 0x86dbf000U, 0xee0c0800U, 0x4310c400U, 0xa4fc2600U, 0x8c5d4300U, 0xf9cc1f80U, 0x60f45e40U, 0x284c1fa0U, 0x20b45e50U, 0x9eec1f98U, 0x64245e5cU, 0x17541faaU, 0x14585e5bU, 0x5dca1f84U, 0xeef15e64U, 0x414a9fa2U, 0x34339e63U, 0xf82abf99U, 0xb7416e41U, 0x932637afU, 0x32d36a5dU, 0x621a31a8U, 0xb66cd97eU, 0x28e2a63fU, 0x23368313U, 0xedacbf8dU, 0x9046e62U, 0x6480b7aeU, 0x4ec4aa6eU, 0xff64918dU, 0xf675e946U, 0xc58e8e2fU, 0x1c54b726U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xf0000000U, 0x48000000U, 0xe4000000U, 0x9e000000U, 0x8f000000U, 0x52800000U, 0x1400000U, 0xada00000U, 0xc100000U, 0x15a80000U, 0x2dac0000U, 0x41aa0000U, 0x9baf0000U, 0x7aa88000U, 0xef2ac000U, 0x58ede000U, 0x6a091000U, 0x44bd6800U, 0xf87fc00U, 0x36c3f600U, 0xf7609b00U, 0x2175fb80U, 0xd5dad6c0U, 0x6df5fba0U, 0x9b9ad6f0U, 0x32d5fb88U, 0x66cad6ccU, 0xc2ddfb9aU, 0xa376d6f5U, 0x8dffbbdU, 0x9a75d6d6U, 0x615d7ba9U, 0xefb016d6U, 0xeeb81b82U, 0x6683c6d5U, 0xe7409387U, 0x2ea12adeU, 0xd4940d97U, 0x4de94df8U, 0xb98a8009U, 0x8079c003U, 0xade7603fU, 0xa430d029U, 0xb67a0806U, 0x56e72c16U, 0x70b1fe19U, 0x643bb712U, 0x9bc605b6U, 0x88e261c4U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0xe8000000U, 0xb4000000U, 0xb6000000U, 0x31000000U, 0x5e800000U, 0x73400000U, 0x36e00000U, 0x50300000U, 0xf4d80000U, 0xb0dc0000U, 0x9eda0000U, 0x43df0000U, 0xe75f8000U, 0x4f18c000U, 0x147d6000U, 0xee88d000U, 0x30715800U, 0xcbbfac00U, 0xb42e3600U, 0xd5248100U, 0xb8978080U, 0x6e89e640U, 0xf07780a0U, 0x6bb9e670U, 0xa42f8088U, 0x3d25e674U, 0xc9580b2U, 0xd88ae659U, 0xc172009fU, 0x353e2655U, 0xd76d6088U, 0xbc5f649U, 0x5ca1b885U, 0x2c519a5dU, 0x71af6eb8U, 0xabe60b71U, 0x94b1561fU, 0xec9f5121U, 0x13bb5886U, 0x382d8a42U, 0x9f21568bU, 0x9b92774dU, 0x5f0bb815U, 0x58b3bc16U, 0xc6980e0fU, 0x80bcfd32U, 0xf1af6eb3U, 0x6be60b7dU, 0x80000000U, 0x40000000U, 0x60000000U, 0xd0000000U, 0x58000000U, 0xf4000000U, 0x52000000U, 0xe7000000U, 0xba800000U, 0xadc00000U, 0x31600000U, 0x39300000U, 0xa8880000U, 0xaa8c0000U, 0x558e0000U, 0x7b0d0000U, 0x54cb8000U, 0xdaa94000U, 0xad1ee000U, 0xfa547000U, 0x86bf4800U, 0x50849c00U, 0x2ec4f200U, 0xe1e2f900U, 0x57f47080U, 0x296ad4c0U, 0x2d7c70a0U, 0x24e6d4d0U, 0xa27270b8U, 0x222bd4e4U, 0x9fd9f0aeU, 0x35b294d9U, 0xc84f10baU, 0x826ae4e0U, 0xa1fe5894U, 0x42378cbU, 0xea912a98U, 0x658c1c5U, 0xb8f3ba32U, 0x7fea652fU, 0x46be8287U, 0x70852de1U, 0x9ec3802aU, 0x69e54033U, 0xfbf0e02fU, 0x8f697014U, 0x987cc814U, 0x7961dc30U, 0xb5341233U, 0xbe8b8927U, 0x9788b890U, 0xa40b08f1U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0x28000000U, 0xcc000000U, 0x86000000U, 0x35000000U, 0xf1800000U, 0x17c00000U, 0xf2e00000U, 0xf700000U, 0xb0a80000U, 0x26ac0000U, 0xabaa0000U, 0xee2d0000U, 0x2be88000U, 0x8e09c000U, 0xfffa000U, 0xea139000U, 0xed1e3800U, 0x5d63b400U, 0xe9b60a00U, 0xa9cd1d00U, 0x151aa680U, 0xc96383c0U, 0x6bb2a6a0U, 0x66cf83f0U, 0x7f98a698U, 0xd62283dcU, 0xf9102692U, 0xb99b43efU, 0xc32786b3U, 0x5894d3e2U, 0x365bbe8fU, 0xd5c667e7U, 0x1de734b3U, 0x35f3bae4U, 0x37e8b21fU, 0x500b692dU, 0x3ef90c95U, 0xe1900ee6U, 0x61deb807U, 0xa7067419U, 0x8683aa16U, 0xc9438d0cU, 0x3fa41ebeU, 0xcad5f7c9U, 0xe1790cb3U, 0xcf500ee8U, 0x4beb82fU, 0x3ab6743dU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x50000000U, 0x28000000U, 0xe4000000U, 0x5a000000U, 0xeb000000U, 0x44800000U, 0xc6400000U, 0x85a00000U, 0x67d00000U, 0x30a80000U, 0x2eac0000U, 0xefaa0000U, 0xd82d0000U, 0xc6ef8000U, 0x130ec000U, 0xa479e000U, 0x6833000U, 0x71406800U, 0xb7244c00U, 0xa4957e00U, 0x688bd300U, 0xc4bdad80U, 0x826508c0U, 0x39b5ada0U, 0xbf1908f0U, 0x74b7ad98U, 0x169808e4U, 0x6b722d92U, 0x14fbc8ddU, 0x92c44d84U, 0x4be638e7U, 0xb675c595U, 0x757d44d6U, 0x3902d3b4U, 0x3b83dbcfU, 0x40c78038U, 0x34e2c004U, 0x30f3e023U, 0xc43e3002U, 0x6e27e82aU, 0xcf168c12U, 0x4e9e09U, 0x1459e32aU, 0xe8904583U, 0x168e84fdU, 0x95bcb39bU, 0x7de22be6U, 0x93740833U, 0x18f8bc0bU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x30000000U, 0xc8000000U, 0xdc000000U, 0xce000000U, 0xb1000000U, 0x28800000U, 0xd7400000U, 0x8fe00000U, 0x8f00000U, 0xef380000U, 0x853c0000U, 0x2e3a0000U, 0x5bf0000U, 0xb57e8000U, 0xbc58c000U, 0x188e2000U, 0x69e05000U, 0x35f1d800U, 0x51be9c00U, 0xc7792600U, 0x535ad900U, 0x7909de80U, 0x8221c740U, 0x7f51dea0U, 0xa9adc770U, 0xb933de88U, 0xc69ec77cU, 0x8aaf5ebaU, 0x2eb5074bU, 0x285dfe89U, 0xca8e9767U, 0xb6e68683U, 0x9c779b52U, 0x667ed8a0U, 0x43db4e50U, 0x1a49d81bU, 0x2fc29c31U, 0xc0a32630U, 0x315d900U, 0xdcf5eb5U, 0x1050763U, 0x2085fea1U, 0xab42977eU, 0x71e486b7U, 0x71f49b4aU, 0x1bba58beU, 0x9c7c8e5cU, 0x10d97830U, 0x25ca0c12U, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0xa8000000U, 0xa4000000U, 0x86000000U, 0x83000000U, 0x7e800000U, 0x6bc00000U, 0x9ea00000U, 0xc6d00000U, 0x6b280000U, 0x512c0000U, 0x682e0000U, 0x6fad0000U, 0x63ed8000U, 0xe108c000U, 0xd3de000U, 0x2e21d000U, 0xda11c800U, 0xc5083c00U, 0xcb3c6200U, 0xcd221700U, 0xb4966180U, 0x6ca98c0U, 0xf19e61a0U, 0x8df698d0U, 0x5cb861b8U, 0x296798d4U, 0xf273e192U, 0x7cfe58fdU, 0xf98581b3U, 0xa34648ddU, 0xae6229acU, 0x3af664c7U, 0x4c39e38bU, 0x5a45ff6U, 0x84544811U, 0xfaecfc22U, 0xd68f822bU, 0xd97ec729U, 0xb0c229abU, 0xbc2664d5U, 0x4711e3a2U, 0x44885fe7U, 0x447a482dU, 0x3141fc32U, 0x3362020aU, 0xbb760722U, 0xc37fc9b9U, 0xf9c7b4f6U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0xa8000000U, 0x1c000000U, 0x9a000000U, 0xdd000000U, 0x80800000U, 0xa5c00000U, 0x8e00000U, 0xb8500000U, 0x4d880000U, 0xb88c0000U, 0xe40a0000U, 0xfbcb0000U, 0x3e2b8000U, 0xaefec000U, 0x5ab62000U, 0x70def000U, 0xf1821800U, 0xc7451c00U, 0xe427b200U, 0xa6333500U, 0xbf1bd780U, 0xbc64cbc0U, 0x5b91d7a0U, 0x226fcbf0U, 0x4d5a57a8U, 0x24c10bf4U, 0xf2647782U, 0xf093fbf3U, 0x7dec6fa4U, 0x111de7c4U, 0x27605d84U, 0xbc1012edU, 0xca2daa06U, 0xc8fa2903U, 0x2db665b5U, 0x955cfeddU, 0x60c18024U, 0xec65c017U, 0x1395a029U, 0xe6c300fU, 0x6f5e383bU, 0x4dc0ec27U, 0xf4e62a2bU, 0x1254e90fU, 0x28884596U, 0x8c0e0ed6U, 0xc7c99828U, 0xb42bdc20U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x30000000U, 0x18000000U, 0x5c000000U, 0x5a000000U, 0x6b000000U, 0x95800000U, 0xb8c00000U, 0x7ea00000U, 0x300000U, 0x62e80000U, 0xd5ec0000U, 0xda6a0000U, 0xa9af0000U, 0x728e8000U, 0xd27e4000U, 0x9234a000U, 0x1dea7000U, 0xce6b2800U, 0x27ac8400U, 0x378dc200U, 0x32ff7700U, 0xd2755680U, 0x7f0a71c0U, 0xf6bf56a0U, 0x169571f0U, 0x46d9d688U, 0x210731fcU, 0x1687768eU, 0xc94241ebU, 0xf062de98U, 0x579085f1U, 0xc05bbcbdU, 0xc04582dfU, 0xa2e5c222U, 0x98d3771fU, 0x13f569aU, 0x695571daU, 0x4ff9d6a4U, 0x9ef731ccU, 0xdd4f7696U, 0x935e41e3U, 0xf9c0dea2U, 0xf82385e9U, 0xe1773ca2U, 0xd688c2d4U, 0x847de215U, 0x2b344736U, 0x976c5e86U, 0xfd2ec5ecU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x10000000U, 0x18000000U, 0x94000000U, 0xda000000U, 0x25000000U, 0x79800000U, 0xf5c00000U, 0x98a00000U, 0x69b00000U, 0x78e80000U, 0xf1ec0000U, 0x966e0000U, 0x24ab0000U, 0x648b8000U, 0x437b4000U, 0xe7f7e000U, 0x448d3000U, 0x137a1800U, 0x5ff6d400U, 0xc088fa00U, 0xd17a7f00U, 0xeef25280U, 0x630a65c0U, 0x1bc52a0U, 0xfd165d0U, 0xff7fd288U, 0xe1f625d4U, 0x978e328eU, 0x11fc15f1U, 0x34b1aab8U, 0x656a81f8U, 0x762d30a6U, 0xb7ca8ec5U, 0x629c9a00U, 0x82a00f1fU, 0xacb1aabeU, 0xb16a81f3U, 0xc2d3093U, 0x82ca8eeeU, 0x31c9a24U, 0xe3600f1fU, 0xee11aa8dU, 0xfdda81f2U, 0xd4530a9U, 0x86e68ec5U, 0xdd29a0fU, 0xae7b0f37U, 0xf2722a9cU, 0x4f4dc1f5U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0xf8000000U, 0x1c000000U, 0xa000000U, 0xc1000000U, 0xc6800000U, 0xd8c00000U, 0xbae00000U, 0xd6b00000U, 0xe8880000U, 0xfd8c0000U, 0x650e0000U, 0x62cb0000U, 0x61a98000U, 0x865e4000U, 0x1d76a000U, 0x59eaf000U, 0x677af800U, 0x62a3cc00U, 0xc7968a00U, 0x3f5c1d00U, 0x87f48880U, 0x2b2ffcc0U, 0x4c9a88a0U, 0x8a94fcd0U, 0xebdb0888U, 0x7236bcc4U, 0xf54ba8b6U, 0x67eb4cc3U, 0x87ed0b4U, 0xd321c0f3U, 0x42d17a85U, 0xa2fe6dc5U, 0xe9e62a2bU, 0x7d31ed30U, 0xf4c9f0b1U, 0xeaa970dfU, 0x21db22a0U, 0x533051c3U, 0xc3cdd82eU, 0x172b7c31U, 0x569cd235U, 0x13922100U, 0x615f7ab7U, 0x58f56dcaU, 0x92afaa07U, 0x7ddfad11U, 0xf93750b8U, 0x52cf80e5U, 0x80000000U, 0x40000000U, 0x20000000U, 0x10000000U, 0x88000000U, 0xec000000U, 0xc2000000U, 0xe9000000U, 0xc2800000U, 0x95400000U, 0x7ea00000U, 0x65f00000U, 0xf180000U, 0xa41c0000U, 0xcf9e0000U, 0xb85f0000U, 0x43bf8000U, 0xd0ebc000U, 0x5604a000U, 0x3f06b000U, 0xbd83f800U, 0x8c4ec00U, 0x6660c600U, 0x8b977300U, 0x688b3c80U, 0xe915440U, 0x280d3ca0U, 0x52d25450U, 0x842cbca8U, 0x2a669454U, 0x19979c8aU, 0x298be46fU, 0x3010c4baU, 0xf749b855U, 0x2973fa8aU, 0xe15a2770U, 0x59380015U, 0x1ac0029U, 0x16a60036U, 0xf9f30010U, 0x7519800dU, 0x3918c03aU, 0xab1d203fU, 0xea1e7035U, 0xd49ed81aU, 0xbda9c00U, 0x707e1e05U, 0x150def27U, 0x66552283U, 0x7e6cbb5cU, 0x41401e3aU, 0x88a2ef26U, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0x38000000U, 0xa4000000U, 0xd6000000U, 0x35000000U, 0x37800000U, 0x1f400000U, 0xbd200000U, 0x78100000U, 0xeef80000U, 0xf5fc0000U, 0x337e0000U, 0x5dbf0000U, 0x42da8000U, 0x2c6b4000U, 0xd7c66000U, 0x92e4d000U, 0x2ef77800U, 0x860fc400U, 0xcef6be00U, 0x560c9700U, 0x66f57780U, 0x7a0e3040U, 0x2cf377a0U, 0x3d0d3050U, 0xf877f7a8U, 0x20c9707cU, 0x6d9317a6U, 0xfabae055U, 0x465c0f93U, 0x99aef458U, 0x6e27499eU, 0x296e75fU, 0x423ae031U, 0x319c9001U, 0xfb4d982aU, 0x58d3542cU, 0x909b262eU, 0x62cfc317U, 0xf69651b0U, 0x7c3df375U, 0x89b2610U, 0x36cfc30cU, 0x389651beU, 0x5d3df356U, 0xd11b2604U, 0xb88fc308U, 0x643651b5U, 0xf6df373U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x30000000U, 0xf8000000U, 0x74000000U, 0xea000000U, 0x3000000U, 0xb6800000U, 0xf2c00000U, 0x8e600000U, 0x84b00000U, 0xb8c80000U, 0x19cc0000U, 0xe04a0000U, 0x5a090000U, 0xffa88000U, 0xb8ff4000U, 0xb4c4e000U, 0x8367b000U, 0x7331a800U, 0x438f1c00U, 0xb5ed0a00U, 0x8558b900U, 0xb7943c80U, 0x9d5b2ac0U, 0x33963ca0U, 0xef5e2af0U, 0x7494bcb8U, 0x4bd86afcU, 0xf150dc86U, 0x993c9ae1U, 0x842794bcU, 0x191136e1U, 0xeb99b691U, 0xcff0d3ddU, 0x2cece032U, 0x68dbb03cU, 0xd7d3a83cU, 0xc3fa1c0aU, 0xb6478a1cU, 0xfba2f910U, 0xce525c9dU, 0x89badae3U, 0x8be3f4aaU, 0xf8f5c6f3U, 0xd06efe83U, 0xc91d7fd3U, 0x2732c233U, 0x398a550eU, 0x1eeefeaaU, 0x8fdd7fdfU, 0x80000000U, 0x40000000U, 0x20000000U, 0xd0000000U, 0xb8000000U, 0xc000000U, 0x2000000U, 0xa7000000U, 0xed800000U, 0x9fc00000U, 0xe2600000U, 0xf0100000U, 0x60480000U, 0x694c0000U, 0xb1ce0000U, 0xfc8f0000U, 0xb0a98000U, 0x871c4000U, 0x5e242000U, 0x48b03000U, 0xc8bf0800U, 0xe3556400U, 0x71691a00U, 0x387cc900U, 0xc8b6a980U, 0x88bbfbc0U, 0xc350a9a0U, 0xa168fbd0U, 0x807f29a8U, 0xc4b7bbe4U, 0x8abc8986U, 0x6454cbe7U, 0x4cee2186U, 0x1fbddfceU, 0x26d413bdU, 0x7aa842e9U, 0x41aa805U, 0x25a51415U, 0xae74323dU, 0xda5a9d1fU, 0xca073b99U, 0x830116d4U, 0x7b82ba3bU, 0xe6c3b926U, 0x12e20184U, 0x2951eff9U, 0xf26d1b8bU, 0x43fe26c1U, 0x2e743209U, 0x9a5a9d2dU, 0xea073b96U, 0x530116c8U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x30000000U, 0x28000000U, 0xbc000000U, 0x82000000U, 0x7b000000U, 0x89800000U, 0xc3c00000U, 0xbe00000U, 0x7700000U, 0xed380000U, 0xf83c0000U, 0x70be0000U, 0x45fb0000U, 0x225a8000U, 0x800bc000U, 0xad262000U, 0xc163000U, 0x530fe800U, 0xd8a2a400U, 0xedd33a00U, 0x13ed2500U, 0x7e507e80U, 0x7f2dc740U, 0x62367ea0U, 0x729ac750U, 0x5e6afe88U, 0x7b96075cU, 0x89c85e82U, 0xb1c0f773U, 0xb8e316a2U, 0xa2f3a36dU, 0xb4ffe480U, 0x1cdd125dU, 0xc04fc802U, 0x9203941cU, 0x23005219U, 0xbd834132U, 0xcdc1e4adU, 0xdae6126fU, 0x49f5480fU, 0x25785430U, 0x4b1e720cU, 0xf5a97131U, 0x6c700c98U, 0x3cbfb654U, 0xffcf22bU, 0x755eb130U, 0x93882c85U, 0x81e28663U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xf0000000U, 0x68000000U, 0x84000000U, 0xba000000U, 0xed000000U, 0xe9800000U, 0x6bc00000U, 0x58200000U, 0xfad00000U, 0x7e180000U, 0x379c0000U, 0x6c5a0000U, 0x7c7b0000U, 0xf2ac8000U, 0x5eb7c000U, 0x2fe000U, 0x3ff03000U, 0xc54c5800U, 0x86479400U, 0x49e30a00U, 0x6ff62b00U, 0x9d4dcd80U, 0x4a406540U, 0x87e14da0U, 0x50f7a570U, 0x1dceada8U, 0x7207954cU, 0x5902f5b2U, 0x1b80016dU, 0xf2c1ff9cU, 0x63a62a56U, 0xf8143226U, 0x75ba4f0cU, 0x4b8f7f90U, 0xa3e6ea42U, 0xdaf55227U, 0xb8cabf03U, 0xef82478eU, 0xe0c18e71U, 0x2aa3602eU, 0x5b97f030U, 0x9b7bb808U, 0x7e2ba433U, 0x88f55229U, 0x11cabf10U, 0x9c0247bcU, 0x96018e78U, 0xf303603dU, 0x4e87f017U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0x98000000U, 0x1c000000U, 0xca000000U, 0xe7000000U, 0x4d800000U, 0xb8400000U, 0xaca00000U, 0xd0f00000U, 0x40180000U, 0xfd9c0000U, 0xadda0000U, 0x357f0000U, 0xbb8f8000U, 0x52934000U, 0xd38fa000U, 0xa693f000U, 0x2d8bc800U, 0x1f962400U, 0xc908a600U, 0xdb566300U, 0xbd6d1480U, 0xb5c5dc40U, 0x74e294a0U, 0xcc569c70U, 0x18ed3488U, 0x39856c74U, 0x8646fcaeU, 0xb5a34873U, 0x24765a9cU, 0x1cd92b4aU, 0x95f94e0fU, 0x94ff724U, 0x1bf65a84U, 0x8f992b60U, 0x86d94e1cU, 0x8afff72bU, 0xe8ce5a99U, 0xe1b52b55U, 0x403b4e2bU, 0xcdacf70bU, 0x5fa3da90U, 0x13756b46U, 0x69596e3fU, 0x21bf4711U, 0xf7ea32b9U, 0x3000ff48U, 0x48002009U, 0x2400b007U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0x78000000U, 0xc4000000U, 0x5a000000U, 0xa3000000U, 0xd8800000U, 0xbf400000U, 0xfde00000U, 0xc900000U, 0x50e80000U, 0x146c0000U, 0xe52e0000U, 0x39cb0000U, 0x1adf8000U, 0xff44000U, 0x3e3e6000U, 0xa8e2b000U, 0xd114a800U, 0xaa29ec00U, 0xe74a5600U, 0xa89ed900U, 0x3b948d80U, 0x4a6f62c0U, 0xfc2b0da0U, 0x724b22d0U, 0x951d6d88U, 0xf15592f4U, 0x514fc596U, 0xd9b7ec5U, 0xee141380U, 0x3caae7edU, 0x79097e36U, 0x7aff7502U, 0x72c6bba9U, 0x3f240bd1U, 0x9bb2a835U, 0xd75eec20U, 0xcd33d61aU, 0xa91d992bU, 0x2f536dbcU, 0x84e92d5U, 0xe61845adU, 0xf1d33ed9U, 0xba0c73aeU, 0xd27f57d3U, 0x85845614U, 0xeec5d921U, 0x71230dbeU, 0xbab722c3U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x90000000U, 0x98000000U, 0xa4000000U, 0x3e000000U, 0x59000000U, 0x2e800000U, 0x9bc00000U, 0xd200000U, 0x2e900000U, 0x89c80000U, 0x394c0000U, 0x4b8a0000U, 0x802d0000U, 0x99798000U, 0x1f954000U, 0xcb4c6000U, 0x408f9000U, 0x15ac5800U, 0x7f3eac00U, 0x58f23200U, 0xa0bfbb00U, 0x61b01f80U, 0x445a69c0U, 0x89019fa0U, 0x968329f0U, 0x4fc7ff98U, 0x3b21b9d4U, 0x4b9227beU, 0x3d4a55fdU, 0xc58c75b1U, 0x312a7eebU, 0x1bf8323aU, 0x8652bb0dU, 0x5699f99U, 0x279f29f6U, 0x7025ffa3U, 0xfe10b9ecU, 0xab09a7afU, 0x8aee15c1U, 0x66db95a0U, 0xa0c1aef9U, 0xb0a38a16U, 0x84d7c719U, 0x5ca815bbU, 0x9b9eedbU, 0x87366a14U, 0x39d1722U, 0x8e202d82U, 0x4714d2e0U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x10000000U, 0x58000000U, 0xb4000000U, 0xfe000000U, 0x55000000U, 0xc2800000U, 0x6dc00000U, 0x67a00000U, 0x1dd00000U, 0xf8e80000U, 0xf46c0000U, 0xc4ae0000U, 0x2d8b0000U, 0x79b8000U, 0x6bd14000U, 0xa1e8e000U, 0xcce91000U, 0x4a6cb800U, 0x31af2c00U, 0xff0e0200U, 0x325a5f00U, 0xb870e180U, 0x423e7ec0U, 0x610361a0U, 0x7c833ed0U, 0x98c58188U, 0xb5212ed4U, 0x2812b99eU, 0x2b4f42f9U, 0x17bc5ba1U, 0x69400decU, 0x1b660211U, 0xaef65f37U, 0x21fee1a8U, 0xbba57ee0U, 0x5fd0e19eU, 0x1fee7ec9U, 0x39eb6191U, 0x98ef3eebU, 0x46b81b9U, 0x2caa2ec9U, 0xd189399eU, 0x159e02f4U, 0x74d4bba5U, 0xc8691de4U, 0x36aaba3dU, 0x82897312U, 0x2618e3bcU, 0x7d9321e4U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xf0000000U, 0x68000000U, 0xa4000000U, 0x2000000U, 0xcf000000U, 0xd9800000U, 0x92400000U, 0x26e00000U, 0x6bd00000U, 0x55880000U, 0x360c0000U, 0xf74a0000U, 0x56290000U, 0x5ebe8000U, 0xf555c000U, 0x8a4ce000U, 0x88aef000U, 0x217d8800U, 0xdbf7c400U, 0xc47b9600U, 0xc976c100U, 0x1db9af80U, 0x2ad3ebc0U, 0x450f2fa0U, 0x20ca2bf0U, 0xcd69cfb8U, 0x9cdddbccU, 0x7242c7a2U, 0x16e3dfe5U, 0x63d7b1a2U, 0x18eeed6U, 0x5c0f1614U, 0x9c4a0132U, 0x8dabcfbdU, 0x3f8dbd8U, 0xa364790U, 0x73df1fd9U, 0xfbc5d1afU, 0x7ca5ded9U, 0x79367e22U, 0xa45f353eU, 0x6087d196U, 0xbec0defbU, 0xfe22fe19U, 0x38f3f53fU, 0x8bfdb196U, 0x9e37eeffU, 0x79d9961bU, 0x60c3c13bU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x30000000U, 0x68000000U, 0xc4000000U, 0x2a000000U, 0x1f000000U, 0x62800000U, 0xc7c00000U, 0xb0600000U, 0xb8f00000U, 0xdee80000U, 0x126c0000U, 0x40aa0000U, 0xdd490000U, 0x98f88000U, 0x9db3c000U, 0x6949e000U, 0x7afab000U, 0x16b74800U, 0x79cadc00U, 0xe3c2200U, 0x2a51c100U, 0x33fdf680U, 0x1d3269c0U, 0x258d76a0U, 0xda1da9f0U, 0xda8696b8U, 0x9bc219fcU, 0x56635ea2U, 0x79f205cdU, 0xe16e1ca8U, 0x6c2ab4caU, 0x7f8d4230U, 0xd18b13bU, 0x2c035ebcU, 0x2e0205e5U, 0x55061cb3U, 0x4d86b4ddU, 0xcd474221U, 0xb3a1b117U, 0x2293deb7U, 0x791dc5f6U, 0xae05fc87U, 0x950504e2U, 0x2d808a34U, 0xfd44ad1eU, 0xdba41c9cU, 0xe693b4f8U, 0x531dc21dU, 0xb1077106U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0x38000000U, 0xac000000U, 0x12000000U, 0x8d000000U, 0x42800000U, 0x90c00000U, 0x84600000U, 0x5d00000U, 0x1de80000U, 0x596c0000U, 0x3aaa0000U, 0x434b0000U, 0x29da8000U, 0x5a134000U, 0xbe0a2000U, 0xaf8b000U, 0x85e3d800U, 0x90954c00U, 0x7acf8a00U, 0x109a0900U, 0x2f305780U, 0x7af880c0U, 0x5de2d7a0U, 0x2c97c0f0U, 0x60caf7a8U, 0x99870fcU, 0xd3b1afa6U, 0x75397cd7U, 0x160485a2U, 0xfb0385f4U, 0x6987aa32U, 0xd145b910U, 0xf1230fb3U, 0x72f58ce1U, 0x5c1dfd9cU, 0xd8f639cbU, 0xbd1b5814U, 0xa8710c3cU, 0x90dd2a34U, 0x5696f912U, 0xa9c92f87U, 0xdd1d3cdbU, 0x787625b9U, 0xb8df75c1U, 0xf296d20dU, 0x2fcc053dU, 0xee1dfdb1U, 0xa5f639daU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x10000000U, 0x78000000U, 0xcc000000U, 0x2e000000U, 0xd5000000U, 0xbe800000U, 0xd4c00000U, 0x57600000U, 0x8d500000U, 0x6ad80000U, 0x1e5c0000U, 0xa59a0000U, 0x8b7d0000U, 0xff6d8000U, 0xc9964000U, 0x85bc2000U, 0xbf0f5000U, 0xf140f800U, 0x38268c00U, 0x28756a00U, 0xb82d7100U, 0xf8b28b80U, 0x454fc540U, 0xcae70ba0U, 0xce158570U, 0xf1f92b98U, 0x61abd574U, 0x31f65386U, 0x916a1947U, 0x3c90998dU, 0xcb3f7872U, 0x3c94a22U, 0x12222107U, 0x57727397U, 0xb9a94954U, 0xcdf26195U, 0x3768f467U, 0x4d93a01aU, 0xefb81032U, 0xe00b5810U, 0xc29c36U, 0x6564322dU, 0xee52ed1dU, 0xdd5b39b5U, 0x221b6876U, 0x3f38121bU, 0xc1cdbd39U, 0x1923c1a1U, 0x54f1e44cU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x90000000U, 0xc8000000U, 0x8c000000U, 0x86000000U, 0x8d000000U, 0x11800000U, 0x66400000U, 0xb1e00000U, 0x16d00000U, 0x33680000U, 0x63ec0000U, 0xf22a0000U, 0x988f0000U, 0x763b8000U, 0x71c5c000U, 0x9aa5a000U, 0x16b79000U, 0xd3fef800U, 0x2966f400U, 0xb118600U, 0xdfcb6900U, 0x5a6f80U, 0xe4535cc0U, 0x15abefa0U, 0x4bc99cf0U, 0xa25dcf88U, 0x5357ccd4U, 0x572c97baU, 0xf509a8f7U, 0x6e78699bU, 0x9921f5d4U, 0x5ff6201fU, 0xc49e500dU, 0x1b715813U, 0x375e6438U, 0x66d4fe37U, 0xb685d04U, 0x17ee49b9U, 0xa02fa5c1U, 0xd78f7825U, 0xe0bc340eU, 0xd07a60fU, 0xd1853906U, 0xc643378dU, 0x21e138ceU, 0xded511b0U, 0xbf6ec1d1U, 0xe5e80601U, 0x7f2da910U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xb0000000U, 0x78000000U, 0x84000000U, 0x36000000U, 0xb5000000U, 0x2e800000U, 0x15c00000U, 0xdc200000U, 0xdb700000U, 0x2a480000U, 0x5cc0000U, 0xb08a0000U, 0x28690000U, 0x87bc8000U, 0xae474000U, 0xf7676000U, 0xba90d000U, 0x611e7800U, 0x3ef68c00U, 0x980fe200U, 0x30ac2300U, 0x911bc880U, 0xe6f272c0U, 0xcc0d48a0U, 0xceac32f0U, 0xd81ea8b8U, 0x7a77a2dcU, 0x5acdb0a6U, 0x8908fefdU, 0x3828aaabU, 0x99d911d0U, 0x5851e020U, 0xc8be9015U, 0x3fc59837U, 0xab211c13U, 0x6ef6fa25U, 0x900a7f3eU, 0xacaa5297U, 0x9318ddd5U, 0x1df1621bU, 0xd38e6323U, 0xc3ea2895U, 0xa4fce2d4U, 0x53a0d09cU, 0xbe312ed0U, 0x7aaa52bbU, 0x5618ddfdU, 0x2b71622bU, 0xf24e6307U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x30000000U, 0xc8000000U, 0xfc000000U, 0xde000000U, 0x89000000U, 0xa0800000U, 0xccc00000U, 0x58200000U, 0x60b00000U, 0xe3380000U, 0x1ebc0000U, 0xfa0000U, 0x9b1f0000U, 0x8e0e8000U, 0x8bc0c000U, 0x49a32000U, 0x98f3d000U, 0x65da9800U, 0xb92a1c00U, 0x56f43a00U, 0xd4d81b00U, 0x8dae6e80U, 0x88307f40U, 0x13faeea0U, 0x389fbf70U, 0xd94f4e88U, 0x10a0af7cU, 0xa074f6baU, 0xd1a6343U, 0x3b0ed48dU, 0x5547a461U, 0x3c612025U, 0xa850d012U, 0x35ae1813U, 0xdc35dc3aU, 0xa1f99a03U, 0x979b0b31U, 0xc4cfd6b1U, 0x5ee5b368U, 0x63964c85U, 0x1c0eb858U, 0xd4c19a17U, 0x3c270b01U, 0x1ab5d68aU, 0xb03ab378U, 0xdd38cc98U, 0xc7be7854U, 0xf87aba09U, 0x53d8db10U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0x28000000U, 0xe4000000U, 0xc6000000U, 0x3b000000U, 0xcd800000U, 0xbd400000U, 0xab600000U, 0xf7100000U, 0x73780000U, 0xe3fc0000U, 0x783a0000U, 0xab9b0000U, 0xbeab8000U, 0x7fa2c000U, 0xc731e000U, 0x2409d000U, 0x92150800U, 0x99f9e400U, 0xb93e4e00U, 0x671bb500U, 0xef6afd80U, 0x95065e40U, 0xf2837da0U, 0x86c39e70U, 0x15231da8U, 0x5df38e74U, 0x1b2c75a2U, 0xc6e17a4dU, 0x9a56d393U, 0xd01afb43U, 0xe0ef6820U, 0xe542f42cU, 0x9762a62aU, 0xcd178121U, 0x527bbbbeU, 0x1f7f0f5dU, 0x11fc4e0aU, 0x8d3cb53eU, 0xa91b7dbcU, 0x206f9e5bU, 0xb6811d9cU, 0x90c48e70U, 0x2625f5a1U, 0x6474ba58U, 0x486eb39bU, 0xb286eb61U, 0x66c20016U, 0x25270032U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xb0000000U, 0x58000000U, 0x54000000U, 0x32000000U, 0x93000000U, 0x77800000U, 0x71c00000U, 0x58a00000U, 0x3b900000U, 0xe0380000U, 0x6bc0000U, 0xbfa0000U, 0xa11f0000U, 0x31ea8000U, 0x79e04000U, 0x8776e000U, 0x29c97000U, 0x4e34e800U, 0x9928d400U, 0xe1c69a00U, 0x70a47f00U, 0x97907380U, 0x363b0a40U, 0xffb8f3a0U, 0xbb784a70U, 0x955e9388U, 0x8b8e7a5cU, 0x6d561b9eU, 0x2d1f9e49U, 0x97ea8992U, 0x78e6456dU, 0xd3f2880fU, 0x778ee431U, 0x33561239U, 0xc8199b0fU, 0xa96ee1a9U, 0xe1a1d162U, 0xeb10721dU, 0xc47fab2fU, 0x54de6995U, 0x134c3549U, 0x6d76e037U, 0x2ec97016U, 0xabb4e820U, 0xcbe8d413U, 0x96e69a0fU, 0x6ef47f0fU, 0x1d0873b9U, 0x98170a49U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xf0000000U, 0x28000000U, 0xd4000000U, 0xb6000000U, 0xcd000000U, 0xaa800000U, 0xfc00000U, 0x5a600000U, 0x61d00000U, 0xdef80000U, 0x977c0000U, 0xa33a0000U, 0xae190000U, 0x396e8000U, 0x47a7c000U, 0xa8b56000U, 0x6caed000U, 0xaac7b800U, 0x84e76c00U, 0x48135200U, 0x919ba100U, 0xa02fdf80U, 0x1006a040U, 0x18035fa0U, 0x9c046070U, 0x9202bfb8U, 0x5304704cU, 0xb386e7b2U, 0x13460c79U, 0x98a56d9fU, 0x9131114aU, 0xb0ead835U, 0x13e5bc09U, 0x5596ea03U, 0xd3d9cd21U, 0x80dacU, 0xddf3c178U, 0x410f602eU, 0xfd77d016U, 0x81c93835U, 0x8690ac38U, 0xa05e3227U, 0x73497129U, 0xb55267bcU, 0xf838cc56U, 0x999e8dbeU, 0x24280157U, 0x1e00001aU, 0xd900001fU, 0x80000000U, 0x40000000U, 0xe0000000U, 0xf0000000U, 0x58000000U, 0x54000000U, 0xc6000000U, 0x4f000000U, 0x1f800000U, 0x94400000U, 0xfae00000U, 0xe2d00000U, 0xa4b80000U, 0xe63c0000U, 0xa4fe0000U, 0x7ad90000U, 0x192e8000U, 0x69e44000U, 0x6752e000U, 0xa5fed000U, 0x765fa800U, 0x48ead400U, 0x7243b600U, 0xe5e54100U, 0xb554a780U, 0xccfe5a40U, 0xd6dc27a0U, 0x9b2f1a50U, 0x48e64798U, 0x3bd08a6cU, 0xbc3b8f8eU, 0x91f9ce79U, 0x5bf1bfU, 0xbfeccb6aU, 0xc9c1a838U, 0xefa3d40fU, 0x54b53626U, 0xf7ad0127U, 0xa92047b7U, 0x98758a62U, 0x9a8b0fa8U, 0x1f548e79U, 0xa1ff91a7U, 0xf85a5b4cU, 0xfbeae02fU, 0xa7c2d015U, 0xaca1a81dU, 0xd933d43cU, 0xeaed3617U, 0x3410125U, 0xf16647bbU, 0x50908a65U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x10000000U, 0x48000000U, 0x54000000U, 0x5a000000U, 0xaf000000U, 0xe2800000U, 0x6cc00000U, 0xe7e00000U, 0xa5900000U, 0xd9780000U, 0xcafc0000U, 0x59ba0000U, 0xbb190000U, 0x75298000U, 0x31e3c000U, 0x8c956000U, 0xfaf9b000U, 0xa1bbc800U, 0xd71a5c00U, 0x23287a00U, 0xd8e56500U, 0xcf14d980U, 0x81bbca40U, 0x671f59a0U, 0x1b2d0a70U, 0xd4e1b9b8U, 0x89127a74U, 0x20bc91aaU, 0x709b5661U, 0x3a6bc3bcU, 0xbd421f4aU, 0xa7a3c804U, 0xbbb65c11U, 0xc68a7a1dU, 0x70506508U, 0x951f59b3U, 0x302d0a7eU, 0x4461b997U, 0xed27a75U, 0x37dc9184U, 0x42cb5656U, 0xbc73c38dU, 0x11ee1f66U, 0x2201c80aU, 0x3035c11U, 0xd481fa2cU, 0x95c6a53eU, 0xec61b9a8U, 0x8ad27a5dU, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0x78000000U, 0x84000000U, 0xf2000000U, 0x79000000U, 0x7d800000U, 0x6bc00000U, 0x8ce00000U, 0xce900000U, 0x83380000U, 0xe1bc0000U, 0xb4fe0000U, 0xcb5d0000U, 0x196a8000U, 0x40e14000U, 0xe0916000U, 0x1c3cf000U, 0x9f383800U, 0x27be5400U, 0x27fdca00U, 0xbbda0d00U, 0x85282980U, 0x5ac3d840U, 0x2d64a9a0U, 0x43539850U, 0xcd949b8U, 0xd7af286cU, 0x578491a6U, 0x46c1cc4dU, 0xeb62839aU, 0xd0542553U, 0x7c583805U, 0x4bee5409U, 0x4da5ca06U, 0x8b360d2aU, 0xb40e29beU, 0x43b2d86eU, 0x8c4829adU, 0x3b93d86dU, 0xb0bca98fU, 0xe57f985fU, 0x3e9f49b6U, 0x128e2863U, 0x84f0118eU, 0x7aed8c47U, 0xec2163b8U, 0x6f5954bU, 0x3bef6017U, 0x75a1f01cU, 0x80000000U, 0x40000000U, 0x20000000U, 0x90000000U, 0xf8000000U, 0x3c000000U, 0x8e000000U, 0x1d000000U, 0xac800000U, 0x61c00000U, 0x90e00000U, 0xaf900000U, 0xac80000U, 0x314c0000U, 0x330e0000U, 0x4daf0000U, 0xca9b8000U, 0xf6644000U, 0x2151a000U, 0x85afd000U, 0xde9a3800U, 0x9c61dc00U, 0x1e501200U, 0x422bf500U, 0x32d83980U, 0x4fc7e7c0U, 0x5de5b9a0U, 0xdb10a7d0U, 0xc70999a8U, 0xd7a837f4U, 0xbd9f8196U, 0x65e17bfbU, 0x87118bb5U, 0xf90fc2fcU, 0xa2a9b81eU, 0xd5199c24U, 0xb627b21aU, 0x84f7251fU, 0xe71f8190U, 0x65217bf7U, 0x15718b82U, 0xba5fc2fbU, 0x6c01b81bU, 0x16059c25U, 0x9101b226U, 0x4a842503U, 0xb8c2019eU, 0x8e663becU, 0x5d55abaeU, 0x2bab52f7U, 0x5399a021U, 0xc8e3d03fU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x10000000U, 0xb8000000U, 0x74000000U, 0xbe000000U, 0x97000000U, 0xa3800000U, 0xb5c00000U, 0x50e00000U, 0x65700000U, 0x5cd80000U, 0xaa5c0000U, 0x691a0000U, 0x3abd0000U, 0xec6d8000U, 0x76604000U, 0xfe37e000U, 0x6b7c1000U, 0x7a8ba800U, 0x10103400U, 0xaf6b5a00U, 0x5be0fd00U, 0x94f6e680U, 0x441a9840U, 0xd83966a0U, 0x412bd870U, 0xeac10698U, 0xef668874U, 0x42b2ceb6U, 0x413bec69U, 0xfdaa5c99U, 0xc086754cU, 0x68442831U, 0x92217421U, 0x86133a05U, 0x346dad08U, 0xd2652eaaU, 0x1837fc66U, 0x9879f4beU, 0xdf0a4145U, 0x46d57212U, 0xe20c8939U, 0x1c505c8bU, 0x3b4b7563U, 0x3ef1a836U, 0xbd1d342fU, 0xb4beda14U, 0x336cbd17U, 0x9e30686U, 0x39f7886dU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0x48000000U, 0x74000000U, 0x9e000000U, 0x5b000000U, 0x3f800000U, 0xe3400000U, 0xa1a00000U, 0x52300000U, 0xa6180000U, 0xb55c0000U, 0x1cfe0000U, 0xdac90000U, 0x92d28000U, 0x348cc000U, 0x63f16000U, 0xc47c9000U, 0xac0cc800U, 0xf531f400U, 0xd39f8e00U, 0x31a1300U, 0xe1da4a80U, 0x683f8e40U, 0x9c2b2aa0U, 0xb7431e50U, 0xefa7e298U, 0xd132ea4cU, 0xd5986c8aU, 0xf418f951U, 0xc5a262dU, 0x727b7707U, 0xb30f0c82U, 0xfcb1696fU, 0x6fda6e32U, 0x4b3f4337U, 0x7fab6291U, 0xce072a4bU, 0xc3038cbbU, 0x9384a97aU, 0x31418e1dU, 0x58a31318U, 0xdcb0cab7U, 0xbfdf4e5eU, 0x933c4aadU, 0x33aa8e78U, 0x6c07aabaU, 0x7206de4eU, 0x69040295U, 0xb682ba5dU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xb0000000U, 0x68000000U, 0x94000000U, 0xb2000000U, 0x49000000U, 0x4a800000U, 0x77400000U, 0xeea00000U, 0xd0f00000U, 0x10680000U, 0xb72c0000U, 0x618e0000U, 0x5d7b0000U, 0xb3168000U, 0x339c000U, 0x47336000U, 0xdc8df000U, 0xf5f93800U, 0xf552ac00U, 0xeb1a7600U, 0xae84f300U, 0x4d414c80U, 0x23a263c0U, 0xf0722ca0U, 0xd22f93d0U, 0x350b1488U, 0x3d3d3ffcU, 0xa0316292U, 0xe909ccd9U, 0xeb382e3eU, 0x9337af0bU, 0xce8c028cU, 0xcff3cc6U, 0xd7d7963fU, 0x85cc30eU, 0xf22514a9U, 0xd4b63ffaU, 0x794fe28fU, 0x301c0ce6U, 0x5d054e2fU, 0xb8815f20U, 0x9e43ba81U, 0x142450d9U, 0xcfb68035U, 0x6ac9c00eU, 0xd5db6028U, 0x38e1f02fU, 0xa0d7382eU, 0xa5d9ac32U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x70000000U, 0x28000000U, 0xec000000U, 0x6e000000U, 0xff000000U, 0x6f800000U, 0x72c00000U, 0xfd600000U, 0xed00000U, 0x83680000U, 0x89ac0000U, 0xca0000U, 0x41f0000U, 0x8a748000U, 0xd559c000U, 0xdbd4a000U, 0x51e8d000U, 0xa5eba800U, 0x6fe91400U, 0xc2ea2200U, 0x646b1900U, 0x4229c780U, 0x200d48c0U, 0x307d67a0U, 0xd02598f0U, 0xc976cf88U, 0x4cdc8cecU, 0x3214ed82U, 0x310b95d7U, 0x60ff2a19U, 0x6d65dd28U, 0x36d4cda2U, 0x976a85c4U, 0x53a82215U, 0x55c8192bU, 0x169f47b7U, 0x63788deU, 0xca7f47aeU, 0x352788f7U, 0x53f747aeU, 0x5c9b88c6U, 0x6b3547adU, 0xccf888c9U, 0x6363c79bU, 0x19d248d0U, 0xa0e9e7afU, 0xe56c58f5U, 0x2aaa6f82U, 0x89485ce8U, 0x80000000U, 0x40000000U, 0x20000000U, 0x70000000U, 0xd8000000U, 0x2c000000U, 0xbe000000U, 0x41000000U, 0xa2800000U, 0xd0c00000U, 0x71600000U, 0xed900000U, 0x76580000U, 0x6a9c0000U, 0xb5fe0000U, 0x916f0000U, 0xc1b48000U, 0x31ee4000U, 0x26712000U, 0x70bd000U, 0x83a55800U, 0xdbf20c00U, 0x44baa00U, 0x7884f100U, 0xcbc64580U, 0x88e3bb40U, 0xe4d765a0U, 0x7e786b50U, 0x572a3da8U, 0xd216674cU, 0x221f979eU, 0x863d9647U, 0x458d5231U, 0x43606d17U, 0x229317b9U, 0x6ddfd673U, 0x44da720dU, 0x7258bd04U, 0x609ccf8eU, 0x46fc9a59U, 0xbcec7812U, 0x2af5dc2aU, 0x1ec8f23bU, 0xd445fd05U, 0xaca76f97U, 0xd0760a4cU, 0xa20c8027U, 0x3b224024U, 0x70372025U, 0xdca8d017U, 0x3457d81dU, 0x41bf4c1fU, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0xd8000000U, 0x84000000U, 0xc6000000U, 0xaf000000U, 0x19800000U, 0xe4400000U, 0x29600000U, 0x73b00000U, 0x81280000U, 0x96c0000U, 0xfa0e0000U, 0x44bf0000U, 0x5128000U, 0x86b84000U, 0x2c126000U, 0x103b5000U, 0x61d4a800U, 0x5182400U, 0xbf076600U, 0x31807d00U, 0x9844c880U, 0xdb6525c0U, 0xc2b6a8a0U, 0xb3ae75d0U, 0x32aa00a8U, 0x982a51fcU, 0x7eb669eU, 0x13c92cddU, 0x279b2e2fU, 0xacc74936U, 0x2fa36689U, 0x29152cdfU, 0x7cbd2e2bU, 0x5114493fU, 0x8bfe695U, 0x6f126ce0U, 0x93bdce04U, 0x68975907U, 0x5cf92eacU, 0x9e7118e9U, 0x640e0004U, 0x2fbf003eU, 0xfa92801fU, 0x7df8402eU, 0xc4f2602dU, 0x3cb5032U, 0xf9ca81fU, 0xd0c42419U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x50000000U, 0x68000000U, 0x94000000U, 0x3e000000U, 0x63000000U, 0x88800000U, 0x66400000U, 0xe4600000U, 0xf0500000U, 0xab980000U, 0xe3dc0000U, 0x6cba0000U, 0x706f0000U, 0xbbb58000U, 0x230ac000U, 0x9d646000U, 0x7dd29000U, 0x2a580800U, 0x7b7c8c00U, 0xbfccde00U, 0x8e40ed00U, 0xb067a780U, 0x6e511740U, 0x989bc7a0U, 0x35f8770U, 0x9ef9cf88U, 0xaa0c0b64U, 0x28e09192U, 0x162641U, 0x18fb561dU, 0xf509a119U, 0xaa62999fU, 0x6b55aa70U, 0x7f1a082eU, 0x7f9f8c28U, 0xbddb5e16U, 0xffb92d11U, 0xc0ec47b0U, 0x21f64764U, 0x6d6a2f89U, 0x30375b78U, 0x3dcb7992U, 0x2741fa4eU, 0x95e46033U, 0xdb929028U, 0x6e38083bU, 0xdb2c8c3bU, 0x7c54de02U, 0xf99ced01U, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0xb8000000U, 0x4c000000U, 0xd6000000U, 0x55000000U, 0x8d800000U, 0x82c00000U, 0x3fa00000U, 0x1c300000U, 0xd280000U, 0x21ec0000U, 0x274e0000U, 0x70fd0000U, 0x62168000U, 0x5df4000U, 0x26632000U, 0xe7109000U, 0x6058b800U, 0x40a59400U, 0x8ab3a200U, 0xb6a4f00U, 0xf085680U, 0x271c0bc0U, 0x49c376a0U, 0x53209bd0U, 0xe975ceb8U, 0x43480fccU, 0x62f8ec96U, 0x751100dfU, 0x375d9a23U, 0x12209b0aU, 0xcef0d4a0U, 0x9a8ad4faU, 0xb9dd9817U, 0x8640431U, 0x9e139a02U, 0x4bdd9b26U, 0x2f665488U, 0x749594e0U, 0x439eb808U, 0x68849417U, 0x97432220U, 0xe1640f10U, 0x3d93f6a1U, 0xb01edbe0U, 0x3b466ebdU, 0x766dfe7U, 0xb093f4a2U, 0x19a44d2U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x70000000U, 0x68000000U, 0x24000000U, 0x66000000U, 0x51000000U, 0x2b800000U, 0x9ac00000U, 0x7a00000U, 0xaf300000U, 0xa4b80000U, 0xc07c0000U, 0x1ada0000U, 0x7c6f0000U, 0x5148000U, 0xd04bc000U, 0xf0e0e000U, 0xd354d000U, 0xefaed800U, 0x5364400U, 0x77b97200U, 0x7cff1f00U, 0x8a9a7e80U, 0xa28a7f40U, 0x13429ea0U, 0xba62af70U, 0x6a164688U, 0x86cbeb6cU, 0xd3a3b492U, 0x61333465U, 0x71bb2a0bU, 0xfdfe9b31U, 0xb919eca1U, 0x744eb067U, 0x56e2b828U, 0x22555420U, 0xb42d4a13U, 0xf7f28b35U, 0x541954beU, 0xb5c8e46bU, 0x7f217216U, 0x49731f14U, 0x93587eb0U, 0xc1a97f55U, 0xc0341ebbU, 0xf23a6f4cU, 0xe33826a3U, 0xa8bbfb56U, 0xe2790ca6U, 0xfdda605eU, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0x48000000U, 0xb4000000U, 0x46000000U, 0xdb000000U, 0xc8800000U, 0x43c00000U, 0x77200000U, 0x28900000U, 0xd5f80000U, 0xc43c0000U, 0x9e1e0000U, 0xcd0f0000U, 0xd7b08000U, 0x296ec000U, 0x87c56000U, 0x39205000U, 0x67920800U, 0xab788c00U, 0x14fef200U, 0x95ba9b00U, 0xe05b9780U, 0xae681440U, 0xd46f7a0U, 0x8fe44450U, 0x4732ffa8U, 0x6afc86cU, 0x9ae28dbaU, 0x80b49341U, 0x1becfa2bU, 0xcd021737U, 0xeb8565b9U, 0x57428f77U, 0x36e5600cU, 0x8ab05011U, 0x5aea0803U, 0xdc848c21U, 0xb5c0f22fU, 0xc4259b35U, 0xa41317abU, 0x983ad474U, 0xdc1d9794U, 0x380b1446U, 0x8030779fU, 0xac29847bU, 0xdc211f87U, 0xe812587bU, 0x23b6589U, 0x51d8f6eU, 0x80000000U, 0x40000000U, 0xe0000000U, 0xb0000000U, 0x48000000U, 0xb4000000U, 0x22000000U, 0xdb000000U, 0x54800000U, 0xd1400000U, 0xb9600000U, 0x64500000U, 0x5aa80000U, 0xd0ec0000U, 0x7d0e0000U, 0x28190000U, 0x7bd48000U, 0x876ac000U, 0x14c96000U, 0xce3d7000U, 0x13e12800U, 0xe8104c00U, 0x564b2600U, 0xa6795d00U, 0xc5023780U, 0xb985dec0U, 0x2cc557a0U, 0x1fa1aed0U, 0xa4f0ff98U, 0xc0db22fcU, 0xae72b98aU, 0x1c9f0fd1U, 0x5a91a602U, 0x960a9d27U, 0x749fd7b7U, 0xfe926ec3U, 0xac0d1f81U, 0xe39c92e6U, 0x7412f1bdU, 0x304e33d3U, 0xf77da838U, 0x4e868c02U, 0x5644461bU, 0x2be12d31U, 0xb4119f9dU, 0x904a52c3U, 0xa77d9193U, 0xb68643e9U, 0xaa46003fU, 0xbde50024U, 0x4d128028U, 0x1fcfc028U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0xa8000000U, 0xac000000U, 0x4a000000U, 0x21000000U, 0x91800000U, 0x59c00000U, 0x8e00000U, 0xb5300000U, 0xdbe80000U, 0xcb2c0000U, 0x5e4e0000U, 0x68b90000U, 0x42b28000U, 0xa92bc000U, 0x9348a000U, 0x533ff000U, 0x4a727800U, 0x984c3400U, 0xd3b8da00U, 0xca32ad00U, 0x156cdc80U, 0x8c6f47c0U, 0x29ea7ca0U, 0xde29b7d0U, 0x61ca8498U, 0x867e43ccU, 0x18d2feb2U, 0x595f1ee7U, 0xc2025a20U, 0x5d056d2fU, 0xe3827ca4U, 0xcc5b7e9U, 0xd76484beU, 0x2bf743c8U, 0x29887e9aU, 0x9758decdU, 0x4504fa35U, 0x47839d34U, 0x7ac284b3U, 0x646243d0U, 0x9f74fea9U, 0x7ca1ef3U, 0xad7eda1dU, 0x4857ad3dU, 0xe1185c90U, 0x3b2187d4U, 0x4cd65cbcU, 0xc75887d5U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0xf8000000U, 0xd4000000U, 0x4a000000U, 0xf000000U, 0x4a800000U, 0xed400000U, 0x44e00000U, 0xd7500000U, 0xaa780000U, 0xe03c0000U, 0x25a0000U, 0xc6490000U, 0xbdd78000U, 0x373c4000U, 0xecd8e000U, 0x290fb000U, 0xa324800U, 0xcced5c00U, 0x3ae15600U, 0x82568100U, 0x77f99380U, 0x43f8ac40U, 0x19fb73a0U, 0x8efe1c70U, 0xc07ebbb8U, 0x9f3f0044U, 0xdf0d86U, 0xd70a3171U, 0x9f36d614U, 0x716ac132U, 0x492173a6U, 0x61f71c79U, 0xeb493b8fU, 0x74534048U, 0xbeffed83U, 0x28798171U, 0xd33e9e2fU, 0x4ede9d36U, 0x6a0fa5a0U, 0xeb1dd73U, 0x9caa4820U, 0xef815c33U, 0xb8c3561fU, 0x7b23813cU, 0x7af4138fU, 0x8bcdec57U, 0x461413a3U, 0x489dec46U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x50000000U, 0x98000000U, 0xb4000000U, 0xa2000000U, 0xdf000000U, 0x60800000U, 0x6dc00000U, 0xffe00000U, 0xf2700000U, 0x18a80000U, 0x26c0000U, 0x10a0000U, 0x60bb0000U, 0x86f18000U, 0x47694000U, 0x9a8ee000U, 0x77fcf000U, 0x2fd18800U, 0x1078cc00U, 0x7690c200U, 0x505c8d00U, 0x6c017680U, 0xf6010fc0U, 0xd0596a0U, 0x7786fff0U, 0x21459ea8U, 0x842773e4U, 0x7093bc8eU, 0x555b0ec9U, 0x17814226U, 0x9145cd3eU, 0x6c27969eU, 0xc91ffd5U, 0xdb5e1e89U, 0xde8533cdU, 0x8cc4dca1U, 0xbe62bef4U, 0xfe342a2fU, 0xbb0af136U, 0xcbbf5c9eU, 0x6470fefbU, 0xa5ab4a37U, 0x9def4125U, 0x5c48348bU, 0x6a98c2d4U, 0x3f600036U, 0xfb00026U, 0x5f480032U, 0x141c0037U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x30000000U, 0x58000000U, 0xfc000000U, 0x46000000U, 0x3d000000U, 0x7f800000U, 0x8cc00000U, 0x39600000U, 0xbaf00000U, 0x68f80000U, 0x953c0000U, 0x8dde0000U, 0x9ae90000U, 0xc2f08000U, 0x4fe4000U, 0x5b3fa000U, 0x24d89000U, 0x76ff800U, 0xc9374400U, 0x391a0200U, 0x2f881900U, 0x86031680U, 0x9d00c540U, 0xaf82b6a0U, 0xe4c15550U, 0x9d65ce98U, 0xf4515cU, 0x13fe6c8eU, 0xd7bdd863U, 0x7e9a021fU, 0x2f48192cU, 0x416316a0U, 0xd6f0c55fU, 0xa6fab6b6U, 0x3c3d556dU, 0x105bce82U, 0x912d517bU, 0xff16eca6U, 0x704f986dU, 0xf9e3a218U, 0xbeb58900U, 0x61da6ebfU, 0x14ecc154U, 0x8bf194b2U, 0xa97a9c71U, 0x8f8002bU, 0xe53c000aU, 0x35de003eU, 0x56e9002aU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0x68000000U, 0xc4000000U, 0x5e000000U, 0xb9000000U, 0x77800000U, 0x37400000U, 0xbfa00000U, 0xe3300000U, 0x3fe80000U, 0x7dac0000U, 0x5f8e0000U, 0x34fb0000U, 0x46378000U, 0x6a68c000U, 0xa1e8e000U, 0x24ad1000U, 0x18095800U, 0xfbbd2400U, 0x5591fe00U, 0x135cd300U, 0x7902f280U, 0x978679c0U, 0x74412a0U, 0x47a069d0U, 0x4f32ca88U, 0xa5e98df4U, 0x9aadd492U, 0x910f4ec5U, 0x743ffe05U, 0xced7d32bU, 0x36fd72b8U, 0x7d32b9f6U, 0x66eaf29fU, 0x3a2a79faU, 0x90ca12a2U, 0x275b69f0U, 0x3f054ab8U, 0xb2814de2U, 0x12c534a3U, 0x3be25edbU, 0xa416a639U, 0xe11af727U, 0xe3248cbfU, 0xf0f26aeeU, 0x7f8e003aU, 0xe4fb000cU, 0x8e378030U, 0x3e68c03bU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0xc8000000U, 0x94000000U, 0xfe000000U, 0xdf000000U, 0x19800000U, 0x59400000U, 0x3c600000U, 0xefd00000U, 0xd6c80000U, 0x7c8c0000U, 0xdb6a0000U, 0x8fd0000U, 0x22d48000U, 0x724ec000U, 0x69486000U, 0xb6ce9000U, 0x8c8ee800U, 0xf369e400U, 0xacf9ce00U, 0x14d37d00U, 0x39490b80U, 0x8ecb89c0U, 0x308b6ba0U, 0xa96819f0U, 0x45f90398U, 0x46533dfcU, 0x878aadaaU, 0x34efd0d9U, 0xfabbce15U, 0xc9327d2eU, 0xd3df8bb3U, 0xe6449c8U, 0x82d58ba4U, 0x624949cfU, 0x71490b9bU, 0xdacb89f9U, 0x2e8b6ba0U, 0x466819e9U, 0x94790391U, 0x8b133dd4U, 0x45eaad82U, 0x43fd0d4U, 0x35f3ce1bU, 0xecfe7d0cU, 0x34d58b93U, 0xe94949e4U, 0x76c90bbbU, 0x6c8b89e5U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x90000000U, 0xf8000000U, 0x94000000U, 0xe2000000U, 0x1f000000U, 0xc1800000U, 0xd0400000U, 0x9b600000U, 0x60700000U, 0xacf80000U, 0x41bc0000U, 0xa45e0000U, 0xa5e90000U, 0x2a358000U, 0xfc9e4000U, 0xe24ce000U, 0x57e6f000U, 0x46b18800U, 0xaa5ec400U, 0x8ce82600U, 0xf6b1cd00U, 0x6259e680U, 0x90ec5540U, 0xe8b306a0U, 0xf35fa550U, 0x38690e98U, 0x4762174U, 0x66f848a6U, 0xd2bf5c51U, 0x83dcc61eU, 0x70ab3d16U, 0xfbd66e8eU, 0x6f2b9172U, 0x1a96a0b0U, 0x2ccc285eU, 0xfe22081dU, 0x7995840fU, 0x234f4612U, 0xa7607d14U, 0x4e710ea8U, 0xb5fa217cU, 0x153e4898U, 0xc69a5c70U, 0x594f4604U, 0xfc607d31U, 0x75f10e8bU, 0x7eba2174U, 0x55de48b6U, 0xfdaa5c6dU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x90000000U, 0xb8000000U, 0xec000000U, 0xee000000U, 0xdd000000U, 0x24800000U, 0x2e400000U, 0xfae00000U, 0xb4500000U, 0x50180000U, 0x955c0000U, 0xa3a0000U, 0x52ab0000U, 0xcf178000U, 0x8a7e4000U, 0x954b2000U, 0xefc35000U, 0xdc243800U, 0xaef25c00U, 0x53a88e00U, 0xed97c900U, 0xd3c3380U, 0xd92d1f40U, 0xfed513a0U, 0x63594f70U, 0x6b3caba8U, 0x2e5354U, 0x40508586U, 0x2188a6fU, 0x3e59ae3dU, 0x8fbf9918U, 0xe6f8b94U, 0x2ab10363U, 0xe4ebd82U, 0x8241d65aU, 0xf4e6a030U, 0xd9561020U, 0x5c989807U, 0xef1f4c08U, 0xf2df960eU, 0xd5fac532U, 0x668a85b2U, 0x15e38a54U, 0x4bd62e34U, 0xf3ddd930U, 0xf77eab97U, 0xe1c95365U, 0x5985059dU, 0x5ac1ca67U, 0x80000000U, 0x40000000U, 0x20000000U, 0xd0000000U, 0x38000000U, 0x84000000U, 0x6a000000U, 0xb3000000U, 0x21800000U, 0x2e400000U, 0xc0a00000U, 0x70f00000U, 0x91980000U, 0x4edc0000U, 0xc0fe0000U, 0xa1cf0000U, 0xefb18000U, 0x3fbc4000U, 0xffee6000U, 0xb6863000U, 0xf5c02800U, 0x45e46400U, 0xc5d1f600U, 0x9d2e0300U, 0x28e68c80U, 0xb554b440U, 0x6deeeca0U, 0xe1818450U, 0x4e4144a8U, 0x30a6a064U, 0x98f752a6U, 0x2d9ed345U, 0xa0d9963cU, 0x19fb3329U, 0x33492494U, 0xe0739072U, 0xd158fa8cU, 0x4fb9f74aU, 0x57ef802eU, 0x2a83400cU, 0xcbc7e02aU, 0xa4e67039U, 0xd350480bU, 0xf8ed5425U, 0x75005e02U, 0x2486273eU, 0xa2c11ab1U, 0xfe60874cU, 0xb096483cU, 0xc00e540bU, 0x9857de25U, 0x3d696739U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0xf8000000U, 0x94000000U, 0x2e000000U, 0xd7000000U, 0x86800000U, 0x59400000U, 0x19e00000U, 0x28500000U, 0x83d80000U, 0xd79c0000U, 0xe1fa0000U, 0xa96b0000U, 0x30968000U, 0xcdfd4000U, 0xf36be000U, 0x59959000U, 0xd47ba800U, 0x40afdc00U, 0xa3317600U, 0x1ccce900U, 0xbaa22380U, 0x28b4d140U, 0x6a0bc3a0U, 0xc3864170U, 0x1ac4eba8U, 0xc323dd5cU, 0xcb72fd96U, 0xf8ace479U, 0xd736161dU, 0xa2cf390cU, 0x25a4eb9cU, 0xc233dd6aU, 0x894afdb2U, 0x2360e47cU, 0x63141624U, 0x9f383900U, 0x5c486b89U, 0x28e59d4aU, 0xd5d79d87U, 0xc6183446U, 0xde3c5e2aU, 0x79ce7505U, 0x4920b5acU, 0xa71a84aU, 0x1d28481eU, 0x96f64c2dU, 0xcd68de35U, 0x694351bU, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0x98000000U, 0x6c000000U, 0xd6000000U, 0x37000000U, 0x2d800000U, 0x11c00000U, 0xd3e00000U, 0x71700000U, 0x2c80000U, 0x1e8c0000U, 0xacaa0000U, 0x26390000U, 0x71878000U, 0x4fc74000U, 0x70e22000U, 0x36f79000U, 0x6a08a800U, 0xbbe90400U, 0x379cea00U, 0xd1d7c500U, 0xe01f7680U, 0x8110ccc0U, 0x997ad6a0U, 0x84201cf0U, 0xad905eb8U, 0x823e88c4U, 0x93841c9eU, 0xa2c049dfU, 0x6c67802bU, 0xa5b74012U, 0xe9aa2000U, 0xdebb9026U, 0xa0c2a82cU, 0x9160040eU, 0x41336a0aU, 0xc6ec8512U, 0x131f5694U, 0x9e925cd6U, 0xfdbffea3U, 0x274758f1U, 0x99a11493U, 0x34559dd4U, 0xc5dbe22fU, 0x88f71126U, 0xd90e949cU, 0x46edde6U, 0xe35bc20bU, 0x3ab58115U, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0x18000000U, 0x4c000000U, 0x46000000U, 0xf7000000U, 0x18800000U, 0x84400000U, 0xbe600000U, 0xcf500000U, 0xc0380000U, 0xa4fc0000U, 0x62de0000U, 0x2ded0000U, 0x69828000U, 0x4bc64000U, 0xb2a62000U, 0x1d771000U, 0xe50f2800U, 0xa1932c00U, 0xb71b6e00U, 0x449ad00U, 0xba76ef80U, 0x35886a40U, 0xe1d24fa0U, 0xeb793a50U, 0x2e1b47b8U, 0x9fcd066cU, 0xbcb701beU, 0x56ab877fU, 0x2b64802fU, 0x72d74002U, 0xc1faa009U, 0xc75c5033U, 0x602b883eU, 0x4c227c3cU, 0xbe326608U, 0xcbed9106U, 0x4e82a981U, 0xdb42eb70U, 0x92e7ce3dU, 0xb114fd13U, 0xd759e786U, 0xc82d564bU, 0x782289b1U, 0x4434fb75U, 0x62ec660bU, 0xed00912dU, 0x180298eU, 0x5fc4ab6dU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0xb8000000U, 0x64000000U, 0xd6000000U, 0x8b000000U, 0xf1800000U, 0x7dc00000U, 0x9fa00000U, 0xf300000U, 0xf6380000U, 0x4e7c0000U, 0x121e0000U, 0x45890000U, 0x37028000U, 0x73834000U, 0x78c26000U, 0xf123d000U, 0xed740800U, 0xfb5e4400U, 0xf96a8a00U, 0x1dd2c700U, 0x93ede680U, 0x19905b40U, 0x4d8d06a0U, 0x4b00cb50U, 0x51836e98U, 0xedc15f4cU, 0x57a3ecb6U, 0xd334dc55U, 0x443e0003U, 0x13790037U, 0x689a801fU, 0xc9cf4038U, 0xd5646000U, 0xe316d027U, 0x81c88813U, 0x4964042dU, 0xb1126a22U, 0xacce571eU, 0x8be58e93U, 0x5954cf5dU, 0x98a9048aU, 0x90730872U, 0x51d86234U, 0x5d291303U, 0x53b58480U, 0x979485cU, 0xd9988204U, 0x59498328U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0x18000000U, 0x3c000000U, 0x16000000U, 0xc5000000U, 0x43800000U, 0xd1c00000U, 0x7b200000U, 0x11300000U, 0xacb80000U, 0xb0fc0000U, 0x231a0000U, 0x7c890000U, 0x5c78000U, 0x39234000U, 0x5634a000U, 0xc83f1000U, 0xd5bbb800U, 0x257f6400U, 0x57db0a00U, 0x942ee300U, 0xdd308280U, 0xd2ba1b40U, 0xe1fba2a0U, 0x829a4b70U, 0x5a4ebab8U, 0xd2633f44U, 0x695188beU, 0xd6edf84bU, 0x8094a03bU, 0xe1cf103aU, 0x2fa3b80bU, 0x7c73643eU, 0xeed90a0dU, 0x61abe30eU, 0x79f502a0U, 0x221c5b6dU, 0x50a828dU, 0x7f031b73U, 0x28842284U, 0xdb450b7dU, 0x37601a89U, 0x5ad52f44U, 0xaf2db092U, 0xfb1dc50U, 0xc2fb0a1fU, 0x6c1ee31eU, 0x5c088297U, 0x9a861b50U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x30000000U, 0xc8000000U, 0xbc000000U, 0xbe000000U, 0x15000000U, 0x38800000U, 0x4cc00000U, 0x7d200000U, 0xbf900000U, 0x9380000U, 0x1b7c0000U, 0xbb9a0000U, 0x2baf0000U, 0xf6c68000U, 0xc224c000U, 0x172000U, 0x2e7fd000U, 0x731af800U, 0xf6b7c00U, 0x7e1fa00U, 0xbb26300U, 0xa02f7780U, 0xb3821a40U, 0x9146d7a0U, 0x61650a70U, 0x2710f88U, 0xbd8ea67cU, 0x4d48dbaU, 0x2f5f7953U, 0xd28f2015U, 0x2353d016U, 0xec18f83bU, 0x40e87c35U, 0x48a57a0cU, 0xefd5a316U, 0x62dcd7bcU, 0x36ca0a7fU, 0xeab78f9dU, 0x5aaa6640U, 0xf443ad86U, 0xf1e0a96fU, 0x62b5d82bU, 0x86a8ac24U, 0xda41023aU, 0x1ce61f14U, 0x2e300db3U, 0xc868b943U, 0xc64802bU, 0x8ef7c02fU, 0x80000000U, 0x40000000U, 0x60000000U, 0x90000000U, 0x98000000U, 0x4c000000U, 0xc6000000U, 0xd5000000U, 0xb5800000U, 0x70400000U, 0x5be00000U, 0xb2300000U, 0x4ec80000U, 0x790c0000U, 0xddae0000U, 0x6afd0000U, 0x5ac18000U, 0xad214000U, 0x9112000U, 0x6adc1000U, 0x7a523800U, 0x89bd5400U, 0x21a1b600U, 0xbad4d900U, 0xfc7ea080U, 0x62045ac0U, 0x170600a0U, 0x12850ad0U, 0xac318b8U, 0x15254ef4U, 0xb517169eU, 0xa4dc83e7U, 0x7b56a02fU, 0xb63c5012U, 0x42e49822U, 0x81b1041eU, 0x8b8d2e2cU, 0x769dd16U, 0x87dd8e99U, 0x33d087dbU, 0x57fa0e3fU, 0xeb44cd24U, 0xaf6036bcU, 0x9df193e7U, 0xe66b1836U, 0x685d4436U, 0xa8958e14U, 0xb0988d18U, 0xc2b09689U, 0x530cc3f2U, 0x7ea8002cU, 0x627c0007U, 0x80000000U, 0x40000000U, 0x60000000U, 0x90000000U, 0x28000000U, 0xc4000000U, 0x7e000000U, 0x3d000000U, 0x4e800000U, 0xd6400000U, 0x3e200000U, 0xaf100000U, 0xda580000U, 0xf79c0000U, 0x257e0000U, 0xc40d0000U, 0xce618000U, 0x9034c000U, 0xc9c8e000U, 0xec841000U, 0xc9477800U, 0x2fa54c00U, 0x8d25e00U, 0xd3bd9f00U, 0x796a6f80U, 0xb5d11940U, 0xdd3d0fa0U, 0xcf2cc950U, 0x1bf317b8U, 0x5a295574U, 0xd176d1b2U, 0x92699645U, 0x4257982dU, 0x5bfd5c0aU, 0x8a4b261eU, 0xec45d32fU, 0x3d21b189U, 0xbc944660U, 0xd2998015U, 0x37f8c03cU, 0x704ee03bU, 0xcf451036U, 0xdea0f809U, 0xc508c32U, 0xfefd3e21U, 0xd8cc4f1cU, 0x380277a9U, 0xac058550U, 0xda07499eU, 0xd305ca5bU, 0x5b833e12U, 0x5cc14f20U, 0x80000000U, 0x40000000U, 0x20000000U, 0x90000000U, 0x8000000U, 0xa4000000U, 0xda000000U, 0x77000000U, 0xf9800000U, 0xeac00000U, 0x6c600000U, 0xe5b00000U, 0xfab80000U, 0xc6fc0000U, 0x75de0000U, 0xd8cf0000U, 0x9ea38000U, 0x65d7c000U, 0x4108e000U, 0x1433000U, 0x35a20800U, 0x1a568400U, 0x1ac97200U, 0x5a40100U, 0xc253f480U, 0x96cb1d40U, 0xeba694a0U, 0x6750ed50U, 0xbc4ffca8U, 0x22e29974U, 0x96f466aaU, 0xcc1f2c5dU, 0xd72ae81cU, 0xc6d5b400U, 0x9a8b7a02U, 0x8082852aU, 0x46428691U, 0x14231c77U, 0x7c93600dU, 0x98a8f03fU, 0x4514e80eU, 0x126ab420U, 0x9970fa1dU, 0x6fd9450eU, 0xcfcc66a2U, 0xd7232c43U, 0x1714e839U, 0x816ab403U, 0x9af0fa2fU, 0x62194503U, 0x522c6697U, 0x7c532c7aU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0x68000000U, 0x84000000U, 0xda000000U, 0x7b000000U, 0x90800000U, 0xc00000U, 0x9ee00000U, 0xad500000U, 0x85480000U, 0xba0c0000U, 0xe6aa0000U, 0x1adb0000U, 0x9ea38000U, 0x9b74c000U, 0x12fee000U, 0x58153000U, 0xcaec6800U, 0x52f8ac00U, 0xb8130a00U, 0xfaefed00U, 0x2afcbf80U, 0x5412a1c0U, 0xa4ebdfa0U, 0x8bf851f0U, 0xbf92d7a8U, 0x34ad0df4U, 0x15d955b2U, 0x8c247cd5U, 0x1cb10804U, 0x2a995c0bU, 0xd0818200U, 0xe0c2713bU, 0xaee3ddafU, 0xd555e0d4U, 0x694c6a34U, 0xe4091d2bU, 0x47afb793U, 0xf15cfdc7U, 0xee3dda2U, 0x555e0f4U, 0x214c6a25U, 0x70091d32U, 0xf5afb79eU, 0xe5cfdc7U, 0x4463dd94U, 0x7e95e0feU, 0x2f2c6a09U, 0xdd991d2dU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0x48000000U, 0xe4000000U, 0xa6000000U, 0xdd000000U, 0x2f800000U, 0xac00000U, 0x94a00000U, 0x1c900000U, 0xdee80000U, 0xbaac0000U, 0xc14a0000U, 0xfcbb0000U, 0x4ee68000U, 0x8670c000U, 0x7699e000U, 0xd531d000U, 0x2df8b800U, 0x4e808400U, 0x5f417200U, 0x69602700U, 0x88b7cb80U, 0xd43d90c0U, 0xeca2aba0U, 0x709780f0U, 0xbced73a8U, 0x71aa14dcU, 0x7bcf59baU, 0x3dfc67e5U, 0x7685d813U, 0xd3469412U, 0x9b64aa38U, 0xbbb6b320U, 0xc2bb6195U, 0x6fe723cbU, 0x33f3ca10U, 0x1b5ba32cU, 0xb91039a1U, 0x8b2d77f8U, 0x5a8c8003U, 0x959bc03eU, 0xdbb76028U, 0x92bd101eU, 0xb7e3582cU, 0x2ff65403U, 0x115d4a1eU, 0x2617632dU, 0xdfabd99fU, 0xa2cba7e5U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x30000000U, 0x58000000U, 0xc4000000U, 0x42000000U, 0xdb000000U, 0x72800000U, 0x48400000U, 0x55a00000U, 0xd1f00000U, 0x8c780000U, 0xafbc0000U, 0x5bde0000U, 0x5490000U, 0x75208000U, 0x8ab64000U, 0xe75a6000U, 0xd80b7000U, 0x87062800U, 0x54847c00U, 0x1439e00U, 0x9426e300U, 0x77311480U, 0x179e3340U, 0xb2edf4a0U, 0xafd60350U, 0x1c4f3c98U, 0x9ca64f5cU, 0x50706a8eU, 0xcab9e06dU, 0x45ea81eU, 0x1e8e3c1bU, 0x3547fe22U, 0x2e249319U, 0xb837bc8fU, 0x4f1c0f61U, 0xbdac0a9aU, 0xef7906bU, 0x1cfe0024U, 0xecf90010U, 0x14f88013U, 0xfa4001U, 0x2afc6017U, 0x6dfe7039U, 0x9978a81fU, 0x483b3c24U, 0xb4197e0cU, 0x5f2bd302U, 0xceb55cb3U, 0xe55d3f5cU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0x98000000U, 0xac000000U, 0x86000000U, 0xc1000000U, 0x14800000U, 0xc0c00000U, 0x32e00000U, 0x5100000U, 0x79980000U, 0x8adc0000U, 0x7d7a0000U, 0x16cb0000U, 0x9c628000U, 0xead24000U, 0x8af92000U, 0x41881000U, 0x29c19800U, 0xd260fc00U, 0xcfd41a00U, 0x3c7c7d00U, 0xc24abd80U, 0x7ca72540U, 0xe8331da0U, 0x17ea7570U, 0x941325a8U, 0x251bd97cU, 0x6e1d078eU, 0xcd9d0857U, 0x60db182fU, 0x1a7ebc27U, 0xf34f3a0aU, 0xd0236d27U, 0xb4f3a58eU, 0x3b0e996aU, 0xfc04a796U, 0xce005853U, 0xe5032020U, 0x9683102aU, 0xb3c31804U, 0xcd62bc3bU, 0x96553a03U, 0x5e386d16U, 0x696925b4U, 0xf3d0d95bU, 0xd27f8795U, 0x174f4850U, 0x72223811U, 0xf7f6ac2bU, 0x80000000U, 0x40000000U, 0xe0000000U, 0xb0000000U, 0x28000000U, 0x74000000U, 0x66000000U, 0xaf000000U, 0x94800000U, 0x86c00000U, 0x200000U, 0x8c500000U, 0xc9380000U, 0x5a7c0000U, 0x631e0000U, 0x53290000U, 0xfba48000U, 0x3e11c000U, 0x1fd86000U, 0x4e085000U, 0x7a72a800U, 0xd26c4c00U, 0xbc05a00U, 0x35a32b00U, 0xa5111180U, 0xd5b0c40U, 0xd7cbf1a0U, 0xc6d79c50U, 0xacfbb998U, 0xa4db407cU, 0x4c8dab92U, 0x9bb1b761U, 0x82c8280bU, 0x4f548c0aU, 0x27bcba0eU, 0x81babb3bU, 0x8ebbd9b6U, 0x4a3f1074U, 0x54f903aeU, 0x8d8fb6fU, 0x968af217U, 0x96b3673cU, 0xf74f4ba6U, 0x8611275fU, 0x53de6020U, 0x240d5038U, 0x5f70283bU, 0xd3e88c1aU, 0xa482ba0aU, 0xeec3bb3aU, 0x94275999U, 0x5a52d077U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xf0000000U, 0xa8000000U, 0x84000000U, 0xea000000U, 0xb7000000U, 0xff800000U, 0x7a400000U, 0xa0600000U, 0xcd100000U, 0xbad80000U, 0xa61c0000U, 0xfeba0000U, 0xb10d0000U, 0xbb628000U, 0x9c93c000U, 0x7d99e000U, 0xbefdb000U, 0x1e698800U, 0x55f43400U, 0x9a084600U, 0xa2e55500U, 0x2fd7a580U, 0x277c5f40U, 0x6d2ec5a0U, 0xef132f70U, 0xb9de2d98U, 0xfb986b4cU, 0x47fe83b2U, 0xacea7a6dU, 0x3f338808U, 0x93a93400U, 0xdbd2c617U, 0xa57a952eU, 0xbe2c4587U, 0xa90ef61U, 0xdc9fcda3U, 0x2079db59U, 0x1aad0b9eU, 0x1534e64U, 0xabb94e25U, 0xad8fa13cU, 0x6ca48388U, 0x2db77a7dU, 0x29690806U, 0x6a76f413U, 0x492605U, 0xf2862509U, 0x4ac54da6U, 0x19a61b7eU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x50000000U, 0x48000000U, 0xc000000U, 0xfa000000U, 0x93000000U, 0xb3800000U, 0x89400000U, 0x2e200000U, 0xbe900000U, 0x4b280000U, 0x74ec0000U, 0x990a0000U, 0x87d0000U, 0xb5278000U, 0x2111c000U, 0x886fa000U, 0xd1cb7000U, 0xd01b6800U, 0x3c13b400U, 0x86e91e00U, 0x260fff00U, 0xf1fff380U, 0xb76266c0U, 0xf8b5d3a0U, 0x49b9d6f0U, 0xddc49b98U, 0x3ae1d2e4U, 0xd4f4cd8aU, 0x5d1a29e7U, 0x9a916834U, 0x2d2eb403U, 0xb5ee9e38U, 0xe58e3f11U, 0x80b8538bU, 0x8d4516eaU, 0xf824bbabU, 0x679762c4U, 0x73aa058bU, 0xa2fedf6U, 0xc86c9e18U, 0xf1cf3f1fU, 0x601dd3afU, 0x2415d6d0U, 0xc2ee9bbdU, 0xd00cd2c4U, 0x98fb4d9bU, 0x97e7e9f7U, 0xc274c834U, 0xeed8c428U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x70000000U, 0x98000000U, 0x14000000U, 0x82000000U, 0x61000000U, 0xf1800000U, 0x5e400000U, 0xbe600000U, 0x5b100000U, 0x5d980000U, 0x7d5c0000U, 0x8bfa0000U, 0x6a4f0000U, 0xe0648000U, 0x84144000U, 0x631ae000U, 0x559ff000U, 0xe1597800U, 0x55ff3400U, 0x754ee600U, 0x7ee3c500U, 0xdcd6b580U, 0x91b9c540U, 0x7e2ad5a0U, 0xf6717570U, 0xce0fcd88U, 0x3b06f16cU, 0xe48433aeU, 0xfdc2b069U, 0x6921780eU, 0x98f33431U, 0xcecce612U, 0x7da0c516U, 0x3d303595U, 0x13ee855cU, 0x1756b584U, 0xaf9c576U, 0x8bcad5aeU, 0xf6217568U, 0xc677cd8cU, 0x360af15bU, 0xff06339bU, 0x8e81b040U, 0x10c7f808U, 0xea4741dU, 0x25b08638U, 0xe028753eU, 0x89752d88U, 0x80890178U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x10000000U, 0x58000000U, 0x54000000U, 0x52000000U, 0x71000000U, 0x8a800000U, 0x20c00000U, 0xb8600000U, 0x41300000U, 0x49f80000U, 0x1cbc0000U, 0xc19e0000U, 0x558b0000U, 0x24638000U, 0x5f354000U, 0x9efde000U, 0xa53e7000U, 0x42df7800U, 0x13acec00U, 0xaff7ca00U, 0x9e9e5900U, 0xb7880U, 0x1120f340U, 0x721318a0U, 0xe2ecc350U, 0xc8d40088U, 0x678c1f54U, 0xa564d29eU, 0x3db29a41U, 0xa23f780aU, 0x435cec1dU, 0x74efca08U, 0xf3d25905U, 0x680d788eU, 0x4d27f351U, 0x8c1698aaU, 0x85ee8353U, 0x395460a6U, 0xe8cc2f5eU, 0xe545ca9bU, 0x95254654U, 0x98122a06U, 0x77ec2931U, 0x58520086U, 0x3a4b1f6aU, 0x918152bbU, 0x7f40da5cU, 0xa827181eU, 0xb490dc19U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x10000000U, 0x78000000U, 0x44000000U, 0xca000000U, 0x45000000U, 0xdd800000U, 0xd8400000U, 0x66200000U, 0x58d00000U, 0xa3780000U, 0x555c0000U, 0xb58a0000U, 0x32f10000U, 0xbdad8000U, 0x35244000U, 0x9e576000U, 0x31bcb000U, 0x27bad800U, 0x3cbb5400U, 0x76392600U, 0x62fccf00U, 0xb31f5d80U, 0x54aa6040U, 0xdea585a0U, 0xed113470U, 0x151ca3b8U, 0x47adfb74U, 0xb823fe26U, 0xfd79b25U, 0xffe7bb4U, 0xf29aaf44U, 0x72e8d83bU, 0x5f865406U, 0x1146a604U, 0x3da58f35U, 0x2397bd98U, 0xabdf9064U, 0xc34fbd8eU, 0xfa13906eU, 0x199dbda5U, 0x906e9056U, 0x17423d9aU, 0x5ea7d07eU, 0x2d12ddbdU, 0x751e206fU, 0x57aae5bdU, 0xc0218455U, 0x4bd47badU, 0xc5fbaf5bU, 0x80000000U, 0x40000000U, 0x60000000U, 0x30000000U, 0x18000000U, 0xdc000000U, 0xbe000000U, 0x63000000U, 0x25800000U, 0x30c00000U, 0xf1200000U, 0xf5b00000U, 0xb6f80000U, 0xafdc0000U, 0xbe6e0000U, 0x3a950000U, 0x60488000U, 0x5ca64000U, 0x1175a000U, 0x6dd8d000U, 0x736d8800U, 0x34110400U, 0x810c5200U, 0xe7445300U, 0x14e1fa80U, 0xd6119f40U, 0x1c0c72a0U, 0xc1c09b50U, 0x31a020b8U, 0xff4c85cU, 0xc499da3eU, 0x3c89572bU, 0x4b83a8b1U, 0x3bc0cc63U, 0x70a50800U, 0x97774433U, 0x82d9f202U, 0xc0ec8325U, 0xa3d4729eU, 0x37ac9b6dU, 0xff3620b1U, 0x15bdc850U, 0x993f5a2bU, 0xd57a1722U, 0x501e8891U, 0xacce5c44U, 0x70e52024U, 0xa4129015U, 0x890e2829U, 0x7340d439U, 0x5ee75a12U, 0xcf161710U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0x98000000U, 0x5c000000U, 0xba000000U, 0xd5000000U, 0x78800000U, 0x89c00000U, 0xa3600000U, 0x24900000U, 0xf1880000U, 0x6eec0000U, 0x207a0000U, 0x8cf30000U, 0x6e9e8000U, 0xb9204000U, 0xa5b1a000U, 0xf83af000U, 0x94d41800U, 0xdaa7c00U, 0xdbdec200U, 0xb584c100U, 0x6d451980U, 0xb0a217c0U, 0x62f101a0U, 0x35986bf0U, 0x4aa7c3a8U, 0x57f0aafcU, 0x5d18da0eU, 0x6b61bd2bU, 0x30975b80U, 0x9f8996eeU, 0xf5e93836U, 0xf3ffcc30U, 0x4eb7fa10U, 0x53bb0d12U, 0x1a92e3acU, 0x22891ae7U, 0x696be212U, 0xac3d7134U, 0x1ad621b9U, 0x86aedbf8U, 0xa0587b94U, 0xb3c326ddU, 0xb664802dU, 0x7c134001U, 0x484f2002U, 0x558ab00aU, 0x58edb833U, 0xc77c8c07U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0xb8000000U, 0x3c000000U, 0x6a000000U, 0xf9000000U, 0xe9800000U, 0x81c00000U, 0xbe00000U, 0x2e500000U, 0xcc80000U, 0xed2c0000U, 0xfa7a0000U, 0x3f330000U, 0xe3da8000U, 0xaa454000U, 0x8727a000U, 0x2367000U, 0xbc58f800U, 0x28821400U, 0x94436a00U, 0xc0214d00U, 0x6cb76b80U, 0x731bc7c0U, 0x5c2793a0U, 0x76b5d3f0U, 0x121ef9a8U, 0x39a79edcU, 0x25731206U, 0xdcf91913U, 0x947321bcU, 0x517abaddU, 0xd3b5202eU, 0xc19f3021U, 0x6965582aU, 0xf3176439U, 0x9d691215U, 0x3c5a191fU, 0xe881a1a5U, 0xb443fac1U, 0x7020801fU, 0xd4b6400eU, 0x4f1d202dU, 0x36233002U, 0x8fb7581bU, 0xfb986414U, 0xb861920fU, 0x2e90590bU, 0xf2ae8193U, 0x98bfcaecU, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0xe8000000U, 0x94000000U, 0x56000000U, 0xcb000000U, 0x74800000U, 0xdb400000U, 0x9a00000U, 0x78d00000U, 0x55480000U, 0x5aec0000U, 0xb13e0000U, 0xccf70000U, 0x7f5c8000U, 0xb2c5c000U, 0x2d666000U, 0xfeb05000U, 0xf7fc800U, 0x96d40c00U, 0x524d8600U, 0x246a8300U, 0x937a8980U, 0xc4d2c5c0U, 0xf74d41a0U, 0x17eac9d0U, 0x16bec7a8U, 0x1f374aecU, 0x6fb8ce12U, 0x5eb04f09U, 0xbf7befa7U, 0x5ed6d6ebU, 0x364ce012U, 0x9a6e9031U, 0xcc7b2802U, 0xe6569c26U, 0xe708ae30U, 0x6acb1f1bU, 0xb52ea7aeU, 0x43dc1ac9U, 0x4d85861bU, 0xbac6832fU, 0x296489b2U, 0x90b5c5c2U, 0x4879c198U, 0xc85309d5U, 0x800ea78dU, 0xc44c1afeU, 0x8f6d8623U, 0x37fa830eU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0xd8000000U, 0x9c000000U, 0x56000000U, 0xa1000000U, 0x7f800000U, 0x3c00000U, 0xb6e00000U, 0x34100000U, 0xf780000U, 0x279c0000U, 0x668a0000U, 0x54750000U, 0x732c8000U, 0x6fc04000U, 0x18e1a000U, 0x59179000U, 0x4efed800U, 0xc15e8400U, 0x65e80a00U, 0x94a1e500U, 0x14358180U, 0xbd040U, 0xc43359a0U, 0xa8095470U, 0x60315398U, 0xd20db15cU, 0x4f30522eU, 0x908a213bU, 0x6570ab9bU, 0x84ade563U, 0x9801a01cU, 0xbc07903fU, 0x606d81fU, 0xc9028409U, 0x3b820a07U, 0xc9c4e523U, 0x41e101a2U, 0xea979079U, 0x7338f9b9U, 0x92bbc477U, 0xe47b0bb6U, 0x6f1f7549U, 0x5bcbf824U, 0x2ed5540fU, 0x2a1d720eU, 0x7e4df135U, 0x5217d3afU, 0xb678f141U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xb0000000U, 0x18000000U, 0xd4000000U, 0xa2000000U, 0x43000000U, 0xbb800000U, 0xcdc00000U, 0xede00000U, 0xbf500000U, 0xc580000U, 0xa7bc0000U, 0xa1ee0000U, 0x61310000U, 0xa2c88000U, 0x78064000U, 0x2401e000U, 0x5a047000U, 0x27042800U, 0x1821400U, 0x5ac70a00U, 0xf461cd00U, 0x3196e380U, 0x5a3f2b40U, 0xd52acba0U, 0x40513f50U, 0x79dbc198U, 0xf7df27cU, 0xbe8ba21eU, 0x27259909U, 0x43300996U, 0xa1ca9649U, 0x23800020U, 0x59c00006U, 0xafe00005U, 0x4c500020U, 0xafd80010U, 0xbe7c0000U, 0xee0e0038U, 0x9d61000eU, 0x1510802dU, 0x127a401cU, 0x680fe032U, 0x8465703fU, 0x8994a82bU, 0xde385421U, 0xdf28ea3eU, 0xcf54bd33U, 0xb45a4bbbU, 0x23bb7f75U, 0x80000000U, 0x40000000U, 0x20000000U, 0x10000000U, 0x78000000U, 0x94000000U, 0xba000000U, 0xe9000000U, 0x7b800000U, 0x7d400000U, 0xa5200000U, 0xccb00000U, 0xa9080000U, 0xba2c0000U, 0xc19e0000U, 0x8170000U, 0xa1fb8000U, 0x95864000U, 0x4e45e000U, 0x7a3b000U, 0xa276b800U, 0x9d6a8400U, 0xfdbfde00U, 0xf726cf00U, 0x89b4ee80U, 0xdc8c58c0U, 0x846a56a0U, 0x8e3adcd0U, 0x566388a8U, 0x6a9713d4U, 0xaf3ae636U, 0x91e60b31U, 0x61d0d0b8U, 0xdd1e27dbU, 0xdd3800eU, 0xb31a4010U, 0x7ed3e011U, 0x3198b012U, 0x133803U, 0x7dfbc427U, 0xd381be1dU, 0xf1433f25U, 0xbb27b6acU, 0xf7b56cd6U, 0xd78b3082U, 0x92ea97c5U, 0x4afeb811U, 0xf3068439U, 0xc281de22U, 0x5ec1cf38U, 0x5c676eadU, 0xab9618d7U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x70000000U, 0x38000000U, 0x2c000000U, 0xa000000U, 0x69000000U, 0x45800000U, 0xf5c00000U, 0x9ae00000U, 0x21300000U, 0x79480000U, 0xcdac0000U, 0x3b9a0000U, 0x58510000U, 0xebe8000U, 0x62854000U, 0x17452000U, 0x4da3f000U, 0xc91f800U, 0x5d8f400U, 0xf073aa00U, 0xe7ef0500U, 0xb5be3880U, 0xd205b8c0U, 0xf507c0a0U, 0x17814cf0U, 0xc0c66ab8U, 0xed6349ecU, 0x91f4d236U, 0xac2eb127U, 0x705ab294U, 0x9db44dcdU, 0x410c803dU, 0xd688401cU, 0xd649a02dU, 0x5b2bb033U, 0xbad85827U, 0x2ef3440dU, 0x72abf234U, 0xe51c4137U, 0xcd15ca82U, 0x5e19f9c0U, 0x7d920a0eU, 0xbc58b525U, 0x27b46083U, 0x700bfce5U, 0xcf08b29aU, 0x11894dc6U, 0x84c8002bU, 0xd46c0022U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x30000000U, 0x98000000U, 0xc4000000U, 0xd6000000U, 0xe3000000U, 0xb4800000U, 0x19400000U, 0x2c600000U, 0xa5900000U, 0xe6b80000U, 0x49dc0000U, 0x88ce0000U, 0x7f330000U, 0x768e8000U, 0xd1d44000U, 0xb9596000U, 0x78d5000U, 0x10500800U, 0x579fcc00U, 0xb62cd600U, 0x18e1fd00U, 0xfcd67d80U, 0x6adace40U, 0xdc4875a0U, 0xf6760250U, 0xf2ea2388U, 0x2843bf5cU, 0x4de53e2eU, 0x7b54212dU, 0xcf1d43bbU, 0x856def45U, 0xf583b61eU, 0x40c3ad1fU, 0x6a6f5bbU, 0xc232425bU, 0xd0b4399U, 0x5612ef5cU, 0x4d7b362dU, 0x97f8ed00U, 0xd9bf15a5U, 0xaf585242U, 0x48caba9U, 0x34d4335aU, 0xe6de881eU, 0xc64b8c10U, 0xaf75b60dU, 0x2f6cad1fU, 0x748675aaU, 0xf945024fU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x50000000U, 0xc8000000U, 0xa4000000U, 0xca000000U, 0x79000000U, 0x68800000U, 0x49400000U, 0xf2200000U, 0x8d300000U, 0xada80000U, 0x2e8c0000U, 0xcf3e0000U, 0x51d10000U, 0x6c7f8000U, 0x2af7c000U, 0xf1cbe000U, 0xf21e3000U, 0x8b643800U, 0xa7159c00U, 0xac9a6600U, 0xbd200f00U, 0x9ab31a80U, 0x2b69a1c0U, 0xd66922a0U, 0x84ed3dd0U, 0xccacc498U, 0x6a0af2c4U, 0x87c3e2aU, 0x40f1632dU, 0x38cf24b8U, 0x298c2e3U, 0xae26063aU, 0x3b35ff35U, 0x92aac2acU, 0x10f0dfbU, 0x95fefc9fU, 0x5f326ec3U, 0xf8afd80eU, 0xc80bac26U, 0x657e5e13U, 0x7a75933aU, 0x64897ca8U, 0xf639aef6U, 0xd9523826U, 0x75389c08U, 0x10d3e618U, 0xd8facf0bU, 0x95b17a91U, 0xdced51c7U, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0x38000000U, 0x4000000U, 0x12000000U, 0xd000000U, 0xe7800000U, 0xfec00000U, 0x7c600000U, 0xc5700000U, 0x3580000U, 0xba3c0000U, 0xe4ce0000U, 0x6f550000U, 0xc60a8000U, 0x35354000U, 0x44786000U, 0xa8ee7000U, 0xcd055800U, 0xc7870400U, 0xeec00200U, 0x3461f900U, 0xf973b680U, 0x155a5e40U, 0xa538eea0U, 0xe485a50U, 0x76126cb8U, 0x44ace34cU, 0x8c21ba36U, 0x8254cd0dU, 0x118a0c92U, 0x93f2935eU, 0x4c1ce213U, 0x479fc92dU, 0xc75c0ebaU, 0x883a6a51U, 0xf9cbd488U, 0xc0d5d771U, 0x4ce001aU, 0x5f55000bU, 0x9e0a8027U, 0x4135401aU, 0x6e78600cU, 0xa1ee700fU, 0x3885582eU, 0x34470404U, 0x75200206U, 0xfd1f903U, 0x864bb698U, 0x6a165e6bU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xb0000000U, 0x28000000U, 0x8c000000U, 0xfe000000U, 0x61000000U, 0x82800000U, 0xc5400000U, 0x64e00000U, 0x32700000U, 0xc3880000U, 0x6a6c0000U, 0x549a0000U, 0xbb570000U, 0xb5e8000U, 0x7ef5c000U, 0x8fcea000U, 0xa00bd000U, 0xedaf1800U, 0x553eac00U, 0x5dc7d600U, 0xd2a12900U, 0x5b123680U, 0x4f3fecc0U, 0x2ec72ea0U, 0xdf2640f0U, 0xe5d67888U, 0xc81ea9dcU, 0xcf10ee02U, 0xd53d953fU, 0x9dc6589dU, 0x72a0b9d7U, 0xeb115635U, 0x6738e93aU, 0xa2c696aeU, 0x21233cc9U, 0x84d6b6a3U, 0x4a9d2cf4U, 0xa570e8bU, 0xb1d850fcU, 0xafb7c085U, 0xb12bd5e5U, 0x81782010U, 0x33a21032U, 0x1993b817U, 0x2a7e7c1eU, 0xfa244e16U, 0xc5514521U, 0xaa5fc08eU, 0x5c77d5d2U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x50000000U, 0x58000000U, 0x34000000U, 0x5a000000U, 0x5b000000U, 0xd0800000U, 0x19400000U, 0xf6a00000U, 0xe3d00000U, 0x41d80000U, 0xb07c0000U, 0xa52e0000U, 0x70b10000U, 0x83ef8000U, 0x55d34000U, 0x34dbe000U, 0x81fab000U, 0x67ed2800U, 0x17d54c00U, 0xbbdab600U, 0x5b786b00U, 0x7dad5980U, 0x5f49140U, 0x1b4e71a0U, 0xb700dd50U, 0xfe834798U, 0xf847f644U, 0x2d23fe0eU, 0x7214d709U, 0x9a3927b8U, 0xff0f064fU, 0x5c22b614U, 0x51946b0dU, 0x8ffb59a7U, 0x76e9917cU, 0x2457f1afU, 0x161e9d4fU, 0xb699278aU, 0x7df065aU, 0x2d7ab623U, 0xa8a86b2aU, 0x84755981U, 0xd188915eU, 0xbc6071b0U, 0xa8b1dd51U, 0xf7ecc794U, 0xefd4b643U, 0x3fd81e1fU, 0x97e671cU, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0x28000000U, 0xfc000000U, 0x72000000U, 0x31000000U, 0x65800000U, 0x27400000U, 0xe600000U, 0x57100000U, 0xfda80000U, 0x40cc0000U, 0x2b5e0000U, 0x8350000U, 0x63da8000U, 0x8f5c000U, 0x33ff2000U, 0xb8023000U, 0xe4047800U, 0xc6037400U, 0xcf07fe00U, 0xe80b500U, 0x8fc59980U, 0x3ea59ac0U, 0x4f37e1a0U, 0xc15feed0U, 0xcd349fb8U, 0x985f9bccU, 0x34b4a632U, 0xbd1df133U, 0x23d01f8eU, 0x738f5befU, 0x8b39062fU, 0xc26012aU, 0x92f5479eU, 0xdefb1fccU, 0xbf80000fU, 0xaa400023U, 0x79e00032U, 0x31500017U, 0xbe48003eU, 0xcc9c0026U, 0xaa960001U, 0x2ee90037U, 0xd0ac800bU, 0x674cc004U, 0x751ba00fU, 0xefd2f00bU, 0x4989d80eU, 0x3638842fU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x50000000U, 0x18000000U, 0xac000000U, 0x1e000000U, 0x9b000000U, 0x3f800000U, 0x7a400000U, 0x91a00000U, 0xe7500000U, 0x98180000U, 0x84bc0000U, 0x136a0000U, 0x8cb70000U, 0x2ee98000U, 0x5bf34000U, 0x5fc92000U, 0x3645000U, 0x1d35c800U, 0xe7a81400U, 0xb1d51600U, 0x38d89300U, 0x3bd8dd80U, 0x685efb40U, 0xac1f15a0U, 0xf6bdef70U, 0x36698388U, 0x78313c64U, 0x7329fe0eU, 0x1c14d70fU, 0x373803a9U, 0xe72e7c59U, 0x3e12de2eU, 0xa3b8723U, 0xbfae4b84U, 0x7dd22855U, 0xd6df682bU, 0xe8d8041dU, 0xe3d87e29U, 0x645b9709U, 0xe21b23a0U, 0x75bd2c61U, 0xa5ee961bU, 0x1c70d31aU, 0x798a7d9aU, 0xc4c2eb44U, 0xd5607dbaU, 0xf235eb76U, 0xca29fd87U, 0x1e96ab58U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0xe8000000U, 0x74000000U, 0x8a000000U, 0xd7000000U, 0xcf800000U, 0x5bc00000U, 0x2e600000U, 0x76d00000U, 0xbdd80000U, 0x9abc0000U, 0xaeee0000U, 0x28710000U, 0xe4ee8000U, 0x5f77c000U, 0xbb6d6000U, 0x9cb3b000U, 0x908c800U, 0x1460d400U, 0xe9d03a00U, 0x9659c100U, 0xd37a8380U, 0xcb8c4740U, 0x6f244ba0U, 0x5ff19350U, 0xf32cf198U, 0xf712924cU, 0x7cbb9222U, 0x2feba511U, 0x2ef4f1a0U, 0x5dae9274U, 0xda55920bU, 0x39aa52eU, 0xa81a71a2U, 0xa1d95262U, 0x24b8f20dU, 0x13e91520U, 0x40f2b995U, 0x98a98658U, 0x5ed0c814U, 0x69dcd420U, 0x80be3a2dU, 0xe1e8c10eU, 0x7bf403b3U, 0x412b8758U, 0x2c112bb4U, 0xd53e2375U, 0xb52a39b1U, 0xe6134679U, 0x80000000U, 0x40000000U, 0x20000000U, 0x30000000U, 0x58000000U, 0x84000000U, 0xb2000000U, 0x95000000U, 0xd8800000U, 0xb0400000U, 0xb3a00000U, 0x63d00000U, 0xfc80000U, 0xf76c0000U, 0xf73e0000U, 0x13370000U, 0x283a8000U, 0xaab64000U, 0x8afd6000U, 0x88567000U, 0x680e9800U, 0x45083c00U, 0x498c4e00U, 0x3ce8b00U, 0xc96d0980U, 0x1c39e9c0U, 0xb591a0U, 0xbbfad5d0U, 0xd2d55fa8U, 0x15491edcU, 0xaa29b63eU, 0x281bc73dU, 0x2aa35fb2U, 0x85521ec8U, 0x548d362cU, 0x574a8738U, 0x72cbfbeU, 0x649e2eddU, 0x40e0ce2fU, 0x7ff3cb38U, 0xd9dce9b6U, 0xcfc2d9c8U, 0xe62e9b4U, 0x98b5d9ceU, 0x5ff869bdU, 0x70d399edU, 0xe84d09b9U, 0xaea9e9f5U, 0xae5d91a9U, 0xbe06d5f7U, 0xab035f97U, 0x33821ef5U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0x68000000U, 0x94000000U, 0x26000000U, 0x77000000U, 0x2800000U, 0x91400000U, 0xfea00000U, 0x66100000U, 0x41980000U, 0x8dbc0000U, 0xc2ea0000U, 0x21d70000U, 0x687b8000U, 0xd20ac000U, 0x9fe56000U, 0x80b5d000U, 0x6b8ba800U, 0x6255c00U, 0xe256c600U, 0x24bbfb00U, 0x8b6e4780U, 0xa0142540U, 0x469e6fa0U, 0x573bb970U, 0xbfadc988U, 0x5759274U, 0xcb682612U, 0xc014eb11U, 0xf6988fbbU, 0x2f38a97cU, 0x43a901b3U, 0xb7721e6cU, 0x9a6ec83eU, 0xb5908c14U, 0x655d6e1dU, 0x40dea73fU, 0xdb18818cU, 0x90ffde4aU, 0x56482813U, 0xfac39c16U, 0x8661a61aU, 0x9752b25U, 0x616c6f92U, 0xdd10b94aU, 0x491c498cU, 0x11f8526eU, 0xebcec622U, 0xed07fb0cU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xd0000000U, 0x28000000U, 0xc4000000U, 0xce000000U, 0xf5000000U, 0x6b800000U, 0x80c00000U, 0x10a00000U, 0x7d700000U, 0x3c680000U, 0x1f4c0000U, 0xfefa0000U, 0xc0350000U, 0xa50f8000U, 0xdb1cc000U, 0x1023e000U, 0x8b301000U, 0xe38e7800U, 0xec594400U, 0x72459200U, 0x31e68f00U, 0x36173080U, 0x1f39b9c0U, 0x9d16c8a0U, 0x89bc3df0U, 0x8250ba98U, 0x2fdaa2c4U, 0xf681f212U, 0xf465f35U, 0x6e60a881U, 0x60d5edf8U, 0xc69aa283U, 0xa9e336dcU, 0xca13f835U, 0xdd3c8406U, 0xb213f223U, 0xf13f5f3dU, 0x5815288dU, 0x1a3c2de4U, 0xee96c290U, 0x357fe6ecU, 0xb0f66014U, 0xada9d01fU, 0x9a6a182cU, 0xe499432U, 0x6b7a0a29U, 0x4df6db2eU, 0x32295a96U, 0x2cafb2ebU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x90000000U, 0x8000000U, 0xc000000U, 0x32000000U, 0xc5000000U, 0x7e800000U, 0x60c00000U, 0xd2600000U, 0x8db00000U, 0x6e80000U, 0x60c0000U, 0x897a0000U, 0xb0f30000U, 0xd9cb8000U, 0xc99c000U, 0xa106a000U, 0x3086b000U, 0x2fc25800U, 0xfde08c00U, 0xa5f6fa00U, 0x4f4f9100U, 0xd05a4080U, 0xd96515c0U, 0x7c3398a0U, 0x69ac59f0U, 0x6c2bc2a8U, 0x456978d4U, 0x6c49da2aU, 0xbddfe117U, 0x8c273886U, 0xdf15e9d6U, 0xe9381ab1U, 0x155334daU, 0x8d9a000fU, 0x183001eU, 0x17438020U, 0xde25c01dU, 0x6a14a019U, 0x2fb9b03cU, 0xe193d806U, 0x69fa4c07U, 0x7733da17U, 0x982ce118U, 0x36cb8a0U, 0x2f4c29d2U, 0xa05eba89U, 0x616584fdU, 0xe830582aU, 0x5faf8c21U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xf0000000U, 0xa8000000U, 0x24000000U, 0x92000000U, 0xc9000000U, 0xca800000U, 0xf9c00000U, 0x36a00000U, 0xf2500000U, 0xbce80000U, 0x4ccc0000U, 0x315a0000U, 0x40170000U, 0xd0c8000U, 0x1bfbc000U, 0xfc41e000U, 0x96e3f000U, 0x4ab17800U, 0x815e4c00U, 0x8817b200U, 0x790b9f00U, 0xd1fa3180U, 0xb9465cc0U, 0xea67c9a0U, 0xe873d0f0U, 0xb4799b88U, 0x4907bfccU, 0xa80d222U, 0x59c4af05U, 0xc6a629a6U, 0x5a5020c7U, 0x98e8e39cU, 0xdec9f3f5U, 0xf85f6013U, 0x8a93303cU, 0xf4ce1812U, 0x2d5d7c24U, 0xe11aa20U, 0x2a0ae304U, 0x6799bb6U, 0xb007bfc9U, 0xc800d22fU, 0x7404af01U, 0xca0629a4U, 0x450020d0U, 0x7c80e3a6U, 0xa2c5f3e1U, 0x35256027U, 0xc1143038U, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0xf8000000U, 0xdc000000U, 0x32000000U, 0x53000000U, 0xd2800000U, 0x62c00000U, 0xe1e00000U, 0x85100000U, 0xf3a80000U, 0x44cc0000U, 0x7d1e0000U, 0x86550000U, 0xf2098000U, 0xdaf84000U, 0x2647a000U, 0x7e21b000U, 0xb7766800U, 0x85fadc00U, 0x1ec23a00U, 0xe3e7fd00U, 0x5e103980U, 0x152836c0U, 0x300fd1a0U, 0x21faaad0U, 0xb0c24bb8U, 0xe2e0e7d4U, 0xcf921a06U, 0x5d6b0d23U, 0x6f2871aaU, 0x770b1ae7U, 0x957c23a6U, 0x87063bebU, 0x94862038U, 0x47c5f039U, 0x9e67c816U, 0xac526c1bU, 0x2d0bd229U, 0xa27c6132U, 0xdb8223a7U, 0x87433bcaU, 0xdfa7a006U, 0x7731b021U, 0xeede6804U, 0x5e36dc3cU, 0x7b5c3a3eU, 0x8872fd01U, 0xad79b992U, 0x7b0076dfU, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0xb8000000U, 0x54000000U, 0xf2000000U, 0xb7000000U, 0x3e800000U, 0x56c00000U, 0x11e00000U, 0xe6500000U, 0x86e80000U, 0xbb8c0000U, 0xec1e0000U, 0x9d950000U, 0xd2898000U, 0xe39a4000U, 0xc0d1e000U, 0xb429f000U, 0x906f0800U, 0x41489c00U, 0x3bfc9a00U, 0x2ec37d00U, 0x65e36380U, 0x645326c0U, 0x99edeba0U, 0x690dfad0U, 0x1cde91b8U, 0xc97277d4U, 0xbd5b7a16U, 0xd338d01U, 0x3c7beb8aU, 0xaf84fafcU, 0x6d4111bdU, 0xaea137fdU, 0x8ff51a0fU, 0x9f993d15U, 0x9ed2839cU, 0xc52ad6d3U, 0xfbeae3acU, 0x260966d8U, 0x165c0ba5U, 0x7db40addU, 0xa3b999a2U, 0x81e6ebdfU, 0x1e51e02fU, 0xb2e9f03eU, 0x598f0805U, 0xe3189c16U, 0xf7149a25U, 0x764f7d09U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x30000000U, 0x88000000U, 0xb4000000U, 0x22000000U, 0xdf000000U, 0x85800000U, 0xc6c00000U, 0xe2e00000U, 0x51d00000U, 0x4d80000U, 0x51bc0000U, 0x1aa0000U, 0xe110000U, 0xe6bc8000U, 0xc02ac000U, 0x2d26000U, 0x5f5df000U, 0xbe7cc800U, 0xabcc0400U, 0x4b840200U, 0xf7c53d00U, 0xc6628780U, 0x6b970b40U, 0xd07acfa0U, 0xcacdcf70U, 0xd706adb8U, 0xf184027cU, 0x84c4621aU, 0xde5cd11U, 0x5c50cfb2U, 0x761ccf56U, 0x915a2dabU, 0x8f7ec25bU, 0x8f4e0229U, 0x71c43d2eU, 0x236607a2U, 0x5d11cb50U, 0xbd3aafb3U, 0x2fed3f69U, 0xa8b4e5a9U, 0x1acfc65dU, 0xaf04803aU, 0xad86c010U, 0x22c0601dU, 0x78e0f01bU, 0xb2d24837U, 0x175bc43cU, 0x6a78e224U, 0xb9cf0d2cU, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0x88000000U, 0xec000000U, 0xa000000U, 0x85000000U, 0x7800000U, 0xb2c00000U, 0xbbe00000U, 0x9900000U, 0x5a380000U, 0x345c0000U, 0xde0e0000U, 0x76570000U, 0x6a5c8000U, 0x550ec000U, 0xc2d2a000U, 0x28187000U, 0xbaa99800U, 0x23e18400U, 0xfd91a200U, 0xe439c500U, 0x2f5bbd80U, 0x328e7640U, 0xa016a5a0U, 0xebfd3250U, 0xd73ba7a8U, 0x9fdb876cU, 0x46cd020aU, 0xb8b6b517U, 0xec4ea5a8U, 0x51f13266U, 0x476da781U, 0x7a808766U, 0x91478205U, 0xcf237523U, 0xcd768593U, 0x592c8264U, 0x37241f8fU, 0xe970b358U, 0x9f299810U, 0x48218424U, 0xe3f1a218U, 0xc669c52bU, 0x4b03bd9cU, 0xd4827642U, 0x9240a5a3U, 0x97a63276U, 0x853127b0U, 0x338e4777U, 0x80000000U, 0x40000000U, 0x20000000U, 0x10000000U, 0xd8000000U, 0x34000000U, 0xee000000U, 0x4d000000U, 0x79800000U, 0xf8c00000U, 0xe7600000U, 0xe8700000U, 0x92b80000U, 0x665c0000U, 0x5dee0000U, 0xd0b70000U, 0x15db8000U, 0xbe2b4000U, 0x751e000U, 0x5aeb1000U, 0x92313800U, 0xcd9a9400U, 0x260c0200U, 0x65836100U, 0x8ac76680U, 0x98656940U, 0xcef5dea0U, 0x5cf8bd50U, 0x977e3ca8U, 0x70bbcc54U, 0x815de21eU, 0x6f687119U, 0xe0f65e85U, 0x71fffd5aU, 0xdef9dcb3U, 0x407bdc70U, 0x8a395a34U, 0x5d1ea503U, 0xd1483cbdU, 0x2320cc54U, 0x2506227U, 0x8f683119U, 0x90f23e9bU, 0x99f8ad6bU, 0x22fa84a2U, 0x427d1854U, 0x1d3b802eU, 0x879b402eU, 0x1d09e03fU, 0x45071026U, 0xf5873829U, 0x12c19433U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x50000000U, 0xf8000000U, 0xc4000000U, 0x56000000U, 0xa5000000U, 0x18800000U, 0x98400000U, 0x9e200000U, 0x47500000U, 0xfc80000U, 0xa36c0000U, 0xab7a0000U, 0xa1130000U, 0xc8ed8000U, 0x4eb84000U, 0x9ff16000U, 0xd9dc5000U, 0x60063800U, 0xb0041c00U, 0x8801ce00U, 0x6c06e700U, 0x6a025180U, 0x370579c0U, 0xeb81e9a0U, 0x25c525f0U, 0x1ee347a8U, 0x413092e4U, 0xd6b8ae16U, 0xebf6b715U, 0x7de69a3U, 0xa90265ccU, 0xc285a78dU, 0x274782ceU, 0x19a2761cU, 0x896bb3aU, 0x2628ff94U, 0x9dccefaU, 0x58000005U, 0x54000039U, 0x8e000000U, 0x31000008U, 0xb6800020U, 0xf940000bU, 0xd0a0003cU, 0x7a100019U, 0x89680032U, 0x7c7c0027U, 0x3a92001fU, 0x452f0010U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xd0000000U, 0x58000000U, 0xfc000000U, 0x2a000000U, 0xfd000000U, 0x72800000U, 0x92400000U, 0xc0e00000U, 0xe8700000U, 0x81680000U, 0x4d0c0000U, 0x343e0000U, 0x44310000U, 0xa28b8000U, 0x44ff4000U, 0xae95a000U, 0xa6197000U, 0x5fe4d800U, 0x63f36c00U, 0x87aace00U, 0x40ad3100U, 0x372fae80U, 0x1befd3c0U, 0xeb48f6a0U, 0x9adfffd0U, 0x57419898U, 0xde66bee4U, 0xe8376e0eU, 0x9088411bU, 0xa5fd76a4U, 0x2611bff4U, 0x915fb8a0U, 0x11808ef4U, 0x33c6163eU, 0x3b225d05U, 0x975360a2U, 0x103fe2c6U, 0xd232d821U, 0x958e6c28U, 0x1b7f4e2bU, 0x1653713cU, 0x8b98eb4U, 0x5d75e3c8U, 0xf7ef8eaeU, 0x3948e3e6U, 0xabda0eb4U, 0x87c6a3e3U, 0x15242ea0U, 0x8c5093efU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0xb8000000U, 0x6c000000U, 0x22000000U, 0x83000000U, 0x93800000U, 0xdfc00000U, 0xbaa00000U, 0x58300000U, 0x65780000U, 0xa75c0000U, 0x172a0000U, 0x1350000U, 0x39fc8000U, 0x991b4000U, 0xf9492000U, 0xa422b000U, 0x9572e800U, 0x409ed400U, 0x1895a00U, 0x9b020700U, 0x6f868280U, 0x15c72b40U, 0x5da2eaa0U, 0x3db7bf70U, 0x77be1098U, 0x2f7c485cU, 0x805b5a36U, 0x92ab0707U, 0xa3f0029eU, 0x9d96b57U, 0x626f4aa2U, 0x48d24f7cU, 0xbd2fd89aU, 0x96352c5dU, 0x47c6825U, 0x57dc940fU, 0xeb6efa2cU, 0xdc52f728U, 0xb76bca90U, 0x86550f43U, 0xb86cf897U, 0x87d29c7eU, 0x5caa001eU, 0xc2f5000bU, 0xf95c803fU, 0x9e2b4017U, 0x95b1200aU, 0x33beb007U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0xe8000000U, 0x1c000000U, 0xc2000000U, 0xf000000U, 0x38800000U, 0x6f400000U, 0x6b600000U, 0x5cb00000U, 0x23080000U, 0xe3ec0000U, 0x6a9e0000U, 0xe2b30000U, 0x9e0b8000U, 0xc6ac000U, 0x595d2000U, 0xd092b000U, 0x78dd0800U, 0x86556c00U, 0xc17be600U, 0x65415500U, 0xa862cc80U, 0xee354ac0U, 0xcf4a44a0U, 0x9a09e6d0U, 0x4a6f0288U, 0x505cc3f4U, 0x4113e632U, 0x161d5533U, 0x6bf4cca2U, 0x6c6a4ae0U, 0x295fc4a4U, 0x89026cfU, 0x1cd9a2acU, 0xb054b3fbU, 0x107bce2eU, 0x90c68907U, 0xf0a422aaU, 0xd29173f7U, 0x97db6e11U, 0x8ed1f90cU, 0xd6398aa7U, 0xfa236fe4U, 0x2ad52029U, 0x3eb035U, 0x1b230828U, 0xa7566c3cU, 0xacf86605U, 0xf987951cU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x90000000U, 0x68000000U, 0xc4000000U, 0xc6000000U, 0x6b000000U, 0xa1800000U, 0x32400000U, 0x55200000U, 0xbff00000U, 0xa5080000U, 0x86ac0000U, 0x9a0000U, 0x8bf30000U, 0x7b0b8000U, 0xf1aac000U, 0x5b1be000U, 0xb8b05000U, 0xe6a8c800U, 0x709aa400U, 0x53f42600U, 0x470a6700U, 0x9bac0c80U, 0x321fdac0U, 0xb43544a0U, 0x1e6cbef0U, 0xb67902a8U, 0x8b6049d4U, 0x8d42632U, 0x7fa6725U, 0x11240ca3U, 0xb9f3dacfU, 0xee0f44a3U, 0xb72fbed7U, 0x5ada82a4U, 0x1ad689edU, 0x2fdc626U, 0x3fa53727U, 0x7c35449fU, 0x8a6cbee3U, 0x38790294U, 0xb46049e8U, 0x754262cU, 0x9aba671dU, 0x23840cb7U, 0x5f43dad9U, 0xbfa7448cU, 0xbc33bed4U, 0xaa68828dU, 0xa87989fcU, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0x48000000U, 0x4c000000U, 0x7a000000U, 0xa1000000U, 0x3800000U, 0x15c00000U, 0x49600000U, 0x89700000U, 0x57d80000U, 0x963c0000U, 0x500e0000U, 0x7cf70000U, 0xf91c8000U, 0xadd8c000U, 0x7739a000U, 0x738cf000U, 0x99343800U, 0xf8780400U, 0x68af1a00U, 0x5ae08900U, 0x44b35680U, 0xcabe9a40U, 0x914deea0U, 0xd8d55e50U, 0x7e49d4a8U, 0x6456e76cU, 0x2f0b9a3aU, 0x5874493fU, 0x5c5cf684U, 0xeff96a47U, 0x936b56acU, 0x1c829a6eU, 0xe143eea4U, 0x54225e63U, 0xcf5554bdU, 0x858e277dU, 0x22323a37U, 0x8af8b90fU, 0xc6e8cebbU, 0x2416e53U, 0xb2a44c89U, 0xcf121364U, 0xf228b834U, 0x8a0c40fU, 0xe16ba28U, 0x21ac7906U, 0xa5676e8cU, 0x43769e52U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xf0000000U, 0x78000000U, 0x4c000000U, 0xbe000000U, 0x2d000000U, 0x95800000U, 0xcf400000U, 0x7aa00000U, 0xd9700000U, 0xf380000U, 0xeb1c0000U, 0x39aa0000U, 0xb0f10000U, 0xa67a8000U, 0x60bb4000U, 0x435c2000U, 0x698d5000U, 0x50407800U, 0xdc217400U, 0x3eb69e00U, 0xa75ad300U, 0xb38a5c80U, 0x67453340U, 0x1ea2a4a0U, 0xc3720770U, 0x58389ab8U, 0xd99fc44cU, 0xbc6c1e26U, 0x391931fU, 0x726e7ca9U, 0x96946364U, 0xcbe8dcb4U, 0x17d2735bU, 0xe44c84acU, 0x17225742U, 0x9a30629eU, 0xab98f060U, 0xef6e201aU, 0xdb105034U, 0xd8a8f828U, 0x5b773419U, 0x243a3e3dU, 0x7f9dc333U, 0x2d6c84baU, 0x50125741U, 0xdc28629dU, 0xc7b4f067U, 0xf0dc2035U, 0xf7cd5033U, 0x80000000U, 0x40000000U, 0x20000000U, 0x90000000U, 0x18000000U, 0x94000000U, 0xe000000U, 0x13000000U, 0x71800000U, 0x3400000U, 0x31a00000U, 0x20100000U, 0x27480000U, 0x726c0000U, 0xffbe0000U, 0x21970000U, 0xcc0f8000U, 0x7fc94000U, 0xcdaee000U, 0x97db1000U, 0x46e7c800U, 0xefb42400U, 0xbc5aee00U, 0x38a68b00U, 0xc961f80U, 0x668f73c0U, 0xa10857a0U, 0xf54917d0U, 0x836dd9a8U, 0xb73accf4U, 0xc6556e2eU, 0x106fcb11U, 0x86b8ff8dU, 0xe51463c5U, 0xb1cf9fb9U, 0xbead33f1U, 0x565f37bbU, 0xcda047f8U, 0x521571b7U, 0x64bb8c5U, 0x2e92817U, 0x1c7f3409U, 0xebf52614U, 0xb27eaf0eU, 0x28f2f1aaU, 0xfbfef8dbU, 0x2fb1c82bU, 0xdc5f2401U, 0x88a36e23U, 0x8494cb28U, 0xea897fb2U, 0x3b0a23caU, 0x80000000U, 0x40000000U, 0xa0000000U, 0xf0000000U, 0x78000000U, 0x34000000U, 0x22000000U, 0x6f000000U, 0x43800000U, 0xe8400000U, 0x8f200000U, 0x32b00000U, 0x38480000U, 0x4dec0000U, 0x799e0000U, 0x5a330000U, 0x89888000U, 0xd18d4000U, 0x558be000U, 0xaf887000U, 0x48f4800U, 0x1d0f3400U, 0xae48c600U, 0x40eed700U, 0xf51e2680U, 0x1f2bac0U, 0x96efeea0U, 0x581fced0U, 0x7d724888U, 0xb52b29ecU, 0x737e4616U, 0xd6e09721U, 0xf2d546beU, 0x2a5b8aeaU, 0x495546a6U, 0xb61b8afcU, 0x447546b3U, 0x1bab8ac1U, 0x47bd46abU, 0x8a078ac4U, 0x930346adU, 0x8d848af3U, 0x6143c6bcU, 0xf9a5caf1U, 0xc2762684U, 0x3eaebac5U, 0x7739ee95U, 0xbfc0cec7U, 0xf564c882U, 0xa9569f5U, 0x8d7d2608U, 0xc7e5a72aU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0xd8000000U, 0xe4000000U, 0x3e000000U, 0x13000000U, 0x8b800000U, 0x19c00000U, 0x56a00000U, 0x27700000U, 0x6a880000U, 0xceac0000U, 0x4e9a0000U, 0x37f30000U, 0x14ce8000U, 0x93ca4000U, 0x1e4a6000U, 0xe08b1000U, 0xebacc800U, 0xfa197400U, 0x97b76a00U, 0x4aa8b700U, 0xa09f4880U, 0xecf78ec0U, 0x934f00a0U, 0x880bbaf0U, 0x81ee8aa8U, 0x617d5dfcU, 0x63ea1eU, 0xf051f705U, 0xb13ba8b1U, 0x6606def1U, 0x3701a8bbU, 0x9585decbU, 0x3ac72890U, 0x5239ef7U, 0xdab748b3U, 0x22b8ef9U, 0xfadd008dU, 0xaf94baf6U, 0xe09a0abfU, 0xcf41dddU, 0x834f0a37U, 0x600ca71fU, 0xbdef00a4U, 0xbb7bbaefU, 0x2d668abfU, 0x68d15de8U, 0x2379ea2bU, 0x2962f73aU, 0x80000000U, 0x40000000U, 0x20000000U, 0x10000000U, 0x78000000U, 0x34000000U, 0x86000000U, 0x53000000U, 0xb800000U, 0xc7c00000U, 0xd8e00000U, 0x80f00000U, 0x69180000U, 0xab7c0000U, 0x3ace0000U, 0x68770000U, 0x8d5b8000U, 0xd85e4000U, 0xc0dce000U, 0x2c995000U, 0x23b88800U, 0x3aab400U, 0xde411a00U, 0x9a257500U, 0x5891b680U, 0x1ad9c40U, 0x2344bea0U, 0xaea26850U, 0x36d4c4a8U, 0xb38b0d54U, 0x17d49a36U, 0xd0c3519U, 0xb896d6b7U, 0x71aa8c5dU, 0x6b40d69dU, 0xf2a18c78U, 0xfcd556bdU, 0x5288cc51U, 0xc9523698U, 0x924fdc62U, 0xac365eb5U, 0xee7c385dU, 0x5a4fcca2U, 0xb033f97aU, 0x47f603eU, 0xab4b103bU, 0x16b26802U, 0xaf38e41bU, 0x39ec1210U, 0xda668115U, 0x95b7cc8bU, 0xbcbff965U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x70000000U, 0x18000000U, 0x4000000U, 0x7a000000U, 0x1f000000U, 0x14800000U, 0x85400000U, 0xfd200000U, 0xfe300000U, 0xd9980000U, 0x21fc0000U, 0xe2ea0000U, 0xa5410000U, 0x2d268000U, 0xf6304000U, 0xb59b6000U, 0x47ff3000U, 0x83e90800U, 0xd4c28c00U, 0xa3e2f600U, 0x9ad32700U, 0x33cf5280U, 0x9d71e440U, 0x85bd3aa0U, 0xce4c5870U, 0xc5b6c4b8U, 0xf05df36cU, 0x4d9b603eU, 0xf3ff302dU, 0x81e90800U, 0xbfc28c1aU, 0xd562f61dU, 0x4932727U, 0xa06f52a4U, 0xf901e459U, 0xb5853aacU, 0x94c05866U, 0x3e4c489U, 0x8ad0f372U, 0x5bcfe03bU, 0x81727031U, 0xfbbee81eU, 0xab4cfc1fU, 0xce361e1bU, 0x619edb3eU, 0x35ffcc81U, 0xf0ef7f5bU, 0xa6419628U, 0x47a01712U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x70000000U, 0x88000000U, 0x6c000000U, 0xa2000000U, 0x4f000000U, 0x35800000U, 0x33400000U, 0x3a00000U, 0x6100000U, 0x98980000U, 0x187c0000U, 0x75ce0000U, 0x57430000U, 0x8da48000U, 0x4b12c000U, 0x921ca000U, 0x96be3000U, 0x292a0800U, 0xf0f5c400U, 0x5c2ece00U, 0xfe76eb00U, 0xccef1780U, 0xb797d940U, 0xf5d9bfa0U, 0xaedc2d50U, 0x9d5d7988U, 0x8f1f024cU, 0x243ca02aU, 0xe3ee3017U, 0x12120822U, 0x9e99c414U, 0x3978ce07U, 0xdd49eb04U, 0x968597a5U, 0xe4c6195eU, 0xdfe19f8bU, 0x4030dd5bU, 0x25cbd1b3U, 0xef44f65eU, 0xc9a06632U, 0xf5111f16U, 0xf71dd1b8U, 0x803bf676U, 0x8deae62aU, 0x8f10df1fU, 0x6c1df1b4U, 0x53bb0664U, 0x4faa4e07U, 0xdc342b2eU, 0x80000000U, 0x40000000U, 0x20000000U, 0x50000000U, 0x98000000U, 0xc4000000U, 0xb6000000U, 0xc9000000U, 0x8d800000U, 0xed400000U, 0x51600000U, 0xeeb00000U, 0x9e880000U, 0xaac0000U, 0xd97e0000U, 0x33470000U, 0xd4618000U, 0xa9374000U, 0x98c86000U, 0x314b5000U, 0x5a0bd800U, 0x2a689400U, 0x4558ce00U, 0xdc90cd00U, 0x3c59f480U, 0xf911dac0U, 0xfd1a4ca0U, 0x12721ed0U, 0x30a95aa8U, 0xba7a47c4U, 0x25c0600eU, 0x9ba75035U, 0xc995d803U, 0x83df9417U, 0x4b514e28U, 0xb8fb8d38U, 0x407949aU, 0xd6018af2U, 0xb90614b0U, 0x4586cad2U, 0xb14674adU, 0x23619af1U, 0x91b3acaaU, 0xda0e0ed1U, 0x6a6ae286U, 0x655983edU, 0x8c937605U, 0xa45f0910U, 0x3d14e295U, 0x4b1e83e6U, 0xdb72f633U, 0xbd284912U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x90000000U, 0x58000000U, 0x34000000U, 0x92000000U, 0xc5000000U, 0x12800000U, 0x36c00000U, 0xf1600000U, 0xd2900000U, 0xbc080000U, 0x2fac0000U, 0x4e5e0000U, 0x5dc10000U, 0x78e18000U, 0xe5d14000U, 0xf62fe000U, 0x811bf000U, 0x53e51800U, 0x8c572c00U, 0x516c8a00U, 0x933ce900U, 0xc955c980U, 0x3eccfc0U, 0x45ff31a0U, 0xa83013d0U, 0x897ea398U, 0xcdf7d6f4U, 0x1599e00eU, 0x226f039U, 0x82b2980aU, 0x5bbb6c18U, 0x1694ea36U, 0xa60b5931U, 0x66a8b19cU, 0x6adc53c8U, 0x6406c3b7U, 0x6a0066e2U, 0x81049818U, 0x48866c1cU, 0x9fc36a0cU, 0x45e7190cU, 0xb350d182U, 0x9aebe3f2U, 0xd97bbbb7U, 0x35f0fad6U, 0x519d6a1dU, 0x5826192aU, 0x2bb1518fU, 0xef3aa3d1U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xf0000000U, 0x58000000U, 0x1c000000U, 0x96000000U, 0xcd000000U, 0x3800000U, 0xccc00000U, 0x31e00000U, 0x29500000U, 0xcab80000U, 0xfb9c0000U, 0x7d2e0000U, 0x7c10000U, 0x17628000U, 0x42124000U, 0x4d9da000U, 0xe02a9000U, 0x4c443800U, 0x6fa7c400U, 0xa1f09200U, 0x23cab500U, 0x72108380U, 0xb598c040U, 0xec291ba0U, 0x72459450U, 0xe6a5b198U, 0x2874e56cU, 0xb40ba00eU, 0x8d77902bU, 0x5388b80bU, 0xdbb48408U, 0x916fb233U, 0x78626507U, 0x1e911ba9U, 0x25d9944aU, 0xb58bb19eU, 0xeb5e557U, 0x6ee92039U, 0xd2a5d019U, 0xba751806U, 0x130e1414U, 0x25f38a3aU, 0x9c9a11dU, 0x391789a0U, 0xd31e2173U, 0x676fb204U, 0x5626502U, 0xa5111ba1U, 0x5199476U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x30000000U, 0xd8000000U, 0x94000000U, 0xbe000000U, 0x29000000U, 0x99800000U, 0x29400000U, 0x86a00000U, 0xd9d00000U, 0x11980000U, 0x827c0000U, 0x8f0a0000U, 0x14410000U, 0x61248000U, 0xb9944000U, 0x3ebbe000U, 0xaaeb9000U, 0x8c321800U, 0xf1ed7400U, 0xd6b24e00U, 0xb628f300U, 0xf9d6d180U, 0x819ca740U, 0xa7f29a0U, 0xf30a4370U, 0xe6477fb8U, 0x6223c47cU, 0xb711e00eU, 0xa77a9019U, 0x9c8e9801U, 0xfa053423U, 0xbf03ae3fU, 0x9c826325U, 0xaac049a8U, 0xe0e59376U, 0x7bf687a3U, 0xc689206cU, 0x1503b63eU, 0xcb82172fU, 0x7a448791U, 0x60242062U, 0xc15360dU, 0xdfb571eU, 0x6349e7a5U, 0x7166f074U, 0xeeb24e08U, 0xd228f312U, 0xffd6d1baU, 0xc9ca761U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x30000000U, 0xa8000000U, 0xc4000000U, 0x72000000U, 0xb3000000U, 0x36800000U, 0x9cc00000U, 0xdfa00000U, 0x1af00000U, 0x5be80000U, 0xda8c0000U, 0xc4da0000U, 0xd7470000U, 0x88e28000U, 0x5211c000U, 0xa9fae000U, 0x4374f000U, 0x2fae2800U, 0x3ceebc00U, 0xc60b4a00U, 0x2719ef00U, 0xb8626c80U, 0x67d0a5c0U, 0x97dea4a0U, 0xb1c6e9f0U, 0x2c21c688U, 0xd1b6bafcU, 0xad0a6022U, 0x1d9e300dU, 0x2a4481eU, 0xe1708c11U, 0x64af023bU, 0xf669633aU, 0x74cd6ea6U, 0x55b9c6cdU, 0x9113ca0cU, 0x577f2f27U, 0x8bb20cb8U, 0x1a0995c9U, 0xf9186c8fU, 0x1d67a5d6U, 0xa05424adU, 0x269b29e1U, 0x2126acU, 0x7b54ae1U, 0xfc0ec819U, 0x1d4c31U, 0xc4e7e211U, 0x1416931fU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x50000000U, 0x58000000U, 0x4c000000U, 0x56000000U, 0x89000000U, 0x4a800000U, 0xa9c00000U, 0xc0e00000U, 0xf500000U, 0x2b280000U, 0xcc0c0000U, 0x86be0000U, 0x5e410000U, 0xc9a78000U, 0x51774000U, 0x631a2000U, 0x49361000U, 0x9bbe9800U, 0x4ec7ac00U, 0x5f63d200U, 0x214dd00U, 0xd70bd380U, 0x473b54c0U, 0xce076ba0U, 0x6506e8d0U, 0xac842198U, 0x28c499c4U, 0x9e63a00eU, 0xbc905017U, 0x34cb383bU, 0xdafc25U, 0x4ed16a11U, 0xfb68611bU, 0x80af19b7U, 0x2b4e65cbU, 0x4d9aca08U, 0x52f4310aU, 0x205a21a3U, 0x901599f3U, 0x5c0c202fU, 0x7ebb1033U, 0xa2471826U, 0x97a1ec27U, 0xcc767208U, 0x33998d2cU, 0x3ff16b8cU, 0x98dbe8e0U, 0xa2d5a1bcU, 0x1d6ed9cbU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x50000000U, 0x78000000U, 0xc000000U, 0x8a000000U, 0x51000000U, 0x43800000U, 0x27c00000U, 0xaa600000U, 0xd4900000U, 0xc6980000U, 0xa93c0000U, 0x92ca0000U, 0xb5470000U, 0xe218000U, 0xf9344000U, 0xe8692000U, 0xc333f000U, 0xf168b800U, 0x4b5c400U, 0x78ad2a00U, 0x1d4b100U, 0x38be2980U, 0x780b5340U, 0xea7b1a0U, 0xf0716770U, 0x24482388U, 0xef071264U, 0xf482a016U, 0x4f40b027U, 0xb7201814U, 0x6eb27403U, 0x19acb22cU, 0xca52851eU, 0x3b7bbb98U, 0x2c6a2668U, 0xd34b22bU, 0xae6e8526U, 0xb831bb97U, 0xb3ed2666U, 0x18f53228U, 0xf90ac50aU, 0xf5209b97U, 0x7bb2d663U, 0x542f8a2bU, 0x12940135U, 0x7d9e31b8U, 0x4bb92744U, 0xde8b03b3U, 0x4ce3e24fU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0x48000000U, 0xf4000000U, 0x62000000U, 0x35000000U, 0x9f800000U, 0x6400000U, 0xcde00000U, 0x51100000U, 0x13380000U, 0x469c0000U, 0x196a0000U, 0x23c70000U, 0x82a38000U, 0x3577c000U, 0x36d6000U, 0x7ac2f000U, 0x63231800U, 0x80334400U, 0x4e0de600U, 0x7314e100U, 0x463d7580U, 0x691e6e40U, 0x472b0da0U, 0x5223da70U, 0x45b7f388U, 0x714f7f74U, 0xef76e01aU, 0xfa693009U, 0x8b447822U, 0x9e66b434U, 0x39557e2dU, 0x25dc6531U, 0x630ff38cU, 0x30937f58U, 0x667ce030U, 0xabfe3034U, 0xbff819U, 0x4edd7409U, 0x9f8a1e30U, 0x5e559529U, 0x175d6bbeU, 0xe6ccfb56U, 0x7d35e63fU, 0xe588e102U, 0xb7577590U, 0xaed96e72U, 0xef888dacU, 0xa6541a7aU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xb0000000U, 0xf8000000U, 0xac000000U, 0x12000000U, 0x65000000U, 0x23800000U, 0xe5c00000U, 0x29e00000U, 0xc4b00000U, 0xb5f80000U, 0x1fdc0000U, 0x598a0000U, 0x24470000U, 0x31268000U, 0x72d74000U, 0xce8f2000U, 0xb2c63000U, 0x1f60d800U, 0x5af7a400U, 0x65d89a00U, 0x188cbd00U, 0xe1c72480U, 0xbfe15540U, 0xf7b0dca0U, 0x57cc170U, 0xfa9a9e88U, 0x6d2cd85cU, 0x7851a036U, 0xcacd7037U, 0xf3e5f812U, 0x35b6941eU, 0x887ec232U, 0x3d1c590bU, 0xcee89e86U, 0x8ab7d851U, 0x5afd200fU, 0xe55d303fU, 0xc5cc5819U, 0xd967e413U, 0x41f13a09U, 0x915dcd39U, 0xbc8dcadU, 0xf660c160U, 0x1b709e90U, 0xbd1bd86fU, 0xeef202fU, 0x2ab63011U, 0xeaf8d81dU, 0x1d5ba43fU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0x78000000U, 0x14000000U, 0x3a000000U, 0x6d000000U, 0xff800000U, 0xec400000U, 0x6c600000U, 0xe5d00000U, 0xd8180000U, 0xcd3c0000U, 0x6f0a0000U, 0xa4830000U, 0xa0c78000U, 0x60a24000U, 0x8b73e000U, 0x146ab000U, 0x33d61800U, 0x5b1b4400U, 0x45bef600U, 0x1c97d00U, 0xa323ef80U, 0xd135ad40U, 0xb0c17a0U, 0x16875970U, 0x91c379a8U, 0xd9272074U, 0x5c358036U, 0xc48d4031U, 0x92c66018U, 0x91a7f01aU, 0x12f0782fU, 0xd32cb425U, 0x9b368e2aU, 0xee09c919U, 0xb5076192U, 0x3b836471U, 0x8e46f616U, 0x5657d13U, 0x5851ef8dU, 0x4d5aad46U, 0x64d997afU, 0xb9a1941U, 0xef7d19a0U, 0x646cd064U, 0xbbd7f836U, 0x71ef419U, 0x3bd6e36U, 0x3acf7901U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xf0000000U, 0x88000000U, 0xc4000000U, 0xb6000000U, 0x6f000000U, 0x6b800000U, 0x7400000U, 0xeae00000U, 0x6100000U, 0x4e480000U, 0xf4ec0000U, 0x9f9a0000U, 0x32810000U, 0xc3c28000U, 0xe620c000U, 0x1bb5e000U, 0x2abfd000U, 0x78b4e800U, 0x933b9400U, 0x36f71e00U, 0x55db100U, 0x10241d80U, 0xd4b2b5c0U, 0xd13f15a0U, 0x7f7f1f0U, 0x35de63b8U, 0x42e114ccU, 0x9210801aU, 0xe04dc03dU, 0x27ed6017U, 0xe1e1016U, 0x28c38815U, 0x9ba4842bU, 0xe3f6160dU, 0xd3d9f51bU, 0x35e7ebb3U, 0x459490fdU, 0x1d0c162eU, 0xd008f500U, 0xba8d6b9cU, 0x654850f4U, 0xe96bf613U, 0x97da253eU, 0x43e1039dU, 0x4a9204f0U, 0x868b880dU, 0x5f48842fU, 0x946c1618U, 0xd558f536U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0x98000000U, 0xf4000000U, 0x16000000U, 0x6f000000U, 0x51800000U, 0xc2400000U, 0x42a00000U, 0x45900000U, 0xa6d80000U, 0xa13c0000U, 0x8b8a0000U, 0xf0830000U, 0xe8c18000U, 0x37634000U, 0xe275e000U, 0x9c6bd000U, 0x62306800U, 0xb7cf4400U, 0xa122e600U, 0xa6d60b00U, 0xefbeb80U, 0xb1682f40U, 0x5ab463a0U, 0xf30fbb70U, 0x54476da8U, 0xeda5b444U, 0x3413800eU, 0xb49c4039U, 0x7b9e602bU, 0x3a1b9012U, 0x405c0837U, 0x26fbd416U, 0xed6d6e01U, 0xd0b19f3aU, 0x3608e5adU, 0x10c22049U, 0xf3608e3bU, 0x9c764f35U, 0x4f6a8db9U, 0x49b2646dU, 0xf889e826U, 0xcb00041bU, 0x1f850617U, 0x7942db28U, 0xd52003baU, 0x70d72b6eU, 0x41fae586U, 0x30ed2052U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x90000000U, 0x88000000U, 0xdc000000U, 0xea000000U, 0x5b000000U, 0xe3800000U, 0x48400000U, 0x45a00000U, 0x39100000U, 0x8b380000U, 0xf1dc0000U, 0xdcee0000U, 0xc9810000U, 0xb3418000U, 0xd627c000U, 0x69562000U, 0x9a9df000U, 0xfecf6800U, 0xe6d49400U, 0x80da8600U, 0xc468f300U, 0x12476780U, 0xa6a01c40U, 0xfe902fa0U, 0xed787850U, 0x517c4198U, 0x6b7fdf74U, 0x5879803aU, 0xf7fbc003U, 0xddb82020U, 0x1f1cf005U, 0x2f8ee820U, 0xb7f35433U, 0xe00ca613U, 0x4db5030aU, 0x4aa80f8bU, 0x31248860U, 0xb0d2a9a4U, 0xe1dc8b50U, 0x14ed2621U, 0xf582c30fU, 0xc9462f9bU, 0x5257872U, 0x56d3c1b1U, 0x38d91f5bU, 0xe06e201fU, 0x3c41f01eU, 0x43a16828U, 0x7015942eU, 0x80000000U, 0xc0000000U, 0x20000000U, 0x70000000U, 0xc8000000U, 0x4c000000U, 0xf6000000U, 0x25000000U, 0x800000U, 0x45400000U, 0x59a00000U, 0xb9500000U, 0x8ba80000U, 0x744c0000U, 0x993a0000U, 0xf2030000U, 0x5f048000U, 0xf384c000U, 0x10c7a000U, 0xd4639000U, 0xe9b4f800U, 0x9d5e9c00U, 0x63b70600U, 0x665ee300U, 0x5a302d80U, 0x6d9edac0U, 0xe7d175a0U, 0x37ecd6f0U, 0x436c0ba8U, 0xb42b69ecU, 0x5288001aU, 0x485c003fU, 0x6b320007U, 0x4f1f0006U, 0x8596800fU, 0x39cbc00bU, 0x20f9202bU, 0xf0e45036U, 0xa6f7d834U, 0xfff9cc22U, 0xc3645e12U, 0x9633ef0fU, 0x5b9bd393U, 0xe2d2a5ddU, 0x476c5e15U, 0xce2fef05U, 0xa189d3a1U, 0x1ddda5f2U, 0xe6f2de34U, 0x1ff82f28U, 0x9362f381U, 0x2e36f5f0U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0x98000000U, 0x5c000000U, 0xae000000U, 0xeb000000U, 0x68800000U, 0x72400000U, 0xff200000U, 0xb4d00000U, 0x38680000U, 0x280c0000U, 0x9c7a0000U, 0x74050000U, 0xaa008000U, 0xf9024000U, 0x1d87a000U, 0x69c35000U, 0xb9e0c800U, 0x97b16c00U, 0x989f8e00U, 0xcc332f00U, 0xfe5fcd80U, 0x3f509cc0U, 0xf6aaa5a0U, 0x1f6ba0f0U, 0x668f6398U, 0x113ea3fcU, 0xb9a0003eU, 0xed90002bU, 0x4fc80035U, 0xde9c0021U, 0xc3320017U, 0xb4d90031U, 0xa012800eU, 0x4e0b400bU, 0x437d202bU, 0x9684103bU, 0xf147e816U, 0xb3a07c3aU, 0x490e603U, 0x1a4d1329U, 0x435a8b8aU, 0x10d7dff9U, 0x3a6a6623U, 0x150a5331U, 0x73fdabb7U, 0x58c6cfc0U, 0x90650e31U, 0x74746f3eU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0x28000000U, 0xac000000U, 0x2e000000U, 0x3d000000U, 0xaf800000U, 0xc5c00000U, 0x7600000U, 0x7d900000U, 0x5ae80000U, 0x434c0000U, 0x973a0000U, 0xbc010000U, 0xa6078000U, 0xa100c000U, 0xf986a000U, 0x7cc55000U, 0x2ae5f800U, 0xab55e400U, 0xcf0aba00U, 0x549f6900U, 0xf77f980U, 0x85bc00c0U, 0x1646a1a0U, 0x4a1b4f0U, 0x8bf463b8U, 0xf6faf9e4U, 0xc9600032U, 0xd090000fU, 0xbd680019U, 0x7a8c0030U, 0x965a002aU, 0x50910015U, 0x7d6f8021U, 0x1a8cc021U, 0xc65ca03cU, 0x7894503eU, 0xd16a7832U, 0x34892420U, 0xfb5e1a1aU, 0xd7173917U, 0x14af81b2U, 0x33e824d8U, 0x86cd3bbdU, 0x8dfb4dedU, 0x57e0c23fU, 0xa4d64d04U, 0x3ac9e3a8U, 0x2bfb39e1U, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0x28000000U, 0x4000000U, 0x36000000U, 0xe7000000U, 0xc0800000U, 0x40400000U, 0x9da00000U, 0xa8d00000U, 0x38780000U, 0xf09c0000U, 0xf46e0000U, 0x13050000U, 0x9e828000U, 0xc341c000U, 0x1b22e000U, 0x2790d000U, 0x615ea800U, 0x2e0c8c00U, 0xb6b53e00U, 0x8bc9eb00U, 0x12d72980U, 0xbd78a840U, 0xd91d61a0U, 0xcfadf450U, 0x146277b8U, 0x3eb0534cU, 0xdfce0032U, 0x1cd5000dU, 0x67a801fU, 0x39dc024U, 0x5aece037U, 0x9845d028U, 0xf1a4281aU, 0xfad14c03U, 0x9979de19U, 0xff1c3b06U, 0x70ab0194U, 0xf8e5e452U, 0x4cf2bfb4U, 0x9368cf58U, 0x9385f624U, 0xbec17731U, 0x2ee4dfabU, 0x9bf0df6fU, 0x1bed3e14U, 0xa7c5eb08U, 0x3d612994U, 0x6531a873U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x10000000U, 0xd8000000U, 0x4c000000U, 0xae000000U, 0xfd000000U, 0x41800000U, 0xab400000U, 0xd9e00000U, 0xf8f00000U, 0x52d80000U, 0x4f7c0000U, 0x54ea0000U, 0x4d030000U, 0x49878000U, 0x1f474000U, 0x2be42000U, 0x73f1d000U, 0xa258f800U, 0xbbc9400U, 0xdb4abe00U, 0x2d929900U, 0x48ebd280U, 0xdb00de40U, 0xc8850aa0U, 0x38c29a70U, 0xe9a2cca8U, 0x994d774U, 0xa2ea001eU, 0x3c030027U, 0x86078015U, 0x59074028U, 0x6b84200dU, 0x6c41d006U, 0x8760f80dU, 0x4130942bU, 0x9cf8be32U, 0x84ad9907U, 0x8c6652b7U, 0x71b49e7eU, 0xf83eaab3U, 0x1b080a77U, 0x34f414a5U, 0x3cda937cU, 0x927fc62eU, 0x56a4d3eU, 0x3e42cc81U, 0xdc64d77dU, 0x49b20021U, 0x843f0009U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0xa8000000U, 0x44000000U, 0x16000000U, 0x51000000U, 0x5f800000U, 0xa0400000U, 0xe3a00000U, 0xbbd00000U, 0xe2980000U, 0x9efc0000U, 0x16ca0000U, 0xe4250000U, 0xd7948000U, 0x33fc000U, 0x7a2ee000U, 0x16d5d000U, 0xd7191800U, 0xc5be4400U, 0xb1efb600U, 0xb328300U, 0x2a69d180U, 0x7d742f40U, 0x78caa9a0U, 0x29207b70U, 0x9212e798U, 0x10796c5cU, 0x290d9832U, 0x47c1840dU, 0x3fe15617U, 0xf2775329U, 0x4248c9b8U, 0x88e66b6dU, 0x74f71f8aU, 0xa98bf862U, 0xc505b60fU, 0x9187833dU, 0xfd455197U, 0x5e27ef4dU, 0xf4964987U, 0x4bbcab6bU, 0xcced7fa4U, 0xe6b1e85cU, 0x7d2a4e03U, 0x3850173fU, 0x78d9ff90U, 0x9e5e2856U, 0x59cae36U, 0x79c72fU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0x78000000U, 0x7c000000U, 0x52000000U, 0xd5000000U, 0x1b800000U, 0xe8c00000U, 0xf4200000U, 0x3100000U, 0xbca80000U, 0xcbcc0000U, 0x5c3a0000U, 0x23a10000U, 0x51d78000U, 0xf98a4000U, 0xad5ea000U, 0xf750b000U, 0xaecad800U, 0xafb96400U, 0xaf627200U, 0xdbf51b00U, 0x5980f80U, 0xa37324c0U, 0x9ddbf7a0U, 0x3b10b0f0U, 0x60adfdb8U, 0xa9cc7fe4U, 0xa13d5826U, 0x3c23243bU, 0x9714d212U, 0x8aa9ab3eU, 0x60c8d78cU, 0xb8bb40d0U, 0x79e6058fU, 0x4b3ebffU, 0x3379522cU, 0xfd42eb2cU, 0x6be1f783U, 0x71b1b0f1U, 0x18fa7d86U, 0x3d863fdeU, 0x9bc3f802U, 0x5ca39420U, 0x23560a29U, 0x38cccf19U, 0x34b8a5b3U, 0x63e35bf8U, 0x85b38a0bU, 0x7efb8f30U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xf0000000U, 0x38000000U, 0x6c000000U, 0x82000000U, 0xdf000000U, 0x38800000U, 0x13c00000U, 0xea600000U, 0x38f00000U, 0xaa280000U, 0x630c0000U, 0x565e0000U, 0xd0e10000U, 0xb4328000U, 0x98c94000U, 0xb8392000U, 0x2e10b000U, 0xe71c8800U, 0xca47ac00U, 0xf423e200U, 0x62d3a900U, 0x75fefa80U, 0x174edc0U, 0x4469d2a0U, 0x12ab1d0U, 0xe58f9898U, 0x309e04ecU, 0x79060816U, 0x7182ec37U, 0xfa44c216U, 0x6c221910U, 0x1ed0f2a0U, 0x3ffa01e8U, 0x8a7310b4U, 0x92e9a8edU, 0x4fedea06U, 0xe86d453eU, 0x232c38b3U, 0x2a8bf4c5U, 0xc01da01cU, 0x3ec4f036U, 0x75e12800U, 0x9fb35c16U, 0x218aca00U, 0x569cf50eU, 0x9002309aU, 0x880518c0U, 0xb4076208U, 0x1e07e912U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x70000000U, 0xb8000000U, 0xdc000000U, 0x66000000U, 0xa7000000U, 0xf7800000U, 0x6400000U, 0xc6200000U, 0xd7700000U, 0x18f80000U, 0x731c0000U, 0xc20a0000U, 0x8ca50000U, 0xb7b28000U, 0xa0194000U, 0x878ca000U, 0xcfe21000U, 0xeb11e800U, 0xffad3400U, 0xd390f600U, 0x3a6c9f00U, 0x81f66880U, 0xfe3bc540U, 0x1cf9a0a0U, 0x791da170U, 0x5b0c1e98U, 0x70221a6cU, 0x98716836U, 0x1b7d741bU, 0x75cd60fU, 0xa12ecf02U, 0xb153a08aU, 0x9f88a15fU, 0x43e69eb5U, 0xa5175a6dU, 0x4cafc812U, 0x26166404U, 0x212dbe11U, 0x7153bb21U, 0x7f8f76acU, 0x33e66e49U, 0x1d153e38U, 0x90affb20U, 0x40115682U, 0x862d3e4cU, 0x86d07616U, 0x79ccdf2cU, 0xf5c248b9U, 0xca659544U, 0x80000000U, 0x40000000U, 0x60000000U, 0x70000000U, 0xd8000000U, 0x3c000000U, 0xbe000000U, 0xc1000000U, 0xa8800000U, 0x67c00000U, 0x79e00000U, 0xc0d00000U, 0x1e380000U, 0x49c0000U, 0x8c6e0000U, 0x6e650000U, 0xee928000U, 0xb89e4000U, 0x7268a000U, 0xcf64d000U, 0x36131800U, 0x75e3c00U, 0x37893200U, 0xb1b49500U, 0xe92be780U, 0xab424040U, 0xdc22dfa0U, 0xa636ec50U, 0xc76855b8U, 0xde4954cU, 0xaad7980eU, 0xe5397c03U, 0x9f1d1201U, 0xe42b0523U, 0x25c2dfb3U, 0x26e6ec66U, 0xb95055bbU, 0x79789549U, 0xfeb9980bU, 0xb75c7c24U, 0xcf8f9214U, 0x9db54539U, 0xff2a7f86U, 0x8e423c4bU, 0xf6a34da1U, 0xbef6a97fU, 0xd708aa26U, 0x274e939U, 0xaaca75abU, 0x5892057cU, 0xcd9a2027U, 0x90ea9032U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xf0000000U, 0x98000000U, 0x1c000000U, 0xba000000U, 0x29000000U, 0xd8800000U, 0x89c00000U, 0x32200000U, 0xc6100000U, 0x7c180000U, 0xeb7c0000U, 0xe88e0000U, 0xfa10000U, 0xe5528000U, 0x7afc4000U, 0x9cfa000U, 0xcc47f000U, 0xfd617800U, 0xe2f2dc00U, 0xaba88200U, 0xad333b00U, 0xba8cdf80U, 0xe2a3d940U, 0x7bd087a0U, 0x903ab550U, 0x526edd98U, 0x4710a26cU, 0x809df83eU, 0xd4bf9c2bU, 0x21ada230U, 0xbc348b31U, 0x6e0c07beU, 0xb967f56fU, 0xe4f3fdb4U, 0x28ab1249U, 0x34b3203dU, 0x6fcab005U, 0xff445837U, 0x1ce56c33U, 0xdbb05a14U, 0x944b172aU, 0xff01a599U, 0x93837e46U, 0x8447fa1eU, 0x2960e716U, 0xccf6ddbcU, 0x4caca257U, 0x62b3f818U, 0x64ce9c05U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xb0000000U, 0x68000000U, 0x3c000000U, 0x6a000000U, 0x45000000U, 0xd8800000U, 0xec00000U, 0x8ba00000U, 0xd1f00000U, 0xc2b80000U, 0x755c0000U, 0x24ce0000U, 0x84a10000U, 0x5c708000U, 0x2cf9c000U, 0x143b2000U, 0x409ff000U, 0x84e99800U, 0x1c133c00U, 0xee2f5a00U, 0xe9b6cf00U, 0xccdcd480U, 0x6c8c1f40U, 0x42c6eca0U, 0x29a51350U, 0xf8f50e98U, 0xa83e107cU, 0x6a9f9802U, 0x21ee3c33U, 0x7491da38U, 0x88ee0f32U, 0x5e1774b6U, 0x772a2f5dU, 0xeb3454aeU, 0xef19df76U, 0x3abccbcU, 0xf7f7e356U, 0x25ba1699U, 0x84d9ec7bU, 0x408d6236U, 0x10c3c315U, 0x88a13695U, 0x1e761c4bU, 0xb5fcfa07U, 0x16bcff25U, 0x63586c99U, 0xebcdd37aU, 0xa926aebeU, 0xe2342072U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x30000000U, 0xb8000000U, 0x14000000U, 0xe6000000U, 0xc9000000U, 0x70800000U, 0x1b400000U, 0xede00000U, 0xf3900000U, 0xc3c80000U, 0x83ec0000U, 0xdfde0000U, 0x1ae10000U, 0x2e148000U, 0x160b4000U, 0x9848e000U, 0xef2c5000U, 0xecf8d800U, 0x15527c00U, 0x6bec5600U, 0x3dbd100U, 0xb0e5f980U, 0x2517f5c0U, 0xf18941a0U, 0x2e8e99d0U, 0x8f0b2f98U, 0x20ca64dcU, 0xb86ed836U, 0xc31f7c19U, 0x71c6d62fU, 0x5a1913bU, 0xdf1998bU, 0x509ce5f1U, 0x510779beU, 0xf481b5d8U, 0x9543218fU, 0xb8e489c6U, 0xc911978aU, 0xe38e08c3U, 0x318e3603U, 0x8e8dc108U, 0x5f0941a9U, 0xa8ce99c5U, 0x146b2f86U, 0x311a64e6U, 0x5ec6d831U, 0xbc237c0aU, 0x6630d63bU, 0xa63c9119U, 0x80000000U, 0x40000000U, 0x20000000U, 0xb0000000U, 0x88000000U, 0x4000000U, 0x4e000000U, 0x8f000000U, 0xb4800000U, 0xa4c00000U, 0x8a200000U, 0x1700000U, 0x99d80000U, 0x5bc0000U, 0xc12e0000U, 0xb9270000U, 0x37f68000U, 0xd818c000U, 0x4a1de000U, 0xd7181000U, 0xbe992800U, 0x53d92c00U, 0x84ba3a00U, 0xdaaa3300U, 0x1965ec80U, 0x91147c40U, 0x574fa4a0U, 0x9cb18050U, 0xc47f56a8U, 0xce8d8f7cU, 0x8f17280aU, 0x804e2c3dU, 0x3434ba39U, 0x12bef30eU, 0x9ae0c9cU, 0xffe76c4bU, 0xc8d60cbcU, 0x24eb6c5aU, 0x48800c81U, 0x6c06c54U, 0xdf208cbeU, 0x4cf3ac52U, 0x8a9dec82U, 0xd5d87c47U, 0x2fb9a49bU, 0x902a805aU, 0xbaa7d6a6U, 0xabb24f60U, 0xbcfc482cU, 0x4efc21U, 0x74307228U, 0x32bfcf0eU, 0x80000000U, 0x40000000U, 0x20000000U, 0x90000000U, 0xd8000000U, 0xe4000000U, 0xaa000000U, 0xe3000000U, 0x82800000U, 0x1dc00000U, 0xeb200000U, 0xf7d00000U, 0xdab80000U, 0xb8dc0000U, 0x54ee0000U, 0x79270000U, 0xd78000U, 0x9a3b4000U, 0xea196000U, 0xab4ab000U, 0x3e326800U, 0xfac9dc00U, 0xa974a200U, 0x102cc300U, 0x6b81b980U, 0xac45da40U, 0x8c6531a0U, 0x7531f650U, 0xb44c9ba8U, 0x92b55974U, 0x1e0a681eU, 0x6bd5dc0dU, 0x44baa214U, 0x9dbc325U, 0x416e39bcU, 0x94629a46U, 0xf1325190U, 0xae4c4652U, 0x39b17384U, 0xa08bc560U, 0x3811aa07U, 0xe698af00U, 0x9f88f3b7U, 0x4978573U, 0xda5f4a33U, 0xb9295f04U, 0xfa03fb8dU, 0x5b04e954U, 0xd6818025U, 0xffc0402dU, 0x3420e004U, 0x3b56f000U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x70000000U, 0x78000000U, 0x1c000000U, 0xd6000000U, 0x11000000U, 0x9d800000U, 0xc400000U, 0xc6e00000U, 0x38900000U, 0xf3680000U, 0xb64c0000U, 0xcf7a0000U, 0x70e50000U, 0x99928000U, 0xf6ef4000U, 0xd60ca000U, 0xa79f9000U, 0x4573d800U, 0x21785400U, 0x5de74600U, 0x42141900U, 0xe3ad0180U, 0xe96930c0U, 0x5948f9a0U, 0xb7fdb4f0U, 0x2322c798U, 0xf03769ecU, 0x4e1bd806U, 0x4b34542bU, 0xa49d4613U, 0x53f1191fU, 0x9fbf818cU, 0xfc670c0U, 0x9fa45983U, 0x39f224f9U, 0x8b91fb2U, 0x6b433dccU, 0x1a669e38U, 0x41554d14U, 0x2dcac7baU, 0xfa3b69d3U, 0xdf81d80cU, 0x6f415438U, 0x6067c619U, 0x1e525909U, 0xcd492187U, 0xc5fce0d6U, 0x18250195U, 0xdab530e9U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x70000000U, 0xe8000000U, 0xc000000U, 0x5e000000U, 0xed000000U, 0x4e800000U, 0xc0400000U, 0x68e00000U, 0xc7f00000U, 0x63d80000U, 0x58fc0000U, 0x712a0000U, 0x21a30000U, 0x73948000U, 0xf76dc000U, 0x8040a000U, 0x88e3d000U, 0x97f4f800U, 0xfbdc6c00U, 0xbcf85e00U, 0x232d5100U, 0x92a28a80U, 0xd0158e40U, 0x79a852a0U, 0x28e4f270U, 0x27f0d4a8U, 0x33dbdf6cU, 0xc0fe5812U, 0x952cbc2fU, 0x73a02625U, 0xc090fd24U, 0x54e874beU, 0xe840f48U, 0x2040a03eU, 0x38e3d00aU, 0x5ff4f819U, 0x87dc6c0bU, 0xaf85e24U, 0xc22d512cU, 0x82228a8fU, 0xfd558e58U, 0x5fc85293U, 0x2f54f257U, 0x2cc8d4abU, 0xacd7df7cU, 0xd20c5820U, 0xec73bc2dU, 0x711ea617U, 0x165e3d2eU, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0xc8000000U, 0x9c000000U, 0x7e000000U, 0xf000000U, 0x37800000U, 0xd6400000U, 0x6e200000U, 0x5e100000U, 0xefb80000U, 0x475c0000U, 0xbaae0000U, 0x65650000U, 0x9eb68000U, 0x536ac000U, 0x61012000U, 0x40835000U, 0xd5c46800U, 0xaa65b400U, 0x89313600U, 0x15289f00U, 0x3720c380U, 0x4a948440U, 0xd87d0ba0U, 0x9c3da050U, 0xb1ff5b8U, 0x91891b6cU, 0x11f3480aU, 0x29cfe40bU, 0x8d5de35U, 0x745eeb18U, 0x232855a0U, 0xe4208b51U, 0x63160029U, 0xf1390031U, 0xd988035U, 0x1f4fc00fU, 0x6e17a03cU, 0x7b99038U, 0x4b5d482dU, 0xfcaae41fU, 0x3e635e1cU, 0x4b342b28U, 0xf4297591U, 0x37a3db79U, 0xff526814U, 0x821cb43eU, 0xdd09b62cU, 0x82375f18U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x10000000U, 0x18000000U, 0x8c000000U, 0x52000000U, 0xd7000000U, 0x31800000U, 0xdfc00000U, 0x80200000U, 0x5cb00000U, 0x93180000U, 0xa27c0000U, 0x44ae0000U, 0xeae10000U, 0x92158000U, 0x45ef4000U, 0xb8802000U, 0x2b443000U, 0x59674800U, 0x22d52400U, 0x88490a00U, 0x61f31300U, 0x7b788a80U, 0x482fc440U, 0xafa462a0U, 0xa6709050U, 0x5bf8098U, 0x188dd754U, 0x1c51681eU, 0x4a0c1437U, 0x9c15c22aU, 0x78e87712U, 0x2204209eU, 0x9f07a761U, 0x45838018U, 0x11c24005U, 0x1d23a030U, 0x3636700cU, 0x2f5ce813U, 0x2a9f5426U, 0xa9bbe205U, 0xfa8d4736U, 0x2356e897U, 0xff8dc356U, 0x85d2aa1cU, 0xf1c96314U, 0xca326286U, 0x355d9076U, 0x899c009dU, 0x563f974bU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0x8000000U, 0x7c000000U, 0x32000000U, 0xf7000000U, 0x38800000U, 0xd2400000U, 0x31a00000U, 0x72100000U, 0xd9c80000U, 0xc9ac0000U, 0x32da0000U, 0x3de70000U, 0x4eb38000U, 0xb85dc000U, 0xd8a72000U, 0xe7943000U, 0x808c800U, 0x38cb6c00U, 0x202aae00U, 0xd11a3b00U, 0x3b829f80U, 0x64c0abc0U, 0x86e4f7a0U, 0x9c3537f0U, 0x491a3188U, 0x8f8190f4U, 0x8ac7e80aU, 0x53e35c2bU, 0x5bb06626U, 0xdfda5726U, 0x5e61b180U, 0x3e7050d6U, 0xc0bac82eU, 0x99906c25U, 0x150b2e1cU, 0x234cfb1eU, 0x94ec3fb4U, 0xfffe5bfeU, 0xcbb09f85U, 0x17dbabdeU, 0x826577afU, 0x1c73f7d8U, 0x3fbc91a1U, 0xdd1360eeU, 0xf549800cU, 0xe5eac027U, 0xde7ca020U, 0xf475f03eU, 0x80000000U, 0x40000000U, 0x60000000U, 0x50000000U, 0x98000000U, 0xa4000000U, 0x62000000U, 0xf3000000U, 0x70800000U, 0xf3400000U, 0x1e200000U, 0xaf00000U, 0x20880000U, 0xcc6c0000U, 0xb87e0000U, 0xf7e50000U, 0x8938000U, 0xb2dd4000U, 0x4c576000U, 0xf538f000U, 0xccc6a800U, 0x1be78c00U, 0x16944600U, 0xe7db4f00U, 0xfdd4ec80U, 0x1df91ac0U, 0xf520a4a0U, 0x9e7226d0U, 0xd1c8aab8U, 0x714e55c4U, 0x5a0a481eU, 0x802e3c2dU, 0xb8db8e26U, 0xf3513301U, 0xebbd82a2U, 0xc28499e9U, 0xd8416e23U, 0xaaa18312U, 0xcbb7ca8bU, 0x55aaa5d9U, 0x121ae027U, 0x9b0b035U, 0xd6aa4824U, 0xca9e3c0aU, 0x96f38e05U, 0x968d3339U, 0xf56b82bdU, 0x57fd99e9U, 0x2a24ee11U, 0xd0f5c31dU, 0x478d2ab8U, 0x16ea15d3U, 0x80000000U, 0x40000000U, 0x20000000U, 0x70000000U, 0x78000000U, 0x3c000000U, 0xd2000000U, 0x8d000000U, 0x29800000U, 0x12c00000U, 0xd1600000U, 0xdc300000U, 0xa3180000U, 0x863c0000U, 0x552e0000U, 0xd4270000U, 0x8908000U, 0x6ec94000U, 0x5c55a000U, 0x94aeb000U, 0x92e61800U, 0x1ff23400U, 0xd9ff7200U, 0xcdc93100U, 0x4ad3ac80U, 0x72ebfa40U, 0x70c694a0U, 0x44653e50U, 0x99b4dea8U, 0x6bdecb4cU, 0x9e5b3836U, 0x4e99c403U, 0x3afaca22U, 0xfb4eb530U, 0xdc9446a0U, 0xe8cebf68U, 0x17576a2aU, 0xd62c0500U, 0xb2a45e9eU, 0x96d78b4eU, 0xb0ee9837U, 0xd5c7743cU, 0x59e4d203U, 0x1d708130U, 0xd9bd3494U, 0x34ec8e40U, 0x5bc24691U, 0x56e5bf7dU, 0xb1f1ea0fU, 0xa6fe4538U, 0x194f7eb7U, 0x9977b79U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x50000000U, 0x68000000U, 0x6c000000U, 0x5e000000U, 0xc7000000U, 0xde800000U, 0xd2400000U, 0x77e00000U, 0x48500000U, 0x45080000U, 0x4f2c0000U, 0x975e0000U, 0x5f210000U, 0x2ff78000U, 0x3bbec000U, 0xff6a000U, 0xcbb8d000U, 0xd7f4a800U, 0x9fbabc00U, 0x8df61e00U, 0x6ab83900U, 0xca75df80U, 0xa17e0dc0U, 0xb15657a0U, 0x4c8fa1d0U, 0xcbebc198U, 0xefa34c4U, 0x56958802U, 0x89acac1fU, 0xb11c1635U, 0xc2c6553eU, 0xaaa169baU, 0x3d3188deU, 0xb91c161dU, 0xbec65507U, 0x7ca16983U, 0xc63188e1U, 0x519c1613U, 0xc786551dU, 0x8bc16990U, 0x9b2188efU, 0xbdf41620U, 0x12ba5514U, 0x2e77698fU, 0xc37c88ecU, 0x40559609U, 0x39099523U, 0x992849b3U, 0x6c5b98f5U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xf0000000U, 0xb8000000U, 0x7c000000U, 0x3e000000U, 0x51000000U, 0x2a800000U, 0x8400000U, 0x62200000U, 0xa4f00000U, 0xf3b80000U, 0x845c0000U, 0xdd4a0000U, 0x1ce70000U, 0xc0948000U, 0x7c6f4000U, 0x7595a000U, 0x24e9d000U, 0xad19800U, 0xb14bac00U, 0xae75e00U, 0x5906700U, 0x5cef4480U, 0xd6d34340U, 0x7f4dfca0U, 0xe3e57f70U, 0x53101a88U, 0x6aaf244cU, 0xe5f0b826U, 0xf13d3c13U, 0x181b6609U, 0xb56e1b37U, 0x131382abU, 0xaaf8849U, 0xb5f1663dU, 0xb9391b0fU, 0xdc1f0286U, 0xf76cc876U, 0x7c16c61dU, 0x712bcb20U, 0x97301a9cU, 0xd35f2451U, 0x1ac8b81eU, 0xa0213c3cU, 0xbf16610U, 0x28391b3bU, 0x569f0285U, 0xf2cc858U, 0xa636c617U, 0xa9dbcb12U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xd0000000U, 0xa8000000U, 0xc000000U, 0x5e000000U, 0x63000000U, 0x75800000U, 0xebc00000U, 0xd8600000U, 0x9a300000U, 0xf6980000U, 0xd5bc0000U, 0x5eae0000U, 0x2e230000U, 0x45918000U, 0x9acec000U, 0xa217a000U, 0xac0dd000U, 0x1cf08800U, 0xd07ec400U, 0x7dcbaa00U, 0x1592d100U, 0x72cdfc80U, 0xe115e40U, 0x220d54a0U, 0xd7f38a50U, 0xa9fe5688U, 0xc80f8f64U, 0xaef6a822U, 0x9d7dd427U, 0x134c8215U, 0x2fd1c52fU, 0x136edea0U, 0x71414b61U, 0x5825021cU, 0x6a930514U, 0x114f7ebeU, 0xfad39b5dU, 0xa9ea0a16U, 0x6100010bU, 0xa082f484U, 0x51425a74U, 0xc820deb9U, 0x62924b6fU, 0xcd4c8217U, 0xcd1c523U, 0xc6eede92U, 0x4a814b62U, 0x28450238U, 0xfca30514U, 0x80000000U, 0x40000000U, 0x20000000U, 0x30000000U, 0x88000000U, 0xd4000000U, 0xaa000000U, 0xdb000000U, 0x24800000U, 0x20c00000U, 0xa7600000U, 0x36b00000U, 0x25380000U, 0xa31c0000U, 0x78e0000U, 0x4c270000U, 0x6f928000U, 0xd72cc000U, 0x5f776000U, 0x61ddb000U, 0xcfe82800U, 0xe4152c00U, 0x969ba00U, 0xabd73900U, 0x308f1880U, 0xdea49f40U, 0xca54d0a0U, 0x15cbc350U, 0x3e86a2a8U, 0x33c3a65cU, 0x77e3c80aU, 0x8c735c29U, 0xd15c7200U, 0x652f650fU, 0xa877ea81U, 0x935c3a4bU, 0x7a28da2aU, 0x9ef18923U, 0x349bb0a1U, 0x87ca7361U, 0xf9808aa3U, 0x49418a53U, 0x1620f211U, 0x5c94a524U, 0x37aa0aaeU, 0x6db14a4fU, 0x41b9923eU, 0xa3de150aU, 0x90e8a284U, 0xf294a651U, 0x9ea9481eU, 0xde339c17U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x70000000U, 0x88000000U, 0xfc000000U, 0xe2000000U, 0x7000000U, 0x5c800000U, 0x8b400000U, 0x5da00000U, 0xdeb00000U, 0x9b680000U, 0x400c0000U, 0xedde0000U, 0x17630000U, 0x67d48000U, 0x71bac000U, 0x46342000U, 0x662eb000U, 0xd4a9c800U, 0x72e84c00U, 0x28c9c600U, 0xb3bb3300U, 0x71339280U, 0x12afdbc0U, 0xd3ecfaa0U, 0x454ce7d0U, 0xd7a5488U, 0x9654e8ccU, 0xbd7f682aU, 0xfe533c33U, 0x917eae32U, 0xe4540f22U, 0xe27b3c8dU, 0xa6d4d4dcU, 0x8c3d4618U, 0xa0f1f304U, 0x854fb28eU, 0xed7d6bd9U, 0x46533288U, 0x457babcdU, 0x8a5112b4U, 0x8f7a1bc4U, 0x1525a8eU, 0xb9fb97d1U, 0x71133cb8U, 0x5ad8d4dcU, 0x23e3460dU, 0xc092f329U, 0x361b32aaU, 0xeb87abc6U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xf0000000U, 0x78000000U, 0x54000000U, 0x56000000U, 0x6f000000U, 0x4d800000U, 0xac400000U, 0x2b200000U, 0x1a700000U, 0x70680000U, 0x2a1c0000U, 0xfa720000U, 0x406d0000U, 0x32188000U, 0x5e764000U, 0x6e6c6000U, 0x9189000U, 0x45f78800U, 0xad2d7400U, 0x6fbf9e00U, 0xf3c3b300U, 0xf664fe80U, 0x5fd0cec0U, 0x79db60a0U, 0x9c137df0U, 0x97bf9e38U, 0x67c3b30cU, 0xc064fe86U, 0xc0d0cee9U, 0x4c5b60abU, 0x64537dfeU, 0xea9f9e3eU, 0x12b3b33cU, 0xfd8cfe9fU, 0x468ccec4U, 0x9d0960bdU, 0x3e4e7df2U, 0xa8ef1e1cU, 0x66d9f326U, 0x69929eadU, 0xff95ec3U, 0xeae668aaU, 0xcd1549e7U, 0xa93ce016U, 0x9c02d00fU, 0xda01e827U, 0xfd04e414U, 0xfc82962cU, 0xa2c5873cU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x10000000U, 0x78000000U, 0x74000000U, 0xba000000U, 0x5000000U, 0xb4800000U, 0xb2400000U, 0x56e00000U, 0xf6100000U, 0xd480000U, 0xdb5c0000U, 0x86160000U, 0x854f0000U, 0x67598000U, 0x20154000U, 0x364f6000U, 0x18dff000U, 0x99d0b800U, 0x636aec00U, 0xbeefc600U, 0x862f9d00U, 0x158beb80U, 0x18fa1cc0U, 0x53642da0U, 0xaad581d0U, 0x5cefc608U, 0xa72f9d14U, 0xc30bebb6U, 0xcbba1cd9U, 0x73042d90U, 0x9f8581ccU, 0x9c7c60bU, 0x3d239d39U, 0xaa35eb8eU, 0xd1f91cc8U, 0xc9e3ad86U, 0x1793c1c7U, 0xd38f2629U, 0x5bfa2d2eU, 0xe4e5b3b6U, 0xf1640e1U, 0xbfca3392U, 0xca1c00c9U, 0xd774d382U, 0xbe9ab0f0U, 0x85350b9fU, 0x587cacc8U, 0x1b25f590U, 0x59339deaU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x70000000U, 0x68000000U, 0xa4000000U, 0xe6000000U, 0xaf000000U, 0x9d800000U, 0xea400000U, 0xf600000U, 0xb1900000U, 0x8b480000U, 0xf2dc0000U, 0x8d920000U, 0x61490000U, 0xffd88000U, 0x2912c000U, 0xd18f6000U, 0x237a9000U, 0x9ba08800U, 0x4b36f400U, 0x76fd2e00U, 0x85e1a100U, 0x5a540380U, 0xd46f78c0U, 0xb9292da0U, 0xafced9f0U, 0x821d2e18U, 0xb131a12cU, 0xa3fc03a2U, 0xd6378f5U, 0xd8932d83U, 0x29cbd9f2U, 0x9d1fae06U, 0xa4b6613dU, 0x9db9e386U, 0x8c0228e3U, 0x620445a2U, 0xd9057de2U, 0x2a856807U, 0xbbc7a419U, 0xa722461aU, 0xf7f30531U, 0x85cc589U, 0xe57bdd0U, 0x9a6a082dU, 0x522d341fU, 0xa44ace3bU, 0xaf59f12bU, 0x87d3ebbbU, 0x1e2f1cefU, 0x80000000U, 0x40000000U, 0x60000000U, 0xb0000000U, 0xc8000000U, 0x14000000U, 0xce000000U, 0x35000000U, 0xd3800000U, 0xcac00000U, 0x52200000U, 0x18f00000U, 0xe2c80000U, 0x623c0000U, 0xacf60000U, 0xbcc90000U, 0x4f3a8000U, 0x1375c000U, 0x640fe000U, 0xf21c5000U, 0x23021800U, 0xaa80d400U, 0xdb409a00U, 0xfe0df00U, 0xbe538280U, 0xc79cbc0U, 0x309318a0U, 0xa85914d0U, 0xa1609a38U, 0xf310df3cU, 0x3a9b82aaU, 0xff45cbe9U, 0x49e518a1U, 0xff5014d8U, 0xa1fa1a3fU, 0x7551f03U, 0x3dfc628aU, 0xbd559bddU, 0x76f9008dU, 0x93d5c0c6U, 0x7bbe002cU, 0xc5350034U, 0x46c8032U, 0xec8cc036U, 0x4e5d6027U, 0x7065902eU, 0x4693f805U, 0x6159841eU, 0x78e60226U, 0xbad0cb36U, 0x523878bfU, 0x24f584e6U, 0x80000000U, 0x40000000U, 0x20000000U, 0x10000000U, 0x8000000U, 0x34000000U, 0xca000000U, 0xd3000000U, 0xbf800000U, 0x51400000U, 0xc200000U, 0x6a700000U, 0x8a680000U, 0x341c0000U, 0x4760000U, 0xdb6b0000U, 0x4c9d8000U, 0x30b6c000U, 0x5d0ae000U, 0xa14a7000U, 0x4bee0800U, 0x3c5d8400U, 0x44d70600U, 0x4fd9e300U, 0x93943680U, 0x56fd46c0U, 0x736330a0U, 0x1754a5d0U, 0x889f0628U, 0x82b5e314U, 0x820a368aU, 0xf8ca46c9U, 0x3fa8b090U, 0xa2f965e9U, 0xd9606635U, 0xf4555334U, 0x2f18dea6U, 0xeff6b2c7U, 0x702c3eb1U, 0x8bbbc2feU, 0xd941b696U, 0x782786cfU, 0x8077d094U, 0x4969d5edU, 0x839a8e3dU, 0x6135a71eU, 0x1d4a50b1U, 0xf5ef15f5U, 0x5586e2dU, 0x3853d701U, 0xa91a5885U, 0xfaf591d1U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x90000000U, 0xf8000000U, 0xb4000000U, 0xa6000000U, 0x9d000000U, 0xfe800000U, 0xaf400000U, 0x69200000U, 0x45100000U, 0x71d80000U, 0x38cc0000U, 0x7b120000U, 0x8d90000U, 0x784f8000U, 0x6d514000U, 0xc17b6000U, 0xbb1f1000U, 0x2d289800U, 0x8ee47c00U, 0x26779e00U, 0xf76bab00U, 0x95409d80U, 0x3e227840U, 0x449703a0U, 0x7319d370U, 0xd12f9e18U, 0x14e7ab14U, 0xc1729d86U, 0x7eeb7849U, 0x4b8083b7U, 0x3dc4937aU, 0xa466fe0eU, 0x7f31bb18U, 0x1b4d85a3U, 0xad24473U, 0xbebe7db1U, 0x3c792865U, 0x15997b8cU, 0x9a6aff54U, 0xc3c47803U, 0x3d662c1aU, 0xafb66607U, 0xf509c704U, 0x77701b91U, 0xdbecef60U, 0xe103602eU, 0xa483102aU, 0xa8429803U, 0x70a17c17U, 0x80000000U, 0x40000000U, 0x20000000U, 0x70000000U, 0x8000000U, 0x24000000U, 0x8a000000U, 0x11000000U, 0x40800000U, 0x46400000U, 0x91200000U, 0xb8100000U, 0xf0680000U, 0x727c0000U, 0xfb160000U, 0xbdeb0000U, 0xf2be8000U, 0xe375c000U, 0x475a6000U, 0x8903f000U, 0x7c851800U, 0xb042ec00U, 0x5626c600U, 0x4f922300U, 0x49aae580U, 0x7e9a25c0U, 0xc5e423a0U, 0x627406d0U, 0x1fd8c628U, 0xb345230cU, 0x3ba2658aU, 0xbf54e5d5U, 0x59c8c380U, 0xa02e36ddU, 0x3459be1aU, 0xec833f19U, 0xa8413bbeU, 0x2a26eaeaU, 0x99960018U, 0xfeab002fU, 0x811e8038U, 0x5825c03aU, 0xe4926034U, 0x302ff021U, 0x2c5b1817U, 0x9085ec2cU, 0x7e46461cU, 0x9d20e32cU, 0x661005acU, 0x636b15c6U, 0x7fbdbb6U, 0x77d7dadaU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x10000000U, 0x58000000U, 0x74000000U, 0x66000000U, 0x8f000000U, 0x26800000U, 0x6c400000U, 0xd7600000U, 0x90d00000U, 0xb0480000U, 0x8e9c0000U, 0x5dd20000U, 0x7c90000U, 0xcf5b8000U, 0xee704000U, 0x8f386000U, 0xc231000U, 0xc5330800U, 0x92db2c00U, 0x2b64600U, 0x5b1e5100U, 0x7d17d180U, 0xd1eee2c0U, 0xf6997a0U, 0x272cb3f0U, 0x3e4c4618U, 0x1d9b5134U, 0xc15651aeU, 0xbe8ba2d9U, 0xfbb877afU, 0xa966e3ceU, 0x4bd4ae08U, 0xcf2d0cU, 0x25d97f92U, 0x8034cfe6U, 0xe9596836U, 0x41713c09U, 0x59bece13U, 0x28653d1eU, 0x3e51f78eU, 0x100fa3d8U, 0x5bff4e30U, 0x7c007d2cU, 0x6a001798U, 0x6d05f3daU, 0x8787a616U, 0xe9c40101U, 0x8fa73982U, 0xc2f69edeU, 0x80000000U, 0x40000000U, 0x20000000U, 0x10000000U, 0xa8000000U, 0xac000000U, 0x1a000000U, 0x43000000U, 0x58800000U, 0x7e400000U, 0xcba00000U, 0x4f300000U, 0x98a80000U, 0xf19c0000U, 0xd8360000U, 0xbe2b0000U, 0x4add8000U, 0xaa13c000U, 0x90db2000U, 0x89103000U, 0xf85d0800U, 0x4f55fc00U, 0x37fe0600U, 0xb6672700U, 0xf6531880U, 0x5c7b1ac0U, 0x8a51ea0U, 0x57b03dd0U, 0xc6e80628U, 0x2a3c2714U, 0x3f0698a2U, 0x8a84daefU, 0xa1403e8cU, 0x31270debU, 0x76768e38U, 0xbd8d1b1bU, 0x99e83e86U, 0x90bb0de3U, 0x26408e18U, 0xbfa61b04U, 0x6135be88U, 0xd5a8cdd8U, 0xf41bae0aU, 0xbf62b32U, 0xa48b6acU, 0xab8d31f3U, 0x90eda816U, 0x33d0c06U, 0xbc85ae2bU, 0xb8412b3cU, 0xaa3369cU, 0x40b5f1faU, 0x80000000U, 0x40000000U, 0x60000000U, 0xb0000000U, 0xd8000000U, 0xfc000000U, 0xde000000U, 0x2f000000U, 0x74800000U, 0xc3400000U, 0x38a00000U, 0x68f00000U, 0x64480000U, 0x76bc0000U, 0x5ff60000U, 0xccc90000U, 0xbbfa8000U, 0x20554000U, 0xf4b82000U, 0x3ef39000U, 0x9f4ec800U, 0x983cfc00U, 0x21b72e00U, 0xa9ef9700U, 0xb7cd3e80U, 0x157e6bc0U, 0x3e1210a0U, 0x219dfcd0U, 0xeac12e38U, 0x5666973cU, 0x8c97beaeU, 0x11db2bd3U, 0xa8e230a1U, 0xbad26ce4U, 0x80f9e612U, 0xeed36b07U, 0x5afa10bdU, 0x33d1fcf9U, 0xb77f2e36U, 0x8f139723U, 0x1a1b3ebcU, 0xed076bf9U, 0x758090bcU, 0x20c4bcfeU, 0xc3670e0bU, 0x95100737U, 0xe71df6a7U, 0xd08797e4U, 0xa141beb9U, 0xa9a22bc9U, 0x8370b0bdU, 0xb8b2cf2U, 0x80000000U, 0x40000000U, 0x60000000U, 0xd0000000U, 0xe8000000U, 0x6c000000U, 0xee000000U, 0x8d000000U, 0xf6800000U, 0xf2c00000U, 0x39a00000U, 0x48700000U, 0x13c80000U, 0x7abc0000U, 0x51f60000U, 0xe4890000U, 0x42598000U, 0x9867c000U, 0x72552000U, 0xbbf99000U, 0xf016d800U, 0xd19dfc00U, 0xf9433200U, 0x25e1c300U, 0xb7141280U, 0xd81f1fc0U, 0xc60120a0U, 0xc107dcd0U, 0xa884b238U, 0x47c30324U, 0x4b26b2a2U, 0x38b44fefU, 0x496d58a1U, 0x494d70e8U, 0x467df83eU, 0x55516c3bU, 0x627a6a11U, 0x2752ff01U, 0x597b808bU, 0x8d08cf4U, 0x373eca36U, 0xccb0af28U, 0xd36e78afU, 0x1e4de0c5U, 0x87faa01cU, 0xb617500fU, 0x509a7813U, 0x31c3ac2aU, 0xb220ca01U, 0x1435af05U, 0x8ca9f8aaU, 0x616f20c6U, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0xb8000000U, 0x14000000U, 0x9e000000U, 0xd7000000U, 0x51800000U, 0x25400000U, 0xe1a00000U, 0x95f00000U, 0x1e80000U, 0x6f1c0000U, 0xf5760000U, 0x96290000U, 0xf4788000U, 0x3b644000U, 0x1e146000U, 0xa038d000U, 0x8440800U, 0x1235400U, 0x4234f600U, 0xfa8bef00U, 0x510e5680U, 0xc549a6c0U, 0xd66ca0a0U, 0x595b49d0U, 0xf3527638U, 0xad9aaf2cU, 0x77b4b6b6U, 0xb9cc36f9U, 0x13ac48a9U, 0x6f388de0U, 0x9dc0e80bU, 0x9263c410U, 0x28929e1aU, 0xcf96b15U, 0x28a628b1U, 0x53755dceU, 0x152a602eU, 0x5bfdd012U, 0x39228834U, 0x1632143bU, 0x48e162cU, 0x760e7f1dU, 0x2ccebe9fU, 0xe72a62e3U, 0x26fe3ea6U, 0xb1a222ccU, 0xfdf45ebeU, 0x3deff2e0U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0x98000000U, 0x14000000U, 0x2000000U, 0x27000000U, 0xcc800000U, 0x8c400000U, 0x58a00000U, 0x33d00000U, 0x2a680000U, 0x22bc0000U, 0x2a520000U, 0xc5ab0000U, 0x16df8000U, 0xb604000U, 0x39b76000U, 0xd25b3000U, 0x6b276800U, 0x7153c00U, 0x8c8fb600U, 0x26cd0f00U, 0x736ac780U, 0x573d6bc0U, 0x639771a0U, 0x3ccb64f0U, 0x806a3608U, 0x39ba4f04U, 0x18d0278eU, 0x30ed1bf1U, 0x2bf8f986U, 0x497528fcU, 0x2ebd883bU, 0xfc554c2eU, 0x40a83e2bU, 0x2d5f431eU, 0xd3a779baU, 0xf95568c8U, 0xbb2ae813U, 0x559e7c23U, 0xc3475602U, 0x8267f28U, 0x9192cfb1U, 0x93cf67f7U, 0x60edafb4U, 0x73f857f5U, 0xfd70c78dU, 0xfcba6bdcU, 0x4352f18cU, 0x982c24e7U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0x98000000U, 0xac000000U, 0x12000000U, 0xb1000000U, 0xe0800000U, 0x6fc00000U, 0x9200000U, 0x83b00000U, 0xb1280000U, 0xc19c0000U, 0x79320000U, 0xfbed0000U, 0x26398000U, 0x7e404000U, 0x2664a000U, 0x55507000U, 0x73bf5800U, 0xc7072c00U, 0xb7878a00U, 0xe0452f00U, 0xf5605880U, 0x2cd12ec0U, 0x18fdd2a0U, 0x87e501f0U, 0x32160a38U, 0x91596f04U, 0xbb96f8beU, 0x121c5edfU, 0x7f730a82U, 0x618e6df7U, 0x996f2004U, 0xc0fd3033U, 0x8be27804U, 0x90171c24U, 0x685c720cU, 0x6f127317U, 0xc3d88a8eU, 0xd5532df9U, 0xb3ba000dU, 0xa701002aU, 0x67838036U, 0x7841402eU, 0x59672001U, 0x3ed13001U, 0xa9f87822U, 0x67661c04U, 0x5dd7f228U, 0x987f3322U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0xb8000000U, 0x34000000U, 0x7e000000U, 0x6d000000U, 0x65800000U, 0x94400000U, 0x67a00000U, 0xfb100000U, 0xd7080000U, 0xcf1c0000U, 0xd8920000U, 0xda4b0000U, 0x13398000U, 0xcac74000U, 0xb7676000U, 0x8777d000U, 0xdcfdd800U, 0x34202400U, 0xfe53de00U, 0x972a0700U, 0x2f482180U, 0x92b92ec0U, 0x3881ffa0U, 0x99c429f0U, 0xdfe25e08U, 0xc6b14734U, 0x871d4186U, 0x2495fec9U, 0x984da791U, 0x9c3f4de6U, 0x3044e00eU, 0x61a7900aU, 0x2113806U, 0xdc8bb412U, 0x8e58e61dU, 0xeeb6b31bU, 0xcb1b4785U, 0xce93ddfbU, 0x9b4c5812U, 0x2cbb642fU, 0xf586be2dU, 0xec46d71aU, 0xf3a479b7U, 0x95124ae4U, 0x20f4185U, 0x9e9efec7U, 0x32d4278cU, 0xd0e80dc3U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x70000000U, 0x18000000U, 0x24000000U, 0x6a000000U, 0xaf000000U, 0xc3800000U, 0x2a400000U, 0xa0600000U, 0xed100000U, 0x8b180000U, 0x70c0000U, 0xca960000U, 0x2b5f0000U, 0xd86a8000U, 0x8c054000U, 0xb606e000U, 0x3104f000U, 0x6e856800U, 0x7ac28400U, 0x7a53e00U, 0xa2327900U, 0xaae90f80U, 0x88c07e40U, 0xcca231a0U, 0xabb10750U, 0x5fafbe08U, 0xf327390cU, 0x2ff7efaeU, 0xeac88e55U, 0x1ab159bcU, 0x712c8372U, 0x29e00022U, 0x5850002dU, 0x50f80036U, 0x945c0024U, 0x93ee0016U, 0x4a430018U, 0x3064803aU, 0x2516402aU, 0xc71a601cU, 0x510eb018U, 0x2b910811U, 0x2ddf3415U, 0x9ea8b626U, 0xc5a70d19U, 0xd135d99eU, 0xf76ac35fU, 0xf826010U, 0x3c42b035U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x70000000U, 0xe8000000U, 0xac000000U, 0x12000000U, 0x5000000U, 0x68800000U, 0x13400000U, 0x73e00000U, 0xb7d00000U, 0xfe880000U, 0xda5c0000U, 0x17560000U, 0x71cf0000U, 0xf3ba8000U, 0x7982c000U, 0x1dc52000U, 0x93a37000U, 0x67b47800U, 0xcd994c00U, 0x85f22e00U, 0x60f9bd00U, 0x4a644d80U, 0xa1014c0U, 0x1d2863a0U, 0x55eaa9d0U, 0x76c8ae08U, 0xe63b7d0cU, 0x96416d92U, 0x5b6364f7U, 0x4941b9eU, 0xfd6fe5faU, 0x858c8016U, 0x45ddc009U, 0xb997a014U, 0xe1edb01eU, 0x60cf581dU, 0xfd393c31U, 0x99c2d624U, 0xcda1312fU, 0xa0b7c3bfU, 0x381b19ebU, 0xba31f638U, 0xbe5d4131U, 0x99513b8cU, 0x2ecc95e1U, 0x4238f81bU, 0xf8448c12U, 0xd4658e24U, 0x2d140d3dU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xf0000000U, 0x88000000U, 0xc4000000U, 0xa000000U, 0x8f000000U, 0x41800000U, 0xc0c00000U, 0xd2a00000U, 0x39d00000U, 0x43f80000U, 0xc32c0000U, 0xc8520000U, 0x6b3b0000U, 0x858e8000U, 0x8381c000U, 0xebc16000U, 0xc924f000U, 0xe17e800U, 0x9cdc1400U, 0xf43e7a00U, 0xdc0ebb00U, 0x5f462f80U, 0x8f635b40U, 0x39f255a0U, 0x4d6ae070U, 0x5bb0fa08U, 0xe08f7b0cU, 0xdd074f8aU, 0xb287ab4dU, 0x6745bd80U, 0xa366f462U, 0xa7f6801aU, 0xb06dc01fU, 0xd933602eU, 0xafcff033U, 0x4a616804U, 0x9771d42cU, 0x9c2d1a30U, 0x31d14b39U, 0x47ff47b7U, 0x692e8f44U, 0xb7554f9fU, 0xa2bcab5cU, 0x814b3d93U, 0x5b273473U, 0x5d17e007U, 0xcb593017U, 0xdfc8839U, 0x862fe428U, 0x80000000U, 0x40000000U, 0x60000000U, 0xb0000000U, 0xd8000000U, 0x6c000000U, 0x36000000U, 0x9f000000U, 0x50800000U, 0xfdc00000U, 0xc6600000U, 0xfd100000U, 0x3df80000U, 0x106c0000U, 0x90560000U, 0x26590000U, 0xfb1a8000U, 0x38bd4000U, 0xbfc8a000U, 0x21225000U, 0x27b70800U, 0xad0d5c00U, 0x4fc0fa00U, 0x9b633500U, 0x8967780U, 0x89bba540U, 0x3c4c0da0U, 0x6a65d050U, 0xeb12da38U, 0x72fc253cU, 0x28e9dfaeU, 0xd994a977U, 0xba3bff9bU, 0xaf0bb96cU, 0xcac457a1U, 0x2e4b564U, 0x8ad3a5abU, 0x3a9adc67U, 0x96fd283dU, 0x5aee4c3bU, 0xa491521cU, 0x9fb93922U, 0x734d0584U, 0x52e18c7bU, 0xa2d0a016U, 0xee9e5035U, 0x7cf90830U, 0x2be85c02U, 0x7147a08U, 0x4fb752aU, 0xd7ea57a6U, 0x3911b568U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0xb8000000U, 0xe4000000U, 0xee000000U, 0x43000000U, 0xf0800000U, 0x90400000U, 0x30a00000U, 0xcf700000U, 0xa6680000U, 0xf99c0000U, 0x1fb20000U, 0x7e8f0000U, 0xc24c8000U, 0xa8ae4000U, 0xda79e000U, 0x30e2d000U, 0xb7d62800U, 0x151ffc00U, 0x65f31600U, 0xf32c8f00U, 0x36bf3280U, 0x3206a6c0U, 0x8900a4a0U, 0x7d8469f0U, 0x13c67628U, 0xe8601f3cU, 0x8b90faa6U, 0xb7bb8af5U, 0xd3859ab5U, 0xb0c71ad9U, 0x8e252afU, 0x93d636c8U, 0xdb1d6cb6U, 0x16f645d2U, 0xbbafc818U, 0x42fd2c18U, 0xeca53e0fU, 0x5737320U, 0x2b6c2492U, 0x7a1a29cbU, 0xc7779604U, 0x3a6ecf2fU, 0xd39cd28dU, 0x82b776f3U, 0x75080ca8U, 0x468ad5c8U, 0xe648002fU, 0x66ac001bU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x10000000U, 0x98000000U, 0x9c000000U, 0xae000000U, 0x3d000000U, 0xa4800000U, 0xa4400000U, 0xdda00000U, 0x1f00000U, 0x35580000U, 0xc02c0000U, 0xa9320000U, 0x98bb0000U, 0x16798000U, 0x829e4000U, 0xc24f2000U, 0xdea61000U, 0xc073d800U, 0x9996c00U, 0x7c9d600U, 0xd0657700U, 0x9490be80U, 0xe948bb40U, 0xb20e8a0U, 0x56b38c70U, 0xc17f7608U, 0x491d2734U, 0xe18c468eU, 0xb6c7c763U, 0x18e2e6adU, 0x76d39758U, 0xbdec1e8aU, 0x1457eb52U, 0x50af90b0U, 0x7775b07aU, 0x7219d83fU, 0xac0e6c2cU, 0xbc02562bU, 0x7e003713U, 0x5061ebcU, 0x2880eb47U, 0x924410adU, 0x7ca0f071U, 0xb777831U, 0xac1a3c3eU, 0xb90cae2aU, 0xc844b23U, 0x704590bbU, 0xd7a2b067U, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0x28000000U, 0x64000000U, 0x1e000000U, 0xf1000000U, 0x41800000U, 0xcbc00000U, 0xdae00000U, 0xbd500000U, 0xfb380000U, 0xefec0000U, 0x9b160000U, 0xc0190000U, 0x2f5f8000U, 0x19ffc000U, 0x688f6000U, 0xdf865000U, 0x7ac7b800U, 0xfb646400U, 0x66964200U, 0x9dd9100U, 0x36b96980U, 0x7e2f1940U, 0xdef0aba0U, 0xf5cd4850U, 0x1226a238U, 0x9d340114U, 0x7b29b192U, 0xe9712d5dU, 0xcb0f51adU, 0x8741bd75U, 0x32a009afU, 0x7f70495aU, 0x6e089394U, 0x80c6ec50U, 0x5467803dU, 0xb613c025U, 0x9399601dU, 0xf9f5018U, 0x7d983806U, 0x869ba40eU, 0x1019220eU, 0x275bc12bU, 0xdfed1baU, 0x4e8b7d5fU, 0x6286e982U, 0x4140d94eU, 0xdfa7cba5U, 0xcf71873U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xd0000000U, 0xd8000000U, 0x34000000U, 0x9a000000U, 0x57000000U, 0xda800000U, 0xe400000U, 0x4da00000U, 0x40700000U, 0xf6980000U, 0x6c0000U, 0x96b20000U, 0x767d0000U, 0xfd398000U, 0x711a4000U, 0xfbae6000U, 0x8bd2f000U, 0xe7eb2800U, 0xbd728c00U, 0xb31d9600U, 0x58ac1700U, 0xab55f280U, 0x6eaeb940U, 0xf251e4a0U, 0xc928ee70U, 0x79927638U, 0xbc48a704U, 0xd402baaeU, 0x8a03c579U, 0xef06dab0U, 0x3e803568U, 0x4c4672a8U, 0x2ea5f952U, 0xf404abU, 0xafdd5e5aU, 0x974ebe06U, 0xd8829b0cU, 0xcd4264a6U, 0xbd23ae72U, 0x1137960fU, 0x8dbd173aU, 0xe05e72a7U, 0xe089f94cU, 0xbbe604acU, 0x49d05e7eU, 0x44ef3e3fU, 0x9df4db39U, 0x3a5e0487U, 0x178c5e54U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0xb8000000U, 0xcc000000U, 0xea000000U, 0x25000000U, 0xa5800000U, 0xba400000U, 0x4ba00000U, 0xc6b00000U, 0x93480000U, 0xaa7c0000U, 0x2e720000U, 0xee2f0000U, 0xf2ab8000U, 0x7f694000U, 0x4788a000U, 0x551cb000U, 0x27a63800U, 0x3cb62400U, 0x2e4b8e00U, 0x13f8d700U, 0xc6369c80U, 0x4c8d49c0U, 0x7b9e92a0U, 0x7360def0U, 0x3d2ae28U, 0x79e2704U, 0x116184a6U, 0xa2d19dc7U, 0xec1804b4U, 0x1027ddcaU, 0x4ff324bbU, 0xfa6e2de3U, 0xf20fbcbdU, 0x775bb9e8U, 0x70018a8aU, 0xa8000ae5U, 0x5406383aU, 0xf6062401U, 0x77038e10U, 0x4c84d735U, 0xf5c49ca6U, 0xd4e249c5U, 0x28951296U, 0xefb99eedU, 0x72920e02U, 0x42be971eU, 0x5315bc8cU, 0xb6f8b9faU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x50000000U, 0x98000000U, 0x44000000U, 0xc6000000U, 0xa7000000U, 0x2b800000U, 0xb4400000U, 0x5c200000U, 0x31500000U, 0x43a80000U, 0xbb7c0000U, 0x9d960000U, 0x9e4f0000U, 0x214b8000U, 0xec84000U, 0xdc8de000U, 0x77ad9000U, 0xf57e4800U, 0x46930400U, 0x67c9ae00U, 0x6c092b00U, 0x9a6b5f80U, 0xb41981c0U, 0x7b6171a0U, 0x8f4ead0U, 0x1db9ce08U, 0x5d73fb04U, 0x5afb778eU, 0xd4d355c5U, 0x6ced77b7U, 0xbedc55e8U, 0xb186f7b3U, 0xd14415c0U, 0xb6a317b3U, 0x599585f4U, 0x184b5f98U, 0x264981deU, 0x754971a2U, 0xf0c8ead8U, 0x6f8fce2dU, 0x22cfb39U, 0xa238f78dU, 0xf73715fdU, 0x45de9797U, 0x5802c5ccU, 0xa4053fbfU, 0x360051ccU, 0x6f04d984U, 0xf7857ed5U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0xd0000000U, 0x8000000U, 0xcc000000U, 0xee000000U, 0xd3000000U, 0x52800000U, 0x4ac00000U, 0xa5e00000U, 0xbed00000U, 0x68780000U, 0x562c0000U, 0x51920000U, 0x47db0000U, 0x42df8000U, 0xb75cc000U, 0xf5192000U, 0x33389000U, 0x83882800U, 0xbc63ac00U, 0x2941200U, 0xd55b3100U, 0xa81f0580U, 0xc2bbbf40U, 0x43cc97a0U, 0x97404e70U, 0x3ba0b208U, 0x3ef46104U, 0x17c98daaU, 0xdd404347U, 0xbaa38d99U, 0x89774377U, 0x188e0da7U, 0x42e08362U, 0xd650adb7U, 0x7bb8d34aU, 0x804ba582U, 0xc204ef79U, 0x8d021fabU, 0xf987b255U, 0xc45a808U, 0xc5246c02U, 0xea32b21bU, 0xb92f613aU, 0xf5160d97U, 0xba1c835dU, 0x47baad98U, 0x764fd34aU, 0x750625bcU, 0x2d832f59U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xf0000000U, 0xe8000000U, 0xb4000000U, 0x22000000U, 0x81000000U, 0x21800000U, 0x56400000U, 0xc2200000U, 0xa9100000U, 0xe6480000U, 0x2fdc0000U, 0x5e560000U, 0xb5ef0000U, 0x988e8000U, 0x3e3ec000U, 0xf921e000U, 0x15943000U, 0xa788d800U, 0xe8bc6400U, 0x7de64e00U, 0x39731b00U, 0xe77dcd80U, 0xa5810cc0U, 0x7c4303a0U, 0xa723d7d0U, 0xb291ae08U, 0x6d082b2cU, 0x5a7b9592U, 0x203a8d1U, 0x3104ad92U, 0x6984fcddU, 0x1244bb88U, 0x82543d9U, 0x9c16d80aU, 0xe5cf643eU, 0xf89ece13U, 0xbdf2db10U, 0x4abaad94U, 0xbce7fcfeU, 0xb8f43ba1U, 0x413883edU, 0x8fa7b811U, 0x61569412U, 0x636f761bU, 0x1c4b4f22U, 0x12db5b8cU, 0xb9d273d0U, 0x58ae8009U, 0xa62ec025U, 0x80000000U, 0x40000000U, 0x20000000U, 0x90000000U, 0xb8000000U, 0x1c000000U, 0x1a000000U, 0xd1000000U, 0x3800000U, 0x65c00000U, 0x27a00000U, 0xc0500000U, 0xe3b80000U, 0x516c0000U, 0x4960000U, 0x8f9b0000U, 0xe0f98000U, 0xee8f4000U, 0x71a22000U, 0xd357b000U, 0x9d3e1800U, 0x52b3400U, 0x33f0c200U, 0x6defab00U, 0x6dd0fb80U, 0xa97fe540U, 0x824fb9a0U, 0xf9840e50U, 0x44c4e228U, 0x2c231b34U, 0x919763a6U, 0x7a1b9163U, 0x463d5b88U, 0x2fac1563U, 0x69b201aeU, 0xa58bca59U, 0xe326180fU, 0x9517341aU, 0x4f5ec211U, 0x5ad8ab33U, 0xc1f7b91U, 0xc53ba55dU, 0xe92c1996U, 0x21f0fe55U, 0x88eeda3dU, 0xd0549f06U, 0x1bb839adU, 0x6d6c4e51U, 0x8e914222U, 0xe69ceb35U, 0xff7cdbbcU, 0x914f5554U, 0x80000000U, 0x40000000U, 0x20000000U, 0x50000000U, 0x48000000U, 0xec000000U, 0xb2000000U, 0x3000000U, 0xf3800000U, 0x70c00000U, 0x3f200000U, 0x9c300000U, 0xec580000U, 0x28ec0000U, 0x9bf60000U, 0x76fb0000U, 0xb91f8000U, 0x5a0ec000U, 0xa622000U, 0x9ed37000U, 0x65cc4800U, 0x64c42400U, 0x1926aa00U, 0xf9319700U, 0x5add8c80U, 0xbea9c140U, 0x7a92a6a0U, 0xe7ad9650U, 0x76128a28U, 0xbee9e704U, 0x86f6449aU, 0x147f256fU, 0x69582c9eU, 0xae68716bU, 0x35b2ceb8U, 0x639dc258U, 0x3e49e809U, 0xc8059404U, 0xac06c202U, 0x9201c302U, 0x5306ee9fU, 0xbb85b270U, 0x9cc22037U, 0x8d237020U, 0x9f34482cU, 0x1fd82414U, 0x5828aa1bU, 0xa4d69735U, 0xeacc0c80U, 0x55400166U, 0x72e10686U, 0x91972671U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x70000000U, 0xa8000000U, 0x4000000U, 0x2a000000U, 0xcb000000U, 0x32800000U, 0x68400000U, 0xada00000U, 0xabf00000U, 0x2ba80000U, 0xfddc0000U, 0x66b20000U, 0xb58f0000U, 0x97ee8000U, 0x627cc000U, 0x8a466000U, 0xf2a5f000U, 0x4b70c800U, 0x54e92c00U, 0xe4fae600U, 0x40030700U, 0xe001ae80U, 0x50020cc0U, 0xd807c8a0U, 0xac02cbf0U, 0x2e068628U, 0xe105f72cU, 0xf985e6a2U, 0x5ac4e0ddU, 0xc5e7ce80U, 0x657fcc3U, 0x805f00aeU, 0xd677e7c4U, 0x9b6e6025U, 0xd339f01dU, 0x2262c809U, 0xf5962c3aU, 0xe83c663fU, 0x78e3c73bU, 0xb9d5ce91U, 0x1f98fcf7U, 0xb011808aU, 0xa4fb27dbU, 0xa0000020U, 0xb000003dU, 0x8800003fU, 0x74000012U, 0x8200003fU, 0xcf00003eU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xd0000000U, 0x38000000U, 0x7c000000U, 0x6000000U, 0xf7000000U, 0xae800000U, 0x79400000U, 0x9d600000U, 0x22500000U, 0xc5880000U, 0x625c0000U, 0x86120000U, 0xff690000U, 0xfccd8000U, 0xdf3d4000U, 0x94472000U, 0xd2e45000U, 0xda97c800U, 0x232e6c00U, 0x9a28ae00U, 0x77a94900U, 0xd26a0580U, 0x534db8c0U, 0xf7fd2ba0U, 0x4ae0b1f0U, 0x56958e18U, 0x2d281904U, 0xf92a4db6U, 0x9b2b94ebU, 0x262d25afU, 0x91a9e8d2U, 0xf56ae3b2U, 0xc5cedde7U, 0xf2bd201aU, 0xd181500dU, 0x83c04821U, 0x46262c06U, 0xe2300e34U, 0x8059591bU, 0xfb176d93U, 0xa8eac4e3U, 0x480d6d87U, 0xd79fc4fdU, 0xdf32edbcU, 0xf7db84d7U, 0x7fd04da9U, 0x484e94deU, 0x477aa5beU, 0x88a1a8d3U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x70000000U, 0xd8000000U, 0x84000000U, 0xd6000000U, 0xc5000000U, 0x92800000U, 0xb6400000U, 0xdb200000U, 0xa0b00000U, 0x3380000U, 0x600c0000U, 0x79f60000U, 0xd9d0000U, 0xbf788000U, 0x6c2b4000U, 0xb8c3e000U, 0x9f641000U, 0xf892d800U, 0x5c0bdc00U, 0x1bf17600U, 0x269dd300U, 0x1cfcd080U, 0x46ef9240U, 0x94a326a0U, 0xa0740150U, 0x285c9618U, 0x7698c30cU, 0x14f8888eU, 0x8aee0e7dU, 0x6ea730a3U, 0xef778240U, 0x2ddffe89U, 0x415edd50U, 0x2e1b603cU, 0xd5bf5028U, 0xa049380dU, 0xf7d3cc3cU, 0x97adae39U, 0x56070f26U, 0x85032696U, 0x7284016cU, 0xc6449633U, 0x324c331U, 0x24b68880U, 0xd53f0e5fU, 0xa509b09fU, 0xeb71c26fU, 0xbbdc9eb3U, 0x645d8d5aU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x90000000U, 0xc8000000U, 0x8c000000U, 0xa000000U, 0xfd000000U, 0x44800000U, 0x35400000U, 0xff200000U, 0xd3b00000U, 0x38880000U, 0x88bc0000U, 0x94f20000U, 0x2eab0000U, 0xf18d8000U, 0x7238c000U, 0x22b52000U, 0xb60bb000U, 0xe0fc7800U, 0xbf516c00U, 0x5afe00U, 0xba200b00U, 0x23303880U, 0x73cc1fc0U, 0x549d46a0U, 0xb0c3d4f0U, 0x1ce7de08U, 0xd7bb14U, 0x469e409aU, 0x69c673c7U, 0xee623890U, 0x9a971fecU, 0x4438c69bU, 0x4db714e6U, 0xeb88fe14U, 0x873b0b0eU, 0x4a35b8a9U, 0x1948dfeeU, 0x2ada66aaU, 0xa46364c8U, 0x796263dU, 0x30be1705U, 0x20f19e8eU, 0x50adc8edU, 0xd28e7834U, 0x85ba6c33U, 0x28777e14U, 0xcfe8cb22U, 0x40ad1885U, 0xda8bafd2U, 0x80000000U, 0x40000000U, 0xe0000000U, 0xd0000000U, 0x78000000U, 0x8c000000U, 0x86000000U, 0x53000000U, 0x93800000U, 0x2bc00000U, 0x68e00000U, 0xb0f00000U, 0x1a380000U, 0x5c4c0000U, 0x45360000U, 0xdddd0000U, 0xb13d8000U, 0x3cb4000U, 0x8f6a000U, 0x363bd000U, 0xea48e800U, 0xbe312400U, 0xba5b5200U, 0x90fd5100U, 0xbe2fb480U, 0x7884ac40U, 0x944766a0U, 0xf523bd50U, 0x2315f218U, 0xcd4a8124U, 0x67b15ca6U, 0xa4988857U, 0xe899b49fU, 0xce99ac67U, 0xad9ae69dU, 0x9618fd7aU, 0x49db5238U, 0x2b3d5121U, 0x4ecfb49bU, 0x9474ac78U, 0x707f66acU, 0x766fbd4dU, 0x73a3f23aU, 0x68578121U, 0x2decdcb0U, 0x3c63c86bU, 0x92b714aaU, 0x141e7c49U, 0x18dc0eb2U, 0xa9b8d951U, 0x78b8006U, 0x65d64021U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xb0000000U, 0x18000000U, 0x44000000U, 0x6e000000U, 0x8d000000U, 0x7b800000U, 0xf7c00000U, 0xea00000U, 0xed700000U, 0x26280000U, 0xbdc0000U, 0xc8b20000U, 0xff8d0000U, 0x62a8000U, 0x1bdf4000U, 0xb3e000U, 0x1389d000U, 0x342d5800U, 0xbcdad400U, 0x9834f200U, 0x12ca7300U, 0xb6c99a80U, 0xa8cb30c0U, 0x5dcde8a0U, 0xd24f03f0U, 0x538f1238U, 0x942fa31cU, 0x6cdec29eU, 0x3030e4fdU, 0x4ec99abdU, 0x9ccb30c2U, 0x4bcde8bdU, 0xab4f03c2U, 0x5e0f1223U, 0xaaefa30bU, 0x77fec28fU, 0xa780e4e7U, 0x1dc19a98U, 0x8da730c2U, 0xabf7e88dU, 0xb26e03c0U, 0xb6bf922bU, 0x4561e30bU, 0xb9d5a2b0U, 0x505b74f3U, 0x2f75a2b2U, 0x392b74efU, 0x75da286U, 0xff774eaU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x10000000U, 0x58000000U, 0x94000000U, 0xae000000U, 0xe9000000U, 0xe4800000U, 0xa3400000U, 0x70600000U, 0xb7500000U, 0x61080000U, 0x91dc0000U, 0x58160000U, 0x6b6f0000U, 0xc1898000U, 0x249c4000U, 0xe5756000U, 0xdebe5000U, 0x26c17800U, 0x1ba48c00U, 0xee742e00U, 0xa9388100U, 0x8605e580U, 0xd50564c0U, 0x36864ba0U, 0x3842a5d0U, 0x1fe14e08U, 0x2396d114U, 0x11ac9dbeU, 0xf82de8e1U, 0xb9ec659dU, 0xffc924cfU, 0xae7b2b9aU, 0x5060f5c6U, 0xe756363bU, 0x990d5d34U, 0x15d93391U, 0xae1529d2U, 0x166ae02aU, 0x8b0d1019U, 0x6edd9800U, 0x71969c28U, 0xcaa83622U, 0x37ae5d3aU, 0x3d2eb389U, 0xd76a69d8U, 0x53880015U, 0x1f9c0023U, 0x9af60031U, 0x127f0012U, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0x18000000U, 0x7c000000U, 0x86000000U, 0xa7000000U, 0xda800000U, 0x2400000U, 0x51600000U, 0x45500000U, 0x23980000U, 0x594c0000U, 0x2f160000U, 0x56f90000U, 0x86188000U, 0xdd894000U, 0x6a362000U, 0xdc95000U, 0x5e514800U, 0x5f1d4c00U, 0x6c0ed600U, 0x4cf1f100U, 0x75eebd80U, 0xee3a840U, 0xe096eba0U, 0x1b3e1950U, 0xdab8f638U, 0xa478a12cU, 0xc05ff59eU, 0xe6eee463U, 0xe6603d87U, 0x37d3e866U, 0x25d84bafU, 0x22e0945U, 0x53479e1cU, 0x74e0bd22U, 0x81966ba3U, 0x6bb594dU, 0xf278d632U, 0xef58f125U, 0xa86e3db1U, 0x626e866U, 0x3bb6cbb7U, 0x9b0e497cU, 0x5e713e03U, 0x83acad03U, 0x4d870386U, 0xe0c64553U, 0xbf27c825U, 0x7a310c06U, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0x38000000U, 0xfc000000U, 0x86000000U, 0x11000000U, 0x5800000U, 0xdcc00000U, 0xe7e00000U, 0x79500000U, 0x94780000U, 0x4bac0000U, 0x5960000U, 0x43990000U, 0x7aff8000U, 0x45ef4000U, 0x4a332000U, 0x146a5000U, 0x94f2f800U, 0xf88c0400U, 0x6f23da00U, 0x9cb00100U, 0xe62aa180U, 0x5d524b40U, 0xbe78fba0U, 0x84a80a50U, 0xfd10fa38U, 0x24da5114U, 0xacd85996U, 0x58de4f7bU, 0x6adb218fU, 0x29d80b6bU, 0x7f5a5b98U, 0xcd181a67U, 0x64b8a20eU, 0x324a4502U, 0xe1c5dbabU, 0x7c675a73U, 0x3893822aU, 0xd81c151eU, 0x3b39239eU, 0x98e5e68U, 0x3aa1d83fU, 0x18765400U, 0xedc92213U, 0x9a000527U, 0xc7077b8bU, 0x4c874a42U, 0x3543da17U, 0x8520013eU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x90000000U, 0x98000000U, 0x84000000U, 0xe2000000U, 0x75000000U, 0xf7800000U, 0x9c00000U, 0xe0600000U, 0xa0100000U, 0xac780000U, 0xa5ac0000U, 0x59b20000U, 0xb4090000U, 0xcdc78000U, 0x22664000U, 0xa517e000U, 0x53ffb000U, 0xb06c7800U, 0xdfd23400U, 0x8319e200U, 0xe33b6500U, 0x798fff80U, 0x1505cd40U, 0xa781fda0U, 0x71c11870U, 0xf4627a18U, 0xda16e114U, 0x5d7a659eU, 0xb02c9c45U, 0x2577e03eU, 0xa3efb00cU, 0x6414783dU, 0x6e7e343bU, 0xa0abe223U, 0xa632650bU, 0xa1c87fabU, 0x4ba38d5cU, 0x15761da0U, 0x8beea876U, 0x8160205U, 0x78d519U, 0x2ba987afU, 0x42b2f970U, 0xc88d9fadU, 0x20853d42U, 0xab45e5a2U, 0x6e26dc4cU, 0x41b2002cU, 0xf0090036U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x50000000U, 0x8000000U, 0xc000000U, 0xce000000U, 0x25000000U, 0x64800000U, 0x37c00000U, 0x89a00000U, 0x36d00000U, 0xca980000U, 0x178c0000U, 0xd2b60000U, 0x3aed0000U, 0xd8418000U, 0xefe0c000U, 0x4372000U, 0x1e2c9000U, 0xa4631800U, 0x10706c00U, 0x9fcbea00U, 0x35525b00U, 0x32dc9f80U, 0x86d3c40U, 0x6e8055a0U, 0x70c3f750U, 0xb627d218U, 0x1892a704U, 0x147a6dbaU, 0x5d3e0b57U, 0x4c58a011U, 0x90ad501aU, 0x84a3b812U, 0xae513c10U, 0x8b5e5239U, 0xef2e6703U, 0x4ae34da3U, 0x20b39b41U, 0xc9ec383fU, 0x7dc0fc16U, 0x2ea6f218U, 0x5953372cU, 0xecd8f587U, 0xc56ea77aU, 0x56046a0fU, 0x81039b14U, 0x16843f99U, 0x84c06c6bU, 0xcc23edaaU, 0xa792cb56U, 0x80000000U, 0x40000000U, 0xa0000000U, 0x90000000U, 0xe8000000U, 0xc4000000U, 0x66000000U, 0x21000000U, 0xdb800000U, 0xe5400000U, 0x6ba00000U, 0x52900000U, 0x42b80000U, 0xc16c0000U, 0x16760000U, 0xb88f0000U, 0xedc58000U, 0x1a61c000U, 0xd2f46000U, 0x5b499000U, 0x52a17800U, 0xd513f400U, 0xddffc600U, 0x51cdff00U, 0xf4665580U, 0x47f68b40U, 0x3ecdf3a0U, 0x2ae2e450U, 0x2f32de08U, 0xe92b9b34U, 0xe456eb92U, 0x785b8055U, 0x465fe003U, 0x9b5b5029U, 0xaade9807U, 0x5c98a415U, 0x43b95e16U, 0xcae95b1cU, 0xbb310b93U, 0x872cd06cU, 0x31577803U, 0xbddcf437U, 0xae1a460cU, 0x897c3f18U, 0x5a0a35a5U, 0x8f031b51U, 0xee828b9cU, 0x10c21055U, 0xfbe69826U, 0x6cb4a42aU, 0x106f5e36U, 0x55f65b12U, 0x80000000U, 0x40000000U, 0x60000000U, 0x30000000U, 0x8000000U, 0x14000000U, 0x22000000U, 0x5d000000U, 0x6c800000U, 0x9ac00000U, 0x4ca00000U, 0x54d00000U, 0xbe780000U, 0xbc6c0000U, 0xb60000U, 0xeb090000U, 0x62468000U, 0xb463c000U, 0x2573e000U, 0xb6283000U, 0x90d7b800U, 0xe47b2c00U, 0x9d69a200U, 0x6a33db00U, 0x6cae780U, 0xb65a340U, 0x34f0a5a0U, 0x106e4850U, 0x7eb5fa38U, 0xe00cc71cU, 0x41c2fd9aU, 0x17245449U, 0x8b95602aU, 0x169bf002U, 0x6bdc580bU, 0xde3f1c3dU, 0x5081a0aU, 0x7141f736U, 0xdbe5c5b4U, 0x8835b86dU, 0x7bc9a214U, 0x37e3db23U, 0x9632e793U, 0x40c9a34eU, 0x1c66a59cU, 0x2177487aU, 0xcc2b7a1dU, 0xe1d30725U, 0xb6ff1d9aU, 0x6ca96461U, 0x35125816U, 0xf95a1c22U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0x18000000U, 0x54000000U, 0xa000000U, 0x29000000U, 0x7800000U, 0x2bc00000U, 0x69600000U, 0xb7900000U, 0xd6080000U, 0xd85c0000U, 0xda320000U, 0x987f0000U, 0x26808000U, 0x10434000U, 0x24a36000U, 0x19f77000U, 0x5d19d800U, 0x5f17d400U, 0x4d4f3200U, 0x9e7e5d00U, 0xb1814b80U, 0xa4c592c0U, 0x89e519a0U, 0x10d0bff0U, 0xf62f8a28U, 0x74edf91cU, 0xda0d218eU, 0x665c5bf9U, 0x69328024U, 0x1efc402fU, 0x46c3e00bU, 0xce4302cU, 0xd952b81dU, 0x56eca432U, 0x7f0cea2dU, 0x1fda8911U, 0xd1f4f982U, 0x411b8fdaU, 0x8915b205U, 0x924e1d3fU, 0xf6f8abbdU, 0xeac2a2d8U, 0xc2e5218eU, 0x52505bd2U, 0x34688027U, 0xd4f4022U, 0x7e796039U, 0x2184703bU, 0x80000000U, 0xc0000000U, 0x60000000U, 0x70000000U, 0x48000000U, 0xe4000000U, 0x6e000000U, 0x7f000000U, 0x27800000U, 0x47c00000U, 0x37a00000U, 0x89d00000U, 0xf9a80000U, 0x81bc0000U, 0x2cb20000U, 0xa15d0000U, 0xb6848000U, 0xdf47c000U, 0x37e66000U, 0x89b7d000U, 0xfdac800U, 0x15c1e400U, 0x3aa67200U, 0x73537b00U, 0x1cef4f80U, 0x8f5ffdc0U, 0x69875da0U, 0xe8c756f0U, 0x4820da38U, 0x12144f2cU, 0xc0d758aU, 0xfd6ba2e5U, 0xe39e8029U, 0x3fa6c016U, 0xcdd0e00aU, 0x87ad1012U, 0xc6b82816U, 0xa731f40aU, 0x6c9ada28U, 0x90254f1dU, 0xe13f5bcU, 0xae0d62d9U, 0x786e600bU, 0x9d1bd00dU, 0xc4e0c806U, 0xf430e429U, 0x118f217U, 0xa6e5bb36U, 0x1137afbbU, 0xf9eedf1U, 0x15a575adU, 0xccd7a2fcU, 0x80000000U, 0x40000000U, 0xe0000000U, 0xd0000000U, 0xb8000000U, 0x44000000U, 0xba000000U, 0x81000000U, 0x4e800000U, 0x21c00000U, 0xda600000U, 0x71500000U, 0x82b80000U, 0xac2c0000U, 0x8ff60000U, 0x7d0d0000U, 0xcf058000U, 0x5d814000U, 0xf240e000U, 0x9b217000U, 0x9f41800U, 0xa20c5c00U, 0x8a82aa00U, 0xdbc1d500U, 0xbb602d80U, 0xefd01140U, 0x1b7a67a0U, 0x324cb450U, 0x44a05218U, 0x7eb1f924U, 0x2dab1f96U, 0xf3b0d865U, 0x552e0020U, 0x25710021U, 0xd6cb8005U, 0xfc60401cU, 0x9e53600bU, 0xaf3d3005U, 0xd6697838U, 0x38d06c17U, 0x32f85210U, 0x120df93cU, 0xa2851fa6U, 0xc7c1d854U, 0x9565800fU, 0x6cd1400aU, 0x90f8e025U, 0xe70d7025U, 0x3e02183dU, 0x9b015c18U, 0xff872a1eU, 0x740950bU, 0x80000000U, 0x40000000U, 0x20000000U, 0x50000000U, 0xf8000000U, 0xec000000U, 0xc6000000U, 0x21000000U, 0xd4800000U, 0x52400000U, 0x6ee00000U, 0x16f00000U, 0x37080000U, 0xb9bc0000U, 0x37560000U, 0xe59b0000U, 0x27078000U, 0x95874000U, 0xf6c1a000U, 0x94a3d000U, 0x6c10f800U, 0xbf8cc00U, 0x69b60600U, 0x7b6aed00U, 0x54086480U, 0xfe3f1dc0U, 0xca97c2a0U, 0x42ba20d0U, 0xecd15e28U, 0x765af104U, 0xb5211ab6U, 0xa0d67cefU, 0xa05e002fU, 0x4c270023U, 0xc851800cU, 0xcc1c4008U, 0xefc62010U, 0xcc24902aU, 0x88515827U, 0xec1b1c23U, 0xbfc6fe35U, 0x34222103U, 0x6456629fU, 0x2a19f0d9U, 0x9ec1a619U, 0xe0a23d3eU, 0x36171ca3U, 0x44fc91caU, 0x88366496U, 0xd7a81dd2U, 0x8fae42abU, 0x73aa60c8U, 0x80000000U, 0x40000000U, 0xe0000000U, 0x90000000U, 0x88000000U, 0xd4000000U, 0x9a000000U, 0x8b000000U, 0xd9800000U, 0x60c00000U, 0x6200000U, 0xe4100000U, 0x37680000U, 0xb5bc0000U, 0xe1f60000U, 0x8dd0000U, 0xf4078000U, 0xaa02c000U, 0x7305e000U, 0x1586f000U, 0xa6c4c800U, 0xc3243400U, 0x2c911a00U, 0x52f6f00U, 0xadddd80U, 0x63039dc0U, 0xdd8127a0U, 0x92c602d0U, 0xc9263218U, 0x2f90ab34U, 0x8af8f9aU, 0xf01a06d1U, 0xee200024U, 0xe0100007U, 0xc5680028U, 0x7abc001eU, 0x2a760015U, 0x371d0014U, 0xb1a7802aU, 0xa5d2c036U, 0x9bcde003U, 0x24eaf037U, 0x767ac804U, 0x9a553411U, 0xe089a2cU, 0x124caf02U, 0x6c29bd8dU, 0xd45aadf7U, 0xfc478fbfU, 0xee6606cbU, 0x3076000dU, 0xfc1d0028U, 0x80000000U, 0xc0000000U, 0x60000000U, 0xf0000000U, 0xa8000000U, 0xe4000000U, 0x5a000000U, 0xa1000000U, 0xa5800000U, 0xb3c00000U, 0x22200000U, 0xd9700000U, 0x82680000U, 0x1edc0000U, 0x91920000U, 0xc0bd0000U, 0x70008000U, 0x6804c000U, 0x84016000U, 0xaa027000U, 0x9029800U, 0x41870400U, 0xe9c26200U, 0x83218700U, 0x7cf2f680U, 0x31af46c0U, 0x3cf9f4a0U, 0x48e0b1f0U, 0x42d39a38U, 0x6ed9f30cU, 0xf9928cb2U, 0x44bd05c5U, 0xda00001cU, 0x61000021U, 0xc5800027U, 0x43c00038U, 0x8a20000bU, 0x3d700023U, 0xd868003eU, 0xbfdc0019U, 0x3412002dU, 0x737d001bU, 0x52208030U, 0xb174c01cU, 0x669601dU, 0xb4de7037U, 0x98909807U, 0x813a040aU, 0x99c2e224U, 0xeb25472aU, 0xf8f39684U, 0x9bad36c6U, 0x80000000U, 0x40000000U, 0x60000000U, 0x90000000U, 0x18000000U, 0xc000000U, 0xd2000000U, 0xc9000000U, 0xba800000U, 0xdb400000U, 0x72e00000U, 0x4ef00000U, 0xcfc80000U, 0x837c0000U, 0xdcd60000U, 0xa6190000U, 0x85e38000U, 0x3f764000U, 0x1f0ba000U, 0xc5e7000U, 0xf1861800U, 0x90c2fc00U, 0xef221e00U, 0xbd574500U, 0x2edc9480U, 0x66c023c0U, 0x50232aa0U, 0xf8d016d0U, 0xd01a2638U, 0x7ae48934U, 0x1af0b29eU, 0x71cdaae7U, 0x8781812U, 0xb757fc21U, 0xcbdf9e02U, 0xfe440520U, 0xca62b4b4U, 0x24b113e6U, 0x9bad12bbU, 0xdccadad1U, 0xa4fd8012U, 0x313400bU, 0x84be2014U, 0xd2713012U, 0xd38e3827U, 0x281acc1dU, 0xa6e7a616U, 0xb0f7c90aU, 0x24ce9294U, 0x78fc9ae1U, 0xa9162038U, 0xd1bd3016U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xf0000000U, 0x68000000U, 0xac000000U, 0x1a000000U, 0x63000000U, 0x24800000U, 0x28c00000U, 0x2c200000U, 0xdf100000U, 0xaf080000U, 0x8fdc0000U, 0x36720000U, 0xbb7f0000U, 0xa3a28000U, 0x4f52c000U, 0xf9ef2000U, 0x43ee3000U, 0x10ea8800U, 0x7c6c5c00U, 0x8ac3200U, 0x568cff00U, 0x469c1d80U, 0xd710b6c0U, 0x130d0fa0U, 0x2ddd79f0U, 0x61711a28U, 0x41ff530cU, 0x5e650792U, 0x3ef3e5d7U, 0x49ba083cU, 0xcc819c03U, 0x44c19207U, 0x16200f2eU, 0x4c11b598U, 0xe38edad6U, 0xb19b586U, 0x52dafcU, 0x76bb587U, 0x282ddacbU, 0xe849359cU, 0xe3bf1aedU, 0x27861589U, 0x1c412adfU, 0xbce49d8aU, 0xc73176d4U, 0xae1aaf98U, 0xf5d289dbU, 0xe42c3230U, 0xe24cff11U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x30000000U, 0x28000000U, 0x24000000U, 0x8a000000U, 0xb1000000U, 0xe0800000U, 0xbc00000U, 0x61a00000U, 0x46500000U, 0x84a80000U, 0xe43c0000U, 0x77b20000U, 0x39190000U, 0x4c228000U, 0xb16c000U, 0x21cf6000U, 0x48f000U, 0xe30a9800U, 0x7d6eac00U, 0xc89f8a00U, 0xb7631b00U, 0x9976db80U, 0x3a3cf9c0U, 0x44b431a0U, 0x9c9e12f0U, 0x3562f218U, 0xdc76873cU, 0x48bc29b2U, 0xf2767ec5U, 0xb3ba1808U, 0x43f16c15U, 0x68fa6a22U, 0x1912b22U, 0x6b0923aaU, 0x496fa5daU, 0xba99a3bbU, 0x3a6065f4U, 0xfff4439cU, 0x2efe55c9U, 0xfe91bb84U, 0x808809e8U, 0x3b2ca98aU, 0x1479bee2U, 0x9c57f825U, 0xedaf5c0aU, 0xe8bf9229U, 0xe277770aU, 0x4bbc31b5U, 0x7ff212ecU, 0x80000000U, 0x40000000U, 0x20000000U, 0x50000000U, 0x18000000U, 0xb4000000U, 0x2000000U, 0x7b000000U, 0xcc800000U, 0xe1c00000U, 0x19a00000U, 0x80900000U, 0xeea80000U, 0x6fc0000U, 0x4e760000U, 0x695b0000U, 0xd7e78000U, 0x40704000U, 0xb45c6000U, 0x5a633000U, 0xf2310800U, 0x9ab91c00U, 0xed97fa00U, 0x4b2edb00U, 0x68ba0d80U, 0x9e90efc0U, 0xbaf97a0U, 0x6f7a04d0U, 0xe6351228U, 0x88b8b704U, 0xae969f8eU, 0x63af18f9U, 0x937ce826U, 0x48316c23U, 0x45bd123bU, 0x1b14b732U, 0x35e89fb3U, 0xa79818f5U, 0x30c5681dU, 0x32262c2fU, 0x73d0f213U, 0x93ccc737U, 0x864a77a6U, 0xc00e74c7U, 0xcce9fa03U, 0x5019db09U, 0x3d838db9U, 0x9a47afc6U, 0xf2e27792U, 0x49f274f9U, 0x6c1ffa1fU, 0xf382db38U, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x90000000U, 0x98000000U, 0xbc000000U, 0xae000000U, 0x87000000U, 0xf0800000U, 0xc7c00000U, 0xca00000U, 0xd5100000U, 0x46080000U, 0xa5dc0000U, 0x44f20000U, 0x9d7b0000U, 0xdbe58000U, 0xee764000U, 0x37bc2000U, 0x82c01000U, 0x2d238800U, 0xe9535c00U, 0xdbe84a00U, 0x18aaa300U, 0x39cea980U, 0x4578d6c0U, 0x7e0c3a0U, 0x707565f0U, 0xb8ba6208U, 0x5643af14U, 0xf8e34b8eU, 0xccf639cbU, 0x797a282dU, 0x69e50c3eU, 0x5777e23fU, 0xd839ef34U, 0x9856b99U, 0x484129ebU, 0xb7e62019U, 0xb877100dU, 0x3cbc0814U, 0xd4421c1bU, 0x49e3ea02U, 0x777f306U, 0xe03c8181U, 0x2581dad3U, 0x7e45218bU, 0x8ce78afcU, 0xe6f28980U, 0x7c78c6e6U, 0x28634b8aU, 0x5b3639e5U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0x18000000U, 0x64000000U, 0x1e000000U, 0x1b000000U, 0x5a800000U, 0xf1c00000U, 0x53a00000U, 0xa1100000U, 0xe2880000U, 0xf5c0000U, 0x8bf20000U, 0xa8ff0000U, 0xcce38000U, 0xc5704000U, 0x4f3ae000U, 0xd8415000U, 0x94e6e800U, 0x41702c00U, 0xa13b2a00U, 0xb410b00U, 0xb2606180U, 0xcab462c0U, 0xf79baba0U, 0xebd739f0U, 0xfbaca228U, 0x678c3704U, 0x8edd438eU, 0xb715edU, 0xda9f8821U, 0x26513c2fU, 0xe2ef2219U, 0xbcec770eU, 0x47efa384U, 0xed6a45cdU, 0xd4ab600bU, 0xfb0e101dU, 0x201f8804U, 0xc7913c21U, 0x894f2203U, 0xa9fc772aU, 0xa367a39fU, 0x9d3645c2U, 0x1bd96022U, 0xb9311000U, 0xe5dc0822U, 0x52317c3fU, 0x775dc229U, 0xdff1271cU, 0x80000000U, 0x40000000U, 0xe0000000U, 0x30000000U, 0xf8000000U, 0x14000000U, 0xce000000U, 0x35000000U, 0x800000U, 0xe3c00000U, 0x97200000U, 0xe7100000U, 0xd0e80000U, 0xc73c0000U, 0xc9760000U, 0xf81d0000U, 0xb2628000U, 0xeaf44000U, 0xaa586000U, 0x20035000U, 0x90021800U, 0x28060c00U, 0xdc00ea00U, 0x2205cf00U, 0xef032580U, 0xfb80d1c0U, 0xd645afa0U, 0x74674ed0U, 0x93f01218U, 0xa0d8d31cU, 0xf0c7b786U, 0xdea142c9U, 0xf650f82dU, 0x830d1c18U, 0xa08c920bU, 0xf2cd9339U, 0x60ab579bU, 0x1a5b52c4U, 0x98000002U, 0x64000015U, 0xd600003eU, 0x1100003bU, 0x36800005U, 0xc2c00038U, 0x59a00001U, 0x31d0000eU, 0x4748003cU, 0xc3ec0004U, 0x8ebe001aU, 0xd8310001U, 0xabfc8012U, 0xd5d5400fU, 0x80000000U, 0x40000000U, 0x60000000U, 0x10000000U, 0x28000000U, 0x14000000U, 0x62000000U, 0x87000000U, 0x8c800000U, 0xbac00000U, 0x5f200000U, 0xb9d00000U, 0xf8d80000U, 0xeacc0000U, 0x74b60000U, 0xdee90000U, 0x3fe78000U, 0x1df3c000U, 0xdb8ae000U, 0x5dd73000U, 0xe2dc6800U, 0x31cffc00U, 0x9e342200U, 0xa92b5700U, 0x7f447380U, 0xf0670e40U, 0x41b4b1a0U, 0xdd6e6950U, 0x6da52a38U, 0xa2105b14U, 0x867ed992U, 0xe6589541U, 0xaf0e8832U, 0xfb14cc34U, 0xbbfe4a23U, 0x551dab0bU, 0x516fd1beU, 0x3a39945U, 0xb142211U, 0xc3fb5725U, 0x91c7398U, 0x376b0e67U, 0xcea2b1afU, 0x1497694bU, 0x97baaa27U, 0x6bff9b1fU, 0x5d1a39a2U, 0x356aa543U, 0x59a36035U, 0xb011f03bU, 0x397f0813U, 0x56de0c30U, 0x80000000U, 0xc0000000U, 0x60000000U, 0x50000000U, 0x98000000U, 0xf4000000U, 0xfa000000U, 0xc7000000U, 0x95800000U, 0x80c00000U, 0xaaa00000U, 0x17100000U, 0xdb980000U, 0x554c0000U, 0xd4f20000U, 0xd0ed0000U, 0xca658000U, 0x2db04000U, 0x34886000U, 0x2ad6f000U, 0xe3bb2800U, 0x371a3400U, 0x750ffa00U, 0xa012ab00U, 0x26196180U, 0x898cf240U, 0xb854fba0U, 0x96f9a970U, 0x4d793238U, 0x50be2f24U, 0x989dd3beU, 0x52ce9d69U, 0xcf334838U, 0x29ccc43cU, 0xcb4d203U, 0x89f05U, 0x5e969ba9U, 0x5d5e5958U, 0xceed9a02U, 0xcf655b11U, 0xbb35c9beU, 0x13cb8655U, 0xabb6e1abU, 0xc58db277U, 0x46531b8fU, 0x3fe1941U, 0x23fdfa3bU, 0xd3ffab0aU, 0x7bfce1bdU, 0x47fcb273U, 0xd1fc9bb2U, 0x18ff5949U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x70000000U, 0x28000000U, 0xa4000000U, 0x7e000000U, 0xe5000000U, 0x8d800000U, 0x8ec00000U, 0x12600000U, 0x1bf00000U, 0x14880000U, 0xa6bc0000U, 0xdad20000U, 0xbdf0000U, 0x17a68000U, 0xd914c000U, 0xd03d6000U, 0xac915000U, 0x62fb9800U, 0x6cf36400U, 0x360e6a00U, 0x46ff8d00U, 0xd2f08080U, 0xf309bdc0U, 0xbb798aa0U, 0x743460f0U, 0x456e1228U, 0xde89792cU, 0x85b81282U, 0x6e5404f5U, 0x8a9cf835U, 0x9c013420U, 0x62017234U, 0x47072906U, 0xea850aadU, 0x1443a0ccU, 0x2e27f23eU, 0x91d3e926U, 0xfb586a98U, 0xb8e2f0d4U, 0xefb46a1dU, 0x6aac8d2bU, 0x6f6c00a3U, 0xad8e7dd1U, 0x69386a93U, 0x6312f0c8U, 0xdb3c6a23U, 0xbc108d2fU, 0x9dbe00a9U, 0x2517df9U, 0x80000000U, 0xc0000000U, 0x20000000U, 0xb0000000U, 0x28000000U, 0x3c000000U, 0x6e000000U, 0x7000000U, 0x81800000U, 0xf400000U, 0x3600000U, 0x59500000U, 0xaff80000U, 0xd06c0000U, 0x8fb20000U, 0x4bef0000U, 0x85f08000U, 0x180ac000U, 0xf165a000U, 0x40511000U, 0x217b0800U, 0xd2ac5400U, 0xc5944600U, 0x2adeb900U, 0x9cdd2d80U, 0x6fd93740U, 0x2c5c4ba0U, 0xd21c5e70U, 0x43ffce28U, 0xc6682d1cU, 0xcb4cb82U, 0x6a9e63U, 0xf7b06e31U, 0xcfea3d3eU, 0x4ff543b3U, 0x650f0a6eU, 0x25e3080aU, 0xa790542aU, 0xabde4638U, 0x65db90fU, 0x3f1fada2U, 0xf7cf76aU, 0x35a96bb9U, 0xd4178e73U, 0xbd99663eU, 0x8bb9693dU, 0x64898595U, 0xeaa77343U, 0x84f18582U, 0x428b7372U, 0x81a3859aU, 0xd374734dU, 0x80000000U, 0x40000000U, 0xa0000000U, 0x10000000U, 0x18000000U, 0xd4000000U, 0x66000000U, 0xfd000000U, 0x4d800000U, 0x8a400000U, 0xa1a00000U, 0xe9700000U, 0xcd380000U, 0xe78c0000U, 0x9f560000U, 0xa90f0000U, 0x31918000U, 0x96a4000U, 0x1e076000U, 0xd9071000U, 0x83811800U, 0xab43a400U, 0x4625ce00U, 0x2c301700U, 0xba1b1a80U, 0x343e9840U, 0x340834a0U, 0x8c13df50U, 0x2b2d5608U, 0x63a5f314U, 0x9a77b4aeU, 0x1ba9f71U, 0x9a4db63fU, 0xe3b7a31aU, 0xe3584ca2U, 0x49186b59U, 0xb8b8001dU, 0xe9cc003dU, 0xe0f6002aU, 0x797f0038U, 0xcf298001U, 0x4da64004U, 0xb71601aU, 0xee38102dU, 0x9308982bU, 0x2695e42fU, 0xabecae28U, 0x52c4070cU, 0x5a65828eU, 0xd8947c5aU, 0xc2ed1abfU, 0xd941984aU, 0x80000000U, 0xc0000000U, 0xa0000000U, 0x90000000U, 0x28000000U, 0xa4000000U, 0x2a000000U, 0x9f000000U, 0x32800000U, 0xc4400000U, 0xf7a00000U, 0xed700000U, 0xf0680000U, 0xffdc0000U, 0x6e520000U, 0x385b0000U, 0x67958000U, 0x93bc000U, 0x1056000U, 0x6f86f000U, 0x6dc1e800U, 0xbb64cc00U, 0x6997a600U, 0x7c384700U, 0xc841280U, 0x94432c0U, 0x762354a0U, 0x5b145f0U, 0x5e8bce08U, 0xec8b4b14U, 0xaf8cd4a2U, 0x9b0d85cdU, 0xde492e20U, 0x866d7b3eU, 0xa6dddcaeU, 0x7dd479f2U, 0xc39a001bU, 0x75f70013U, 0x6b2f8023U, 0x9afcc007U, 0xd762e021U, 0x17963029U, 0xd1390835U, 0xbd05fc10U, 0x59812e29U, 0x54c17b17U, 0x98e7dcbdU, 0x2a5379c0U, 0xe25d8004U, 0xe097c03cU, 0x27bf602aU, 0x6341f02cU, 0x80000000U, 0xc0000000U, 0xe0000000U, 0x70000000U, 0x48000000U, 0xc000000U, 0xbe000000U, 0x69000000U, 0x40800000U, 0x35400000U, 0x97e00000U, 0x40300000U, 0xb2180000U, 0xa3ec0000U, 0xb1520000U, 0xba690000U, 0xac908000U, 0x84cfc000U, 0xfd412000U, 0x5be01000U, 0x1e33f800U, 0xab1aac00U, 0xab681e00U, 0x88143d00U, 0x93884a80U, 0x85a5f340U, 0x7651f4a0U, 0x6bee1e70U, 0x7d536618U, 0xe46d512cU, 0xb59374aaU, 0x8c48de5fU, 0xc402c61dU, 0x72028129U, 0x3701ac87U, 0x5982624bU, 0x3dc12007U, 0xaea0102eU, 0x69d3f81eU, 0x9b2aac3eU, 0x51701e02U, 0x27f83d08U, 0x9cda4a8dU, 0x56ccf345U, 0x9a417488U, 0xda61de62U, 0x17f24629U, 0xffbd412eU, 0x19b88c80U, 0x84be725eU, 0xde38d800U, 0x407fbc12U, 0x80000000U, 0x40000000U, 0x60000000U, 0x30000000U, 0xe8000000U, 0x34000000U, 0x12000000U, 0xfd000000U, 0xe0800000U, 0x50400000U, 0x2aa00000U, 0xb3f00000U, 0x5580000U, 0x4a6c0000U, 0xebd60000U, 0x5be90000U, 0xe5168000U, 0x720cc000U, 0x77c1e000U, 0x7362b000U, 0x6b933800U, 0xe948cc00U, 0xeae65600U, 0x61579f00U, 0x3aa85e80U, 0xb1355f40U, 0x92b968a0U, 0x8bbcb050U, 0xe13bee38U, 0xf07f931cU, 0x2c59e8a2U, 0xc8e97041U, 0xce948e1eU, 0x95cde322U, 0xfca530a4U, 0x94f60c67U, 0x7cd96028U, 0x30ab7025U, 0xb0325817U, 0x43fbc0dU, 0xecfa0e39U, 0xa1d231dU, 0xd54ad08dU, 0xbce1bc59U, 0x652d83dU, 0x232a7c16U, 0xfbf56e2fU, 0x215f5310U, 0xe06e08a2U, 0xfad2c061U, 0x75693637U, 0x6e55ef11U, 0x80000000U, 0xc0000000U, 0xe0000000U, 0xb0000000U, 0xa8000000U, 0x2c000000U, 0x96000000U, 0x23000000U, 0x15800000U, 0xf1400000U, 0x54600000U, 0x8a900000U, 0xe0380000U, 0xf06c0000U, 0x9a720000U, 0x67690000U, 0x5df68000U, 0xef2ec000U, 0x19172000U, 0xa7e5000U, 0x658be800U, 0x43a75400U, 0xe237d600U, 0xab8fd100U, 0xc4a62b80U, 0x1db7e740U, 0xf7c85da0U, 0x2244a670U, 0xc9e0be18U, 0x7d3451cU, 0x3a5a5d92U, 0xddfda667U, 0xd5ce3e2fU, 0xd3418533U, 0xa5677d98U, 0xe616f658U, 0x1f9561aU, 0xcbcd1125U, 0x8c430bb0U, 0x3ee0b77aU, 0xb0553591U, 0xfa1d3262U, 0x5184819U, 0xe9ec414U, 0xa0dd9e3eU, 0x6f38151eU, 0xb3ed35a3U, 0xa831326aU, 0x968a480eU, 0x8e27c439U, 0x77731e01U, 0xf5ead504U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xf0000000U, 0xf8000000U, 0x14000000U, 0x3a000000U, 0x89000000U, 0x9b800000U, 0xbbc00000U, 0x5e00000U, 0x55700000U, 0xb9080000U, 0x7e3c0000U, 0x5c160000U, 0x673f0000U, 0x2f968000U, 0x60fa4000U, 0xc766000U, 0x6a8cf000U, 0x89fb5800U, 0x87f1b400U, 0x79481200U, 0x901f9900U, 0x481c880U, 0x674695c0U, 0xc6a13aa0U, 0xf1d3bcd0U, 0x25dbca08U, 0x2676d2cU, 0x78b73a96U, 0xbbecbcf9U, 0xf3cd4a10U, 0xb45d2d37U, 0x28a15a80U, 0xa2d04cf0U, 0x675e1239U, 0x2a20992eU, 0x2a974889U, 0xc57cd5d4U, 0xacb75a81U, 0x61ef4cfdU, 0x2ac8921bU, 0x27dad91aU, 0x7f612896U, 0x893025caU, 0x812c02a7U, 0x81aef8c0U, 0x74e88039U, 0x27494022U, 0x9b1ee03aU, 0xa205b03cU, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0x88000000U, 0x4000000U, 0x5a000000U, 0x45000000U, 0x1b800000U, 0xa2400000U, 0x68600000U, 0x23900000U, 0xedf80000U, 0xe9ac0000U, 0xf1760000U, 0x9da90000U, 0x63708000U, 0xbca9c000U, 0xd2f36000U, 0xd3ef7000U, 0xa513b800U, 0x83f5400U, 0x658c5e00U, 0xd985d900U, 0xdb451380U, 0xc5e5e940U, 0x6ad2ada0U, 0x91a8050U, 0x32f96638U, 0x972a4d2cU, 0xd8b2adbaU, 0x2f8a807dU, 0xa4816614U, 0x2cc64d00U, 0xc9a4ad88U, 0x95b38045U, 0x7009e61eU, 0x3cc38d31U, 0xf1a1cdafU, 0x79b5f05fU, 0xde0ade03U, 0xabc51924U, 0xab26f3b0U, 0x9a73596dU, 0x512a7593U, 0xfbb6a458U, 0xc7088015U, 0xf645c024U, 0x6a65602fU, 0x7a967034U, 0xd07b3809U, 0xd8ea940cU, 0x80000000U, 0xc0000000U, 0x20000000U, 0xd0000000U, 0xf8000000U, 0x1c000000U, 0x2e000000U, 0xf000000U, 0xc3800000U, 0x24400000U, 0xe6a00000U, 0x72100000U, 0x2bd80000U, 0x2c0c0000U, 0xf4320000U, 0x580f0000U, 0xde338000U, 0x950f4000U, 0x14b22000U, 0x99c91000U, 0x27d3c800U, 0x83e0400U, 0x543c8e00U, 0x9a3a0f00U, 0x653f0980U, 0x8ebef440U, 0x4efa27a0U, 0x9a5eab70U, 0xc94ec628U, 0x2e144b04U, 0xe5da27b6U, 0xd30eab73U, 0x1fb6c615U, 0x98484b34U, 0xa9027b3U, 0xc61dab7eU, 0xf3ef4617U, 0x52040b22U, 0x110387b0U, 0xc484fb60U, 0xd3c52e19U, 0x8e05f23U, 0xa9b4e1b0U, 0xbb4ae058U, 0xef14e196U, 0xd95ae076U, 0x1ccce1abU, 0x3956e069U, 0x3efee187U, 0x7259e040U, 0xd4d6190U, 0xcc16a069U, 0x80000000U, 0x40000000U, 0x60000000U, 0xf0000000U, 0x28000000U, 0x24000000U, 0x9e000000U, 0x4d000000U, 0x34800000U, 0x63c00000U, 0xf1a00000U, 0x9c700000U, 0x95680000U, 0xb45c0000U, 0x98560000U, 0xa4590000U, 0x508000U, 0xc85cc000U, 0x4a576000U, 0x33585000U, 0x17d0d800U, 0xfa1f6c00U, 0xc8b00a00U, 0xa34a5b00U, 0xa2687a80U, 0x73d99ec0U, 0x121790a0U, 0xdabb55d0U, 0x2465238U, 0x8ae0f72cU, 0x24179092U, 0xf3bb55f5U, 0xc8c6520dU, 0x5420f70aU, 0xc93790b2U, 0x280b55f7U, 0x320e521bU, 0x310cf726U, 0xf08990a6U, 0x5bce55e5U, 0x5ba8d224U, 0xc1793705U, 0x2fe670a5U, 0x1496c5d3U, 0x9e796a10U, 0xac670b12U, 0xf0d622b2U, 0x859f32d3U, 0xbef67ab5U, 0x4fac9ec8U, 0x5779108dU, 0xd6e295c9U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x30000000U, 0x88000000U, 0xbc000000U, 0x26000000U, 0xd000000U, 0x35800000U, 0x76c00000U, 0x5ee00000U, 0xb7500000U, 0x75880000U, 0x139c0000U, 0x19320000U, 0xdd9f0000U, 0x78348000U, 0x561bc000U, 0x7f4a000U, 0x2f7b5000U, 0x51601800U, 0x1a93a400U, 0xbbee6a00U, 0x6b894900U, 0xea999180U, 0x96b328c0U, 0xb05fdba0U, 0x9656f1f0U, 0x1e08f228U, 0x7c5e2d3cU, 0xd857dbaaU, 0xbf0af1e3U, 0xd7daf20bU, 0x97912d1cU, 0x4e6b5b8cU, 0x3d4d31d2U, 0x847c5218U, 0xa9e57d2fU, 0x79d7c38bU, 0xa3c955e6U, 0xa3c9814U, 0x94446431U, 0xd6a0ca0eU, 0xb7f11900U, 0x677f09adU, 0xcd644ce8U, 0xc9191adU, 0x3eef28e4U, 0xe20ddb9cU, 0xba59f1ecU, 0xc554720eU, 0x3289ed3dU, 0x80000000U, 0x40000000U, 0xe0000000U, 0xb0000000U, 0x18000000U, 0x1c000000U, 0xf2000000U, 0xd1000000U, 0xc6800000U, 0xdb400000U, 0x24a00000U, 0x34f00000U, 0xdbf80000U, 0x24cc0000U, 0x2fd60000U, 0xb6cd0000U, 0xed68000U, 0x884f4000U, 0x79932000U, 0x46e8f000U, 0x8062d800U, 0xa997dc00U, 0xaee8be00U, 0x64601700U, 0xf793e680U, 0x95e8ca40U, 0x6fe6f8a0U, 0x18536d50U, 0xbb0ae618U, 0xb9358b3cU, 0x2c1ef8beU, 0x609f6d6bU, 0x86dce61aU, 0x6ef88b23U, 0xfc4878b5U, 0x2f902d6eU, 0x29efc61eU, 0xcde07b2cU, 0x6152a0bbU, 0x798bf15cU, 0x8c71782aU, 0x2bbd6c05U, 0x43efc605U, 0x40e07b1aU, 0xb5d2a09cU, 0xc3cbf14bU, 0x76517820U, 0xd80d6c3fU, 0x4eb7c637U, 0x81dc7b02U, 0x877ca08cU, 0x8a8af14aU, 0x80000000U, 0x40000000U, 0x20000000U, 0xf0000000U, 0xe8000000U, 0xb4000000U, 0xa000000U, 0x6d000000U, 0xa7800000U, 0x73400000U, 0x11e00000U, 0x3a300000U, 0x7e680000U, 0xcd9c0000U, 0xfed60000U, 0xfdb0000U, 0xb6b28000U, 0x1aac000U, 0xe3bfe000U, 0xcac47000U, 0xb5a77800U, 0x29557400U, 0xd49e3600U, 0x33569d00U, 0xc19b9280U, 0x18d780c0U, 0x14dec4a0U, 0x3234add0U, 0x5a6f4e28U, 0xff98e92cU, 0x3fd724b2U, 0xfe5bddd1U, 0x16f2b618U, 0xd0cb5d26U, 0x6048f2a3U, 0x718e30fbU, 0x20aadcb7U, 0x823869efU, 0x52856031U, 0xc8c2b00aU, 0xfca6983bU, 0xbcd6043dU, 0x66ddce2eU, 0xd332293bU, 0x5be8c4a1U, 0xb7dfadc6U, 0x5ab5ce27U, 0x77ae2939U, 0xc0bec4a6U, 0xe244adc7U, 0xb8674e07U, 0xe674e935U, 0x80000000U, 0xc0000000U, 0x20000000U, 0x70000000U, 0x58000000U, 0xe4000000U, 0x92000000U, 0x59000000U, 0x64800000U, 0x2b400000U, 0x64600000U, 0xf7100000U, 0xa2a80000U, 0xeb7c0000U, 0x1e720000U, 0x1b3f0000U, 0x8f968000U, 0x4fef4000U, 0x3c18e000U, 0x40e23000U, 0x3c539800U, 0x96cc4c00U, 0x346bae00U, 0xdf5100U, 0x86470f80U, 0x5ae12fc0U, 0x6950c1a0U, 0xfc4c0ef0U, 0x402a3628U, 0x933c1d2cU, 0x8392219eU, 0x41ed3ee5U, 0x631d2e12U, 0xb760111fU, 0xce97efb5U, 0x2f6f1fc0U, 0xd55959b6U, 0x558342feU, 0x13c5183dU, 0x69230c3dU, 0x70734e28U, 0xd43d6113U, 0x7014978fU, 0x712d63c7U, 0xabbb6f99U, 0x8ed35fd5U, 0xc68d39afU, 0x158d32e8U, 0x2c0ae02eU, 0xa1cd3024U, 0x9fed1836U, 0xd41f0c09U, 0x80000000U, 0x40000000U, 0xa0000000U, 0xb0000000U, 0x58000000U, 0x84000000U, 0x4a000000U, 0x1d000000U, 0x83800000U, 0xfec00000U, 0x52200000U, 0x5ad00000U, 0xf3f80000U, 0x6d6c0000U, 0xbf60000U, 0x75af0000U, 0x32d48000U, 0x6ffd4000U, 0x36fe000U, 0xecf5f000U, 0xb32f7800U, 0xcb945400U, 0x891cfa00U, 0x169a6f00U, 0xc659ab80U, 0xd379c740U, 0xff2831a0U, 0xad941850U, 0xa21d8208U, 0xf61d3b3cU, 0xb41fd1beU, 0x651de84dU, 0xc09cfa24U, 0xb55a6f36U, 0xb7f9ab9aU, 0xc769c754U, 0x6f03182U, 0x1e281858U, 0x10138232U, 0xf3de3b36U, 0xebd51a0U, 0x818fa874U, 0xa3079a3eU, 0x6c82df26U, 0xf44133aaU, 0x8d64636fU, 0x3735b3acU, 0xb689234cU, 0x6d8253b0U, 0x59c0d35aU, 0x34a32b93U, 0x1397876eU, }; } RenderKit-ospray-f2a61c2/modules/cpu/math/sobol.h000066400000000000000000000026431456566705700220330ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // Copyright (c) 2012 Leonhard Gruenschloss (leonhard@gruenschloss.org) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #pragma once #define Sobol_numDimensions 1024 #define Sobol_numBits 52 #ifdef __cplusplus namespace ospray { extern const unsigned int Sobol_matrices[Sobol_numDimensions * Sobol_numBits]; } // namespace ospray #endif RenderKit-ospray-f2a61c2/modules/cpu/math/sobol.ih000066400000000000000000000041151456566705700222000ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // Copyright (c) 2012 Leonhard Gruenschloss (leonhard@gruenschloss.org) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #pragma once #include "math/sobol.h" #include "rkcommon/math/math.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // Compute one component of the Sobol'-sequence, where the component // corresponds to the dimension parameter, and the index specifies // the point inside the sequence. The scramble parameter can be used // to permute elementary intervals, and might be chosen randomly to // generate a randomized QMC sequence. inline float Sobol_sample(const unsigned int *uniform sobol_matrices, unsigned int index, uniform unsigned int dimension, unsigned int scramble = 0) { #ifndef OSPRAY_TARGET_SYCL assert(dimension < Sobol_numDimensions); #endif unsigned int result = scramble; for (uniform unsigned int i = dimension * Sobol_numBits; index; index >>= 1, ++i) { if (index & 1) result ^= sobol_matrices[i]; } return to_float_unorm(result); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/math/spectrum.h000066400000000000000000000040451456566705700225550ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ==> 430..675 #define SPECTRUM_SAMPLES 8 #define SPECTRUM_FIRSTWL 430.f #define SPECTRUM_SPACING 35.f #ifdef __cplusplus #include #include struct alignas(SPECTRUM_SAMPLES * sizeof(float)) spectrum : public std::array { spectrum() = default; spectrum(const spectrum &) = default; ~spectrum() = default; spectrum &operator=(const spectrum &) = default; // The initializer_list constructor lets us construct the spectrum object // in C++ as if it's directly a std::array using the array init syntax spectrum(std::initializer_list l) { assert(l.size() == SPECTRUM_SAMPLES); std::copy(l.begin(), l.end(), begin()); } }; #endif // __cplusplus #define SPECTRUM_AL_ETA \ { \ 0.570, 0.686, 0.813, 0.952, 1.11, 1.29, 1.49, 1.73 \ } #define SPECTRUM_AL_K \ { \ 5.21, 5.64, 6.05, 6.45, 6.85, 7.24, 7.61, 7.94 \ } #define RGB_AL_ETA \ { \ 1.47f, 0.984f, 0.602f \ } #define RGB_AL_K \ { \ 7.64f, 6.55f, 5.36f \ } // = ((eta-1)^2+k^2)/((eta+1)^2+k^2) #define RGB_AL_COLOR \ { \ 0.909f, 0.916f, 0.923f \ } RenderKit-ospray-f2a61c2/modules/cpu/math/spectrum.ih000066400000000000000000000025121456566705700227230ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "math/spectrum.h" #include "rkcommon/math/vec.ih" #ifndef OSPRAY_TARGET_SYCL typedef uniform float spectrum; #endif OSPRAY_BEGIN_ISPC_NAMESPACE #ifdef ISPC extern spectrum spectrum_sRGB_r; extern spectrum spectrum_sRGB_g; extern spectrum spectrum_sRGB_b; #endif inline uniform vec3f spectrum_sRGB(const uniform int l) { #ifdef OSPRAY_TARGET_SYCL const spectrum spectrum_sRGB_r = {0.0598548f, -0.0234574f, -0.220138f, -0.238902f, 0.316327f, 0.738315f, 0.323302f, 0.0446981f}; const spectrum spectrum_sRGB_g = {-0.0567346f, -0.0160361f, 0.223861f, 0.531185f, 0.337221f, 0.0149718f, -0.0296053f, -0.00486239f}; const spectrum spectrum_sRGB_b = {0.420693f, 0.616597f, 0.0796766f, -0.0496266f, -0.0473149f, -0.0167536f, -0.00295686f, -0.000314818f}; #endif return make_vec3f(spectrum_sRGB_r[l], spectrum_sRGB_g[l], spectrum_sRGB_b[l]); } // note: result can be <0 or >1 inline uniform vec3f spectrum2rgb(const spectrum &s) { uniform vec3f rgb = make_vec3f(0.f); for (uniform int l = 0; l < SPECTRUM_SAMPLES; l++) rgb = rgb + s[l] * spectrum_sRGB(l); return rgb; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/math/spectrum.ispc000066400000000000000000000013051456566705700232600ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "math/spectrum.ih" // convolutions of: normalization * D65 * CIE_XYZ * xyz2sRGB OSPRAY_BEGIN_ISPC_NAMESPACE #ifdef ISPC spectrum spectrum_sRGB_r = {0.0598548f, -0.0234574f, -0.220138f, -0.238902f, 0.316327f, 0.738315f, 0.323302f, 0.0446981f}; spectrum spectrum_sRGB_g = {-0.0567346f, -0.0160361f, 0.223861f, 0.531185f, 0.337221f, 0.0149718f, -0.0296053f, -0.00486239f}; spectrum spectrum_sRGB_b = {0.420693f, 0.616597f, 0.0796766f, -0.0496266f, -0.0473149f, -0.0167536f, -0.00295686f, -0.000314818f}; #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/pf/000077500000000000000000000000001456566705700202135ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/pf/LUTPixelFilter.ih000066400000000000000000000005401456566705700233500ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "PixelFilter.ih" #include "math/Distribution2D.ih" // c++ shared #include "LUTPixelFilterShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL vec2f LUTPixelFilter_sample( const PixelFilter *uniform self, const vec2f &s); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/pf/LUTPixelFilter.ispc000066400000000000000000000105401456566705700237070ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "math/Distribution1D.ih" #include "pf/LUTPixelFilter.ih" OSPRAY_BEGIN_ISPC_NAMESPACE vec2f LUTPixelFilter_sample(const PixelFilter *uniform _self, const vec2f &s) { const LUTPixelFilter *uniform self = (const LUTPixelFilter *uniform)_self; Sample2D sample2d = Distribution2D_sample(self->distribution, s); return (sample2d.uv + make_vec2f(-0.5f)) * make_vec2f(self->super.width); } inline float Gaussian_eval(const PixelFilter *uniform self, const vec2f &x) { const float sigma = (0.5f * self->width) / 3.0f; const float sigmaSqr = sigma * sigma; const float distanceSqr = x.x * x.x + x.y * x.y; return exp(-0.5f * (distanceSqr / sigmaSqr)); } inline float MitchellNetravali_eval( const PixelFilter *uniform self, const vec2f &x) { const float oneOverSix = 1.0f / 6.0f; const float B = 1.0f / 3.0f; const float C = 1.0f / 3.0f; const vec2f tx = (x / make_vec2f(self->width)) * make_vec2f(4.0f); const float fx = sqrt(tx.x * tx.x + tx.y * tx.y); const float fx2 = fx * fx; const float fx3 = fx2 * fx; float value = 0.0f; if (fx < 1.0f) { value = oneOverSix * ((12.0f - 9.0f * B - 6.0f * C) * fx3 + (-18.0f + 12.0f * B + 6.0f * C) * fx2 + (6.0f - 2.0f * B)); } else if (fx < 2.0f) { value = oneOverSix * ((-B - 6.0f * C) * fx3 + (6.0f * B + 30.0f * C) * fx2 + (-12.0f * B - 48.0f * C) * fx + (8.0f * B + 24.0f * C)); } return value; } inline float BlackmanHarris_eval( const PixelFilter *uniform self, const vec2f &x) { const float a0 = 0.35875f; const float a1 = 0.48829f; const float a2 = 0.14128f; const float a3 = 0.01168f; const float fx = sqrt(x.x * x.x + x.y * x.y) + self->width / 2.0f; const float oneOverWMinusOne = 1.0f / (self->width); const float value = a0 - a1 * cos((2.0f * M_PI * fx) * oneOverWMinusOne) + a2 * cos((4.0f * M_PI * fx) * oneOverWMinusOne) - a3 * cos((6.0f * M_PI * fx) * oneOverWMinusOne); return value; } #ifndef OSPRAY_TARGET_SYCL task #endif unmasked void LUTPixelFilter_calcRowImportance(const LUTPixelFilter *uniform const self, int uniform const lut_width, float *uniform const importance, float *uniform const row_importance #ifdef OSPRAY_TARGET_SYCL , const int taskIndex #endif ) { const uniform float filter_width = self->super.width; const uniform int y = taskIndex; const uniform float fy = (y + 0.5f) * (1.0f / (float)lut_width); #ifdef OSPRAY_TARGET_SYCL for (int x = 0; x < lut_width; ++x) { #else foreach (x = 0 ... lut_width) { #endif const varying float fx = (x + 0.5f) * (1.0f / (float)lut_width); const vec2f coord = make_vec2f(fx, fy) - make_vec2f(0.5f); float filterEval = 0.f; switch (self->lutFilterType) { case LUT_PIXEL_FILTER_TYPE_GAUSSIAN: filterEval = Gaussian_eval(&self->super, coord * make_vec2f(filter_width)); break; case LUT_PIXEL_FILTER_TYPE_MITCHELL_NETRAVALI: filterEval = MitchellNetravali_eval( &self->super, coord * make_vec2f(filter_width)); break; case LUT_PIXEL_FILTER_TYPE_BLACKMANN_HARRIS: filterEval = BlackmanHarris_eval(&self->super, coord * make_vec2f(filter_width)); break; default: break; } // clamp the evaluation of the filter // to avoid negative values importance[y * lut_width + x] = max(0.0f, filterEval); } row_importance[y] = Distribution1D_create(lut_width, importance + y * lut_width); } export void LUTPixelFilter_buildLUT(void *uniform _self) { LUTPixelFilter *uniform self = (LUTPixelFilter * uniform) _self; const uniform int lut_width = self->distribution->size.x; float *uniform cdf_x = self->distribution->cdf_x; float *uniform row_importance = self->distribution->cdf_y; #ifdef OSPRAY_TARGET_SYCL // TODO: This could become a kernel launch via SYCL // This serial loop is just for testing an initial C++ migration of the ISPC // code for (int i = 0; i < lut_width; ++i) { LUTPixelFilter_calcRowImportance(self, lut_width, cdf_x, row_importance, i); } #else launch[lut_width] LUTPixelFilter_calcRowImportance( self, lut_width, cdf_x, row_importance); sync; #endif // Initialize the distribution with the computed cdf/f values Distribution2D_init(self->distribution); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/pf/LUTPixelFilterShared.h000066400000000000000000000013751456566705700243350ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "math/Distribution2DShared.h" #include "pf/PixelFilterShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus enum LUTPixelFilterType { LUT_PIXEL_FILTER_TYPE_GAUSSIAN, LUT_PIXEL_FILTER_TYPE_BLACKMANN_HARRIS, LUT_PIXEL_FILTER_TYPE_MITCHELL_NETRAVALI, }; #define LUTPIXELFILTER_PER_PIXEL_BINS 5 struct LUTPixelFilter { PixelFilter super; // The 2D distribution used to importance sample Distribution2D *distribution; LUTPixelFilterType lutFilterType; #ifdef __cplusplus LUTPixelFilter() : distribution(nullptr), lutFilterType{LUT_PIXEL_FILTER_TYPE_GAUSSIAN} { super.type = PIXEL_FILTER_TYPE_LUT; } }; } #else }; #endif RenderKit-ospray-f2a61c2/modules/cpu/pf/PixelFilter.cpp000066400000000000000000000035611456566705700231530ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "PixelFilter.h" #include "ISPCDevice.h" #include "ISPCDeviceObject.h" #include "math/Distribution2D.h" #ifndef OSPRAY_TARGET_SYCL #include "pf/LUTPixelFilter_ispc.h" #else namespace ispc { void LUTPixelFilter_buildLUT(void *self); } #endif namespace ospray { PixelFilter::PixelFilter(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device) {} LUTPixelFilter::LUTPixelFilter(const float size, ispc::LUTPixelFilterType lutFilterType, api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device) { getSh()->super.width = size; getSh()->super.type = ispc::PIXEL_FILTER_TYPE_LUT; const vec2i lutSize = vec2i(std::ceil(size)) * LUTPIXELFILTER_PER_PIXEL_BINS; distribution = new Distribution2D(lutSize, device); // Remove local ref distribution->refDec(); getSh()->distribution = distribution->getSh(); getSh()->lutFilterType = lutFilterType; ispc::LUTPixelFilter_buildLUT(getSh()); } PointPixelFilter::PointPixelFilter(api::ISPCDevice &device) : PixelFilter(device) { getSh()->type = ispc::PIXEL_FILTER_TYPE_POINT; getSh()->width = 0.f; } BoxPixelFilter::BoxPixelFilter(api::ISPCDevice &device) : PixelFilter(device) { getSh()->type = ispc::PIXEL_FILTER_TYPE_BOX; getSh()->width = 1.f; } GaussianLUTPixelFilter::GaussianLUTPixelFilter(api::ISPCDevice &device) : LUTPixelFilter(3.f, ispc::LUT_PIXEL_FILTER_TYPE_GAUSSIAN, device) {} BlackmanHarrisLUTPixelFilter::BlackmanHarrisLUTPixelFilter( api::ISPCDevice &device) : LUTPixelFilter(3.f, ispc::LUT_PIXEL_FILTER_TYPE_BLACKMANN_HARRIS, device) {} MitchellNetravaliLUTPixelFilter::MitchellNetravaliLUTPixelFilter( api::ISPCDevice &device) : LUTPixelFilter( 4.f, ispc::LUT_PIXEL_FILTER_TYPE_MITCHELL_NETRAVALI, device) {} } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/pf/PixelFilter.h000066400000000000000000000026421456566705700226170ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ISPCDevice.h" #include "ISPCDeviceObject.h" #include "common/Managed.h" #include "common/StructShared.h" #include "math/Distribution2D.h" // ispc shared #include "pf/LUTPixelFilterShared.h" #include "pf/PixelFilterShared.h" namespace ospray { struct OSPRAY_SDK_INTERFACE PixelFilter : public AddStructShared { PixelFilter(api::ISPCDevice &device); }; struct OSPRAY_SDK_INTERFACE LUTPixelFilter : public AddStructShared { LUTPixelFilter(const float size, ispc::LUTPixelFilterType lutFilterType, api::ISPCDevice &device); Ref distribution; }; struct OSPRAY_SDK_INTERFACE PointPixelFilter : public PixelFilter { PointPixelFilter(api::ISPCDevice &device); }; struct OSPRAY_SDK_INTERFACE BoxPixelFilter : public PixelFilter { BoxPixelFilter(api::ISPCDevice &device); }; struct OSPRAY_SDK_INTERFACE GaussianLUTPixelFilter : public LUTPixelFilter { GaussianLUTPixelFilter(api::ISPCDevice &device); }; struct OSPRAY_SDK_INTERFACE BlackmanHarrisLUTPixelFilter : public LUTPixelFilter { BlackmanHarrisLUTPixelFilter(api::ISPCDevice &device); }; struct OSPRAY_SDK_INTERFACE MitchellNetravaliLUTPixelFilter : public LUTPixelFilter { MitchellNetravaliLUTPixelFilter(api::ISPCDevice &device); }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/pf/PixelFilter.ih000066400000000000000000000012111456566705700227570ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/vec.ih" // c++ shared #include "pf/PixelFilterShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE inline void PixelFilter_Constructor(PixelFilter *uniform self, uniform float width, uniform PixelFilter_SampleFunc sample) { self->width = width; self->sample = sample; } inline vec2f Point_sample(const PixelFilter *uniform, const vec2f &) { return make_vec2f(0.0f); } inline vec2f Box_sample(const PixelFilter *uniform self, const vec2f &s) { return (s + make_vec2f(-0.5f)) * make_vec2f(self->width); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/pf/PixelFilterDispatch.ih000066400000000000000000000015041456566705700244440ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/OSPCommon.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct PixelFilter; /* Samples a relative pixel position proportional to the kernel of a pixel filter. The sampled position is relative to the center of a pixel. It converts a uniform 2D random variable s with values of the range [0..1) into a non-uniform 2D position in the range of [-w/2 .. w/2], where w = self->width. The center of the pixel filter kernel is [0,0], which represents a position at the center of the pixel. Returns a 2D position in the domain [-w/2 .. w/2] distributed proportionally to the filter kernel. */ SYCL_EXTERNAL vec2f PixelFilter_dispatch_sample( const PixelFilter *uniform self, const vec2f &x); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/pf/PixelFilterDispatch.ispc000066400000000000000000000011351456566705700250020ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "pf/LUTPixelFilter.ih" #include "pf/PixelFilter.ih" #include "pf/PixelFilterDispatch.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL vec2f PixelFilter_dispatch_sample( const PixelFilter *uniform self, const vec2f &x) { switch (self->type) { case PIXEL_FILTER_TYPE_POINT: return Point_sample(self, x); case PIXEL_FILTER_TYPE_BOX: return Box_sample(self, x); case PIXEL_FILTER_TYPE_LUT: return LUTPixelFilter_sample(self, x); default: return make_vec2f(0.f); } } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/pf/PixelFilterShared.h000066400000000000000000000024401456566705700237420ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus #if defined(__cplusplus) && !defined(OSPRAY_TARGET_SYCL) typedef void *PixelFilter_SampleFunc; #else struct PixelFilter; /* Samples a relative pixel position proportional to the kernel of a pixel filter. The sampled position is relative to the center of a pixel. It converts a uniform 2D random variable s with values of the range [0..1) into a non-uniform 2D position in the range of [-w/2 .. w/2], where w = self->width. The center of the pixel filter kernel is [0,0], which represents a position at the center of the pixel, which should be sampled for input s = [0.5, 0.5]. Returns a 2D position in the domain [-w/2 .. w/2] distributed proportionally to the filter kernel. */ typedef vec2f (*PixelFilter_SampleFunc)( const PixelFilter *uniform self, const vec2f &s); #endif enum PixelFilterType { PIXEL_FILTER_TYPE_POINT, PIXEL_FILTER_TYPE_BOX, PIXEL_FILTER_TYPE_LUT, PIXEL_FILTER_TYPE_UNKNOWN, }; struct PixelFilter { PixelFilterType type; float width; PixelFilter_SampleFunc sample; #ifdef __cplusplus PixelFilter() : type(PIXEL_FILTER_TYPE_UNKNOWN), width(0.f), sample(nullptr) {} }; } #else }; #endif RenderKit-ospray-f2a61c2/modules/cpu/render/000077500000000000000000000000001456566705700210655ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/render/LoadBalancer.cpp000066400000000000000000000026771456566705700241140ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "LoadBalancer.h" #include "camera/Camera.h" #include "common/World.h" #include "fb/FrameBuffer.h" // ispc shared #include "fb/LocalFBShared.h" #ifndef OSPRAY_TARGET_SYCL #include "render/RenderTask.h" #include "rkcommon/utility/CodeTimer.h" #else #include "render/RenderTaskSycl.h" #endif namespace ospray { std::pair LocalTiledLoadBalancer::renderFrame( FrameBuffer *fb, Renderer *renderer, Camera *camera, World *world, bool wait) { fb->beginFrame(); void *perFrameData = renderer->beginFrame(fb, world); // Get render tasks and process them all utility::ArrayView taskIds = fb->getRenderTaskIDs(renderer->errorThreshold, renderer->spp); AsyncEvent rendererEvent; if (taskIds.size()) rendererEvent = renderer->renderTasks(fb, camera, world, perFrameData, taskIds, wait); // Can set flag only if we wait if (wait) fb->setCompletedEvent(OSP_WORLD_RENDERED); // But we can queue FB post-processing kernel if any tasks has been rendered AsyncEvent fbEvent; if (taskIds.size()) fbEvent = fb->postProcess(wait); // Can set flag only if we wait if (wait) fb->setCompletedEvent(OSP_FRAME_FINISHED); return std::make_pair(rendererEvent, fbEvent); } std::string LocalTiledLoadBalancer::toString() const { return "ospray::LocalTiledLoadBalancer"; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/LoadBalancer.h000066400000000000000000000025541456566705700235530ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/OSPCommon.h" #include "render/Renderer.h" namespace ospray { struct FrameBuffer; struct Camera; struct World; struct OSPRAY_SDK_INTERFACE TiledLoadBalancer { virtual ~TiledLoadBalancer() = default; virtual std::string toString() const = 0; /*! Render the entire framebuffer using the given renderer, camera and * world configuration using the load balancer to parallelize the work */ virtual std::pair renderFrame(FrameBuffer *fb, Renderer *renderer, Camera *camera, World *world, bool wait = true) = 0; }; // Inlined definitions ////////////////////////////////////////////////////// //! tiled load balancer for local rendering on the given machine /*! a tiled load balancer that orchestrates (multi-threaded) rendering on a local machine, without any cross-node communication/load balancing at all (even if there are multiple application ranks each doing local rendering on their own) */ struct OSPRAY_SDK_INTERFACE LocalTiledLoadBalancer : public TiledLoadBalancer { std::pair renderFrame(FrameBuffer *fb, Renderer *renderer, Camera *camera, World *world, bool wait = true) override; std::string toString() const override; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/Material.cpp000066400000000000000000000116501456566705700233320ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Material.h" #include "render/bsdfs/MicrofacetAlbedoTables.h" #include "texture/Texture.h" #ifndef OSPRAY_TARGET_SYCL // ispc #include "render/Material_ispc.h" #endif namespace ospray { // Material definitions /////////////////////////////////////////////////////// Ref Material::microfacetAlbedoTables; Material::Material(api::ISPCDevice &device, const FeatureFlagsOther ffo) : AddStructShared(device.getIspcrtContext(), device), featureFlags(ffo) { managedObjectType = OSP_MATERIAL; #ifndef OSPRAY_TARGET_SYCL getSh()->getTransparency = reinterpret_cast( ispc::Material_getTransparency_addr()); getSh()->selectNextMedium = reinterpret_cast( ispc::Material_selectNextMedium_addr()); #endif if (!microfacetAlbedoTables) { microfacetAlbedoTables = new MicrofacetAlbedoTables(device); // Release the extra local ref microfacetAlbedoTables->refDec(); } else { microfacetAlbedoTables->refInc(); } getSh()->microfacetAlbedoTables = microfacetAlbedoTables->getSh(); } Material::~Material() { if (microfacetAlbedoTables) { const bool lastReference = microfacetAlbedoTables->useCount() == 1; // The last material referencing the albedo tables should null out the // pointer so we don't try to call refDec again and know to re-create it // when a new material is made if (lastReference) { microfacetAlbedoTables = nullptr; } else { microfacetAlbedoTables->refDec(); } } } std::string Material::toString() const { return "ospray::Material"; } void Material::commit() {} ispc::TextureParam Material::getTextureParam(const char *texture_name) { // Get texture pointer Texture *ptr = getParamObject(texture_name); if (ptr) featureFlags |= FFO_TEXTURE_IN_MATERIAL; // Get 2D transformation if exists int transformFlags = ispc::TRANSFORM_FLAG_NONE; affine2f xfm2f = affine2f(one); utility::Optional xform2f = getTextureTransform2f(texture_name); if (xform2f.has_value()) { xfm2f = xform2f.value(); transformFlags |= ispc::TRANSFORM_FLAG_2D; } // Get 3D transformation if exists affine3f xfm3f = affine3f(one); auto xform3f = getOptParam((std::string(texture_name) + ".transform").c_str()); if (xform3f.has_value()) { xfm3f = xform3f.value(); transformFlags |= ispc::TRANSFORM_FLAG_3D; } // Initialize ISPC structure ispc::TextureParam param; param.ptr = ptr ? ptr->getSh() : nullptr; param.transformFlags = (ispc::TransformFlags)transformFlags; param.xform2f = xfm2f; param.xform3f = xfm3f; // Done return param; } MaterialParam1f Material::getMaterialParam1f( const char *name, float valIfNotFound) { const std::string mapName = "map_" + std::string(name); MaterialParam1f param; param.tex = getTextureParam(mapName.c_str()); param.rot = ((linear2f *)(¶m.tex.xform2f.l))->orthogonal().transposed(); param.factor = getParam(name, param.tex.ptr ? 1.f : valIfNotFound); return param; } MaterialParam3f Material::getMaterialParam3f( const char *name, vec3f valIfNotFound) { const std::string mapName = "map_" + std::string(name); MaterialParam3f param; param.tex = getTextureParam(mapName.c_str()); param.rot = ((linear2f *)(¶m.tex.xform2f.l))->orthogonal().transposed(); param.factor = getParam(name, param.tex.ptr ? vec3f(1.f) : valIfNotFound); return param; } utility::Optional Material::getTextureTransform2f( const char *_texname) { std::string texname(_texname); texname += "."; utility::Optional xform; // Apply translation const utility::Optional translation = getOptParam((texname + "translation").c_str()); if (translation.has_value()) xform = affine2f::translate(-translation.value()); // Apply scale const utility::Optional scale = getOptParam((texname + "scale").c_str()); if (scale.has_value()) { xform = xform.value_or(affine2f(one)) * affine2f::translate(vec2f(0.5f)); xform = *xform * affine2f::scale(rcp(scale.value())); xform = *xform * affine2f::translate(vec2f(-0.5f)); } // Apply rotation const utility::Optional rotation = getOptParam((texname + "rotation").c_str()); if (rotation.has_value()) { xform = xform.value_or(affine2f(one)) * affine2f::translate(vec2f(0.5f)); xform = *xform * affine2f::rotate(-deg2rad(rotation.value())); xform = *xform * affine2f::translate(vec2f(-0.5f)); } // Apply complete transformation const utility::Optional transf = getOptParam((texname + "transform").c_str()); if (transf.has_value()) xform = xform.value_or(affine2f(one)) * affine2f(transf.value()); return xform; } OSPTYPEFOR_DEFINITION(Material *); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/Material.h000066400000000000000000000057621456566705700230060ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ISPCDeviceObject.h" #include "common/FeatureFlagsEnum.h" #include "common/ObjectFactory.h" #include "common/StructShared.h" // ispc shared #include "MaterialShared.h" #include "bsdfs/MicrofacetAlbedoTables.h" #include "texture/TextureParamShared.h" namespace ospray { /*! helper structure to store a uniform or textured material parameter */ template struct MaterialParam { T factor; ispc::TextureParam tex; linear2f rot; }; using MaterialParam1f = MaterialParam; using MaterialParam3f = MaterialParam; struct OSPRAY_SDK_INTERFACE Material : public AddStructShared, public ObjectFactory { Material(api::ISPCDevice &device, const FeatureFlagsOther ffo); virtual ~Material() override; virtual std::string toString() const override; virtual void commit() override; FeatureFlags getFeatureFlags() const; // helper function to get all texture related parameters ispc::TextureParam getTextureParam(const char *texture_name); /*! \brief helper function to get a uniform or texture material parameter */ MaterialParam1f getMaterialParam1f(const char *name, float valIfNotFound); MaterialParam3f getMaterialParam3f(const char *name, vec3f valIfNotFound); bool isEmissive() const; private: /*! \brief helper function to combine multiple texture transformation parameters The following parameters (prefixed with "texture_name.") are combined into one transformation matrix: name type description transform vec4f interpreted as 2x2 matrix (linear part), column-major rotation float angle in degree, counterclock-wise, around center (0.5, 0.5) scale vec2f enlarge texture, relative to center (0.5, 0.5) translation vec2f move texture in positive direction (right/up) The transformations are applied in the given order. Rotation, scale and translation are interpreted "texture centric", i.e. their effect seen by an user are relative to the texture (although the transformations are applied to the texture coordinates). */ utility::Optional getTextureTransform2f(const char *_texname); utility::Optional getTextureTransform3f(const char *_texname); FeatureFlagsOther featureFlags; // Microfacet albedo tables data, shared by all materials. New materials // increment the use count, and decrement it on destruction to ensure // the data will be released before the device static Ref microfacetAlbedoTables; }; OSPTYPEFOR_SPECIALIZATION(Material *, OSP_MATERIAL); // Inlined definitions ///////////////////////////////////////////////////////// inline FeatureFlags Material::getFeatureFlags() const { FeatureFlags ff; ff.other = featureFlags; return ff; } inline bool Material::isEmissive() const { return reduce_max(getSh()->emission) > 0.f; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/Material.ih000066400000000000000000000061741456566705700231550ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/DifferentialGeometry.ih" #include "common/FeatureFlags.ih" #include "texture/TextureParam.ih" // c++ shared #include "MaterialShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE #define define_texture_get_ff(fn, map, dg, val, ffh) \ ((getFeatureFlagsOther(ffh) & FFO_TEXTURE_IN_MATERIAL) ? fn(map, dg, val) \ : val) #define get1f_ff(map, dg, val, ff) \ define_texture_get_ff(get1f, map, dg, val, ff) #define get3f_ff(map, dg, val, ff) \ define_texture_get_ff(get3f, map, dg, val, ff) #define get4f_ff(map, dg, val, ff) \ define_texture_get_ff(get4f, map, dg, val, ff) inline linear3f makeShadingFrame(const DifferentialGeometry &dg) { vec3f N = dg.Ns; vec3f U = normalize(dg.dPds); vec3f V = cross(N, U); if (dot(V, V) > 0.f) { V = normalize(V); U = cross(V, N); return make_LinearSpace3f(U, V, N); } else { return frame(N); } } inline linear3f makeShadingFrame(const linear3f &f, const vec3f &localN) { // in general f is not ortho-normal, thus need to re-normalize vec3f N = normalize(f * localN); // transform normal to world space vec3f U = f.vx; vec3f V = cross(N, U); if (dot(V, V) > 0.f) { V = normalize(V); U = cross(V, N); return make_LinearSpace3f(U, V, N); } else { return frame(N); } } inline linear3f makeShadingFrame( const DifferentialGeometry &dg, const vec3f &localN) { linear3f f = makeShadingFrame(dg); return makeShadingFrame(f, localN); } inline linear3f makeShadingFrame(const DifferentialGeometry &dg, const uniform TextureParam &normalMap, const uniform linear2f &normalRot, uniform float normalScale = 1.f) { if (valid(normalMap)) { linear3f f = make_LinearSpace3f(normalize(dg.dPds), normalize(dg.dPdt), dg.Ns); // get normal from texture vec3f localN = getNormal(normalMap, dg) * make_vec3f(normalScale, normalScale, 1.f); // rotate in 2D (tangent space) to account for tc transformations vec2f rotN = normalRot * make_vec2f(localN.x, localN.y); localN.x = rotN.x; localN.y = rotN.y; return makeShadingFrame(f, localN); } else { return makeShadingFrame(dg); } } inline linear3f makeShadingFrame_ff(const DifferentialGeometry &dg, const uniform TextureParam &normalMap, const uniform linear2f &normalRot, const uniform FeatureFlagsHandler &ffh) { return (getFeatureFlagsOther(ffh) & FFO_TEXTURE_IN_MATERIAL) ? makeShadingFrame(dg, normalMap, normalRot) : makeShadingFrame(dg); } SYCL_EXTERNAL vec3f Material_getTransparency( const uniform Material *uniform self, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL void Material_selectNextMedium( const uniform Material *uniform self, const DifferentialGeometry &dg, Medium ¤tMedium); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/Material.ispc000066400000000000000000000015201456566705700235010ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Material.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL vec3f Material_getTransparency(const uniform Material *uniform, const DifferentialGeometry &, const Ray &, const Medium &, const uniform FeatureFlagsHandler &) { return make_vec3f(0.0f); } SYCL_EXTERNAL void Material_selectNextMedium( const uniform Material *uniform, const DifferentialGeometry &, Medium &) { /* do nothing by default */ } /////////////////////////////////////////////////////////////////////////////// // External API export void *uniform Material_getTransparency_addr() { return (void *uniform)Material_getTransparency; } export void *uniform Material_selectNextMedium_addr() { return (void *uniform)Material_selectNextMedium; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/MaterialDispatch.ih000066400000000000000000000023631456566705700246310ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/FeatureFlags.ih" #include "common/FeatureFlagsEnum.h" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL __noinline const varying BSDF *uniform Material_dispatch_getBSDF( const uniform Material *uniform self, uniform ShadingContext *uniform ctx, // The point to shade on a surface. const DifferentialGeometry &dg, // The ray arriving at the point to shade. const Ray &ray, // The medium this ray travels inside. const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL __noinline vec3f Material_dispatch_getTransparency( const uniform Material *uniform self, // The point to shade on a surface. const DifferentialGeometry &dg, // The ray arriving at the point to shade. const Ray &ray, // The medium this ray travels inside. const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL __noinline void Material_dispatch_selectNextMedium( const uniform Material *uniform self, const DifferentialGeometry &dg, Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/MaterialDispatch.ispc000066400000000000000000000122371456566705700251700ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Material.ih" #include "MaterialDispatch.ih" #include "common/FeatureFlagsEnum.h" #include "render/materials/Alloy.ih" #include "render/materials/CarPaint.ih" #include "render/materials/Glass.ih" #include "render/materials/Luminous.ih" #include "render/materials/Metal.ih" #include "render/materials/MetallicPaint.ih" #include "render/materials/Mix.ih" #include "render/materials/OBJ.ih" #include "render/materials/Plastic.ih" #include "render/materials/Principled.ih" #include "render/materials/ThinGlass.ih" #include "render/materials/Velvet.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL __noinline const varying BSDF *uniform Material_dispatch_getBSDF( const uniform Material *uniform self, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlagsOther ffo = getFeatureFlagsOther(ffh); if ((self->type == MATERIAL_TYPE_ALLOY) && (ffo & FFO_MATERIAL_ALLOY)) { return Alloy_getBSDF(self, ctx, dg, ray, currentMedium, ffh); } else if ((self->type == MATERIAL_TYPE_CARPAINT) && (ffo & FFO_MATERIAL_CARPAINT)) { return CarPaint_getBSDF(self, ctx, dg, ray, currentMedium, ffh); } else if ((self->type == MATERIAL_TYPE_GLASS) && (ffo & FFO_MATERIAL_GLASS)) { return Glass_getBSDF(self, ctx, dg, ray, currentMedium, ffh); } else if ((self->type == MATERIAL_TYPE_LUMINOUS) && (ffo & FFO_MATERIAL_LUMINOUS)) { return Luminous_getBSDF(self, ctx, dg, ray, currentMedium, ffh); } else if ((self->type == MATERIAL_TYPE_METAL) && (ffo & FFO_MATERIAL_METAL)) { return Metal_getBSDF(self, ctx, dg, ray, currentMedium, ffh); } else if ((self->type == MATERIAL_TYPE_METALLICPAINT) && (ffo & FFO_MATERIAL_METALLICPAINT)) { return MetallicPaint_getBSDF(self, ctx, dg, ray, currentMedium, ffh); } else if ((self->type == MATERIAL_TYPE_OBJ) && (ffo & FFO_MATERIAL_OBJ)) { return OBJ_getBSDF(self, ctx, dg, ray, currentMedium, ffh); } else if ((self->type == MATERIAL_TYPE_PLASTIC) && (ffo & FFO_MATERIAL_PLASTIC)) { return Plastic_getBSDF(self, ctx, dg, ray, currentMedium, ffh); } else if ((self->type == MATERIAL_TYPE_PRINCIPLED) && (ffo & FFO_MATERIAL_PRINCIPLED)) { return Principled_getBSDF(self, ctx, dg, ray, currentMedium, ffh); } else if ((self->type == MATERIAL_TYPE_THINGLASS) && (ffo & FFO_MATERIAL_THINGLASS)) { return ThinGlass_getBSDF(self, ctx, dg, ray, currentMedium, ffh); } else if ((self->type == MATERIAL_TYPE_VELVET) && (ffo & FFO_MATERIAL_VELVET)) { return Velvet_getBSDF(self, ctx, dg, ray, currentMedium, ffh); } #ifndef OSPRAY_TARGET_SYCL else if ((self->type == MATERIAL_TYPE_MIX) && (ffo & FFO_MATERIAL_MIX)) { return Mix_getBSDF(self, ctx, dg, ray, currentMedium, ffh); } else { return self->getBSDF(self, ctx, dg, ray, currentMedium, ffh); } #endif return NULL; } SYCL_EXTERNAL __noinline vec3f Material_dispatch_getTransparency( const uniform Material *uniform self, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlagsOther ffo = getFeatureFlagsOther(ffh); if ((self->type == MATERIAL_TYPE_GLASS) && (ffo & FFO_MATERIAL_GLASS)) { return Glass_getTransparency(self, dg, ray, currentMedium, ffh); } else if ((self->type == MATERIAL_TYPE_LUMINOUS) && (ffo & FFO_MATERIAL_LUMINOUS)) { return Luminous_getTransparency(self, dg, ray, currentMedium, ffh); } else if ((self->type == MATERIAL_TYPE_OBJ) && (ffo & FFO_MATERIAL_OBJ)) { return OBJ_getTransparency(self, dg, ray, currentMedium, ffh); } else if ((self->type == MATERIAL_TYPE_PRINCIPLED) && (ffo & FFO_MATERIAL_PRINCIPLED)) { return Principled_getTransparency(self, dg, ray, currentMedium, ffh); } else if ((self->type == MATERIAL_TYPE_THINGLASS) && (ffo & FFO_MATERIAL_THINGLASS)) { return ThinGlass_getTransparency(self, dg, ray, currentMedium, ffh); } #ifndef OSPRAY_TARGET_SYCL else if ((self->type == MATERIAL_TYPE_MIX) && (ffo & FFO_MATERIAL_MIX)) { return Mix_getTransparency(self, dg, ray, currentMedium, ffh); } else { return self->getTransparency(self, dg, ray, currentMedium, ffh); } #else else { return Material_getTransparency(self, dg, ray, currentMedium, ffh); } #endif } SYCL_EXTERNAL __noinline void Material_dispatch_selectNextMedium( const uniform Material *uniform self, const DifferentialGeometry &dg, Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlagsOther ffo = getFeatureFlagsOther(ffh); if ((self->type == MATERIAL_TYPE_GLASS) && (ffo & FFO_MATERIAL_GLASS)) { Glass_selectNextMedium(self, dg, currentMedium); } else if ((self->type == MATERIAL_TYPE_PRINCIPLED) && (ffo & FFO_MATERIAL_PRINCIPLED)) { Principled_selectNextMedium(self, dg, currentMedium); } else { #ifndef OSPRAY_TARGET_SYCL self->selectNextMedium(self, dg, currentMedium); #else Material_selectNextMedium(self, dg, currentMedium); #endif } } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/MaterialShared.h000066400000000000000000000052331456566705700241260ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "texture/TextureParamShared.h" #define EPS 1e-5f #include "bsdfs/MicrofacetAlbedoTablesShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus #if defined(__cplusplus) && !defined(OSPRAY_TARGET_SYCL) typedef void *Material_GetBSDFFunc; typedef void *Material_GetTransparencyFunc; typedef void *Material_SelectNextMediumFunc; #else struct BSDF; struct ShadingContext; struct Medium; struct DifferentialGeometry; struct Ray; struct Material; struct FeatureFlagsHandler; typedef const varying BSDF *uniform (*Material_GetBSDFFunc)( const uniform Material *uniform self, uniform ShadingContext *uniform ctx, // The point to shade on a surface. const DifferentialGeometry &dg, // The ray arriving at the point to shade. const Ray &ray, // The medium this ray travels inside. const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); // shortcut: compute transmission of material, for transparent shadows, // neglecting refraction typedef vec3f (*Material_GetTransparencyFunc)( const uniform Material *uniform self, // The point to shade on a surface. const DifferentialGeometry &dg, // The ray arriving at the point to shade. const Ray &ray, // The medium this ray travels inside. const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); typedef void (*Material_SelectNextMediumFunc)( const uniform Material *uniform self, const DifferentialGeometry &dg, Medium ¤tMedium); #endif enum MaterialType { MATERIAL_TYPE_ALLOY = 0, MATERIAL_TYPE_CARPAINT = 1, MATERIAL_TYPE_GLASS = 2, MATERIAL_TYPE_LUMINOUS = 3, MATERIAL_TYPE_METAL = 4, MATERIAL_TYPE_METALLICPAINT = 5, MATERIAL_TYPE_MIX = 6, MATERIAL_TYPE_OBJ = 7, MATERIAL_TYPE_PLASTIC = 8, MATERIAL_TYPE_PRINCIPLED = 9, MATERIAL_TYPE_THINGLASS = 10, MATERIAL_TYPE_VELVET = 11, MATERIAL_TYPE_UNKNOWN = 12 }; // ISPC-side abstraction for a material. struct Material { MaterialType type; Material_GetBSDFFunc getBSDF; Material_GetTransparencyFunc getTransparency; Material_SelectNextMediumFunc selectNextMedium; vec3f emission; // angular constant, returns radiance TextureParam emissionMap; // spatially varying emission (SV-EDF) MicrofacetAlbedoTables *microfacetAlbedoTables; #ifdef __cplusplus Material(const vec3f &emission = vec3f(0.f)) : type(MATERIAL_TYPE_UNKNOWN), getBSDF(nullptr), getTransparency(nullptr), selectNextMedium(nullptr), emission(emission), microfacetAlbedoTables(nullptr) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/RenderTask.h000066400000000000000000000026621456566705700233060ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/tasking/AsyncTask.h" // ospray #include "../common/Future.h" #include "../fb/FrameBuffer.h" namespace ospray { struct RenderTask : public Future, public tasking::AsyncTask { RenderTask(FrameBuffer *, std::function fcn); ~RenderTask() override = default; bool isFinished(OSPSyncEvent event = OSP_TASK_FINISHED) override; void wait(OSPSyncEvent event = OSP_TASK_FINISHED) override; void cancel() override; float getProgress() override; float getTaskDuration() override; private: Ref fb; float taskDuration{0.f}; }; // Inlined definitions ////////////////////////////////////////////////////// inline RenderTask::RenderTask(FrameBuffer *_fb, std::function fcn) : AsyncTask(fcn), fb(_fb) {} inline bool RenderTask::isFinished(OSPSyncEvent event) { return finished() || fb->getLatestCompleteEvent() >= event; } inline void RenderTask::wait(OSPSyncEvent event) { if (event == OSP_TASK_FINISHED) AsyncTask::wait(); else fb->waitForEvent(event); } inline void RenderTask::cancel() { fb->cancelFrame(); } inline float RenderTask::getProgress() { return fb->getCurrentProgress(); } inline float RenderTask::getTaskDuration() { if (AsyncTask::valid()) taskDuration = AsyncTask::get(); return taskDuration; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/RenderTaskSycl.h000066400000000000000000000056741456566705700241470ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray #include "common/Future.h" namespace ospray { struct RenderTask : public Future { RenderTask(sycl::event rendererEvent, sycl::event frameBufferEvent); ~RenderTask() override; bool isFinished(OSPSyncEvent event = OSP_TASK_FINISHED) override; void wait(OSPSyncEvent event = OSP_TASK_FINISHED) override; void cancel() override; float getProgress() override; float getTaskDuration() override; private: sycl::event rendererEvent; sycl::event frameBufferEvent; }; // Inlined definitions ////////////////////////////////////////////////////// inline RenderTask::RenderTask( sycl::event rendererEvent, sycl::event frameBufferEvent) : rendererEvent(rendererEvent), frameBufferEvent(frameBufferEvent) {} inline RenderTask::~RenderTask() { // Mimic non-sycl RenderTask behavior which waits on destruction wait(); } inline bool RenderTask::isFinished(OSPSyncEvent event) { switch (event) { case OSP_TASK_FINISHED: case OSP_FRAME_FINISHED: frameBufferEvent.wait_and_throw(); [[fallthrough]]; case OSP_WORLD_RENDERED: rendererEvent.wait_and_throw(); [[fallthrough]]; default: return true; } // The proper way of checking is commented out because it degrades // performance by a factor of 3. Analysis shows that sharing GPU // between SYCL kernel and OpenGL Draws/SwapBuffers is highly ineffective. // Need to first finish SYCL kernel then render FB and GUI. // return (syclEvent.get_info() // == sycl::info::event_command_status::complete); } inline void RenderTask::wait(OSPSyncEvent event) { switch (event) { case OSP_TASK_FINISHED: case OSP_FRAME_FINISHED: frameBufferEvent.wait_and_throw(); [[fallthrough]]; case OSP_WORLD_RENDERED: rendererEvent.wait_and_throw(); [[fallthrough]]; default: return; } } inline void RenderTask::cancel() { // No task canceling on GPU for now } inline float RenderTask::getProgress() { // No progress reported on GPU for now return 0.f; } inline float RenderTask::getTaskDuration() { try { const auto t0 = rendererEvent .get_profiling_info(); const auto t1 = rendererEvent .get_profiling_info(); return (t1 - t0) * 1.0e-9; // TODO: We need a way to tell if the fbEvent was actually submitted, // otherwise getting the time gives an error /* const auto t2 = frameBufferEvent .get_profiling_info(); const auto t3 = frameBufferEvent .get_profiling_info(); return ((t1 - t0) + (t3 - t2)) * 1E-9; */ } catch (...) { // In case no profiling data is available return 0.f; } } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/Renderer.cpp000066400000000000000000000121501456566705700233360ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Renderer.h" #include "LoadBalancer.h" #include "Material.h" #include "camera/Camera.h" #include "common/Instance.h" #include "common/World.h" #include "fb/FrameBuffer.h" #include "geometry/GeometricModel.h" #include "ospray/OSPEnums.h" #include "pf/PixelFilter.h" #ifdef OSPRAY_TARGET_SYCL namespace ispc { void precomputeZOrder(); } #else // ispc exports #include "render/Renderer_ispc.h" #include "render/util_ispc.h" #endif namespace ospray { // Renderer definitions /////////////////////////////////////////////////////// Renderer::Renderer(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device), device(device) { managedObjectType = OSP_RENDERER; pixelFilter = nullptr; mathConstants = rkcommon::make_unique(device); getSh()->mathConstants = mathConstants->getSh(); } std::string Renderer::toString() const { return "ospray::Renderer"; } void Renderer::commit() { spp = std::max(1, getParam("pixelSamples", 1)); const uint32_t maxDepth = std::max(0, getParam("maxPathLength", 20)); const float minContribution = getParam("minContribution", 0.001f); errorThreshold = getParam("varianceThreshold", 0.f); maxDepthTexture = getParamObject("map_maxDepth"); backplate = getParamObject("map_backplate"); featureFlags.reset(); if (maxDepthTexture || backplate) featureFlags.other |= FFO_TEXTURE_IN_RENDERER; if (maxDepthTexture) { if (maxDepthTexture->format != OSP_TEXTURE_R32F || maxDepthTexture->filter != OSP_TEXTURE_FILTER_NEAREST) { static WarnOnce warning( "maxDepthTexture provided to the renderer " "needs to be of type OSP_TEXTURE_R32F and have " "the OSP_TEXTURE_FILTER_NEAREST flag"); } } vec3f bgColor3 = getParam( "backgroundColor", vec3f(getParam("backgroundColor", 0.f))); bgColor = getParam("backgroundColor", vec4f(bgColor3, 0.f)); // Handle materials assigned to renderer materialArray = nullptr; getSh()->material = nullptr; materialData = getParamDataT("material"); if (materialData) { for (auto &&mat : *materialData) featureFlags |= mat->getFeatureFlags(); materialArray = make_buffer_shared_unique( getISPCDevice().getIspcrtContext(), createArrayOfSh(*materialData)); getSh()->numMaterials = materialArray->size(); getSh()->material = materialArray->sharedPtr(); } getSh()->spp = spp; getSh()->maxDepth = maxDepth; getSh()->minContribution = minContribution; getSh()->bgColor = bgColor; getSh()->backplate = backplate ? backplate->getSh() : nullptr; getSh()->maxDepthTexture = maxDepthTexture ? maxDepthTexture->getSh() : nullptr; setupPixelFilter(); getSh()->pixelFilter = pixelFilter ? pixelFilter->getSh() : nullptr; ispc::precomputeZOrder(); } OSPPickResult Renderer::pick( FrameBuffer *fb, Camera *camera, World *world, const vec2f &screenPos) { OSPPickResult res; res.instance = nullptr; res.model = nullptr; res.primID = RTC_INVALID_GEOMETRY_ID; #ifndef OSPRAY_TARGET_SYCL int instID = RTC_INVALID_GEOMETRY_ID; int geomID = RTC_INVALID_GEOMETRY_ID; int primID = RTC_INVALID_GEOMETRY_ID; ispc::Renderer_pick(getSh(), fb->getSh(), camera->getSh(), world->getSh(), (const ispc::vec2f &)screenPos, (ispc::vec3f &)res.worldPosition[0], instID, geomID, primID, res.hasHit); if (res.hasHit) { auto *instance = (*world->instances)[instID]; auto *group = instance->group.ptr; if (!group->geometricModels) { res.hasHit = false; return res; } auto *model = (*group->geometricModels)[geomID]; instance->refInc(); model->refInc(); res.instance = (OSPInstance)instance; res.model = (OSPGeometricModel)model; res.primID = static_cast(primID); } #else // Silence unused parameter warning (void)fb; (void)camera; (void)world; (void)screenPos; #endif return res; } void Renderer::setupPixelFilter() { const auto pixelFilterType = (OSPPixelFilterType)getParam( "pixelFilter", OSPPixelFilterType::OSP_PIXELFILTER_GAUSS); pixelFilter = nullptr; switch (pixelFilterType) { case OSPPixelFilterType::OSP_PIXELFILTER_BOX: { pixelFilter = new BoxPixelFilter(getISPCDevice()); break; } case OSPPixelFilterType::OSP_PIXELFILTER_POINT: { pixelFilter = new PointPixelFilter(getISPCDevice()); break; } case OSPPixelFilterType::OSP_PIXELFILTER_BLACKMAN_HARRIS: { pixelFilter = new BlackmanHarrisLUTPixelFilter(getISPCDevice()); break; } case OSPPixelFilterType::OSP_PIXELFILTER_MITCHELL: { pixelFilter = new MitchellNetravaliLUTPixelFilter(getISPCDevice()); break; } case OSPPixelFilterType::OSP_PIXELFILTER_GAUSS: default: { pixelFilter = new GaussianLUTPixelFilter(getISPCDevice()); break; } } if (pixelFilter) { // Need to remove extra local ref pixelFilter->refDec(); } } OSPTYPEFOR_DEFINITION(Renderer *); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/Renderer.h000066400000000000000000000052531456566705700230110ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ISPCDeviceObject.h" #include "common/FeatureFlagsEnum.h" #include "math/MathConstants.h" #include "pf/PixelFilter.h" #include "rkcommon/utility/ArrayView.h" #include "texture/Texture2D.h" // ispc shared #include "RendererShared.h" namespace ospray { struct Camera; struct World; struct Material; struct FrameBuffer; // abstract base class for all ospray renderers. // // This base renderer abstraction only knows about // 'rendering a frame'; most actual renderers will be derived from a // tile renderer, but this abstraction level also allows for frame // compositing or even projection/splatting based approaches struct OSPRAY_SDK_INTERFACE Renderer : public AddStructShared, public ObjectFactory { Renderer(api::ISPCDevice &device); virtual ~Renderer() override = default; virtual void commit() override; virtual std::string toString() const override; // called to initialize a new frame // // this function gets called exactly once (on each node) at the // beginning of each frame, and allows the renderer to do whatever // is required to initialize a new frame. In particular, this // function _can_ return a pointer to some "per-frame-data"; this // pointer (can be NULL) is then passed to 'renderFrame' to do with as they // please // // returns pointer to per-frame data, or NULL if this does not apply virtual void *beginFrame(FrameBuffer *fb, World *world); // called by the load balancer to render one "sample" for each task virtual AsyncEvent renderTasks(FrameBuffer *, Camera *, World *, void *, const utility::ArrayView &, bool wait = true) const = 0; virtual OSPPickResult pick( FrameBuffer *fb, Camera *camera, World *world, const vec2f &screenPos); // Data // int32 spp{1}; float errorThreshold{0.f}; vec4f bgColor{0.f}; Ref maxDepthTexture; Ref backplate; Ref pixelFilter; // TODO: This could be shared among multiple renderers but we need to be // careful about making sure it's released before the ISPCDevice so that we // can still release the USM allocations std::unique_ptr mathConstants; Ref> materialData; std::unique_ptr> materialArray; protected: FeatureFlags featureFlags; api::ISPCDevice &device; private: void setupPixelFilter(); }; OSPTYPEFOR_SPECIALIZATION(Renderer *, OSP_RENDERER); inline void *Renderer::beginFrame(FrameBuffer *, World *) { return nullptr; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/Renderer.ih000066400000000000000000000010011456566705700231450ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/FeatureFlags.ih" // c++ shared #include "RendererShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL vec4f Renderer_getBackground(const Renderer *uniform self, const vec2f &screenPos, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL float Renderer_getMaxDepth(const Renderer *uniform self, const vec2f &screenPos, const uniform FeatureFlagsHandler &ffh); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/Renderer.ispc000066400000000000000000000057371456566705700235270ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // TODO: Seems like ISPC bug: if Renderer.ih included before // Texture2D.ih I get an error that the Texture2D type is declared but not // defined #include "common/FeatureFlagsEnum.h" #include "texture/Texture2D.ih" #include "Renderer.ih" #include "camera/Camera.ih" #include "camera/CameraDispatch.ih" #include "common/World.ih" #include "fb/FrameBuffer.ih" #include "fb/FrameBufferDispatch.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL vec4f Renderer_getBackground(const Renderer *uniform self, const vec2f &screenPos, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlags ff = getFeatureFlags(ffh); if (!self->backplate || !(ff.other & FFO_TEXTURE_IN_RENDERER)) return self->bgColor; // TODO: Now for GPU making a whole DifferentialGeometry object // just to set up the texture coords we want to sample for the background // seems very wasteful DifferentialGeometry lookup; initDgFromTexCoord(lookup, clamp2edge(self->backplate, screenPos)); return get4f(self->backplate, lookup); } SYCL_EXTERNAL float Renderer_getMaxDepth(const Renderer *uniform self, const vec2f &screenPos, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlags ff = getFeatureFlags(ffh); if (!self->maxDepthTexture || !(ff.other & FFO_TEXTURE_IN_RENDERER)) return inf; DifferentialGeometry lookup; initDgFromTexCoord(lookup, screenPos); return max(0.f, get1f(self->maxDepthTexture, lookup)); } // Exports (called from C++) ////////////////////////////////////////////////// export void Renderer_pick(const void *uniform _self, const void *uniform, const void *uniform _camera, const void *uniform _world, const uniform vec2f &screenPos, uniform vec3f &pos, uniform int32 &instID, uniform int32 &geomID, uniform int32 &primID, uniform int32 &hit) { #ifndef OSPRAY_TARGET_SYCL const Renderer *uniform self = (const Renderer *uniform)_self; const Camera *uniform camera = (const Camera *uniform)_camera; const World *uniform world = (const World *uniform)_world; CameraSample cameraSample; cameraSample.screen.x = screenPos.x; cameraSample.screen.y = screenPos.y; // use center of lens and shutter time cameraSample.lens.x = 0.0f; cameraSample.lens.y = 0.0f; cameraSample.time = 0.5f; uniform FeatureFlagsHandler ffh; Ray ray; Camera_dispatch_initRay(camera, ray, cameraSample, ffh); ray.t = min(ray.t, Renderer_getMaxDepth(self, cameraSample.screen, ffh)); traceRay(world, ray, ffh); vec3f p = ray.org + ray.dir * ray.t; pos.x = extract(p.x, 0); pos.y = extract(p.y, 0); pos.z = extract(p.z, 0); hit = extract((int)(hadHit(ray)), 0); instID = extract(ray.instID, 0); geomID = extract(ray.geomID, 0); primID = extract(ray.primID, 0); #else (void)_self; (void)_camera; (void)_world; (void)screenPos; (void)pos; (void)instID; (void)geomID; (void)primID; (void)hit; #endif } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/RendererData.h000066400000000000000000000003451456566705700236000ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray #include "OSPCommon.h" namespace ospray { struct RendererData { virtual ~RendererData() = default; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/RendererRenderTaskFn.inl000066400000000000000000000101241456566705700256040ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // This is shared between ISPC and SYCL, in ISPC it's compiled // as a function in Renderer.ispc but in SYCL it's a template function in the // RendererShared header. #ifndef OSPRAY_TARGET_SYCL task #endif static void Renderer_default_renderTask(Renderer *uniform self, FrameBuffer *uniform fb, Camera *uniform camera, World *uniform world, const uint32 *uniform taskIDs, #ifdef OSPRAY_TARGET_SYCL const sycl::nd_item<3> taskIndex, #endif const uniform FeatureFlagsHandler &ffh) { const uniform int32 spp = self->spp; ScreenSample screenSample; screenSample.z = inf; screenSample.alpha = 0.f; CameraSample cameraSample; #ifdef OSPRAY_TARGET_SYCL uint32 taskIndex0 = taskIndex.get_global_id(0); #endif uniform RenderTaskDesc taskDesc = FrameBuffer_dispatch_getRenderTaskDesc(fb, taskIDs[taskIndex0], ffh); const uniform int startSampleID = (fb->doAccumulation ? max(fb->frameID, 0) * spp : 0) + 1; // Halton Sequence starts with 1 if (fb->cancelRender || isEmpty(taskDesc.region)) { return; } #ifdef OSPRAY_TARGET_SYCL { int32 y = taskDesc.region.lower.y + taskIndex.get_global_id(1); int32 x = taskDesc.region.lower.x + taskIndex.get_global_id(2); #else foreach_tiled (y = taskDesc.region.lower.y... taskDesc.region.upper.y, x = taskDesc.region.lower.x... taskDesc.region.upper.x) { #endif screenSample.sampleID.x = x; screenSample.sampleID.y = y; // set ray t value for early ray termination (from maximum depth texture) vec2f center = make_vec2f(screenSample.sampleID.x, screenSample.sampleID.y) + 0.5f; const float tMax = Renderer_getMaxDepth(self, center * fb->rcpSize, ffh); screenSample.z = tMax; vec3f col = make_vec3f(0.f); float alpha = 0.f; float depth = inf; vec3f normal = make_vec3f(0.f); vec3f albedo = make_vec3f(0.f); for (uniform int32 s = 0; s < spp; s++) { const float pixel_du = Halton_sample2(startSampleID + s); const float pixel_dv = CranleyPattersonRotation( Halton_sample3(self->mathConstants, startSampleID + s), 1.f / 6.f); // rotate to sample center (0.5) of pixel for sampleID=0 const vec2f pixelSample = make_vec2f(pixel_du, pixel_dv); vec2f pfSample = pixelSample; const PixelFilter *uniform pf = self->pixelFilter; if (pf) { pfSample = PixelFilter_dispatch_sample(pf, pixelSample) + make_vec2f(0.5f); } screenSample.sampleID.z = startSampleID + s; cameraSample.screen.x = (screenSample.sampleID.x + pfSample.x) * fb->rcpSize.x; cameraSample.screen.y = (screenSample.sampleID.y + pfSample.y) * fb->rcpSize.y; screenSample.pos = cameraSample.screen; // no DoF or MB per default cameraSample.lens.x = 0.0f; cameraSample.lens.y = 0.0f; cameraSample.time = 0.5f; Camera_dispatch_initRay(camera, screenSample.ray, cameraSample, ffh); screenSample.ray.t = min(screenSample.ray.t, tMax); screenSample.z = inf; screenSample.primID = RTC_INVALID_GEOMETRY_ID; screenSample.geomID = RTC_INVALID_GEOMETRY_ID; screenSample.instID = RTC_INVALID_GEOMETRY_ID; screenSample.albedo = make_vec3f(Renderer_getBackground(self, screenSample.pos, ffh)); screenSample.normal = make_vec3f(0.f); // The proper sample rendering function name is substitued here via macro renderSampleFn(self, fb, world, screenSample, ffh); col = col + screenSample.rgb; alpha += screenSample.alpha; depth = min(depth, screenSample.z); normal = normal + screenSample.normal; albedo = albedo + screenSample.albedo; } const float rspp = rcpf(spp); screenSample.rgb = col * rspp; screenSample.alpha = alpha * rspp; screenSample.z = depth; screenSample.normal = normal * rspp; screenSample.albedo = albedo * rspp; FrameBuffer_dispatch_accumulateSample(fb, screenSample, taskDesc, ffh); } FrameBuffer_dispatch_completeTask(fb, taskDesc, ffh); } RenderKit-ospray-f2a61c2/modules/cpu/render/RendererShared.h000066400000000000000000000017101456566705700241320ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Texture2D; struct Material; struct PixelFilter; struct MathConstants; struct Renderer { int32 spp; vec4f bgColor; // background color and alpha Texture2D *backplate; Texture2D *maxDepthTexture; // optional maximum depth texture used for early // ray termination uint32 maxDepth; float minContribution; int32 numMaterials; Material **material; PixelFilter *pixelFilter; MathConstants *mathConstants; #ifdef __cplusplus Renderer() : spp(1), bgColor(0.f), backplate(nullptr), maxDepthTexture(nullptr), maxDepth(20), minContribution(0.001f), numMaterials(0), material(nullptr), pixelFilter(nullptr), mathConstants(nullptr) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/ScreenSample.ih000066400000000000000000000012441456566705700237710ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/Ray.ih" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct ScreenSample { // input values to 'renderSample' vec3i sampleID; // x/y=pixelID, z=accumID/sampleID vec2f pos; // normalized screen position Ray ray; // the primary ray generated by the camera // return values from 'renderSample' vec3f rgb; float alpha; float z; vec3f normal; vec3f albedo; // IDs of primary ray hits. Invalid: unsigned RTC_INVALID_GEOMETRY_ID, 0xffff unsigned int primID; unsigned int geomID; unsigned int instID; }; OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/ao/000077500000000000000000000000001456566705700214645ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/render/ao/AORenderer.cpp000066400000000000000000000043061456566705700241610ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "AORenderer.h" #include "camera/Camera.h" #include "common/FeatureFlagsEnum.h" #include "common/World.h" #include "fb/FrameBuffer.h" #ifndef OSPRAY_TARGET_SYCL #include "render/ao/AORenderer_ispc.h" #else #include "AORenderer.ih" #endif namespace ospray { AORenderer::AORenderer(api::ISPCDevice &device, int defaultNumSamples) : AddStructShared(device.getIspcrtContext(), device), aoSamples(defaultNumSamples) {} std::string AORenderer::toString() const { return "ospray::render::AO"; } void AORenderer::commit() { Renderer::commit(); getSh()->aoSamples = getParam("aoSamples", aoSamples); getSh()->aoRadius = getParam("aoDistance", getParam("aoRadius", 1e20f)); getSh()->aoIntensity = getParam("aoIntensity", 1.f); getSh()->volumeSamplingRate = getParam("volumeSamplingRate", 1.f); } AsyncEvent AORenderer::renderTasks(FrameBuffer *fb, Camera *camera, World *world, void *, const utility::ArrayView &taskIDs, bool wait) const { AsyncEvent event; auto *rendererSh = getSh(); auto *fbSh = fb->getSh(); auto *cameraSh = camera->getSh(); auto *worldSh = world->getSh(); const size_t numTasks = taskIDs.size(); #ifdef OSPRAY_TARGET_SYCL const uint32_t *taskIDsPtr = taskIDs.data(); event = device.getSyclQueue().submit([&](sycl::handler &cgh) { FeatureFlags ff = world->getFeatureFlags(); ff |= featureFlags; ff |= fb->getFeatureFlags(); ff |= camera->getFeatureFlags(); cgh.set_specialization_constant(ff); cgh.parallel_for(fb->getDispatchRange(numTasks), [=](sycl::nd_item<3> taskIndex, sycl::kernel_handler kh) { ispc::FeatureFlagsHandler ffh(kh); ispc::AORenderer_renderTask(&rendererSh->super, fbSh, cameraSh, worldSh, taskIDsPtr, taskIndex, ffh); }); }); if (wait) event.wait_and_throw(); #else (void)wait; ispc::AORenderer_renderTasks( &rendererSh->super, fbSh, cameraSh, worldSh, taskIDs.data(), numTasks); #endif return event; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/ao/AORenderer.h000066400000000000000000000012161456566705700236230ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "render/Renderer.h" // ispc shared #include "AORendererShared.h" namespace ospray { struct AORenderer : public AddStructShared { AORenderer(api::ISPCDevice &device, int defaultAORendererSamples = 1); std::string toString() const override; void commit() override; virtual AsyncEvent renderTasks(FrameBuffer *fb, Camera *camera, World *world, void *perFrameData, const utility::ArrayView &taskIDs, bool wait) const override; private: int aoSamples{1}; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/ao/AORenderer.ih000066400000000000000000000007221456566705700237750ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/FeatureFlags.ih" OSPRAY_BEGIN_ISPC_NAMESPACE #ifdef OSPRAY_TARGET_SYCL SYCL_EXTERNAL void AORenderer_renderTask(Renderer *uniform self, FrameBuffer *uniform fb, Camera *uniform camera, World *uniform world, const uint32 *uniform taskIDs, const sycl::nd_item<3> taskIndex, const uniform FeatureFlagsHandler &ffh); #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/ao/AORenderer.ispc000066400000000000000000000127611456566705700243410ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "camera/Camera.ih" #include "camera/CameraDispatch.ih" #include "common/FeatureFlagsEnum.h" #include "fb/FrameBuffer.ih" #include "fb/FrameBufferDispatch.ih" #include "fb/RenderTaskDesc.ih" #include "math/random.ih" #include "pf/PixelFilterDispatch.ih" #include "render/Renderer.ih" #include "render/ScreenSample.ih" // AO renderer #include "surfaces.ih" #include "volumes.ih" // c++ shared #include "AORendererShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE static void AORenderer_renderSample(Renderer *uniform _self, FrameBuffer *uniform fb, World *uniform world, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { uniform AORenderer *uniform self = (uniform AORenderer * uniform) _self; const uniform FeatureFlags ff = getFeatureFlags(ffh); LDSampler ldSamplerObj; varying LDSampler *uniform ldSampler = &ldSamplerObj; LDSampler_init(ldSampler, self->super.mathConstants, sample.sampleID.x + fb->size.x * sample.sampleID.y, sample.sampleID.z); uniform bool firstHit = true; const float originalRayTFar = sample.ray.t; #ifdef OSPRAY_ENABLE_VOLUMES #ifdef OSPRAY_TARGET_SYCL // We only support a single volume interval on the GPU VolumeInterval vInterval; VolumeIntervals volumeIntervals; volumeIntervals.numVolumeIntervals = 0; volumeIntervals.numAllocated = 1; volumeIntervals.intervals = &vInterval; #else // Allocate memory for volume intervals VolumeIntervals volumeIntervals; allocVolumeIntervals(volumeIntervals); #endif #endif // This is our main ray Ray &ray = sample.ray; // First trace the ray across clipping scene to calculate ray intervals, // this step should keep ray structure unchanged RayIntervals rayIntervals; traceClippingRay(world, ray, rayIntervals, ffh); // Iterate over all translucent geometry till we are fully opaque vec4f outputColor = make_vec4f(0.f); while (outputColor.w < 0.99f) { // Then trace normal geometry using calculated ray intervals, // if hit ray.t will be updated if (ff.geometry) { traceGeometryRayIntervals(world, ray, rayIntervals, ffh); } #ifdef OSPRAY_ENABLE_VOLUMES if (ff.other & FFO_VOLUME_IN_SCENE) { // Determine volume intervals by tracing ray in the volume scene Ray volumeRay = ray; traceVolumeRay(world, volumeRay, volumeIntervals); // Sample volumes across volume intervals (in front of geometry hit) if (volumeIntervals.numVolumeIntervals > 0) { vec4f volumeColor = integrateVolumeIntervals(volumeIntervals, rayIntervals, volumeRay, ldSampler, self->volumeSamplingRate, ffh); outputColor = outputColor + (1.f - outputColor.w) * volumeColor; } } #endif // If any geometry has been hit vec4f blendedColor; const bool rayHadHit = hadHit(ray); if (rayHadHit && ff.geometry) { // Prepare differential geometry structure DifferentialGeometry dg; computeDG(world, self, ray, dg, ffh); // Shade geometry SSI surfaceShading; surfaceShading = AORenderer_computeShading(self, world, dg, sample, ffh); // Use shaded color for blending blendedColor = surfaceShading.shadedColor; // Initialize other per sample data with first hit values if (firstHit) { sample.z = ray.t; sample.albedo = surfaceShading.albedo; sample.normal = dg.Ns; sample.instID = dg.instID; sample.geomID = dg.objID; sample.primID = ray.primID; } // Prepare ray for next loop iteration, // start from the last geometry hit all over to initial Tfar setRay(ray, ray.t + dg.epsilon, originalRayTFar); } else { blendedColor = Renderer_getBackground(&self->super, sample.pos, ffh); // Initialize other per sample data with first hit values if (firstHit) { sample.z = ray.t; sample.albedo = make_vec3f(blendedColor); sample.normal = sample.ray.dir; } } // Blend with output final color outputColor = outputColor + (1.f - outputColor.w) * blendedColor; firstHit = false; if (!rayHadHit) { break; } } #if defined(OSPRAY_ENABLE_VOLUMES) && !defined(OSPRAY_TARGET_SYCL) freeVolumeIntervals(volumeIntervals); #endif sample.rgb = make_vec3f(outputColor); sample.alpha = outputColor.w; } #define renderSampleFn AORenderer_renderSample #include "render/RendererRenderTaskFn.inl" #undef renderSampleFn #ifdef OSPRAY_TARGET_SYCL SYCL_EXTERNAL void AORenderer_renderTask(Renderer *uniform self, FrameBuffer *uniform fb, Camera *uniform camera, World *uniform world, const uint32 *uniform taskIDs, const sycl::nd_item<3> taskIndex, const uniform FeatureFlagsHandler &ffh) { Renderer_default_renderTask(self, fb, camera, world, taskIDs, taskIndex, ffh); } #else export void AORenderer_renderTasks(void *uniform _self, void *uniform _fb, void *uniform _camera, void *uniform _world, void *uniform _taskIDs, uniform uint32 numTasks) { Renderer *uniform self = (Renderer * uniform) _self; FrameBuffer *uniform fb = (FrameBuffer * uniform) _fb; Camera *uniform camera = (Camera * uniform) _camera; World *uniform world = (World * uniform) _world; const uint32 *uniform taskIDs = (const uint32 *uniform)_taskIDs; uniform FeatureFlagsHandler ffh; launch[numTasks] Renderer_default_renderTask( self, fb, camera, world, taskIDs, ffh); sync; } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/ao/AORendererShared.h000066400000000000000000000007421456566705700247550ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/RendererShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct AORenderer { Renderer super; int aoSamples; float aoRadius; float aoIntensity; float volumeSamplingRate; #ifdef __cplusplus AORenderer() : aoSamples(1), aoRadius(1e20f), aoIntensity(1.f), volumeSamplingRate(1.f) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/ao/surfaces.ih000066400000000000000000000017361456566705700236300ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/FeatureFlagsEnum.h" #include "common/World.ih" // c++ shared #include "AORendererShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE struct DifferentialGeometry; struct FrameBuffer; struct ScreenSample; struct SurfaceShadingInfo { vec4f shadedColor; vec3f albedo; }; typedef SurfaceShadingInfo SSI; inline void computeDG(const World *uniform world, const AORenderer *uniform renderer, const Ray &ray, DifferentialGeometry &dg, const uniform FeatureFlagsHandler &ffh) { postIntersect(world, &renderer->super, dg, ray, DG_NG | DG_NS | DG_NORMALIZE | DG_FACEFORWARD | DG_COLOR | DG_TEXCOORD, ffh); } SYCL_EXTERNAL SSI AORenderer_computeShading(const AORenderer *uniform self, const World *uniform world, const DifferentialGeometry &dg, ScreenSample &sample, const uniform FeatureFlagsHandler &ffh); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/ao/surfaces.ispc000066400000000000000000000041401456566705700241560ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/FeatureFlagsEnum.h" #include "math/random.ih" #include "math/sampling.ih" #include "render/ScreenSample.ih" #include "render/materials/OBJ.ih" #include "render/util.ih" #include "texture/TextureParam.ih" // AO Renderer #include "surfaces.ih" // c++ shared #include "render/materials/OBJShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE inline vec4f getSurfaceColor( const DifferentialGeometry &dg, const uniform FeatureFlagsHandler &ffh) { const OBJ *mat = (const OBJ *)dg.material; vec3f surfaceColor = make_vec3f(1.f); float opacity = 1.f; const uniform FeatureFlags ff = getFeatureFlags(ffh); const uniform bool fft = ff.other & FFO_TEXTURE_IN_MATERIAL; foreach_unique (m in mat) { if (m != NULL && m->super.type == MATERIAL_TYPE_OBJ) { surfaceColor = m->Kd; if (valid(m->KdMap) && fft) { vec4f Kd_from_map = get4f(m->KdMap, dg); surfaceColor = surfaceColor * make_vec3f(Kd_from_map); opacity *= Kd_from_map.w; } opacity *= m->d * (fft ? get1f(m->dMap, dg, 1.f) : 1.f); } } return make_vec4f(surfaceColor * make_vec3f(dg.color), opacity * dg.color.w); } SYCL_EXTERNAL SSI AORenderer_computeShading(const AORenderer *uniform self, const World *uniform world, const DifferentialGeometry &dg, ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { SSI retval; const vec4f surfaceColor = getSurfaceColor(dg, ffh); const vec3f color = make_vec3f(surfaceColor); const float opacity = surfaceColor.w; const float eyeLightIntensity = absf(dot(dg.Ns, sample.ray.dir)) * opacity; float intensity = eyeLightIntensity; if (self->aoSamples > 0 && self->aoIntensity > 0.01f) { const float ao = computeAO(&self->super, world, dg, self->aoSamples, self->aoRadius, sample.sampleID, ffh); intensity *= (1.0f - self->aoIntensity) + (ao * self->aoIntensity); } retval.shadedColor = make_vec4f(color * intensity, opacity); retval.albedo = color; return retval; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/ao/volumes.ih000066400000000000000000000011141456566705700234750ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #pragma once #include "common/Clipping.ih" #include "common/FeatureFlagsEnum.h" #include "common/Ray.ih" #include "common/VolumeIntervals.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct LDSampler; SYCL_EXTERNAL vec4f integrateVolumeIntervals(const VolumeIntervals &intervals, const RayIntervals &rayIntervals, Ray &ray, varying LDSampler *uniform ldSampler, const uniform float samplingRate, const uniform FeatureFlagsHandler &ffh); OSPRAY_END_ISPC_NAMESPACE #endif RenderKit-ospray-f2a61c2/modules/cpu/render/ao/volumes.ispc000066400000000000000000000260571456566705700240500ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #include "math/random.ih" #include "math/sampling.ih" #include "render/util.ih" #include "volume/Volume.ih" #include "volume/VolumetricModel.ih" #include "volume/transferFunction/TransferFunctionDispatch.ih" #include "volumes.ih" OSPRAY_BEGIN_ISPC_NAMESPACE #ifndef OSPRAY_TARGET_SYCL struct VolumeContext { uniform uint8 intervalIteratorBuffer[VKL_MAX_INTERVAL_ITERATOR_SIZE]; VKLIntervalIterator intervalIterator; VKLInterval interval; vec3f org; vec3f dir; float iuLength; // VKL interval length in sampling steps as an unit float iuDistance; // sampling distance within VKL interval in sampling steps // as an unit float distance; // last sampling distance from 'vc.org' vec4f sample; uint32 ready; // 1 if sample is ready to be used }; static void sampleVolume(VolumeContext &vc, const VolumetricModel *uniform m, const uniform float samplingRate) { // We have to iterate till we get a valid sample value float dt = 0.f; float sampleVal = nan; while (isnan(sampleVal)) { // Iterate till sampling position is within interval float emptySpace = 0.f; while (vc.iuDistance > vc.iuLength) { // Get next VKL interval const float prevUpper = vc.interval.tRange.upper; if (vklIterateIntervalV(vc.intervalIterator, &vc.interval)) { // Intervals may not be contiguous, accumulate empty space emptySpace += max(vc.interval.tRange.lower - prevUpper, 0.f); // Make it local for the next interval vc.iuDistance -= vc.iuLength; // Calculate how many steps can be made within this interval const float samplingStep = vc.interval.nominalDeltaT / samplingRate; vc.iuLength = (vc.interval.tRange.upper - vc.interval.tRange.lower) / samplingStep; // Initialize distance if necessary vc.distance = (vc.distance == inf) ? vc.interval.tRange.lower : vc.distance; } else { // The end of the volume has been reached vc.distance = inf; return; } } // Calculate sampling distance const float samplingStep = vc.interval.nominalDeltaT / samplingRate; const float newDistance = vc.interval.tRange.lower + vc.iuDistance * samplingStep; // Prepare sampling position const vec3f p = vc.org + newDistance * vc.dir; // Sample volume value in given point sampleVal = vklComputeSampleV( &m->volume->vklSampler, (const varying vkl_vec3f *uniform) & p); // Go to the next sub-interval vc.iuDistance += 1.f; dt = newDistance - vc.distance - emptySpace; vc.distance = newDistance; } // Apply transfer function to get color with alpha vc.sample = TransferFunction_dispatch_get(m->transferFunction, sampleVal); // Weight the opacity with deltaT using Beer law vc.sample.w = 1.f - exp(-vc.sample.w * dt * m->densityScale); } static float sampleAllVolumes(const VolumeIntervals &volumeIntervals, varying VolumeContext *uniform volumeContexts, const uniform float samplingRate, vec4f &sampledColor) { // Look for the closest sample across all volumes float minDist = inf; int usedSampleId = -1; for (uniform uint32 i = 0; i < reduce_max(volumeIntervals.numVolumeIntervals); i++) { if (i >= volumeIntervals.numVolumeIntervals) break; // If the sample has been used already regenerate a new one VolumeContext &vc = volumeContexts[i]; if (vc.ready == 0) { const VolumeInterval &vi = volumeIntervals.intervals[i]; foreach_unique (m in vi.volumetricModel) sampleVolume(vc, m, samplingRate); vc.ready = 1; } // Take the sample if closer if (vc.distance < minDist) { minDist = vc.distance; sampledColor = vc.sample; usedSampleId = i; } } // Mark used samples as not ready if (usedSampleId != -1) { volumeContexts[usedSampleId].ready = 0; } // Return distance for sampled color return minDist; } SYCL_EXTERNAL vec4f integrateVolumeIntervals( const VolumeIntervals &volumeIntervals, const RayIntervals &rayIntervals, Ray &ray, varying LDSampler *uniform ldSampler, const uniform float samplingRate, const uniform FeatureFlagsHandler &) { // Array of volume contexts varying VolumeContext *uniform volumeContexts = (varying VolumeContext * uniform) pushTLS(reduce_max(volumeIntervals.numVolumeIntervals) * sizeof(varying VolumeContext)); // Sampling position jitter const float jitter = LDSampler_getFloat(ldSampler, 0); // Iterate through all volumes and initialize its contexts with data that // do not change across ray intervals for (uniform uint32 i = 0; i < reduce_max(volumeIntervals.numVolumeIntervals); i++) { if (i >= volumeIntervals.numVolumeIntervals) break; // Transform ray into the volume local space const VolumeInterval &vi = volumeIntervals.intervals[i]; Ray transformedRay = ray; AffineSpace3f instanceRcpXfm = vi.instance->rcp_xfm; transformRay(transformedRay, instanceRcpXfm); // Set volume context initial values VolumeContext &vc = volumeContexts[i]; vc.org = transformedRay.org; vc.dir = transformedRay.dir; } // Define initial color with alpha vec3f color = make_vec3f(0.f); float alpha = 0.f; // Iterate through all ray intervals for (uniform uint32 i = 0; i < reduce_max(rayIntervals.count) && (alpha < .99f); i++) { if (i >= rayIntervals.count) break; // Iterate through all volumes for (uniform uint32 j = 0; j < reduce_max(volumeIntervals.numVolumeIntervals); j++) { if (j >= volumeIntervals.numVolumeIntervals) break; // Calculate volume and ray intervals union const VolumeInterval &vi = volumeIntervals.intervals[j]; range1f rInterval = rayIntervals.intervals[i]; rInterval.lower = max(rInterval.lower, vi.interval.lower); rInterval.upper = min(rInterval.upper, vi.interval.upper); // Reset distance to sample VolumeContext &vc = volumeContexts[j]; vc.distance = inf; // Check if volume and ray intervals overlap if (rInterval.upper <= rInterval.lower) { // Skip this volume if not vc.ready = 1; continue; } // We will sample across this volume so initialize members used during // sampling vc.iuDistance = jitter; vc.iuLength = 0.f; vc.ready = 0; vc.interval.tRange.upper = inf; // There might be different volumetric models used across vector lanes // so we must iterate over them float time = 0.5f; VolumetricModel *varying model = vi.volumetricModel; // Create volume interval iterator foreach_unique (m in model) vc.intervalIterator = vklInitIntervalIteratorV(&m->vklIntervalContext, (varying vkl_vec3f *)&vc.org, (varying vkl_vec3f *)&vc.dir, (varying vkl_range1f *)&rInterval, &time, vc.intervalIteratorBuffer); } // Propagate ray across all volumes till opaque while (alpha < .99f) { // Sample across all volumes vec4f sampledColorOpacity; float dist = sampleAllVolumes( volumeIntervals, volumeContexts, samplingRate, sampledColorOpacity); // Exit loop if nothing sampled if (dist == inf) break; // Alpha blend sampled color color = color + ((1.f - alpha) * sampledColorOpacity.w * make_vec3f(sampledColorOpacity)); alpha = alpha + ((1.f - alpha) * sampledColorOpacity.w); } } popTLS(volumeContexts); // Return final color return make_vec4f(color, alpha); } #else // GPU version SYCL_EXTERNAL vec4f integrateVolumeIntervals( const VolumeIntervals &volumeIntervals, const RayIntervals &, Ray &ray, varying LDSampler *uniform ldSampler, const uniform float samplingRate, const uniform FeatureFlagsHandler &ffh) { const VolumeInterval &vi = volumeIntervals.intervals[0]; Ray tRay = ray; AffineSpace3f instanceRcpXfm = vi.instance->rcp_xfm; transformRay(tRay, instanceRcpXfm); // Define initial color with alpha vec3f color = make_vec3f(0.f); float alpha = 0.f; const uniform FeatureFlags ff = getFeatureFlags(ffh); uniform uint8 intervalIteratorBuffer[VKL_MAX_INTERVAL_ITERATOR_SIZE]; VolumetricModel *varying m = vi.volumetricModel; VKLIntervalIterator intervalIterator = vklInitIntervalIteratorV(&m->vklIntervalContext, (varying vkl_vec3f *)&tRay.org, (varying vkl_vec3f *)&tRay.dir, (varying vkl_range1f *)&vi.interval, .5f, intervalIteratorBuffer, ff.volume); // Sampling position jitter const float jitter = LDSampler_getFloat(ldSampler, 0); // Propagate ray across all volumes till opaque float distance = inf; float iuDistance = jitter; float iuLength = 0.f; VKLInterval interval; interval.tRange.upper = inf; float samplingStep = 0.f; while (alpha < .99f) { // Iterate till sampling position is within interval float emptySpace = 0.f; while (iuDistance > iuLength) { // Get next VKL interval const float prevUpper = interval.tRange.upper; if (vklIterateIntervalV(intervalIterator, &interval, ff.volume)) { // Intervals may not be contiguous, accumulate empty space emptySpace += max(interval.tRange.lower - prevUpper, 0.f); // Make it local for the next interval iuDistance -= iuLength; // Calculate how many steps can be made within this interval samplingStep = interval.nominalDeltaT / samplingRate; iuLength = (interval.tRange.upper - interval.tRange.lower) / samplingStep; // Initialize distance if necessary distance = (distance == inf) ? interval.tRange.lower : distance; } else { // The end of the volume has been reached return make_vec4f(color, alpha); } } // Calculate sampling distance const float newDistance = interval.tRange.lower + iuDistance * samplingStep; // Prepare sampling position const vec3f p = tRay.org + newDistance * tRay.dir; // Sample volume value in given point float sampleVal = vklComputeSampleV(&m->volume->vklSampler, (const varying vkl_vec3f *uniform) & p, 0, .5f, ff.volume); if (!isnan(sampleVal)) { // Apply transfer function to get color with alpha vec4f sampledColor = TransferFunction_dispatch_get(m->transferFunction, sampleVal); // Weight the opacity with deltaT using Beer law float dt = newDistance - distance - emptySpace; sampledColor.w = 1.f - exp(-sampledColor.w * dt * m->densityScale); // Alpha blend sampled color color = color + ((1.f - alpha) * sampledColor.w * make_vec3f(sampledColor)); alpha = alpha + ((1.f - alpha) * sampledColor.w); } // Go to the next sub-interval iuDistance += 1.f; distance = newDistance; } // Return final color return make_vec4f(color, alpha); } #endif OSPRAY_END_ISPC_NAMESPACE #endif RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/000077500000000000000000000000001456566705700221665ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/BSDF.ih000066400000000000000000000065071456566705700232360ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/FeatureFlags.ih" #include "common/OSPCommon.ih" #include "render/pathtracer/Scattering.ih" #include "rkcommon/math/LinearSpace.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // keep interface of BSDFs the same typedef Scattering_EvalRes BSDF_EvalRes; typedef Scattering_SampleRes BSDF_SampleRes; typedef Scattering_Type BSDFScatteringType; #define BSDF_SPECULAR_REFLECTION SCATTERING_SPECULAR_REFLECTION #define BSDF_GLOSSY_REFLECTION SCATTERING_GLOSSY_REFLECTION #define BSDF_DIFFUSE_REFLECTION SCATTERING_DIFFUSE_REFLECTION #define BSDF_SPECULAR_TRANSMISSION SCATTERING_SPECULAR_TRANSMISSION #define BSDF_GLOSSY_TRANSMISSION SCATTERING_GLOSSY_TRANSMISSION #define BSDF_DIFFUSE_TRANSMISSION SCATTERING_DIFFUSE_TRANSMISSION #define BSDF_DIFFUSE SCATTERING_DIFFUSE #define BSDF_GLOSSY SCATTERING_GLOSSY #define BSDF_SPECULAR SCATTERING_SPECULAR #define BSDF_REFLECTION SCATTERING_REFLECTION #define BSDF_TRANSMISSION SCATTERING_TRANSMISSION #define BSDF_SMOOTH SCATTERING_SMOOTH #define BSDF_NONE SCATTERING_NONE #define BSDF_ALL SCATTERING_ALL enum BSDFType { BSDF_TYPE_UNKNOWN, BSDF_TYPE_OBJ, BSDF_TYPE_THINGLASS, BSDF_TYPE_GLASS, BSDF_TYPE_LUMINOUS, BSDF_TYPE_METAL, BSDF_TYPE_METAL_ROUGH, BSDF_TYPE_METALLICPAINT, BSDF_TYPE_MIX, BSDF_TYPE_CARPAINT, BSDF_TYPE_PRINCIPLED, BSDF_TYPE_ALLOY, BSDF_TYPE_ALLOY_ROUGH, BSDF_TYPE_PLASTIC, BSDF_TYPE_VELVET, BSDF_TYPE_CONDUCTOR, BSDF_TYPE_DIELECTRIC, BSDF_TYPE_DIELECTRIC_LAYER, BSDF_TYPE_LAMBERT, BSDF_TYPE_LAMBERT_TRANSMISSION, BSDF_TYPE_MICROFACET_CONDUCTOR, BSDF_TYPE_MICROFACET_DIELECTRIC, BSDF_TYPE_MICROFACET_DIELECTRIC_LAYER, BSDF_TYPE_MICROFACET_SHEEN_LAYER, BSDF_TYPE_MINNEART, BSDF_TYPE_MULTI_BSDF, BSDF_TYPE_OREN_NAYAR, BSDF_TYPE_SPECULAR, BSDF_TYPE_SCALE, BSDF_TYPE_REFLECTION, BSDF_TYPE_ROBUST_DIELECTRIC, BSDF_TYPE_ROBUST_THIN_DIELECTRIC, BSDF_TYPE_THIN_DIELECTRIC, BSDF_TYPE_THIN_MICROFACET_DIELECTRIC, BSDF_TYPE_TRANSMISSION, BSDF_TYPE_VELVETY }; inline BSDF_EvalRes make_BSDF_EvalRes_zero() { BSDF_EvalRes res; res.value = make_vec3f(0.0f); res.pdf = 0.0f; return res; } inline BSDF_SampleRes make_BSDF_SampleRes_zero() { BSDF_SampleRes res; res.weight = make_vec3f(0.0f); return res; } struct BSDF { varying vec3f albedo; varying BSDFScatteringType scatteringType; uniform BSDFType bsdfType; const varying linear3f *uniform frame; }; inline void BSDF_Constructor(varying BSDF *uniform self, varying vec3f albedo, varying BSDFScatteringType scatteringType, uniform BSDFType bsdfType, const varying linear3f *uniform frame) { self->albedo = albedo; self->scatteringType = scatteringType; self->bsdfType = bsdfType; self->frame = frame; } inline vec3f getN(const varying BSDF *uniform bsdf) { return bsdf->frame->vz; } inline linear3f getFrame(const varying BSDF *uniform bsdf) { return *bsdf->frame; } SYCL_EXTERNAL __noinline BSDF_EvalRes BSDF_dispatch_eval( const varying BSDF *uniform self, const vec3f &wo, const vec3f &wi, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL __noinline BSDF_SampleRes BSDF_dispatch_sample( const varying BSDF *uniform self, const vec3f &wo, const vec2f &s, float ss, const uniform FeatureFlagsHandler &ffh); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/BSDF.ispc000066400000000000000000000107161456566705700235710ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/bsdfs/BSDF.ih" #include "common/FeatureFlags.ih" #include "common/FeatureFlagsEnum.h" #include "render/materials/Alloy.ih" #include "render/materials/CarPaint.ih" #include "render/materials/Glass.ih" #include "render/materials/Luminous.ih" #include "render/materials/Metal.ih" #include "render/materials/MetallicPaint.ih" #include "render/materials/Mix.ih" #include "render/materials/OBJ.ih" #include "render/materials/Plastic.ih" #include "render/materials/Principled.ih" #include "render/materials/ThinGlass.ih" #include "render/materials/Velvet.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL __noinline BSDF_EvalRes BSDF_dispatch_eval( const varying BSDF *uniform self, const vec3f &wo, const vec3f &wi, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlagsOther ffo = getFeatureFlagsOther(ffh); if ((self->bsdfType == BSDF_TYPE_OBJ) && (ffo & FFO_MATERIAL_OBJ)) { return OBJ_BSDF_eval(self, wo, wi); } else if ((self->bsdfType == BSDF_TYPE_ALLOY_ROUGH) && (ffo & FFO_MATERIAL_ALLOY)) { return AlloyRough_BSDF_eval(self, wo, wi); } else if ((self->bsdfType == BSDF_TYPE_METAL_ROUGH) && (ffo & FFO_MATERIAL_METAL)) { return MetalRough_BSDF_eval(self, wo, wi); } else if ((self->bsdfType == BSDF_TYPE_METALLICPAINT) && (ffo & FFO_MATERIAL_METALLICPAINT)) { return MetallicPaint_BSDF_eval(self, wo, wi); } else if ((self->bsdfType == BSDF_TYPE_CARPAINT) && (ffo & FFO_MATERIAL_CARPAINT)) { return CarPaint_BSDF_eval(self, wo, wi); } else if ((self->bsdfType == BSDF_TYPE_PRINCIPLED) && (ffo & FFO_MATERIAL_PRINCIPLED)) { return Principled_BSDF_eval(self, wo, wi); } else if ((self->bsdfType == BSDF_TYPE_PLASTIC) && (ffo & FFO_MATERIAL_PLASTIC)) { return Plastic_BSDF_eval(self, wo, wi); } else if ((self->bsdfType == BSDF_TYPE_VELVET) && (ffo & FFO_MATERIAL_VELVET)) { return Velvet_BSDF_eval(self, wo, wi); } #ifndef OSPRAY_TARGET_SYCL else if ((self->bsdfType == BSDF_TYPE_MIX) && (ffo & FFO_MATERIAL_MIX)) { return Mix_BSDF_eval(self, wo, wi); } #endif return make_BSDF_EvalRes_zero(); } SYCL_EXTERNAL __noinline BSDF_SampleRes BSDF_dispatch_sample( const varying BSDF *uniform self, const vec3f &wo, const vec2f &s, float ss, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlagsOther ffo = getFeatureFlagsOther(ffh); if ((self->bsdfType == BSDF_TYPE_OBJ) && (ffo & FFO_MATERIAL_OBJ)) { return OBJ_BSDF_sample(self, wo, s, ss); } else if ((self->bsdfType == BSDF_TYPE_THINGLASS) && (ffo & FFO_MATERIAL_THINGLASS)) { return ThinGlass_BSDF_sample(self, wo, s, ss); } else if ((self->bsdfType == BSDF_TYPE_GLASS) && (ffo & FFO_MATERIAL_GLASS)) { return Glass_BSDF_sample(self, wo, s, ss); } else if ((self->bsdfType == BSDF_TYPE_LUMINOUS) && (ffo & FFO_MATERIAL_LUMINOUS)) { return Luminous_BSDF_sample(self, wo, s, ss); } else if ((self->bsdfType == BSDF_TYPE_ALLOY) && (ffo & FFO_MATERIAL_ALLOY)) { return Alloy_BSDF_sample(self, wo, s, ss); } else if ((self->bsdfType == BSDF_TYPE_ALLOY_ROUGH) && (ffo & FFO_MATERIAL_ALLOY)) { return AlloyRough_BSDF_sample(self, wo, s, ss); } else if ((self->bsdfType == BSDF_TYPE_METAL) && (ffo & FFO_MATERIAL_METAL)) { return Metal_BSDF_sample(self, wo, s, ss); } else if ((self->bsdfType == BSDF_TYPE_METAL_ROUGH) && (ffo & FFO_MATERIAL_METAL)) { return MetalRough_BSDF_sample(self, wo, s, ss); } else if ((self->bsdfType == BSDF_TYPE_METALLICPAINT) && (ffo & FFO_MATERIAL_METALLICPAINT)) { return MetallicPaint_BSDF_sample(self, wo, s, ss); } else if ((self->bsdfType == BSDF_TYPE_CARPAINT) && (ffo & FFO_MATERIAL_CARPAINT)) { return CarPaint_BSDF_sample(self, wo, s, ss); } else if ((self->bsdfType == BSDF_TYPE_PRINCIPLED) && (ffo & FFO_MATERIAL_PRINCIPLED)) { return Principled_BSDF_sample(self, wo, s, ss); } else if ((self->bsdfType == BSDF_TYPE_PLASTIC) && (ffo & FFO_MATERIAL_PLASTIC)) { return Plastic_BSDF_sample(self, wo, s, ss); } else if ((self->bsdfType == BSDF_TYPE_VELVET) && (ffo & FFO_MATERIAL_VELVET)) { return Velvet_BSDF_sample(self, wo, s, ss); } #ifndef OSPRAY_TARGET_SYCL else if ((self->bsdfType == BSDF_TYPE_MIX) && (ffo & FFO_MATERIAL_MIX)) { return Mix_BSDF_sample(self, wo, s, ss); } #endif return make_BSDF_SampleRes_zero(); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/BeckmannDistribution.ih000066400000000000000000000016741456566705700266360ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "MicrofacetDistribution.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // Beckmann distribution struct BeckmannDistribution { float alpha; }; inline BeckmannDistribution make_BeckmannDistribution(float alpha) { BeckmannDistribution m; m.alpha = alpha; return m; } inline vec3f sample( const BeckmannDistribution &self, float &pdf, const vec2f &s) { float alpha2 = sqr(self.alpha); float tanTheta2 = -alpha2 * log(1.f - s.x); float cosTheta = rsqrt(1.f + tanTheta2); float sinTheta = cos2sin(cosTheta); float phi = 2.f * (float)pi * s.y; float cosTheta3 = sqr(cosTheta) * cosTheta; pdf = (1.f - s.x) * rcp((float)pi * alpha2 * cosTheta3); float sinPhi, cosPhi; sincos(phi, &sinPhi, &cosPhi); float x = cosPhi * sinTheta; float y = sinPhi * sinTheta; float z = cosTheta; return make_vec3f(x, y, z); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/Conductor.ih000066400000000000000000000024751456566705700244600ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "BSDF.ih" #include "Fresnel.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Conductor { BSDF super; Fresnel *uniform fresnel; }; inline BSDF_SampleRes Conductor_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &, float) { const varying Conductor *uniform self = (const varying Conductor *uniform)super; BSDF_SampleRes res; res.wi = reflect(wo, getN(super)); res.pdf = inf; res.type = BSDF_SPECULAR_REFLECTION; res.weight = Fresnel_dispatch_eval(self->fresnel, dot(wo, getN(super))); return res; } inline void Conductor_Constructor(varying Conductor *uniform self, const varying linear3f *uniform frame, Fresnel *uniform fresnel) { BSDF_Constructor(&self->super, Fresnel_dispatch_evalAvg(fresnel), BSDF_SPECULAR_REFLECTION, BSDF_TYPE_CONDUCTOR, frame); self->fresnel = fresnel; } inline varying BSDF *uniform Conductor_create( uniform ShadingContext *uniform ctx, const varying linear3f *uniform frame, Fresnel *uniform fresnel) { varying Conductor *uniform self = (varying Conductor * uniform) ShadingContext_alloc(ctx, sizeof(Conductor)); Conductor_Constructor(self, frame, fresnel); return &self->super; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/Dielectric.ih000066400000000000000000000042431456566705700245620ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "BSDF.ih" #include "Fresnel.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // FIXME: improve robustness struct Dielectric { BSDF super; float eta; // etaO / etaI }; inline BSDF_EvalRes Dielectric_eval( const varying BSDF *uniform, const vec3f &, const vec3f &) { return make_BSDF_EvalRes_zero(); } inline BSDF_SampleRes Dielectric_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &, float ss) { const varying Dielectric *uniform self = (const varying Dielectric *uniform)super; BSDF_SampleRes res; float cosThetaO = max(dot(wo, getN(super)), 0.f); // Fresnel term float cosThetaT; // positive float F = fresnelDielectricEx(cosThetaO, cosThetaT, self->eta); res.pdf = inf; // Sample the reflection or the transmission bool doReflection = (ss <= F); if (doReflection) { // Reflection res.wi = reflect(wo, getN(super), cosThetaO); res.type = BSDF_SPECULAR_REFLECTION; res.weight = make_vec3f(1.f); } else { // Transmission res.wi = refract(wo, getN(super), cosThetaO, cosThetaT, self->eta); res.type = BSDF_SPECULAR_TRANSMISSION; // res.weight = make_vec3f(sqr(self->eta)); // solid angle compression res.weight = make_vec3f(1.f); // ignore solid angle compression } return res; } inline void Dielectric_Constructor(varying Dielectric *uniform self, const varying linear3f *uniform frame, float eta) { BSDF_Constructor(&self->super, make_vec3f(1.0f), BSDF_SPECULAR, BSDF_TYPE_DIELECTRIC, frame); self->eta = eta; } inline varying BSDF *uniform Dielectric_create( uniform ShadingContext *uniform ctx, const varying linear3f *uniform frame, float eta) { varying Dielectric *uniform self = (varying Dielectric * uniform) ShadingContext_alloc(ctx, sizeof(Dielectric)); Dielectric_Constructor(self, frame, eta); return &self->super; } // Helper function for transparent shadow rays inline vec3f Dielectric_getTransparency(float cosThetaO, float eta) { float T = 1.f - fresnelDielectric(cosThetaO, eta); return make_vec3f(T); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/DielectricLayer.ih000066400000000000000000000241571456566705700255650ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Dielectric.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // Simplified, energy conserving Weidlich-Wilkie smooth coating BSDF. // Refraction is ignored, but absorption is computed from the refracted ray // lengths. [Weidlich and Wilkie, 2007, "Arbitrarily Layered Micro-Facet // Surfaces"] [Kulla and Conty, 2017, "Revisiting Physically Based Shading at // Imageworks"] [Kelemen and Szirmay-Kalos, 2001, "A Microfacet Based Coupled // Specular-Matte BRDF Model with Importance Sampling"] struct DielectricLayer { BSDF super; float weight; float eta; vec3f transmittance; float thickness; // Energy conservation [Kulla and Conty, 2017] float Favg; }; inline void DielectricLayer_Constructor(varying DielectricLayer *uniform self, const varying linear3f *uniform frame, varying BSDF *varying substrate, float eta, vec3f transmittance, float thickness, float weight) { self->Favg = fresnelDielectricAvg(eta) * weight; // XXX check const vec3f albedo = substrate->albedo * ((1.0f - weight) + pow(transmittance, thickness) * (1.f - self->Favg)); BSDF_Constructor(&self->super, albedo, BSDF_SPECULAR_REFLECTION | substrate->scatteringType, BSDF_TYPE_DIELECTRIC_LAYER, frame); self->eta = (eta <= 1.f) ? eta : rcp(eta); self->transmittance = transmittance; self->thickness = thickness; self->weight = weight; } // Helper function for transparent shadow rays inline vec3f DielectricLayer_getTransparency(float cosThetaO, float eta, vec3f transmittance, float thickness, float weight) { if (eta < 1.f) eta = rcp(eta); // Fresnel term float cosThetaO1; // positive float Fo = fresnelDielectricEx(cosThetaO, cosThetaO1, eta) * weight; // Apply the coating medium absorption // Use refracted angles for computing the absorption path length float lengthO1 = rcp(cosThetaO1); vec3f value = lerp(weight, make_vec3f(1.f), pow(transmittance, thickness * lengthO1)); // Energy conservation float T = 1.f - Fo; // for generic (non-diffuse) substrates [Kulla and Conty, 2017] value = value * T; return value; } OSPRAY_END_ISPC_NAMESPACE // Eval macros #define DIELECTRICLAYER_EVAL( \ dl_name, scatteringType, substrate_bsdf, substrate_fn) \ const varying DielectricLayer *uniform dl = \ (const varying DielectricLayer *uniform) & dl_name; \ \ float cosThetaO = dot(wo, getN(&dl->super)); \ if (cosThetaO <= 0.f) \ return make_BSDF_EvalRes_zero(); \ \ /* Evaluate the substrate */ \ /* Ignore refraction */ \ BSDF_EvalRes substrate = substrate_fn(substrate_bsdf, wo, wi); \ \ /* Fresnel term */ \ float cosThetaO1; /* positive */ \ float Fo = fresnelDielectricEx(cosThetaO, cosThetaO1, dl->eta) * dl->weight; \ \ float cosThetaI = dot(wi, getN(&dl->super)); \ float cosThetaI1; /* positive */ \ float Fi = \ fresnelDielectricEx(abs(cosThetaI), cosThetaI1, dl->eta) * dl->weight; \ \ /* Apply the coating medium absorption */ \ /* Use refracted angles for computing the absorption path length */ \ float lengthO1 = rcp(cosThetaO1); \ float lengthI1 = rcp(cosThetaI1); \ float length = lengthO1 + lengthI1; \ if (cosThetaI <= 0.f) \ length *= 0.5f; /* for transmission, use the average length */ \ substrate.value = lerp(dl->weight, \ substrate.value, \ substrate.value * pow(dl->transmittance, dl->thickness * length)); \ \ /* Energy conservation */ \ float T; \ if (scatteringType & ~BSDF_DIFFUSE) \ T = min(1.f - Fo, 1.f - Fi); /* for generic (non-diffuse) substrates \ [Kulla and Conty, 2017] */ \ else \ T = (1.f - Fo) * (1.f - Fi) \ * rcp(1.f - dl->Favg); /* for diffuse substrates [Kelemen and \ Szirmay-Kalos, 2001] */ \ substrate.value = substrate.value * T; \ substrate.pdf *= (1.f - Fo) #define DIELECTRICLAYER_EVAL_GET() substrate // Sample macros #define DIELECTRICLAYER_SAMPLE( \ dl_name, scatteringType, substrate_bsdf, substrate_fn) \ const varying DielectricLayer *uniform dl = \ (const varying DielectricLayer *uniform) & dl_name; \ BSDF_SampleRes res; \ \ float cosThetaO = dot(wo, getN(&dl->super)); \ if (cosThetaO <= 0.f) \ return make_BSDF_SampleRes_zero(); \ \ /* Fresnel term */ \ float cosThetaO1; /* positive */ \ float Fo = fresnelDielectricEx(cosThetaO, cosThetaO1, dl->eta) * dl->weight; \ \ if (ss < Fo) { \ /* Sample the coating */ \ res.type = BSDF_SPECULAR_REFLECTION; \ res.wi = reflect(wo, getN(&dl->super), cosThetaO); \ res.pdf = inf; \ res.weight = make_vec3f(1.f); \ } else { \ /* Sample the substrate */ \ /* Ignore refraction */ \ float ss1 = (ss - Fo) * rcp(1.f - Fo); /* reallocate sample */ \ res = substrate_fn(substrate_bsdf, wo, s, ss1); \ if (reduce_max(res.weight) <= 0.f) \ return res; \ float cosThetaI = dot(res.wi, getN(&dl->super)); \ \ float cosThetaI1; /* positive */ \ float Fi = \ fresnelDielectricEx(abs(cosThetaI), cosThetaI1, dl->eta) * dl->weight; \ \ /* Apply the coating medium absorption */ \ /* Use refracted angles for computing the absorption path length */ \ float lengthO1 = rcp(cosThetaO1); \ float lengthI1 = rcp(cosThetaI1); \ float length = lengthO1 + lengthI1; \ if (cosThetaI <= 0.f) \ length *= 0.5f; /* for transmission, use the average length */ \ res.weight = lerp(dl->weight, \ res.weight, \ res.weight * pow(dl->transmittance, dl->thickness * length)); \ \ /* Energy conservation */ \ float T; \ if (scatteringType & ~BSDF_DIFFUSE) \ T = min(1.f - Fo, 1.f - Fi); /* for generic (non-diffuse) substrates \ [Kulla and Conty, 2017] */ \ else \ T = (1.f - Fo) * (1.f - Fi) \ * rcp(1.f - dl->Favg); /* for diffuse substrates [Kelemen and \ Szirmay-Kalos, 2001] */ \ res.weight = res.weight * (T * rcp(1.f - Fo)); \ res.pdf *= (1.f - Fo); \ } #define DIELECTRICLAYER_SAMPLE_GET() res RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/Fresnel.ih000066400000000000000000000242171456566705700241140ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Optics.ih" #include "ShadingContext.ih" #include "math/sampling.ih" #include "math/spectrum.ih" #include "rkcommon/math/LinearSpace.ih" OSPRAY_BEGIN_ISPC_NAMESPACE //! \brief Computes fresnel coefficient for dielectric medium /*! \detailed Computes fresnel coefficient for media interface with * relative refraction index eta. Eta is the outside refraction index * divided by the inside refraction index. Both cosines have to be * positive. */ inline float fresnelDielectric(float cosI, float cosT, float eta) { const float Rper = (eta * cosI - cosT) * rcpf(eta * cosI + cosT); const float Rpar = (cosI - eta * cosT) * rcpf(cosI + eta * cosT); return 0.5f * (sqr(Rpar) + sqr(Rper)); } /*! Computes fresnel coefficient for media interface with relative * refraction index eta. Eta is the outside refraction index * divided by the inside refraction index. The cosine has to be * positive. */ inline float fresnelDielectric(float cosI, float eta) { const float sqrcost = sqrCosT(cosI, eta); if (sqrcost < 0.0f) return 1.0f; return fresnelDielectric(cosI, sqrt(sqrcost), eta); } inline float fresnelDielectricEx(float cosI, float &cosT, float eta) { const float sqrcost = sqrCosT(cosI, eta); if (sqrcost < 0.0f) { cosT = 0.0f; return 1.0f; } cosT = sqrt(sqrcost); return fresnelDielectric(cosI, cosT, eta); } // F_{\mathit{avg}} = 2 \int_0^1 F(\mu) \mu d\mu // \mu = \cos(\theta) // Fit from [Kulla and Conty, 2017, "Revisiting Physically Based Shading at // Imageworks"] inline float fresnelDielectricAvg(float eta) { if (eta < 1.f) eta = rcp(eta); return (eta - 1.f) / (4.08567f + 1.00071f * eta); } /*! Computes fresnel coefficient for conductor medium with complex * refraction index (eta,k). The cosine has to be positive. */ inline vec3f fresnelConductor(float cosI, vec3f eta, vec3f k) { const vec3f tmp = sqr(eta) + sqr(k); const vec3f Rpar = (tmp * sqr(cosI) - 2.0f * eta * cosI + make_vec3f(1.f)) * rcp(tmp * sqr(cosI) + 2.0f * eta * cosI + make_vec3f(1.f)); const vec3f Rper = (tmp - 2.0f * eta * cosI + make_vec3f(sqr(cosI))) * rcp(tmp + 2.0f * eta * cosI + make_vec3f(sqr(cosI))); return 0.5f * (Rpar + Rper); } inline float fresnelConductor(float cosI, uniform float eta, uniform float k) { const uniform float tmp = sqr(eta) + sqr(k); const float Rpar = (tmp * sqr(cosI) - eta * (2.0f * cosI) + 1.f) * rcp(tmp * sqr(cosI) + eta * (2.0f * cosI) + 1.f); const float Rper = (tmp - 2.0f * eta * cosI + sqr(cosI)) * rcp(tmp + 2.0f * eta * cosI + sqr(cosI)); return 0.5f * (Rpar + Rper); } inline vec3f fresnelConductor(float cosI, spectrum eta, spectrum k) { vec3f rgb = make_vec3f(0.f); for (uniform int l = 0; l < SPECTRUM_SAMPLES; l++) rgb = rgb + fresnelConductor(cosI, eta[l], k[l]) * spectrum_sRGB(l); return clamp(rgb); } // mainly for abstracting the conductor variants struct Fresnel; typedef vec3f (*Fresnel_EvalFunc)(const Fresnel *uniform self, float cosI); // TODO change into member variable vec3f and implement for *all* Fresnels! typedef vec3f (*Fresnel_EvalAvgFunc)(const Fresnel *uniform self); enum FresnelType { FRESNEL_TYPE_CONDUCTOR_RGB_UNIFORM = 0, // TODO: is rgb varying conductor used? FRESNEL_TYPE_CONDUCTOR_RGB_VARYING = 1, FRESNEL_TYPE_SCHLICK = 2, FRESNEL_TYPE_CONDUCTOR_SPECTRAL = 3, FRESNEL_TYPE_CONDUCTOR_ARTISTIC = 4, FRESNEL_TYPE_UNKNOWN = 5 }; struct Fresnel { uniform FresnelType type; }; inline vec3f Fresnel_evalAvg(const Fresnel *uniform) { return make_vec3f(0.f); } inline void Fresnel_Constructor(Fresnel *uniform self, uniform FresnelType type) { self->type = type; } struct FresnelConductorRGBUniform { uniform Fresnel super; uniform vec3f eta; uniform vec3f k; }; inline vec3f FresnelConductorRGBUniform_eval( const Fresnel *uniform super, float cosI) { const FresnelConductorRGBUniform *uniform self = (const FresnelConductorRGBUniform *uniform)super; return make_vec3f(fresnelConductor(cosI, self->eta.x, self->k.x), fresnelConductor(cosI, self->eta.y, self->k.y), fresnelConductor(cosI, self->eta.z, self->k.z)); } inline Fresnel *uniform FresnelConductorRGBUniform_create( ShadingContext *uniform ctx, const uniform vec3f &eta, const uniform vec3f &k) { FresnelConductorRGBUniform *uniform self = (FresnelConductorRGBUniform * uniform) ShadingContext_alloc(ctx, sizeof(FresnelConductorRGBUniform)); Fresnel_Constructor(&self->super, FRESNEL_TYPE_CONDUCTOR_RGB_UNIFORM); self->eta = eta; self->k = k; return &self->super; } struct FresnelConductorRGBVarying { uniform Fresnel super; varying vec3f eta; varying vec3f k; }; inline vec3f FresnelConductorRGBVarying_eval( const Fresnel *uniform super, float cosI) { const FresnelConductorRGBVarying *uniform self = (const FresnelConductorRGBVarying *uniform)super; return fresnelConductor(cosI, self->eta, self->k); } inline Fresnel *uniform FresnelConductorRGBVarying_create( ShadingContext *uniform ctx, const vec3f &eta, const vec3f &k) { FresnelConductorRGBVarying *uniform self = (FresnelConductorRGBVarying * uniform) ShadingContext_alloc(ctx, sizeof(FresnelConductorRGBVarying)); Fresnel_Constructor(&self->super, FRESNEL_TYPE_CONDUCTOR_RGB_VARYING); self->eta = eta; self->k = k; return &self->super; } struct FresnelSchlick { uniform Fresnel super; varying vec3f r; // reflectivity at normal incidence (0 deg) varying vec3f g; // reflectivity at grazing angle (90 deg) }; inline vec3f FresnelSchlick_eval(const Fresnel *uniform super, float cosI) { const FresnelSchlick *uniform self = (const FresnelSchlick *uniform)super; const float c = 1.f - cosI; return lerp(sqr(sqr(c)) * c, self->r, self->g); } // Exact solution from [Kulla and Conty, 2017, "Revisiting Physically Based // Shading at Imageworks"] inline vec3f FresnelSchlick_evalAvg(const Fresnel *uniform super) { const FresnelSchlick *uniform self = (const FresnelSchlick *uniform)super; const vec3f r = self->r; const vec3f g = self->g; const float p = 1.f / 5.f; const float p2 = p * p; return (2.f * g * p2 + r + 3.f * p * r) * rcp(1.f + 3.f * p + 2.f * p2); } inline Fresnel *uniform FresnelSchlick_create( ShadingContext *uniform ctx, const varying vec3f &r, const varying vec3f &g) { FresnelSchlick *uniform self = (FresnelSchlick * uniform) ShadingContext_alloc(ctx, sizeof(FresnelSchlick)); Fresnel_Constructor(&self->super, FRESNEL_TYPE_SCHLICK); self->r = r; self->g = g; return &self->super; } struct FresnelConductorSpectral { uniform Fresnel super; uniform spectrum eta; uniform spectrum k; }; inline vec3f FresnelConductorSpectral_eval( const Fresnel *uniform super, float cosI) { const FresnelConductorSpectral *uniform self = (const FresnelConductorSpectral *uniform)super; return fresnelConductor(cosI, self->eta, self->k); } inline Fresnel *uniform FresnelConductorSpectral_create( ShadingContext *uniform ctx, const spectrum &eta, const spectrum &k) { FresnelConductorSpectral *uniform self = (FresnelConductorSpectral * uniform) ShadingContext_alloc(ctx, sizeof(FresnelConductorSpectral)); Fresnel_Constructor(&self->super, FRESNEL_TYPE_CONDUCTOR_SPECTRAL); self->eta = eta; self->k = k; return &self->super; } // [Gulbrandsen, 2014, "Artist Friendly Metallic Fresnel"] struct FresnelConductorArtistic { uniform Fresnel super; varying vec3f eta; varying vec3f k; varying vec3f r; varying vec3f g; }; inline vec3f FresnelConductorArtistic_eval( const Fresnel *uniform super, float cosI) { const FresnelConductorArtistic *uniform self = (const FresnelConductorArtistic *uniform)super; return fresnelConductor(cosI, self->eta, self->k); } // Fit from [Kulla and Conty, 2017, "Revisiting Physically Based Shading at // Imageworks"] inline vec3f FresnelConductorArtistic_evalAvg(const Fresnel *uniform super) { const FresnelConductorArtistic *uniform self = (const FresnelConductorArtistic *uniform)super; const vec3f r = self->r; const vec3f r2 = r * r; const vec3f r3 = r2 * r; const vec3f g = self->g; const vec3f g2 = g * g; const vec3f g3 = g2 * g; return 0.087237f + 0.0230685f * g - 0.0864902f * g2 + 0.0774594f * g3 + 0.782654f * r - 0.136432f * r2 + 0.278708f * r3 + 0.19744f * g * r + 0.0360605f * g2 * r - 0.2586f * g * r2; } inline Fresnel *uniform FresnelConductorArtistic_create( ShadingContext *uniform ctx, const vec3f &reflectivity, const vec3f &edgeTint) { FresnelConductorArtistic *uniform self = (FresnelConductorArtistic * uniform) ShadingContext_alloc(ctx, sizeof(FresnelConductorArtistic)); Fresnel_Constructor(&self->super, FRESNEL_TYPE_CONDUCTOR_ARTISTIC); const vec3f r = min(reflectivity, make_vec3f(0.99f)); const vec3f g = edgeTint; const vec3f n_min = (1.f - r) / (1.f + r); const vec3f n_max = (1.f + sqrt(r)) / (1.f - sqrt(r)); const vec3f n = g * n_min + (1.f - g) * n_max; const vec3f k2 = (sqr(n + 1.f) * r - sqr(n - 1.f)) / (1.f - r); self->eta = n; self->k = sqrt_safe(k2); // prevent NaN if k2==-0.0f (happens if r==0.0f) self->r = r; self->g = g; return &self->super; } inline vec3f Fresnel_dispatch_eval(const Fresnel *uniform self, float cosI) { switch (self->type) { case FRESNEL_TYPE_CONDUCTOR_RGB_UNIFORM: return FresnelConductorRGBUniform_eval(self, cosI); case FRESNEL_TYPE_CONDUCTOR_RGB_VARYING: return FresnelConductorRGBVarying_eval(self, cosI); case FRESNEL_TYPE_SCHLICK: return FresnelSchlick_eval(self, cosI); case FRESNEL_TYPE_CONDUCTOR_SPECTRAL: return FresnelConductorSpectral_eval(self, cosI); case FRESNEL_TYPE_CONDUCTOR_ARTISTIC: return FresnelConductorArtistic_eval(self, cosI); default: break; } return make_vec3f(0.f); } inline vec3f Fresnel_dispatch_evalAvg(const Fresnel *uniform self) { switch (self->type) { case FRESNEL_TYPE_SCHLICK: return FresnelSchlick_evalAvg(self); case FRESNEL_TYPE_CONDUCTOR_ARTISTIC: return FresnelConductorArtistic_evalAvg(self); default: break; } // The default Fresnel_evalAvg just returns 0.f return Fresnel_evalAvg(self); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/GGXDistribution.ih000066400000000000000000000122631456566705700255410ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "MicrofacetDistribution.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // GGX (Trowbridge-Reitz) microfacet distribution // [Walter et al., 2007, "Microfacet Models for Refraction through Rough // Surfaces"] [Heitz, 2014, "Understanding the Masking-Shadowing Function in // Microfacet-Based BRDFs"] [Heitz and d'Eon, 2014, "Importance Sampling // Microfacet-Based BSDFs using the Distribution of Visible Normals"] [Heitz, // 2017, "A Simpler and Exact Sampling Routine for the GGX Distribution of // Visible Normals"] struct GGXDistribution { vec2f alpha; }; inline GGXDistribution make_GGXDistribution(const vec2f &alpha) { GGXDistribution self; self.alpha = alpha; return self; } // D(\omega_m) = \frac{1}{\pi \alpha_x \alpha_y \cos^4\theta_m \left(1 + // \tan^2\theta_m \left(\frac{\cos^2\phi_m}{\alpha_x^2} + // \frac{\sin^2\phi_m}{\alpha_y^2}\right)\right)^2} inline float eval(const GGXDistribution &self, const vec3f &wh) { float cosTheta = wh.z; float cosTheta2 = sqr(cosTheta); float e = (sqr(wh.x / self.alpha.x) + sqr(wh.y / self.alpha.y)) / cosTheta2; return rcp( (float)pi * self.alpha.x * self.alpha.y * sqr(cosTheta2 * (1.f + e))); } // p(\omega_m) = D(\omega_m) \cos\theta_m inline float eval(const GGXDistribution &self, const vec3f &wh, float &pdf) { float cosTheta = wh.z; float D = eval(self, wh); pdf = D * abs(cosTheta); return D; } // \theta_m = \arctan \left( \frac{\alpha\sqrt{\xi_1}}{\sqrt{1-\xi_1}} \right) // \phi_m = 2\pi \xi_2 // p(\omega_m) = D(\omega_m) \cos\theta_m inline vec3f sample(const GGXDistribution &self, float &pdf, const vec2f &s) { float phi; if (self.alpha.x == self.alpha.y) { phi = 2.f * (float)pi * s.y; } else { phi = atan(self.alpha.y / self.alpha.x * tan((float)pi * (2.f * s.y + 0.5f))); if (s.y > 0.5f) phi += (float)pi; } float sinPhi, cosPhi; sincos(phi, &sinPhi, &cosPhi); float alpha2; if (self.alpha.x == self.alpha.y) alpha2 = sqr(self.alpha.x); else alpha2 = rcp(sqr(cosPhi / self.alpha.x) + sqr(sinPhi / self.alpha.y)); float tanTheta2 = alpha2 * s.x / (1.f - s.x); float cosTheta = rsqrt(1.f + tanTheta2); float cosTheta3 = sqr(cosTheta) * cosTheta; float sinTheta = cos2sin(cosTheta); float e = tanTheta2 / alpha2; pdf = rcp((float)pi * self.alpha.x * self.alpha.y * cosTheta3 * sqr(1.f + e)); float x = cosPhi * sinTheta; float y = sinPhi * sinTheta; float z = cosTheta; return make_vec3f(x, y, z); } // Smith Lambda function [Heitz, 2014] // \Lambda(\omega_o) = \frac{-1 + \sqrt{1+\frac{1}{a^2}}}{2} // a = \frac{1}{\alpha_o \tan\theta_o} // \alpha_o = \sqrt{cos^2\phi_o \alpha_x^2 + sin^2\phi_o \alpha_y^2} inline float evalLambda(const GGXDistribution &self, const vec3f &wo) { float cosThetaO = wo.z; float cosThetaO2 = sqr(cosThetaO); float invA2 = (sqr(wo.x * self.alpha.x) + sqr(wo.y * self.alpha.y)) / cosThetaO2; return 0.5f * (-1.f + sqrt(1.f + invA2)); } inline float evalG1( const GGXDistribution &self, const vec3f &wo, float cosThetaOH) { float cosThetaO = wo.z; if (cosThetaO * cosThetaOH <= 0.f) return 0.f; return rcp(1.f + evalLambda(self, wo)); } // Smith's height-correlated masking-shadowing function // [Heitz, 2014, "Understanding the Masking-Shadowing Function in // Microfacet-Based BRDFs"] inline float evalG2(const GGXDistribution &self, const vec3f &wo, const vec3f &wi, float cosThetaOH, float cosThetaIH) { float cosThetaO = wo.z; float cosThetaI = wi.z; if (cosThetaO * cosThetaOH <= 0.f || cosThetaI * cosThetaIH <= 0.f) return 0.f; return rcp(1.f + evalLambda(self, wo) + evalLambda(self, wi)); } inline float evalVisible(const GGXDistribution &self, const vec3f &wh, const vec3f &wo, float cosThetaOH, float &pdf) { float cosThetaO = wo.z; float D = eval(self, wh); pdf = evalG1(self, wo, cosThetaOH) * abs(cosThetaOH) * D / abs(cosThetaO); return D; } // Fast visible normal sampling (wo must be in the upper hemisphere) // [Heitz, 2017, "A Simpler and Exact Sampling Routine for the GGX Distribution // of Visible Normals"] inline vec3f sampleVisible( const GGXDistribution &self, const vec3f &wo, float &pdf, const vec2f &s) { // Stretch wo vec3f V = normalize(make_vec3f(self.alpha.x * wo.x, self.alpha.y * wo.y, wo.z)); // Orthonormal basis vec3f T1 = (V.z < 0.9999f) ? normalize(cross(V, make_vec3f(0, 0, 1))) : make_vec3f(1, 0, 0); vec3f T2 = cross(T1, V); // Sample point with polar coordinates (r, phi) float a = 1.f / (1.f + V.z); float r = sqrt(s.x); float phi = (s.y < a) ? s.y / a * (float)pi : (float)pi + (s.y - a) / (1.f - a) * (float)pi; float P1 = r * cos(phi); float P2 = r * sin(phi) * ((s.y < a) ? 1.f : V.z); // Compute normal vec3f wh = P1 * T1 + P2 * T2 + sqrt(max(0.f, 1.f - P1 * P1 - P2 * P2)) * V; // Unstretch wh = normalize( make_vec3f(self.alpha.x * wh.x, self.alpha.y * wh.y, max(0.f, wh.z))); // Compute pdf float cosThetaO = wo.z; pdf = evalG1(self, wo, dot(wo, wh)) * abs(dot(wo, wh)) * eval(self, wh) / abs(cosThetaO); return wh; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/Lambert.ih000066400000000000000000000020631456566705700240770ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "BSDF.ih" #include "math/sampling.ih" OSPRAY_BEGIN_ISPC_NAMESPACE inline BSDF_EvalRes Lambert_eval( const varying BSDF *uniform self, const vec3f &, const vec3f &wi) { BSDF_EvalRes res; float cosThetaI = max(dot(wi, getN(self)), 0.f); res.pdf = cosineSampleHemispherePDF(cosThetaI); res.value = self->albedo * (float)one_over_pi * cosThetaI; return res; } inline BSDF_SampleRes Lambert_sample( const varying BSDF *uniform self, const vec3f &, const vec2f &s, float) { const vec3f localDir = cosineSampleHemisphere(s); BSDF_SampleRes res; res.wi = getFrame(self) * localDir; res.pdf = cosineSampleHemispherePDF(localDir); res.type = BSDF_DIFFUSE_REFLECTION; res.weight = self->albedo; return res; } inline void Lambert_Constructor(varying BSDF *uniform self, const varying linear3f *uniform frame, const varying vec3f &R) { BSDF_Constructor(self, R, BSDF_DIFFUSE_REFLECTION, BSDF_TYPE_LAMBERT, frame); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/LambertTransmission.ih000066400000000000000000000027011456566705700265100ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "BSDF.ih" OSPRAY_BEGIN_ISPC_NAMESPACE inline BSDF_EvalRes LambertTransmission_eval( const varying BSDF *uniform self, const vec3f &, const vec3f &wi) { BSDF_EvalRes res; float cosThetaI = max(-dot(wi, getN(self)), 0.f); res.pdf = cosineSampleHemispherePDF(cosThetaI); res.value = self->albedo * (float)one_over_pi * cosThetaI; return res; } inline BSDF_SampleRes LambertTransmission_sample( const varying BSDF *uniform self, const vec3f &, const vec2f &s, float) { const vec3f localDir = cosineSampleHemisphere(s); BSDF_SampleRes res; res.wi = neg(getFrame(self) * localDir); res.pdf = cosineSampleHemispherePDF(localDir); res.type = BSDF_DIFFUSE_TRANSMISSION; res.weight = self->albedo; return res; } inline void LambertTransmission_Constructor(varying BSDF *uniform self, const varying linear3f *uniform frame, const varying vec3f &R) { BSDF_Constructor(self, R, BSDF_DIFFUSE_TRANSMISSION, BSDF_TYPE_LAMBERT_TRANSMISSION, frame); } inline varying BSDF *uniform LambertTransmission_create( uniform ShadingContext *uniform ctx, const varying linear3f *uniform frame, const varying vec3f &R) { varying BSDF *uniform self = (varying BSDF * uniform) ShadingContext_alloc(ctx, sizeof(BSDF)); LambertTransmission_Constructor(self, frame, R); return self; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/MicrofacetAlbedo.ih000066400000000000000000000136251456566705700257020ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Fresnel.ih" #include "GGXDistribution.ih" #include "SheenDistribution.ih" OSPRAY_BEGIN_ISPC_NAMESPACE inline float MicrofacetAlbedo_sample( float cosThetaO, const GGXDistribution µfacet, const vec2f &s) { // Handle edge cases cosThetaO = max(cosThetaO, 1e-6f); // Make an outgoing vector vec3f wo = make_vec3f(cos2sin(cosThetaO), 0.f, cosThetaO); // Sample the microfacet normal float whPdf; vec3f wh = sampleVisible(microfacet, wo, whPdf, s); float cosThetaOH = dot(wo, wh); // Sample the reflection vec3f wi = reflect(wo, wh, cosThetaOH); float cosThetaI = wi.z; if (cosThetaI <= 0.f) return 0.f; float cosThetaIH = dot(wi, wh); float G = evalG2(microfacet, wo, wi, cosThetaOH, cosThetaIH); return G * rcp_safe(evalG1(microfacet, wo, cosThetaOH)); } inline float MicrofacetDielectricAlbedo_sample(float cosThetaO, float eta, const GGXDistribution µfacet, const vec2f &s) { // Handle edge cases cosThetaO = max(cosThetaO, 1e-6f); // Make an outgoing vector vec3f wo = make_vec3f(cos2sin(cosThetaO), 0.f, cosThetaO); // Sample the microfacet normal float whPdf; vec3f wh = sampleVisible(microfacet, wo, whPdf, s); float cosThetaOH = dot(wo, wh); // Fresnel term float cosThetaTH; // positive float F = fresnelDielectricEx(cosThetaOH, cosThetaTH, eta); float weight = 0.f; // Sample the reflection vec3f wi = reflect(wo, wh, cosThetaOH); float cosThetaI = wi.z; if (cosThetaI > 0.f) { float cosThetaIH = dot(wi, wh); float G = evalG2(microfacet, wo, wi, cosThetaOH, cosThetaIH); weight += F * (G * rcp_safe(evalG1(microfacet, wo, cosThetaOH))); } // Sample the transmission // cosThetaTH = -cosThetaIH wi = refract(wo, wh, cosThetaOH, cosThetaTH, eta); cosThetaI = wi.z; if (cosThetaI < 0.f) { float cosThetaIH = dot(wi, wh); float G = evalG2(microfacet, wo, wi, cosThetaOH, cosThetaIH); weight += (1.f - F) * (G * rcp_safe(evalG1(microfacet, wo, cosThetaOH))); } return weight; } inline float MicrofacetDielectricReflectionAlbedo_sample(float cosThetaO, float eta, const GGXDistribution µfacet, const vec2f &s) { // Handle edge cases cosThetaO = max(cosThetaO, 1e-6f); // Make an outgoing vector vec3f wo = make_vec3f(cos2sin(cosThetaO), 0.f, cosThetaO); // Sample the microfacet normal float whPdf; vec3f wh = sampleVisible(microfacet, wo, whPdf, s); float cosThetaOH = dot(wo, wh); // Fresnel term float F = fresnelDielectric(cosThetaOH, eta); // Sample the reflection vec3f wi = reflect(wo, wh, cosThetaOH); float cosThetaI = wi.z; if (cosThetaI <= 0.f) return 0.f; float cosThetaIH = dot(wi, wh); float G = evalG2(microfacet, wo, wi, cosThetaOH, cosThetaIH); return F * (G * rcp_safe(evalG1(microfacet, wo, cosThetaOH))); } inline float MicrofacetSheenAlbedo_sample( float cosThetaO, const SheenDistribution µfacet, const vec2f &s) { // Handle edge cases cosThetaO = max(cosThetaO, 1e-6f); // Make an outgoing vector vec3f wo = make_vec3f(cos2sin(cosThetaO), 0.f, cosThetaO); // Sample the reflection vec3f wi = uniformSampleHemisphere(s); float cosThetaI = wi.z; // Compute the microfacet normal vec3f wh = normalize(wo + wi); float cosThetaH = wh.z; float cosThetaOH = dot(wo, wh); float cosThetaIH = dot(wi, wh); // Evaluate the reflection float D = eval(microfacet, cosThetaH); float G = evalG2(microfacet, cosThetaO, cosThetaI, cosThetaOH, cosThetaIH); float pdf = uniformSampleHemispherePDF(); return D * G * rcp(4.f * cosThetaO * pdf); } inline float MicrofacetAlbedo_integrate( float cosThetaO, float roughness, uniform int numSamples = 1024) { GGXDistribution microfacet = make_GGXDistribution(roughnessToAlpha(roughness, 0.f)); uniform int n = sqrt((uniform float)numSamples); float sum = 0.f; for (uniform int i = 0; i < n; i++) { for (uniform int j = 0; j < n; j++) { vec2f s = min((make_vec2f(i, j) + 0.5f) / n, make_vec2f(1.f - 1e-6f)); sum += MicrofacetAlbedo_sample(cosThetaO, microfacet, s); } } return min(sum / (n * n), 1.f); } inline float MicrofacetDielectricAlbedo_integrate( float cosThetaO, float eta, float roughness, uniform int numSamples = 1024) { GGXDistribution microfacet = make_GGXDistribution(roughnessToAlpha(roughness, 0.f)); uniform int n = sqrt((uniform float)numSamples); float sum = 0.f; for (uniform int i = 0; i < n; i++) { for (uniform int j = 0; j < n; j++) { vec2f s = min((make_vec2f(i, j) + 0.5f) / n, make_vec2f(1.f - 1e-6f)); sum += MicrofacetDielectricAlbedo_sample(cosThetaO, eta, microfacet, s); } } return min(sum / (n * n), 1.f); } inline float MicrofacetDielectricReflectionAlbedo_integrate( float cosThetaO, float eta, float roughness, uniform int numSamples = 1024) { GGXDistribution microfacet = make_GGXDistribution(roughnessToAlpha(roughness, 0.f)); uniform int n = sqrt((uniform float)numSamples); float sum = 0.f; for (uniform int i = 0; i < n; i++) { for (uniform int j = 0; j < n; j++) { vec2f s = min((make_vec2f(i, j) + 0.5f) / n, make_vec2f(1.f - 1e-6f)); sum += MicrofacetDielectricReflectionAlbedo_sample( cosThetaO, eta, microfacet, s); } } return min(sum / (n * n), 1.f); } inline float MicrofacetSheenAlbedo_integrate( float cosThetaO, float roughness, uniform int numSamples = 1024) { SheenDistribution microfacet = make_SheenDistribution(roughnessToAlpha(roughness)); uniform int n = sqrt((uniform float)numSamples); float sum = 0.f; for (uniform int i = 0; i < n; i++) { for (uniform int j = 0; j < n; j++) { vec2f s = min((make_vec2f(i, j) + 0.5f) / n, make_vec2f(1.f - 1e-6f)); sum += MicrofacetSheenAlbedo_sample(cosThetaO, microfacet, s); } } return min(sum / (n * n), 1.f); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/MicrofacetAlbedoTables.cpp000066400000000000000000000060701456566705700272130ustar00rootroot00000000000000#include "MicrofacetAlbedoTables.h" #include "common/ISPCRTBuffers.h" #include "render/bsdfs/MicrofacetAlbedoTablesShared.h" #ifndef OSPRAY_TARGET_SYCL #include "render/bsdfs/MicrofacetAlbedoTables_ispc.h" #else namespace ispc { void precomputeMicrofacetAlbedoTables(void *_tables); } #endif namespace ospray { MicrofacetAlbedoTables::MicrofacetAlbedoTables(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext()) { albedo_dir = make_buffer_shared_unique(device.getIspcrtContext(), MICROFACET_ALBEDO_TABLE_SIZE * MICROFACET_ALBEDO_TABLE_SIZE); albedo_avg = make_buffer_shared_unique( device.getIspcrtContext(), MICROFACET_ALBEDO_TABLE_SIZE); dielectricAlbedo_dir = make_buffer_shared_unique(device.getIspcrtContext(), MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE * MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE * MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE); dielectricAlbedo_avg = make_buffer_shared_unique(device.getIspcrtContext(), MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE * MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE); dielectricRcpEtaAlbedo_dir = make_buffer_shared_unique(device.getIspcrtContext(), MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE * MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE * MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE); dielectricRcpEtaAlbedo_avg = make_buffer_shared_unique(device.getIspcrtContext(), MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE * MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE); dielectricReflectionAlbedo_dir = make_buffer_shared_unique(device.getIspcrtContext(), MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE * MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE * MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE); dielectricReflectionAlbedo_avg = make_buffer_shared_unique(device.getIspcrtContext(), MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE * MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE); sheenAlbedo_dir = make_buffer_shared_unique(device.getIspcrtContext(), MICROFACET_SHEEN_ALBEDO_TABLE_SIZE * MICROFACET_SHEEN_ALBEDO_TABLE_SIZE); getSh()->albedo_dir = albedo_dir->data(); getSh()->albedo_avg = albedo_avg->data(); getSh()->dielectricAlbedo_dir = dielectricAlbedo_dir->data(); getSh()->dielectricAlbedo_avg = dielectricAlbedo_avg->data(); getSh()->dielectricRcpEtaAlbedo_dir = dielectricRcpEtaAlbedo_dir->data(); getSh()->dielectricRcpEtaAlbedo_avg = dielectricRcpEtaAlbedo_avg->data(); getSh()->dielectricReflectionAlbedo_dir = dielectricReflectionAlbedo_dir->data(); getSh()->dielectricReflectionAlbedo_avg = dielectricReflectionAlbedo_avg->data(); getSh()->sheenAlbedo_dir = sheenAlbedo_dir->data(); // TODO: Could be a kernel dispatch for SYCL, right now it's run serially on // the host ispc::precomputeMicrofacetAlbedoTables(getSh()); } std::string MicrofacetAlbedoTables::toString() const { return "ospray::MicrofacetAlbedoTables"; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/MicrofacetAlbedoTables.h000066400000000000000000000040331456566705700266550ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include "ISPCDevice.h" #include "common/Managed.h" #include "common/StructShared.h" // ispc shared #include "MicrofacetAlbedoTablesShared.h" namespace ospray { /* Directional and average albedo tables for microfacet BSDFs * [Kulla and Conty, 2017, "Revisiting Physically Based Shading at * Imageworks"] * * These are stored in USM to reduce the kernel size and avoid issues about * global statics/initialization in SYCL where these are populated by a kernel, * not compile-time defined values */ struct OSPRAY_SDK_INTERFACE MicrofacetAlbedoTables : public AddStructShared { MicrofacetAlbedoTables(api::ISPCDevice &device); virtual std::string toString() const override; private: // Microfacet GGX albedo tables // directional 2D table (cosThetaO, roughness) std::unique_ptr> albedo_dir; // average 1D table (roughness) std::unique_ptr> albedo_avg; // Microfacet GGX dielectric albedo table. eta in [1/3, 1] // directional 3D table (cosThetaO, eta, roughness) std::unique_ptr> dielectricAlbedo_dir; // average 2D table (eta, roughness) std::unique_ptr> dielectricAlbedo_avg; // eta in [1, 3] // directional 3D table (cosThetaO, eta, roughness) std::unique_ptr> dielectricRcpEtaAlbedo_dir; // average 2D table (eta, roughness) std::unique_ptr> dielectricRcpEtaAlbedo_avg; // Microfacet GGX dielectric reflection-only albedo table. eta in [1/3, 1] // directional 3D table (cosThetaO, eta, roughness) std::unique_ptr> dielectricReflectionAlbedo_dir; // average 2D table (eta, roughness) std::unique_ptr> dielectricReflectionAlbedo_avg; // Microfacet sheen albedo table // directional 2D table (cosThetaO, roughness) std::unique_ptr> sheenAlbedo_dir; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/MicrofacetAlbedoTables.ih000066400000000000000000000125701456566705700270330ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "MicrofacetAlbedoTablesShared.h" #include "math/interpolation.ih" OSPRAY_BEGIN_ISPC_NAMESPACE inline float MicrofacetAlbedoTable_eval( const MicrofacetAlbedoTables *uniform albedoTable, float cosThetaO, float roughness) { const uniform int size = MICROFACET_ALBEDO_TABLE_SIZE; const vec2f p = make_vec2f(cosThetaO, roughness) * (size - 1); return interp2DLinear(p, albedoTable->albedo_dir, make_vec2i(size)); } inline float MicrofacetAlbedoTable_evalAvg( const MicrofacetAlbedoTables *uniform albedoTable, float roughness) { const uniform int size = MICROFACET_ALBEDO_TABLE_SIZE; const float x = roughness * (size - 1); return interp1DLinear(x, albedoTable->albedo_avg, size); } inline float MicrofacetDielectricAlbedoTable_eval( const MicrofacetAlbedoTables *uniform albedoTable, float cosThetaO, float eta, float roughness) { const uniform int size = MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE; if (eta <= 1.f) { const uniform float minEta = rcp(MICROFACET_DIELECTRIC_ALBEDO_TABLE_MAX_IOR); const uniform float maxEta = rcp(MICROFACET_DIELECTRIC_ALBEDO_TABLE_MIN_IOR); const float etaParam = (eta - minEta) / (maxEta - minEta); const vec3f p = make_vec3f(cosThetaO, etaParam, roughness) * (size - 1); return interp3DLinear( p, albedoTable->dielectricAlbedo_dir, make_vec3i(size)); } else { const uniform float minEta = MICROFACET_DIELECTRIC_ALBEDO_TABLE_MIN_IOR; const uniform float maxEta = MICROFACET_DIELECTRIC_ALBEDO_TABLE_MAX_IOR; const float etaParam = (eta - minEta) / (maxEta - minEta); const vec3f p = make_vec3f(cosThetaO, etaParam, roughness) * (size - 1); return interp3DLinear( p, albedoTable->dielectricRcpEtaAlbedo_dir, make_vec3i(size)); } } inline float MicrofacetDielectricAlbedoTable_evalAvg( const MicrofacetAlbedoTables *uniform albedoTable, float eta, float roughness) { const uniform int size = MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE; if (eta <= 1.f) { const uniform float minEta = rcp(MICROFACET_DIELECTRIC_ALBEDO_TABLE_MAX_IOR); const uniform float maxEta = rcp(MICROFACET_DIELECTRIC_ALBEDO_TABLE_MIN_IOR); const float etaParam = (eta - minEta) / (maxEta - minEta); const vec2f p = make_vec2f(etaParam, roughness) * (size - 1); return interp2DLinear( p, albedoTable->dielectricAlbedo_avg, make_vec2i(size)); } else { const uniform float minEta = MICROFACET_DIELECTRIC_ALBEDO_TABLE_MIN_IOR; const uniform float maxEta = MICROFACET_DIELECTRIC_ALBEDO_TABLE_MAX_IOR; const float etaParam = (eta - minEta) / (maxEta - minEta); const vec2f p = make_vec2f(etaParam, roughness) * (size - 1); return interp2DLinear( p, albedoTable->dielectricRcpEtaAlbedo_avg, make_vec2i(size)); } } inline float MicrofacetDielectricReflectionAlbedoTable_eval( const MicrofacetAlbedoTables *uniform albedoTable, float cosThetaO, float eta, float roughness) { const uniform int size = MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE; // if (eta <= 1.f) { const uniform float minEta = rcp(MICROFACET_DIELECTRIC_ALBEDO_TABLE_MAX_IOR); const uniform float maxEta = rcp(MICROFACET_DIELECTRIC_ALBEDO_TABLE_MIN_IOR); const float etaParam = (eta - minEta) / (maxEta - minEta); const vec3f p = make_vec3f(cosThetaO, etaParam, roughness) * (size - 1); return interp3DLinear( p, albedoTable->dielectricReflectionAlbedo_dir, make_vec3i(size)); } /* else { const uniform float minEta = MICROFACET_DIELECTRIC_ALBEDO_TABLE_MIN_IOR; const uniform float maxEta = MICROFACET_DIELECTRIC_ALBEDO_TABLE_MAX_IOR; const float etaParam = (eta - minEta) / (maxEta - minEta); const vec3f p = make_vec3f(cosThetaO, etaParam, roughness) * (size-1); return interp3DLinear(p, MicrofacetDielectricReflectionRcpEtaAlbedoTable_dir, make_vec3i(size)); } */ } inline float MicrofacetDielectricReflectionAlbedoTable_evalAvg( const MicrofacetAlbedoTables *uniform albedoTable, float eta, float roughness) { const uniform int size = MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE; // if (eta <= 1.f) { const uniform float minEta = rcp(MICROFACET_DIELECTRIC_ALBEDO_TABLE_MAX_IOR); const uniform float maxEta = rcp(MICROFACET_DIELECTRIC_ALBEDO_TABLE_MIN_IOR); const float etaParam = (eta - minEta) / (maxEta - minEta); const vec2f p = make_vec2f(etaParam, roughness) * (size - 1); return interp2DLinear( p, albedoTable->dielectricReflectionAlbedo_avg, make_vec2i(size)); } /* else { const uniform float minEta = MICROFACET_DIELECTRIC_ALBEDO_TABLE_MIN_IOR; const uniform float maxEta = MICROFACET_DIELECTRIC_ALBEDO_TABLE_MAX_IOR; const float etaParam = (eta - minEta) / (maxEta - minEta); const vec2f p = make_vec2f(etaParam, roughness) * (size-1); return interp2DLinear(p, MicrofacetDielectricReflectionRcpEtaAlbedoTable_avg, make_vec2i(size)); } */ } inline float MicrofacetSheenAlbedoTable_eval( const MicrofacetAlbedoTables *uniform albedoTable, float cosThetaO, float roughness) { const uniform int size = MICROFACET_SHEEN_ALBEDO_TABLE_SIZE; const vec2f p = make_vec2f(cosThetaO, roughness) * (size - 1); return interp2DLinear(p, albedoTable->sheenAlbedo_dir, make_vec2i(size)); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/MicrofacetAlbedoTables.ispc000066400000000000000000000120551456566705700273670ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "MicrofacetAlbedo.ih" #include "MicrofacetAlbedoTables.ih" #include "MicrofacetAlbedoTablesShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE static inline uniform float MicrofacetAlbedoTable_integrateAvg( const uniform float *uniform f, uniform int size, uniform int numSamples = 1024) { // Trapezoidal rule const uniform int n = numSamples + 1; float sum = 0.f; #ifdef OSPRAY_TARGET_SYCL for (int i = 0; i < n; ++i) { #else foreach (i = 0 ... n) { #endif const float cosThetaO = (float)i / (n - 1); const float x = cosThetaO * (size - 1); sum += interp1DLinear(x, f, size) * cosThetaO * ((i == 0 || i == n - 1) ? 0.5f : 1.f); } uniform float totalSum = reduce_add(sum); return min(2.f * (totalSum / (n - 1)), 1.f); } static void MicrofacetAlbedoTable_precompute( MicrofacetAlbedoTables *uniform tables) { const uniform int size = MICROFACET_ALBEDO_TABLE_SIZE; uniform float *uniform dirPtr = tables->albedo_dir; uniform float *uniform avgPtr = tables->albedo_avg; for (uniform int j = 0; j < size; j++) { const float roughness = (float)j / (size - 1); // compute the direction albedo for each cosThetaO #ifdef OSPRAY_TARGET_SYCL for (int i = 0; i < size; ++i) { #else foreach (i = 0 ... size) { #endif const float cosThetaO = (float)i / (size - 1); dirPtr[i] = MicrofacetAlbedo_integrate(cosThetaO, roughness); } // compute the average albedo *avgPtr = MicrofacetAlbedoTable_integrateAvg(dirPtr, size); dirPtr += size; avgPtr++; } } typedef float (*MicrofacetDielectricAlbedo_IntegrateFunc)( float cosThetaO, float eta, float roughness, uniform int numSamples); static void MicrofacetDielectricAlbedoTable_precompute( MicrofacetDielectricAlbedo_IntegrateFunc func, uniform int size, uniform float minEta, uniform float maxEta, uniform float *uniform dirValues, uniform float *uniform avgValues) { const uniform int numSamples = 1024; uniform float *uniform dirPtr = dirValues; uniform float *uniform avgPtr = avgValues; for (uniform int k = 0; k < size; k++) { const float roughness = (float)k / (size - 1); for (uniform int j = 0; j < size; j++) { const float eta = lerp((float)j / (size - 1), minEta, maxEta); // compute the direction albedo for each cosThetaO #ifdef OSPRAY_TARGET_SYCL for (int i = 0; i < size; ++i) { #else foreach (i = 0 ... size) { #endif const float cosThetaO = (float)i / (size - 1); dirPtr[i] = func(cosThetaO, eta, roughness, numSamples); } // compute the average albedo *avgPtr = MicrofacetAlbedoTable_integrateAvg(dirPtr, size); dirPtr += size; avgPtr++; } } } static void MicrofacetDielectricAlbedoTable_precompute( MicrofacetAlbedoTables *uniform tables) { const uniform int size = MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE; const uniform float minEta = rcp(MICROFACET_DIELECTRIC_ALBEDO_TABLE_MAX_IOR); const uniform float maxEta = rcp(MICROFACET_DIELECTRIC_ALBEDO_TABLE_MIN_IOR); MicrofacetDielectricAlbedoTable_precompute( &MicrofacetDielectricAlbedo_integrate, size, minEta, maxEta, tables->dielectricAlbedo_dir, tables->dielectricAlbedo_avg); MicrofacetDielectricAlbedoTable_precompute( &MicrofacetDielectricReflectionAlbedo_integrate, size, minEta, maxEta, tables->dielectricReflectionAlbedo_dir, tables->dielectricReflectionAlbedo_avg); } static void MicrofacetDielectricRcpEtaAlbedoTable_precompute( MicrofacetAlbedoTables *uniform tables) { const uniform int size = MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE; const uniform float minEta = MICROFACET_DIELECTRIC_ALBEDO_TABLE_MIN_IOR; const uniform float maxEta = MICROFACET_DIELECTRIC_ALBEDO_TABLE_MAX_IOR; MicrofacetDielectricAlbedoTable_precompute( &MicrofacetDielectricAlbedo_integrate, size, minEta, maxEta, tables->dielectricRcpEtaAlbedo_dir, tables->dielectricRcpEtaAlbedo_avg); } static void MicrofacetSheenAlbedoTable_precompute( MicrofacetAlbedoTables *uniform tables) { const uniform int size = MICROFACET_SHEEN_ALBEDO_TABLE_SIZE; uniform float *uniform dirPtr = tables->sheenAlbedo_dir; for (uniform int j = 0; j < size; j++) { const float roughness = (float)j / (size - 1); // compute the direction albedo for each cosThetaO #ifdef OSPRAY_TARGET_SYCL for (int i = 0; i < size; ++i) { #else foreach (i = 0 ... size) { #endif const float cosThetaO = (float)i / (size - 1); dirPtr[i] = MicrofacetSheenAlbedo_integrate(cosThetaO, roughness); } dirPtr += size; } } export void precomputeMicrofacetAlbedoTables(void *uniform _tables) { MicrofacetAlbedoTables *uniform tables = (MicrofacetAlbedoTables * uniform) _tables; MicrofacetAlbedoTable_precompute(tables); MicrofacetDielectricAlbedoTable_precompute(tables); MicrofacetDielectricRcpEtaAlbedoTable_precompute(tables); MicrofacetSheenAlbedoTable_precompute(tables); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/MicrofacetAlbedoTablesShared.h000066400000000000000000000034411456566705700300060ustar00rootroot00000000000000// Copyright 2009-2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #define MICROFACET_ALBEDO_TABLE_SIZE 32 #define MICROFACET_DIELECTRIC_ALBEDO_TABLE_SIZE 16 #define MICROFACET_DIELECTRIC_ALBEDO_TABLE_MIN_IOR 1.f #define MICROFACET_DIELECTRIC_ALBEDO_TABLE_MAX_IOR 3.f #define MICROFACET_SHEEN_ALBEDO_TABLE_SIZE 16 #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct MicrofacetAlbedoTables { // Microfacet GGX albedo tables // directional 2D table (cosThetaO, roughness) float *albedo_dir; // average 1D table (roughness) float *albedo_avg; // Microfacet GGX dielectric albedo table. eta in [1/3, 1] // directional 3D table (cosThetaO, eta, roughness) float *dielectricAlbedo_dir; // average 2D table (eta, roughness) float *dielectricAlbedo_avg; // eta in [1, 3] // directional 3D table (cosThetaO, eta, roughness) float *dielectricRcpEtaAlbedo_dir; // average 2D table (eta, roughness) float *dielectricRcpEtaAlbedo_avg; // Microfacet GGX dielectric reflection-only albedo table. eta in [1/3, 1] // directional 3D table (cosThetaO, eta, roughness) float *dielectricReflectionAlbedo_dir; // average 2D table (eta, roughness) float *dielectricReflectionAlbedo_avg; // Microfacet sheen albedo table // directional 2D table (cosThetaO, roughness) float *sheenAlbedo_dir; #ifdef __cplusplus MicrofacetAlbedoTables() : albedo_dir(nullptr), albedo_avg(nullptr), dielectricAlbedo_dir(nullptr), dielectricAlbedo_avg(nullptr), dielectricRcpEtaAlbedo_dir(nullptr), dielectricRcpEtaAlbedo_avg(nullptr), dielectricReflectionAlbedo_dir(nullptr), dielectricReflectionAlbedo_avg(nullptr), sheenAlbedo_dir(nullptr) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/MicrofacetConductor.ih000066400000000000000000000120121456566705700264410ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "BSDF.ih" #include "Fresnel.ih" #include "GGXDistribution.ih" #include "MicrofacetAlbedoTables.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // Microfacet conductor BRDF with the Smith microsurface model and approximate // multiple scattering. [Kulla and Conty, 2017, "Revisiting Physically Based // Shading at Imageworks"] [Jakob et al., 2014, "A Comprehensive Framework for // Rendering Layered Materials", Extended Technical Report] struct MicrofacetConductor { BSDF super; Fresnel *uniform fresnel; GGXDistribution microfacet; float roughness; const MicrofacetAlbedoTables *uniform microfacetAlbedoTables; // Energy compensation [Kulla and Conty, 2017] float Eavg; vec3f fmsScale; }; inline BSDF_EvalRes MicrofacetConductor_eval( const varying MicrofacetConductor *uniform self, const vec3f &wo, const vec3f &wi) { BSDF_EvalRes res; float cosThetaO = dot(wo, getN(&self->super)); float cosThetaI = dot(wi, getN(&self->super)); if (cosThetaO <= 0.f || cosThetaI <= 0.f) return make_BSDF_EvalRes_zero(); // Compute the microfacet normal vec3f wh = normalize(wi + wo); float cosThetaOH = dot(wo, wh); float cosThetaIH = dot(wi, wh); linear3f toLocal = transposed(getFrame(&self->super)); vec3f wo0 = toLocal * wo; vec3f wi0 = toLocal * wi; vec3f wh0 = toLocal * wh; vec3f F = Fresnel_dispatch_eval(self->fresnel, cosThetaOH); float whPdf; float D = evalVisible(self->microfacet, wh0, wo0, cosThetaOH, whPdf); float G = evalG2(self->microfacet, wo0, wi0, cosThetaOH, cosThetaIH); // Energy compensation float Eo = MicrofacetAlbedoTable_eval( self->microfacetAlbedoTables, cosThetaO, self->roughness); float Ei = MicrofacetAlbedoTable_eval( self->microfacetAlbedoTables, cosThetaI, self->roughness); vec3f fms = self->fmsScale * ((1.f - Eo) * (1.f - Ei) * rcp((float)pi * (1.f - self->Eavg)) * cosThetaI); res.pdf = whPdf * rcp(4.f * abs(cosThetaOH)); res.value = F * (D * G * rcp(4.f * cosThetaO)) + fms; return res; } inline BSDF_SampleRes MicrofacetConductor_sample( const varying MicrofacetConductor *uniform self, const vec3f &wo, const vec2f &s, float) { BSDF_SampleRes res; float cosThetaO = dot(wo, getN(&self->super)); if (cosThetaO <= 0.f) return make_BSDF_SampleRes_zero(); linear3f toGlobal = getFrame(&self->super); linear3f toLocal = transposed(getFrame(&self->super)); vec3f wo0 = toLocal * wo; // Sample the microfacet normal float whPdf; vec3f wh = toGlobal * sampleVisible(self->microfacet, wo0, whPdf, s); res.wi = reflect(wo, wh); float cosThetaI = dot(res.wi, getN(&self->super)); if (cosThetaI <= 0.f) return make_BSDF_SampleRes_zero(); float cosThetaOH = dot(wo, wh); float cosThetaIH = dot(res.wi, wh); vec3f wi0 = toLocal * res.wi; vec3f F = Fresnel_dispatch_eval(self->fresnel, cosThetaOH); float G = evalG2(self->microfacet, wo0, wi0, cosThetaOH, cosThetaIH); // Energy compensation float Eo = MicrofacetAlbedoTable_eval( self->microfacetAlbedoTables, cosThetaO, self->roughness); float Ei = MicrofacetAlbedoTable_eval( self->microfacetAlbedoTables, cosThetaI, self->roughness); vec3f fms = self->fmsScale * ((1.f - Eo) * (1.f - Ei) * rcp((float)pi * (1.f - self->Eavg)) * cosThetaI); res.type = BSDF_GLOSSY_REFLECTION; res.pdf = whPdf * rcp(4.f * abs(cosThetaOH)); res.weight = F * (G * rcp_safe(evalG1(self->microfacet, wo0, cosThetaOH))) + (fms * rcp(res.pdf)); return res; } inline void MicrofacetConductor_Constructor( varying MicrofacetConductor *uniform self, MicrofacetAlbedoTables *uniform microfacetAlbedoTables, const varying linear3f *uniform frame, Fresnel *uniform fresnel, float roughness, float anisotropy) { // Energy compensation self->Eavg = MicrofacetAlbedoTable_evalAvg(microfacetAlbedoTables, roughness); vec3f Favg = Fresnel_dispatch_evalAvg(fresnel); self->fmsScale = sqr(Favg) * self->Eavg / (1.f - Favg * (1.f - self->Eavg)); // Stephen Hill's tweak BSDF_Constructor(&self->super, Favg * self->Eavg, // TODO better estimate BSDF_GLOSSY_REFLECTION, BSDF_TYPE_MICROFACET_CONDUCTOR, frame); self->fresnel = fresnel; self->microfacet = make_GGXDistribution(roughnessToAlpha(roughness, anisotropy)); self->roughness = roughness; self->microfacetAlbedoTables = microfacetAlbedoTables; } inline varying BSDF *uniform MicrofacetConductor_create( uniform ShadingContext *uniform ctx, MicrofacetAlbedoTables *uniform microfacetAlbedoTables, const varying linear3f *uniform frame, Fresnel *uniform fresnel, float roughness, float anisotropy) { varying MicrofacetConductor *uniform self = (varying MicrofacetConductor * uniform) ShadingContext_alloc(ctx, sizeof(MicrofacetConductor)); MicrofacetConductor_Constructor( self, microfacetAlbedoTables, frame, fresnel, roughness, anisotropy); return &self->super; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/MicrofacetDielectric.ih000066400000000000000000000225661456566705700265670ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "BSDF.ih" #include "Fresnel.ih" #include "GGXDistribution.ih" #include "MicrofacetAlbedoTables.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // Microfacet dielectric BSDF with the Smith microsurface model and approximate // multiple scattering. [Walter et al., 2007, "Microfacet Models for Refraction // through Rough Surfaces"] [Kulla and Conty, 2017, "Revisiting Physically Based // Shading at Imageworks"] [Jakob et al., 2014, "A Comprehensive Framework for // Rendering Layered Materials", Extended Technical Report] // FIXME: improve robustness struct MicrofacetDielectric { BSDF super; float eta; // etaO / etaI GGXDistribution microfacet; float roughness; const MicrofacetAlbedoTables *uniform microfacetAlbedoTables; // Energy compensation [Kulla and Conty, 2017] float EavgEta, EavgRcpEta; float FavgEta, FavgRcpEta; float fmsRatio; }; // Single-scattering lobe inline BSDF_EvalRes MicrofacetDielectric_evalSingle( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi) { const varying MicrofacetDielectric *uniform self = (const varying MicrofacetDielectric *uniform)super; BSDF_EvalRes res; float cosThetaO = dot(wo, getN(super)); if (cosThetaO <= 0.f) return make_BSDF_EvalRes_zero(); float cosThetaI = dot(wi, getN(super)); bool isReflection = cosThetaI > 0.f; // Compute the microfacet normal vec3f wh; if (isReflection) { // Reflection wh = wo + wi; } else { // Transmission wh = self->eta * wo + wi; } wh = normalize(wh); float cosThetaH = dot(wh, getN(super)); // Ensure that the micronormal is in the same hemisphere as the macronormal if (cosThetaH < 0.f) wh = neg(wh); float cosThetaOH = dot(wo, wh); float cosThetaIH = dot(wi, wh); // Fresnel term float F = fresnelDielectric(cosThetaOH, self->eta); float value; if (isReflection) { // Reflection res.pdf = F * rcp(4.f * abs(cosThetaOH)); value = F * rcp(4.f * cosThetaO); } else { // Transmission res.pdf = (1.f - F) * rcp(sqr(self->eta)) * abs(cosThetaIH) * rcp(sqr(cosThetaOH + rcp(self->eta) * cosThetaIH)); value = res.pdf * abs(cosThetaOH) * rcp(cosThetaO); // ignore solid angle compression } linear3f toLocal = transposed(getFrame(super)); vec3f wo0 = toLocal * wo; vec3f wi0 = toLocal * wi; vec3f wh0 = toLocal * wh; float whPdf; float D = evalVisible(self->microfacet, wh0, wo0, cosThetaOH, whPdf); float G = evalG2(self->microfacet, wo0, wi0, cosThetaOH, cosThetaIH); res.pdf *= whPdf; res.value = make_vec3f(value * D * G); return res; } inline BSDF_EvalRes MicrofacetDielectric_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi) { const varying MicrofacetDielectric *uniform self = (const varying MicrofacetDielectric *uniform)super; BSDF_EvalRes res; float cosThetaO = dot(wo, getN(super)); if (cosThetaO <= 0.f) return make_BSDF_EvalRes_zero(); float cosThetaI = dot(wi, getN(super)); bool isReflection = cosThetaI > 0.f; // Evaluate the energy compensation lobe [Kulla and Conty, 2017] float Eo = MicrofacetDielectricAlbedoTable_eval( self->microfacetAlbedoTables, cosThetaO, self->eta, self->roughness); BSDF_EvalRes fms; if (isReflection) { // Reflection float Ei = MicrofacetDielectricAlbedoTable_eval( self->microfacetAlbedoTables, cosThetaI, self->eta, self->roughness); fms.pdf = self->fmsRatio * cosineSampleHemispherePDF(cosThetaI); fms.value = make_vec3f(self->fmsRatio * (1.f - Eo) * (1.f - Ei) * rcp((float)pi * (1.f - self->EavgEta)) * cosThetaI); } else { // Transmission float Ei = MicrofacetDielectricAlbedoTable_eval(self->microfacetAlbedoTables, abs(cosThetaI), rcp(self->eta), self->roughness); fms.pdf = (1.f - self->fmsRatio) * cosineSampleHemispherePDF(abs(cosThetaI)); fms.value = make_vec3f((1.f - self->fmsRatio) * (1.f - Eo) * (1.f - Ei) * rcp((float)pi * (1.f - self->EavgRcpEta)) * abs(cosThetaI)); } // Evaluate the single-scattering lobe BSDF_EvalRes single = MicrofacetDielectric_evalSingle(super, wo, wi); // Compute the final result float singlePickProb = Eo; res.pdf = singlePickProb * single.pdf + (1.f - singlePickProb) * fms.pdf; res.value = single.value + fms.value; return res; } inline BSDF_SampleRes MicrofacetDielectric_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss) { const varying MicrofacetDielectric *uniform self = (const varying MicrofacetDielectric *uniform)super; BSDF_SampleRes res; float cosThetaO = dot(wo, getN(super)); if (cosThetaO <= 0.f) return make_BSDF_SampleRes_zero(); // Energy compensation float Eo = MicrofacetDielectricAlbedoTable_eval( self->microfacetAlbedoTables, cosThetaO, self->eta, self->roughness); float singlePickProb = Eo; bool doReflection; bool doSingle = (ss <= singlePickProb); if (doSingle) { // Sample the single-scattering lobe linear3f toGlobal = getFrame(super); linear3f toLocal = transposed(getFrame(super)); vec3f wo0 = toLocal * wo; // Sample the microfacet normal float whPdf; vec3f wh = toGlobal * sampleVisible(self->microfacet, wo0, whPdf, s); float cosThetaOH = dot(wo, wh); // Fresnel term float cosThetaTH; // positive float F = fresnelDielectricEx(cosThetaOH, cosThetaTH, self->eta); // Sample the reflection or the transmission float ss1 = ss * rcp(singlePickProb); doReflection = (ss1 <= F); if (doReflection) { // Reflection res.type = BSDF_GLOSSY_REFLECTION; res.wi = reflect(wo, wh, cosThetaOH); } else { // Transmission res.type = BSDF_GLOSSY_TRANSMISSION; res.wi = refract(wo, wh, cosThetaOH, cosThetaTH, self->eta); } } else { // Sample the energy compensation lobe float ss1 = (ss - singlePickProb) * rcp(1.f - singlePickProb); doReflection = (ss1 <= self->fmsRatio); res.wi = getFrame(super) * cosineSampleHemisphere(s); if (doReflection) { // Reflection res.type = BSDF_DIFFUSE_REFLECTION; } else { // Transmission res.type = BSDF_DIFFUSE_TRANSMISSION; res.wi = neg(res.wi); } } float cosThetaI = dot(res.wi, getN(super)); if ((doReflection && cosThetaI <= 0.f) || (!doReflection && cosThetaI >= 0.f)) return make_BSDF_SampleRes_zero(); // Evaluate the energy compensation lobe BSDF_EvalRes fms; if (doReflection) { // Reflection float Ei = MicrofacetDielectricAlbedoTable_eval( self->microfacetAlbedoTables, cosThetaI, self->eta, self->roughness); fms.pdf = self->fmsRatio * cosineSampleHemispherePDF(cosThetaI); fms.value = make_vec3f(self->fmsRatio * (1.f - Eo) * (1.f - Ei) * rcp((float)pi * (1.f - self->EavgEta)) * cosThetaI); } else { // Transmission float Ei = MicrofacetDielectricAlbedoTable_eval(self->microfacetAlbedoTables, abs(cosThetaI), rcp(self->eta), self->roughness); fms.pdf = (1.f - self->fmsRatio) * cosineSampleHemispherePDF(abs(cosThetaI)); fms.value = make_vec3f((1.f - self->fmsRatio) * (1.f - Eo) * (1.f - Ei) * rcp((float)pi * (1.f - self->EavgRcpEta)) * abs(cosThetaI)); } // Evaluate the single-scattering lobe BSDF_EvalRes single = MicrofacetDielectric_evalSingle(super, wo, res.wi); // Compute the final result res.pdf = singlePickProb * single.pdf + (1.f - singlePickProb) * fms.pdf; res.weight = (single.value + fms.value) * rcp(res.pdf); return res; } inline void MicrofacetDielectric_Constructor( varying MicrofacetDielectric *uniform self, MicrofacetAlbedoTables *uniform microfacetAlbedoTables, const varying linear3f *uniform frame, float eta, float roughness, float anisotropy) { BSDF_Constructor(&self->super, make_vec3f(0.9f), // TODO better estimate BSDF_GLOSSY | BSDF_DIFFUSE, BSDF_TYPE_MICROFACET_DIELECTRIC, frame); self->eta = eta; self->microfacet = make_GGXDistribution(roughnessToAlpha(roughness, anisotropy)); self->roughness = roughness; self->microfacetAlbedoTables = microfacetAlbedoTables; // Energy compensation self->EavgEta = MicrofacetDielectricAlbedoTable_evalAvg( microfacetAlbedoTables, eta, roughness); self->EavgRcpEta = MicrofacetDielectricAlbedoTable_evalAvg( microfacetAlbedoTables, rcp(eta), roughness); self->FavgEta = fresnelDielectricAvg(eta); self->FavgRcpEta = fresnelDielectricAvg(rcp(eta)); float a = (1.f - self->FavgEta) * rcp(1.f - self->EavgRcpEta); float b = (1.f - self->FavgRcpEta) * rcp(1.f - self->EavgEta) /* * sqr(eta)*/; // ignore solid angle compression float x = b * rcp(a + b); self->fmsRatio = (1.f - x * (1.f - self->FavgEta)); } inline varying BSDF *uniform MicrofacetDielectric_create( uniform ShadingContext *uniform ctx, MicrofacetAlbedoTables *uniform microfacetAlbedoTables, const varying linear3f *uniform frame, float eta, float roughness, float anisotropy) { varying MicrofacetDielectric *uniform self = (varying MicrofacetDielectric * uniform) ShadingContext_alloc(ctx, sizeof(MicrofacetDielectric)); MicrofacetDielectric_Constructor( self, microfacetAlbedoTables, frame, eta, roughness, anisotropy); return &self->super; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/MicrofacetDielectricLayer.ih000066400000000000000000000547521456566705700275660ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "MicrofacetAlbedoTables.ih" #include "MicrofacetDielectric.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // Simplified, energy conserving Weidlich-Wilkie microfacet coating BSDF with // the Smith microsurface model. Refraction is ignored, but absorption is // computed from the refracted ray lengths. // [Weidlich and Wilkie, 2007, "Arbitrarily Layered Micro-Facet Surfaces"] // [Walter et al., 2007, "Microfacet Models for Refraction through Rough // Surfaces"] [Kulla and Conty, 2017, "Revisiting Physically Based Shading at // Imageworks"] [Kelemen and Szirmay-Kalos, 2001, "A Microfacet Based Coupled // Specular-Matte BRDF Model with Importance Sampling"] [Jakob et al., 2014, "A // Comprehensive Framework for Rendering Layered Materials", Extended Technical // Report] struct MicrofacetDielectricLayer { BSDF super; float weight; float eta; vec3f transmittance; float thickness; GGXDistribution microfacet; float roughness; const MicrofacetAlbedoTables *uniform microfacetAlbedoTables; // Energy conservation/compensation [Kulla and Conty, 2017] float Ravg; float Eavg; float fmsScale; }; inline void MicrofacetDielectricLayer_Constructor( varying MicrofacetDielectricLayer *uniform self, MicrofacetAlbedoTables *uniform microfacetAlbedoTables, const varying linear3f *uniform frame, varying BSDF *varying substrate, float eta, vec3f transmittance, float thickness, float roughness, float anisotropy, float weight) { // Energy conservation/compensation self->Eavg = MicrofacetAlbedoTable_evalAvg(microfacetAlbedoTables, roughness); float Favg = fresnelDielectricAvg(eta); self->fmsScale = Favg * (1.f - self->Eavg) * rcp(1.f - Favg * self->Eavg); self->Ravg = (MicrofacetDielectricReflectionAlbedoTable_evalAvg( microfacetAlbedoTables, self->eta, roughness) + self->fmsScale * (1.f - self->Eavg)) * weight; // add missing energy // XXX check const vec3f albedo = substrate->albedo * ((1.0f - weight) + pow(transmittance, thickness) * (1.f - Favg)); BSDF_Constructor(&self->super, albedo, BSDF_GLOSSY_REFLECTION | substrate->scatteringType, BSDF_TYPE_MICROFACET_DIELECTRIC_LAYER, frame); self->eta = (eta <= 1.f) ? eta : rcp(eta); self->transmittance = transmittance; self->thickness = thickness; self->microfacet = make_GGXDistribution(roughnessToAlpha(roughness, anisotropy)); self->roughness = roughness; self->microfacetAlbedoTables = microfacetAlbedoTables; self->weight = weight; } inline varying BSDF *uniform MicrofacetDielectricLayer_create( uniform ShadingContext *uniform ctx, MicrofacetAlbedoTables *uniform microfacetAlbedoTables, const varying linear3f *uniform frame, varying BSDF *varying substrate, float eta, vec3f transmittance, float thickness, float roughness, float anisotropy, float weight) { varying MicrofacetDielectricLayer *uniform self = (varying MicrofacetDielectricLayer * uniform) ShadingContext_alloc(ctx, sizeof(MicrofacetDielectricLayer)); MicrofacetDielectricLayer_Constructor(self, microfacetAlbedoTables, frame, substrate, eta, transmittance, thickness, roughness, anisotropy, weight); return &self->super; } // Helper function for transparent shadow rays inline vec3f MicrofacetDielectricLayer_getTransparency( MicrofacetAlbedoTables *uniform microfacetAlbedoTables, float cosThetaO, float eta, vec3f transmittance, float thickness, float roughness, float, float weight) { if (eta > 1.f) eta = rcp(eta); // Apply the coating medium absorption // Use refracted angles for computing the absorption path length float lengthO1 = rcp(refract(cosThetaO, eta)); // rcp(cosThetaO1) vec3f value = lerp(weight, make_vec3f(1.f), pow(transmittance, thickness * lengthO1)); // Energy conservation float Eavg = MicrofacetAlbedoTable_evalAvg(microfacetAlbedoTables, roughness); float Favg = fresnelDielectricAvg(eta); float fmsScale = Favg * (1.f - Eavg) * rcp(1.f - Favg * Eavg); float Eo = MicrofacetAlbedoTable_eval(microfacetAlbedoTables, cosThetaO, roughness); float Ro = (MicrofacetDielectricReflectionAlbedoTable_eval( microfacetAlbedoTables, cosThetaO, eta, roughness) + fmsScale * (1.f - Eo)) * weight; // add missing energy float T = 1.f - Ro; // for generic (non-diffuse) substrates [Kulla and Conty, 2017] value = value * T; return value; } OSPRAY_END_ISPC_NAMESPACE // Eval macros #define MICROFACETDIELECTRICLAYER_EVAL( \ mdl_name, scatteringType, substrate_bsdf, substrate_fn) \ const varying MicrofacetDielectricLayer *uniform mdl = \ (const varying MicrofacetDielectricLayer *uniform) & mdl_name; \ \ float cosThetaO = dot(wo, getN(&mdl->super)); \ if (cosThetaO <= 0.f) \ return make_BSDF_EvalRes_zero(); \ float cosThetaI = dot(wi, getN(&mdl->super)); \ \ /* Evaluate the substrate */ \ /* Ignore refraction */ \ BSDF_EvalRes substrate = substrate_fn(substrate_bsdf, wo, wi); \ \ /* Apply the coating medium absorption */ \ /* Use refracted angles for computing the absorption path length */ \ float lengthO1 = rcp(refract(cosThetaO, mdl->eta)); /* rcp(cosThetaO1) */ \ float lengthI1 = \ rcp(refract(abs(cosThetaI), mdl->eta)); /* rcp(cosThetaI1) */ \ float length = lengthO1 + lengthI1; \ if (cosThetaI <= 0.f) \ length *= 0.5f; /* for transmission, use the average length */ \ substrate.value = lerp(mdl->weight, \ substrate.value, \ substrate.value * pow(mdl->transmittance, mdl->thickness * length)); \ \ /* Energy conservation */ \ float Eo = MicrofacetAlbedoTable_eval( \ mdl->microfacetAlbedoTables, cosThetaO, mdl->roughness); \ float Ei = MicrofacetAlbedoTable_eval( \ mdl->microfacetAlbedoTables, abs(cosThetaI), mdl->roughness); \ float Ro = \ (MicrofacetDielectricReflectionAlbedoTable_eval( \ mdl->microfacetAlbedoTables, cosThetaO, mdl->eta, mdl->roughness) \ + mdl->fmsScale * (1.f - Eo)) \ * mdl->weight; /* add missing energy */ \ float Ri = (MicrofacetDielectricReflectionAlbedoTable_eval( \ mdl->microfacetAlbedoTables, \ abs(cosThetaI), \ mdl->eta, \ mdl->roughness) \ + mdl->fmsScale * (1.f - Ei)) \ * mdl->weight; /* add missing energy */ \ float T; \ if (scatteringType & ~BSDF_DIFFUSE) \ T = min(1.f - Ro, 1.f - Ri); /* for generic (non-diffuse) substrates \ [Kulla and Conty, 2017] */ \ else \ T = (1.f - Ro) * (1.f - Ri) \ * rcp(1.f - mdl->Ravg); /* for diffuse substrates [Kelemen and \ Szirmay-Kalos, 2001] */ \ substrate.value = substrate.value * T; \ \ float coatPickProb = Ro; \ float substratePickProb = 1.f - coatPickProb; \ \ if (cosThetaI > 0.f) { \ /* Compute the microfacet normal */ \ vec3f wh = normalize(wo + wi); \ float cosThetaOH = dot(wo, wh); \ \ /* Fresnel term */ \ float F = fresnelDielectric(cosThetaOH, mdl->eta) * mdl->weight; \ \ /* Evaluate the coating reflection */ \ float cosThetaIH = dot(wi, wh); \ \ linear3f toLocal = transposed(getFrame(&mdl->super)); \ vec3f wo0 = toLocal * wo; \ vec3f wi0 = toLocal * wi; \ vec3f wh0 = toLocal * wh; \ \ float whPdf; \ float D = evalVisible(mdl->microfacet, wh0, wo0, cosThetaOH, whPdf); \ float G = evalG2(mdl->microfacet, wo0, wi0, cosThetaOH, cosThetaIH); \ \ /* Energy compensation */ \ float fms = mdl->fmsScale \ * ((1.f - Eo) * (1.f - Ei) * rcp((float)pi * (1.f - mdl->Eavg)) \ * cosThetaI); \ \ BSDF_EvalRes coat; \ coat.pdf = whPdf * rcp(4.f * cosThetaOH); \ coat.value = make_vec3f(F * D * G * rcp(4.f * cosThetaO) + fms); \ \ /* Compute the total reflection */ \ substrate.pdf = \ coatPickProb * coat.pdf + substratePickProb * substrate.pdf; \ substrate.value = coat.value + substrate.value; \ } else { \ /* Return the substrate transmission */ \ substrate.pdf *= substratePickProb; \ } #define MICROFACETDIELECTRICLAYER_EVAL_GET() substrate // Sample macros #define MICROFACETDIELECTRICLAYER_SAMPLE(mdl_name, \ scatteringType, \ substrate_bsdf, \ substrate_eval, \ substrate_sample) \ const varying MicrofacetDielectricLayer *uniform mdl = \ (const varying MicrofacetDielectricLayer *uniform) & mdl_name; \ BSDF_SampleRes res; \ \ float cosThetaO = dot(wo, getN(&mdl->super)); \ if (cosThetaO <= 0.f) \ return make_BSDF_SampleRes_zero(); \ \ linear3f toGlobal = getFrame(&mdl->super); \ linear3f toLocal = transposed(getFrame(&mdl->super)); \ vec3f wo0 = toLocal * wo; \ \ /* Energy conservation */ \ float Eo = MicrofacetAlbedoTable_eval( \ mdl->microfacetAlbedoTables, cosThetaO, mdl->roughness); \ float Ro = \ MicrofacetDielectricReflectionAlbedoTable_eval( \ mdl->microfacetAlbedoTables, cosThetaO, mdl->eta, mdl->roughness) \ + mdl->fmsScale * (1.f - Eo) * mdl->weight; /* add missing energy */ \ \ /* Sample the coating or the substrate */ \ vec3f wh; \ BSDF_EvalRes substrate; \ \ float coatPickProb = Ro; \ float substratePickProb = 1.f - coatPickProb; \ \ if (ss < coatPickProb) { \ /* Sample the microfacet normal */ \ float whPdf; \ wh = toGlobal * sampleVisible(mdl->microfacet, wo0, whPdf, s); \ float cosThetaOH = dot(wo, wh); \ \ res.type = BSDF_GLOSSY_REFLECTION; \ res.wi = reflect(wo, wh, cosThetaOH); \ \ /* Evaluate the substrate */ \ /* Ignore refraction */ \ substrate = substrate_eval(substrate_bsdf, wo, res.wi); \ } else { \ /* Sample the substrate */ \ /* Ignore refraction */ \ float ss1 = \ (ss - coatPickProb) * rcp(substratePickProb); /* reallocate sample */ \ res = substrate_sample(substrate_bsdf, wo, s, ss1); \ if (reduce_max(res.weight) <= 0.f) \ return res; \ \ substrate.pdf = res.pdf; \ substrate.value = res.weight \ * ((res.type & BSDF_SPECULAR) \ ? 1.f \ : res.pdf); /* correctly handle delta distributions */ \ \ /* Compute the microfacet normal */ \ wh = normalize(wo + res.wi); \ } \ \ float cosThetaI = dot(res.wi, getN(&mdl->super)); \ float cosThetaOH = dot(wo, wh); \ \ /* Apply the coating medium absorption */ \ /* Use refracted angles for computing the absorption path length */ \ float lengthO1 = rcp(refract(cosThetaO, mdl->eta)); /* rcp(cosThetaO1) */ \ float lengthI1 = \ rcp(refract(abs(cosThetaI), mdl->eta)); /* rcp(cosThetaI1) */ \ float length = lengthO1 + lengthI1; \ if (cosThetaI <= 0.f) \ length *= 0.5f; /* for transmission, use the average length */ \ substrate.value = lerp(mdl->weight, \ substrate.value, \ substrate.value * pow(mdl->transmittance, mdl->thickness * length)); \ \ /* Energy conservation */ \ float Ei = MicrofacetAlbedoTable_eval( \ mdl->microfacetAlbedoTables, abs(cosThetaI), mdl->roughness); \ float Ri = (MicrofacetDielectricReflectionAlbedoTable_eval( \ mdl->microfacetAlbedoTables, \ abs(cosThetaI), \ mdl->eta, \ mdl->roughness) \ + mdl->fmsScale * (1.f - Ei)) \ * mdl->weight; /* add missing energy */ \ float T; \ if (scatteringType & ~BSDF_DIFFUSE) \ T = min(1.f - Ro, 1.f - Ri); /* for generic (non-diffuse) substrates \ [Kulla and Conty, 2017] */ \ else \ T = (1.f - Ro) * (1.f - Ri) \ * rcp(1.f - mdl->Ravg); /* for diffuse substrates [Kelemen and \ Szirmay-Kalos, 2001] */ \ substrate.value = substrate.value * T; \ \ if (res.type & BSDF_SPECULAR) { \ /* If we sampled a delta distribution, we don't have to evaluate the \ * coating reflection (see MultiBSDF_sample) */ \ res.weight = substrate.value * rcp(substratePickProb); \ } else if (cosThetaI <= 0.f) { \ /* If we sampled transmission, we just have to return the substrate \ * transmission */ \ res.pdf = substratePickProb * substrate.pdf; \ res.weight = substrate.value * rcp(res.pdf); \ } else { \ /* Fresnel term */ \ float F = fresnelDielectric(cosThetaOH, mdl->eta) * mdl->weight; \ \ /* Evaluate the coating reflection */ \ float cosThetaIH = dot(res.wi, wh); \ vec3f wi0 = toLocal * res.wi; \ vec3f wh0 = toLocal * wh; \ \ float whPdf; \ float D = evalVisible(mdl->microfacet, wh0, wo0, cosThetaOH, whPdf); \ float G = evalG2(mdl->microfacet, wo0, wi0, cosThetaOH, cosThetaIH); \ \ /* Energy compensation */ \ float fms = mdl->fmsScale \ * ((1.f - Eo) * (1.f - Ei) * rcp((float)pi * (1.f - mdl->Eavg)) \ * cosThetaI); \ \ BSDF_EvalRes coat; \ coat.pdf = whPdf * rcp(4.f * cosThetaOH); \ coat.value = make_vec3f(F * D * G * rcp(4.f * cosThetaO) + fms); \ \ /* Compute the total reflection */ \ res.pdf = coatPickProb * coat.pdf + substratePickProb * substrate.pdf; \ res.weight = (coat.value + substrate.value) * rcp(res.pdf); \ } #define MICROFACETDIELECTRICLAYER_SAMPLE_GET() res RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/MicrofacetDistribution.ih000066400000000000000000000011451456566705700271650ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/math.ih" OSPRAY_BEGIN_ISPC_NAMESPACE inline float roughnessToAlpha(float roughness) { // Roughness is squared for perceptual reasons return max(sqr(roughness), 0.001f); } // [Burley, 2012, "Physically Based Shading at Disney", Course Notes, v3] inline vec2f roughnessToAlpha(float roughness, float anisotropy) { float aspect = sqrt(1.f - 0.9f * anisotropy); return make_vec2f(max(sqr(roughness) / aspect, 0.001f), max(sqr(roughness) * aspect, 0.001f)); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/MicrofacetSheenLayer.ih000066400000000000000000000311771456566705700265550ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "BSDF.ih" #include "MicrofacetAlbedoTables.ih" #include "SheenDistribution.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // Microfacet sheen BSDF for cloth-like materials. // [Conty and Kulla, 2017, "Production Friendly Microfacet Sheen BRDF"] // [Kulla and Conty, 2017, "Revisiting Physically Based Shading at Imageworks"] struct MicrofacetSheenLayer { BSDF super; float weight; vec3f R; SheenDistribution microfacet; float roughness; const MicrofacetAlbedoTables *uniform microfacetAlbedoTables; }; inline void MicrofacetSheenLayer_Constructor( varying MicrofacetSheenLayer *uniform self, const MicrofacetAlbedoTables *uniform microfacetAlbedoTables, const varying linear3f *uniform frame, varying BSDF *varying substrate, vec3f R, float roughness, float weight) { BSDF_Constructor(&self->super, lerp(weight * 0.1f, substrate->albedo, R), // lean towards substrate (sheen is only at edge) BSDF_DIFFUSE_REFLECTION | substrate->scatteringType, BSDF_TYPE_MICROFACET_SHEEN_LAYER, frame); self->R = R; self->microfacet = make_SheenDistribution(roughnessToAlpha(roughness)); self->roughness = roughness; self->weight = weight; self->microfacetAlbedoTables = microfacetAlbedoTables; } inline varying BSDF *uniform MicrofacetSheenLayer_create( uniform ShadingContext *uniform ctx, const MicrofacetAlbedoTables *uniform microfacetAlbedoTables, const varying linear3f *uniform frame, varying BSDF *varying substrate, vec3f R, float roughness, float weight) { varying MicrofacetSheenLayer *uniform self = (varying MicrofacetSheenLayer * uniform) ShadingContext_alloc(ctx, sizeof(MicrofacetSheenLayer)); MicrofacetSheenLayer_Constructor( self, microfacetAlbedoTables, frame, substrate, R, roughness, weight); return &self->super; } // Helper function for transparent shadow rays inline vec3f MicrofacetSheenLayer_getTransparency( const MicrofacetAlbedoTables *uniform microfacetAlbedoTables, float cosThetaO, float roughness, float weight) { // Energy conservation float Ro = MicrofacetSheenAlbedoTable_eval( microfacetAlbedoTables, cosThetaO, roughness) * weight; float T = 1.f - Ro; return make_vec3f(T); } OSPRAY_END_ISPC_NAMESPACE // Eval macros #define MICROFACETSHEENLAYER_EVAL(msl_name, substrate_bsdf, substrate_fn) \ const varying MicrofacetSheenLayer *uniform msl = \ (const varying MicrofacetSheenLayer *uniform) & msl_name; \ \ float cosThetaO = dot(wo, getN(&msl->super)); \ if (cosThetaO <= 0.f) \ return make_BSDF_EvalRes_zero(); \ float cosThetaI = dot(wi, getN(&msl->super)); \ \ /* Evaluate the substrate */ \ BSDF_EvalRes substrate = substrate_fn(substrate_bsdf, wo, wi); \ \ /* Energy conservation */ \ float Ro = MicrofacetSheenAlbedoTable_eval( \ msl->microfacetAlbedoTables, cosThetaO, msl->roughness) \ * msl->weight; \ float Ri = MicrofacetSheenAlbedoTable_eval( \ msl->microfacetAlbedoTables, abs(cosThetaI), msl->roughness) \ * msl->weight; \ float T = min(1.f - Ro, 1.f - Ri); \ substrate.value = substrate.value * T; \ \ float coatPickProb = Ro; \ float substratePickProb = 1.f - coatPickProb; \ \ if (cosThetaI > 0.f) { \ /* Compute the microfacet normal */ \ vec3f wh = normalize(wo + wi); \ float cosThetaH = dot(wh, getN(&msl->super)); \ float cosThetaOH = dot(wo, wh); \ float cosThetaIH = dot(wi, wh); \ \ /* Evaluate the coating reflection */ \ float D = eval(msl->microfacet, cosThetaH); \ float G = \ evalG2(msl->microfacet, cosThetaO, cosThetaI, cosThetaOH, cosThetaIH); \ \ BSDF_EvalRes coat; \ coat.pdf = uniformSampleHemispherePDF(); \ coat.value = msl->R * (D * G * rcp(4.f * cosThetaO) * msl->weight); \ \ /* Compute the total reflection */ \ substrate.pdf = \ coatPickProb * coat.pdf + substratePickProb * substrate.pdf; \ substrate.value = coat.value + substrate.value; \ } else { \ /* Return the substrate transmission */ \ substrate.pdf *= substratePickProb; \ } #define MICROFACETSHEENLAYER_EVAL_GET() substrate // Sample macros #define MICROFACETSHEENLAYER_SAMPLE( \ msl_name, substrate_bsdf, substrate_eval, substrate_sample) \ const varying MicrofacetSheenLayer *uniform msl = \ (const varying MicrofacetSheenLayer *uniform) & msl_name; \ BSDF_SampleRes res; \ \ float cosThetaO = dot(wo, getN(&msl->super)); \ if (cosThetaO <= 0.f) \ return make_BSDF_SampleRes_zero(); \ \ /* Energy conservation */ \ float Ro = MicrofacetSheenAlbedoTable_eval( \ msl->microfacetAlbedoTables, cosThetaO, msl->roughness) \ * msl->weight; \ \ /* Sample the coating or the substrate */ \ BSDF_EvalRes substrate; \ \ float coatPickProb = Ro; \ float substratePickProb = 1.f - coatPickProb; \ \ if (ss < coatPickProb) { \ /* Sample the coating reflection */ \ res.type = BSDF_DIFFUSE_REFLECTION; \ res.wi = getFrame(&msl->super) * uniformSampleHemisphere(s); \ \ /* Evaluate the substrate */ \ substrate = substrate_eval(substrate_bsdf, wo, res.wi); \ } else { \ /* Sample the substrate */ \ float ss1 = \ (ss - coatPickProb) * rcp(substratePickProb); /* reallocate sample */ \ res = substrate_sample(substrate_bsdf, wo, s, ss1); \ if (reduce_max(res.weight) <= 0.f) \ return res; \ \ substrate.pdf = res.pdf; \ substrate.value = res.weight \ * ((res.type & BSDF_SPECULAR) \ ? 1.f \ : res.pdf); /* correctly handle delta distributions */ \ } \ \ float cosThetaI = dot(res.wi, getN(&msl->super)); \ \ /* Energy conservation */ \ float Ri = MicrofacetSheenAlbedoTable_eval( \ msl->microfacetAlbedoTables, abs(cosThetaI), msl->roughness) \ * msl->weight; \ float T = min(1.f - Ro, 1.f - Ri); \ substrate.value = substrate.value * T; \ \ if (res.type & BSDF_SPECULAR) { \ /* If we sampled a delta distribution, we don't have to evaluate the \ * coating reflection (see MultiBSDF_sample) */ \ res.weight = substrate.value * rcp(substratePickProb); \ } else if (cosThetaI <= 0.f) { \ /* If we sampled transmission, we just have to return the substrate \ * transmission */ \ res.pdf = substratePickProb * substrate.pdf; \ res.weight = substrate.value * rcp(res.pdf); \ } else { \ /* Compute the microfacet normal */ \ vec3f wh = normalize(wo + res.wi); \ float cosThetaH = dot(wh, getN(&msl->super)); \ float cosThetaOH = dot(wo, wh); \ float cosThetaIH = dot(res.wi, wh); \ \ /* Evaluate the coating reflection */ \ float D = eval(msl->microfacet, cosThetaH); \ float G = \ evalG2(msl->microfacet, cosThetaO, cosThetaI, cosThetaOH, cosThetaIH); \ \ BSDF_EvalRes coat; \ coat.pdf = uniformSampleHemispherePDF(); \ coat.value = msl->R * (D * G * rcp(4.f * cosThetaO) * msl->weight); \ \ /* Compute the total reflection */ \ res.pdf = coatPickProb * coat.pdf + substratePickProb * substrate.pdf; \ res.weight = (coat.value + substrate.value) * rcp(res.pdf); \ } #define MICROFACETSHEENLAYER_SAMPLE_GET() res RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/Minneart.ih000066400000000000000000000034401456566705700242660ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "BSDF.ih" #include "ShadingContext.ih" #include "math/sampling.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Minneart { BSDF super; /*! The amount of backscattering. A value of 0 means lambertian * diffuse, and inf means maximum backscattering. */ float b; }; inline BSDF_EvalRes Minneart_eval( const varying Minneart *uniform self, const vec3f &wo, const vec3f &wi) { BSDF_EvalRes res; const float cosThetaI = clamp(dot(wi, getN(&self->super))); const float backScatter = pow(clamp(dot(wo, wi)), self->b); res.pdf = cosineSampleHemispherePDF(cosThetaI); res.value = (backScatter * cosThetaI * (float)one_over_pi) * self->super.albedo; return res; } inline BSDF_SampleRes Minneart_sample(const varying Minneart *uniform self, const vec3f &wo, const vec2f &s, float) { BSDF_SampleRes res; const vec3f localDir = cosineSampleHemisphere(s); res.wi = getFrame(&self->super) * localDir; res.type = BSDF_DIFFUSE_REFLECTION; BSDF_EvalRes eval = Minneart_eval(self, wo, res.wi); res.pdf = eval.pdf; res.weight = eval.value * rcp(eval.pdf); return res; } inline void Minneart_Constructor(varying Minneart *uniform self, const varying linear3f *uniform frame, vec3f R, float b) { BSDF_Constructor( &self->super, R, BSDF_DIFFUSE_REFLECTION, BSDF_TYPE_MINNEART, frame); self->b = b; } inline varying BSDF *uniform Minneart_create( uniform ShadingContext *uniform ctx, const varying linear3f *uniform frame, vec3f R, float b) { varying Minneart *uniform self = (varying Minneart * uniform) ShadingContext_alloc(ctx, sizeof(Minneart)); Minneart_Constructor(self, frame, R, b); return &self->super; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/MultiBSDF.ih000066400000000000000000000126431456566705700242470ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "BSDF.ih" #include "ShadingContext.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct MultiBSDF_Child { float weight; float importance; }; #define DEFINE_MULTIBSDF(size) \ BSDF super; \ float importanceSum; \ MultiBSDF_Child children[size] struct MultiBSDF { DEFINE_MULTIBSDF(1); }; inline void MultiBSDF_add(varying MultiBSDF *uniform self, const uniform int id, const varying BSDF *uniform bsdf, float weight = 1.f, float importance = 1.f) { self->super.albedo = self->super.albedo + bsdf->albedo * weight; self->super.scatteringType |= bsdf->scatteringType; if (!self->super.frame) // use first frame TODO use dominant frame self->super.frame = bsdf->frame; self->children[id].weight = weight; unmasked { self->children[id].importance = 0.f; } self->children[id].importance = importance; self->importanceSum += importance; } inline void MultiBSDF_Constructor( varying MultiBSDF *uniform self, const uniform int count) { BSDF_Constructor( &self->super, make_vec3f(0.f), BSDF_NONE, BSDF_TYPE_MULTI_BSDF, NULL); unmasked { self->importanceSum = 0.0f; for (uniform int i = 0; i < count; i++) { self->children[i].weight = 0.f; self->children[i].importance = 0.f; } } } OSPRAY_END_ISPC_NAMESPACE // Eval macros #define MULTIBSDF_EVAL_BEGIN() \ BSDF_EvalRes eRes = make_BSDF_EvalRes_zero(); \ const int choice = -1 #define MULTIBSDF_EVAL_CHILD(id, child_bsdf, eval_fn) \ if ((self->children[id].importance > 0.f) && (choice != id)) { \ BSDF_EvalRes cur = eval_fn(child_bsdf, wo, wi); \ cur.value = cur.value * self->children[id].weight; \ eRes.value = eRes.value + cur.value; \ eRes.pdf += cur.pdf * self->children[id].importance; \ } #define MULTIBSDF_EVAL_END() eRes.pdf *= rcp(self->importanceSum) #define MULTIBSDF_EVAL_GET() eRes // Sample macros #define MULTIBSDF_SAMPLE_BEGIN() \ BSDF_SampleRes res = make_BSDF_SampleRes_zero(); \ float x = ss * self->importanceSum; \ int choice = 0; \ float prefixSum = 0.f; \ if (self->importanceSum == 0.f) { \ return res #define MULTIBSDF_SAMPLE_CHILD(id, child_bsdf, sample_fn) \ } \ else if (x < (prefixSum += self->children[id].importance)) \ { \ choice = id; \ \ ss = (x + self->children[id].importance - prefixSum) \ * rcp(self->children[id].importance); \ \ res = sample_fn(child_bsdf, wo, s, ss); \ res.weight = res.weight * self->children[id].weight #define MULTIBSDF_SAMPLE_EVAL() \ } \ if (eq(res.weight, make_vec3f(0.0f)) || (res.pdf == 0.0f)) \ return make_BSDF_SampleRes_zero(); \ \ /* if the sampled BSDF is specular (has a delta distribution), we cannot add \ * the contributions from the other BSDFs [Pharr et al., 2016, "Physically \ * Based Rendering", 3rd Edition, Section 14.1.6] */ \ if (res.type & BSDF_SPECULAR) { \ /* scale by rcp(selection pdf) */ \ res.weight = res.weight \ * (self->importanceSum * rcp(self->children[choice].importance)); \ return res; \ } \ BSDF_EvalRes eRes; \ eRes.value = res.weight * res.pdf; \ res.pdf *= self->children[choice].importance; \ eRes.pdf = res.pdf; \ const vec3f wi = res.wi #define MULTIBSDF_SAMPLE_END() \ res.pdf = eRes.pdf; \ res.pdf *= rcp(self->importanceSum); \ res.weight = eRes.value * rcp(res.pdf) #define MULTIBSDF_SAMPLE_GET() res RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/Optics.ih000066400000000000000000000031771456566705700237610ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "math/sampling.ih" #include "rkcommon/math/LinearSpace.ih" OSPRAY_BEGIN_ISPC_NAMESPACE /*! Reflects a viewing vector I at a normal N. Cosine between I * and N is given as input. */ inline vec3f reflect(const vec3f &I, const vec3f &N, float cosI) { return (2.0f * cosI) * N - I; } /*! Reflects a viewing vector I at a normal N. */ inline vec3f reflect(const vec3f &I, const vec3f &N) { return reflect(I, N, dot(I, N)); } // helper function which computes cosT^2 from cosI and eta inline float sqrCosT(const float cosI, const float eta) { return 1.0f - sqr(eta) * (1.0f - sqr(cosI)); } //! \brief Refracts a viewing vector I at a normal N /*! \detailed Refracts a viewing vector I at a normal N using the * relative refraction index eta. Eta is refraction index of outside * medium (where N points into) divided by refraction index of the * inside medium. The vectors I and N have to point towards the same * side of the surface. The cosine between I and N, and the cosine of -N and * the refracted ray is given as input */ inline vec3f refract( const vec3f &I, const vec3f &N, float cosI, float cosT, float eta) { return eta * (cosI * N - I) - cosT * N; } inline vec3f refract(const vec3f &I, const vec3f &N, float cosI, float eta) { const float sqrcost = sqrCosT(cosI, eta); if (sqrcost < 0.0f) return make_vec3f(0.f); return refract(I, N, cosI, sqrt(sqrcost), eta); } inline float refract(float cosI, float eta) { const float sqrcost = sqrCosT(cosI, eta); return sqrt(max(sqrcost, 0.0f)); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/OrenNayar.ih000066400000000000000000000040541456566705700244110ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "BSDF.ih" #include "GGXDistribution.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // Oren-Nayar BRDF. // [Fujii, 2012, "A tiny improvement of Oren-Nayar reflectance model"] struct OrenNayar { BSDF super; float roughness; }; inline BSDF_EvalRes OrenNayar_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi) { const varying OrenNayar *uniform self = (const varying OrenNayar *uniform)super; BSDF_EvalRes res; float cosThetaO = max(dot(wo, getN(super)), 0.f); float cosThetaI = max(dot(wi, getN(super)), 0.f); float s = dot(wo, wi) - cosThetaO * cosThetaI; float sInvt = (s > 0.f) ? (s * rcp_safe(max(cosThetaO, cosThetaI))) : s; res.value = self->super.albedo * (cosThetaI * (1.f + self->roughness * sInvt) * rcp((float)pi + ((float)pi / 2.f - 2.f / 3.f) * self->roughness)); res.pdf = cosineSampleHemispherePDF(cosThetaI); return res; } inline BSDF_SampleRes OrenNayar_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float) { const vec3f localDir = cosineSampleHemisphere(s); BSDF_SampleRes res; res.wi = getFrame(super) * localDir; BSDF_EvalRes eval = OrenNayar_eval(super, wo, res.wi); res.pdf = eval.pdf; res.type = BSDF_DIFFUSE_REFLECTION; res.weight = eval.value * rcp(eval.pdf); return res; } inline void OrenNayar_Constructor(varying OrenNayar *uniform self, const varying linear3f *uniform frame, const vec3f &R, float roughness) { BSDF_Constructor( &self->super, R, BSDF_DIFFUSE_REFLECTION, BSDF_TYPE_OREN_NAYAR, frame); self->roughness = roughness; } inline varying BSDF *uniform OrenNayar_create( uniform ShadingContext *uniform ctx, const varying linear3f *uniform frame, const vec3f &R, float roughness) { varying OrenNayar *uniform self = (varying OrenNayar * uniform) ShadingContext_alloc(ctx, sizeof(OrenNayar)); OrenNayar_Constructor(self, frame, R, roughness); return &self->super; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/PassthroughLayer.ih000066400000000000000000000015001456566705700260100ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "BSDF.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct PassthroughLayer { BSDF super; float weight; }; inline void PassthroughLayer_Constructor( varying PassthroughLayer *uniform self, varying BSDF *uniform substrate) { BSDF_Constructor(&self->super, substrate->albedo, substrate->scatteringType, substrate->bsdfType, substrate->frame); self->weight = 0.f; } #ifndef OSPRAY_TARGET_SYCL inline void PassthroughLayer_Constructor( varying PassthroughLayer *uniform self, varying BSDF *varying substrate) { foreach_unique (s in substrate) { BSDF_Constructor( &self->super, s->albedo, s->scatteringType, s->bsdfType, s->frame); } self->weight = 0.f; } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/PowerCosineDistribution.ih000066400000000000000000000016231456566705700273470ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/math.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct PowerCosineDistribution { float exp; }; inline float eval( const PowerCosineDistribution &self, float cosThetaH, float &pdf) { pdf = powerCosineSampleHemispherePDF(cosThetaH, self.exp); return (self.exp + 2) * one_over_two_pi * pow(abs(cosThetaH), self.exp); // TODO: check with powerCosineSampleHemispherePDF } /*! Samples the power cosine distribution. */ inline vec3f sample( const PowerCosineDistribution &self, float &pdf, const vec2f &s) { const vec3f wh = powerCosineSampleHemisphere(self.exp, s); pdf = powerCosineSampleHemispherePDF(wh, self.exp); return wh; } inline PowerCosineDistribution make_PowerCosineDistribution(float _exp) { PowerCosineDistribution m; m.exp = _exp; return m; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/Reflection.ih000066400000000000000000000022411456566705700246010ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "BSDF.ih" OSPRAY_BEGIN_ISPC_NAMESPACE inline BSDF_EvalRes Reflection_eval(const varying BSDF *uniform, const vec3f &, const vec3f &, const uniform FeatureFlagsHandler &) { return make_BSDF_EvalRes_zero(); } inline BSDF_SampleRes Reflection_sample(const varying BSDF *uniform self, const vec3f &wo, const vec2f &, float, const uniform FeatureFlagsHandler &) { BSDF_SampleRes res; res.wi = reflect(wo, getN(self)); res.pdf = inf; res.type = BSDF_SPECULAR_REFLECTION; res.weight = self->albedo; return res; } inline varying BSDF *uniform Reflection_create( uniform ShadingContext *uniform ctx, const varying linear3f *uniform frame, vec3f reflectance) { varying BSDF *uniform self = (varying BSDF * uniform) ShadingContext_alloc(ctx, sizeof(BSDF)); BSDF_Constructor(self, reflectance, BSDF_SPECULAR_REFLECTION, BSDF_TYPE_REFLECTION, #ifdef OSPRAY_TARGET_SYCL NULL, NULL, #else Reflection_eval, Reflection_sample, #endif frame); return self; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/RobustDielectric.ih000066400000000000000000000154751456566705700257720ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "BSDF.ih" #include "Fresnel.ih" #include "common/DifferentialGeometry.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // FIXME: this should be cleaned up and integrated into Dielectric and // MicrofacetDielectric struct RobustDielectric { BSDF super; float eta; // FIXME: BSDFs should *not* store the DifferentialGeometry or similar // parameters (i.e., Ng, Ns). These should be passed to sample/eval // DifferentialGeometry dgeom; vec3f Ng; vec3f Ns; }; struct RefractionResult { vec3f outgoingDirection; float FresnelReflectionCoefficient; bool mustReflect; }; inline RefractionResult RefractionDirection( const vec3f &incomingDir, const vec3f &surfaceNormal, const float eta) { RefractionResult res; res.mustReflect = false; float cos1 = dot(incomingDir, surfaceNormal); float cos1_abs = cos1; if (cos1_abs < 0.f) { cos1_abs = -cos1_abs; } // For head-on collisions the cosine of the angle of the ray with the surface // normal will be equal to one or minus one. bool headOn = (1.f - 1e-6f < cos1_abs && cos1_abs < 1.f - 1e-6f); if (headOn) { res.FresnelReflectionCoefficient = sqr((eta - 1.f) / (eta + 1.f)); res.outgoingDirection = incomingDir; } else { vec3f dirParallelToNormal = cos1 * surfaceNormal; vec3f dirPerpendicularToNormal = incomingDir - dirParallelToNormal; vec3f b = normalize(dirPerpendicularToNormal); float sin1 = dot(dirPerpendicularToNormal, b); float sin2 = sin1 / eta; if (sin2 > 1.0f) { // Total internal reflection. res.outgoingDirection = make_vec3f(0.f); // Can't refract. res.FresnelReflectionCoefficient = 1.f; res.mustReflect = true; } else { // Refracting. float cos2 = sqrt(clamp(1.f - sin2 * sin2)); vec3f N2 = normalize(dirParallelToNormal); res.outgoingDirection = N2 * cos2 + b * sin2; float c1 = cos1_abs; float c2 = cos2; float r1 = (eta * c1 - c2) / (eta * c1 + c2); float r2 = (c1 - eta * c2) / (c1 + eta * c2); res.FresnelReflectionCoefficient = 0.5f * (r1 * r1 + r2 * r2); } } // Clamp in case of roundoff error. res.FresnelReflectionCoefficient = clamp(res.FresnelReflectionCoefficient); return res; } inline vec3f ReflectionDirection(const vec3f &incomingDir, const vec3f &normal) { // Imagine a particle traveling toward the surface and then bouncing off in // the // reflection direction. // Parallel or anti-parallel direction. vec3f dirParallelToNormal = dot(incomingDir, normal) * normal; vec3f dirPerpendicularToNormal = incomingDir - dirParallelToNormal; // Outgoing direction. return (dirPerpendicularToNormal - dirParallelToNormal); } inline BSDF_SampleRes RobustDielectric_sample(const varying BSDF *uniform super, const vec3f &wo, const vec2f & /*randomV*/, float randomF) { const varying RobustDielectric *uniform self = (const varying RobustDielectric *uniform)super; BSDF_SampleRes res; res.pdf = inf; // We want the actual ray direction into the surface. vec3f incomingDir = neg(wo); vec3f shadingNormal = self->Ns; vec3f geometricNormal = self->Ng; float eta = 1.f / self->eta; // ior(outside) / ior(inside) float glass_epsilon = 1e-6f; bool canReflect = (eta < 1.f - glass_epsilon || eta > 1.f + glass_epsilon); bool be_careful = true; // Extra test for edge cases when the shading normal // is different from the geometry normal. bool nudge = true; // When we have grazing angles. Only used if be_careful==true. if (be_careful) { // Flip the normals to be on the same side of the surface as the incoming // ray. if (dot(incomingDir, shadingNormal) > 0.f) { shadingNormal = neg(shadingNormal); } if (dot(incomingDir, geometricNormal) > 0.f) { geometricNormal = neg(geometricNormal); } } float geometricCosine; vec3f dirR = ReflectionDirection(incomingDir, shadingNormal); RefractionResult refractionRes = RefractionDirection(incomingDir, shadingNormal, eta); vec3f dirT = refractionRes.outgoingDirection; float FresnelR = refractionRes.FresnelReflectionCoefficient; bool mustReflect = refractionRes.mustReflect; res.weight = make_vec3f(1.f); // Sample the reflection or the transmission using the provided random number. if ((randomF < FresnelR && canReflect) || mustReflect) { // Reflection res.wi = dirR; // Outgoing ray direction. res.type = BSDF_SPECULAR_REFLECTION; if (be_careful) { geometricCosine = dot(res.wi, geometricNormal); if (geometricCosine >= 0.f) { // Reflecting as expected. if (nudge && (geometricCosine < glass_epsilon)) { // Grazing angle. res.wi = res.wi + glass_epsilon * geometricNormal; // Nudge the ray away from the surface. res.wi = normalize(res.wi); } } else { // geometricCosine < 0 // We actually "refracted" since we are now on the other side of the // surface. Keep the ray type as reflection, but move the ray above the // surface. res.wi = res.wi - 2.f * geometricNormal * geometricCosine; } } } else { // Transmission res.wi = dirT; // Outgoing ray direction. res.type = BSDF_SPECULAR_TRANSMISSION; // res.weight = make_vec3f(rsqrt(self->eta));// Solid angle compression. if (be_careful) { geometricCosine = dot(res.wi, geometricNormal); if (geometricCosine <= 0.f) { // Transmitting as expected. if (nudge && (geometricCosine > -glass_epsilon)) { // Grazing angle. res.wi = res.wi - glass_epsilon * geometricNormal; // Nudge the ray away from the surface. res.wi = normalize(res.wi); } } else { // geometricCosine > 0 // We actually "reflected" since we are still on the same side of the // surface. Change ray type to reflection. res.type = BSDF_SPECULAR_REFLECTION; } } } return res; } inline void RobustDielectric_Constructor(varying RobustDielectric *uniform self, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, float eta) { const varying linear3f *uniform shadingframe = LinearSpace3f_create(ctx, frame(dg.Ns)); BSDF_Constructor(&self->super, make_vec3f(1.0f), BSDF_SPECULAR, BSDF_TYPE_ROBUST_DIELECTRIC, shadingframe); self->eta = eta; self->Ns = dg.Ns; self->Ng = dg.Ng; } inline varying BSDF *uniform RobustDielectric_create( uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, float eta) { varying RobustDielectric *uniform self = (varying RobustDielectric * uniform) ShadingContext_alloc(ctx, sizeof(RobustDielectric)); RobustDielectric_Constructor(self, ctx, dg, eta); return &self->super; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/RobustThinDielectric.ih000066400000000000000000000060261456566705700266050ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Dielectric.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // Thin dielectric BSDF. // It represents a transparent slab with unit thickness, and ignores refraction. struct RobustThinDielectric { BSDF super; float eta; vec3f attenuation; }; inline BSDF_SampleRes RobustThinDielectric_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &, float ss) { const varying RobustThinDielectric *uniform self = (const varying RobustThinDielectric *uniform)super; BSDF_SampleRes res; float cosThetaO = max(dot(wo, getN(super)), 0.f); // Fresnel terms float cosThetaT; // positive float Fo = fresnelDielectricEx(cosThetaO, cosThetaT, self->eta); float Ft = fresnelDielectric(cosThetaT, rcp(self->eta)); // Attenuation for crossing the slab once float length = rcp(cosThetaT); vec3f A = expf(self->attenuation * length); // Reflection and transmission weights vec3f R = Fo + (1.f - Fo) * (1.f - Ft) * (Ft * sqr(A)) * rcp(1.f - sqr(Ft * A)); vec3f T = (1.f - Fo) * A * (1.f - Ft) * (1.f + sqr(Ft * A) * rcp(1.f - sqr(Ft * A))); // Sample the reflection or the transmission float pR = luminance(R); float pT = luminance(T); float p = clamp(pR * rcp(pR + pT), 0.25f, 0.75f); bool doReflection = (ss <= p); if (doReflection) { // Reflection res.wi = reflect(wo, getN(super), cosThetaO); res.type = BSDF_SPECULAR_REFLECTION; res.weight = R * rcp(p); } else { // Transmission res.wi = neg(wo); res.type = BSDF_SPECULAR_TRANSMISSION; res.weight = T * rcp(1.f - p); } res.pdf = inf; return res; } inline void RobustThinDielectric_Constructor( varying RobustThinDielectric *uniform self, const varying linear3f *uniform frame, float eta, vec3f attenuation) { BSDF_Constructor(&self->super, expf(attenuation), BSDF_SPECULAR, BSDF_TYPE_ROBUST_THIN_DIELECTRIC, frame); self->eta = eta; self->attenuation = attenuation; } inline varying BSDF *uniform RobustThinDielectric_create( uniform ShadingContext *uniform ctx, const varying linear3f *uniform frame, float eta, vec3f attenuation) { varying RobustThinDielectric *uniform self = (varying RobustThinDielectric * uniform) ShadingContext_alloc(ctx, sizeof(RobustThinDielectric)); RobustThinDielectric_Constructor(self, frame, eta, attenuation); return &self->super; } // Helper function for transparent shadow rays inline vec3f RobustThinDielectric_getTransparency( float cosThetaO, float eta, vec3f attenuation) { // Fresnel terms float cosThetaT; // positive float Fo = fresnelDielectricEx(cosThetaO, cosThetaT, eta); float Ft = fresnelDielectric(cosThetaT, rcp(eta)); // Attenuation for crossing the slab once float length = rcp(cosThetaT); vec3f A = expf(attenuation * length); // Transmission weight vec3f T = (1.f - Fo) * A * (1.f - Ft) * (1.f + sqr(Ft * A) * rcp(1.f - sqr(Ft * A))); return T; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/Scale.ih000066400000000000000000000034341456566705700235430ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "BSDF.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Scale { BSDF super; const varying BSDF *uniform base; float factor; }; inline BSDF_EvalRes Scale_eval(const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi, const uniform FeatureFlagsHandler &ffh) { const varying Scale *uniform self = (const varying Scale *uniform)super; BSDF_EvalRes res = BSDF_dispatch_eval_base(self->base, wo, wi, ffh); res.value = res.value * self->factor; return res; } inline BSDF_SampleRes Scale_sample(const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss, const uniform FeatureFlagsHandler &ffh) { const varying Scale *uniform self = (const varying Scale *uniform)super; BSDF_SampleRes res = BSDF_dispatch_sample_base(self->base, wo, s, ss, ffh); res.weight = res.weight * self->factor; return res; } inline void Scale_Constructor(varying Scale *uniform self, const varying linear3f *uniform frame, const varying BSDF *uniform base, float factor) { BSDF_Constructor(&self->super, base->albedo * factor, base->bsdfType, BSDF_TYPE_SCALE, #ifdef OSPRAY_TARGET_SYCL NULL, NULL, #else Scale_eval, Scale_sample, #endif frame); self->base = base; self->factor = factor; } inline varying BSDF *uniform Scale_create(uniform ShadingContext *uniform ctx, const varying BSDF *uniform base, float factor) { varying Scale *uniform self = (varying Scale * uniform) ShadingContext_alloc(ctx, sizeof(Scale)); Scale_Constructor(self, LinearSpace3f_create(ctx, make_LinearSpace3f_varying_identity()), base, factor); return &self->super; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/ShadingContext.ih000066400000000000000000000027311456566705700254350ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/ISPCMessages.h" #include "rkcommon/math/LinearSpace.ih" OSPRAY_BEGIN_ISPC_NAMESPACE #define SHADINGCONTEXT_SIZE (programCount * programCount * 1024) #define SHADINGCONTEXT_ALIGNMENT 64 struct ShadingContext { /*! Data storage. Has to be at the beginning of the class due to alignment. */ uniform int8 data[SHADINGCONTEXT_SIZE]; //!< Storage for BSDFs uniform uint32 size; //!< Number of bytes occupied in storage varying int dummy; // FIXME: needed to force correct alignment }; inline void ShadingContext_Constructor(uniform ShadingContext *uniform self) { self->size = 0; } /*! Allocates aligned data. */ inline void *uniform ShadingContext_alloc( uniform ShadingContext *uniform self, uniform uint32 size) { // print("ShadingContext_alloc: %, %\n", this->size, size); void *uniform ptr = &self->data[self->size]; self->size = (self->size + size + SHADINGCONTEXT_ALIGNMENT - 1) & ((uint32)(-SHADINGCONTEXT_ALIGNMENT)); #ifndef OSPRAY_TARGET_SYCL if (self->size > SHADINGCONTEXT_SIZE) postStatusMsg(ISPC_MSG_SHADING_CONTEXT, OSP_LOG_ERROR); #endif return ptr; } inline varying linear3f *uniform LinearSpace3f_create( uniform ShadingContext *uniform ctx, const linear3f &l) { varying linear3f *uniform ptr = (varying linear3f * uniform) ShadingContext_alloc(ctx, sizeof(linear3f)); *ptr = l; return ptr; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/SheenDistribution.ih000066400000000000000000000046451456566705700261630ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "MicrofacetDistribution.ih" #include "math/sampling.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // Cylindrical microfiber distribution for sheen // [Conty and Kulla, 2017, "Production Friendly Microfacet Sheen BRDF"] // [Kulla and Conty, 2017, "Revisiting Physically Based Shading at Imageworks"] struct SheenDistribution { float r; // in (0, 1] }; inline SheenDistribution make_SheenDistribution(float r) { SheenDistribution self; self.r = r; return self; } inline float eval(const SheenDistribution &self, float cosTheta) { float sinTheta = cos2sin(cosTheta); float invr = rcp(self.r); return (2.f + invr) * pow(sinTheta, invr) * (float)one_over_two_pi; } // Helper function for computing Lambda inline float evalL(const SheenDistribution &self, float x) { const float a0 = 25.3245f; const float a1 = 21.5473f; const float b0 = 3.32435f; const float b1 = 3.82987f; const float c0 = 0.16801f; const float c1 = 0.19823f; const float d0 = -1.27393f; const float d1 = -1.97760f; const float e0 = -4.85967f; const float e1 = -4.32054f; float r = self.r; float w0 = sqr(1.f - r); float w1 = 1.f - w0; float a = w0 * a0 + w1 * a1; float b = w0 * b0 + w1 * b1; float c = w0 * c0 + w1 * c1; float d = w0 * d0 + w1 * d1; float e = w0 * e0 + w1 * e1; return a / (1.f + b * pow(x, c)) + d * x + e; } inline float evalLambda(const SheenDistribution &self, float cosTheta) { if (cosTheta < 0.5f) return exp(evalL(self, cosTheta)); else return exp(2.f * evalL(self, 0.5f) - evalL(self, 1.f - cosTheta)); } // Non-physical artistic adjustment for a softer light terminator inline float evalLambdaI(const SheenDistribution &self, float cosTheta) { float x = 1.f + 2.f * sqr(sqr(sqr(1.f - cosTheta))); return pow(evalLambda(self, cosTheta), x); } // Smith's height-correlated masking-shadowing function // [Heitz, 2014, "Understanding the Masking-Shadowing Function in // Microfacet-Based BRDFs"] inline float evalG2(const SheenDistribution &self, float cosThetaO, float cosThetaI, float cosThetaOH, float cosThetaIH) { if (cosThetaO * cosThetaOH <= 0.f || cosThetaI * cosThetaIH <= 0.f) return 0.f; // return rcp(1.f + evalLambda(self, cosThetaO) + evalLambda(self, // cosThetaI)); return rcp(1.f + evalLambda(self, cosThetaO) + evalLambdaI(self, cosThetaI)); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/Specular.ih000066400000000000000000000043241456566705700242710ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "BSDF.ih" #include "Optics.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // uses a variant of Blinn-Phong BRDF: // f = r*(n+2)/(4pi(2-2^(-n/2)))*cos(HN)^n/cos(LN) struct Specular { BSDF super; vec3f ks; // reflectivity albedo, including normalization vec3f weight; // = constant part of f * cosNL/pdf float ns; // exponent }; inline BSDF_EvalRes Specular_eval( const varying Specular *uniform self, const vec3f &wo, const vec3f &wi) { BSDF_EvalRes res; const vec3f N = getN(&self->super); const float cosThetaO = dot(wo, N); const float cosThetaI = dot(wi, N); if (cosThetaO <= 0.0f || cosThetaI <= 0.0f) return make_BSDF_EvalRes_zero(); const vec3f wh = normalize(wo + wi); const float cosThetaH = dot(wh, N); res.pdf = powerCosineSampleHemispherePDF(cosThetaH, self->ns) * rcp(4.0f * dot(wo, wh)); res.value = self->ks * powf(cosThetaH, self->ns); return res; } inline BSDF_SampleRes Specular_sample(const varying Specular *uniform self, const vec3f &wo, const vec2f &s, float) { BSDF_SampleRes res; const vec3f wh_local = powerCosineSampleHemisphere(self->ns, s); const vec3f wh = getFrame(&self->super) * wh_local; const float cosThetaOH = dot(wo, wh); res.wi = reflect(wo, wh, cosThetaOH); const float cosThetaI = dot(res.wi, getN(&self->super)); if (cosThetaI <= 0.0f) // below surface? return make_BSDF_SampleRes_zero(); const float cosThetaH = wh_local.z; res.pdf = powerCosineSampleHemispherePDF(cosThetaH, self->ns) * rcp(4.0f * cosThetaOH); res.type = BSDF_GLOSSY_REFLECTION; res.weight = self->weight * cosThetaOH; return res; } inline void Specular_Constructor(varying Specular *uniform self, const varying linear3f *uniform frame, vec3f R, float exp_) { BSDF_Constructor( &self->super, R, BSDF_GLOSSY_REFLECTION, BSDF_TYPE_SPECULAR, frame); // convert from Phong exponent to Blinn self->ns = exp_ * 4.f; const float tmp = (self->ns + 2.f) * rcp(2.f - exp(self->ns * -(float)lntwo_over_two)); self->ks = R * ((float)one_over_four_pi * tmp); self->weight = R * (2.f * tmp * rcp(self->ns + 1.f)); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/ThinDielectric.ih000066400000000000000000000050321456566705700254020ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Dielectric.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // Thin dielectric BSDF. // It represents a transparent slab with unit thickness, and ignores refraction. struct ThinDielectric { BSDF super; float eta; vec3f attenuation; }; inline BSDF_EvalRes ThinDielectric_eval( const varying BSDF *uniform, const vec3f &, const vec3f &) { return make_BSDF_EvalRes_zero(); } inline BSDF_SampleRes ThinDielectric_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &, float ss) { const varying ThinDielectric *uniform self = (const varying ThinDielectric *uniform)super; BSDF_SampleRes res; float cosThetaO = max(dot(wo, getN(super)), 0.f); // Fresnel term float cosThetaT; // positive float F = fresnelDielectricEx(cosThetaO, cosThetaT, self->eta); res.pdf = inf; // Sample the reflection or the transmission bool doReflection = (ss <= F); if (doReflection) { // Reflection res.wi = reflect(wo, getN(super), cosThetaO); res.type = BSDF_SPECULAR_REFLECTION; res.weight = make_vec3f(1.f); } else { // Transmission // Attenuation for crossing the slab once float length = rcp(cosThetaT); vec3f A = expf(self->attenuation * length); res.wi = neg(wo); res.type = BSDF_SPECULAR_TRANSMISSION; res.weight = A; } return res; } inline void ThinDielectric_Constructor(varying ThinDielectric *uniform self, const varying linear3f *uniform frame, float eta, vec3f attenuation) { BSDF_Constructor(&self->super, expf(attenuation), BSDF_SPECULAR, BSDF_TYPE_THIN_DIELECTRIC, frame); self->eta = eta; self->attenuation = attenuation; } inline varying BSDF *uniform ThinDielectric_create( uniform ShadingContext *uniform ctx, const varying linear3f *uniform frame, float eta, vec3f attenuation) { varying ThinDielectric *uniform self = (varying ThinDielectric * uniform) ShadingContext_alloc(ctx, sizeof(ThinDielectric)); ThinDielectric_Constructor(self, frame, eta, attenuation); return &self->super; } // Helper function for transparent shadow rays inline vec3f ThinDielectric_getTransparency( float cosThetaO, float eta, vec3f attenuation) { // Fresnel term float cosThetaT; // positive float F = fresnelDielectricEx(cosThetaO, cosThetaT, eta); // Attenuation for crossing the slab once float length = rcp(cosThetaT); vec3f A = expf(attenuation * length); return (1.f - F) * A; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/ThinMicrofacetDielectric.ih000066400000000000000000000165501456566705700274060ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "MicrofacetAlbedoTablesShared.h" #include "MicrofacetDielectric.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // Thin microfacet dielectric BSDF with the Smith microsurface model. // It represents a transparent slab with unit thickness, and ignores refraction. // [Walter et al., 2007, "Microfacet Models for Refraction through Rough // Surfaces"] [Kulla and Conty, 2017, "Revisiting Physically Based Shading at // Imageworks"] [Jakob et al., 2014, "A Comprehensive Framework for Rendering // Layered Materials", Extended Technical Report] // FIXME: rough transmission struct ThinMicrofacetDielectric { BSDF super; float eta; vec3f attenuation; GGXDistribution microfacet; float roughness; const MicrofacetAlbedoTables *uniform microfacetAlbedoTables; // Energy compensation [Kulla and Conty, 2017] float Eavg; float fmsScale; }; inline BSDF_EvalRes ThinMicrofacetDielectric_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi) { const varying ThinMicrofacetDielectric *uniform self = (const varying ThinMicrofacetDielectric *uniform)super; float cosThetaO = dot(wo, getN(super)); if (cosThetaO <= 0.f) return make_BSDF_EvalRes_zero(); float cosThetaI = dot(wi, getN(super)); bool isReflection = cosThetaI > 0.f; if (isReflection) { // Compute the microfacet normal vec3f wh = normalize(wo + wi); float cosThetaOH = dot(wo, wh); float cosThetaIH = dot(wi, wh); linear3f toLocal = transposed(getFrame(super)); vec3f wo0 = toLocal * wo; vec3f wi0 = toLocal * wi; vec3f wh0 = toLocal * wh; float F = fresnelDielectric(cosThetaOH, self->eta); float whPdf; float D = evalVisible(self->microfacet, wh0, wo0, cosThetaOH, whPdf); float G = evalG2(self->microfacet, wo0, wi0, cosThetaOH, cosThetaIH); // Energy compensation float Eo = MicrofacetAlbedoTable_eval( self->microfacetAlbedoTables, cosThetaO, self->roughness); float Ei = MicrofacetAlbedoTable_eval( self->microfacetAlbedoTables, cosThetaI, self->roughness); float fms = self->fmsScale * ((1.f - Eo) * (1.f - Ei) * rcp((float)pi * (1.f - self->Eavg)) * cosThetaI); // Energy conservation float R = MicrofacetDielectricReflectionAlbedoTable_eval( self->microfacetAlbedoTables, cosThetaO, self->eta, self->roughness) + self->fmsScale * (1.f - Eo); // add missing energy BSDF_EvalRes res; res.pdf = whPdf * rcp(4.f * cosThetaOH) * R; res.value = make_vec3f(F * D * G * rcp(4.f * cosThetaO) + fms); return res; } else { return make_BSDF_EvalRes_zero(); } } inline BSDF_SampleRes ThinMicrofacetDielectric_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss) { const varying ThinMicrofacetDielectric *uniform self = (const varying ThinMicrofacetDielectric *uniform)super; BSDF_SampleRes res; float cosThetaO = dot(wo, getN(super)); if (cosThetaO <= 0.f) return make_BSDF_SampleRes_zero(); // Energy conservation float Eo = MicrofacetAlbedoTable_eval( self->microfacetAlbedoTables, cosThetaO, self->roughness); float R = MicrofacetDielectricReflectionAlbedoTable_eval( self->microfacetAlbedoTables, cosThetaO, self->eta, self->roughness) + self->fmsScale * (1.f - Eo); // add missing energy if (ss < R) { // Reflection linear3f toGlobal = getFrame(super); linear3f toLocal = transposed(getFrame(super)); vec3f wo0 = toLocal * wo; // Sample the microfacet normal float whPdf; vec3f wh = toGlobal * sampleVisible(self->microfacet, wo0, whPdf, s); res.wi = reflect(wo, wh); float cosThetaI = dot(res.wi, getN(super)); if (cosThetaI <= 0.f) return make_BSDF_SampleRes_zero(); float cosThetaOH = dot(wo, wh); float cosThetaIH = dot(res.wi, wh); vec3f wi0 = toLocal * res.wi; float F = fresnelDielectric(cosThetaOH, self->eta); float G = evalG2(self->microfacet, wo0, wi0, cosThetaOH, cosThetaIH); // Energy compensation float Ei = MicrofacetAlbedoTable_eval( self->microfacetAlbedoTables, cosThetaI, self->roughness); float fms = self->fmsScale * ((1.f - Eo) * (1.f - Ei) * rcp((float)pi * (1.f - self->Eavg)) * cosThetaI); res.type = BSDF_GLOSSY_REFLECTION; res.pdf = whPdf * rcp(4.f * abs(cosThetaOH)) * R; res.weight = (make_vec3f(F * G * rcp_safe(evalG1(self->microfacet, wo0, cosThetaOH)) * rcp(R)) + (fms * rcp(res.pdf))); } else { // Transmission // Attenuation for crossing the slab once float length = rcp(refract(cosThetaO, self->eta)); // rcp(cosThetaO1) vec3f A = expf(self->attenuation * length); res.type = BSDF_SPECULAR_TRANSMISSION; res.wi = neg(wo); res.pdf = inf; res.weight = A; } return res; } inline void ThinMicrofacetDielectric_Constructor( varying ThinMicrofacetDielectric *uniform self, const MicrofacetAlbedoTables *uniform microfacetAlbedoTables, const varying linear3f *uniform frame, float eta, float roughness, float anisotropy, vec3f attenuation) { BSDF_Constructor(&self->super, expf(attenuation), BSDF_GLOSSY_REFLECTION | BSDF_SPECULAR_TRANSMISSION, BSDF_TYPE_THIN_MICROFACET_DIELECTRIC, frame); self->eta = eta; self->microfacet = make_GGXDistribution(roughnessToAlpha(roughness, anisotropy)); self->roughness = roughness; self->attenuation = attenuation; self->microfacetAlbedoTables = microfacetAlbedoTables; // Energy compensation self->Eavg = MicrofacetAlbedoTable_evalAvg(self->microfacetAlbedoTables, roughness); float Favg = fresnelDielectricAvg(eta); self->fmsScale = Favg * (1.f - self->Eavg) * rcp(1.f - Favg * self->Eavg); } inline varying BSDF *uniform ThinMicrofacetDielectric_create( uniform ShadingContext *uniform ctx, const MicrofacetAlbedoTables *uniform microfacetAlbedoTables, const varying linear3f *uniform frame, float eta, float roughness, float anisotropy, vec3f attenuation) { varying ThinMicrofacetDielectric *uniform self = (varying ThinMicrofacetDielectric * uniform) ShadingContext_alloc(ctx, sizeof(ThinMicrofacetDielectric)); ThinMicrofacetDielectric_Constructor(self, microfacetAlbedoTables, frame, eta, roughness, anisotropy, attenuation); return &self->super; } // Helper function for transparent shadow rays inline vec3f ThinMicrofacetDielectric_getTransparency( const MicrofacetAlbedoTables *uniform microfacetAlbedoTables, float cosThetaO, float eta, float roughness, vec3f attenuation) { // Energy conservation/compensation float Eavg = MicrofacetAlbedoTable_evalAvg(microfacetAlbedoTables, roughness); float Favg = fresnelDielectricAvg(eta); float fmsScale = Favg * (1.f - Eavg) * rcp(1.f - Favg * Eavg); float Eo = MicrofacetAlbedoTable_eval(microfacetAlbedoTables, cosThetaO, roughness); float R = MicrofacetDielectricReflectionAlbedoTable_eval( microfacetAlbedoTables, cosThetaO, eta, roughness) + fmsScale * (1.f - Eo); // add missing energy // Attenuation for crossing the slab once float length = rcp(refract(cosThetaO, eta)); // rcp(cosThetaO1) vec3f A = expf(attenuation * length); return (1.f - R) * A; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/Transmission.ih000066400000000000000000000017431456566705700252060ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "BSDF.ih" #include "ShadingContext.ih" OSPRAY_BEGIN_ISPC_NAMESPACE inline BSDF_SampleRes Transmission_sample( const varying BSDF *uniform self, const vec3f &wo, const vec2f &, float) { BSDF_SampleRes res; res.wi = neg(wo); res.pdf = inf; res.type = BSDF_SPECULAR_TRANSMISSION; res.weight = self->albedo; return res; } inline void Transmission_Constructor( varying BSDF *uniform self, const varying linear3f *uniform frame, vec3f T) { BSDF_Constructor( self, T, BSDF_SPECULAR_TRANSMISSION, BSDF_TYPE_TRANSMISSION, frame); } inline varying BSDF *uniform Transmission_create( uniform ShadingContext *uniform ctx, const varying linear3f *uniform frame, vec3f T) { varying BSDF *uniform self = (varying BSDF * uniform) ShadingContext_alloc(ctx, sizeof(BSDF)); Transmission_Constructor(self, frame, T); return self; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/bsdfs/Velvety.ih000066400000000000000000000034541456566705700241540ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "BSDF.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Velvety { BSDF super; /*! The falloff of horizon scattering. 0 no falloff, * and inf means maximum falloff. */ float f; }; inline BSDF_EvalRes Velvety_eval( const varying Velvety *uniform self, const vec3f &wo, const vec3f &wi) { BSDF_EvalRes res; const float cosThetaO = clamp(dot(wo, getN(&self->super))); const float cosThetaI = clamp(dot(wi, getN(&self->super))); const float sinThetaO = sqrt(1.0f - cosThetaO * cosThetaO); const float horizonScatter = pow(sinThetaO, self->f); res.pdf = cosineSampleHemispherePDF(cosThetaI); res.value = (horizonScatter * cosThetaI * (float)one_over_pi) * self->super.albedo; return res; } inline BSDF_SampleRes Velvety_sample( const varying Velvety *uniform self, const vec3f &wo, const vec2f &s, float) { BSDF_SampleRes res; const vec3f localDir = cosineSampleHemisphere(s); res.wi = getFrame(&self->super) * localDir; res.type = BSDF_DIFFUSE_REFLECTION; BSDF_EvalRes eval = Velvety_eval(self, wo, res.wi); res.pdf = eval.pdf; res.weight = eval.value * rcp(eval.pdf); return res; } inline void Velvety_Constructor(varying Velvety *uniform self, const varying linear3f *uniform frame, vec3f R, float f) { BSDF_Constructor( &self->super, R, BSDF_DIFFUSE_REFLECTION, BSDF_TYPE_VELVETY, frame); self->f = f; } inline varying BSDF *uniform Velvety_create(uniform ShadingContext *uniform ctx, const varying linear3f *uniform frame, vec3f R, float f) { varying Velvety *uniform self = (varying Velvety * uniform) ShadingContext_alloc(ctx, sizeof(Velvety)); Velvety_Constructor(self, frame, R, f); return &self->super; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/debug/000077500000000000000000000000001456566705700221535ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/render/debug/DebugRenderer.cpp000066400000000000000000000066131456566705700254020ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "DebugRenderer.h" #include "camera/Camera.h" #include "common/FeatureFlagsEnum.h" #include "common/World.h" #include "fb/FrameBuffer.h" #ifndef OSPRAY_TARGET_SYCL // ispc exports #include "render/debug/DebugRenderer_ispc.h" #else #include "DebugRenderer.ih" #endif namespace ospray { // Helper functions ///////////////////////////////////////////////////////// static ispc::DebugRendererType typeFromString(const std::string &name) { if (name == "rayDir") return ispc::DebugRendererType::RAY_DIR; else if (name == "eyeLight") return ispc::DebugRendererType::EYE_LIGHT; else if (name == "Ng") return ispc::DebugRendererType::NG; else if (name == "Ns") return ispc::DebugRendererType::NS; else if (name == "color") return ispc::DebugRendererType::COLOR; else if (name == "texCoord") return ispc::DebugRendererType::TEX_COORD; else if (name == "backfacing_Ng") return ispc::DebugRendererType::BACKFACING_NG; else if (name == "backfacing_Ns") return ispc::DebugRendererType::BACKFACING_NS; else if (name == "dPds") return ispc::DebugRendererType::DPDS; else if (name == "dPdt") return ispc::DebugRendererType::DPDT; else if (name == "primID") return ispc::DebugRendererType::PRIM_ID; else if (name == "geomID") return ispc::DebugRendererType::GEOM_ID; else if (name == "instID") return ispc::DebugRendererType::INST_ID; else if (name == "volume") return ispc::DebugRendererType::VOLUME; else return ispc::DebugRendererType::TEST_FRAME; } // DebugRenderer definitions //////////////////////////////////////////////// DebugRenderer::DebugRenderer(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device) {} std::string DebugRenderer::toString() const { return "ospray::DebugRenderer"; } void DebugRenderer::commit() { Renderer::commit(); const std::string method = getParam("method", "eyeLight"); getSh()->type = typeFromString(method); } AsyncEvent DebugRenderer::renderTasks(FrameBuffer *fb, Camera *camera, World *world, void *, const utility::ArrayView &taskIDs, bool wait) const { AsyncEvent event; auto *rendererSh = getSh(); auto *fbSh = fb->getSh(); auto *cameraSh = camera->getSh(); auto *worldSh = world->getSh(); const size_t numTasks = taskIDs.size(); #ifdef OSPRAY_TARGET_SYCL const uint32_t *taskIDsPtr = taskIDs.data(); event = device.getSyclQueue().submit([&](sycl::handler &cgh) { FeatureFlags ff = world->getFeatureFlags(); ff |= featureFlags; ff |= fb->getFeatureFlags(); ff |= camera->getFeatureFlags(); cgh.set_specialization_constant(ff); cgh.set_specialization_constant(rendererSh->type); cgh.parallel_for(fb->getDispatchRange(numTasks), [=](sycl::nd_item<3> taskIndex, sycl::kernel_handler kh) { ispc::FeatureFlagsHandler ffh(kh); ispc::DebugRenderer_renderTask(&rendererSh->super, fbSh, cameraSh, worldSh, taskIDsPtr, taskIndex, ffh); }); }); if (wait) event.wait_and_throw(); #else (void)wait; ispc::DebugRenderer_renderTasks( &rendererSh->super, fbSh, cameraSh, worldSh, taskIDs.data(), numTasks); #endif return event; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/debug/DebugRenderer.h000066400000000000000000000012711456566705700250420ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray #include "common/StructShared.h" #include "render/Renderer.h" // ispc shared #include "DebugRendererShared.h" namespace ospray { struct DebugRenderer : public AddStructShared { DebugRenderer(api::ISPCDevice &device); virtual ~DebugRenderer() override = default; std::string toString() const override; void commit() override; virtual AsyncEvent renderTasks(FrameBuffer *fb, Camera *camera, World *world, void *perFrameData, const utility::ArrayView &taskIDs, bool wait) const override; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/debug/DebugRenderer.ih000066400000000000000000000007251456566705700252160ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/FeatureFlags.ih" OSPRAY_BEGIN_ISPC_NAMESPACE #ifdef OSPRAY_TARGET_SYCL SYCL_EXTERNAL void DebugRenderer_renderTask(Renderer *uniform self, FrameBuffer *uniform fb, Camera *uniform camera, World *uniform world, const uint32 *uniform taskIDs, const sycl::nd_item<3> taskIndex, const uniform FeatureFlagsHandler &ffh); #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/debug/DebugRenderer.ispc000066400000000000000000000316271456566705700255610ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "camera/Camera.ih" #include "camera/CameraDispatch.ih" #include "common/FeatureFlagsEnum.h" #include "common/Intersect.ih" #include "common/World.ih" #include "fb/FrameBuffer.ih" #include "fb/FrameBufferDispatch.ih" #include "fb/RenderTaskDesc.ih" #include "math/random.ih" #include "pf/PixelFilterDispatch.ih" #include "render/Renderer.ih" #include "render/ScreenSample.ih" #include "rkcommon/utility/random.ih" #ifdef OSPRAY_ENABLE_VOLUMES #include "volume/VolumetricModel.ih" #include "volume/transferFunction/TransferFunctionDispatch.ih" #endif // c++ shared #include "DebugRendererShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE // common utility function, traces ray and handles default and background inline bool hitBackground(Renderer *uniform self, World *uniform world, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { traceRay(world, sample.ray, ffh); sample.z = sample.ray.t; sample.alpha = 1.f; sample.rgb = make_vec3f(Renderer_getBackground(self, sample.pos, ffh)); return noHit(sample.ray); } inline float eyeLight(varying ScreenSample &sample) { return 0.2f + 0.8f * abs(dot(normalize(sample.ray.Ng), sample.ray.dir)); } /* a simple test-frame renderer that doesn't even trace a ray, just returns a well-defined test frame (mostly useful for debugging whether frame buffers are properly set up etcpp */ static void DebugRenderer_testFrame( Renderer *uniform, World *uniform, varying ScreenSample &sample) { sample.rgb.x = ((sample.sampleID.x) % 256) / 255.f; sample.rgb.y = ((sample.sampleID.y) % 256) / 255.f; sample.rgb.z = ((sample.sampleID.x + sample.sampleID.y + sample.sampleID.z) % 256) / 255.f; sample.alpha = 1.f; sample.z = 1.f; } /* a simple test-frame renderer that doesn't even trace a ray, just returns the absolute of the ray direction */ static void DebugRenderer_rayDir( Renderer *uniform, World *uniform, varying ScreenSample &sample) { sample.rgb = absf(sample.ray.dir); sample.alpha = 1.f; sample.z = 1.f; } static void DebugRenderer_eyeLight(Renderer *uniform self, World *uniform world, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { if (hitBackground(self, world, sample, ffh)) { return; } sample.rgb = make_vec3f(eyeLight(sample)); } static void DebugRenderer_Ng(Renderer *uniform self, World *uniform world, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { if (hitBackground(self, world, sample, ffh)) return; DifferentialGeometry dg; postIntersect(world, self, dg, sample.ray, DG_NORMALIZE | DG_NG, ffh); sample.rgb = absf(dg.Ng); } static void DebugRenderer_Ns(Renderer *uniform self, World *uniform world, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { if (hitBackground(self, world, sample, ffh)) return; DifferentialGeometry dg; postIntersect(world, self, dg, sample.ray, DG_NORMALIZE | DG_NS, ffh); sample.rgb = absf(dg.Ns); } static void DebugRenderer_texCoord(Renderer *uniform self, World *uniform world, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { if (hitBackground(self, world, sample, ffh)) return; DifferentialGeometry dg; postIntersect(world, self, dg, sample.ray, DG_TEXCOORD, ffh); sample.rgb = abs(make_vec3f(dg.st.x, dg.st.y, 0.0f)); } static void DebugRenderer_dPds(Renderer *uniform self, World *uniform world, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { if (hitBackground(self, world, sample, ffh)) return; DifferentialGeometry dg; postIntersect(world, self, dg, sample.ray, DG_TANGENTS, ffh); sample.rgb = normalize(dg.dPds); if (sample.rgb.x < 0.f) sample.rgb.x = sample.rgb.x * -0.3f; if (sample.rgb.y < 0.f) sample.rgb.y = sample.rgb.y * -0.3f; if (sample.rgb.z < 0.f) sample.rgb.z = sample.rgb.z * -0.3f; } static void DebugRenderer_dPdt(Renderer *uniform self, World *uniform world, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { if (hitBackground(self, world, sample, ffh)) return; DifferentialGeometry dg; postIntersect(world, self, dg, sample.ray, DG_TANGENTS, ffh); sample.rgb = normalize(dg.dPdt); if (sample.rgb.x < 0.f) sample.rgb.x = sample.rgb.x * -0.3f; if (sample.rgb.y < 0.f) sample.rgb.y = sample.rgb.y * -0.3f; if (sample.rgb.z < 0.f) sample.rgb.z = sample.rgb.z * -0.3f; } static void DebugRenderer_vertexColor(Renderer *uniform self, World *uniform world, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { if (hitBackground(self, world, sample, ffh)) return; DifferentialGeometry dg; postIntersect(world, self, dg, sample.ray, DG_COLOR | DG_NS, ffh); sample.rgb = make_vec3f(dg.color) * abs(dot(normalize(sample.ray.dir), normalize(dg.Ns))); } static void DebugRenderer_primID(Renderer *uniform self, World *uniform world, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { if (hitBackground(self, world, sample, ffh)) return; sample.rgb = eyeLight(sample) * makeRandomColor(sample.ray.primID); } static void DebugRenderer_instID(Renderer *uniform self, World *uniform world, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { if (hitBackground(self, world, sample, ffh)) return; sample.rgb = eyeLight(sample) * makeRandomColor(sample.ray.instID); } static void DebugRenderer_geomID(Renderer *uniform self, World *uniform world, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { if (hitBackground(self, world, sample, ffh)) return; sample.rgb = eyeLight(sample) * makeRandomColor(sample.ray.geomID); } static void DebugRenderer_backfacing_Ng(Renderer *uniform self, World *uniform world, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { if (hitBackground(self, world, sample, ffh)) return; sample.rgb = make_vec3f(eyeLight(sample)); if (dot(sample.ray.Ng, sample.ray.dir) > 0.f) sample.rgb.y = 0.f; } static void DebugRenderer_backfacing_Ns(Renderer *uniform self, World *uniform world, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { if (hitBackground(self, world, sample, ffh)) return; DifferentialGeometry dg; postIntersect(world, self, dg, sample.ray, DG_NORMALIZE | DG_NS, ffh); const float c = dot(dg.Ns, sample.ray.dir); sample.rgb = make_vec3f(.2f + .8f * abs(c)); if (c > 0.f) sample.rgb.y = 0.f; } static void DebugRenderer_volume(Renderer *uniform self, FrameBuffer *uniform fb, World *uniform world, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { #ifdef OSPRAY_ENABLE_VOLUMES const uniform FeatureFlags ff = getFeatureFlags(ffh); if (!(ff.other & FFO_VOLUME_IN_SCENE)) { return; } LDSampler ldSamplerObj; varying LDSampler *uniform ldSampler = &ldSamplerObj; LDSampler_init(ldSampler, self->mathConstants, sample.sampleID.x + fb->size.x * sample.sampleID.y, sample.sampleID.z); vec3f &color = sample.rgb; float &alpha = sample.alpha; vec4f bgColor = Renderer_getBackground(self, sample.pos, ffh); color = make_vec3f(bgColor); alpha = bgColor.w; VolumeInterval vInterval; traceVolumeRay(world, sample.ray, vInterval); if (!hasInterval(vInterval)) { return; } VolumetricModel *varying model = vInterval.volumetricModel; Ray &ray = sample.ray; ray.t0 = vInterval.interval.lower; ray.t = vInterval.interval.upper; const float jitter = LDSampler_getFloat(ldSampler, 0); uniform uint8 intervalIteratorBuffer[VKL_MAX_INTERVAL_ITERATOR_SIZE]; foreach_unique (m in model) { Volume *uniform volume = m->volume; float time = 0.5f; VKLIntervalIterator intervalIterator = vklInitIntervalIteratorV(&m->vklIntervalContext, (varying vkl_vec3f *)&ray.org, (varying vkl_vec3f *)&ray.dir, (varying vkl_range1f *)&vInterval.interval, #ifndef OSPRAY_TARGET_SYCL & #endif time, (void *uniform)intervalIteratorBuffer #ifdef OSPRAY_TARGET_SYCL , ff.volume #endif ); VKLInterval interval; static const uniform float samplingRate = 0.5f; while (vklIterateIntervalV(intervalIterator, &interval #ifdef OSPRAY_TARGET_SYCL , ff.volume #endif ) && alpha < 0.99f) { const float nominalSamplingDt = interval.nominalDeltaT / samplingRate; // initial sub interval, based on our renderer-defined sampling rate // and the volume's nominal dt box1f subInterval = make_box1f(interval.tRange.lower, min(interval.tRange.lower + nominalSamplingDt, interval.tRange.upper)); while (subInterval.upper - subInterval.lower > 0.f && alpha < 0.99f) { ray.t0 = subInterval.lower + jitter * (subInterval.upper - subInterval.lower); const float dt = subInterval.upper - subInterval.lower; // Get volume sample vec3f p = ray.org + ray.t0 * ray.dir; const float sample = vklComputeSampleV(&volume->vklSampler, (const varying vkl_vec3f *uniform) & p #ifdef OSPRAY_TARGET_SYCL , 0, time, ff.volume #endif ); if (!isnan(sample)) { vec4f sampleColorOpacity = TransferFunction_dispatch_get(m->transferFunction, sample); const float clampedOpacity = clamp(sampleColorOpacity.w * dt); color = color + ((1.f - alpha) * clampedOpacity * make_vec3f(sampleColorOpacity)); alpha = alpha + ((1.f - alpha) * clampedOpacity); } // compute next sub interval subInterval.lower = subInterval.upper; subInterval.upper = min(subInterval.lower + nominalSamplingDt, interval.tRange.upper); } } } #else (void)self; (void)fb; (void)world; (void)sample; (void)ffh; #endif } static void DebugRenderer_renderSample(Renderer *uniform _self, FrameBuffer *uniform fb, World *uniform world, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { #ifdef OSPRAY_TARGET_SYCL const DebugRendererType debugType = ffh.kernel_handler.get_specialization_constant(); #else DebugRenderer *uniform self = (DebugRenderer * uniform) _self; const DebugRendererType debugType = self->type; #endif switch (debugType) { case TEST_FRAME: DebugRenderer_testFrame(_self, world, sample); break; case RAY_DIR: DebugRenderer_rayDir(_self, world, sample); break; case EYE_LIGHT: DebugRenderer_eyeLight(_self, world, sample, ffh); break; case NG: DebugRenderer_Ng(_self, world, sample, ffh); break; case NS: DebugRenderer_Ns(_self, world, sample, ffh); break; case COLOR: DebugRenderer_vertexColor(_self, world, sample, ffh); break; case TEX_COORD: DebugRenderer_texCoord(_self, world, sample, ffh); break; case DPDS: DebugRenderer_dPds(_self, world, sample, ffh); break; case DPDT: DebugRenderer_dPdt(_self, world, sample, ffh); break; case PRIM_ID: DebugRenderer_primID(_self, world, sample, ffh); break; case GEOM_ID: DebugRenderer_geomID(_self, world, sample, ffh); break; case INST_ID: DebugRenderer_instID(_self, world, sample, ffh); break; case BACKFACING_NG: DebugRenderer_backfacing_Ng(_self, world, sample, ffh); break; case BACKFACING_NS: DebugRenderer_backfacing_Ns(_self, world, sample, ffh); break; case VOLUME: DebugRenderer_volume(_self, fb, world, sample, ffh); break; default: DebugRenderer_testFrame(_self, world, sample); break; }; } #define renderSampleFn DebugRenderer_renderSample #include "render/RendererRenderTaskFn.inl" #undef renderSampleFn #ifdef OSPRAY_TARGET_SYCL SYCL_EXTERNAL void DebugRenderer_renderTask(Renderer *uniform self, FrameBuffer *uniform fb, Camera *uniform camera, World *uniform world, const uint32 *uniform taskIDs, const sycl::nd_item<3> taskIndex, const uniform FeatureFlagsHandler &ffh) { Renderer_default_renderTask(self, fb, camera, world, taskIDs, taskIndex, ffh); } #else export void DebugRenderer_renderTasks(void *uniform _self, void *uniform _fb, void *uniform _camera, void *uniform _world, void *uniform _taskIDs, uniform uint32 numTasks) { Renderer *uniform self = (Renderer * uniform) _self; FrameBuffer *uniform fb = (FrameBuffer * uniform) _fb; Camera *uniform camera = (Camera * uniform) _camera; World *uniform world = (World * uniform) _world; const uint32 *uniform taskIDs = (const uint32 *uniform)_taskIDs; uniform FeatureFlagsHandler ffh; launch[numTasks] Renderer_default_renderTask( self, fb, camera, world, taskIDs, ffh); sync; } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/debug/DebugRendererShared.h000066400000000000000000000012331456566705700261670ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/RendererShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus enum DebugRendererType { TEST_FRAME, RAY_DIR, EYE_LIGHT, NG, NS, COLOR, TEX_COORD, DPDS, DPDT, PRIM_ID, GEOM_ID, INST_ID, BACKFACING_NG, BACKFACING_NS, VOLUME }; struct DebugRenderer { Renderer super; DebugRendererType type; #ifdef __cplusplus DebugRenderer() : type(TEST_FRAME) {} #endif }; #ifdef __cplusplus } #ifdef OSPRAY_TARGET_SYCL inline constexpr sycl::specialization_id debugRendererType; #endif #endif RenderKit-ospray-f2a61c2/modules/cpu/render/materials/000077500000000000000000000000001456566705700230465ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Alloy.cpp000066400000000000000000000021431456566705700246320ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Alloy.h" #ifndef OSPRAY_TARGET_SYCL // ispc #include "render/materials/Alloy_ispc.h" #endif namespace ospray { namespace pathtracer { Alloy::Alloy(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFO_MATERIAL_ALLOY) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.getBSDF = reinterpret_cast(ispc::Alloy_getBSDF_addr()); #endif } std::string Alloy::toString() const { return "ospray::pathtracer::Alloy"; } //! \brief commit the material's parameters void Alloy::commit() { MaterialParam3f color = getMaterialParam3f("color", vec3f(0.9f)); MaterialParam3f edgeColor = getMaterialParam3f("edgeColor", vec3f(1.f)); MaterialParam1f roughness = getMaterialParam1f("roughness", 0.1f); getSh()->color = color.factor; getSh()->colorMap = color.tex; getSh()->edgeColor = edgeColor.factor; getSh()->edgeColorMap = edgeColor.tex; getSh()->roughness = roughness.factor; getSh()->roughnessMap = roughness.tex; } } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Alloy.h000066400000000000000000000006471456566705700243060ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" // ispc shared #include "AlloyShared.h" namespace ospray { namespace pathtracer { struct Alloy : public AddStructShared { Alloy(api::ISPCDevice &device); virtual std::string toString() const override; virtual void commit() override; }; } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Alloy.ih000066400000000000000000000017471456566705700244610ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/bsdfs/BSDF.ih" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Material; struct ShadingContext; struct DifferentialGeometry; struct Ray; struct Medium; SYCL_EXTERNAL const varying BSDF *uniform Alloy_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL BSDF_EvalRes AlloyRough_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi); SYCL_EXTERNAL BSDF_SampleRes AlloyRough_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss); SYCL_EXTERNAL BSDF_SampleRes Alloy_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Alloy.ispc000066400000000000000000000046111456566705700250100ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Alloy.ih" #include "render/Material.ih" #include "render/bsdfs/Conductor.ih" #include "render/bsdfs/MicrofacetConductor.ih" #include "texture/TextureParam.ih" // c++ shared #include "AlloyShared.h" /////////////////////////////////////////////////////////////////////////////// // Implementation OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL const varying BSDF *uniform Alloy_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &, const Medium &, const uniform FeatureFlagsHandler &) { const uniform Alloy *uniform self = (const uniform Alloy *uniform)super; varying linear3f *uniform shadingframe = LinearSpace3f_create(ctx, frame(dg.Ns)); const vec3f color = self->color * make_vec3f(dg.color) * get3f(self->colorMap, dg, make_vec3f(1.f)); const vec3f edgeColor = self->edgeColor * get3f(self->edgeColorMap, dg, make_vec3f(1.f)); Fresnel *uniform fresnel = FresnelSchlick_create(ctx, color, edgeColor); varying BSDF *uniform bsdf; if (self->roughness == 0.0f) { bsdf = Conductor_create(ctx, shadingframe, fresnel); bsdf->bsdfType = BSDF_TYPE_ALLOY; } else { bsdf = MicrofacetConductor_create(ctx, super->microfacetAlbedoTables, shadingframe, fresnel, self->roughness * get1f(self->roughnessMap, dg, 1.f), 0.f); bsdf->bsdfType = BSDF_TYPE_ALLOY_ROUGH; } return bsdf; } SYCL_EXTERNAL BSDF_EvalRes AlloyRough_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi) { return MicrofacetConductor_eval( (const varying MicrofacetConductor *uniform)super, wo, wi); } SYCL_EXTERNAL BSDF_SampleRes AlloyRough_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss) { return MicrofacetConductor_sample( (const varying MicrofacetConductor *uniform)super, wo, s, ss); } SYCL_EXTERNAL BSDF_SampleRes Alloy_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss) { return Conductor_sample(super, wo, s, ss); } /////////////////////////////////////////////////////////////////////////////// // External API export void *uniform Alloy_getBSDF_addr() { return (void *uniform)Alloy_getBSDF; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/AlloyShared.h000066400000000000000000000012771456566705700254350ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/MaterialShared.h" #include "texture/TextureParamShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Alloy { Material super; vec3f color; // reflectivity at normal incidence (0 deg) TextureParam colorMap; vec3f edgeColor; // reflectivity at grazing angle (90 deg) TextureParam edgeColorMap; float roughness; // in [0, 1]; 0==ideally smooth (mirror) TextureParam roughnessMap; #ifdef __cplusplus Alloy() : color(.9f), edgeColor(1.f), roughness(.1f) { super.type = ispc::MATERIAL_TYPE_ALLOY; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/materials/CarPaint.cpp000066400000000000000000000067701456566705700252650ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "CarPaint.h" #ifndef OSPRAY_TARGET_SYCL // ispc #include "render/materials/CarPaint_ispc.h" #endif namespace ospray { namespace pathtracer { CarPaint::CarPaint(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFO_MATERIAL_CARPAINT) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.getBSDF = reinterpret_cast( ispc::CarPaint_getBSDF_addr()); #endif } std::string CarPaint::toString() const { return "ospray::pathtracer::CarPaint"; } void CarPaint::commit() { MaterialParam3f baseColor = getMaterialParam3f("baseColor", vec3f(0.8f)); MaterialParam1f roughness = getMaterialParam1f("roughness", 0.f); MaterialParam1f normal = getMaterialParam1f("normal", 1.f); bool useFlakeColor = findParam("flakeColor") != nullptr; MaterialParam3f flakeColor = getMaterialParam3f("flakeColor", vec3f(0.f)); MaterialParam1f flakeScale = getMaterialParam1f("flakeScale", 100.f); MaterialParam1f flakeDensity = getMaterialParam1f("flakeDensity", 0.f); MaterialParam1f flakeSpread = getMaterialParam1f("flakeSpread", 0.3f); MaterialParam1f flakeJitter = getMaterialParam1f("flakeJitter", 0.75f); MaterialParam1f flakeRoughness = getMaterialParam1f("flakeRoughness", 0.3f); MaterialParam1f coat = getMaterialParam1f("coat", 1.f); MaterialParam1f coatIor = getMaterialParam1f("coatIor", 1.5f); MaterialParam3f coatColor = getMaterialParam3f("coatColor", vec3f(1.f)); MaterialParam1f coatThickness = getMaterialParam1f("coatThickness", 1.f); MaterialParam1f coatRoughness = getMaterialParam1f("coatRoughness", 0.f); MaterialParam1f coatNormal = getMaterialParam1f("coatNormal", 1.f); MaterialParam3f flipflopColor = getMaterialParam3f("flipflopColor", vec3f(1.f)); MaterialParam1f flipflopFalloff = getMaterialParam1f("flipflopFalloff", 1.f); getSh()->baseColor = baseColor.factor; getSh()->baseColorMap = baseColor.tex; getSh()->roughness = roughness.factor; getSh()->roughnessMap = roughness.tex; getSh()->normal = normal.factor; getSh()->normalMap = normal.tex; getSh()->normalRot = normal.rot; getSh()->useFlakeColor = useFlakeColor; getSh()->flakeColor = flakeColor.factor; getSh()->flakeColorMap = flakeColor.tex; getSh()->flakeScale = flakeScale.factor; getSh()->flakeScaleMap = flakeScale.tex; getSh()->flakeDensity = flakeDensity.factor; getSh()->flakeDensityMap = flakeDensity.tex; getSh()->flakeSpread = flakeSpread.factor; getSh()->flakeSpreadMap = flakeSpread.tex; getSh()->flakeJitter = flakeJitter.factor; getSh()->flakeJitterMap = flakeJitter.tex; getSh()->flakeRoughness = flakeRoughness.factor; getSh()->flakeRoughnessMap = flakeRoughness.tex; getSh()->coat = coat.factor; getSh()->coatMap = coat.tex; getSh()->coatIor = coatIor.factor; getSh()->coatIorMap = coatIor.tex; getSh()->coatColor = coatColor.factor; getSh()->coatColorMap = coatColor.tex; getSh()->coatThickness = coatThickness.factor; getSh()->coatThicknessMap = coatThickness.tex; getSh()->coatRoughness = coatRoughness.factor; getSh()->coatRoughnessMap = coatRoughness.tex; getSh()->coatNormal = coatNormal.factor; getSh()->coatNormalMap = coatNormal.tex; getSh()->coatNormalRot = coatNormal.rot; getSh()->flipflopColor = flipflopColor.factor; getSh()->flipflopColorMap = flipflopColor.tex; getSh()->flipflopFalloff = flipflopFalloff.factor; getSh()->flipflopFalloffMap = flipflopFalloff.tex; } } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/CarPaint.h000066400000000000000000000006631456566705700247250ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" // ispc shared #include "CarPaintShared.h" namespace ospray { namespace pathtracer { struct CarPaint : public AddStructShared { CarPaint(api::ISPCDevice &device); virtual std::string toString() const override; virtual void commit() override; }; } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/CarPaint.ih000066400000000000000000000015671456566705700251020ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/bsdfs/BSDF.ih" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Material; struct ShadingContext; struct DifferentialGeometry; struct Ray; struct Medium; SYCL_EXTERNAL __noinline const varying BSDF *uniform CarPaint_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL __noinline BSDF_EvalRes CarPaint_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi); SYCL_EXTERNAL __noinline BSDF_SampleRes CarPaint_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/CarPaint.ispc000066400000000000000000000266231456566705700254400ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "CarPaint.ih" #include "common/Ray.ih" #include "render/Material.ih" #include "render/bsdfs/Conductor.ih" #include "render/bsdfs/DielectricLayer.ih" #include "render/bsdfs/Lambert.ih" #include "render/bsdfs/MicrofacetConductor.ih" #include "render/bsdfs/MicrofacetDielectricLayer.ih" #include "render/bsdfs/OrenNayar.ih" #include "render/bsdfs/PassthroughLayer.ih" #include "render/shaders/Flakes.ih" #include "texture/TextureParam.ih" // c++ shared #include "CarPaintShared.h" /////////////////////////////////////////////////////////////////////////////// // Implementation OSPRAY_BEGIN_ISPC_NAMESPACE struct CarPaint_BSDF { BSDF root; MicrofacetDielectricLayer dielectricLayer; int flakeMask; MicrofacetConductor conductor; OrenNayar baseDiffuse; }; SYCL_EXTERNAL __noinline const varying BSDF *uniform CarPaint_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &ray, const Medium &, const uniform FeatureFlagsHandler &) { const uniform CarPaint *uniform self = (const uniform CarPaint *uniform)super; varying linear3f *uniform frame = LinearSpace3f_create(ctx, makeShadingFrame(dg, self->normalMap, self->normalRot, self->normal)); // Allocate memory and initialize material BSDF varying CarPaint_BSDF *uniform bsdf = (varying CarPaint_BSDF * uniform) ShadingContext_alloc(ctx, sizeof(CarPaint_BSDF)); const float flakeDensity = clamp(self->flakeDensity * get1f(self->flakeDensityMap, dg, 1.f)); int flakeMask = 0; varying linear3f *uniform flakeFrame = NULL; varying BSDF *varying substrate = NULL; // metallic flakes in the clear coat layer if (flakeDensity > EPS) { const float flakeScale = max(self->flakeScale * get1f(self->flakeScaleMap, dg, 1.f), 0.f); const float flakeSpread = max(self->flakeSpread * get1f(self->flakeSpreadMap, dg, 1.f), 0.f); const float flakeJitter = clamp(self->flakeJitter * get1f(self->flakeJitterMap, dg, 1.f)); Flakes flakes; flakes.scale = flakeScale; flakes.density = flakeDensity; flakes.spread = flakeSpread; flakes.jitter = flakeJitter; const vec3f flakeN = Flakes_eval(flakes, dg.P, flakeMask); if (flakeMask) { flakeFrame = LinearSpace3f_create(ctx, makeShadingFrame(dg, flakeN)); Fresnel *uniform flakeFresnel; if (self->useFlakeColor) { const vec3f r = clamp( self->flakeColor * get3f(self->flakeColorMap, dg, make_vec3f(1.f))); const vec3f g = make_vec3f(1.f); flakeFresnel = FresnelSchlick_create(ctx, r, g); } else { // flakes are made of aluminum const uniform vec3f flakeEta = make_vec3f(1.69700277f, 0.879832864f, 0.5301736f); const uniform vec3f flakeK = make_vec3f(9.30200672f, 6.27604008f, 4.89433956f); flakeFresnel = FresnelConductorRGBUniform_create(ctx, flakeEta, flakeK); } if (self->flakeRoughness < EPS) Conductor_Constructor((varying Conductor * uniform) & bsdf->conductor, flakeFrame, flakeFresnel); else MicrofacetConductor_Constructor(&bsdf->conductor, super->microfacetAlbedoTables, flakeFrame, flakeFresnel, max(self->flakeRoughness * get1f(self->flakeRoughnessMap, dg, 1.f), 0.f), 0.f); substrate = &bsdf->conductor.super; } } // base diffuse layer if (!flakeMask) { const vec3f baseColor = clamp(self->baseColor * get3f(self->baseColorMap, dg, make_vec3f(1.f)) * make_vec3f(dg.color)); if (self->roughness < EPS) Lambert_Constructor( (varying BSDF * uniform) & bsdf->baseDiffuse, frame, baseColor); else OrenNayar_Constructor(&bsdf->baseDiffuse, frame, baseColor, max(self->roughness * get1f(self->roughnessMap, dg, 1.f), 0.f)); substrate = &bsdf->baseDiffuse.super; } bsdf->flakeMask = flakeMask; // clear coat layer if ((self->coat > EPS) && (abs(self->coatIor - 1.f) > EPS || valid(self->coatIorMap))) { const float coat = max(self->coat * get1f(self->coatMap, dg, 1.f), 0.f); float coatIor = self->coatIor * get1f(self->coatIorMap, dg, 1.f); if (coatIor < 1.f) coatIor = rcp(coatIor); coatIor = clamp(coatIor, 1.f, 3.f); // clamp to common range due to LUTs // compute the final coat color const vec3f coatColor = clamp(self->coatColor * get3f(self->coatColorMap, dg, make_vec3f(1.f))); vec3f coatFinalColor = coatColor; if (flakeMask) { const float flipflopFalloff = clamp( self->flipflopFalloff * get1f(self->flipflopFalloffMap, dg, 1.f)); if (flipflopFalloff < 1.f - EPS) { // pearlescent flakes const vec3f flipflopColor = clamp(self->flipflopColor * get3f(self->flipflopColorMap, dg, make_vec3f(1.f))); const float cosThetaO = max(-dot(ray.dir, flakeFrame->vz), 0.f); const float weight = pow(1.f - cosThetaO, rcp(1.f - flipflopFalloff)); // use Schlick for the blending weight coatFinalColor = lerp(weight, coatColor, flipflopColor); } } const float coatThickness = max(self->coatThickness * get1f(self->coatThicknessMap, dg, 1.f), 0.f); varying linear3f *uniform coatFrame = LinearSpace3f_create(ctx, makeShadingFrame( dg, self->coatNormalMap, self->coatNormalRot, self->coatNormal)); if (self->coatRoughness < EPS) { DielectricLayer_Constructor( (varying DielectricLayer * uniform) & bsdf->dielectricLayer, coatFrame, substrate, rcp(coatIor), coatFinalColor, coatThickness, coat); } else { MicrofacetDielectricLayer_Constructor(&bsdf->dielectricLayer, super->microfacetAlbedoTables, coatFrame, substrate, rcp(coatIor), coatFinalColor, coatThickness, max(self->coatRoughness * get1f(self->coatRoughnessMap, dg, 1.f), 0.f), 0.f, coat); } } else { PassthroughLayer_Constructor( (varying PassthroughLayer * uniform) & bsdf->dielectricLayer, substrate); } bsdf->root = bsdf->dielectricLayer.super; bsdf->root.bsdfType = BSDF_TYPE_CARPAINT; return &bsdf->root; } // Conductor BSDF inline BSDF_EvalRes ConductorBSDF_eval( const varying MicrofacetConductor *uniform self, const vec3f &wo, const vec3f &wi) { if (self->super.bsdfType == BSDF_TYPE_MICROFACET_CONDUCTOR) return MicrofacetConductor_eval(self, wo, wi); else return make_BSDF_EvalRes_zero(); } inline BSDF_SampleRes ConductorBSDF_sample( const varying MicrofacetConductor *uniform self, const vec3f &wo, const vec2f &s, float ss) { if (self->super.bsdfType == BSDF_TYPE_MICROFACET_CONDUCTOR) return MicrofacetConductor_sample(self, wo, s, ss); else return Conductor_sample(&self->super, wo, s, ss); } // Diffuse BSDF inline BSDF_EvalRes DiffuseBSDF_eval( const varying OrenNayar *uniform self, const vec3f &wo, const vec3f &wi) { if (self->super.bsdfType == BSDF_TYPE_OREN_NAYAR) return OrenNayar_eval(&self->super, wo, wi); else return Lambert_eval(&self->super, wo, wi); } inline BSDF_SampleRes DiffuseBSDF_sample(const varying OrenNayar *uniform self, const vec3f &wo, const vec2f &s, float ss) { if (self->super.bsdfType == BSDF_TYPE_OREN_NAYAR) return OrenNayar_sample(&self->super, wo, s, ss); else return Lambert_sample(&self->super, wo, s, ss); } // Base layer BSDF __noinline BSDF_EvalRes BaseBSDF_eval( const varying CarPaint_BSDF *uniform self, const vec3f &wo, const vec3f &wi) { if (self->flakeMask) { return ConductorBSDF_eval(&self->conductor, wo, wi); } else { return DiffuseBSDF_eval(&self->baseDiffuse, wo, wi); } } __noinline BSDF_SampleRes BaseBSDF_sample( const varying CarPaint_BSDF *uniform self, const vec3f &wo, const vec2f &s, float ss) { if (self->flakeMask) { return ConductorBSDF_sample(&self->conductor, wo, s, ss); } else { return DiffuseBSDF_sample(&self->baseDiffuse, wo, s, ss); } } // DielectricLayer BSDF inline BSDF_EvalRes DielectricLayerBSDF_eval( const varying CarPaint_BSDF *uniform self, const vec3f &wo, const vec3f &wi) { BSDFScatteringType scatteringType = (self->flakeMask) ? self->conductor.super.scatteringType : self->baseDiffuse.super.scatteringType; DIELECTRICLAYER_EVAL( self->dielectricLayer, scatteringType, self, BaseBSDF_eval); return DIELECTRICLAYER_EVAL_GET(); } inline BSDF_SampleRes DielectricLayerBSDF_sample( const varying CarPaint_BSDF *uniform self, const vec3f &wo, const vec2f &s, float ss) { BSDFScatteringType scatteringType = (self->flakeMask) ? self->conductor.super.scatteringType : self->baseDiffuse.super.scatteringType; DIELECTRICLAYER_SAMPLE( self->dielectricLayer, scatteringType, self, BaseBSDF_sample); return DIELECTRICLAYER_SAMPLE_GET(); } // MicrofacetDielectricLayer BSDF inline BSDF_EvalRes MicrofacetDielectricLayerBSDF_eval( const varying CarPaint_BSDF *uniform self, const vec3f &wo, const vec3f &wi) { BSDFScatteringType scatteringType = (self->flakeMask) ? self->conductor.super.scatteringType : self->baseDiffuse.super.scatteringType; MICROFACETDIELECTRICLAYER_EVAL( self->dielectricLayer, scatteringType, self, BaseBSDF_eval); return MICROFACETDIELECTRICLAYER_EVAL_GET(); } inline BSDF_SampleRes MicrofacetDielectricLayerBSDF_sample( const varying CarPaint_BSDF *uniform self, const vec3f &wo, const vec2f &s, float ss) { BSDFScatteringType scatteringType = (self->flakeMask) ? self->conductor.super.scatteringType : self->baseDiffuse.super.scatteringType; MICROFACETDIELECTRICLAYER_SAMPLE(self->dielectricLayer, scatteringType, self, BaseBSDF_eval, BaseBSDF_sample); return MICROFACETDIELECTRICLAYER_SAMPLE_GET(); } // CarPaint BSDF SYCL_EXTERNAL __noinline BSDF_EvalRes CarPaint_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi) { const varying CarPaint_BSDF *uniform self = (const varying CarPaint_BSDF *uniform)super; // Skip dielectric layer if no clear coat if (self->dielectricLayer.weight < EPS) return BaseBSDF_eval(self, wo, wi); if (self->dielectricLayer.super.bsdfType == BSDF_TYPE_MICROFACET_DIELECTRIC_LAYER) return MicrofacetDielectricLayerBSDF_eval(self, wo, wi); else return DielectricLayerBSDF_eval(self, wo, wi); } SYCL_EXTERNAL __noinline BSDF_SampleRes CarPaint_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss) { const varying CarPaint_BSDF *uniform self = (const varying CarPaint_BSDF *uniform)super; // Skip dielectric layer if no clear coat if (self->dielectricLayer.weight < EPS) return BaseBSDF_sample(self, wo, s, ss); if (self->dielectricLayer.super.bsdfType == BSDF_TYPE_MICROFACET_DIELECTRIC_LAYER) return MicrofacetDielectricLayerBSDF_sample(self, wo, s, ss); else return DielectricLayerBSDF_sample(self, wo, s, ss); } /////////////////////////////////////////////////////////////////////////////// // External API export void *uniform CarPaint_getBSDF_addr() { return (void *uniform)CarPaint_getBSDF; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/CarPaintShared.h000066400000000000000000000037541456566705700260600ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/MaterialShared.h" #include "texture/TextureParamShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct CarPaint { Material super; vec3f baseColor; TextureParam baseColorMap; float roughness; TextureParam roughnessMap; float normal; // scale TextureParam normalMap; linear2f normalRot; bool useFlakeColor; // if disabled, flakes are Aluminium vec3f flakeColor; TextureParam flakeColorMap; float flakeScale; TextureParam flakeScaleMap; float flakeDensity; TextureParam flakeDensityMap; float flakeSpread; TextureParam flakeSpreadMap; float flakeJitter; TextureParam flakeJitterMap; float flakeRoughness; TextureParam flakeRoughnessMap; // dielectric clear coat reflectivity in [0, 1] float coat; TextureParam coatMap; // dielectric clear coat index of refraction in [1, 3] float coatIor; TextureParam coatIorMap; float coatThickness; TextureParam coatThicknessMap; float coatRoughness; TextureParam coatRoughnessMap; float coatNormal; // scale TextureParam coatNormalMap; linear2f coatNormalRot; vec3f coatColor; TextureParam coatColorMap; vec3f flipflopColor; TextureParam flipflopColorMap; float flipflopFalloff; TextureParam flipflopFalloffMap; #ifdef __cplusplus CarPaint() : baseColor(0.8f), roughness(0.f), normal(1.f), normalRot(one), useFlakeColor(false), flakeColor(0.f), flakeScale(0.f), flakeDensity(0.f), flakeSpread(0.f), flakeJitter(0.f), flakeRoughness(0.f), coat(1.f), coatIor(1.5f), coatThickness(1.f), coatRoughness(0.f), coatNormal(1.f), coatNormalRot(one), coatColor(1.f), flipflopColor(1.f), flipflopFalloff(1.f) { super.type = ispc::MATERIAL_TYPE_CARPAINT; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Glass.cpp000066400000000000000000000037721456566705700246340ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Glass.h" #ifndef OSPRAY_TARGET_SYCL // ispc #include "render/materials/Glass_ispc.h" #endif namespace ospray { namespace pathtracer { Glass::Glass(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFO_MATERIAL_GLASS) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.getBSDF = reinterpret_cast(ispc::Glass_getBSDF_addr()); getSh()->super.getTransparency = reinterpret_cast( ispc::Glass_getTransparency_addr()); getSh()->super.selectNextMedium = reinterpret_cast( ispc::Glass_selectNextMedium_addr()); #endif } std::string Glass::toString() const { return "ospray::pathtracer::Glass"; } void Glass::commit() { const float etaInside = getParam("etaInside", getParam("eta", 1.5f)); const float etaOutside = getParam("etaOutside", 1.f); const vec3f &attenuationColorInside = getParam("attenuationColorInside", getParam("attenuationColor", vec3f(1.f))); const vec3f &attenuationColorOutside = getParam("attenuationColorOutside", vec3f(1.f)); const float attenuationDistance = getParam("attenuationDistance", 1.0f); getSh()->mediumInside.ior = etaInside; getSh()->mediumInside.attenuation = vec3f(log(attenuationColorInside.x), log(attenuationColorInside.y), log(attenuationColorInside.z)) / std::max(attenuationDistance, EPS); getSh()->mediumOutside.ior = etaOutside; getSh()->mediumOutside.attenuation = vec3f(log(attenuationColorOutside.x), log(attenuationColorOutside.y), log(attenuationColorOutside.z)) / std::max(attenuationDistance, EPS); } } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Glass.h000066400000000000000000000006471456566705700242770ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" // ispc shared #include "GlassShared.h" namespace ospray { namespace pathtracer { struct Glass : public AddStructShared { Glass(api::ISPCDevice &device); virtual std::string toString() const override; virtual void commit() override; }; } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Glass.ih000066400000000000000000000021001456566705700244320ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/bsdfs/BSDF.ih" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Material; struct ShadingContext; struct DifferentialGeometry; struct Ray; struct Medium; SYCL_EXTERNAL const varying BSDF *uniform Glass_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL vec3f Glass_getTransparency(const uniform Material *uniform super, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL void Glass_selectNextMedium(const uniform Material *uniform super, const DifferentialGeometry &dg, Medium ¤tMedium); SYCL_EXTERNAL BSDF_SampleRes Glass_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Glass.ispc000066400000000000000000000050531456566705700250020ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Glass.ih" #include "Medium.ih" #include "common/Ray.ih" #include "render/Material.ih" #include "render/bsdfs/RobustDielectric.ih" // c++ shared #include "GlassShared.h" /////////////////////////////////////////////////////////////////////////////// // Implementation OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL const varying BSDF *uniform Glass_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &, const Medium ¤tMedium, const uniform FeatureFlagsHandler &) { uniform const Glass *uniform self = (uniform const Glass *uniform)super; float eta = eq(currentMedium, self->mediumOutside) ? self->mediumOutside.ior * rcp(self->mediumInside.ior) : self->mediumInside.ior * rcp(self->mediumOutside.ior); varying BSDF *uniform bsdf = RobustDielectric_create(ctx, dg, eta); bsdf->bsdfType = BSDF_TYPE_GLASS; return bsdf; } SYCL_EXTERNAL vec3f Glass_getTransparency( const uniform Material *uniform material, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &) { const uniform Glass *uniform self = (const uniform Glass *uniform)material; float eta = eq(currentMedium, self->mediumOutside) ? self->mediumOutside.ior * rcp(self->mediumInside.ior) : self->mediumInside.ior * rcp(self->mediumOutside.ior); float cosThetaO = max(-dot(ray.dir, dg.Ns), 0.0f); return make_vec3f(1.0f - fresnelDielectric(cosThetaO, eta)); } SYCL_EXTERNAL void Glass_selectNextMedium(const uniform Material *uniform super, const DifferentialGeometry &, Medium ¤tMedium) { const uniform Glass *uniform self = (const uniform Glass *uniform)super; if (eq(currentMedium, self->mediumOutside)) currentMedium = self->mediumInside; else currentMedium = self->mediumOutside; } SYCL_EXTERNAL BSDF_SampleRes Glass_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss) { return RobustDielectric_sample(super, wo, s, ss); } /////////////////////////////////////////////////////////////////////////////// // External API export void *uniform Glass_getBSDF_addr() { return (void *uniform)Glass_getBSDF; } export void *uniform Glass_getTransparency_addr() { return (void *uniform)Glass_getTransparency; } export void *uniform Glass_selectNextMedium_addr() { return (void *uniform)Glass_selectNextMedium; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/GlassShared.h000066400000000000000000000006741456566705700254260ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "MediumShared.h" #include "render/MaterialShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Glass { Material super; Medium mediumInside; Medium mediumOutside; #ifdef __cplusplus Glass() { super.type = ispc::MATERIAL_TYPE_GLASS; } #endif }; #ifdef __cplusplus } // namespace ispc #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Luminous.cpp000066400000000000000000000022211456566705700253620ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Luminous.h" #ifndef OSPRAY_TARGET_SYCL // ispc #include "render/materials/Luminous_ispc.h" #endif namespace ospray { namespace pathtracer { Luminous::Luminous(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFO_MATERIAL_LUMINOUS) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.getBSDF = reinterpret_cast( ispc::Luminous_getBSDF_addr()); getSh()->super.getTransparency = reinterpret_cast( ispc::Luminous_getTransparency_addr()); #endif } std::string Luminous::toString() const { return "ospray::pathtracer::Luminous"; } void Luminous::commit() { MaterialParam3f emissiveColor = getMaterialParam3f("color", vec3f(1.f)); const vec3f radiance = emissiveColor.factor * getParam("intensity", 1.f); const float transparency = getParam("transparency", 0.f); getSh()->super.emission = radiance; getSh()->super.emissionMap = emissiveColor.tex; getSh()->transparency = transparency; } } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Luminous.h000066400000000000000000000006631456566705700250370ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" // ispc shared #include "LuminousShared.h" namespace ospray { namespace pathtracer { struct Luminous : public AddStructShared { Luminous(api::ISPCDevice &device); virtual std::string toString() const override; virtual void commit() override; }; } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Luminous.ih000066400000000000000000000016741456566705700252130ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/bsdfs/BSDF.ih" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Material; struct ShadingContext; struct DifferentialGeometry; struct Ray; struct Medium; SYCL_EXTERNAL const varying BSDF *uniform Luminous_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL vec3f Luminous_getTransparency( const uniform Material *uniform super, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL BSDF_SampleRes Luminous_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Luminous.ispc000066400000000000000000000033371456566705700255470ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Luminous.ih" #include "render/Material.ih" #include "render/bsdfs/Transmission.ih" // c++ shared #include "LuminousShared.h" /////////////////////////////////////////////////////////////////////////////// // Implementation OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL const varying BSDF *uniform Luminous_getBSDF( const uniform Material *uniform _self, uniform ShadingContext *uniform ctx, const DifferentialGeometry &, const Ray &, const Medium &, const uniform FeatureFlagsHandler &) { uniform Luminous *uniform self = (uniform Luminous * uniform) _self; varying BSDF *uniform bsdf = NULL; if (self->transparency > 0.0f) { vec3f T = make_vec3f(self->transparency); bsdf = Transmission_create(ctx, NULL /*no frame needed*/, T); bsdf->bsdfType = BSDF_TYPE_LUMINOUS; } return bsdf; } SYCL_EXTERNAL vec3f Luminous_getTransparency( const uniform Material *uniform _self, const DifferentialGeometry &, const Ray &, const Medium &, const uniform FeatureFlagsHandler &) { uniform Luminous *uniform self = (uniform Luminous * uniform) _self; return make_vec3f(self->transparency); } SYCL_EXTERNAL BSDF_SampleRes Luminous_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss) { return Transmission_sample(super, wo, s, ss); } /////////////////////////////////////////////////////////////////////////////// // External API export void *uniform Luminous_getBSDF_addr() { return (void *uniform)Luminous_getBSDF; } export void *uniform Luminous_getTransparency_addr() { return (void *uniform)Luminous_getTransparency; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/LuminousShared.h000066400000000000000000000006421456566705700261630ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/MaterialShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Luminous { Material super; float transparency; #ifdef __cplusplus Luminous() : super(1.f), transparency(0.f) { super.type = ispc::MATERIAL_TYPE_LUMINOUS; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Medium.ih000066400000000000000000000015011456566705700246050ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/vec.ih" #include "MediumShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE inline Medium make_Medium(const vec3f attenuation, const float ior) { Medium m; m.attenuation = attenuation; m.ior = ior; return m; } inline Medium make_Medium_vacuum() { return make_Medium(make_vec3f(0.0f), 1.0f); } inline bool eq(const Medium &a, const Medium &b) { return (a.ior == b.ior) & eq(a.attenuation, b.attenuation); } #ifdef ISPC inline bool eq(const Medium &a, const uniform Medium &b) { return (a.ior == b.ior) & eq(a.attenuation, b.attenuation); } inline uniform bool eq(const uniform Medium &a, const uniform Medium &b) { return (a.ior == b.ior) & eq(a.attenuation, b.attenuation); } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/MediumShared.h000066400000000000000000000007031456566705700255660ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Medium { vec3f attenuation; //!< negative Napierian attenuation coefficient, // i.e. wrt. the natural base e float ior; //!< Refraction index of medium. #ifdef __cplusplus Medium() : attenuation(0.f), ior(1.f) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Metal.cpp000066400000000000000000000036031456566705700246160ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Metal.h" #include "common/Data.h" #ifndef OSPRAY_TARGET_SYCL // ispc #include "render/materials/Metal_ispc.h" #endif namespace ospray { namespace pathtracer { Metal::Metal(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFO_MATERIAL_METAL) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.getBSDF = reinterpret_cast(ispc::Metal_getBSDF_addr()); #endif } std::string Metal::toString() const { return "ospray::pathtracer::Metal"; } void Metal::commit() { auto ior = getParamDataT("ior"); const vec3f &eta = getParam("eta", vec3f(RGB_AL_ETA)); const vec3f &k = getParam("k", vec3f(RGB_AL_K)); MaterialParam1f roughness = getMaterialParam1f("roughness", 0.1f); if (ior) { // resample, relies on ordered samples spectrum etaResampled; spectrum kResampled; auto iorP = ior->begin(); auto iorPrev = *iorP; const auto iorLast = ior->end(); float wl = SPECTRUM_FIRSTWL; for (int l = 0; l < SPECTRUM_SAMPLES; wl += SPECTRUM_SPACING, l++) { for (; iorP != iorLast && iorP->x < wl; iorP++) iorPrev = *iorP; if (iorP->x == iorPrev.x) { etaResampled[l] = iorPrev.y; kResampled[l] = iorPrev.z; } else { auto f = (wl - iorPrev.x) / (iorP->x - iorPrev.x); etaResampled[l] = (1.f - f) * iorPrev.y + f * iorP->y; kResampled[l] = (1.f - f) * iorPrev.z + f * iorP->z; } } getSh()->spectral = true; getSh()->eta = etaResampled; getSh()->k = kResampled; } else { // default to Aluminium, used when ior not given getSh()->spectral = false; getSh()->etaRGB = eta; getSh()->kRGB = k; } getSh()->roughness = roughness.factor; getSh()->roughnessMap = roughness.tex; } } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Metal.h000066400000000000000000000007021456566705700242600ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "math/spectrum.h" #include "render/Material.h" // ispc shared #include "MetalShared.h" namespace ospray { namespace pathtracer { struct Metal : public AddStructShared { Metal(api::ISPCDevice &device); virtual std::string toString() const override; virtual void commit() override; }; } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Metal.ih000066400000000000000000000017471456566705700244430ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/bsdfs/BSDF.ih" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Material; struct ShadingContext; struct DifferentialGeometry; struct Ray; struct Medium; SYCL_EXTERNAL const varying BSDF *uniform Metal_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL BSDF_EvalRes MetalRough_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi); SYCL_EXTERNAL BSDF_SampleRes MetalRough_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss); SYCL_EXTERNAL BSDF_SampleRes Metal_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Metal.ispc000066400000000000000000000045311456566705700247730ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Metal.ih" #include "math/spectrum.ih" #include "render/Material.ih" #include "render/bsdfs/Conductor.ih" #include "render/bsdfs/MicrofacetConductor.ih" #include "texture/TextureParam.ih" // c++ shared #include "MetalShared.h" /////////////////////////////////////////////////////////////////////////////// // Implementation OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL const varying BSDF *uniform Metal_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &, const Medium &, const uniform FeatureFlagsHandler &) { const uniform Metal *uniform self = (const uniform Metal *uniform)super; varying linear3f *uniform shadingframe = LinearSpace3f_create(ctx, frame(dg.Ns)); Fresnel *uniform fresnel; if (self->spectral) fresnel = FresnelConductorSpectral_create(ctx, self->eta, self->k); else fresnel = FresnelConductorRGBUniform_create(ctx, self->etaRGB, self->kRGB); varying BSDF *uniform bsdf; if (self->roughness == 0.0f) { bsdf = Conductor_create(ctx, shadingframe, fresnel); bsdf->bsdfType = BSDF_TYPE_METAL; } else { bsdf = MicrofacetConductor_create(ctx, super->microfacetAlbedoTables, shadingframe, fresnel, self->roughness * get1f(self->roughnessMap, dg, 1.f), 0.f); bsdf->bsdfType = BSDF_TYPE_METAL_ROUGH; } return bsdf; } SYCL_EXTERNAL BSDF_EvalRes MetalRough_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi) { return MicrofacetConductor_eval( (const varying MicrofacetConductor *uniform)super, wo, wi); } SYCL_EXTERNAL BSDF_SampleRes MetalRough_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss) { return MicrofacetConductor_sample( (const varying MicrofacetConductor *uniform)super, wo, s, ss); } SYCL_EXTERNAL BSDF_SampleRes Metal_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss) { return Conductor_sample(super, wo, s, ss); } /////////////////////////////////////////////////////////////////////////////// // External API export void *uniform Metal_getBSDF_addr() { return (void *uniform)Metal_getBSDF; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/MetalShared.h000066400000000000000000000016041456566705700254110ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/MaterialShared.h" #include "texture/TextureParamShared.h" #ifdef __cplusplus #include "math/spectrum.h" #else #include "math/spectrum.ih" #endif #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Metal { Material super; bool spectral; spectrum eta; // index of refraction spectrum k; // index of refraction, imaginary part vec3f etaRGB; // index of refraction vec3f kRGB; // index of refraction, imaginary part float roughness; // in [0, 1]; 0==ideally smooth (mirror) TextureParam roughnessMap; #ifdef __cplusplus Metal() : spectral(false), eta{}, k{}, etaRGB(RGB_AL_ETA), kRGB(RGB_AL_K), roughness(.1f) { super.type = ispc::MATERIAL_TYPE_METAL; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/materials/MetallicPaint.cpp000066400000000000000000000024261456566705700263040ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "MetallicPaint.h" #ifndef OSPRAY_TARGET_SYCL // ispc #include "render/materials/MetallicPaint_ispc.h" #endif namespace ospray { namespace pathtracer { MetallicPaint::MetallicPaint(api::ISPCDevice &device) : AddStructShared( device.getIspcrtContext(), device, FFO_MATERIAL_METALLICPAINT) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.getBSDF = reinterpret_cast( ispc::MetallicPaint_getBSDF_addr()); #endif } std::string MetallicPaint::toString() const { return "ospray::pathtracer::MetallicPaint"; } void MetallicPaint::commit() { MaterialParam3f color = getMaterialParam3f("baseColor", vec3f(0.8f)); const float flakeAmount = getParam("flakeAmount", 0.3f); const vec3f &flakeColor = getParam("flakeColor", vec3f(RGB_AL_COLOR)); const float flakeSpread = getParam("flakeSpread", 0.5f); const float eta = getParam("eta", 1.5f); getSh()->baseColor = color.factor * (1.f - flakeAmount); getSh()->baseColorMap = color.tex; getSh()->flakeAmount = flakeAmount; getSh()->flakeColor = flakeColor * flakeAmount; getSh()->flakeSpread = flakeSpread; getSh()->eta = rcp(eta); } } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/MetallicPaint.h000066400000000000000000000007421456566705700257500ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "math/spectrum.h" #include "render/Material.h" // ispc shared #include "MetallicPaintShared.h" namespace ospray { namespace pathtracer { struct MetallicPaint : public AddStructShared { MetallicPaint(api::ISPCDevice &device); virtual std::string toString() const override; virtual void commit() override; }; } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/MetallicPaint.ih000066400000000000000000000015451456566705700261230ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/bsdfs/BSDF.ih" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Material; struct ShadingContext; struct DifferentialGeometry; struct Ray; struct Medium; SYCL_EXTERNAL const varying BSDF *uniform MetallicPaint_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL BSDF_EvalRes MetallicPaint_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi); SYCL_EXTERNAL BSDF_SampleRes MetallicPaint_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/MetallicPaint.ispc000066400000000000000000000112361456566705700264570ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "MetallicPaint.ih" #include "render/Material.ih" #include "render/bsdfs/DielectricLayer.ih" #include "render/bsdfs/Lambert.ih" #include "render/bsdfs/MicrofacetConductor.ih" #include "render/bsdfs/MultiBSDF.ih" #include "texture/TextureParam.ih" // c++ shared #include "MetallicPaintShared.h" /////////////////////////////////////////////////////////////////////////////// // Implementation OSPRAY_BEGIN_ISPC_NAMESPACE struct MetallicPaint_MultiBSDF { DEFINE_MULTIBSDF(2); BSDF lambert; MicrofacetConductor microfacetConductor; }; struct MetallicPaint_BSDF { DielectricLayer dielectricLayer; MetallicPaint_MultiBSDF multi; }; SYCL_EXTERNAL const varying BSDF *uniform MetallicPaint_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &, const Medium &, const uniform FeatureFlagsHandler &) { const uniform MetallicPaint *uniform self = (const uniform MetallicPaint *uniform)super; varying LinearSpace3f *uniform shadingFrame = LinearSpace3f_create(ctx, frame(dg.Ns)); // Allocate memory and initialize material BSDF varying MetallicPaint_BSDF *uniform bsdf = (varying MetallicPaint_BSDF * uniform) ShadingContext_alloc(ctx, sizeof(MetallicPaint_BSDF)); varying MultiBSDF *uniform bsdfMulti = (varying MultiBSDF * uniform) & bsdf->multi; MultiBSDF_Constructor(bsdfMulti, 2); const vec3f color = self->baseColor * make_vec3f(dg.color) * get3f(self->baseColorMap, dg, make_vec3f(1.f)); Lambert_Constructor(&bsdf->multi.lambert, shadingFrame, color); MultiBSDF_add(bsdfMulti, 0, &bsdf->multi.lambert, 1.f, luminance(color)); if (self->flakeAmount > 0.f) { const vec3f r = self->flakeColor; const vec3f g = make_vec3f(self->flakeAmount); Fresnel *uniform fresnel = FresnelSchlick_create(ctx, r, g); MicrofacetConductor_Constructor(&bsdf->multi.microfacetConductor, super->microfacetAlbedoTables, shadingFrame, fresnel, self->flakeSpread, 0.f); MultiBSDF_add(bsdfMulti, 1, (varying BSDF * uniform) & bsdf->multi.microfacetConductor, 1.f, luminance(r)); } DielectricLayer_Constructor(&bsdf->dielectricLayer, shadingFrame, &bsdf->multi.super, self->eta, make_vec3f(1.0f), 1.0f, 1.0f); bsdf->dielectricLayer.super.bsdfType = BSDF_TYPE_METALLICPAINT; return &bsdf->dielectricLayer.super; } inline BSDF_EvalRes MultiBSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi) { const varying MetallicPaint_MultiBSDF *uniform self = (const varying MetallicPaint_MultiBSDF *uniform)super; MULTIBSDF_EVAL_BEGIN(); MULTIBSDF_EVAL_CHILD(0, &self->lambert, Lambert_eval); MULTIBSDF_EVAL_CHILD(1, &self->microfacetConductor, MicrofacetConductor_eval); MULTIBSDF_EVAL_END(); return MULTIBSDF_EVAL_GET(); } inline BSDF_SampleRes MultiBSDF_sample(const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss) { const varying MetallicPaint_MultiBSDF *uniform self = (const varying MetallicPaint_MultiBSDF *uniform)super; MULTIBSDF_SAMPLE_BEGIN(); MULTIBSDF_SAMPLE_CHILD(0, &self->lambert, Lambert_sample); MULTIBSDF_SAMPLE_CHILD( 1, &self->microfacetConductor, MicrofacetConductor_sample); MULTIBSDF_SAMPLE_EVAL(); MULTIBSDF_EVAL_CHILD(0, &self->lambert, Lambert_eval); MULTIBSDF_EVAL_CHILD(1, &self->microfacetConductor, MicrofacetConductor_eval); MULTIBSDF_SAMPLE_END(); return MULTIBSDF_SAMPLE_GET(); } SYCL_EXTERNAL BSDF_EvalRes MetallicPaint_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi) { const varying MetallicPaint_BSDF *uniform self = (const varying MetallicPaint_BSDF *uniform)super; DIELECTRICLAYER_EVAL(self->dielectricLayer, self->multi.super.scatteringType, &self->multi.super, MultiBSDF_eval); return DIELECTRICLAYER_EVAL_GET(); } SYCL_EXTERNAL BSDF_SampleRes MetallicPaint_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss) { const varying MetallicPaint_BSDF *uniform self = (const varying MetallicPaint_BSDF *uniform)super; DIELECTRICLAYER_SAMPLE(self->dielectricLayer, self->multi.super.scatteringType, &self->multi.super, MultiBSDF_sample); return DIELECTRICLAYER_SAMPLE_GET(); } /////////////////////////////////////////////////////////////////////////////// // External API export void *uniform MetallicPaint_getBSDF_addr() { return (void *uniform)MetallicPaint_getBSDF; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/MetallicPaintShared.h000066400000000000000000000012731456566705700270770ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/MaterialShared.h" #include "texture/TextureParamShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct MetallicPaint { Material super; vec3f baseColor; TextureParam baseColorMap; float flakeAmount; vec3f flakeColor; float flakeSpread; float eta; #ifdef __cplusplus MetallicPaint() : baseColor(.25f), flakeAmount(.5f), flakeColor(flakeAmount * vec3f(RGB_AL_COLOR)), flakeSpread(0.5f), eta(1.f / 1.6f) { super.type = ispc::MATERIAL_TYPE_METALLICPAINT; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Mix.cpp000066400000000000000000000033461456566705700243150ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Mix.h" #ifndef OSPRAY_TARGET_SYCL // ispc #include "render/materials/Mix_ispc.h" #endif namespace ospray { namespace pathtracer { MixMaterial::MixMaterial(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFO_MATERIAL_MIX) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.getBSDF = reinterpret_cast(ispc::Mix_getBSDF_addr()); getSh()->super.getTransparency = reinterpret_cast( ispc::Mix_getTransparency_addr()); #endif } std::string MixMaterial::toString() const { return "ospray::pathtracer::MixMaterial"; } void MixMaterial::commit() { MaterialParam1f factor = getMaterialParam1f("factor", .5f); mat1 = getParamObject("material1"); mat2 = getParamObject("material2"); getSh()->factor = clamp(factor.factor); getSh()->factorMap = factor.tex; getSh()->mat1 = mat1 ? mat1->getSh() : nullptr; getSh()->mat2 = mat2 ? mat2->getSh() : nullptr; // XXX mixing emission(Map) is not supported, below are merely some WAs vec3f emission = vec3f(0.f); ispc::TextureParam emissionMap; if (mat1) { emission = (1.f - getSh()->factor) * getSh()->mat1->emission; if (getSh()->mat1->emissionMap.ptr) emissionMap = getSh()->mat1->emissionMap; } if (mat2) { emission = emission + getSh()->factor * getSh()->mat2->emission; // if both materials have emission texture, material2 wins if (getSh()->mat2->emissionMap.ptr) emissionMap = getSh()->mat2->emissionMap; } getSh()->super.emission = emission; getSh()->super.emissionMap = emissionMap; } } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Mix.h000066400000000000000000000007501456566705700237560ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" // ispc shared #include "MixShared.h" namespace ospray { namespace pathtracer { struct MixMaterial : public AddStructShared { MixMaterial(api::ISPCDevice &device); virtual std::string toString() const override; virtual void commit() override; protected: Ref mat1; Ref mat2; }; } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Mix.ih000066400000000000000000000020731456566705700241270ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/bsdfs/BSDF.ih" #include "rkcommon/math/vec.ih" #ifndef OSPRAY_TARGET_SYCL OSPRAY_BEGIN_ISPC_NAMESPACE struct Material; struct ShadingContext; struct DifferentialGeometry; struct Ray; struct Medium; SYCL_EXTERNAL const varying BSDF *uniform Mix_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL vec3f Mix_getTransparency(const uniform Material *uniform super, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL BSDF_EvalRes Mix_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi); SYCL_EXTERNAL BSDF_SampleRes Mix_BSDF_sample(const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss); OSPRAY_END_ISPC_NAMESPACE #endifRenderKit-ospray-f2a61c2/modules/cpu/render/materials/Mix.ispc000066400000000000000000000100001456566705700244520ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Mix.ih" #include "common/FeatureFlags.ih" #include "render/Material.ih" #include "render/bsdfs/MultiBSDF.ih" #include "texture/TextureParam.ih" // c++ shared #include "MixShared.h" /////////////////////////////////////////////////////////////////////////////// // Implementation #ifndef OSPRAY_TARGET_SYCL OSPRAY_BEGIN_ISPC_NAMESPACE #define MULTIBSDF_SIZE 2 struct Mix_BSDF { DEFINE_MULTIBSDF(MULTIBSDF_SIZE); const varying BSDF *uniform bsdf1; const varying BSDF *uniform bsdf2; }; SYCL_EXTERNAL const varying BSDF *uniform Mix_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh) { const Mix *uniform self = (const Mix *uniform)super; // Allocate memory and initialize material BSDF varying Mix_BSDF *uniform bsdf = (varying Mix_BSDF * uniform) ShadingContext_alloc(ctx, sizeof(Mix_BSDF)); varying MultiBSDF *uniform mbsdf = (varying MultiBSDF * uniform) bsdf; MultiBSDF_Constructor(mbsdf, MULTIBSDF_SIZE); bsdf->super.bsdfType = BSDF_TYPE_MIX; bsdf->bsdf1 = NULL; bsdf->bsdf2 = NULL; float factor = self->factor * clamp(get1f(self->factorMap, dg, 1.f)); if (self->mat1) { bsdf->bsdf1 = self->mat1->getBSDF(self->mat1, ctx, dg, ray, currentMedium, ffh); MultiBSDF_add(mbsdf, 0, bsdf->bsdf1, 1.0f - factor, 1.0f - factor); } if (self->mat2) { bsdf->bsdf2 = self->mat2->getBSDF(self->mat2, ctx, dg, ray, currentMedium, ffh); MultiBSDF_add(mbsdf, 1, bsdf->bsdf2, factor, factor); } return &bsdf->super; } SYCL_EXTERNAL vec3f Mix_getTransparency(const uniform Material *uniform super, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh) { const Mix *uniform self = (const Mix *uniform)super; vec3f t1 = make_vec3f(0.f); if (self->mat1) t1 = self->mat1->getTransparency(self->mat1, dg, ray, currentMedium, ffh); vec3f t2 = make_vec3f(0.f); if (self->mat2) t2 = self->mat2->getTransparency(self->mat2, dg, ray, currentMedium, ffh); float factor = self->factor * clamp(get1f(self->factorMap, dg, 1.f)); return lerp(factor, t1, t2); } inline BSDF_EvalRes BSDF_dispatch_eval( const varying BSDF *uniform self, const vec3f &wo, const vec3f &wi) { uniform FeatureFlagsHandler ffh; return BSDF_dispatch_eval(self, wo, wi, ffh); } inline BSDF_SampleRes BSDF_dispatch_sample( const varying BSDF *uniform self, const vec3f &wo, const vec2f &s, float ss) { uniform FeatureFlagsHandler ffh; return BSDF_dispatch_sample(self, wo, s, ss, ffh); } SYCL_EXTERNAL BSDF_EvalRes Mix_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi) { const varying Mix_BSDF *uniform self = (const varying Mix_BSDF *uniform)super; MULTIBSDF_EVAL_BEGIN(); MULTIBSDF_EVAL_CHILD(0, self->bsdf1, BSDF_dispatch_eval); MULTIBSDF_EVAL_CHILD(1, self->bsdf2, BSDF_dispatch_eval); MULTIBSDF_EVAL_END(); return MULTIBSDF_EVAL_GET(); } SYCL_EXTERNAL BSDF_SampleRes Mix_BSDF_sample(const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss) { const varying Mix_BSDF *uniform self = (const varying Mix_BSDF *uniform)super; MULTIBSDF_SAMPLE_BEGIN(); MULTIBSDF_SAMPLE_CHILD(0, self->bsdf1, BSDF_dispatch_sample); MULTIBSDF_SAMPLE_CHILD(1, self->bsdf2, BSDF_dispatch_sample); MULTIBSDF_SAMPLE_EVAL(); MULTIBSDF_EVAL_CHILD(0, self->bsdf1, BSDF_dispatch_eval); MULTIBSDF_EVAL_CHILD(1, self->bsdf2, BSDF_dispatch_eval); MULTIBSDF_SAMPLE_END(); return MULTIBSDF_SAMPLE_GET(); } /////////////////////////////////////////////////////////////////////////////// // External API export void *uniform Mix_getBSDF_addr() { return (void *uniform)Mix_getBSDF; } export void *uniform Mix_getTransparency_addr() { return (void *uniform)Mix_getTransparency; } OSPRAY_END_ISPC_NAMESPACE #endifRenderKit-ospray-f2a61c2/modules/cpu/render/materials/MixShared.h000066400000000000000000000007771456566705700251160ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/MaterialShared.h" #include "texture/TextureParamShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Mix { Material super; float factor; TextureParam factorMap; Material *mat1; Material *mat2; #ifdef __cplusplus Mix() : factor(.5f), mat1(nullptr), mat2(nullptr) { super.type = ispc::MATERIAL_TYPE_MIX; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/materials/OBJ.cpp000066400000000000000000000035761456566705700241770ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "OBJ.h" #ifndef OSPRAY_TARGET_SYCL // ispc #include "render/materials/OBJ_ispc.h" #endif namespace ospray { namespace pathtracer { OBJMaterial::OBJMaterial(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFO_MATERIAL_OBJ) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.getBSDF = reinterpret_cast(ispc::OBJ_getBSDF_addr()); getSh()->super.getTransparency = reinterpret_cast( ispc::OBJ_getTransparency_addr()); #endif } std::string OBJMaterial::toString() const { return "ospray::pathtracer::obj"; } void OBJMaterial::commit() { MaterialParam1f d = getMaterialParam1f("d", 1.f); MaterialParam3f Kd = getMaterialParam3f("kd", vec3f(0.8f)); MaterialParam3f Ks = getMaterialParam3f("ks", vec3f(0.f)); MaterialParam1f Ns = getMaterialParam1f("ns", 10.f); vec3f Tf = getParam("tf", vec3f(0.f)); ispc::TextureParam bumpTex = getTextureParam("map_bump"); linear2f bumpRot = ((linear2f *)(&bumpTex.xform2f.l))->orthogonal().transposed(); const float color_total = reduce_max(Kd.factor + Ks.factor + Tf); if (color_total > 1.f) { postStatusMsg(OSP_LOG_DEBUG) << "#osp:PT OBJ material produces energy " << "(kd + ks + tf = " << color_total << ", should be <= 1). Scaling down to 1."; Kd.factor /= color_total; Ks.factor /= color_total; Tf /= color_total; } getSh()->dMap = d.tex; getSh()->d = d.factor; getSh()->KdMap = Kd.tex; getSh()->Kd = Kd.factor; getSh()->KsMap = Ks.tex; getSh()->Ks = Ks.factor; getSh()->NsMap = Ns.tex; getSh()->Ns = Ns.factor; getSh()->Tf = Tf; getSh()->bumpMap = bumpTex; getSh()->bumpRot = bumpRot; } } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/OBJ.h000066400000000000000000000006571456566705700236410ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" // ispc shared #include "OBJShared.h" namespace ospray { namespace pathtracer { struct OBJMaterial : public AddStructShared { OBJMaterial(api::ISPCDevice &device); virtual std::string toString() const override; virtual void commit() override; }; } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/OBJ.ih000066400000000000000000000020721456566705700240030ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/FeatureFlags.ih" #include "render/bsdfs/BSDF.ih" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Material; struct ShadingContext; struct DifferentialGeometry; struct Ray; struct Medium; SYCL_EXTERNAL const varying BSDF *uniform OBJ_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL vec3f OBJ_getTransparency(const uniform Material *uniform super, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL BSDF_EvalRes OBJ_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi); SYCL_EXTERNAL BSDF_SampleRes OBJ_BSDF_sample(const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/OBJ.ispc000066400000000000000000000114651456566705700243470ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "OBJ.ih" #include "render/Material.ih" #include "render/bsdfs/Lambert.ih" #include "render/bsdfs/MultiBSDF.ih" #include "render/bsdfs/Specular.ih" #include "render/bsdfs/Transmission.ih" #include "texture/TextureParam.ih" // c++ shared #include "OBJShared.h" /////////////////////////////////////////////////////////////////////////////// // Implementation OSPRAY_BEGIN_ISPC_NAMESPACE #define MULTIBSDF_SIZE 3 struct OBJ_BSDF { DEFINE_MULTIBSDF(MULTIBSDF_SIZE); BSDF lambert; BSDF transmission; Specular specular; }; SYCL_EXTERNAL const varying BSDF *uniform OBJ_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &, const Medium &, const uniform FeatureFlagsHandler &ffh) { uniform const OBJ *uniform self = (uniform const OBJ *uniform)super; // Allocate memory and initialize material BSDF varying OBJ_BSDF *uniform bsdf = (varying OBJ_BSDF * uniform) ShadingContext_alloc(ctx, sizeof(OBJ_BSDF)); varying MultiBSDF *uniform mbsdf = (varying MultiBSDF * uniform) bsdf; MultiBSDF_Constructor(mbsdf, MULTIBSDF_SIZE); bsdf->super.bsdfType = BSDF_TYPE_OBJ; // textures modify (mul) values, see http://paulbourke.net/dataformats/mtl/ // Normal map varying linear3f *uniform shadingFrame = LinearSpace3f_create( ctx, makeShadingFrame_ff(dg, self->bumpMap, self->bumpRot, ffh)); /*! cut-out opacity */ float d = self->d * get1f_ff(self->dMap, dg, 1.f, ffh) * dg.color.w; const uniform FeatureFlagsOther ffo = getFeatureFlagsOther(ffh); // Diffuse component vec3f Kd = self->Kd; if (valid(self->KdMap) && (ffo & FFO_TEXTURE_IN_MATERIAL)) { vec4f Kd_from_map = get4f(self->KdMap, dg); Kd = Kd * make_vec3f(Kd_from_map); d *= Kd_from_map.w; } // Lambert shading Kd = Kd * d * make_vec3f(dg.color); if (reduce_max(Kd) > 0.0f) { Lambert_Constructor(&bsdf->lambert, shadingFrame, Kd); MultiBSDF_add(mbsdf, 0, &bsdf->lambert, 1.f, luminance(Kd)); } // Transmission component vec3f T = self->Tf * d + make_vec3f(1.f - d); if (reduce_max(T) > 0.0f) { Transmission_Constructor(&bsdf->transmission, shadingFrame, T); MultiBSDF_add(mbsdf, 1, &bsdf->transmission, 1.f, luminance(T)); } /*! specular component */ float Ns = self->Ns * get1f_ff(self->NsMap, dg, 1.0f, ffh); vec3f Ks = d * self->Ks * get3f_ff(self->KsMap, dg, make_vec3f(1.f), ffh); if (reduce_max(Ks) > 0.0f) { Specular_Constructor(&bsdf->specular, shadingFrame, Ks, Ns); MultiBSDF_add(mbsdf, 2, (varying BSDF * uniform) & bsdf->specular, 1.f, luminance(Ks)); } return &bsdf->super; } SYCL_EXTERNAL vec3f OBJ_getTransparency(const uniform Material *uniform super, const DifferentialGeometry &dg, const Ray &, const Medium &, const uniform FeatureFlagsHandler &ffh) { uniform const OBJ *uniform self = (uniform const OBJ *uniform)super; const uniform FeatureFlagsOther ffo = getFeatureFlagsOther(ffh); /*! cut-out opacity */ float d = self->d * get1f_ff(self->dMap, dg, 1.f, ffh) * dg.color.w; if (hasAlpha(self->KdMap) && (ffo & FFO_TEXTURE_IN_MATERIAL)) { vec4f Kd_from_map = get4f(self->KdMap, dg); d *= Kd_from_map.w; } // Transmission component vec3f T = self->Tf * d + make_vec3f(1.f - d); return T; } SYCL_EXTERNAL BSDF_EvalRes OBJ_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi) { const varying OBJ_BSDF *uniform self = (const varying OBJ_BSDF *uniform)super; MULTIBSDF_EVAL_BEGIN(); MULTIBSDF_EVAL_CHILD(0, &self->lambert, Lambert_eval); // 1 - omitted, no evaluation needed for transmission BSDF MULTIBSDF_EVAL_CHILD(2, &self->specular, Specular_eval); MULTIBSDF_EVAL_END(); return MULTIBSDF_EVAL_GET(); } SYCL_EXTERNAL BSDF_SampleRes OBJ_BSDF_sample(const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss) { const varying OBJ_BSDF *uniform self = (const varying OBJ_BSDF *uniform)super; MULTIBSDF_SAMPLE_BEGIN(); MULTIBSDF_SAMPLE_CHILD(0, &self->lambert, Lambert_sample); MULTIBSDF_SAMPLE_CHILD(1, &self->transmission, Transmission_sample); MULTIBSDF_SAMPLE_CHILD(2, &self->specular, Specular_sample); MULTIBSDF_SAMPLE_EVAL(); MULTIBSDF_EVAL_CHILD(0, &self->lambert, Lambert_eval); // 1 - omitted, no evaluation needed for transmission BSDF MULTIBSDF_EVAL_CHILD(2, &self->specular, Specular_eval); MULTIBSDF_SAMPLE_END(); return MULTIBSDF_SAMPLE_GET(); } /////////////////////////////////////////////////////////////////////////////// // External API export void *uniform OBJ_getBSDF_addr() { return (void *uniform)OBJ_getBSDF; } export void *uniform OBJ_getTransparency_addr() { return (void *uniform)OBJ_getTransparency; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/OBJShared.h000066400000000000000000000014111456566705700247550ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/MaterialShared.h" #include "texture/TextureParamShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct OBJ { Material super; float d; // cut-out opacity TextureParam dMap; vec3f Kd; TextureParam KdMap; vec3f Ks; TextureParam KsMap; float Ns; TextureParam NsMap; vec3f Tf; // transmission filter TextureParam bumpMap; linear2f bumpRot; // just the inverse of rotational/mirror part (must be // orthonormal) of tc xfrom #ifdef __cplusplus OBJ() : d(1.f), Kd(.8f), Ks(0.f), Ns(2.f), Tf(0.f), bumpRot(one) { super.type = MATERIAL_TYPE_OBJ; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Plastic.cpp000066400000000000000000000016601456566705700251540ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Plastic.h" #ifndef OSPRAY_TARGET_SYCL // ispc #include "render/materials/Plastic_ispc.h" #endif namespace ospray { namespace pathtracer { Plastic::Plastic(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFO_MATERIAL_PLASTIC) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.getBSDF = reinterpret_cast( ispc::Plastic_getBSDF_addr()); #endif } std::string Plastic::toString() const { return "ospray::pathtracer::Plastic"; } void Plastic::commit() { const vec3f pigmentColor = getParam("pigmentColor", vec3f(1.f)); const float eta = getParam("eta", 1.4f); const float roughness = getParam("roughness", 0.01f); getSh()->pigmentColor = pigmentColor; getSh()->eta = rcp(eta); getSh()->roughness = roughness; } } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Plastic.h000066400000000000000000000006571456566705700246260ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" // ispc shared #include "PlasticShared.h" namespace ospray { namespace pathtracer { struct Plastic : public AddStructShared { Plastic(api::ISPCDevice &device); virtual std::string toString() const override; virtual void commit() override; }; } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Plastic.ih000066400000000000000000000015231456566705700247700ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/bsdfs/BSDF.ih" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Material; struct ShadingContext; struct DifferentialGeometry; struct Ray; struct Medium; SYCL_EXTERNAL const varying BSDF *uniform Plastic_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL BSDF_EvalRes Plastic_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi); SYCL_EXTERNAL BSDF_SampleRes Plastic_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Plastic.ispc000066400000000000000000000105141456566705700253260ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Plastic.ih" #include "render/Material.ih" #include "render/bsdfs/DielectricLayer.ih" #include "render/bsdfs/Lambert.ih" #include "render/bsdfs/MicrofacetDielectricLayer.ih" // c++ shared #include "PlasticShared.h" /////////////////////////////////////////////////////////////////////////////// // Implementation OSPRAY_BEGIN_ISPC_NAMESPACE struct Plastic_BSDF { BSDF root; MicrofacetDielectricLayer dielectricLayer; BSDF lambert; }; SYCL_EXTERNAL const varying BSDF *uniform Plastic_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &, const Medium &, const uniform FeatureFlagsHandler &) { const uniform Plastic *uniform self = (const uniform Plastic *uniform)super; varying LinearSpace3f *uniform shadingFrame = LinearSpace3f_create(ctx, frame(dg.Ns)); // Allocate memory and initialize material BSDF varying Plastic_BSDF *uniform bsdf = (varying Plastic_BSDF * uniform) ShadingContext_alloc(ctx, sizeof(Plastic_BSDF)); const vec3f _pigmentColor = self->pigmentColor; Lambert_Constructor(&bsdf->lambert, shadingFrame, _pigmentColor); if (self->roughness == 0.0f) { DielectricLayer_Constructor( (varying DielectricLayer * uniform) & bsdf->dielectricLayer, shadingFrame, &bsdf->lambert, self->eta, make_vec3f(1.0f), 1.0f, 1.0f); } else { MicrofacetDielectricLayer_Constructor(&bsdf->dielectricLayer, super->microfacetAlbedoTables, shadingFrame, &bsdf->lambert, self->eta, make_vec3f(1.0f), 1.0f, self->roughness, 0.f, 1.0f); } bsdf->root = bsdf->dielectricLayer.super; bsdf->root.bsdfType = BSDF_TYPE_PLASTIC; return &bsdf->root; } // DielectricLayer BSDF inline BSDF_EvalRes DielectricLayerBSDF_eval( const varying Plastic_BSDF *uniform self, const vec3f &wo, const vec3f &wi) { DIELECTRICLAYER_EVAL(self->dielectricLayer, self->lambert.scatteringType, &self->lambert, Lambert_eval); return DIELECTRICLAYER_EVAL_GET(); } inline BSDF_SampleRes DielectricLayerBSDF_sample( const varying Plastic_BSDF *uniform self, const vec3f &wo, const vec2f &s, float ss) { DIELECTRICLAYER_SAMPLE(self->dielectricLayer, self->lambert.scatteringType, &self->lambert, Lambert_sample); return DIELECTRICLAYER_SAMPLE_GET(); } // MicrofacetDielectricLayer BSDF inline BSDF_EvalRes MicrofacetDielectricLayerBSDF_eval( const varying Plastic_BSDF *uniform self, const vec3f &wo, const vec3f &wi) { MICROFACETDIELECTRICLAYER_EVAL(self->dielectricLayer, self->lambert.scatteringType, &self->lambert, Lambert_eval); return MICROFACETDIELECTRICLAYER_EVAL_GET(); } inline BSDF_SampleRes MicrofacetDielectricLayerBSDF_sample( const varying Plastic_BSDF *uniform self, const vec3f &wo, const vec2f &s, float ss) { MICROFACETDIELECTRICLAYER_SAMPLE(self->dielectricLayer, self->lambert.scatteringType, &self->lambert, Lambert_eval, Lambert_sample); return MICROFACETDIELECTRICLAYER_SAMPLE_GET(); } // Plastic BSDF SYCL_EXTERNAL __noinline BSDF_EvalRes Plastic_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi) { const varying Plastic_BSDF *uniform self = (const varying Plastic_BSDF *uniform)super; if (self->dielectricLayer.super.bsdfType == BSDF_TYPE_MICROFACET_DIELECTRIC_LAYER) return MicrofacetDielectricLayerBSDF_eval(self, wo, wi); else return DielectricLayerBSDF_eval(self, wo, wi); } SYCL_EXTERNAL __noinline BSDF_SampleRes Plastic_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss) { const varying Plastic_BSDF *uniform self = (const varying Plastic_BSDF *uniform)super; if (self->dielectricLayer.super.bsdfType == BSDF_TYPE_MICROFACET_DIELECTRIC_LAYER) return MicrofacetDielectricLayerBSDF_sample(self, wo, s, ss); else return DielectricLayerBSDF_sample(self, wo, s, ss); } /////////////////////////////////////////////////////////////////////////////// // External API export void *uniform Plastic_getBSDF_addr() { return (void *uniform)Plastic_getBSDF; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/PlasticShared.h000066400000000000000000000007201456566705700257440ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/MaterialShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Plastic { Material super; vec3f pigmentColor; float eta; float roughness; #ifdef __cplusplus Plastic() : pigmentColor(1.f), eta(1.4f), roughness(0.01f) { super.type = ispc::MATERIAL_TYPE_PLASTIC; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Principled.cpp000066400000000000000000000140431456566705700256450ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Principled.h" #ifndef OSPRAY_TARGET_SYCL // ispc #include "render/materials/Principled_ispc.h" #endif namespace ospray { namespace pathtracer { Principled::Principled(api::ISPCDevice &device) : AddStructShared( device.getIspcrtContext(), device, FFO_MATERIAL_PRINCIPLED) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.getBSDF = reinterpret_cast( ispc::Principled_getBSDF_addr()); getSh()->super.getTransparency = reinterpret_cast( ispc::Principled_getTransparency_addr()); getSh()->super.selectNextMedium = reinterpret_cast( ispc::Principled_selectNextMedium_addr()); #endif } std::string Principled::toString() const { return "ospray::pathtracer::Principled"; } void Principled::commit() { MaterialParam3f baseColor = getMaterialParam3f("baseColor", vec3f(0.8f)); MaterialParam3f edgeColor = getMaterialParam3f("edgeColor", vec3f(1.f)); MaterialParam1f metallic = getMaterialParam1f("metallic", 0.f); MaterialParam1f diffuse = getMaterialParam1f("diffuse", 1.f); MaterialParam1f specular = getMaterialParam1f("specular", 1.f); MaterialParam1f ior = getMaterialParam1f("ior", 1.f); MaterialParam1f transmission = getMaterialParam1f("transmission", 0.f); MaterialParam3f transmissionColor = getMaterialParam3f("transmissionColor", vec3f(1.f)); MaterialParam1f transmissionDepth = getMaterialParam1f("transmissionDepth", 1.f); MaterialParam1f roughness = getMaterialParam1f("roughness", 0.f); MaterialParam1f anisotropy = getMaterialParam1f("anisotropy", 0.f); MaterialParam1f rotation = getMaterialParam1f("rotation", 0.f); MaterialParam1f normal = getMaterialParam1f("normal", 1.f); MaterialParam1f baseNormal = getMaterialParam1f("baseNormal", 1.f); MaterialParam1f coat = getMaterialParam1f("coat", 0.f); MaterialParam1f coatIor = getMaterialParam1f("coatIor", 1.5f); MaterialParam3f coatColor = getMaterialParam3f("coatColor", vec3f(1.f)); MaterialParam1f coatThickness = getMaterialParam1f("coatThickness", 1.f); MaterialParam1f coatRoughness = getMaterialParam1f("coatRoughness", 0.f); MaterialParam1f coatNormal = getMaterialParam1f("coatNormal", 1.f); MaterialParam1f sheen = getMaterialParam1f("sheen", 0.f); MaterialParam3f sheenColor = getMaterialParam3f("sheenColor", vec3f(1.f)); MaterialParam1f sheenTint = getMaterialParam1f("sheenTint", 0.f); MaterialParam1f sheenRoughness = getMaterialParam1f("sheenRoughness", 0.2f); MaterialParam1f opacity = getMaterialParam1f("opacity", 1.f); bool thin = getParam("thin", false); MaterialParam1f backlight = getMaterialParam1f("backlight", 0.f); MaterialParam1f thickness = getMaterialParam1f("thickness", 1.f); float outsideIor = getParam("outsideIor", 1.f); vec3f outsideTransmissionColor = getParam("outsideTransmissionColor", vec3f(1.f)); float outsideTransmissionDepth = getParam("outsideTransmissionDepth", 1.f); MaterialParam3f emissiveColor = getMaterialParam3f("emissiveColor", vec3f(0.f)); // intensity is an additional constant factor to emission emissiveColor.factor *= getParam("intensity", 1.f); getSh()->super.emission = emissiveColor.factor; getSh()->super.emissionMap = emissiveColor.tex; getSh()->baseColor = baseColor.factor; getSh()->baseColorMap = baseColor.tex; getSh()->edgeColor = edgeColor.factor; getSh()->edgeColorMap = edgeColor.tex; getSh()->metallic = metallic.factor; getSh()->metallicMap = metallic.tex; getSh()->diffuse = diffuse.factor; getSh()->diffuseMap = diffuse.tex; getSh()->specular = specular.factor; getSh()->specularMap = specular.tex; getSh()->ior = ior.factor; getSh()->iorMap = ior.tex; getSh()->transmission = transmission.factor; getSh()->transmissionMap = transmission.tex; getSh()->transmissionColor = transmissionColor.factor; getSh()->transmissionColorMap = transmissionColor.tex; getSh()->transmissionDepth = transmissionDepth.factor; getSh()->transmissionDepthMap = transmissionDepth.tex; getSh()->roughness = roughness.factor; getSh()->roughnessMap = roughness.tex; getSh()->anisotropy = anisotropy.factor; getSh()->anisotropyMap = anisotropy.tex; getSh()->rotation = rotation.factor; getSh()->rotationMap = rotation.tex; getSh()->normal = normal.factor; getSh()->normalMap = normal.tex; getSh()->normalRot = normal.rot; getSh()->baseNormal = baseNormal.factor; getSh()->baseNormalMap = baseNormal.tex; getSh()->baseNormalRot = baseNormal.rot; getSh()->coat = coat.factor; getSh()->coatMap = coat.tex; getSh()->coatIor = coatIor.factor; getSh()->coatIorMap = coatIor.tex; getSh()->coatColor = coatColor.factor; getSh()->coatColorMap = coatColor.tex; getSh()->coatThickness = coatThickness.factor; getSh()->coatThicknessMap = coatThickness.tex; getSh()->coatRoughness = coatRoughness.factor; getSh()->coatRoughnessMap = coatRoughness.tex; getSh()->coatNormal = coatNormal.factor; getSh()->coatNormalMap = coatNormal.tex; getSh()->coatNormalRot = coatNormal.rot; getSh()->sheen = sheen.factor; getSh()->sheenMap = sheen.tex; getSh()->sheenColor = sheenColor.factor; getSh()->sheenColorMap = sheenColor.tex; getSh()->sheenTint = sheenTint.factor; getSh()->sheenTintMap = sheenTint.tex; getSh()->sheenRoughness = sheenRoughness.factor; getSh()->sheenRoughnessMap = sheenRoughness.tex; getSh()->opacity = opacity.factor; getSh()->opacityMap = opacity.tex; getSh()->thin = thin; getSh()->backlight = backlight.factor; getSh()->backlightMap = backlight.tex; getSh()->thickness = thickness.factor; getSh()->thicknessMap = thickness.tex; getSh()->outsideMedium.ior = outsideIor >= 1.f ? outsideIor : rcp(outsideIor); vec3f otc = vec3f(log(outsideTransmissionColor.x), log(outsideTransmissionColor.y), log(outsideTransmissionColor.z)); getSh()->outsideMedium.attenuation = otc / outsideTransmissionDepth; } } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Principled.h000066400000000000000000000006731456566705700253160ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" // ispc shared #include "PrincipledShared.h" namespace ospray { namespace pathtracer { struct Principled : public AddStructShared { Principled(api::ISPCDevice &device); virtual std::string toString() const override; virtual void commit() override; }; } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Principled.ih000066400000000000000000000024211456566705700254600ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/bsdfs/BSDF.ih" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Material; struct ShadingContext; struct DifferentialGeometry; struct Ray; struct Medium; SYCL_EXTERNAL __noinline const varying BSDF *uniform Principled_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL __noinline vec3f Principled_getTransparency( const uniform Material *uniform super, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL __noinline void Principled_selectNextMedium( const uniform Material *uniform super, const DifferentialGeometry &dg, Medium ¤tMedium); SYCL_EXTERNAL __noinline BSDF_EvalRes Principled_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi); SYCL_EXTERNAL __noinline BSDF_SampleRes Principled_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Principled.ispc000066400000000000000000001026231456566705700260230ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Principled.ih" #include "Medium.ih" #include "common/Ray.ih" #include "render/Material.ih" #include "render/bsdfs/Conductor.ih" #include "render/bsdfs/Dielectric.ih" #include "render/bsdfs/DielectricLayer.ih" #include "render/bsdfs/Lambert.ih" #include "render/bsdfs/LambertTransmission.ih" #include "render/bsdfs/MicrofacetConductor.ih" #include "render/bsdfs/MicrofacetDielectric.ih" #include "render/bsdfs/MicrofacetDielectricLayer.ih" #include "render/bsdfs/MicrofacetSheenLayer.ih" #include "render/bsdfs/MultiBSDF.ih" #include "render/bsdfs/OrenNayar.ih" #include "render/bsdfs/PassthroughLayer.ih" #include "render/bsdfs/ThinDielectric.ih" #include "render/bsdfs/ThinMicrofacetDielectric.ih" #include "render/bsdfs/Transmission.ih" #include "texture/TextureParam.ih" // c++ shared #include "PrincipledShared.h" /////////////////////////////////////////////////////////////////////////////// // Implementation OSPRAY_BEGIN_ISPC_NAMESPACE struct Principled_Diffuse_BSDF { DEFINE_MULTIBSDF(2); OrenNayar lambert; BSDF lambertTransmission; }; struct Principled_Plastic_BSDF { MicrofacetDielectricLayer dielectricLayer; Principled_Diffuse_BSDF diffuse; }; struct Principled_Glass_BSDF { int bsdfId; MicrofacetDielectric dielectric; ThinMicrofacetDielectric thinDielectric; BSDF transmission; }; struct Principled_Base_MultiBSDF { DEFINE_MULTIBSDF(3); MicrofacetConductor metal; Principled_Glass_BSDF glass; Principled_Plastic_BSDF plastic; }; struct Principled_ClearCoat_BSDF { MicrofacetDielectricLayer dielectricLayer; Principled_Base_MultiBSDF base; }; struct Principled_SheenLayer_BSDF { MicrofacetSheenLayer sheenLayer; Principled_ClearCoat_BSDF clearCoat; }; struct Principled_BSDF { DEFINE_MULTIBSDF(2); BSDF transmission; Principled_SheenLayer_BSDF sheen; }; SYCL_EXTERNAL __noinline const varying BSDF *uniform Principled_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &, const Medium ¤tMedium, const uniform FeatureFlagsHandler &) { const uniform Principled *uniform self = (const uniform Principled *uniform)super; // Allocate memory and initialize material BSDF varying Principled_BSDF *uniform bsdf = (varying Principled_BSDF * uniform) ShadingContext_alloc(ctx, sizeof(Principled_BSDF)); varying MultiBSDF *uniform multiRoot = (varying MultiBSDF * uniform) bsdf; MultiBSDF_Constructor(multiRoot, 2); bsdf->super.bsdfType = BSDF_TYPE_PRINCIPLED; // create the default shading frame varying linear3f *uniform frame = LinearSpace3f_create(ctx, makeShadingFrame(dg, self->normalMap, self->normalRot, self->normal)); const float rotation = clamp(self->rotation * get1f(self->rotationMap, dg, 1.f)); const float theta = 2.f * (float)pi * rotation; if (theta > 0.f) { frame->vx = rotate(frame->vx, frame->vz, theta); frame->vy = cross(frame->vz, frame->vx); } float opacity = clamp(self->opacity * get1f(self->opacityMap, dg, 1.f)); if (hasAlpha(self->baseColorMap)) { vec4f baseColorSample = get4f(self->baseColorMap, dg, make_vec4f(1.f)); opacity *= baseColorSample.w; } if (self->opacity > EPS) { varying linear3f *uniform baseFrame = frame; if (valid(self->baseNormalMap)) { baseFrame = LinearSpace3f_create(ctx, makeShadingFrame( dg, self->baseNormalMap, self->baseNormalRot, self->baseNormal)); if (theta > 0.f) { baseFrame->vx = rotate(baseFrame->vx, baseFrame->vz, theta); baseFrame->vy = cross(baseFrame->vz, baseFrame->vx); } } varying MultiBSDF *uniform multiBase = (varying MultiBSDF * uniform) & bsdf->sheen.clearCoat.base; MultiBSDF_Constructor(multiBase, 3); const vec3f baseColor = clamp(self->baseColor * get3f(self->baseColorMap, dg, make_vec3f(1.f)) * make_vec3f(dg.color)); const float specular = clamp(self->specular * get1f(self->specularMap, dg, 1.f)); const float metallic = clamp(self->metallic * get1f(self->metallicMap, dg, 1.f)); const float roughness = clamp(self->roughness * get1f(self->roughnessMap, dg, 1.f)); const float anisotropy = clamp(self->anisotropy * get1f(self->anisotropyMap, dg, 1.f)); const bool fromOutside = self->thin ? true : eq(currentMedium, self->outsideMedium); // dielectric base const float dielectric = (1.f - metallic); if (dielectric > EPS) { const float transmission = clamp(self->transmission * get1f(self->transmissionMap, dg, 1.f)); float ior = self->ior * get1f(self->iorMap, dg, 1.f); if (ior < 1.f) ior = rcp(ior); float eta = fromOutside ? self->outsideMedium.ior * rcp(ior) : ior * rcp(self->outsideMedium.ior); eta = clamp(eta, 1.f / 3.f, 3.f); // clamp to common range due to LUTs // plastic base const float plastic = dielectric * (1.f - transmission); if (plastic > EPS) { varying MultiBSDF *uniform multiDiffuse = (varying MultiBSDF * uniform) & bsdf->sheen.clearCoat.base.plastic.diffuse; MultiBSDF_Constructor(multiDiffuse, 2); varying Principled_Plastic_BSDF *uniform plasticBsdf = &bsdf->sheen.clearCoat.base.plastic; // diffuse const float diffuse = clamp(self->diffuse * get1f(self->diffuseMap, dg, 1.f)); const vec3f diffuseColor = baseColor * diffuse; const float backlight = self->thin ? clamp( self->backlight * get1f(self->backlightMap, dg, 1.f), 0.f, 2.f) : 0.f; const float diffuseTransmission = backlight * 0.5f; const float diffuseReflection = 1.f - diffuseTransmission; if (diffuseReflection > EPS) { if (self->roughness < EPS) Lambert_Constructor( &plasticBsdf->diffuse.lambert.super, baseFrame, diffuseColor); else OrenNayar_Constructor(&plasticBsdf->diffuse.lambert, baseFrame, diffuseColor, roughness); MultiBSDF_add(multiDiffuse, 0, &plasticBsdf->diffuse.lambert.super, diffuseReflection, diffuseReflection); } if (diffuseTransmission > EPS) { LambertTransmission_Constructor( &plasticBsdf->diffuse.lambertTransmission, baseFrame, diffuseColor); MultiBSDF_add(multiDiffuse, 1, &plasticBsdf->diffuse.lambertTransmission, diffuseTransmission, diffuseTransmission); } // specular if (self->specular > EPS) { if (self->roughness < EPS) { DielectricLayer_Constructor((varying DielectricLayer * uniform) & plasticBsdf->dielectricLayer, baseFrame, &plasticBsdf->diffuse.super, eta, make_vec3f(1.f), 1.f, specular); } else { MicrofacetDielectricLayer_Constructor(&plasticBsdf->dielectricLayer, super->microfacetAlbedoTables, baseFrame, &plasticBsdf->diffuse.super, eta, make_vec3f(1.f), 1.f, roughness, anisotropy, specular); } } else { PassthroughLayer_Constructor((varying PassthroughLayer * uniform) & plasticBsdf->dielectricLayer, &plasticBsdf->diffuse.super); } MultiBSDF_add(multiBase, 2, &plasticBsdf->dielectricLayer.super, plastic, plastic * max(diffuse, specular)); } // glass base const float glass = dielectric * transmission * specular; if (glass > EPS) { varying Principled_Glass_BSDF *uniform glassBsdf = &bsdf->sheen.clearCoat.base.glass; if (abs(eta - 1.f) > EPS) { if (!self->thin) { if (self->roughness < EPS) Dielectric_Constructor( (varying Dielectric * uniform) & glassBsdf->dielectric, baseFrame, eta); else MicrofacetDielectric_Constructor(&glassBsdf->dielectric, super->microfacetAlbedoTables, baseFrame, eta, roughness, anisotropy); glassBsdf->bsdfId = 1; MultiBSDF_add( multiBase, 1, &glassBsdf->dielectric.super, glass, glass); } else { // thin const vec3f transmissionColor = clamp(self->transmissionColor * get3f(self->transmissionColorMap, dg, make_vec3f(1.f))); const float transmissionDepth = max(self->transmissionDepth * get1f(self->transmissionDepthMap, dg, 1.f), EPS); const float thickness = max(self->thickness * get1f(self->thicknessMap, dg, 1.f), 0.f); const vec3f attenuation = logf(transmissionColor) / transmissionDepth * thickness; if (self->roughness < EPS) ThinDielectric_Constructor((varying ThinDielectric * uniform) & glassBsdf->thinDielectric, baseFrame, eta, attenuation); else ThinMicrofacetDielectric_Constructor(&glassBsdf->thinDielectric, super->microfacetAlbedoTables, baseFrame, eta, roughness, anisotropy, attenuation); glassBsdf->bsdfId = 2; MultiBSDF_add( multiBase, 1, &glassBsdf->thinDielectric.super, glass, glass); } } else { Transmission_Constructor( &glassBsdf->transmission, baseFrame, make_vec3f(1.f)); glassBsdf->bsdfId = 0; MultiBSDF_add(multiBase, 1, &glassBsdf->transmission, glass, glass); } } } // conductor base const float conductor = metallic * specular; if (conductor > EPS) { const vec3f edgeColor = clamp( self->edgeColor * get3f(self->edgeColorMap, dg, make_vec3f(1.f))); Fresnel *uniform fresnel = FresnelConductorArtistic_create(ctx, baseColor, edgeColor); varying MicrofacetConductor *uniform metalBsdf = &bsdf->sheen.clearCoat.base.metal; if (self->roughness < EPS) Conductor_Constructor( (varying Conductor * uniform) metalBsdf, baseFrame, fresnel); else MicrofacetConductor_Constructor(metalBsdf, super->microfacetAlbedoTables, baseFrame, fresnel, roughness, anisotropy); MultiBSDF_add(multiBase, 0, &metalBsdf->super, conductor, conductor); } // coatings varying linear3f *uniform coatFrame = frame; // clear coat if (self->coat > EPS) { const float coat = clamp(self->coat * get1f(self->coatMap, dg, 1.f)); float coatIor = self->coatIor * get1f(self->coatIorMap, dg, 1.f); if (coatIor < 1.f) coatIor = rcp(coatIor); float coatEta = fromOutside ? self->outsideMedium.ior * rcp(coatIor) : coatIor * rcp(self->outsideMedium.ior); coatEta = clamp(coatEta, 1.f / 3.f, 3.f); // clamp to common range due to LUTs const vec3f coatColor = clamp( self->coatColor * get3f(self->coatColorMap, dg, make_vec3f(1.f))); const float coatThickness = max( self->coatThickness * get1f(self->coatThicknessMap, dg, 1.f), 0.f); if (valid(self->coatNormalMap)) { coatFrame = LinearSpace3f_create(ctx, makeShadingFrame(dg, self->coatNormalMap, self->coatNormalRot, self->coatNormal)); } if (self->coatRoughness < EPS || abs(coatEta - 1.f) < EPS) { DielectricLayer_Constructor((varying DielectricLayer * uniform) & bsdf->sheen.clearCoat.dielectricLayer, coatFrame, &bsdf->sheen.clearCoat.base.super, coatEta, coatColor, coatThickness, coat); } else { const float coatRoughness = clamp(self->coatRoughness * get1f(self->coatRoughnessMap, dg, 1.f)); MicrofacetDielectricLayer_Constructor( &bsdf->sheen.clearCoat.dielectricLayer, super->microfacetAlbedoTables, coatFrame, &bsdf->sheen.clearCoat.base.super, coatEta, coatColor, coatThickness, coatRoughness, 0.f, coat); } } else { PassthroughLayer_Constructor((varying PassthroughLayer * uniform) & bsdf->sheen.clearCoat.dielectricLayer, &bsdf->sheen.clearCoat.base.super); } // sheen if (self->sheen > EPS) { const float sheen = clamp(self->sheen * get1f(self->sheenMap, dg, 1.f)); vec3f sheenColor = clamp( self->sheenColor * get3f(self->sheenColorMap, dg, make_vec3f(1.f))); const float sheenTint = clamp(self->sheenTint * get1f(self->sheenTintMap, dg, 1.f)); sheenColor = lerp(sheenTint, sheenColor, baseColor); const float sheenRoughness = clamp(self->sheenRoughness * get1f(self->sheenRoughnessMap, dg, 1.f)); MicrofacetSheenLayer_Constructor(&bsdf->sheen.sheenLayer, super->microfacetAlbedoTables, coatFrame, &bsdf->sheen.clearCoat.dielectricLayer.super, sheenColor, sheenRoughness, sheen); } else PassthroughLayer_Constructor( (varying PassthroughLayer * uniform) & bsdf->sheen.sheenLayer, &bsdf->sheen.clearCoat.dielectricLayer.super); MultiBSDF_add( multiRoot, 1, &bsdf->sheen.sheenLayer.super, opacity, opacity); } // cut-out transparency const float transparency = 1.f - opacity; if (transparency > EPS) { Transmission_Constructor( &bsdf->transmission, frame, make_vec3f(transparency)); MultiBSDF_add(multiRoot, 0, &bsdf->transmission, 1.f, transparency); } return &bsdf->super; } SYCL_EXTERNAL __noinline vec3f Principled_getTransparency( const uniform Material *uniform super, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &) { const uniform Principled *uniform self = (const uniform Principled *uniform)super; vec3f T = make_vec3f(0.f); float opacity = clamp(self->opacity * get1f(self->opacityMap, dg, 1.f)); if (hasAlpha(self->baseColorMap)) { vec4f baseColorSample = get4f(self->baseColorMap, dg, make_vec4f(1.f)); opacity *= baseColorSample.w; } const float transparency = 1.f - opacity; const float transmission = clamp(self->transmission * get1f(self->transmissionMap, dg, 1.f)); // early exit if (transparency <= EPS && transmission <= EPS) return T; // cut-out opacity if (self->opacity > EPS) { // glass base const float specular = clamp(self->specular * get1f(self->specularMap, dg, 1.f)); const float metallic = clamp(self->metallic * get1f(self->metallicMap, dg, 1.f)); const float dielectric = (1.f - metallic); const float glass = dielectric * transmission * specular; if (glass > EPS) { const bool fromOutside = self->thin ? true : eq(currentMedium, self->outsideMedium); float ior = self->ior * get1f(self->iorMap, dg, 1.f); if (ior < 1.f) ior = rcp(ior); float eta = fromOutside ? self->outsideMedium.ior * rcp(ior) : ior * rcp(self->outsideMedium.ior); eta = clamp(eta, 1.f / 3.f, 3.f); // clamp to common range due to LUTs const float cosThetaO = max(-dot(ray.dir, dg.Ns), 0.f); if (abs(eta - 1.f) > EPS) { if (!self->thin) { // solid // use microfacet if textured due to different // transparent shadow behavior if (self->roughness < EPS) T = Dielectric_getTransparency(cosThetaO, eta); } else { // thin const vec3f transmissionColor = clamp(self->transmissionColor * get3f(self->transmissionColorMap, dg, make_vec3f(1.f))); const float transmissionDepth = max(self->transmissionDepth * get1f(self->transmissionDepthMap, dg, 1.f), EPS); const float thickness = max(self->thickness * get1f(self->thicknessMap, dg, 1.f), 0.f); const vec3f attenuation = logf(transmissionColor) / transmissionDepth * thickness; if (self->roughness < EPS) { T = ThinDielectric_getTransparency(cosThetaO, eta, attenuation); } else { const float roughness = clamp(self->roughness * get1f(self->roughnessMap, dg, 1.f)); T = ThinMicrofacetDielectric_getTransparency( super->microfacetAlbedoTables, cosThetaO, eta, roughness, attenuation); } } } else { T = make_vec3f(1.f); } if (reduce_max(T) > 0.f) { // clear coat if (self->coat > EPS) { const float coat = clamp(self->coat * get1f(self->coatMap, dg, 1.f)); float coatIor = self->coatIor * get1f(self->coatIorMap, dg, 1.f); if (coatIor < 1.f) coatIor = rcp(coatIor); float coatEta = fromOutside ? self->outsideMedium.ior * rcp(coatIor) : coatIor * rcp(self->outsideMedium.ior); coatEta = clamp( coatEta, 1.f / 3.f, 3.f); // clamp to common range due to LUTs if (abs(coatEta - 1.f) > EPS) { const float coatEta = fromOutside ? self->outsideMedium.ior * rcp(coatIor) : coatIor * rcp(self->outsideMedium.ior); const vec3f coatColor = clamp(self->coatColor * get3f(self->coatColorMap, dg, make_vec3f(1.f))); const float coatThickness = max( self->coatThickness * get1f(self->coatThicknessMap, dg, 1.f), 0.f); if (self->coatRoughness < EPS) { T = T * DielectricLayer_getTransparency( cosThetaO, coatEta, coatColor, coatThickness, coat); } else { const float coatRoughness = clamp( self->coatRoughness * get1f(self->coatRoughnessMap, dg, 1.f)); T = T * MicrofacetDielectricLayer_getTransparency( super->microfacetAlbedoTables, cosThetaO, coatEta, coatColor, coatThickness, coatRoughness, 0.f, coat); } } } // sheen if (self->sheen > EPS) { const float sheen = clamp(self->sheen * get1f(self->sheenMap, dg, 1.f)); const float sheenRoughness = clamp( self->sheenRoughness * get1f(self->sheenRoughnessMap, dg, 1.f)); T = T * MicrofacetSheenLayer_getTransparency( super->microfacetAlbedoTables, cosThetaO, sheenRoughness, sheen); } T = T * glass; } } } // cut-out transparency T = T * opacity + transparency; return T; } SYCL_EXTERNAL __noinline void Principled_selectNextMedium( const uniform Material *uniform super, const DifferentialGeometry &dg, Medium ¤tMedium) { const uniform Principled *uniform self = (const uniform Principled *uniform)super; if (self->thin || self->transmission <= EPS) return; if (eq(currentMedium, self->outsideMedium)) { float ior = self->ior * get1f(self->iorMap, dg, 1.f); if (ior < 1.f) ior = rcp(ior); const vec3f transmissionColor = clamp(self->transmissionColor * get3f(self->transmissionColorMap, dg, make_vec3f(1.f))); const float transmissionDepth = max( self->transmissionDepth * get1f(self->transmissionDepthMap, dg, 1.f), EPS); currentMedium.ior = ior; currentMedium.attenuation = logf(transmissionColor) / transmissionDepth; } else { currentMedium = self->outsideMedium; } } // Lambert BSDF __noinline BSDF_EvalRes LambertBSDF_eval( const varying OrenNayar *uniform self, const vec3f &wo, const vec3f &wi) { if (self->super.bsdfType == BSDF_TYPE_OREN_NAYAR) return OrenNayar_eval(&self->super, wo, wi); else return Lambert_eval(&self->super, wo, wi); } __noinline BSDF_SampleRes LambertBSDF_sample( const varying OrenNayar *uniform self, const vec3f &wo, const vec2f &s, float ss) { if (self->super.bsdfType == BSDF_TYPE_OREN_NAYAR) return OrenNayar_sample(&self->super, wo, s, ss); else return Lambert_sample(&self->super, wo, s, ss); } // Diffuse BSDF __noinline BSDF_EvalRes DiffuseBSDF_eval( const varying Principled_Diffuse_BSDF *uniform self, const vec3f &wo, const vec3f &wi) { MULTIBSDF_EVAL_BEGIN(); MULTIBSDF_EVAL_CHILD(0, &self->lambert, LambertBSDF_eval); MULTIBSDF_EVAL_CHILD(1, &self->lambertTransmission, LambertTransmission_eval); MULTIBSDF_EVAL_END(); return MULTIBSDF_EVAL_GET(); } __noinline BSDF_SampleRes DiffuseBSDF_sample( const varying Principled_Diffuse_BSDF *uniform self, const vec3f &wo, const vec2f &s, float ss) { MULTIBSDF_SAMPLE_BEGIN(); MULTIBSDF_SAMPLE_CHILD(0, &self->lambert, LambertBSDF_sample); MULTIBSDF_SAMPLE_CHILD( 1, &self->lambertTransmission, LambertTransmission_sample); MULTIBSDF_SAMPLE_EVAL(); MULTIBSDF_EVAL_CHILD(0, &self->lambert, LambertBSDF_eval); MULTIBSDF_EVAL_CHILD(1, &self->lambertTransmission, LambertTransmission_eval); MULTIBSDF_SAMPLE_END(); return MULTIBSDF_SAMPLE_GET(); } // Plastic DielectricLayer BSDF inline BSDF_EvalRes Plastic_DielectricLayerBSDF_eval( const varying Principled_Plastic_BSDF *uniform self, const vec3f &wo, const vec3f &wi) { DIELECTRICLAYER_EVAL(self->dielectricLayer, self->diffuse.super.scatteringType, &self->diffuse, DiffuseBSDF_eval); return DIELECTRICLAYER_EVAL_GET(); } inline BSDF_SampleRes Plastic_DielectricLayerBSDF_sample( const varying Principled_Plastic_BSDF *uniform self, const vec3f &wo, const vec2f &s, float ss) { DIELECTRICLAYER_SAMPLE(self->dielectricLayer, self->diffuse.super.scatteringType, &self->diffuse, DiffuseBSDF_sample); return DIELECTRICLAYER_SAMPLE_GET(); } // Plastic MicrofacetDielectricLayer BSDF inline BSDF_EvalRes Plastic_MicrofacetDielectricLayerBSDF_eval( const varying Principled_Plastic_BSDF *uniform self, const vec3f &wo, const vec3f &wi) { MICROFACETDIELECTRICLAYER_EVAL(self->dielectricLayer, self->diffuse.super.scatteringType, &self->diffuse, DiffuseBSDF_eval); return MICROFACETDIELECTRICLAYER_EVAL_GET(); } inline BSDF_SampleRes Plastic_MicrofacetDielectricLayerBSDF_sample( const varying Principled_Plastic_BSDF *uniform self, const vec3f &wo, const vec2f &s, float ss) { MICROFACETDIELECTRICLAYER_SAMPLE(self->dielectricLayer, self->diffuse.super.scatteringType, &self->diffuse, DiffuseBSDF_eval, DiffuseBSDF_sample); return MICROFACETDIELECTRICLAYER_SAMPLE_GET(); } // Plastic BSDF __noinline BSDF_EvalRes PlasticBSDF_eval( const varying Principled_Plastic_BSDF *uniform self, const vec3f &wo, const vec3f &wi) { // Skip dielectric layer if no specular if (self->dielectricLayer.weight < EPS) return DiffuseBSDF_eval(&self->diffuse, wo, wi); if (self->dielectricLayer.super.bsdfType == BSDF_TYPE_MICROFACET_DIELECTRIC_LAYER) return Plastic_MicrofacetDielectricLayerBSDF_eval(self, wo, wi); else return Plastic_DielectricLayerBSDF_eval(self, wo, wi); } __noinline BSDF_SampleRes PlasticBSDF_sample( const varying Principled_Plastic_BSDF *uniform self, const vec3f &wo, const vec2f &s, float ss) { // Skip dielectric layer if no specular if (self->dielectricLayer.weight < EPS) return DiffuseBSDF_sample(&self->diffuse, wo, s, ss); if (self->dielectricLayer.super.bsdfType == BSDF_TYPE_MICROFACET_DIELECTRIC_LAYER) return Plastic_MicrofacetDielectricLayerBSDF_sample(self, wo, s, ss); else return Plastic_DielectricLayerBSDF_sample(self, wo, s, ss); } // Glass Dielectric BSDF inline BSDF_EvalRes Glass_DielectricBSDF_eval( const varying MicrofacetDielectric *uniform self, const vec3f &wo, const vec3f &wi) { if (self->super.bsdfType == BSDF_TYPE_MICROFACET_DIELECTRIC) return MicrofacetDielectric_eval(&self->super, wo, wi); else return Dielectric_eval(&self->super, wo, wi); } inline BSDF_SampleRes Glass_DielectricBSDF_sample( const varying MicrofacetDielectric *uniform self, const vec3f &wo, const vec2f &s, float ss) { if (self->super.bsdfType == BSDF_TYPE_MICROFACET_DIELECTRIC) return MicrofacetDielectric_sample(&self->super, wo, s, ss); else return Dielectric_sample(&self->super, wo, s, ss); } // Glass ThinDielectric BSDF inline BSDF_EvalRes Glass_ThinDielectricBSDF_eval( const varying ThinMicrofacetDielectric *uniform self, const vec3f &wo, const vec3f &wi) { if (self->super.bsdfType == BSDF_TYPE_THIN_MICROFACET_DIELECTRIC) return ThinMicrofacetDielectric_eval(&self->super, wo, wi); else return ThinDielectric_eval(&self->super, wo, wi); } inline BSDF_SampleRes Glass_ThinDielectricBSDF_sample( const varying ThinMicrofacetDielectric *uniform self, const vec3f &wo, const vec2f &s, float ss) { if (self->super.bsdfType == BSDF_TYPE_THIN_MICROFACET_DIELECTRIC) return ThinMicrofacetDielectric_sample(&self->super, wo, s, ss); else return ThinDielectric_sample(&self->super, wo, s, ss); } // Glass BSDF __noinline BSDF_EvalRes GlassBSDF_eval( const varying Principled_Glass_BSDF *uniform self, const vec3f &wo, const vec3f &wi) { if (self->bsdfId == 1) return Glass_DielectricBSDF_eval(&self->dielectric, wo, wi); else if (self->bsdfId == 2) return Glass_ThinDielectricBSDF_eval(&self->thinDielectric, wo, wi); else return make_BSDF_EvalRes_zero(); } __noinline BSDF_SampleRes GlassBSDF_sample( const varying Principled_Glass_BSDF *uniform self, const vec3f &wo, const vec2f &s, float ss) { if (self->bsdfId == 1) return Glass_DielectricBSDF_sample(&self->dielectric, wo, s, ss); else if (self->bsdfId == 2) return Glass_ThinDielectricBSDF_sample(&self->thinDielectric, wo, s, ss); else return Transmission_sample(&self->transmission, wo, s, ss); } // Metal BSDF __noinline BSDF_EvalRes MetalBSDF_eval( const varying MicrofacetConductor *uniform self, const vec3f &wo, const vec3f &wi) { if (self->super.bsdfType == BSDF_TYPE_MICROFACET_CONDUCTOR) return MicrofacetConductor_eval(self, wo, wi); else return make_BSDF_EvalRes_zero(); } __noinline BSDF_SampleRes MetalBSDF_sample( const varying MicrofacetConductor *uniform self, const vec3f &wo, const vec2f &s, float ss) { if (self->super.bsdfType == BSDF_TYPE_MICROFACET_CONDUCTOR) return MicrofacetConductor_sample(self, wo, s, ss); else return Conductor_sample(&self->super, wo, s, ss); } // Base BSDF __noinline BSDF_EvalRes BaseBSDF_eval( const varying Principled_Base_MultiBSDF *uniform self, const vec3f &wo, const vec3f &wi) { MULTIBSDF_EVAL_BEGIN(); MULTIBSDF_EVAL_CHILD(0, &self->metal, MetalBSDF_eval); MULTIBSDF_EVAL_CHILD(1, &self->glass, GlassBSDF_eval); MULTIBSDF_EVAL_CHILD(2, &self->plastic, PlasticBSDF_eval); MULTIBSDF_EVAL_END(); return MULTIBSDF_EVAL_GET(); } __noinline BSDF_SampleRes BaseBSDF_sample( const varying Principled_Base_MultiBSDF *uniform self, const vec3f &wo, const vec2f &s, float ss) { MULTIBSDF_SAMPLE_BEGIN(); MULTIBSDF_SAMPLE_CHILD(0, &self->metal, MetalBSDF_sample); MULTIBSDF_SAMPLE_CHILD(1, &self->glass, GlassBSDF_sample); MULTIBSDF_SAMPLE_CHILD(2, &self->plastic, PlasticBSDF_sample); MULTIBSDF_SAMPLE_EVAL(); MULTIBSDF_EVAL_CHILD(0, &self->metal, MetalBSDF_eval); MULTIBSDF_EVAL_CHILD(1, &self->glass, GlassBSDF_eval); MULTIBSDF_EVAL_CHILD(2, &self->plastic, PlasticBSDF_eval); MULTIBSDF_SAMPLE_END(); return MULTIBSDF_SAMPLE_GET(); } // ClearCoat DielectricLayer BSDF inline BSDF_EvalRes ClearCoat_DielectricLayerBSDF_eval( const varying Principled_ClearCoat_BSDF *uniform self, const vec3f &wo, const vec3f &wi) { DIELECTRICLAYER_EVAL(self->dielectricLayer, self->base.super.scatteringType, &self->base, BaseBSDF_eval); return DIELECTRICLAYER_EVAL_GET(); } inline BSDF_SampleRes ClearCoat_DielectricLayerBSDF_sample( const varying Principled_ClearCoat_BSDF *uniform self, const vec3f &wo, const vec2f &s, float ss) { DIELECTRICLAYER_SAMPLE(self->dielectricLayer, self->base.super.scatteringType, &self->base, BaseBSDF_sample); return DIELECTRICLAYER_SAMPLE_GET(); } // ClearCoat MicrofacetDielectricLayer BSDF inline BSDF_EvalRes ClearCoat_MicrofacetDielectricLayerBSDF_eval( const varying Principled_ClearCoat_BSDF *uniform self, const vec3f &wo, const vec3f &wi) { MICROFACETDIELECTRICLAYER_EVAL(self->dielectricLayer, self->base.super.scatteringType, &self->base, BaseBSDF_eval); return MICROFACETDIELECTRICLAYER_EVAL_GET(); } inline BSDF_SampleRes ClearCoat_MicrofacetDielectricLayerBSDF_sample( const varying Principled_ClearCoat_BSDF *uniform self, const vec3f &wo, const vec2f &s, float ss) { MICROFACETDIELECTRICLAYER_SAMPLE(self->dielectricLayer, self->base.super.scatteringType, &self->base, BaseBSDF_eval, BaseBSDF_sample); return MICROFACETDIELECTRICLAYER_SAMPLE_GET(); } // ClearCoat BSDF __noinline BSDF_EvalRes ClearCoatBSDF_eval( const varying Principled_ClearCoat_BSDF *uniform self, const vec3f &wo, const vec3f &wi) { // Skip dielectric layer if no clear coat if (self->dielectricLayer.weight < EPS) return BaseBSDF_eval(&self->base, wo, wi); if (self->dielectricLayer.super.bsdfType == BSDF_TYPE_MICROFACET_DIELECTRIC_LAYER) return ClearCoat_MicrofacetDielectricLayerBSDF_eval(self, wo, wi); else return ClearCoat_DielectricLayerBSDF_eval(self, wo, wi); } __noinline BSDF_SampleRes ClearCoatBSDF_sample( const varying Principled_ClearCoat_BSDF *uniform self, const vec3f &wo, const vec2f &s, float ss) { // Skip dielectric layer if no clear coat if (self->dielectricLayer.weight < EPS) return BaseBSDF_sample(&self->base, wo, s, ss); if (self->dielectricLayer.super.bsdfType == BSDF_TYPE_MICROFACET_DIELECTRIC_LAYER) return ClearCoat_MicrofacetDielectricLayerBSDF_sample(self, wo, s, ss); else return ClearCoat_DielectricLayerBSDF_sample(self, wo, s, ss); } // SheenLayer BSDF __noinline BSDF_EvalRes SheenLayerBSDF_eval( const varying Principled_SheenLayer_BSDF *uniform self, const vec3f &wo, const vec3f &wi) { // Skip sheen layer if does not exists if (self->sheenLayer.weight < EPS) return ClearCoatBSDF_eval(&self->clearCoat, wo, wi); MICROFACETSHEENLAYER_EVAL( self->sheenLayer, &self->clearCoat, ClearCoatBSDF_eval); return MICROFACETSHEENLAYER_EVAL_GET(); } __noinline BSDF_SampleRes SheenLayerBSDF_sample( const varying Principled_SheenLayer_BSDF *uniform self, const vec3f &wo, const vec2f &s, float ss) { // Skip sheen layer if does not exists if (self->sheenLayer.weight < EPS) return ClearCoatBSDF_sample(&self->clearCoat, wo, s, ss); MICROFACETSHEENLAYER_SAMPLE(self->sheenLayer, &self->clearCoat, ClearCoatBSDF_eval, ClearCoatBSDF_sample); return MICROFACETSHEENLAYER_SAMPLE_GET(); } // Principled BSDF SYCL_EXTERNAL __noinline BSDF_EvalRes Principled_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi) { const varying Principled_BSDF *uniform self = (const varying Principled_BSDF *uniform)super; MULTIBSDF_EVAL_BEGIN(); // 0 - omitted, no evaluation needed for transmission BSDF MULTIBSDF_EVAL_CHILD(1, &self->sheen, SheenLayerBSDF_eval); MULTIBSDF_EVAL_END(); return MULTIBSDF_EVAL_GET(); } SYCL_EXTERNAL __noinline BSDF_SampleRes Principled_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss) { const varying Principled_BSDF *uniform self = (const varying Principled_BSDF *uniform)super; MULTIBSDF_SAMPLE_BEGIN(); MULTIBSDF_SAMPLE_CHILD(0, &self->transmission, Transmission_sample); MULTIBSDF_SAMPLE_CHILD(1, &self->sheen, SheenLayerBSDF_sample); MULTIBSDF_SAMPLE_EVAL(); // 0 - omitted, no evaluation needed for transmission BSDF MULTIBSDF_EVAL_CHILD(1, &self->sheen, SheenLayerBSDF_eval); MULTIBSDF_SAMPLE_END(); return MULTIBSDF_SAMPLE_GET(); } /////////////////////////////////////////////////////////////////////////////// // External API export void *uniform Principled_getBSDF_addr() { return (void *uniform)Principled_getBSDF; } export void *uniform Principled_getTransparency_addr() { return (void *uniform)Principled_getTransparency; } export void *uniform Principled_selectNextMedium_addr() { return (void *uniform)Principled_selectNextMedium; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/PrincipledShared.h000066400000000000000000000065761456566705700264550ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "MediumShared.h" #include "render/MaterialShared.h" #include "texture/TextureParamShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Principled { Material super; vec3f baseColor; TextureParam baseColorMap; // metallic reflectivity at grazing angle (90 deg) / edge tint vec3f edgeColor; TextureParam edgeColorMap; float metallic; TextureParam metallicMap; // diffuse weight in [0, 1] float diffuse; TextureParam diffuseMap; // specular weight in [0, 1] float specular; TextureParam specularMap; // index of refraction float ior; TextureParam iorMap; // specular transmission in [0, 1] float transmission; TextureParam transmissionMap; vec3f transmissionColor; TextureParam transmissionColorMap; float transmissionDepth; TextureParam transmissionDepthMap; // roughness in [0, 1]; 0 = ideally smooth (mirror) float roughness; TextureParam roughnessMap; // degree of anisotropy in [0, 1]; 0 = isotropic, 1 = maximally anisotropic float anisotropy; TextureParam anisotropyMap; // anisotropic rotation in [0, 1]; float rotation; TextureParam rotationMap; // default normal map for all layers float normal; // scale TextureParam normalMap; linear2f normalRot; // base normal map (overrides default normal) float baseNormal; // scale TextureParam baseNormalMap; linear2f baseNormalRot; // dielectric clear coat weight in [0, 1] float coat; TextureParam coatMap; // dielectric clear coat index of refraction float coatIor; TextureParam coatIorMap; vec3f coatColor; TextureParam coatColorMap; float coatThickness; TextureParam coatThicknessMap; float coatRoughness; TextureParam coatRoughnessMap; // clear coat normal map (overrides default normal) float coatNormal; // scale TextureParam coatNormalMap; linear2f coatNormalRot; // sheen weight in [0, 1] float sheen; TextureParam sheenMap; vec3f sheenColor; TextureParam sheenColorMap; // sheen tint in [0, 1] float sheenTint; TextureParam sheenTintMap; float sheenRoughness; TextureParam sheenRoughnessMap; // cut-out opacity in [0, 1] float opacity; TextureParam opacityMap; // solid or thin mode flag bool thin; // diffuse transmission in [0, 2] (thin only) float backlight; TextureParam backlightMap; // thickness (thin only) float thickness; TextureParam thicknessMap; Medium outsideMedium; #ifdef __cplusplus Principled() : baseColor(0.8f), edgeColor(1.f), metallic(0.f), diffuse(1.f), specular(1.f), ior(1.f), transmission(0.f), transmissionColor(1.f), transmissionDepth(1.f), roughness(0.f), anisotropy(0.f), rotation(0.f), normal(1.f), normalRot(one), baseNormal(1.f), baseNormalRot(one), coat(0.f), coatIor(1.5f), coatColor(1.f), coatThickness(1.f), coatRoughness(0.f), coatNormal(1.f), coatNormalRot(one), sheen(0.f), sheenColor(1.f), sheenTint(0.f), sheenRoughness(0.2f), opacity(1.f), thin(false), backlight(0.f), thickness(1.f) { super.type = ispc::MATERIAL_TYPE_PRINCIPLED; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/materials/ThinGlass.cpp000066400000000000000000000026221456566705700254500ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ThinGlass.h" #ifndef OSPRAY_TARGET_SYCL // ispc #include "render/materials/ThinGlass_ispc.h" #endif namespace ospray { namespace pathtracer { ThinGlass::ThinGlass(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFO_MATERIAL_THINGLASS) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.getBSDF = reinterpret_cast( ispc::ThinGlass_getBSDF_addr()); getSh()->super.getTransparency = reinterpret_cast( ispc::ThinGlass_getTransparency_addr()); #endif } std::string ThinGlass::toString() const { return "ospray::pathtracer::ThinGlass"; } void ThinGlass::commit() { const float eta = getParam("eta", 1.5f); MaterialParam3f attenuationColor = getMaterialParam3f("attenuationColor", vec3f(1.f)); const float attenuationDistance = getParam("attenuationDistance", 1.f); const float thickness = getParam("thickness", 1.f); getSh()->eta = rcp(eta); getSh()->attenuationScale = thickness * rcp(std::max(attenuationDistance, EPS)); const vec3f &acf = attenuationColor.factor; getSh()->attenuation = vec3f(log(acf.x), log(acf.y), log(acf.z)) * getSh()->attenuationScale; getSh()->attenuationColorMap = attenuationColor.tex; } } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/ThinGlass.h000066400000000000000000000006671456566705700251240ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" // ispc shared #include "ThinGlassShared.h" namespace ospray { namespace pathtracer { struct ThinGlass : public AddStructShared { ThinGlass(api::ISPCDevice &device); virtual std::string toString() const override; virtual void commit() override; }; } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/ThinGlass.ih000066400000000000000000000016771456566705700252770ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/bsdfs/BSDF.ih" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Material; struct ShadingContext; struct DifferentialGeometry; struct Ray; struct Medium; SYCL_EXTERNAL const varying BSDF *uniform ThinGlass_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL vec3f ThinGlass_getTransparency( const uniform Material *uniform super, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL BSDF_SampleRes ThinGlass_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/ThinGlass.ispc000066400000000000000000000045251456566705700256300ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ThinGlass.ih" #include "common/Ray.ih" #include "render/Material.ih" #include "render/bsdfs/RobustThinDielectric.ih" #include "texture/TextureParam.ih" // c++ shared #include "ThinGlassShared.h" /////////////////////////////////////////////////////////////////////////////// // Implementation OSPRAY_BEGIN_ISPC_NAMESPACE static inline const vec3f getAttenuation( const ThinGlass *uniform self, const DifferentialGeometry &dg) { vec3f attenuation = self->attenuation + logf(make_vec3f(dg.color)) * self->attenuationScale; if (valid(self->attenuationColorMap)) { vec3f attenuationColor = get3f(self->attenuationColorMap, dg); attenuation = attenuation + logf(attenuationColor) * self->attenuationScale; } return attenuation; } SYCL_EXTERNAL const varying BSDF *uniform ThinGlass_getBSDF( const Material *uniform super, ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &, const Medium &, const uniform FeatureFlagsHandler &) { const ThinGlass *uniform self = (const ThinGlass *uniform)super; varying linear3f *uniform shadingframe = LinearSpace3f_create(ctx, frame(dg.Ns)); varying BSDF *uniform bsdf = RobustThinDielectric_create( ctx, shadingframe, self->eta, getAttenuation(self, dg)); bsdf->bsdfType = BSDF_TYPE_THINGLASS; return bsdf; } SYCL_EXTERNAL vec3f ThinGlass_getTransparency(const Material *uniform material, const DifferentialGeometry &dg, const Ray &ray, const Medium &, const uniform FeatureFlagsHandler &) { const ThinGlass *uniform self = (const ThinGlass *uniform)material; float cosThetaO = max(-dot(ray.dir, dg.Ns), 0.0f); return RobustThinDielectric_getTransparency( cosThetaO, self->eta, getAttenuation(self, dg)); } SYCL_EXTERNAL BSDF_SampleRes ThinGlass_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss) { return RobustThinDielectric_sample(super, wo, s, ss); } /////////////////////////////////////////////////////////////////////////////// // External API export void *uniform ThinGlass_getBSDF_addr() { return (void *uniform)ThinGlass_getBSDF; } export void *uniform ThinGlass_getTransparency_addr() { return (void *uniform)ThinGlass_getTransparency; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/ThinGlassShared.h000066400000000000000000000015261456566705700262460ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/MaterialShared.h" #include "texture/TextureParamShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct ThinGlass { Material super; float eta; // reciprocal refraction index of internal medium // assumed to be <=1 vec3f attenuation; // negative Napierian attenuation coefficient, // i.e. wrt. the natural base e float attenuationScale; // factor to scale attenuation from texture due to // thickness and attenuationDistance TextureParam attenuationColorMap; #ifdef __cplusplus ThinGlass() : eta(1.5f), attenuation(0.f), attenuationScale(1.f) { super.type = ispc::MATERIAL_TYPE_THINGLASS; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Velvet.cpp000066400000000000000000000022441456566705700250210ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Velvet.h" #ifndef OSPRAY_TARGET_SYCL // ispc #include "render/materials/Velvet_ispc.h" #endif namespace ospray { namespace pathtracer { Velvet::Velvet(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFO_MATERIAL_VELVET) { #ifndef OSPRAY_TARGET_SYCL getSh()->super.getBSDF = reinterpret_cast(ispc::Velvet_getBSDF_addr()); #endif } std::string Velvet::toString() const { return "ospray::pathtracer::Velvet"; } void Velvet::commit() { vec3f reflectance = getParam("reflectance", vec3f(.4f, 0.f, 0.f)); float backScattering = getParam("backScattering", .5f); vec3f horizonScatteringColor = getParam("horizonScatteringColor", vec3f(.75f, .1f, .1f)); float horizonScatteringFallOff = getParam("horizonScatteringFallOff", 10); getSh()->reflectance = reflectance; getSh()->backScattering = backScattering; getSh()->horizonScatteringColor = horizonScatteringColor; getSh()->horizonScatteringFallOff = horizonScatteringFallOff; } } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Velvet.h000066400000000000000000000006531456566705700244700ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/Material.h" // ispc shared #include "VelvetShared.h" namespace ospray { namespace pathtracer { struct Velvet : public AddStructShared { Velvet(api::ISPCDevice &device); virtual std::string toString() const override; virtual void commit() override; }; } // namespace pathtracer } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Velvet.ih000066400000000000000000000015201456566705700246330ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/bsdfs/BSDF.ih" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Material; struct ShadingContext; struct DifferentialGeometry; struct Ray; struct Medium; SYCL_EXTERNAL const varying BSDF *uniform Velvet_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &ray, const Medium ¤tMedium, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL BSDF_EvalRes Velvet_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi); SYCL_EXTERNAL BSDF_SampleRes Velvet_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/Velvet.ispc000066400000000000000000000056651456566705700252070ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Velvet.ih" #include "render/Material.ih" #include "render/bsdfs/Minneart.ih" #include "render/bsdfs/MultiBSDF.ih" #include "render/bsdfs/Velvety.ih" // c++ shared #include "VelvetShared.h" /////////////////////////////////////////////////////////////////////////////// // Implementation OSPRAY_BEGIN_ISPC_NAMESPACE #define MULTIBSDF_SIZE 2 struct Velvet_BSDF { DEFINE_MULTIBSDF(MULTIBSDF_SIZE); Minneart minneart; Velvety velvety; }; SYCL_EXTERNAL const varying BSDF *uniform Velvet_getBSDF( const uniform Material *uniform super, uniform ShadingContext *uniform ctx, const DifferentialGeometry &dg, const Ray &, const Medium &, const uniform FeatureFlagsHandler &) { const uniform Velvet *uniform self = (const uniform Velvet *uniform)super; varying LinearSpace3f *uniform shadingFrame = LinearSpace3f_create(ctx, frame(dg.Ns)); // Allocate memory and initialize material BSDF varying Velvet_BSDF *uniform bsdf = (varying Velvet_BSDF * uniform) ShadingContext_alloc(ctx, sizeof(Velvet_BSDF)); varying MultiBSDF *uniform mbsdf = (varying MultiBSDF * uniform) bsdf; MultiBSDF_Constructor(mbsdf, MULTIBSDF_SIZE); bsdf->super.bsdfType = BSDF_TYPE_VELVET; Minneart_Constructor( &bsdf->minneart, shadingFrame, self->reflectance, self->backScattering); MultiBSDF_add( mbsdf, 0, &bsdf->minneart.super, 1.f, luminance(self->reflectance)); Velvety_Constructor(&bsdf->velvety, shadingFrame, self->horizonScatteringColor, self->horizonScatteringFallOff); MultiBSDF_add(mbsdf, 1, &bsdf->velvety.super, 1.f, luminance(self->horizonScatteringColor)); return &bsdf->super; } SYCL_EXTERNAL BSDF_EvalRes Velvet_BSDF_eval( const varying BSDF *uniform super, const vec3f &wo, const vec3f &wi) { const varying Velvet_BSDF *uniform self = (const varying Velvet_BSDF *uniform)super; MULTIBSDF_EVAL_BEGIN(); MULTIBSDF_EVAL_CHILD(0, &self->minneart, Minneart_eval); MULTIBSDF_EVAL_CHILD(1, &self->velvety, Velvety_eval); MULTIBSDF_EVAL_END(); return MULTIBSDF_EVAL_GET(); } SYCL_EXTERNAL BSDF_SampleRes Velvet_BSDF_sample( const varying BSDF *uniform super, const vec3f &wo, const vec2f &s, float ss) { const varying Velvet_BSDF *uniform self = (const varying Velvet_BSDF *uniform)super; MULTIBSDF_SAMPLE_BEGIN(); MULTIBSDF_SAMPLE_CHILD(0, &self->minneart, Minneart_sample); MULTIBSDF_SAMPLE_CHILD(1, &self->velvety, Velvety_sample); MULTIBSDF_SAMPLE_EVAL(); MULTIBSDF_EVAL_CHILD(0, &self->minneart, Minneart_eval); MULTIBSDF_EVAL_CHILD(1, &self->velvety, Velvety_eval); MULTIBSDF_SAMPLE_END(); return MULTIBSDF_SAMPLE_GET(); } /////////////////////////////////////////////////////////////////////////////// // External API export void *uniform Velvet_getBSDF_addr() { return (void *uniform)Velvet_getBSDF; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/materials/VelvetShared.h000066400000000000000000000015751456566705700256230ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/MaterialShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Velvet { Material super; // Diffuse reflectance of the surface. The range is from 0 // (black) to 1 (white). vec3f reflectance; // Amount of back scattering. The range is from 0 (no back // scattering) to inf (maximum back scattering). float backScattering; // Color of horizon scattering. vec3f horizonScatteringColor; // Fall-off of horizon scattering. float horizonScatteringFallOff; #ifdef __cplusplus Velvet() : reflectance(.4f, 0.f, 0.f), backScattering(.5f), horizonScatteringColor(.75f, .1f, .1f), horizonScatteringFallOff(10) { super.type = ispc::MATERIAL_TYPE_VELVET; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/000077500000000000000000000000001456566705700232225ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/GeometryLight.ih000066400000000000000000000013551456566705700263330ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/FeatureFlags.ih" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct PathContext; struct PathState; struct PathVertex; struct Ray; struct Light; struct Light_SampleRes; struct DifferentialGeometry; SYCL_EXTERNAL vec3f evaluateGeometryLights(const PathContext &pathContext, const PathState &pathState, const PathVertex &lastVertex, const PathVertex &pathVertex, const Ray &ray); SYCL_EXTERNAL Light_SampleRes GeometryLight_sample(const Light *uniform super, const DifferentialGeometry &dg, const vec2f &s, const float time, const uniform FeatureFlagsHandler &ffh); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/GeometryLight.ispc000066400000000000000000000077501456566705700266760ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/pathtracer/GeometryLight.ih" #include "render/pathtracer/PathStructs.ih" #include "render/pathtracer/PathTracerUtil.ih" #include "render/Material.ih" #include "texture/TextureParam.ih" #include "common/Instance.ih" #include "geometry/GeometricModel.ih" #include "math/Distribution1D.ih" #include "rkcommon/math/AffineSpace.ih" // c++ shared #include "GeometryLightShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL vec3f evaluateGeometryLights(const PathContext &pathContext, const PathState &pathState, const PathVertex &lastVertex, const PathVertex &pathVertex, const Ray &ray) { vec3f L = make_vec3f(0.f); Material *material = pathVertex.dg.material; foreach_unique (m in material) { if (m != NULL && reduce_max(m->emission) > 0.f) { // at the moment we only support uniform light selection // therefore we can evaluate the selection PDF directly float lightSelectionPDF = 0.0f; if (pathContext.numLights > 0) { lightSelectionPDF = (1.0f / (float)pathContext.numLights) * pathContext.numLightSamples; } // convert pdf wrt. area to pdf wrt. solid angle const float cosd = dot(pathVertex.dg.Ng, ray.dir); const float lePdf = pathVertex.dg.areaPDF * sqr(ray.t) / abs(cosd); L = L + pathState.throughput * m->emission * get3f(m->emissionMap, pathVertex.dg, make_vec3f(1.f)) * misHeuristic( pathState, lastVertex.pdf_w, lightSelectionPDF * lePdf); } } return L; } // Implementation ///////////////////////////////////////////////////////////// SYCL_EXTERNAL Light_SampleRes GeometryLight_sample(const Light *uniform super, const DifferentialGeometry &dg, const vec2f &s, const float time, const uniform FeatureFlagsHandler &ffh) { const GeometryLight *uniform self = (GeometryLight * uniform) super; const GeometricModel *uniform model = self->model; const Geometry *uniform geo = model->geom; Light_SampleRes res; res.weight = make_vec3f(0.0f); // choose primitive const Sample1D sample = Distribution1D_sample(self->numPrimitives, self->distribution, 0, s.x); const int32 primID = self->primIDs[sample.idx]; Material *mat = GeometricModel_getMaterial(model, dg.renderer, primID); if (!mat) return res; const vec2f ns = make_vec2f(sample.frac, s.y); // reproject s.x // sample position on primitive // TODO maybe should already be done wrt. solid angle SampleAreaRes as; const Instance *uniform instance = self->super.instance; assert(instance); const uniform FeatureFlagsGeometry ffg = getFeatureFlagsGeometry(ffh); if (instance->motionBlur && (ffg & FFG_MOTION_BLUR)) { foreach_unique (utime in time) { const uniform affine3f xfm = Instance_getTransform(instance, utime); as = Geometry_dispatch_sampleArea( geo, primID, xfm, rcp(xfm), ns, time, ffh); } } else { as = Geometry_dispatch_sampleArea( geo, primID, instance->xfm, instance->rcp_xfm, ns, time, ffh); } // note that sample.pdf/primitives * sampleArea(worldspace).pdf == self->pdf // extant light vector from the hit point const vec3f dir = as.pos - dg.P; const float dist = length(dir); // normalized light vector res.dir = dir / dist; res.dist = dist - calcEpsilon(as.pos, dist); // convert to pdf wrt. solid angle const float cosd = dot(as.normal, res.dir); res.pdf = self->pdf * sqr(dist) / abs(cosd); DifferentialGeometry texDg; texDg.P = as.pos; texDg.Ns = as.normal; texDg.Ng = as.normal; texDg.st = as.st; vec3f radiance; foreach_unique (m in mat) radiance = m->emission * get3f(m->emissionMap, texDg, make_vec3f(1.f)); res.weight = radiance * rcp(res.pdf); return res; } // Exports (called from C++) ////////////////////////////////////////////////// export void *uniform GeometryLight_sample_addr() { return (void *uniform)GeometryLight_sample; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/GeometryLightShared.h000066400000000000000000000020521456566705700273040ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "lights/LightShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct GeometricModel; // The GeometryLight is a proxy object fulfilling the Light.ih API. // It is generated internally for each emitting geometry modelance to facilitate // explicit importance sampling (currently wrt. the surface area). struct GeometryLight { Light super; // inherited light fields const GeometricModel *model; // underlying geometry int32 numPrimitives; // number of emissive primitives int32 *primIDs; // IDs of emissive primitives to sample float *distribution; // pdf over prims proportional to (world-space) area float pdf; // probability density to sample point on surface := 1/area #ifdef __cplusplus GeometryLight() : model(nullptr), numPrimitives(0), primIDs(nullptr), distribution(nullptr), pdf(inf) { super.type = LIGHT_TYPE_GEOMETRY; } }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/NextEventEstimation.ih000066400000000000000000000007001456566705700275160ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/FeatureFlags.ih" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct PathContext; struct PathState; struct PathVertex; SYCL_EXTERNAL vec3f nextEventEstimation(const PathContext &pathContext, const PathState &pathState, PathVertex &pathVertex, const uniform FeatureFlagsHandler &ffh); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/NextEventEstimation.ispc000066400000000000000000000115061456566705700300620ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/pathtracer/NextEventEstimation.ih" #include "render/pathtracer/PathStructs.ih" #include "render/pathtracer/PathTracerDefines.ih" #include "render/pathtracer/PathTracerUtil.ih" #include "render/pathtracer/TransparentShadow.ih" #ifdef OSPRAY_ENABLE_VOLUMES #include "render/pathtracer/volumes/VolumeSampler.ih" #endif #include "common/World.ih" #include "math/Distribution1D.ih" #include "math/sampling.ih" #include "math/random.ih" // c++ shared #include "PathTracerDataShared.h" #include "lights/LightDispatch.ih" #include "lights/LightShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL vec3f nextEventEstimation(const PathContext &pathContext, const PathState &pathState, PathVertex &pathVertex, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlags ff = getFeatureFlags(ffh); // direct lighting including shadows and MIS vec3f L = make_vec3f(0.f); const World *uniform world = pathContext.world; const uniform PathTracerData &pathtracerData = *((const uniform PathTracerData *)world->pathtracerData); for (uniform uint32 i = 0; i < pathContext.numLightSamples; i++) { // select a random light source from the list const float s1 = LDSampler_getFloat( pathContext.ldSampler, pathState.sampleDim + 3 + i * 3); const Sample1D lSelectSample = Distribution1D_sample( pathContext.numLights, pathContext.lightsCDF, 0, s1); const float lightSelectionProb = lSelectSample.prob * pathContext.numLightSamples; const Light *light = pathtracerData.lights[lSelectSample.idx]; // sample the contribution from the random light source const vec2f s2 = LDSampler_getFloat2( pathContext.ldSampler, pathState.sampleDim + 3 + i * 3 + 1); Light_SampleRes ls; foreach_unique (l in light) ls = Light_dispatch_sample(l, pathVertex.dg, s2, pathState.time, ffh); // adjust the contibution with the probabiltiy of selecting the light source ls.weight = ls.weight / lightSelectionProb; ls.pdf = ls.pdf * lightSelectionProb; // skip when zero contribution from light if (reduce_max(ls.weight) <= 0.0f | ls.pdf <= PDF_CULLING) continue; // evaluate BSDF Scattering_EvalRes fe; if (ff.geometry && pathVertex.type == SURFACE) { foreach_unique (f in pathVertex.bsdf) if (f != NULL) fe = BSDF_dispatch_eval(f, pathVertex.wo, ls.dir, ffh); } else { #ifdef OSPRAY_ENABLE_VOLUMES if (ff.other & FFO_VOLUME_IN_SCENE) { foreach_unique (v in pathVertex.volume) if (v != NULL) fe = HenyeyGreenstein_eval(v->anisotropy, pathVertex.wo, ls.dir); } #endif } // skip when zero contribution from material if (reduce_max(fe.value) <= 0.0f) continue; // test for shadows Ray shadowRay; vec3f org = pathVertex.dg.P; if (pathVertex.type != VOLUME) { if (dot(pathVertex.dg.Ng, ls.dir) < 0.f) org = org - (2.0f * pathVertex.dg.epsilon) * pathVertex.dg.Ng; } setRay(shadowRay, org, ls.dir, 0.f, ls.dist, pathState.time); // Trace ray in clipping geometries scene, fill array with ray intervals RayIntervals rayIntervals; traceClippingRay(pathContext.world, shadowRay, rayIntervals, ffh); const vec3f throughput = pathState.throughput * fe.value; #if ROULETTE == 1 // Russian roulette adjustment if (pathState.depth >= pathContext.context->rouletteDepth) { const float contProb = min(luminance(throughput * rcp(fe.pdf)), MAX_ROULETTE_CONT_PROB); fe.pdf *= contProb; } #endif const vec3f unshadedLightContrib = throughput * ls.weight; const vec3f lightContrib = transparentShadow(pathContext.context, pathContext.world, unshadedLightContrib, shadowRay, rayIntervals, pathState.currentMedium, ffh); if (reduce_max(lightContrib) > 0) { #ifdef OSPRAY_ENABLE_VOLUMES if (ff.other & FFO_VOLUME_IN_SCENE) { const float T = volumeTransmittance(pathContext.world, shadowRay, rayIntervals, pathContext.randomSampler, ffh); if (reduce_max(T) > 0) { // we have to use an independent transmittance estimate for MIS to get // a correct result const float T_mis = pathState.disableFWD || pathState.disableNEE ? 1.f : volumeTransmittance(pathContext.world, shadowRay, rayIntervals, pathContext.randomSampler, ffh); L = L + T * lightContrib * misHeuristic(pathState, ls.pdf, fe.pdf * T_mis); } } else #endif { L = L + lightContrib * misHeuristic(pathState, ls.pdf, fe.pdf); } } } return L; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/PathSampler.ih000066400000000000000000000007111456566705700257630ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/FeatureFlags.ih" #include "common/OSPCommon.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct PathContext; struct PathState; struct Ray; struct ScreenSample; SYCL_EXTERNAL void samplePath(const PathContext &pathContext, PathState &pathState, Ray &ray, ScreenSample &sample, const uniform FeatureFlagsHandler &ffh); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/PathSampler.ispc000066400000000000000000000262611456566705700263310ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/pathtracer/GeometryLight.ih" #include "render/pathtracer/NextEventEstimation.ih" #include "render/pathtracer/PathSampler.ih" #include "render/pathtracer/PathStructs.ih" #include "render/pathtracer/PathTracerDefines.ih" #include "render/pathtracer/PathTracerUtil.ih" #include "render/pathtracer/ShadowCatcher.ih" #include "render/pathtracer/TransparentShadow.ih" #include "render/pathtracer/VirtualLight.ih" #include "common/Intersect.ih" #include "common/World.ih" #include "math/random.ih" #include "render/Material.ih" #include "render/MaterialDispatch.ih" #include "render/bsdfs/MicrofacetAlbedoTables.ih" #include "render/bsdfs/ShadingContext.ih" #include "render/materials/Medium.ih" #ifdef OSPRAY_ENABLE_VOLUMES #include "render/pathtracer/volumes/VolumeSampler.ih" #endif // c++ shared #include "PathTracerDataShared.h" #include "PathTracerShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE inline void postIntersect(const PathContext &pathContext, const PathState &, PathVertex &pathVertex, Ray &ray, const uniform FeatureFlagsHandler &ffh) { const PathTracer *uniform pt = pathContext.context; const uniform FeatureFlags ff = getFeatureFlags(ffh); if (ff.geometry && pathVertex.type == SURFACE) { postIntersect(pathContext.world, &pt->super, pathVertex.dg, ray, DG_NS | DG_NG | DG_FACEFORWARD | DG_NORMALIZE | DG_TEXCOORD | DG_COLOR | DG_TANGENTS | DG_MOTIONBLUR, ffh); } #ifdef OSPRAY_ENABLE_VOLUMES if ((ff.other & FFO_VOLUME_IN_SCENE) && pathVertex.type == VOLUME) { pathVertex.dg.P = ray.org + ray.t * ray.dir; pathVertex.dg.renderer = &pt->super; pathVertex.dg.instID = ray.instID; foreach_unique (instID in ray.instID) { if (instID != RTC_INVALID_GEOMETRY_ID) { const World *uniform world = pathContext.world; const Instance *uniform instance = *(world->instances + instID); if (instance->userID != RTC_INVALID_GEOMETRY_ID) pathVertex.dg.instID = instance->userID; } } foreach_unique (volm in pathVertex.volume) VolumetricModel_postIntersect(volm, pathVertex.dg, ray, 0); } #endif } inline Scattering_SampleRes sampleDirection(const PathContext &pathContext, const PathState &pathState, PathVertex &pathVertex, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlags ff = getFeatureFlags(ffh); const vec2f ss = LDSampler_getFloat2(pathContext.ldSampler, pathState.sampleDim); const float s = LDSampler_getFloat(pathContext.ldSampler, pathState.sampleDim + 2); Scattering_SampleRes fs; if (ff.geometry && pathVertex.type == SURFACE) { foreach_unique (f in pathVertex.bsdf) { if (f != NULL) { fs = BSDF_dispatch_sample(f, pathVertex.wo, ss, s, ffh); pathVertex.wi = fs.wi; pathVertex.pdf_w = fs.pdf; } } } #ifdef OSPRAY_ENABLE_VOLUMES if ((ff.other & FFO_VOLUME_IN_SCENE) && pathVertex.type == VOLUME) { foreach_unique (v in pathVertex.volume) { if (v != NULL) { fs = HenyeyGreenstein_sample(v->anisotropy, pathVertex.wo, ss, s); pathVertex.wi = fs.wi; pathVertex.pdf_w = fs.pdf; } } } #endif return fs; } SYCL_EXTERNAL void samplePath(const PathContext &pathContext, PathState &pathState, Ray &ray, ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { PathVertex lastVertex; lastVertex.type = CAMERA; #ifdef OSPRAY_ENABLE_VOLUMES lastVertex.volume = NULL; #endif lastVertex.pdf_w = inf; // probability density of previous sampled BSDF, for MIS lastVertex.dg.P = ray.org; // P and N also used by light eval lastVertex.dg.epsilon = calcEpsilon(ray.org, 0.f); lastVertex.dg.Ns = ray.dir; lastVertex.dg.Ng = ray.dir; uniform ShadingContext ctx; ShadingContext_Constructor(&ctx); const uniform FeatureFlags ff = getFeatureFlags(ffh); if (pathContext.context->shadowCatcher) { const Hit hit = intersectPlane( ray.org, ray.dir, pathContext.context->shadowCatcherPlane); if (hit.hit) pathState.shadowCatcherDist = hit.t; } do { if (pathState.shadowCatcherDist > ray.t0) // valid hit can hide other geometry ray.t = min(pathState.shadowCatcherDist, ray.t); // Trace ray in clipping geometries scene, fill array with ray intervals RayIntervals rayIntervals; traceClippingRay(pathContext.world, ray, rayIntervals, ffh); if (ff.geometry) { // Trace ray intervals in geometry traceGeometryRayIntervals(pathContext.world, ray, rayIntervals, ffh); } PathVertex pathVertex; pathVertex.bsdf = NULL; pathVertex.pdf_w = inf; #ifdef OSPRAY_ENABLE_VOLUMES pathVertex.volume = NULL; #endif if (noHit(ray) || !ff.geometry) { pathVertex.type = ENVIRONMENT; } else { pathVertex.type = SURFACE; } if (shadowCatcher(pathContext, pathState, pathVertex, ray, sample, ffh)) { pathVertex.type = ENVIRONMENT; } pathVertex.wo = neg(ray.dir); #ifdef OSPRAY_ENABLE_VOLUMES if (ff.other & FFO_VOLUME_IN_SCENE) { float extinctionCoefficient; float freePath = volumeSampleFreePath(pathContext.world, ray, rayIntervals, pathContext.randomSampler, &pathVertex.volume, extinctionCoefficient, pathVertex.albedo, ffh); if (freePath < inf) { pathVertex.type = VOLUME; pathState.throughput = pathState.throughput * pathVertex.albedo; } } #endif // record depth of primary rays if (pathState.depth == 0) sample.z = ray.t; // background handling if (pathVertex.type == ENVIRONMENT && (pathContext.context->backgroundRefraction ? pathState.specularTransmissionPath : pathState.straightPath)) { vec4f bg = Renderer_getBackground( &pathContext.context->super, *pathContext.pixel, ffh); pathState.contribution = pathState.contribution + pathState.throughput * make_vec3f(bg); sample.alpha = 1.0f - luminance(pathState.throughput); sample.alpha += (1.f - sample.alpha) * bg.w; } if ((!pathState.disableFWD || pathState.depth == 0) && pathVertex.type != VOLUME) { pathState.contribution = pathState.contribution + evaluateVirtualLights( pathContext, pathState, lastVertex, pathVertex, ray, ffh); } if (pathVertex.type == ENVIRONMENT) { break; } // terminate after evaluation of lights and before next shading to always // have both samples for MIS except if we have geometry lights (which we // still need to evaluate for MIS) const World *uniform w = pathContext.world; const uniform PathTracerData &pathtracerData = *((const uniform PathTracerData *)w->pathtracerData); if (pathState.depth >= pathContext.context->super.maxDepth && pathtracerData.numGeoLights == 0) { break; } postIntersect(pathContext, pathState, pathVertex, ray, ffh); if (!pathState.disableFWD && (pathVertex.type != VOLUME) && (ff.other & FFO_LIGHT_GEOMETRY)) { pathState.contribution = pathState.contribution + evaluateGeometryLights( pathContext, pathState, lastVertex, pathVertex, ray); } // record IDs of primary rays if (pathState.depth == 0) { sample.primID = pathVertex.dg.primID; sample.geomID = pathVertex.dg.objID; sample.instID = pathVertex.dg.instID; } // terminate after evaluation of lights and before next shading to always // have both samples for MIS if (pathState.depth >= pathContext.context->super.maxDepth || pathState.scatteringEvents >= pathContext.context->maxScatteringEvents) { break; } // shade surface ShadingContext_Constructor(&ctx); if (ff.geometry && pathVertex.type == SURFACE) { Material *material = (Material *)pathVertex.dg.material; foreach_unique (m in material) { if (m != NULL) { pathVertex.bsdf = Material_dispatch_getBSDF( m, &ctx, pathVertex.dg, ray, pathState.currentMedium, ffh); if (pathVertex.bsdf != NULL) { pathVertex.albedo = pathVertex.bsdf->albedo; } } } // terminate path when we don't have any BSDF if (pathVertex.bsdf == NULL) { break; } } // next event estimation if (!pathState.disableNEE && isSmooth(pathVertex)) { pathState.contribution = pathState.contribution + nextEventEstimation(pathContext, pathState, pathVertex, ffh); } Scattering_SampleRes fs = sampleDirection(pathContext, pathState, pathVertex, ffh); if (pathState.auxFree && (fs.type & SCATTERING_SMOOTH)) { updateAuxilliaryData(pathState, pathVertex, sample); } // terminate path when zero contribution from material if (reduce_max(fs.weight) <= 0.0f || fs.pdf <= PDF_CULLING) { break; } pathState.throughput = pathState.throughput * fs.weight; #if ROULETTE == 1 // Russian roulette if (pathState.depth >= pathContext.context->rouletteDepth) { const float rr = RandomSampler_getFloat(pathContext.randomSampler); const float contProb = min(luminance(pathState.throughput), MAX_ROULETTE_CONT_PROB); if (rr > contProb) { break; } pathState.throughput = pathState.throughput * rcp(contProb); fs.pdf *= contProb; } #endif // compute attenuation with Beer's law if (reduce_min(pathState.currentMedium.attenuation) < 0.f) pathState.throughput = pathState.throughput * expf(pathState.currentMedium.attenuation * ray.t); vec3f ray_org = pathVertex.dg.P; if (ff.geometry && pathVertex.type == SURFACE) { // update currentMedium if we hit a medium interface // TODO: support nested dielectrics if (fs.type & SCATTERING_TRANSMISSION) { ray_org = ray_org - (2.0f * pathVertex.dg.epsilon) * pathVertex.dg.Ng; Material *material = (Material *)pathVertex.dg.material; foreach_unique (m in material) { if (m != NULL) { Material_dispatch_selectNextMedium( m, pathVertex.dg, pathState.currentMedium, ffh); } } } } // keep lastBsdfPdf and lastDg when there was a specular transmission // to better combine MIS with transparent shadows if (fs.type & ~SCATTERING_SPECULAR_TRANSMISSION || pathVertex.type == VOLUME) { lastVertex = pathVertex; } // continue the path if (!eq(ray.dir, fs.wi)) pathState.straightPath = false; if (!(fs.type & SCATTERING_SPECULAR_TRANSMISSION)) pathState.specularTransmissionPath = false; setRay(ray, ray_org, fs.wi, pathState.time); pathState.depth++; pathState.sampleDim += pathContext.numBounceSampleDims; if (fs.type & SCATTERING_SMOOTH) pathState.scatteringEvents++; } while (reduce_max(pathState.throughput) > pathContext.context->super.minContribution); sample.rgb = pathState.contribution; if (isnan(pathState.contribution.x) || isnan(pathState.contribution.y) || isnan(pathState.contribution.z)) { sample.rgb = make_vec3f(0.f); sample.alpha = 1.0f; } } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/PathStructs.ih000066400000000000000000000041521456566705700260320ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/DifferentialGeometry.ih" #include "render/bsdfs/BSDF.ih" #include "render/materials/Medium.ih" #ifdef OSPRAY_ENABLE_VOLUMES #include "volume/VolumetricModel.ih" #endif // c++ shared #include "PathTracerShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE struct World; struct LDSampler; struct RandomSampler; enum PathVertexType { SURFACE, VOLUME, CAMERA, LIGHT, ENVIRONMENT }; struct PathVertex { DifferentialGeometry dg; vec3f wi; vec3f wo; vec3f albedo; // only valid if path vertex is surface vertex const varying BSDF *bsdf; #ifdef OSPRAY_ENABLE_VOLUMES // only valid if path vertex is volume vertex const VolumetricModel *volume; #endif float pdf_w; // the pdf of sampling wo in solid angle measure PathVertexType type; }; struct PathContext { const PathTracer *uniform context; const World *uniform world; const varying vec2f *uniform pixel; varying LDSampler *uniform ldSampler; varying RandomSampler *uniform randomSampler; uniform uint32 numLights; uniform uint32 numLightSamples; uniform float *uniform lightsCDF; uniform uint32 numBounceSampleDims; // BSDF sample (3D), roulette (1D), light // samples (numLightSamples*(1D+2D)) }; struct PathState { bool straightPath; // path from camera did not change direction, for alpha and // backplate bool specularTransmissionPath; // path from camera only has specular // transmissions, for alpha and backplate bool auxFree; // normal & albedo buffer were not yet written to vec3f throughput; vec3f contribution; float time; Medium currentMedium; float shadowCatcherDist; uniform uint32 sampleDim; // skip: pixel (2D), lens (2D), time (1D) uint32 scatteringEvents; // counting diffuse and glossy bounces uniform uint32 depth; uniform bool disableNEE; // turn off NEE contribution for debugging purposes uniform bool disableFWD; // turn off FWD contribution for debugging purposes uniform bool debug; }; OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/PathTracer.cpp000066400000000000000000000073401456566705700257670ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "PathTracer.h" #include "PathTracerData.h" #include "camera/Camera.h" #include "common/FeatureFlagsEnum.h" #include "common/World.h" #include "fb/FrameBuffer.h" #include "geometry/GeometricModel.h" #include "lights/Light.h" #include "render/Material.h" #ifdef OSPRAY_TARGET_SYCL #include #include "common/FeatureFlags.ih" namespace ispc { SYCL_EXTERNAL void PathTracer_renderTask(Renderer *uniform _self, FrameBuffer *uniform fb, Camera *uniform camera, World *uniform world, const uint32 *uniform taskIDs, const sycl::nd_item<3> taskIndex, const uniform FeatureFlagsHandler &ffh); } #else // ispc exports #include "math/Distribution1D_ispc.h" #include "render/pathtracer/PathTracer_ispc.h" #endif namespace ospray { PathTracer::PathTracer(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device) {} std::string PathTracer::toString() const { return "ospray::PathTracer"; } void PathTracer::commit() { Renderer::commit(); getSh()->rouletteDepth = getParam("roulettePathLength", 5); getSh()->maxScatteringEvents = getParam("maxScatteringEvents", 20); getSh()->maxRadiance = getParam("maxContribution", inf); getSh()->numLightSamples = getParam("lightSamples", -1); // Set shadow catcher plane const vec4f shadowCatcherPlane = getParam("shadowCatcherPlane", vec4f(0.f)); const vec3f normal = vec3f(shadowCatcherPlane); const float l = length(normal); getSh()->shadowCatcher = l > 0.f; const float rl = rcp(l); getSh()->shadowCatcherPlane = vec4f(normal * rl, shadowCatcherPlane.w * rl); scanForGeometryLights = getParam("geometryLights", true); getSh()->backgroundRefraction = getParam("backgroundRefraction", false); } void *PathTracer::beginFrame(FrameBuffer *, World *world) { if (!world) return nullptr; if (!world->pathtracerData || (scanForGeometryLights && !world->pathtracerData->scannedForGeometryLights)) { // Create PathTracerData object std::unique_ptr pathtracerData = rkcommon::make_unique( *world, scanForGeometryLights, *this); world->getSh()->pathtracerData = pathtracerData->getSh(); world->pathtracerData = std::move(pathtracerData); } return nullptr; } AsyncEvent PathTracer::renderTasks(FrameBuffer *fb, Camera *camera, World *world, void *, const utility::ArrayView &taskIDs, bool wait) const { AsyncEvent event; auto *rendererSh = getSh(); auto *fbSh = fb->getSh(); auto *cameraSh = camera->getSh(); auto *worldSh = world->getSh(); const size_t numTasks = taskIDs.size(); #ifdef OSPRAY_TARGET_SYCL const uint32_t *taskIDsPtr = taskIDs.data(); event = device.getSyclQueue().submit([&](sycl::handler &cgh) { FeatureFlags ff = world->getFeatureFlags(); if (world->pathtracerData->getSh()->numGeoLights) ff.other |= FFO_LIGHT_GEOMETRY; ff |= featureFlags; ff |= fb->getFeatureFlags(); ff |= camera->getFeatureFlags(); cgh.set_specialization_constant(ff); cgh.parallel_for(fb->getDispatchRange(numTasks), [=](sycl::nd_item<3> taskIndex, sycl::kernel_handler kh) { ispc::FeatureFlagsHandler ffh(kh); ispc::PathTracer_renderTask(&rendererSh->super, fbSh, cameraSh, worldSh, taskIDsPtr, taskIndex, ffh); }); }); if (wait) event.wait_and_throw(); #else (void)wait; ispc::PathTracer_renderTasks( &rendererSh->super, fbSh, cameraSh, worldSh, taskIDs.data(), numTasks); #endif return event; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/PathTracer.h000066400000000000000000000016471456566705700254400ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/Renderer.h" // ispc shared #include "PathTracerShared.h" namespace ispc { struct Light; } namespace ospray { struct PathTracer : public AddStructShared { PathTracer(api::ISPCDevice &device); virtual std::string toString() const override; virtual void commit() override; virtual void *beginFrame(FrameBuffer *, World *) override; virtual AsyncEvent renderTasks(FrameBuffer *fb, Camera *camera, World *world, void *perFrameData, const utility::ArrayView &taskIDs, bool wait) const override; private: bool scanForGeometryLights{true}; // if geometry lights are importance // sampled using NEE (requires scanning // the scene for geometric lights) }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/PathTracer.ispc000066400000000000000000000202051456566705700261360ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "PathSampler.ih" #include "PathStructs.ih" #include "PathTracerDefines.ih" #include "PathTracerUtil.ih" #include "common/FeatureFlagsEnum.h" #include "render/Renderer.ih" #include "render/bsdfs/BSDF.ih" #include "render/bsdfs/MicrofacetAlbedoTables.ih" #include "render/materials/Medium.ih" #include "render/util.ih" #include "volumes/VolumeSampler.ih" #include "camera/Camera.ih" #include "camera/CameraDispatch.ih" #include "common/World.ih" #include "fb/FrameBuffer.ih" #include "fb/FrameBufferDispatch.ih" #include "fb/RenderTaskDesc.ih" #include "math/Distribution1D.ih" #include "math/random.ih" #include "pf/PixelFilterDispatch.ih" // c++ shared #include "PathTracerDataShared.h" #include "PathTracerShared.h" #include "render/MaterialShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE #define MAX_LIGHTS 1000u static ScreenSample PathTraceIntegrator_Li(const PathTracer *uniform self, const World *uniform world, const vec2f &pixel, // normalized, i.e. in [0..1] Ray &ray, varying LDSampler *uniform ldSampler, varying RandomSampler *uniform randomSampler, const uniform FeatureFlagsHandler &ffh) { ScreenSample sample; sample.rgb = make_vec3f(0.f); sample.alpha = 1.f; sample.normal = make_vec3f(0.0f); sample.albedo = make_vec3f(0.0f); sample.primID = RTC_INVALID_GEOMETRY_ID; sample.geomID = RTC_INVALID_GEOMETRY_ID; sample.instID = RTC_INVALID_GEOMETRY_ID; uniform PathTracerData &pathtracerData = *((uniform PathTracerData *)world->pathtracerData); const uniform uint32 numLights = pathtracerData.lights ? min(MAX_LIGHTS, pathtracerData.numLights) : 0; const uniform uint32 numLightSamples = self->numLightSamples >= 0 && numLights > 0 ? self->numLightSamples : numLights; PathContext pathContext; pathContext.context = self; pathContext.world = world; pathContext.pixel = &pixel; pathContext.ldSampler = ldSampler; pathContext.randomSampler = randomSampler; pathContext.numLights = numLights; pathContext.numLightSamples = numLightSamples; pathContext.lightsCDF = pathtracerData.lightsCDF; // BSDF sample (3D), light samples * (3D, light selection and sampling) pathContext.numBounceSampleDims = 3 + numLightSamples * 3; PathState pathState; pathState.disableNEE = numLightSamples == 0; pathState.disableFWD = false; pathState.straightPath = true; // path from camera did not change direction, // for alpha and backplate pathState.specularTransmissionPath = true; // path from camera only has specular transmissions, for alpha and // backplate pathState.auxFree = true; // normal & albedo buffer were not yet written to pathState.depth = 0; pathState.sampleDim = 5; // skip: pixel (2D), lens (2D), time (1D) pathState.scatteringEvents = 0; pathState.throughput = make_vec3f(1.f); pathState.contribution = make_vec3f(0.f); pathState.time = ray.time; pathState.currentMedium = make_Medium_vacuum(); pathState.shadowCatcherDist = -(float)inf; pathState.debug = false; samplePath(pathContext, pathState, ray, sample, ffh); return sample; } static ScreenSample PathTracer_renderPixel(PathTracer *uniform self, FrameBuffer *uniform fb, Camera *uniform camera, World *uniform world, const uint32 ix, const uint32 iy, const uint32 accumID, const uniform FeatureFlagsHandler &ffh) { ScreenSample screenSample; screenSample.rgb = make_vec3f(0.f); screenSample.alpha = 0.f; screenSample.z = inf; screenSample.normal = make_vec3f(0.f); screenSample.albedo = make_vec3f(0.f); screenSample.sampleID.x = ix; screenSample.sampleID.y = iy; screenSample.primID = RTC_INVALID_GEOMETRY_ID; screenSample.geomID = RTC_INVALID_GEOMETRY_ID; screenSample.instID = RTC_INVALID_GEOMETRY_ID; LDSampler ldSamplerObj; RandomSampler randomSamplerObj; varying LDSampler *uniform ldSampler = &ldSamplerObj; varying RandomSampler *uniform randomSampler = &randomSamplerObj; const int spp = max(1, self->super.spp); for (uniform int s = 0; s < spp; s++) { // init RNG const uint32 sampleID = accumID * spp + s; screenSample.sampleID.z = sampleID; LDSampler_init( ldSampler, self->super.mathConstants, fb->size.x * iy + ix, sampleID); RandomSampler_init(randomSampler, fb->size.x * iy + ix, sampleID); CameraSample cameraSample; const vec2f pixelSample = LDSampler_getFloat2(ldSampler, 0); vec2f pfSample = pixelSample; const PixelFilter *uniform pf = self->super.pixelFilter; if (pf) { pfSample = PixelFilter_dispatch_sample(pf, pixelSample) + make_vec2f(0.5f); } cameraSample.screen.x = (screenSample.sampleID.x + pfSample.x) * fb->rcpSize.x; cameraSample.screen.y = (screenSample.sampleID.y + pfSample.y) * fb->rcpSize.y; cameraSample.lens = LDSampler_getFloat2(ldSampler, 2); cameraSample.time = LDSampler_getFloat(ldSampler, 4); Camera_dispatch_initRay(camera, screenSample.ray, cameraSample, ffh); const float tMax = Renderer_getMaxDepth(&self->super, cameraSample.screen, ffh); screenSample.ray.t = min(screenSample.ray.t, tMax); ScreenSample sample = PathTraceIntegrator_Li(self, world, cameraSample.screen, screenSample.ray, ldSampler, randomSampler, ffh); screenSample.rgb = screenSample.rgb + min(sample.rgb, make_vec3f(self->maxRadiance)); screenSample.alpha = screenSample.alpha + sample.alpha; screenSample.normal = screenSample.normal + sample.normal; screenSample.albedo = screenSample.albedo + sample.albedo; if (sample.z < screenSample.z) { screenSample.z = sample.z; screenSample.primID = sample.primID; screenSample.geomID = sample.geomID; screenSample.instID = sample.instID; } } const float rspp = rcpf(spp); screenSample.rgb = screenSample.rgb * rspp; screenSample.alpha = screenSample.alpha * rspp; screenSample.normal = screenSample.normal * rspp; screenSample.albedo = screenSample.albedo * rspp; return screenSample; } #ifndef OSPRAY_TARGET_SYCL task #endif SYCL_EXTERNAL void PathTracer_renderTask(Renderer *uniform _self, FrameBuffer *uniform fb, Camera *uniform camera, World *uniform world, const uint32 *uniform taskIDs, #ifdef OSPRAY_TARGET_SYCL const sycl::nd_item<3> taskIndex, #endif const uniform FeatureFlagsHandler &ffh) { PathTracer *uniform self = (PathTracer * uniform) _self; #ifdef OSPRAY_TARGET_SYCL uint32 taskIndex0 = taskIndex.get_global_id(0); #endif uniform RenderTaskDesc taskDesc = FrameBuffer_dispatch_getRenderTaskDesc(fb, taskIDs[taskIndex0], ffh); if (fb->cancelRender || isEmpty(taskDesc.region)) { return; } const uniform int frameID = fb->doAccumulation ? max(fb->frameID, 0) : 0; #ifdef OSPRAY_TARGET_SYCL { int32 y = taskDesc.region.lower.y + taskIndex.get_global_id(1); int32 x = taskDesc.region.lower.x + taskIndex.get_global_id(2); #else foreach_tiled (y = taskDesc.region.lower.y... taskDesc.region.upper.y, x = taskDesc.region.lower.x... taskDesc.region.upper.x) { #endif ScreenSample screenSample = PathTracer_renderPixel(self, fb, camera, world, x, y, frameID, ffh); FrameBuffer_dispatch_accumulateSample(fb, screenSample, taskDesc, ffh); } FrameBuffer_dispatch_completeTask(fb, taskDesc, ffh); } // Exports (called from C++) ////////////////////////////////////////////////// #ifndef OSPRAY_TARGET_SYCL export void PathTracer_renderTasks(void *uniform _self, void *uniform _fb, void *uniform _camera, void *uniform _world, void *uniform _taskIDs, uniform uint32 numTasks) { Renderer *uniform self = (Renderer * uniform) _self; FrameBuffer *uniform fb = (FrameBuffer * uniform) _fb; Camera *uniform camera = (Camera * uniform) _camera; World *uniform world = (World * uniform) _world; const uint32 *uniform taskIDs = (const uint32 *uniform)_taskIDs; uniform FeatureFlagsHandler ffh; launch[numTasks] PathTracer_renderTask(self, fb, camera, world, taskIDs, ffh); } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/PathTracerData.cpp000066400000000000000000000123021456566705700265530ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "PathTracerData.h" // ospray #include "common/Instance.h" #include "common/World.h" #include "geometry/GeometricModel.h" #include "lights/Light.h" #include "render/Material.h" #include "render/Renderer.h" #ifndef OSPRAY_TARGET_SYCL // ispc exports #include "geometry/GeometricModel_ispc.h" #include "render/pathtracer/GeometryLight_ispc.h" #else namespace ispc { float Distribution1D_create(const int size, float *cdf); int GeometricModel_gatherEmissivePrimIDs(void *_model, void *_renderer, void *_instance, int *primIDs, float *distribution, float &pdf); } // namespace ispc #endif // ispc shared #include "GeometryLightShared.h" namespace ospray { PathTracerData::PathTracerData( const World &world, bool scanForGeometryLights, const Renderer &renderer) : AddStructShared(world.getISPCDevice().getIspcrtContext()) { size_t geometryLights{0}; if (scanForGeometryLights) { generateGeometryLights(world, renderer); scannedForGeometryLights = true; geometryLights = lightViews.size(); } if (world.lights) { for (auto &&obj : *world.lights) { for (uint32_t id = 0; id < obj->getShCount(); id++) lightViews.push_back(obj->createSh(id)); } } // Iterate through all world instances if (world.instances) { for (auto &&inst : *world.instances) { // Skip instances without lights if (!inst->group->lights) continue; // Add instance lights to array for (auto &&obj : *inst->group->lights) { for (uint32_t id = 0; id < obj->getShCount(); id++) lightViews.push_back(obj->createSh(id, inst->getSh())); } } } // Prepare light cumulative distribution function std::vector lightsCDF(lightViews.size(), 1.f); if (lightsCDF.size()) { ispc::Distribution1D_create(lightsCDF.size(), lightsCDF.data()); } // Retrieve shared memory pointer from each light view and store them // in a temporary local std::vector std::vector lights(lightViews.size()); for (uint32_t i = 0; i < lightViews.size(); i++) lights[i] = (ispc::Light *)ispcrtSharedPtr(lightViews[i]); // Then create shared buffer from the temporary std::vector ispcrt::Context &context = world.getISPCDevice().getIspcrtContext(); lightArray = make_buffer_shared_unique(context, lights); lightCDFArray = make_buffer_shared_unique(context, lightsCDF); getSh()->lights = lightArray->sharedPtr(); getSh()->lightsCDF = lightCDFArray->sharedPtr(); getSh()->numLights = lights.size(); getSh()->numGeoLights = geometryLights; } PathTracerData::~PathTracerData() { // Delete all lights structures for (ISPCRTMemoryView lv : lightViews) BufferSharedDelete(lv); } ISPCRTMemoryView PathTracerData::createGeometryLight(const Instance *instance, const GeometricModel *model, const std::vector &primIDs, const std::vector &distribution, float pdf) { ispcrt::Context &context = instance->getISPCDevice().getIspcrtContext(); ISPCRTMemoryView view = StructSharedCreate(context.handle()); ispc::GeometryLight *sh = (ispc::GeometryLight *)ispcrtSharedPtr(view); sh->super.instance = instance->getSh(); #ifndef OSPRAY_TARGET_SYCL sh->super.sample = reinterpret_cast( ispc::GeometryLight_sample_addr()); #endif sh->super.eval = nullptr; // geometry lights are hit and explicitly handled sh->model = model->getSh(); sh->numPrimitives = primIDs.size(); sh->pdf = pdf; geoLightPrimIDArray.emplace_back(context, primIDs); sh->primIDs = geoLightPrimIDArray.back().sharedPtr(); geoLightDistrArray.emplace_back(context, distribution); sh->distribution = geoLightDistrArray.back().sharedPtr(); return view; } void PathTracerData::generateGeometryLights( const World &world, const Renderer &renderer) { if (!world.instances) return; for (auto &&instance : *world.instances) { auto geometries = instance->group->geometricModels.ptr; if (!geometries) return; for (auto &&model : *geometries) { if (model->hasEmissiveMaterials(renderer.materialData)) { if (model->geometry().supportAreaLighting()) { std::vector primIDs(model->geometry().numPrimitives()); std::vector distribution(model->geometry().numPrimitives()); float pdf = 0.f; unsigned int numPrimIDs = ispc::GeometricModel_gatherEmissivePrimIDs(model->getSh(), renderer.getSh(), instance->getSh(), primIDs.data(), distribution.data(), pdf); // check whether the geometry has any emissive primitives if (numPrimIDs) { lightViews.push_back(createGeometryLight( instance, model, primIDs, distribution, pdf)); } } else { postStatusMsg(OSP_LOG_WARNING) << "#osp:pt Geometry " << model->toString() << " does not implement area sampling! " << "Cannot use importance sampling for that " << "geometry with emissive material!"; } } } } } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/PathTracerData.h000066400000000000000000000022051456566705700262210ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/StructShared.h" #include "render/RendererData.h" // ispc shared #include "PathTracerDataShared.h" namespace ospray { struct World; struct Instance; struct GeometricModel; struct Renderer; struct PathTracerData : public AddStructShared { PathTracerData(const World &world, bool importanceSampleGeometryLights, const Renderer &renderer); ~PathTracerData() override; bool scannedForGeometryLights{false}; private: ISPCRTMemoryView createGeometryLight(const Instance *instance, const GeometricModel *model, const std::vector &primIDs, const std::vector &distribution, float pdf); void generateGeometryLights(const World &world, const Renderer &renderer); std::vector lightViews; std::unique_ptr> lightArray; std::unique_ptr> lightCDFArray; std::vector> geoLightPrimIDArray; std::vector> geoLightDistrArray; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/PathTracerDataShared.h000066400000000000000000000012641456566705700273540ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Light; struct PathTracerData { // array containing the scene light sources // the lights are sorted: first geometric, then virtual lights Light **lights; uint32 numLights; // total number of light sources (geometric + virtual) uint32 numGeoLights; // number of geometric light sources float *lightsCDF; // CDF used by NEE for randomly picking lights #ifdef __cplusplus PathTracerData() : lights(nullptr), numLights(0), numGeoLights(0), lightsCDF(nullptr) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/PathTracerDefines.ih000066400000000000000000000002531456566705700270770ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #define ROULETTE 1 #define MAX_ROULETTE_CONT_PROB 0.95f #define PDF_CULLING 0.0f RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/PathTracerShared.h000066400000000000000000000016431456566705700265630ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/RendererShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct PathTracer { Renderer super; uint32 rouletteDepth; // path depth from which on RR is used uint32 maxScatteringEvents; float maxRadiance; // coefficients of plane equation defining geometry to catch shadows for // compositing; disabled if normal is zero-length vec4f shadowCatcherPlane; bool shadowCatcher; // preprocessed bool backgroundRefraction; int32 numLightSamples; // number of light samples used for NEE #ifdef __cplusplus PathTracer() : rouletteDepth(5), maxScatteringEvents(20), maxRadiance(inf), shadowCatcherPlane(0.f), shadowCatcher(false), backgroundRefraction(false), numLightSamples(1) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/PathTracerUtil.ih000066400000000000000000000032031456566705700264350ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/Renderer.ih" #include "render/ScreenSample.ih" #include "render/pathtracer/PathStructs.ih" #ifdef OSPRAY_ENABLE_VOLUMES #include "render/pathtracer/volumes/VolumeSampler.ih" #endif OSPRAY_BEGIN_ISPC_NAMESPACE inline bool isSmooth(const PathVertex &pathVertex) { if (pathVertex.type == SURFACE && pathVertex.bsdf && pathVertex.bsdf->scatteringType & SCATTERING_SMOOTH) return true; #ifdef OSPRAY_ENABLE_VOLUMES if (pathVertex.type == VOLUME && pathVertex.volume && isSmoothVolumeVertex(pathVertex)) return true; #endif return false; } inline float misHeuristic(const PathState &pathState, float pdf1, float pdf2) { if (pathState.disableNEE || pathState.disableFWD) return 1.f; // power heuristic with beta=2 const float p = sqr(pdf1) * rcp(sqr(pdf1) + sqr(pdf2)); // guard against high pdf (including Dirac delta) // using the limit when pdf1 approaches inf // compare with bit less than sqrt(float_max) (when sqr starts to overflow) return pdf1 > 1e17f ? 1.0f : p; } inline void updateAuxilliaryData( PathState &pathState, const PathVertex &pathVertex, ScreenSample &sample) { sample.albedo = pathState.throughput * pathVertex.albedo; if (pathVertex.type == VOLUME) { sample.normal = make_vec3f(0.f); } else if (pathVertex.type == SURFACE) { vec3f Ns = pathVertex.dg.Ns; foreach_unique (f in pathVertex.bsdf) { if (f != NULL && f->frame != NULL) Ns = getN(f); } sample.normal = pathState.throughput * Ns; } pathState.auxFree = false; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/Scattering.ih000066400000000000000000000054631456566705700256570ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/vec.ih" #define SCATTERING_SPECULAR_REFLECTION \ (1 << 0) /*!< perfect specular reflection */ #define SCATTERING_GLOSSY_REFLECTION \ (1 << 1) /*!< glossy reflection */ #define SCATTERING_DIFFUSE_REFLECTION \ (1 << 2) /*!< diffuse reflection */ #define SCATTERING_SPECULAR_TRANSMISSION \ (1 << 3) /*!< perfect specular transmission */ #define SCATTERING_GLOSSY_TRANSMISSION \ (1 << 4) /*!< glossy transmission */ #define SCATTERING_DIFFUSE_TRANSMISSION \ (1 << 5) /*!< diffuse transmission */ /*! diffuse reflections and transmissions */ #define SCATTERING_DIFFUSE \ (SCATTERING_DIFFUSE_REFLECTION | SCATTERING_DIFFUSE_TRANSMISSION) /*! glossy reflections and transmissions */ #define SCATTERING_GLOSSY \ (SCATTERING_GLOSSY_REFLECTION | SCATTERING_GLOSSY_TRANSMISSION) /*! perfect specular reflections and transmissions */ #define SCATTERING_SPECULAR \ (SCATTERING_SPECULAR_REFLECTION | SCATTERING_SPECULAR_TRANSMISSION) /*! all possible reflections */ #define SCATTERING_REFLECTION \ (SCATTERING_DIFFUSE_REFLECTION | SCATTERING_GLOSSY_REFLECTION \ | SCATTERING_SPECULAR_REFLECTION) /*! all possible transmissions */ #define SCATTERING_TRANSMISSION \ (SCATTERING_DIFFUSE_TRANSMISSION | SCATTERING_GLOSSY_TRANSMISSION \ | SCATTERING_SPECULAR_TRANSMISSION) /*! all non-dirac types */ #define SCATTERING_SMOOTH (SCATTERING_DIFFUSE | SCATTERING_GLOSSY) /*! no component set */ #define SCATTERING_NONE 0 /*! all components set */ #define SCATTERING_ALL (SCATTERING_REFLECTION | SCATTERING_TRANSMISSION) OSPRAY_BEGIN_ISPC_NAMESPACE typedef uint32 Scattering_Type; struct Scattering_EvalRes { vec3f value; //!< radiance (multiplied by foreshortening factor for BSDFs) float pdf; }; // Note: the pdf of Dirac delta distributions is represented with inf. This is // possible, because in weight we already cancel the Dirac delta (but still // account for a changed pdf by e.g. discrete events such as component // selection). struct Scattering_SampleRes { vec3f weight; //!< radiance divided by pdf and multiplied by foreshortening //!< factor for BSDFs vec3f wi; float pdf; Scattering_Type type; }; OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/ShadowCatcher.ih000066400000000000000000000007421456566705700262660ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/FeatureFlags.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct PathContext; struct PathState; struct PathVertex; struct Ray; struct ScreenSample; SYCL_EXTERNAL bool shadowCatcher(const PathContext &pathContext, PathState &pathState, PathVertex &pathVertex, const Ray &ray, ScreenSample &sample, const uniform FeatureFlagsHandler &ffh); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/ShadowCatcher.ispc000066400000000000000000000075271456566705700266340ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/pathtracer/PathStructs.ih" #include "render/pathtracer/PathTracerDefines.ih" #include "render/pathtracer/ShadowCatcher.ih" #include "render/pathtracer/TransparentShadow.ih" #include "render/Renderer.ih" #include "common/Ray.ih" #include "common/World.ih" #include "math/random.ih" // c++ shared #include "PathTracerDataShared.h" #include "lights/LightDispatch.ih" #include "lights/LightShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL bool shadowCatcher(const PathContext &pathContext, PathState &pathState, PathVertex &pathVertex, const Ray &ray, ScreenSample &, const uniform FeatureFlagsHandler &ffh) { if (!(pathContext.context->backgroundRefraction ? pathState.specularTransmissionPath : pathState.straightPath)) return false; // TODO use MIS as well // consider real (flagged) geometries with material and move into // light loop (will also handle MIS) if (pathState.shadowCatcherDist <= ray.t && pathState.shadowCatcherDist > ray.t0) { // "postIntersect" of shadowCatcher plane pathVertex.dg.Ns = pathVertex.dg.Ng = make_vec3f(pathContext.context->shadowCatcherPlane); if (dot(ray.dir, pathVertex.dg.Ng) >= 0.f) pathVertex.dg.Ns = pathVertex.dg.Ng = neg(pathVertex.dg.Ng); pathVertex.dg.renderer = &pathContext.context->super; pathVertex.dg.P = ray.org + pathState.shadowCatcherDist * ray.dir; const float eps = calcEpsilon(pathVertex.dg.P, ray.dir, pathState.shadowCatcherDist); pathVertex.dg.P = pathVertex.dg.P + eps * pathVertex.dg.Ng; vec3f unshaded = make_vec3f(0.f); // illumination without occluders vec3f shaded = make_vec3f(0.f); // illumination including shadows const World *uniform world = pathContext.world; const uniform PathTracerData &pathtracerData = *((const uniform PathTracerData *)world->pathtracerData); for (uniform uint32 i = 0; i < pathContext.numLights; i++) { const Light *uniform light = pathtracerData.lights[i]; const vec2f s = LDSampler_getFloat2( pathContext.ldSampler, pathState.sampleDim + 4 + i * 2); Light_SampleRes ls = Light_dispatch_sample(light, pathVertex.dg, s, pathState.time, ffh); // skip when zero contribution from light if (reduce_max(ls.weight) <= 0.0f | ls.pdf <= PDF_CULLING) continue; // evaluate a white diffuse BRDF const float brdf = clamp(dot(ls.dir, pathVertex.dg.Ns)); // * one_over_pi cancels anyway // skip when zero contribution from material if (brdf <= 0.0f) continue; // test for shadows Ray shadowRay; setRay(shadowRay, pathVertex.dg.P, ls.dir, 0.0f, ls.dist, pathState.time); // Trace ray in clipping geometries scene, fill array with ray intervals RayIntervals rayIntervals; traceClippingRay(pathContext.world, shadowRay, rayIntervals, ffh); const vec3f unshadedLightContrib = pathState.throughput * ls.weight * brdf; // * misHeuristic(pathState, ls.pdf, brdf); unshaded = unshaded + unshadedLightContrib; shaded = shaded + transparentShadow(pathContext.context, pathContext.world, unshadedLightContrib, shadowRay, rayIntervals, pathState.currentMedium, ffh); } // order of args important to filter NaNs (in case unshaded.X is zero) const vec3f ratio = min( pathState.throughput * shaded * rcp(unshaded), pathState.throughput); // alpha blend-in black shadow pathState.throughput = ratio; pathState.contribution = make_vec3f(0.f); return true; } // update dist for potential next intersection (if transparent) pathState.shadowCatcherDist -= ray.t; return false; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/TransparentShadow.ih000066400000000000000000000010701456566705700272110ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/FeatureFlags.ih" #include "render/materials/Medium.ih" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct PathTracer; struct World; struct Ray; struct RayIntervals; SYCL_EXTERNAL vec3f transparentShadow(const uniform PathTracer *uniform self, const World *uniform world, vec3f lightContrib, Ray &shadowRay, RayIntervals &rayIntervals, Medium medium, const uniform FeatureFlagsHandler &ffh); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/TransparentShadow.ispc000066400000000000000000000041661456566705700275600ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "render/pathtracer/TransparentShadow.ih" #include "render/Material.ih" #include "render/MaterialDispatch.ih" #include "render/materials/Medium.ih" #include "common/Ray.ih" #include "common/World.ih" // c++ shared #include "PathTracerShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL vec3f transparentShadow(const uniform PathTracer *uniform self, const World *uniform world, vec3f lightContrib, Ray &shadowRay, RayIntervals &rayIntervals, Medium medium, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlags ff = getFeatureFlags(ffh); // It's not possible to have transpareny shadows if we don't have any geometry if (!ff.geometry) { return lightContrib; } uniform uint32 maxDepth = self->super.maxDepth; const float tOriginal = shadowRay.t; while (1) { traceGeometryRayIntervals(world, shadowRay, rayIntervals, ffh); if (noHit(shadowRay)) return lightContrib; DifferentialGeometry dg; postIntersect(world, &self->super, dg, shadowRay, DG_NS | DG_NG | DG_FACEFORWARD | DG_NORMALIZE | DG_TEXCOORD | DG_COLOR | DG_MOTIONBLUR, ffh); uniform Material *material = (uniform Material *)dg.material; vec3f transparency; foreach_unique (m in material) { if (m != NULL) { transparency = Material_dispatch_getTransparency(m, dg, shadowRay, medium, ffh); } } lightContrib = lightContrib * transparency; // compute attenuation with Beer's law if (ne(medium.attenuation, 0.f)) lightContrib = lightContrib * expf(medium.attenuation * (shadowRay.t - shadowRay.t0)); if (reduce_max(lightContrib) <= self->super.minContribution || --maxDepth <= 0) return make_vec3f(0.f); // Tracking medium if we hit a medium interface. foreach_unique (m in material) { if (m != NULL) { Material_dispatch_selectNextMedium(m, dg, medium, ffh); } } setRay(shadowRay, shadowRay.t + dg.epsilon, tOriginal); } } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/VirtualLight.ih000066400000000000000000000007421456566705700261650ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct PathContext; struct PathState; struct PathVertex; struct Ray; SYCL_EXTERNAL vec3f evaluateVirtualLights(const PathContext &pathContext, const PathState &pathState, const PathVertex &lastVertex, const PathVertex &pathVertex, Ray &ray, const uniform FeatureFlagsHandler &ffh); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/VirtualLight.ispc000066400000000000000000000071441456566705700265260ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/World.ih" #include "render/pathtracer/PathStructs.ih" #include "render/pathtracer/PathTracerUtil.ih" #include "render/pathtracer/VirtualLight.ih" #ifdef OSPRAY_ENABLE_VOLUMES #include "render/pathtracer/volumes/VolumeSampler.ih" #endif // c++ shared #include "PathTracerDataShared.h" #include "lights/LightDispatch.ih" #include "lights/LightShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE inline box1f getMinMaxDistForVirtualLights( const PathVertex &lastVertex, const PathVertex &pathVertex, const Ray &ray) { box1f interval; // minimal distance is not always zero (when previously sampled a Dirac // transmission) interval.lower = distance(lastVertex.dg.P, ray.org); // virtual lights are occluded by hit geometry // because lastVertex.dg.P can be different from ray.org (when previously // sampled a Dirac transmission) we cannot just use ray.t as maximum distance interval.upper = distance(lastVertex.dg.P, ray.org + ray.t * ray.dir); if (pathVertex.type == ENVIRONMENT) interval.upper = inf; return interval; } SYCL_EXTERNAL vec3f evaluateVirtualLights(const PathContext &pathContext, const PathState &pathState, const PathVertex &lastVertex, const PathVertex &pathVertex, Ray &ray, const uniform FeatureFlagsHandler &ffh) { // add light from *virtual* lights by intersecting them vec3f L = make_vec3f(0.f); const World *uniform w = pathContext.world; const uniform PathTracerData &pathtracerData = *((const uniform PathTracerData *)w->pathtracerData); if (pathContext.numLights <= pathtracerData.numGeoLights) return L; // return if no virtual lights at all box1f intervalLightDist = getMinMaxDistForVirtualLights(lastVertex, pathVertex, ray); const uniform float selectionPDF = rcp((uniform float)pathContext.numLights - pathtracerData.numGeoLights); for (uniform uint32 i = pathtracerData.numGeoLights; i < pathContext.numLights; i++) { const Light *uniform light = pathtracerData.lights[i]; if (!pathState.straightPath || light->isVisible) { // to correctly handle MIS through transparencies the light pdf needs to // be calculated wrt. lastVertex.dg however, we only have a valid // intersection with the light in [minLightDist, maxLightDist], otherwise // light could be added twice Light_EvalRes le = Light_dispatch_eval(light, lastVertex.dg, ray.dir, intervalLightDist.lower, intervalLightDist.upper, pathState.time, ffh); if (reduce_max(le.radiance) > 0.0f) { Ray shadowRay; setRay(shadowRay, lastVertex.dg.P, ray.dir, intervalLightDist.lower, intervalLightDist.upper, ray.time); // Trace ray in clipping geometries scene, fill array with ray intervals RayIntervals rayIntervals; traceClippingRay(pathContext.world, shadowRay, rayIntervals, ffh); float T = 1.f; #ifdef OSPRAY_ENABLE_VOLUMES const uniform FeatureFlags ff = getFeatureFlags(ffh); if (ff.other & FFO_VOLUME_IN_SCENE) { T = volumeTransmittance(pathContext.world, shadowRay, rayIntervals, pathContext.randomSampler, ffh); } #endif L = L + pathState.throughput * le.radiance * misHeuristic(pathState, lastVertex.pdf_w * T, selectionPDF * pathContext.numLightSamples * le.pdf); } } } return L; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/volumes/000077500000000000000000000000001456566705700247145ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/volumes/HenyeyGreenstein.ih000066400000000000000000000036741456566705700305350ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #pragma once #include "render/pathtracer/Scattering.ih" #include "math/sampling.ih" #include "rkcommon/math/LinearSpace.ih" OSPRAY_BEGIN_ISPC_NAMESPACE inline float hg(float cosTheta, float g) { float denom = 1.f + g * g - 2.f * g * cosTheta; return rcp(4.f * (float)pi) * (1.f - g * g) * rcp(denom * sqrt(denom)); } inline bool HenyeyGreenstein_isSmooth(float anisotropy) { if (abs(anisotropy) > 1.f - 1e-3f) { return false; } return true; } inline Scattering_EvalRes HenyeyGreenstein_eval( float anisotropy, const vec3f &wo, const vec3f &wi) { Scattering_EvalRes res; if (!HenyeyGreenstein_isSmooth(anisotropy)) { res.pdf = 0.f; res.value = make_vec3f(res.pdf); } res.pdf = hg(dot(neg(wo), wi), anisotropy); res.value = make_vec3f(res.pdf); return res; } inline Scattering_SampleRes HenyeyGreenstein_sample( float anisotropy, const vec3f wo, const vec2f s, float) { Scattering_SampleRes res; res.weight = make_vec3f(1.f); const float g = anisotropy; float cosTheta; if (!HenyeyGreenstein_isSmooth(anisotropy)) { // special case for delta function res.wi = g > 0 ? neg(wo) : wo; res.pdf = inf; res.type = g > 0 ? SCATTERING_SPECULAR_TRANSMISSION : SCATTERING_SPECULAR_REFLECTION; return res; } else if (abs(g) < 1e-3f) { // special case for isotropic scattering cosTheta = 1.f - 2.f * s.x; } else { // general case float sqrTerm = (1.f - g * g) * rcp(1.f - g + 2.f * g * s.x); cosTheta = (1.f + g * g - sqrTerm * sqrTerm) * rcp(2.f * g); } res.type = SCATTERING_SMOOTH; float sinTheta = sqrt(max(0.f, 1.f - cosTheta * cosTheta)); float phi = 2.f * M_PI * s.y; const vec3f localDir = cartesian(phi, sinTheta, cosTheta); res.wi = frame(neg(wo)) * localDir; res.pdf = hg(cosTheta, g); return res; } OSPRAY_END_ISPC_NAMESPACE #endif RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/volumes/VolumeSampler.ih000066400000000000000000000021451456566705700300330ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #pragma once #include "common/FeatureFlagsEnum.h" #include "render/pathtracer/PathStructs.ih" #include "render/pathtracer/volumes/HenyeyGreenstein.ih" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct World; struct LDSampler; struct RandomSampler; struct Ray; struct RayIntervals; SYCL_EXTERNAL float volumeSampleFreePath(const World *uniform world, Ray &ray, RayIntervals &rayIntervals, varying RandomSampler *uniform randomSampler, const VolumetricModel *varying *uniform sampledInstance, float &sampledExtinctionCoefficient, vec3f &sampledAlbedo, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL float volumeTransmittance(const World *uniform world, Ray &ray, RayIntervals &rayIntervals, varying RandomSampler *uniform randomSampler, const uniform FeatureFlagsHandler &ffh); inline bool isSmoothVolumeVertex(const PathVertex &pathVertex) { return HenyeyGreenstein_isSmooth(pathVertex.volume->anisotropy); } OSPRAY_END_ISPC_NAMESPACE #endif RenderKit-ospray-f2a61c2/modules/cpu/render/pathtracer/volumes/VolumeSampler.ispc000066400000000000000000000202501456566705700303660ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #include "common/FeatureFlagsEnum.h" #include "common/World.ih" #include "math/random.ih" #include "render/pathtracer/volumes/VolumeSampler.ih" #include "volume/transferFunction/TransferFunctionDispatch.ih" OSPRAY_BEGIN_ISPC_NAMESPACE float delta_tracking(const VolumetricModel *uniform vModel, const range1f &rInterval, varying RandomSampler *uniform randomSampler, const vec3f &o, const vec3f &w, const float &time, float &mu_t, // sampled extinction coefficint vec3f &albedo, const uniform FeatureFlagsHandler &ffh) // sampled albedo (color) { const uniform FeatureFlags ff = getFeatureFlags(ffh); #ifdef OSPRAY_TARGET_SYCL // No alloca on GPU, need to be conservative for now and use the // VKL_MAX_INTERVAL_ITERATOR_SIZE uniform uint8 intervalIteratorBuffer[VKL_MAX_INTERVAL_ITERATOR_SIZE]; #else void *uniform intervalIteratorBuffer = alloca(vklGetIntervalIteratorSizeV(&vModel->vklIntervalContext)); #endif VKLIntervalIterator intervalIterator = vklInitIntervalIteratorV(&vModel->vklIntervalContext, (varying vkl_vec3f *)&o, (varying vkl_vec3f *)&w, (varying vkl_range1f *)&rInterval, #ifndef OSPRAY_TARGET_SYCL & #endif time, intervalIteratorBuffer #ifdef OSPRAY_TARGET_SYCL , ff.volume #endif ); float t = 0.f; VKLInterval interval; while (vklIterateIntervalV(intervalIterator, &interval #ifdef OSPRAY_TARGET_SYCL , ff.volume #endif )) { t = interval.tRange.lower; const float maxOpacity = TransferFunction_dispatch_getMaxOpacity(vModel->transferFunction, *((varying range1f * uniform) & interval.valueRange)); const float mu_max = vModel->densityScale * maxOpacity; if (mu_max <= 0.f) continue; while (true) { float xi = RandomSampler_getFloat(randomSampler); const float dt = -log(1.f - xi) / mu_max; t += dt; if (t > interval.tRange.upper) break; xi = RandomSampler_getFloat(randomSampler); const vec3f p = o + t * w; const float sample = vklComputeSampleV(&vModel->volume->vklSampler, (const varying vkl_vec3f *uniform) & p #ifdef OSPRAY_TARGET_SYCL , 0, time, ff.volume #endif ); if (isnan(sample)) continue; const vec4f color = TransferFunction_dispatch_get(vModel->transferFunction, sample); mu_t = vModel->densityScale * color.w; if (xi < mu_t / mu_max) { albedo = make_vec3f(color); return t; } } } return inf; } SYCL_EXTERNAL float volumeSampleFreePath(const World *uniform world, Ray &ray, RayIntervals &rayIntervals, varying RandomSampler *uniform randomSampler, const VolumetricModel *varying *uniform sampledInstance, float &sampledExtinctionCoefficient, vec3f &sampledAlbedo, const uniform FeatureFlagsHandler &ffh) { #ifdef OSPRAY_TARGET_SYCL // We only support a single volume interval on the GPU VolumeInterval vInterval; VolumeIntervals volumeIntervals; volumeIntervals.numVolumeIntervals = 0; volumeIntervals.numAllocated = 1; volumeIntervals.intervals = &vInterval; #else VolumeIntervals volumeIntervals; allocVolumeIntervals(volumeIntervals); #endif // Get volume intervals Ray volumeRay = ray; traceVolumeRay(world, volumeRay, volumeIntervals); // Iterate through volume intervals float min_dist = inf; unmasked { *sampledInstance = NULL; } for (uniform uint32 i = 0; i < reduce_max(volumeIntervals.numVolumeIntervals); i++) { if (i >= volumeIntervals.numVolumeIntervals) break; range1f vInterval = volumeIntervals.intervals[i].interval; vInterval.lower = max(0.f, vInterval.lower); vInterval.upper = noHit(ray) ? vInterval.upper : min(vInterval.upper, ray.t); if (isEmpty(vInterval)) continue; AffineSpace3f xfm; foreach_unique (inst in volumeIntervals.intervals[i].instance) xfm = Instance_getTransform(inst, volumeRay.time); Ray transformedVolumeRay = volumeRay; transformRay(transformedVolumeRay, rcp(xfm)); VolumetricModel *varying instance = volumeIntervals.intervals[i].volumetricModel; foreach_unique (inst in instance) { for (uint32 j = 0; j < rayIntervals.count; j++) { range1f rInterval = rayIntervals.intervals[j]; // Skip ray intervals outside of the volume range if (vInterval.upper < rInterval.lower || rInterval.upper < vInterval.lower) { continue; } // Clip ray interval to the volume range rInterval.lower = max(rInterval.lower, vInterval.lower); rInterval.upper = min(rInterval.upper, vInterval.upper); float extinctionCoefficient; vec3f albedo; const float dist = delta_tracking(inst, rInterval, randomSampler, transformedVolumeRay.org, transformedVolumeRay.dir, transformedVolumeRay.time, extinctionCoefficient, albedo, ffh); if (dist < inf) { if (dist < min_dist) { min_dist = dist; *sampledInstance = inst; sampledExtinctionCoefficient = extinctionCoefficient; sampledAlbedo = albedo; ray.t = dist; ray.primID = 0; ray.geomID = volumeIntervals.intervals[i].geomID; ray.instID = volumeIntervals.intervals[i].instID; } break; } } } } #ifndef OSPRAY_TARGET_SYCL freeVolumeIntervals(volumeIntervals); #endif return min_dist; } SYCL_EXTERNAL float volumeTransmittance(const World *uniform world, Ray &ray, RayIntervals &rayIntervals, varying RandomSampler *uniform randomSampler, const uniform FeatureFlagsHandler &ffh) { #ifdef OSPRAY_TARGET_SYCL // We only support a single volume interval on the GPU VolumeInterval vInterval; VolumeIntervals volumeIntervals; volumeIntervals.numVolumeIntervals = 0; volumeIntervals.numAllocated = 1; volumeIntervals.intervals = &vInterval; #else VolumeIntervals volumeIntervals; allocVolumeIntervals(volumeIntervals); #endif // Get volume intervals Ray volumeRay = ray; traceVolumeRay(world, volumeRay, volumeIntervals); // Iterate through volume intervals float transmittance = 1.f; for (uint32 i = 0; i < volumeIntervals.numVolumeIntervals && transmittance > 0.f; i++) { range1f vInterval = volumeIntervals.intervals[i].interval; vInterval.lower = max(ray.t0, vInterval.lower); vInterval.upper = noHit(ray) ? vInterval.upper : min(vInterval.upper, ray.t); if (isEmpty(vInterval)) continue; AffineSpace3f xfm; foreach_unique (inst in volumeIntervals.intervals[i].instance) xfm = Instance_getTransform(inst, volumeRay.time); Ray transformedVolumeRay = volumeRay; transformRay(transformedVolumeRay, rcp(xfm)); VolumetricModel *varying instance = volumeIntervals.intervals[i].volumetricModel; foreach_unique (inst in instance) { for (uint32 j = 0; j < rayIntervals.count && transmittance > 0.f; j++) { range1f rInterval = rayIntervals.intervals[j]; // Skip ray intervals outside of the volume range if (vInterval.upper < rInterval.lower || rInterval.upper < vInterval.lower) { continue; } // Clip ray interval to the volume range rInterval.lower = max(rInterval.lower, vInterval.lower); rInterval.upper = min(rInterval.upper, vInterval.upper); float extinctionCoefficient; vec3f albedo; const float dist = delta_tracking(inst, rInterval, randomSampler, transformedVolumeRay.org, transformedVolumeRay.dir, transformedVolumeRay.time, extinctionCoefficient, albedo, ffh); transmittance = transmittance * ((dist < rInterval.upper) ? 0.f : 1.f); } } } #ifndef OSPRAY_TARGET_SYCL freeVolumeIntervals(volumeIntervals); #endif return transmittance; } OSPRAY_END_ISPC_NAMESPACE #endif RenderKit-ospray-f2a61c2/modules/cpu/render/registration.cpp000066400000000000000000000031571456566705700243110ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ao/AORenderer.h" #include "debug/DebugRenderer.h" #include "pathtracer/PathTracer.h" #include "scivis/SciVis.h" #include "materials/Alloy.h" #include "materials/CarPaint.h" #include "materials/Glass.h" #include "materials/Luminous.h" #include "materials/Metal.h" #include "materials/MetallicPaint.h" #include "materials/Mix.h" #include "materials/OBJ.h" #include "materials/Plastic.h" #include "materials/Principled.h" #include "materials/ThinGlass.h" #include "materials/Velvet.h" using namespace ospray::pathtracer; namespace ospray { void registerAllRenderers() { Renderer::registerType("debug"); Renderer::registerType("pathtracer"); Renderer::registerType("scivis"); Renderer::registerType("ao"); } void registerAllMaterials() { Material::registerType("alloy"); Material::registerType("carPaint"); Material::registerType("glass"); Material::registerType("luminous"); Material::registerType("metal"); Material::registerType("metallicPaint"); #ifndef OSPRAY_TARGET_SYCL // Mix material isn't going to work on the GPU b/c we can't have // recursive calls and it may nest MultiBSDFs. Needs some special treatment Material::registerType("mix"); #endif Material::registerType("obj"); Material::registerType("plastic"); Material::registerType("principled"); Material::registerType("thinGlass"); Material::registerType("velvet"); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/registration.h000066400000000000000000000002611456566705700237470ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 namespace ospray { void registerAllRenderers(); void registerAllMaterials(); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/scivis/000077500000000000000000000000001456566705700223655ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/render/scivis/SciVis.cpp000066400000000000000000000055321456566705700242760ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "SciVis.h" #include "SciVisData.h" #include "camera/Camera.h" #include "common/FeatureFlagsEnum.h" #include "common/World.h" #include "fb/FrameBuffer.h" #ifndef OSPRAY_TARGET_SYCL // ispc exports #include "render/scivis/SciVis_ispc.h" #else #include "common/FeatureFlags.ih" namespace ispc { SYCL_EXTERNAL void SciVis_renderTask(Renderer *uniform self, FrameBuffer *uniform fb, Camera *uniform camera, World *uniform world, const uint32 *uniform taskIDs, const sycl::nd_item<3> taskIndex, const uniform FeatureFlagsHandler &ffh); } #endif namespace ospray { SciVis::SciVis(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device) {} std::string SciVis::toString() const { return "ospray::render::SciVis"; } void SciVis::commit() { Renderer::commit(); getSh()->shadowsEnabled = getParam("shadows", false); getSh()->visibleLights = getParam("visibleLights", false); getSh()->aoSamples = getParam("aoSamples", 0); getSh()->aoRadius = getParam("aoDistance", 1e20f); getSh()->volumeSamplingRate = getParam("volumeSamplingRate", 1.f); } void *SciVis::beginFrame(FrameBuffer *, World *world) { if (!world) return nullptr; if (world->scivisData.get()) return nullptr; // Create SciVisData object std::unique_ptr scivisData = rkcommon::make_unique(*world); world->getSh()->scivisData = scivisData->getSh(); world->scivisData = std::move(scivisData); return nullptr; } AsyncEvent SciVis::renderTasks(FrameBuffer *fb, Camera *camera, World *world, void *, const utility::ArrayView &taskIDs, bool wait) const { AsyncEvent event; auto *rendererSh = getSh(); auto *fbSh = fb->getSh(); auto *cameraSh = camera->getSh(); auto *worldSh = world->getSh(); const size_t numTasks = taskIDs.size(); #ifdef OSPRAY_TARGET_SYCL const uint32_t *taskIDsPtr = taskIDs.data(); event = device.getSyclQueue().submit([&](sycl::handler &cgh) { FeatureFlags ff = world->getFeatureFlags(); ff |= featureFlags; ff |= fb->getFeatureFlags(); ff |= camera->getFeatureFlags(); cgh.set_specialization_constant(ff); cgh.parallel_for(fb->getDispatchRange(numTasks), [=](sycl::nd_item<3> taskIndex, sycl::kernel_handler kh) { ispc::FeatureFlagsHandler ffh(kh); ispc::SciVis_renderTask(&rendererSh->super, fbSh, cameraSh, worldSh, taskIDsPtr, taskIndex, ffh); }); }); if (wait) event.wait_and_throw(); #else (void)wait; ispc::SciVis_renderTasks( &rendererSh->super, fbSh, cameraSh, worldSh, taskIDs.data(), numTasks); #endif return event; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/scivis/SciVis.h000066400000000000000000000011621456566705700237360ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "render/Renderer.h" // ispc shared #include "SciVisShared.h" namespace ospray { struct SciVis : public AddStructShared { SciVis(api::ISPCDevice &device); std::string toString() const override; void commit() override; void *beginFrame(FrameBuffer *, World *) override; virtual AsyncEvent renderTasks(FrameBuffer *fb, Camera *camera, World *world, void *perFrameData, const utility::ArrayView &taskIDs, bool wait) const override; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/scivis/SciVis.ih000066400000000000000000000021471456566705700241130ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/FeatureFlags.ih" #include "render/ScreenSample.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Renderer; struct SciVis; struct FrameBuffer; struct ScreenSample; struct World; struct LDSampler; struct DifferentialGeometry; struct SciVisRenderContext { const SciVis *uniform renderer; const FrameBuffer *uniform fb; const World *uniform world; ScreenSample sample; varying LDSampler *uniform ldSampler; }; SYCL_EXTERNAL vec3f lightAlpha(const uniform SciVis *uniform self, Ray &ray, const World *uniform world, varying LDSampler *uniform ldSampler, vec3f weight, uniform float quality, const uniform FeatureFlagsHandler &ffh); SYCL_EXTERNAL vec3f SciVis_computeAO(const uniform SciVis *uniform self, const World *uniform world, varying LDSampler *uniform ldSampler, const varying DifferentialGeometry &dg, const uniform int sampleCnt, const uniform float aoRadius, const varying vec3i &sampleID, const uniform FeatureFlagsHandler &ffh); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/scivis/SciVis.ispc000066400000000000000000000237641456566705700244610ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "SciVis.ih" #include "camera/Camera.ih" #include "camera/CameraDispatch.ih" #include "common/FeatureFlagsEnum.h" #include "common/World.ih" #include "fb/FrameBuffer.ih" #include "fb/FrameBufferDispatch.ih" #include "fb/RenderTaskDesc.ih" #include "math/random.ih" #include "math/sampling.ih" #include "pf/PixelFilterDispatch.ih" #include "surfaces.ih" #include "volume/VolumetricModel.ih" #include "volumes.ih" // c++ shared #include "SciVisShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE static void SciVis_renderSample(Renderer *uniform _self, FrameBuffer *uniform fb, World *uniform world, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { uniform SciVis *uniform self = (uniform SciVis * uniform) _self; const uniform FeatureFlags ff = getFeatureFlags(ffh); LDSampler ldSamplerObj; varying LDSampler *uniform ldSampler = &ldSamplerObj; LDSampler_init(ldSampler, self->super.mathConstants, sample.sampleID.x + fb->size.x * sample.sampleID.y, sample.sampleID.z); uniform bool firstHit = true; bool allHitsFullyTransmissive = true; const float originalRayTFar = sample.ray.t; #ifdef OSPRAY_ENABLE_VOLUMES #ifdef OSPRAY_TARGET_SYCL // We only support a single volume interval on the GPU VolumeInterval vInterval; VolumeIntervals volumeIntervals; volumeIntervals.numVolumeIntervals = 0; volumeIntervals.numAllocated = 1; volumeIntervals.intervals = &vInterval; #else // Allocate memory for volume intervals VolumeIntervals volumeIntervals; allocVolumeIntervals(volumeIntervals); #endif #endif // This is our main ray Ray &ray = sample.ray; // First trace the ray across clipping scene to calculate ray intervals, // this step should keep ray structure unchanged RayIntervals rayIntervals; traceClippingRay(world, ray, rayIntervals, ffh); // Iterate over all translucent geometry till we are fully opaque vec3f outColor = make_vec3f(0.f); vec3f outTransmission = make_vec3f(1.f); while (true) { if (ff.geometry) { // Then trace normal geometry using calculated ray intervals, // if hit ray.t will be updated traceGeometryRayIntervals(world, ray, rayIntervals, ffh); } #ifdef OSPRAY_ENABLE_VOLUMES Ray volumeRay = ray; if (ff.other & FFO_VOLUME_IN_SCENE) { // Determine volume intervals by tracing ray in the volume scene traceVolumeRay(world, volumeRay, volumeIntervals); // Sample volumes across volume intervals (in front of geometry hit) if (volumeIntervals.numVolumeIntervals > 0) { SciVisRenderContext rc; rc.renderer = self; rc.fb = fb; rc.world = world; rc.sample = sample; rc.ldSampler = ldSampler; volumeRay.geomID = RTC_INVALID_GEOMETRY_ID; vec4f volumeColor = integrateVolumeIntervalsGradient(rc, volumeIntervals, rayIntervals, volumeRay, ldSampler, self->volumeSamplingRate, ffh); // Blend volume outColor = outColor + outTransmission * make_vec3f(volumeColor); outTransmission = outTransmission * volumeColor.w; if (hadHit(volumeRay) && sample.geomID == RTC_INVALID_GEOMETRY_ID) { sample.primID = 0; foreach_unique (instID in volumeRay.instID) { if (instID != RTC_INVALID_GEOMETRY_ID) { const Instance *uniform instance = *(world->instances + instID); sample.instID = (instance->userID == RTC_INVALID_GEOMETRY_ID) ? instID : instance->userID; const VolumetricModel *volms = *(instance->group->volumetricModels + volumeRay.geomID); foreach_unique (volm in volms) { sample.geomID = (volm->userID == RTC_INVALID_GEOMETRY_ID) ? volumeRay.geomID : volm->userID; } } } } } } #endif // Add contribution from visible lights, P is used by light // evaluation DifferentialGeometry dg; if (self->visibleLights) { dg.P = ray.org; outColor = outColor + outTransmission * evaluateLights(world, dg, ray, ffh); } // If any geometry has been hit const bool rayHadHit = hadHit(ray); if (ff.geometry && rayHadHit) { // Prepare differential geometry structure postIntersect(world, &self->super, dg, ray, DG_NG | DG_NS | DG_NORMALIZE | DG_FACEFORWARD | DG_COLOR | DG_TEXCOORD, ffh); // Shade geometry SSI surfaceShading; surfaceShading = SciVis_computeShading( self, world, dg, sample, ldSampler, ray.dir, ffh); // Initialize other per sample data with first hit values // In addition to considering the first hit, all previous, fully // transmissive hits will lead the normal/albedo to be replaced by the // current hit if (firstHit || allHitsFullyTransmissive) { #ifdef OSPRAY_ENABLE_VOLUMES sample.z = min(ray.t, volumeRay.t); #endif sample.albedo = surfaceShading.albedo; sample.normal = dg.Ns; if (sample.geomID == RTC_INVALID_GEOMETRY_ID) { sample.instID = dg.instID; sample.geomID = dg.objID; sample.primID = ray.primID; } firstHit = false; } // A sequence of hits is considered fully transparent if it's total // normalized transmission is close to 1.0f and all previous hits were // fully transmissive allHitsFullyTransmissive = allHitsFullyTransmissive && surfaceShading.opacity < self->super.minContribution; // Blend with output final color outColor = outColor + outTransmission * surfaceShading.shadedColor; outTransmission = outTransmission * surfaceShading.transmission; // Early exit if remaining transmission is below min contribution // threshold if (luminance(outTransmission) < self->super.minContribution) { outTransmission = make_vec3f(0.f); break; } // Prepare ray for next loop iteration, // start from the last geometry hit all over to initial Tfar setRay(ray, ray.t + dg.epsilon, originalRayTFar); } else { // Blend background with output final color vec4f backgroundColor = Renderer_getBackground(&self->super, sample.pos, ffh); outColor = outColor + outTransmission * make_vec3f(backgroundColor); outTransmission = outTransmission * (1.f - backgroundColor.w); // Initialize other per sample data with first hit values // If the ray hits the background and comes from a fully transmissive // path, we overwrite normals/albedo by background values if (firstHit || allHitsFullyTransmissive) { #ifdef OSPRAY_ENABLE_VOLUMES sample.z = min(ray.t, volumeRay.t); #endif sample.albedo = make_vec3f(backgroundColor); // TODO volume albedo sample.normal = make_vec3f(0.f); } // No more intersections break; } } #if defined(OSPRAY_ENABLE_VOLUMES) && !defined(OSPRAY_TARGET_SYCL) // Only a single interval is supported on the GPU, we don't allocate // dynamically freeVolumeIntervals(volumeIntervals); #endif sample.rgb = outColor; sample.alpha = 1.f - luminance(outTransmission); } SYCL_EXTERNAL vec3f SciVis_computeAO(const uniform SciVis *uniform self, const World *uniform world, varying LDSampler *uniform ldSampler, const varying DifferentialGeometry &dg, const uniform int sampleCnt, const uniform float aoRadius, const varying vec3i &sampleID, const uniform FeatureFlagsHandler &ffh) { const uniform int accumID = reduce_max(sampleID.z) * sampleCnt; // init TEA RNG // RandomTEA rng_state; varying RandomTEA *const uniform rng = &rng_state; RandomTEA_Constructor(rng, sampleID.x, sampleID.y); const vec2f rot = RandomTEA_getFloats(rng); vec3f hits = make_vec3f(0.f); const linear3f localToWorld = frame(dg.Ns); for (uniform int i = 0; i < sampleCnt; i++) { // Use base-5 and base-7 Halton to avoid correlation with sample position const vec2f halton = make_vec2f(PermHalton_sample5(self->super.mathConstants, accumID + i), PermHalton_sample7(self->super.mathConstants, accumID + i)); const vec2f r = CranleyPattersonRotation(halton, rot); const vec3f local_ao_dir = cosineSampleHemisphere(r); const vec3f ao_dir = localToWorld * local_ao_dir; if (dot(ao_dir, dg.Ns) < 0.01f) { // check below surface hits = hits + 1.f; continue; } Ray ao_ray; setRay(ao_ray, dg.P, ao_dir, dg.epsilon, aoRadius); hits = hits + (1.f - lightAlpha( self, ao_ray, world, ldSampler, make_vec3f(1.f), 0.1f, ffh)); } // the cosTheta of cosineSampleHemispherePDF and dot(shadingNormal, ao_dir) // cancel return 1.0f - (hits / (float)sampleCnt); } #define renderSampleFn SciVis_renderSample #include "render/RendererRenderTaskFn.inl" #undef renderSampleFn #ifdef OSPRAY_TARGET_SYCL SYCL_EXTERNAL void SciVis_renderTask(Renderer *uniform self, FrameBuffer *uniform fb, Camera *uniform camera, World *uniform world, const uint32 *uniform taskIDs, const sycl::nd_item<3> taskIndex, const uniform FeatureFlagsHandler &ffh) { Renderer_default_renderTask(self, fb, camera, world, taskIDs, taskIndex, ffh); } #else export void SciVis_renderTasks(void *uniform _self, void *uniform _fb, void *uniform _camera, void *uniform _world, void *uniform _taskIDs, uniform uint32 numTasks) { Renderer *uniform self = (Renderer * uniform) _self; FrameBuffer *uniform fb = (FrameBuffer * uniform) _fb; Camera *uniform camera = (Camera * uniform) _camera; World *uniform world = (World * uniform) _world; const uint32 *uniform taskIDs = (const uint32 *uniform)_taskIDs; uniform FeatureFlagsHandler ffh; launch[numTasks] Renderer_default_renderTask( self, fb, camera, world, taskIDs, ffh); sync; } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/scivis/SciVisData.cpp000066400000000000000000000066111456566705700250670ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "SciVisData.h" #include "common/Instance.h" #include "common/World.h" #include "lights/AmbientLight.h" #include "lights/HDRILight.h" #include "lights/SunSkyLight.h" // ispc shared #include "lights/LightShared.h" namespace ospray { namespace { void addVisibleOnlyToArray(std::vector &lightViews, uint32_t &visibleOnly, ISPCRTMemoryView lightSh) { if (visibleOnly == lightViews.size()) lightViews.push_back(lightSh); else { // insert light at the visibleOnly index lightViews.push_back(lightViews[visibleOnly]); lightViews[visibleOnly] = lightSh; } visibleOnly++; } vec3f addLightsToArray(std::vector &lightViews, uint32_t &visibleOnly, Ref> lights, const ispc::Instance *instanceSh) { vec3f aoColor = vec3f(0.f); for (auto &&light : *lights) { // just extract color from ambient lights const auto ambient = dynamic_cast(light); if (ambient) { addVisibleOnlyToArray( lightViews, visibleOnly, light->createSh(0, instanceSh)); aoColor += ambient->radiance; continue; } // no illumination from HDRI lights const auto hdri = dynamic_cast(light); if (hdri) { addVisibleOnlyToArray( lightViews, visibleOnly, light->createSh(0, instanceSh)); continue; } // sun-sky: only sun illuminates const auto sunsky = dynamic_cast(light); if (sunsky) { addVisibleOnlyToArray(lightViews, visibleOnly, light->createSh(0, instanceSh)); // sky visible only lightViews.push_back(light->createSh(1, instanceSh)); // sun continue; } // handle the remaining types of lights for (uint32_t id = 0; id < light->getShCount(); id++) lightViews.push_back(light->createSh(id, instanceSh)); } return aoColor; } } // namespace SciVisData::SciVisData(const World &world) : AddStructShared(world.getISPCDevice().getIspcrtContext()) { vec3f aoColor = vec3f(0.f); uint32_t visibleOnly = 0; // Add lights not assigned to any instance if (world.lights) aoColor += addLightsToArray(lightViews, visibleOnly, world.lights, nullptr); // Iterate through all world instances if (world.instances) { for (auto &&inst : *world.instances) { // Skip instances without lights if (!inst->group->lights) continue; // Add instance lights to array aoColor += addLightsToArray( lightViews, visibleOnly, inst->group->lights, inst->getSh()); } } // Retrieve shared memory pointer from each light view and store them // in a temporary local std::vector std::vector lights(lightViews.size()); for (uint32_t i = 0; i < lightViews.size(); i++) lights[i] = (ispc::Light *)ispcrtSharedPtr(lightViews[i]); // Then create shared buffer from the temporary std::vector lightArray = make_buffer_shared_unique( world.getISPCDevice().getIspcrtContext(), lights); getSh()->lights = lightArray->sharedPtr(); getSh()->numLights = lights.size(); getSh()->numLightsVisibleOnly = visibleOnly; getSh()->aoColorPi = aoColor * float(pi); } SciVisData::~SciVisData() { // Delete all lights structures for (ISPCRTMemoryView lv : lightViews) BufferSharedDelete(lv); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/scivis/SciVisData.h000066400000000000000000000010021456566705700245210ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/StructShared.h" #include "render/RendererData.h" // ispc shared #include "SciVisDataShared.h" namespace ospray { struct World; struct SciVisData : public AddStructShared { SciVisData(const World &world); ~SciVisData() override; private: std::vector lightViews; std::unique_ptr> lightArray; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/scivis/SciVisDataShared.h000066400000000000000000000013471456566705700256640ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Light; struct SciVisData { // array containing the scene light sources // the lights are sorted: first lights that are not sampled (visible only), // then lights that are both sampled and visible Light **lights; uint32 numLights; // total number of light sources uint32 numLightsVisibleOnly; // number of lights that are not sampled // (visible only) vec3f aoColorPi; #ifdef __cplusplus SciVisData() : lights(nullptr), numLights(0), numLightsVisibleOnly(0), aoColorPi(0.f) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/scivis/SciVisShared.h000066400000000000000000000010551456566705700250660ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/RendererShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct SciVis { Renderer super; bool shadowsEnabled; bool visibleLights; int aoSamples; float aoRadius; float volumeSamplingRate; #ifdef __cplusplus SciVis() : shadowsEnabled(false), visibleLights(false), aoSamples(0), aoRadius(1e20f), volumeSamplingRate(1.f) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/render/scivis/lightAlpha.ispc000066400000000000000000000064221456566705700253260ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/FeatureFlagsEnum.h" #include "math/random.ih" #include "math/sampling.ih" #include "render/util.ih" // SciVis renderer #include "surfaces.ih" #ifdef OSPRAY_ENABLE_VOLUMES #include "render/ao/volumes.ih" #endif // c++ shared #include "SciVisShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE // Lighting functions // SYCL_EXTERNAL vec3f lightAlpha(const uniform SciVis *uniform self, Ray &ray, const World *uniform world, varying LDSampler *uniform ldSampler, vec3f weight, uniform float quality, const uniform FeatureFlagsHandler &ffh) { vec3f alpha = make_vec3f(1.f); const float org_t_max = ray.t; #ifdef OSPRAY_ENABLE_VOLUMES const uniform FeatureFlags ff = getFeatureFlags(ffh); #ifdef OSPRAY_TARGET_SYCL // We only support a single volume interval on the GPU VolumeInterval vInterval; VolumeIntervals volumeIntervals; volumeIntervals.numVolumeIntervals = 0; volumeIntervals.numAllocated = 1; volumeIntervals.intervals = &vInterval; #else // Allocate memory for volume intervals VolumeIntervals volumeIntervals; allocVolumeIntervals(volumeIntervals); #endif #endif // First trace the ray across clipping scene to calculate ray intervals, // this step should keep ray structure unchanged RayIntervals rayIntervals; traceClippingRay(world, ray, rayIntervals, ffh); while (true) { // Then trace normal geometry using calculated ray intervals, // if hit ray.t will be updated // WA for https://jira.devtools.intel.com/browse/XDEPS-4875 #ifndef OSPRAY_TARGET_SYCL traceGeometryRayIntervals(world, ray, rayIntervals, ffh); #else traceGeometryRay(world, ray, ffh); #endif #ifdef OSPRAY_ENABLE_VOLUMES if (ff.other & FFO_VOLUME_IN_SCENE) { // Determine volume intervals by tracing ray in the volume scene Ray volumeRay = ray; traceVolumeRay(world, volumeRay, volumeIntervals); // Sample volumes across volume intervals (in front of geometry hit) if (volumeIntervals.numVolumeIntervals > 0) { vec4f volumeColor = integrateVolumeIntervals(volumeIntervals, rayIntervals, volumeRay, ldSampler, self->volumeSamplingRate * quality, ffh); alpha = alpha * make_vec3f(1.f - volumeColor.w); } } #else (void)ldSampler; (void)quality; #endif // If any geometry has been hit const bool rayHadHit = hadHit(ray); if (rayHadHit) { // Prepare differential geometry structure DifferentialGeometry dg; postIntersect(world, &self->super, dg, ray, DG_COLOR | DG_TEXCOORD, ffh); const SciVisBSDF bsdf = evalMaterial(dg, ffh); alpha = alpha * bsdf.transmission; // Prepare ray for next loop iteration, // start from the last geometry hit all over to initial Tfar setRay(ray, ray.t + dg.epsilon, org_t_max); } else { break; } // Check if there is enough contribution from this light if (luminance(alpha * weight) < self->super.minContribution) { alpha = make_vec3f(0.f); break; } } #if defined(OSPRAY_ENABLE_VOLUMES) && !defined(OSPRAY_TARGET_SYCL) // No dynamic allocation on GPU freeVolumeIntervals(volumeIntervals); #endif return alpha; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/scivis/surfaces.ih000066400000000000000000000047711456566705700245330ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "SciVis.ih" #include "common/FeatureFlagsEnum.h" #include "render/Material.ih" #include "render/materials/OBJ.ih" // c++ shared #include "render/materials/OBJShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE struct SurfaceShadingInfo { vec3f shadedColor; vec3f transmission; vec3f albedo; float opacity; }; typedef SurfaceShadingInfo SSI; SYCL_EXTERNAL __noinline SSI SciVis_computeShading(const SciVis *uniform self, const World *uniform world, const DifferentialGeometry &dg, ScreenSample &sample, varying LDSampler *uniform ldSampler, const varying vec3f &inDir, const uniform FeatureFlagsHandler &ff); SYCL_EXTERNAL vec3f evaluateLights(const World *uniform world, const DifferentialGeometry &dg, const Ray &ray, const uniform FeatureFlagsHandler &ffh); struct SciVisBSDF { vec3f diffuse; vec3f specular; float shininess; vec3f transmission; vec3f albedo; float opacity; }; inline SciVisBSDF evalMaterial( const DifferentialGeometry &dg, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlagsOther ffo = getFeatureFlagsOther(ffh); const OBJ *mat = (const OBJ *)dg.material; // defaults SciVisBSDF res; res.diffuse = make_vec3f(dg.color); res.specular = make_vec3f(0.0f); res.shininess = 10.0f; res.transmission = make_vec3f(1.f - dg.color.w); res.opacity = dg.color.w; foreach_unique (m in mat) { if (m != NULL && m->super.type == MATERIAL_TYPE_OBJ) { float d = m->d * get1f_ff(m->dMap, dg, 1.f, ffh) * dg.color.w; res.diffuse = res.diffuse * m->Kd; if (valid(m->KdMap) && (ffo & FFO_TEXTURE_IN_MATERIAL)) { vec4f Kd_from_map = get4f(m->KdMap, dg); res.diffuse = res.diffuse * make_vec3f(Kd_from_map); d *= Kd_from_map.w; } res.diffuse = res.diffuse * d; res.specular = d * m->Ks * get3f_ff(m->KsMap, dg, make_vec3f(1.f), ffh); res.shininess = m->Ns * get1f_ff(m->NsMap, dg, 1.f, ffh); res.transmission = m->Tf * d + make_vec3f(1.f - d); res.opacity = d; } } res.albedo = res.diffuse + res.specular; // before normalization! // convert from Phong exponent to Blinn res.shininess *= 4.0f; // BRDF normalization res.diffuse = res.diffuse * (float)one_over_pi; res.specular = res.specular * ((res.shininess + 2.f) * (float)one_over_four_pi * rcp(2.f - exp(res.shininess * -(float)lntwo_over_two))); return res; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/scivis/surfaces.ispc000066400000000000000000000100141456566705700250540ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/FeatureFlagsEnum.h" #include "lights/LightDispatch.ih" #include "math/random.ih" #include "math/sampling.ih" #include "render/util.ih" #include "surfaces.ih" // c++ shared #include "SciVisDataShared.h" #include "SciVisShared.h" #include "lights/LightShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE vec3f directIllumination(const uniform SciVis *uniform self, const World *uniform world, const varying DifferentialGeometry &dg, ScreenSample &sample, varying LDSampler *uniform ldSampler, const varying SciVisBSDF &bsdf, const varying vec3f &inDir, const uniform FeatureFlagsHandler &ffh) { vec3f color = make_vec3f(0.f); const uniform SciVisData &scivisData = *((const uniform SciVisData *)world->scivisData); if (!scivisData.lights) return color; // calculate shading for all lights for (uniform uint32 i = scivisData.numLightsVisibleOnly; i < scivisData.numLights; i++) { const Light *uniform l = scivisData.lights[i]; const vec2f s = make_vec2f(0.0f); // sample center of area lights const Light_SampleRes light = Light_dispatch_sample(l, dg, s, sample.ray.time, ffh); if (reduce_max(light.weight) > 0.f) { // any potential contribution? const float cosNL = dot(light.dir, dg.Ns); if (cosNL < 0.0f) continue; const vec3f H = normalize(light.dir - inDir); const float cosNH = dot(H, dg.Ns); const vec3f specular = bsdf.specular * powf(cosNH, bsdf.shininess); const vec3f diffuse = bsdf.diffuse * cosNL; const vec3f light_contrib = (diffuse + specular) * light.weight; if (self->shadowsEnabled) { if (luminance(light_contrib) > self->super.minContribution) { vec3f P = dg.P; if (dot(dg.Ng, light.dir) < 0.0f) P = P - (2.f * dg.epsilon) * dg.Ng; Ray shadowRay; setRay(shadowRay, P, light.dir, 0.0f, light.dist); vec3f light_alpha = lightAlpha( self, shadowRay, world, ldSampler, light_contrib, 0.25f, ffh); color = color + light_alpha * light_contrib; } } else { color = color + light_contrib; } } } return color; } SYCL_EXTERNAL __noinline SSI SciVis_computeShading(const SciVis *uniform self, const World *uniform world, const DifferentialGeometry &dg, ScreenSample &sample, varying LDSampler *uniform ldSampler, const varying vec3f &inDir, const uniform FeatureFlagsHandler &ffh) { SSI retval; const SciVisBSDF bsdf = evalMaterial(dg, ffh); retval.albedo = bsdf.albedo; vec3f color = directIllumination(self, world, dg, sample, ldSampler, bsdf, inDir, ffh); vec3f ao = make_vec3f(1.f); const uniform SciVisData &scivisData = *((const uniform SciVisData *)world->scivisData); if (self->aoSamples > 0 && luminance(scivisData.aoColorPi) > self->super.minContribution) ao = SciVis_computeAO(self, world, ldSampler, dg, self->aoSamples, self->aoRadius, sample.sampleID, ffh); color = color + bsdf.diffuse * ao * scivisData.aoColorPi; retval.shadedColor = color; retval.transmission = bsdf.transmission; retval.opacity = bsdf.opacity; return retval; } SYCL_EXTERNAL vec3f evaluateLights(const World *uniform world, const DifferentialGeometry &dg, const Ray &ray, const uniform FeatureFlagsHandler &ffh) { // Iterate through all lights vec3f color = make_vec3f(0.f); const uniform SciVisData &scivisData = *((const uniform SciVisData *)world->scivisData); for (uniform uint32 i = 0; i < scivisData.numLights; i++) { // Skip lights with disabled visibility via parameter const Light *uniform l = scivisData.lights[i]; if (!l->isVisible) continue; // Evaluate light contribution const Light_EvalRes le = Light_dispatch_eval(l, dg, ray.dir, ray.t0, ray.t, ray.time, ffh); color = color + le.radiance; } return color; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/scivis/volumes.ih000066400000000000000000000011611456566705700244000ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #pragma once #include "common/Clipping.ih" #include "common/FeatureFlagsEnum.h" #include "common/Ray.ih" #include "common/VolumeIntervals.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct LDSampler; SYCL_EXTERNAL vec4f integrateVolumeIntervalsGradient(SciVisRenderContext &rc, const VolumeIntervals &intervals, const RayIntervals &rayIntervals, Ray &ray, varying LDSampler *uniform ldSampler, const uniform float samplingRate, const uniform FeatureFlagsHandler &ffh); OSPRAY_END_ISPC_NAMESPACE #endif RenderKit-ospray-f2a61c2/modules/cpu/render/scivis/volumes.ispc000066400000000000000000000341061456566705700247430ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/FeatureFlagsEnum.h" #ifdef OSPRAY_ENABLE_VOLUMES #include "math/random.ih" #include "math/sampling.ih" #include "render/util.ih" #include "surfaces.ih" #include "volume/VolumetricModel.ih" #include "volume/transferFunction/TransferFunctionDispatch.ih" #include "volumes.ih" // c++ shared #include "SciVisShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE #ifndef OSPRAY_TARGET_SYCL struct VolumeContext { uniform uint8 intervalIteratorBuffer[VKL_MAX_INTERVAL_ITERATOR_SIZE]; VKLIntervalIterator intervalIterator; VKLInterval interval; vec3f org; vec3f dir; float iuLength; // VKL interval length in sampling steps as an unit float iuDistance; // sampling distance within VKL interval in sampling steps // as an unit float distance; // last sampling distance from 'vc.org' vec4f sample; uint32 ready; // 1 if sample is ready to be used }; static void sampleVolume(SciVisRenderContext &rc, VolumeContext &vc, const VolumetricModel *uniform m, Ray &ray, const VolumeInterval &vi, const uniform float samplingRate) { // We have to iterate till we get a valid sample value float dt = 0.f; float sampleVal = nan; vec3f p; // in volume local coords while (isnan(sampleVal)) { // Iterate till sampling position is within interval float emptySpace = 0.f; while (vc.iuDistance > vc.iuLength) { // Get next VKL interval const float prevUpper = vc.interval.tRange.upper; if (vklIterateIntervalV(vc.intervalIterator, &vc.interval)) { // Intervals may not be contiguous, accumulate empty space emptySpace += max(vc.interval.tRange.lower - prevUpper, 0.f); // Make it local for the next interval vc.iuDistance -= vc.iuLength; // Calculate how many steps can be made within this interval const float samplingStep = vc.interval.nominalDeltaT / samplingRate; vc.iuLength = (vc.interval.tRange.upper - vc.interval.tRange.lower) / samplingStep; // Initialize distance if necessary vc.distance = (vc.distance == inf) ? vc.interval.tRange.lower : vc.distance; } else { // The end of the volume has been reached vc.distance = inf; return; } } // Calculate sampling distance const float samplingStep = vc.interval.nominalDeltaT / samplingRate; const float newDistance = vc.interval.tRange.lower + vc.iuDistance * samplingStep; // Prepare sampling position p = vc.org + newDistance * vc.dir; // Sample volume value in given point sampleVal = vklComputeSampleV( &m->volume->vklSampler, (const varying vkl_vec3f *uniform) & p); // Go to the next sub-interval vc.iuDistance += 1.f; dt = newDistance - vc.distance - emptySpace; vc.distance = newDistance; } // Apply transfer function to get color with alpha TransferFunction *uniform tf = m->transferFunction; vc.sample = TransferFunction_dispatch_get(tf, sampleVal); // compute gradient shading lighting if (m->gradientShadingScale > 0.0f && vc.sample.w > 0.0f) { uniform FeatureFlagsHandler ffh; vec3f ns = Volume_getGradient(m->volume, p, ffh); if (dot(ns, ns) > 1e-6f) { // assume that opacity directly correlates to volume scalar field, i.e. // that "outside" has lower values; because the gradient point towards // increasing values we need to flip it ns = neg(ns); // use scivis shading function // Prepare differential geometry structure DifferentialGeometry dg; dg.color = vc.sample; dg.material = NULL; dg.epsilon = dt / 2.f; // transform to world coords dg.Ns = dg.Ng = normalize(xfmVector(transposed(vi.instance->rcp_xfm.l), ns)); dg.P = ray.org + vc.distance * ray.dir; SSI shading = SciVis_computeShading( rc.renderer, rc.world, dg, rc.sample, rc.ldSampler, ray.dir, ffh); vec4f shadedColor = make_vec4f( shading.shadedColor, 1.f - luminance(shading.transmission)); vc.sample = lerp(m->gradientShadingScale, vc.sample, shadedColor); } } // Weight the opacity with deltaT using Beer law vc.sample.w = exp(-vc.sample.w * dt * m->densityScale); } static float sampleAllVolumes(SciVisRenderContext &rc, const VolumeIntervals &volumeIntervals, varying VolumeContext *uniform volumeContexts, Ray &ray, const uniform float samplingRate, vec4f &sampledColor) { // Look for the closest sample across all volumes float minDist = inf; int usedSampleId = -1; for (uniform uint32 i = 0; i < reduce_max(volumeIntervals.numVolumeIntervals); i++) { if (i >= volumeIntervals.numVolumeIntervals) break; // If the sample has been used already regenerate a new one VolumeContext &vc = volumeContexts[i]; if (vc.ready == 0) { const VolumeInterval &vi = volumeIntervals.intervals[i]; foreach_unique (m in vi.volumetricModel) sampleVolume(rc, vc, m, ray, vi, samplingRate); vc.ready = 1; } // Take the sample if closer if (vc.distance < minDist) { minDist = vc.distance; sampledColor = vc.sample; usedSampleId = i; const SciVis *scivis = rc.renderer; if (minDist < ray.t && sampledColor.w < 1.0f - scivis->super.minContribution) { ray.t = minDist; ray.geomID = volumeIntervals.intervals[i].geomID; ray.instID = volumeIntervals.intervals[i].instID; } } } // Mark used samples as not ready if (usedSampleId != -1) { volumeContexts[usedSampleId].ready = 0; } // Return distance for sampled color return minDist; } SYCL_EXTERNAL vec4f integrateVolumeIntervalsGradient(SciVisRenderContext &rc, const VolumeIntervals &volumeIntervals, const RayIntervals &rayIntervals, Ray &ray, varying LDSampler *uniform ldSampler, const uniform float samplingRate, const uniform FeatureFlagsHandler &) { // Array of volume contexts varying VolumeContext *uniform volumeContexts = (varying VolumeContext * uniform) pushTLS(reduce_max(volumeIntervals.numVolumeIntervals) * sizeof(varying VolumeContext)); // Sampling position jitter const float jitter = LDSampler_getFloat(ldSampler, 0); // Iterate through all volumes and initialize its contexts with data that // do not change across ray intervals for (uniform uint32 i = 0; i < reduce_max(volumeIntervals.numVolumeIntervals); i++) { if (i >= volumeIntervals.numVolumeIntervals) break; // Transform ray into the volume local space const VolumeInterval &vi = volumeIntervals.intervals[i]; Ray transformedRay = ray; AffineSpace3f instanceRcpXfm = vi.instance->rcp_xfm; transformRay(transformedRay, instanceRcpXfm); // Set volume context initial values VolumeContext &vc = volumeContexts[i]; vc.org = transformedRay.org; vc.dir = transformedRay.dir; } // Define initial color and transmission vec3f color = make_vec3f(0.f); float transmission = 1.f; // Iterate through all ray intervals const SciVis *uniform scivis = rc.renderer; for (uniform uint32 i = 0; i < reduce_max(rayIntervals.count) && (transmission > scivis->super.minContribution); i++) { if (i >= rayIntervals.count) break; // Iterate through all volumes for (uniform uint32 j = 0; j < reduce_max(volumeIntervals.numVolumeIntervals); j++) { if (j >= volumeIntervals.numVolumeIntervals) break; // Calculate volume and ray intervals union const VolumeInterval &vi = volumeIntervals.intervals[j]; range1f rInterval = rayIntervals.intervals[i]; rInterval.lower = max(rInterval.lower, vi.interval.lower); rInterval.upper = min(rInterval.upper, vi.interval.upper); // Reset distance to sample VolumeContext &vc = volumeContexts[j]; vc.distance = inf; // Check if volume and ray intervals overlap if (rInterval.upper <= rInterval.lower) { // Skip this volume if not vc.ready = 1; continue; } // We will sample across this volume so initialize members used during // sampling vc.iuDistance = jitter; vc.iuLength = 0.f; vc.ready = 0; vc.interval.tRange.upper = inf; // There might be different volumetric models used across vector lanes // so we must iterate over them float time = 0.5f; VolumetricModel *varying model = vi.volumetricModel; // Create volume interval iterator foreach_unique (m in model) vc.intervalIterator = vklInitIntervalIteratorV(&m->vklIntervalContext, (varying vkl_vec3f *)&vc.org, (varying vkl_vec3f *)&vc.dir, (varying vkl_range1f *)&rInterval, &time, vc.intervalIteratorBuffer); } // Propagate ray across all volumes till opaque while (transmission > scivis->super.minContribution) { // Sample across all volumes vec4f sampledColor; float dist = sampleAllVolumes( rc, volumeIntervals, volumeContexts, ray, samplingRate, sampledColor); // Exit loop if nothing sampled if (dist == inf) break; // Blend sampled color color = color + transmission * (1.f - sampledColor.w) * make_vec3f(sampledColor); transmission *= sampledColor.w; } } popTLS(volumeContexts); // Return final color return make_vec4f(color, transmission); } #else // GPU version SYCL_EXTERNAL vec4f integrateVolumeIntervalsGradient(SciVisRenderContext &rc, const VolumeIntervals &volumeIntervals, const RayIntervals &, Ray &ray, varying LDSampler *uniform ldSampler, const uniform float samplingRate, const uniform FeatureFlagsHandler &ffh) { const VolumeInterval &vi = volumeIntervals.intervals[0]; Ray tRay = ray; AffineSpace3f instanceRcpXfm = vi.instance->rcp_xfm; transformRay(tRay, instanceRcpXfm); // Define initial color with alpha vec3f color = make_vec3f(0.f); float transmission = 1.f; const uniform FeatureFlags ff = getFeatureFlags(ffh); uniform uint8 intervalIteratorBuffer[VKL_MAX_INTERVAL_ITERATOR_SIZE]; VolumetricModel *varying m = vi.volumetricModel; VKLIntervalIterator intervalIterator = vklInitIntervalIteratorV(&m->vklIntervalContext, (varying vkl_vec3f *)&tRay.org, (varying vkl_vec3f *)&tRay.dir, (varying vkl_range1f *)&vi.interval, .5f, intervalIteratorBuffer, ff.volume); // Sampling position jitter const float jitter = LDSampler_getFloat(ldSampler, 0); // Propagate ray across all volumes till opaque const SciVis *uniform scivis = rc.renderer; float distance = inf; float iuDistance = jitter; float iuLength = 0.f; VKLInterval interval; interval.tRange.upper = inf; float samplingStep = 0.f; while (transmission > scivis->super.minContribution) { // Iterate till sampling position is within interval float emptySpace = 0.f; while (iuDistance > iuLength) { // Get next VKL interval const float prevUpper = interval.tRange.upper; if (vklIterateIntervalV(intervalIterator, &interval, ff.volume)) { // Intervals may not be contiguous, accumulate empty space emptySpace += max(interval.tRange.lower - prevUpper, 0.f); // Make it local for the next interval iuDistance -= iuLength; // Calculate how many steps can be made within this interval samplingStep = interval.nominalDeltaT / samplingRate; iuLength = (interval.tRange.upper - interval.tRange.lower) / samplingStep; // Initialize distance if necessary distance = (distance == inf) ? interval.tRange.lower : distance; } else { // The end of the volume has been reached return make_vec4f(color, transmission); } } // Calculate sampling distance const float newDistance = interval.tRange.lower + iuDistance * samplingStep; // Prepare sampling position const vec3f p = tRay.org + newDistance * tRay.dir; // Sample volume value in given point float sampleVal = vklComputeSampleV(&m->volume->vklSampler, (const varying vkl_vec3f *uniform) & p, 0, .5f, ff.volume); if (!isnan(sampleVal)) { // Apply transfer function to get color with alpha vec4f sampledColor = TransferFunction_dispatch_get(m->transferFunction, sampleVal); // compute gradient shading lighting float dt = newDistance - distance - emptySpace; if ((ff.other & FFO_VOLUME_SCIVIS_SHADING) && (sampledColor.w > 0.0f)) { vec3f ns = Volume_getGradient(m->volume, p, ffh); if (dot(ns, ns) > 1e-6f) { // assume that opacity directly correlates to volume scalar field, // i.e. that "outside" has lower values; because the gradient // point towards increasing values we need to flip it ns = neg(ns); // use scivis shading function // Prepare differential geometry structure DifferentialGeometry dg; dg.color = sampledColor; dg.material = NULL; dg.epsilon = dt / 2.f; // transform to world coords dg.Ns = dg.Ng = normalize(xfmVector(transposed(vi.instance->rcp_xfm.l), ns)); dg.P = p; SSI shading = SciVis_computeShading( rc.renderer, rc.world, dg, rc.sample, rc.ldSampler, ray.dir, ffh); vec4f shadedColor = make_vec4f( shading.shadedColor, 1.f - luminance(shading.transmission)); sampledColor = lerp(m->gradientShadingScale, sampledColor, shadedColor); } } // Weight the opacity with deltaT using Beer law sampledColor.w = exp(-sampledColor.w * dt * m->densityScale); // Alpha blend sampled color color = color + transmission * (1.f - sampledColor.w) * make_vec3f(sampledColor); transmission *= sampledColor.w; } // Go to the next sub-interval iuDistance += 1.f; distance = newDistance; } // Return final color return make_vec4f(color, transmission); } #endif OSPRAY_END_ISPC_NAMESPACE #endif RenderKit-ospray-f2a61c2/modules/cpu/render/shaders/000077500000000000000000000000001456566705700225165ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/render/shaders/Flakes.ih000066400000000000000000000033651456566705700242540ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Noise.ih" #include "render/bsdfs/BeckmannDistribution.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Flakes { float scale; float density; float spread; float jitter; }; inline vec3f Flakes_eval(const Flakes &self, vec3f P, int &mask) { vec3f N = make_vec3f(0.f, 0.f, 1.f); mask = 0; if (self.density <= 0.f || self.spread <= 0.f) return N; const BeckmannDistribution flakeDistribution = make_BeckmannDistribution(roughnessToAlpha(self.spread)); P = P * self.scale; // Simple Worley cellular noise with jittered feature points // [Apodaca and Gritz, 1999, "Advanced RenderMan: Creating CGI for Motion // Pictures", pp. 255-261] const vec3f thisCell = floor(P) + 0.5f; float f1 = 1000.f; unsigned int cellRnd; for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { for (int k = -1; k <= 1; k++) { const vec3f testCell = thisCell + make_vec3f(i, j, k); // generate a random ID for the test cell unsigned int rnd = cellNoise1ui(testCell); // generate the position of the feature point in the test cell const vec3f pos = testCell + self.jitter * (LCG_getFloat3(rnd) - 0.5f); // distance test const vec3f offset = pos - P; const float dist = dot(offset, offset); // actually dist^2 if (dist < f1) { f1 = dist; cellRnd = rnd; } } } } // test whether the flake exists if (LCG_getFloat(cellRnd) <= self.density) { // generate a random normal for the flake float pdf; N = sample(flakeDistribution, pdf, LCG_getFloat2(cellRnd)); mask = 1; } return normalize(N); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/shaders/Noise.ih000066400000000000000000000017651456566705700241260ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "math/random.ih" OSPRAY_BEGIN_ISPC_NAMESPACE // Hash function used in noise functions inline unsigned int noiseHash(const vec3ui &v, unsigned int seed) { unsigned int hash = seed; hash = MurmurHash3_mix(hash, v.x); hash = MurmurHash3_mix(hash, v.y); hash = MurmurHash3_mix(hash, v.z); hash ^= 3 * 4; hash = MurmurHash3_finalize(hash); return hash; } inline unsigned int cellNoise1ui(const vec3f &v) { const vec3ui key = intbits(floor(v)); return noiseHash(key, 0x537e6612); } inline float cellNoise1f(const vec3f &v) { const vec3ui key = intbits(floor(v)); return to_float_unorm(noiseHash(key, 0x537e6612)); } inline vec3f cellNoise3f(const vec3f &v) { const vec3ui key = intbits(floor(v)); return make_vec3f(to_float_unorm(noiseHash(key, 0xf7acd0ce)), to_float_unorm(noiseHash(key, 0x6e2bf582)), to_float_unorm(noiseHash(key, 0xc6ae6d0d))); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/util.h000066400000000000000000000017451456566705700222220ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once /*! \file render/util.h Defines some utility functions shared by different * shading codes */ #include "common/OSPCommon.h" namespace ospray { // TODO: Could use pdep/pext inline uint32_t partitionZOrder(uint32_t n) { n &= 0x0000FFFF; n = (n | (n << 8)) & 0x00FF00FF; n = (n | (n << 4)) & 0x0F0F0F0F; n = (n | (n << 2)) & 0x33333333; n = (n | (n << 1)) & 0x55555555; return n; } inline uint32_t unpartitionZOrder(uint32_t n) { n &= 0x55555555; n = (n ^ (n >> 1)) & 0x33333333; n = (n ^ (n >> 2)) & 0x0F0F0F0F; n = (n ^ (n >> 4)) & 0x00FF00FF; n = (n ^ (n >> 8)) & 0x0000FFFF; return n; } inline uint32_t interleaveZOrder(uint32_t x, uint32_t y) { return partitionZOrder(x) | (partitionZOrder(y) << 1); } inline void deinterleaveZOrder(uint32_t z, uint32_t &x, uint32_t &y) { x = y = 0; x = unpartitionZOrder(z); y = unpartitionZOrder(z >> 1); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/render/util.ih000066400000000000000000000042701456566705700223670ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "OSPConfig.h" #include "common/FeatureFlagsEnum.h" #include "common/World.ih" #include "rkcommon/math/vec.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL float computeAO(const Renderer *uniform, const World *uniform, const varying DifferentialGeometry &, const uniform int sampleCnt, const uniform float aoRadius, const varying vec3i &sampleID, const uniform FeatureFlagsHandler &ff); // struct that stores a precomputed z-order for tiles of TILE_SIZE x TILE_SIZE // pixels struct z_order_t { // 32-bit field specifying both x and y coordinate of the z-order, // with upper 16 bits for the y coordinate, and lower 16 for the x // coordinate. Compared to using two uint32-arrays, this saves on // gather-loop uniform uint32 xyIdx[TILE_SIZE * TILE_SIZE]; uniform uint32 xs[TILE_SIZE * TILE_SIZE]; uniform uint32 ys[TILE_SIZE * TILE_SIZE]; }; inline uint32 getZOrderX(const uint32 &xs16_ys16) { return xs16_ys16 & (0xffff); } inline uint32 getZOrderY(const uint32 &xs16_ys16) { return xs16_ys16 >> 16; } extern uniform z_order_t z_order; extern uniform bool z_order_initialized; // TODO should use PDEP inline uniform uint32 partitionZOrder(uniform uint32 n) { n &= 0x0000FFFF; n = (n | (n << 8)) & 0x00FF00FF; n = (n | (n << 4)) & 0x0F0F0F0F; n = (n | (n << 2)) & 0x33333333; n = (n | (n << 1)) & 0x55555555; return n; } // TODO should use PEXT inline uniform uint32 unpartitionZOrder(uniform uint32 n) { n &= 0x55555555; n = (n ^ (n >> 1)) & 0x33333333; n = (n ^ (n >> 2)) & 0x0F0F0F0F; n = (n ^ (n >> 4)) & 0x00FF00FF; n = (n ^ (n >> 8)) & 0x0000FFFF; return n; } inline uniform uint32 interleaveZOrder(uniform uint32 x, uniform uint32 y) { return partitionZOrder(x) | (partitionZOrder(y) << 1); } inline void deinterleaveZOrder( uniform uint32 z, uniform uint32 *uniform x, uniform uint32 *uniform y) { assert(x); assert(y); *x = *y = 0; *x = unpartitionZOrder(z); *y = unpartitionZOrder(z >> 1); } #ifdef OSPRAY_TARGET_SYCL const z_order_t *get_zorder(); #else extern const z_order_t *uniform get_zorder(); #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/render/util.ispc000066400000000000000000000042521456566705700227250ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/FeatureFlagsEnum.h" #include "common/World.ih" #include "math/random.ih" #include "math/sampling.ih" #include "render/util.ih" OSPRAY_BEGIN_ISPC_NAMESPACE uniform z_order_t z_order; uniform bool z_order_initialized = false; // precompute a per-pixel z-order to be used within a tile export void precomputeZOrder() { if (!z_order_initialized) { for (uniform uint32 i = 0; i < TILE_SIZE * TILE_SIZE; i++) { deinterleaveZOrder(i, &z_order.xs[i], &z_order.ys[i]); z_order.xyIdx[i] = z_order.xs[i] | (z_order.ys[i] << 16); } z_order_initialized = true; } } SYCL_EXTERNAL float computeAO(const Renderer *uniform renderer, const World *uniform world, const varying DifferentialGeometry &dg, const uniform int sampleCnt, const uniform float aoRadius, const varying vec3i &sampleID, const uniform FeatureFlagsHandler &ffh) { const uniform int accumID = reduce_max(sampleID.z) * sampleCnt; // init TEA RNG // RandomTEA rng_state; varying RandomTEA *const uniform rng = &rng_state; RandomTEA_Constructor(rng, sampleID.x, sampleID.y); const vec2f rot = RandomTEA_getFloats(rng); int hits = 0; const linear3f localToWorld = frame(dg.Ns); for (uniform int i = 0; i < sampleCnt; i++) { // Use base-5 and base-7 Halton to avoid correlation with sample position const vec2f halton = make_vec2f(PermHalton_sample5(renderer->mathConstants, accumID + i), PermHalton_sample7(renderer->mathConstants, accumID + i)); const vec2f r = CranleyPattersonRotation(halton, rot); const vec3f local_ao_dir = cosineSampleHemisphere(r); const vec3f ao_dir = localToWorld * local_ao_dir; if (dot(ao_dir, dg.Ns) < 0.01f) { // check below surface hits++; continue; } Ray ao_ray; setRay(ao_ray, dg.P, ao_dir, dg.epsilon, aoRadius); if (isOccluded(world, ao_ray, ffh)) hits++; } // the cosTheta of cosineSampleHemispherePDF and dot(shadingNormal, ao_dir) // cancel return 1.0f - (hits / (float)sampleCnt); } const z_order_t *uniform get_zorder() { return &z_order; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/texture/000077500000000000000000000000001456566705700213065ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/texture/Texture.cpp000066400000000000000000000007221456566705700234530ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Texture.h" namespace ospray { // Texture definitions //////////////////////////////////////////////////////// Texture::Texture(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device) { managedObjectType = OSP_TEXTURE; } std::string Texture::toString() const { return "ospray::Texture"; } OSPTYPEFOR_DEFINITION(Texture *); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/texture/Texture.h000066400000000000000000000011341456566705700231160ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ISPCDeviceObject.h" #include "common/ObjectFactory.h" #include "common/StructShared.h" // ispc shared #include "TextureShared.h" namespace ospray { struct OSPRAY_SDK_INTERFACE Texture : AddStructShared, public ObjectFactory { Texture(api::ISPCDevice &device); virtual ~Texture() override = default; virtual std::string toString() const override; }; OSPTYPEFOR_SPECIALIZATION(Texture *, OSP_TEXTURE); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/texture/Texture.ih000066400000000000000000000056521456566705700233000ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "../common/DifferentialGeometry.ih" #include "TextureShared.h" #include "texture/TextureDispatch.ih" OSPRAY_BEGIN_ISPC_NAMESPACE inline uniform bool hasAlpha(const uniform Texture *uniform self) { return (self == NULL) ? false : self->hasAlpha; } /*! helper function that returns the sampled value for the first channel of the given texture Right now, this function always asks the texture for all four channels, and then discards all but one; later implementations may have specialized 'get1f' methods with the texture \note self may NOT be NULL! */ inline float get1f( const uniform Texture *uniform self, const varying DifferentialGeometry &dg) { vec4f ret = Texture_dispatch_get(self, dg); return ret.x; } /*! helper function that returns the sampled value for the first three channels of the given texture Right now, this function always asks the texture for all four channels, and then discards all but one; later implementations may have specialized 'get3f' methods with the texture \note self may NOT be NULL! */ inline vec3f get3f( const uniform Texture *uniform self, const varying DifferentialGeometry &dg) { vec4f ret = Texture_dispatch_get(self, dg); return make_vec3f(ret); } /*! helper function that returns the sampled value of the four channels of the given texture. Note that it's up to the texture to define clearly what happens if we ask for four channels even if the texture has less physical channels. \note self may NOT be NULL! */ inline vec4f get4f( const uniform Texture *uniform self, const varying DifferentialGeometry &dg) { return Texture_dispatch_get(self, dg); } /*! helper function that returns the sampled values interpreted as a normal */ inline vec3f getNormal( const uniform Texture *uniform self, const varying DifferentialGeometry &dg) { if (self == NULL) return make_vec3f(0.f, 0.f, 1.f); else return Texture_dispatch_getNormal(self, dg); } /*! helper function: get1f() with a default value if the texture is NULL */ inline float get1f(const uniform Texture *uniform self, const varying DifferentialGeometry &dg, const varying float defaultValue) { if (self == NULL) return defaultValue; else return get1f(self, dg); } /*! helper function: get3f() with a default value if the texture is NULL */ inline vec3f get3f(const uniform Texture *uniform self, const varying DifferentialGeometry &dg, const varying vec3f defaultValue) { if (self == NULL) return defaultValue; else return get3f(self, dg); } /*! helper function: get4f() with a default value if the texture is NULL */ inline vec4f get4f(const uniform Texture *uniform self, const varying DifferentialGeometry &dg, const varying vec4f defaultValue) { if (self == NULL) return defaultValue; else return get4f(self, dg); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/texture/Texture2D.cpp000066400000000000000000000055701456566705700236470ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Texture2D.h" #ifndef OSPRAY_TARGET_SYCL #include "texture/Texture2D_ispc.h" #endif #include "../common/Data.h" namespace ispc { void Texture2D::set(const vec2i &aSize, void *aData, OSPTextureFormat aFormat, OSPTextureFilter aFilter, vec2ui aWrapMode) { size = aSize; format = aFormat; filter = aFilter; wrapMode = aWrapMode; // Due to float rounding frac(x) can be exactly 1.0f (e.g. for very small // negative x), although it should be strictly smaller than 1.0f. We handle // this case by having sizef slightly smaller than size, such that // frac(x)*sizef is always < size. sizef = vec2f(nextafter((float)size.x, -1.0f), nextafter((float)size.y, -1.0f)); halfTexel = vec2f(0.5f / size.x, 0.5f / size.y); data = aData; super.hasAlpha = aFormat == OSP_TEXTURE_RGBA8 || aFormat == OSP_TEXTURE_SRGBA || aFormat == OSP_TEXTURE_RA8 || aFormat == OSP_TEXTURE_LA8 || aFormat == OSP_TEXTURE_RGBA32F || aFormat == OSP_TEXTURE_RGBA16 || aFormat == OSP_TEXTURE_RA16; #ifndef OSPRAY_TARGET_SYCL super.get = reinterpret_cast( ispc::Texture2D_get_addr(aFormat, aFilter & OSP_TEXTURE_FILTER_NEAREST)); super.getNormal = reinterpret_cast( ispc::Texture2D_getN_addr(aFormat, aFilter & OSP_TEXTURE_FILTER_NEAREST)); #endif } } // namespace ispc namespace ospray { std::string Texture2D::toString() const { return "ospray::Texture2D"; } void Texture2D::commit() { texData = getParamObject("data"); if (!texData || texData->numItems.z > 1) { throw std::runtime_error(toString() + " must have 2D 'data' array using the first two dimensions."); } const vec2i size = vec2i(texData->numItems.x, texData->numItems.y); if (!texData->compact()) { postStatusMsg(OSP_LOG_INFO) << toString() << " does currently not support strides, copying texture data."; auto data = new Data(getISPCDevice(), texData->type, texData->numItems); data->copy(*texData, vec3ui(0)); texData = data; data->refDec(); } format = static_cast( getParam("format", OSP_TEXTURE_FORMAT_INVALID)); filter = static_cast( getParam("filter", OSP_TEXTURE_FILTER_LINEAR)); wrapMode = getParam("wrapMode", vec2ui(getParam("wrapMode", OSP_TEXTURE_WRAP_REPEAT))); if (format == OSP_TEXTURE_FORMAT_INVALID) throw std::runtime_error(toString() + ": invalid 'format'"); if (sizeOf(format) != sizeOf(texData->type)) throw std::runtime_error(toString() + ": 'format'='" + stringFor(format) + "' does not match type of 'data'='" + stringFor(texData->type) + "'!"); // Initialize ispc shared structure getSh()->set(size, texData->data(), format, filter, wrapMode); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/texture/Texture2D.h000066400000000000000000000014211456566705700233030ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Texture.h" #include "common/Data.h" // ispc shared #include "Texture2DShared.h" namespace ospray { // A Texture defined through a 2D Image struct OSPRAY_SDK_INTERFACE Texture2D : public AddStructShared { Texture2D(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device) {} virtual ~Texture2D() override = default; virtual std::string toString() const override; virtual void commit() override; OSPTextureFormat format{OSP_TEXTURE_FORMAT_INVALID}; OSPTextureFilter filter{OSP_TEXTURE_FILTER_LINEAR}; vec2ui wrapMode{OSP_TEXTURE_WRAP_REPEAT}; protected: Ref texData; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/texture/Texture2D.ih000066400000000000000000000041031456566705700234540ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Texture.ih" #include "Texture2DShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL vec4f Texture2D_get( const uniform Texture *uniform self, const DifferentialGeometry &dg); SYCL_EXTERNAL vec3f Texture2D_getNormal( const uniform Texture *uniform self, const DifferentialGeometry &dg); // XXX won't work with MIPmapping: clean implementation with clamping on integer // coords needed then inline vec2f clamp2edge(const uniform Texture2D *uniform self, const vec2f p) { return clamp(p, self->halfTexel, 1.0f - self->halfTexel); } inline float get1f(const uniform Texture2D *uniform self, const varying DifferentialGeometry &dg) { return get1f(&self->super, dg); } inline vec3f get3f(const uniform Texture2D *uniform self, const varying DifferentialGeometry &dg) { return get3f(&self->super, dg); } inline vec4f get4f(const uniform Texture2D *uniform self, const varying DifferentialGeometry &dg) { return get4f(&self->super, dg); } inline vec3f getNormal(const uniform Texture2D *uniform self, const varying DifferentialGeometry &dg) { return getNormal(&self->super, dg); } inline float get1f(const uniform Texture2D *uniform self, const varying DifferentialGeometry &dg, const varying float defaultValue) { return get1f(&self->super, dg, defaultValue); } inline vec3f get3f(const uniform Texture2D *uniform self, const varying DifferentialGeometry &dg, const varying vec3f defaultValue) { return get3f(&self->super, dg, defaultValue); } inline vec4f get4f(const uniform Texture2D *uniform self, const varying DifferentialGeometry &dg, const varying vec4f defaultValue) { return get4f(&self->super, dg, defaultValue); } #if 0 // crashes ISPC! inline DifferentialGeometry dgFromTexCoord(const varying vec2f &c) { DifferentialGeometry dg; dg.primID = -1; dg.st = c; return dg; } #else inline void initDgFromTexCoord(DifferentialGeometry &dg, const varying vec2f &c) { dg.primID = -1; dg.st = c; } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/texture/Texture2D.ispc000066400000000000000000000335111456566705700240170ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Texture2D.ih" #include "ospray/OSPEnums.h" // Low-level texel accessors ////////////////////////////////////////////////////////////////////////////// OSPRAY_BEGIN_ISPC_NAMESPACE #define BYTE2FLOAT (1.f / 255.f) #define SHORT2FLOAT (1.f / 65535.f) // TODO blocking inline vec4f getTexel_RGBA8(const Texture2D *uniform self, const vec2i i) { assert(self); const uint32 c = ((const uint32 *uniform)self->data)[i.y * self->size.x + i.x]; const uint32 r = c & 0xff; const uint32 g = (c >> 8) & 0xff; const uint32 b = (c >> 16) & 0xff; const uint32 a = c >> 24; return make_vec4f((float)r, (float)g, (float)b, (float)a) * BYTE2FLOAT; } inline vec4f getTexel_RGBA16(const Texture2D *uniform self, const vec2i i) { assert(self); const uint32 texelOfs = (i.y * self->size.x + i.x) * 2; // fetch as 2x 32bit uint32 c = ((const uint32 *uniform)self->data)[texelOfs]; const uint32 r = c & 0xffff; const uint32 g = c >> 16; c = ((const uniform uint32 *uniform)self->data)[texelOfs + 1]; const uint32 b = c & 0xffff; const uint32 a = c >> 16; return make_vec4f((float)r, (float)g, (float)b, (float)a) * SHORT2FLOAT; } inline vec4f getTexel_RGB8(const Texture2D *uniform self, const vec2i i) { assert(self); const uint8 *uniform texel = (const uint8 *uniform)self->data; const uint32 texelOfs = 3 * (i.y * self->size.x + i.x); const uint32 r = texel[texelOfs]; const uint32 g = texel[texelOfs + 1]; const uint32 b = texel[texelOfs + 2]; return make_vec4f(make_vec3f((float)r, (float)g, (float)b) * BYTE2FLOAT, 1.f); } inline vec4f getTexel_RGB16(const Texture2D *uniform self, const vec2i i) { assert(self); const uint16 *uniform texel = (const uint16 *uniform)self->data; const uint32 texelOfs = 3 * (i.y * self->size.x + i.x); const uint32 r = texel[texelOfs]; const uint32 g = texel[texelOfs + 1]; const uint32 b = texel[texelOfs + 2]; return make_vec4f( make_vec3f((float)r, (float)g, (float)b) * SHORT2FLOAT, 1.f); } inline vec4f getTexel_RA8(const Texture2D *uniform self, const vec2i i) { assert(self); const uint16 *uniform texel = (const uint16 *uniform)self->data; const uint32 t = texel[i.y * self->size.x + i.x]; const uint32 c = t & 0xff; const uint32 a = t >> 8; return make_vec4f(c * BYTE2FLOAT, 0.f, 0.f, a * BYTE2FLOAT); } inline vec4f getTexel_RA16(const Texture2D *uniform self, const vec2i i) { assert(self); const uint32 *uniform texel = (const uint32 *uniform)self->data; const uint32 t = texel[i.y * self->size.x + i.x]; const uint32 c = t & 0xffff; const uint32 a = t >> 16; return make_vec4f(c * SHORT2FLOAT, 0.f, 0.f, a * SHORT2FLOAT); } inline vec4f getTexel_R8(const Texture2D *uniform self, const vec2i i) { assert(self); const uint8 c = ((const uniform uint8 *uniform)self->data)[i.y * self->size.x + i.x]; return make_vec4f(c * BYTE2FLOAT, 0.f, 0.f, 1.f); } inline vec4f getTexel_R16(const Texture2D *uniform self, const vec2i i) { assert(self); const uint16 c = ((const uniform uint16 *uniform)self->data)[i.y * self->size.x + i.x]; return make_vec4f(c * SHORT2FLOAT, 0.f, 0.f, 1.f); } // luminance (basically gamma-corrected grayscale) with alpha inline vec4f getTexel_LA8(const Texture2D *uniform self, const vec2i i) { assert(self); const uint16 *uniform texel = (const uint16 *uniform)self->data; const uint32 t = texel[i.y * self->size.x + i.x]; const uint32 l = t & 0xff; const uint32 a = t >> 8; return make_vec4f(make_vec3f(srgb_to_linear(l * BYTE2FLOAT)), a * BYTE2FLOAT); } inline vec4f getTexel_LA16(const Texture2D *uniform self, const vec2i i) { const vec4f t = getTexel_RA16(self, i); return make_vec4f(t.x, t.x, t.x, t.w); } // luminance (basically gamma-corrected grayscale) inline vec4f getTexel_L8(const Texture2D *uniform self, const vec2i i) { assert(self); const uint8 l = ((const uniform uint8 *uniform)self->data)[i.y * self->size.x + i.x]; return make_vec4f(make_vec3f(srgb_to_linear(l * BYTE2FLOAT)), 1.f); } inline vec4f getTexel_SRGBA(const Texture2D *uniform self, const vec2i i) { return srgba_to_linear(getTexel_RGBA8(self, i)); } inline vec4f getTexel_SRGB(const Texture2D *uniform self, const vec2i i) { return srgba_to_linear(getTexel_RGB8(self, i)); } inline vec4f getTexel_RGBA32F(const Texture2D *uniform self, const vec2i i) { assert(self); return ((const uniform vec4f *uniform)self->data)[i.y * self->size.x + i.x]; } inline vec4f getTexel_RGB32F(const Texture2D *uniform self, const vec2i i) { assert(self); vec3f v = ((const uniform vec3f *uniform)self->data)[i.y * self->size.x + i.x]; return make_vec4f(v, 1.f); } inline vec4f getTexel_R32F(const Texture2D *uniform self, const vec2i i) { assert(self); float v = ((const uniform float *uniform)self->data)[i.y * self->size.x + i.x]; return make_vec4f(v, 0.f, 0.f, 1.f); } // Texture coordinate utilities ////////////////////////////////////////////////////////////////////////////// inline float wrap_coord( const uint32 wrapMode, const uniform float halfTexel, const float p) { float tc = 0.f; switch (wrapMode) { case OSP_TEXTURE_WRAP_REPEAT: tc = frac(p - halfTexel) + halfTexel; tc = max(tc, 0.f); // filter out inf/NaN break; case OSP_TEXTURE_WRAP_MIRRORED_REPEAT: { tc = 2.f * frac(p * 0.5f); if (tc >= 1.f) tc = 2.f - tc; tc = clamp(tc, halfTexel, 1.f - halfTexel); break; } case OSP_TEXTURE_WRAP_CLAMP_TO_EDGE: tc = clamp(p, halfTexel, 1.f - halfTexel); } return tc; } inline vec2i nearest_coords(const Texture2D *uniform self, const vec2f p) { vec2f tc; tc.x = wrap_coord(self->wrapMode.x, 0.f, p.x); tc.y = wrap_coord(self->wrapMode.y, 0.f, p.y); tc = tc * self->sizef; return make_vec2i(tc); } struct BilinCoords { vec2i st0; vec2i st1; vec2f frac; }; inline BilinCoords bilinear_coords(const Texture2D *uniform self, const vec2f p) { BilinCoords coords; vec2f tc; tc.x = wrap_coord(self->wrapMode.x, self->halfTexel.x, p.x); tc.y = wrap_coord(self->wrapMode.y, self->halfTexel.y, p.y); tc = tc - self->halfTexel; // lower sample shifted by half a texel tc = tc * self->sizef; coords.frac = frac(tc); coords.st0 = make_vec2i(tc); coords.st1 = coords.st0 + 1; // handle border cases as REPEAT if (coords.st1.x >= self->size.x) coords.st1.x = 0; if (coords.st1.y >= self->size.y) coords.st1.y = 0; return coords; } inline vec4f bilerp(const vec2f frac, const vec4f c00, const vec4f c01, const vec4f c10, const vec4f c11) { return lerp(frac.y, lerp(frac.x, c00, c01), lerp(frac.x, c10, c11)); } // Implementations of Texture2D_get for different formats and filter modi ////////////////////////////////////////////////////////////////////////////// #define __define_tex_get(FMT) \ \ static vec4f Texture2D_nearest_##FMT( \ const Texture2D *uniform self, const DifferentialGeometry &dg) \ { \ return getTexel_##FMT(self, nearest_coords(self, dg.st)); \ } \ \ static vec4f Texture2D_bilinear_##FMT( \ const Texture2D *uniform self, const DifferentialGeometry &dg) \ { \ BilinCoords cs = bilinear_coords(self, dg.st); \ \ const vec4f c00 = getTexel_##FMT(self, make_vec2i(cs.st0.x, cs.st0.y)); \ const vec4f c01 = getTexel_##FMT(self, make_vec2i(cs.st1.x, cs.st0.y)); \ const vec4f c10 = getTexel_##FMT(self, make_vec2i(cs.st0.x, cs.st1.y)); \ const vec4f c11 = getTexel_##FMT(self, make_vec2i(cs.st1.x, cs.st1.y)); \ \ return bilerp(cs.frac, c00, c01, c10, c11); \ } \ struct swallow_semicolon #define __define_tex_case(NAME, FMT) \ case OSP_TEXTURE_##FMT: \ return filter_nearest ? (void *uniform) & NAME##_nearest_##FMT \ : (void *uniform) & NAME##_bilinear_##FMT #define __define_call_tex_case(NAME, FMT) \ case OSP_TEXTURE_##FMT: \ return filter_nearest ? NAME##_nearest_##FMT(self, dg) \ : NAME##_bilinear_##FMT(self, dg) #define __define_tex_call_tex_case(FMT) __define_call_tex_case(Texture2D, FMT) #define __define_tex_callN_tex_case(FMT) \ __define_call_tex_case(Texture2D_N, FMT) #define __define_tex_get_case(FMT) __define_tex_case(Texture2D, FMT) #define __define_tex_getN_case(FMT) __define_tex_case(Texture2D_N, FMT) #define __foreach_fetcher(FCT) \ FCT(RGBA8); \ FCT(SRGBA); \ FCT(RGBA32F); \ FCT(RGB8); \ FCT(SRGB); \ FCT(LA8); \ FCT(RA8); \ FCT(RGB32F); \ FCT(R8); \ FCT(L8); \ FCT(R32F); \ FCT(RGBA16); \ FCT(RGB16); \ FCT(RA16); \ FCT(R16) __foreach_fetcher(__define_tex_get); export void *uniform Texture2D_get_addr( const uniform uint32 type, const uniform bool filter_nearest) { switch (type) { __foreach_fetcher(__define_tex_get_case); default: break; } return NULL; }; SYCL_EXTERNAL vec4f Texture2D_get( const uniform Texture *uniform _self, const DifferentialGeometry &dg) { const uniform Texture2D *uniform self = (const uniform Texture2D *uniform)_self; const uniform bool filter_nearest = self->filter & OSP_TEXTURE_FILTER_NEAREST; switch (self->format) { __foreach_fetcher(__define_tex_call_tex_case); default: break; } return make_vec4f(0.f); } static vec3f Texture2D_Normal_neutral( const Texture2D *uniform, const DifferentialGeometry &) { return make_vec3f(0.f, 0.f, 1.f); } #define __define_tex_getN_flt(NAME, C) \ static vec3f Texture2D_N_##NAME( \ const Texture2D *uniform self, const DifferentialGeometry &dg) \ { \ return make_vec3f(Texture2D_##NAME(self, dg)) * C - 1.f; \ } \ struct swallow_semicolon #define __define_tex_getN(FMT, C) \ __define_tex_getN_flt(nearest_##FMT, C); \ __define_tex_getN_flt(bilinear_##FMT, C) __define_tex_getN(RGB8, (255.f / 127.f)); __define_tex_getN(RGBA8, (255.f / 127.f)); __define_tex_getN(RGB32F, 2.f); __define_tex_getN(RGBA32F, 2.f); __define_tex_getN(RGB16, (65535.f / 32767.f)); __define_tex_getN(RGBA16, (65535.f / 32767.f)); export void *uniform Texture2D_getN_addr( const uniform uint32 type, const uniform bool filter_nearest) { switch (type) { case OSP_TEXTURE_SRGBA: /* fallthrough, sRGB ignored for normals */ __define_tex_getN_case(RGBA8); case OSP_TEXTURE_SRGB: /* fallthrough, sRGB ignored for normals */ __define_tex_getN_case(RGB8); __define_tex_getN_case(RGBA32F); __define_tex_getN_case(RGB32F); __define_tex_getN_case(RGBA16); __define_tex_getN_case(RGB16); default: break; } return (void *uniform) & Texture2D_Normal_neutral; }; SYCL_EXTERNAL vec3f Texture2D_getNormal( const uniform Texture *uniform _self, const DifferentialGeometry &dg) { const uniform Texture2D *uniform self = (const uniform Texture2D *uniform)_self; const uniform bool filter_nearest = self->filter & OSP_TEXTURE_FILTER_NEAREST; switch (self->format) { case OSP_TEXTURE_SRGBA: /* fallthrough, sRGB ignored for normals */ __define_tex_callN_tex_case(RGBA8); case OSP_TEXTURE_SRGB: /* fallthrough, sRGB ignored for normals */ __define_tex_callN_tex_case(RGB8); __define_tex_callN_tex_case(RGBA32F); __define_tex_callN_tex_case(RGB32F); __define_tex_callN_tex_case(RGBA16); __define_tex_callN_tex_case(RGB16); default: break; } return Texture2D_Normal_neutral(self, dg); } #undef __define_tex_get #undef __define_tex_getN #undef __define_tex_getN_flt #undef __define_tex_get_addr #undef __define_tex_case #undef __define_call_tex_case #undef __define_tex_get_case #undef __define_tex_getN_case #undef __foreach_fetcher #undef BYTE2FLOAT #undef SHORT2FLOAT OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/texture/Texture2DShared.h000066400000000000000000000020311456566705700244300ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "TextureShared.h" #include "ospray/OSPEnums.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Texture2D { Texture super; vec2i size; vec2f sizef; // size, as floats; slightly smaller than 'size' to avoid range // checks vec2f halfTexel; // 0.5/size, needed for bilinear filtering and clamp-to-edge void *data; OSPTextureFormat format; OSPTextureFilter filter; vec2ui wrapMode; #ifdef __cplusplus Texture2D() : size(0), sizef(0.f), halfTexel(0.f), data(nullptr), format(OSP_TEXTURE_FORMAT_INVALID), filter(OSP_TEXTURE_FILTER_LINEAR), wrapMode(vec2ui(OSP_TEXTURE_WRAP_REPEAT)) { super.type = TEXTURE_TYPE_2D; } void set(const vec2i &aSize, void *aData, OSPTextureFormat format, OSPTextureFilter flags, vec2ui wrapMode = vec2ui(OSP_TEXTURE_WRAP_REPEAT)); }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/texture/TextureDispatch.ih000066400000000000000000000007531456566705700247550ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/OSPCommon.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct Texture; struct DifferentialGeometry; SYCL_EXTERNAL __noinline vec4f Texture_dispatch_get( const uniform Texture *uniform self, const DifferentialGeometry &dg); SYCL_EXTERNAL __noinline vec3f Texture_dispatch_getNormal( const uniform Texture *const uniform self, const DifferentialGeometry &dg); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/texture/TextureDispatch.ispc000066400000000000000000000022441456566705700253100ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "common/DifferentialGeometry.ih" #include "texture/Texture.ih" #include "texture/Texture2D.ih" #include "texture/TextureVolume.ih" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL __noinline vec4f Texture_dispatch_get( const uniform Texture *uniform self, const DifferentialGeometry &dg) { switch (self->type) { case TEXTURE_TYPE_2D: return Texture2D_get(self, dg); #ifdef OSPRAY_ENABLE_VOLUMES case TEXTURE_TYPE_VOLUME: return TextureVolume_get(self, dg); #endif default: #ifndef OSPRAY_TARGET_SYCL return self->get(self, dg); #else break; #endif } return make_vec4f(0.f); } SYCL_EXTERNAL __noinline vec3f Texture_dispatch_getNormal( const uniform Texture *const uniform self, const DifferentialGeometry &dg) { switch (self->type) { case TEXTURE_TYPE_2D: return Texture2D_getNormal(self, dg); #ifdef OSPRAY_ENABLE_VOLUMES case TEXTURE_TYPE_VOLUME: return TextureVolume_getNormal(self, dg); #endif default: #ifndef OSPRAY_TARGET_SYCL return self->getNormal(self, dg); #else break; #endif } return make_vec3f(0.f); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/texture/TextureParam.ih000066400000000000000000000045511456566705700242560ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Texture.ih" #include "rkcommon/math/AffineSpace.ih" // c++ shared #include "TextureParamShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE inline uniform bool valid(const uniform TextureParam uniform &tex) { return tex.ptr; } inline uniform bool hasAlpha(const uniform TextureParam uniform &tex) { return hasAlpha(tex.ptr); } #define TEXTURE_TRANSFORM(fn) \ if (!tp.transformFlags) \ return fn(tp.ptr, dg); \ \ DifferentialGeometry xfmDg = dg; \ if (tp.transformFlags & TRANSFORM_FLAG_2D) \ xfmDg.st = xfmPoint(tp.xform2f, dg.st); \ if (tp.transformFlags & TRANSFORM_FLAG_3D) \ xfmDg.lP = xfmPoint(tp.xform3f, dg.lP); \ return fn(tp.ptr, xfmDg) inline float get1f(const uniform TextureParam uniform &tp, const varying DifferentialGeometry &dg) { TEXTURE_TRANSFORM(get1f); } inline float get1f(const uniform TextureParam uniform &tp, const varying DifferentialGeometry &dg, const varying float defaultValue) { if (!valid(tp)) return defaultValue; TEXTURE_TRANSFORM(get1f); } inline vec3f get3f(const uniform TextureParam uniform &tp, const varying DifferentialGeometry &dg) { TEXTURE_TRANSFORM(get3f); } inline vec3f get3f(const uniform TextureParam uniform &tp, const varying DifferentialGeometry &dg, const varying vec3f defaultValue) { if (!valid(tp)) return defaultValue; TEXTURE_TRANSFORM(get3f); } inline vec4f get4f(const uniform TextureParam uniform &tp, const varying DifferentialGeometry &dg) { TEXTURE_TRANSFORM(get4f); } inline vec4f get4f(const uniform TextureParam uniform &tp, const varying DifferentialGeometry &dg, const varying vec4f defaultValue) { if (!valid(tp)) return defaultValue; TEXTURE_TRANSFORM(get4f); } inline vec3f getNormal(const uniform TextureParam uniform &tp, const varying DifferentialGeometry &dg) { TEXTURE_TRANSFORM(getNormal); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/texture/TextureParamShared.h000066400000000000000000000011321456566705700252240ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "TextureShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus enum TransformFlags { TRANSFORM_FLAG_NONE = 0x0, TRANSFORM_FLAG_2D = 0x1, TRANSFORM_FLAG_3D = 0x2 }; struct TextureParam { Texture *ptr; TransformFlags transformFlags; affine2f xform2f; affine3f xform3f; #ifdef __cplusplus TextureParam() : ptr(nullptr), transformFlags(TRANSFORM_FLAG_NONE), xform2f(one), xform3f(one) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/texture/TextureShared.h000066400000000000000000000017701456566705700242530ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus #if defined(__cplusplus) && !defined(OSPRAY_TARGET_SYCL) typedef void *Texture_get; typedef void *Texture_getN; #else struct Texture; struct DifferentialGeometry; typedef varying vec4f (*Texture_get)( const Texture *uniform self, const varying DifferentialGeometry &dg); typedef varying vec3f (*Texture_getN)( const Texture *uniform self, const varying DifferentialGeometry &dg); #endif enum TextureType { TEXTURE_TYPE_2D, #ifdef OSPRAY_ENABLE_VOLUMES TEXTURE_TYPE_VOLUME, #endif TEXTURE_TYPE_UNKNOWN, }; struct Texture { TextureType type; Texture_get get; Texture_getN getNormal; bool hasAlpha; // 4 channel texture? #ifdef __cplusplus Texture(bool hasAlpha = false) : type(TEXTURE_TYPE_UNKNOWN), get(nullptr), getNormal(nullptr), hasAlpha(hasAlpha) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/texture/TextureVolume.cpp000066400000000000000000000017711456566705700246500ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #include "TextureVolume.h" #ifndef OSPRAY_TARGET_SYCL #include "texture/TextureVolume_ispc.h" #endif namespace ospray { std::string TextureVolume::toString() const { return "ospray::TextureVolume"; } void TextureVolume::commit() { volume = getParamObject("volume"); if (!volume) throw std::runtime_error(toString() + " must have 'volume' object"); transferFunction = getParamObject("transferFunction"); if (!transferFunction) throw std::runtime_error(toString() + " must have 'transferFunction'"); getSh()->volume = volume->getSh(); getSh()->transferFunction = transferFunction->getSh(); #ifndef OSPRAY_TARGET_SYCL getSh()->super.get = reinterpret_cast(ispc::TextureVolume_get_addr()); getSh()->super.getNormal = reinterpret_cast(ispc::TextureVolume_getN_addr()); #endif } } // namespace ospray #endif RenderKit-ospray-f2a61c2/modules/cpu/texture/TextureVolume.h000066400000000000000000000013311456566705700243050ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #pragma once #include "Texture.h" #include "volume/Volume.h" #include "volume/transferFunction/TransferFunction.h" // ispc shared #include "TextureVolumeShared.h" namespace ospray { // A Texture defined through a volume struct OSPRAY_SDK_INTERFACE TextureVolume : public AddStructShared { TextureVolume(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device) {} virtual std::string toString() const override; virtual void commit() override; private: Ref volume; Ref transferFunction; }; } // namespace ospray #endif RenderKit-ospray-f2a61c2/modules/cpu/texture/TextureVolume.ih000066400000000000000000000007311456566705700244610ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #pragma once #include "Texture.ih" #include "TextureVolumeShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL vec4f TextureVolume_get( const uniform Texture *uniform self, const DifferentialGeometry &dg); SYCL_EXTERNAL vec3f TextureVolume_getNormal( const uniform Texture *uniform self, const DifferentialGeometry &dg); OSPRAY_END_ISPC_NAMESPACE #endif RenderKit-ospray-f2a61c2/modules/cpu/texture/TextureVolume.ispc000066400000000000000000000024431456566705700250210ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #include "Texture.ih" #include "volume/Volume.ih" #include "volume/transferFunction/TransferFunctionDispatch.ih" // c++ shared #include "TextureVolumeShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL vec4f TextureVolume_get( const Texture *uniform _self, const varying DifferentialGeometry &dg) { const TextureVolume *uniform self = (const TextureVolume *uniform)_self; const Volume *uniform volume = self->volume; const uniform box3f bounds = volume->boundingBox; if (box_contains(bounds, dg.lP)) { const float sample = Volume_getSample(volume, dg.lP); const TransferFunction *uniform tfn = self->transferFunction; return TransferFunction_dispatch_get(tfn, sample); } else return make_vec4f(0.f); } SYCL_EXTERNAL vec3f TextureVolume_getNormal( const Texture *uniform, const varying DifferentialGeometry &) { // TODO return make_vec3f(0.f, 0.0f, 1.0f); } /////////////////////////////////////////////////////////////////////////////// export void *uniform TextureVolume_get_addr() { return (void *uniform)TextureVolume_get; } export void *uniform TextureVolume_getN_addr() { return (void *uniform)TextureVolume_getNormal; } OSPRAY_END_ISPC_NAMESPACE #endif RenderKit-ospray-f2a61c2/modules/cpu/texture/TextureVolumeShared.h000066400000000000000000000010571456566705700254410ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #pragma once #include "TextureShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Volume; struct TransferFunction; struct TextureVolume { Texture super; const Volume *volume; const TransferFunction *transferFunction; #ifdef __cplusplus TextureVolume() : super(true), volume(nullptr), transferFunction(nullptr) { super.type = TEXTURE_TYPE_VOLUME; } }; } // namespace ispc #else }; #endif // __cplusplus #endif RenderKit-ospray-f2a61c2/modules/cpu/texture/registration.cpp000066400000000000000000000005641456566705700245310ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Texture2D.h" #ifdef OSPRAY_ENABLE_VOLUMES #include "TextureVolume.h" #endif namespace ospray { void registerAllTextures() { Texture::registerType("texture2d"); #ifdef OSPRAY_ENABLE_VOLUMES Texture::registerType("volume"); #endif } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/texture/registration.h000066400000000000000000000002231456566705700241660ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 namespace ospray { void registerAllTextures(); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/volume/000077500000000000000000000000001456566705700211155ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/volume/Volume.cpp000066400000000000000000000157671456566705700231100ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES // ospray #include "volume/Volume.h" #include "common/Data.h" #ifndef OSPRAY_TARGET_SYCL #include "volume/Volume_ispc.h" #else namespace ispc { void Volume_embreeBounds(const void *_args); } // namespace ispc #endif #include "openvkl/openvkl.h" #include "openvkl/vdb.h" // comment break to prevent clang-format from reordering openvkl includes #include "openvkl/device/openvkl.h" #include namespace ospray { // Volume definitions //////////////////////////////////////////////////////// Volume::Volume(api::ISPCDevice &device, const std::string &type) : AddStructShared(device.getIspcrtContext(), device), vklType(type), vklFeatureFlags(VKL_FEATURE_FLAGS_NONE) { // check VKL has default config for VDB if (type == "vdb" && (vklVdbLevelNumVoxels(0) != 262144 || vklVdbLevelNumVoxels(1) != 32768 || vklVdbLevelNumVoxels(2) != 4096 || vklVdbLevelNumVoxels(3) != 512 || vklVdbLevelNumVoxels(4) != 0)) throw std::runtime_error(toString() + " Open VKL has non-default configuration for VDB volumes."); managedObjectType = OSP_VOLUME; } Volume::~Volume() { if (vklSampler) vklRelease(vklSampler); if (vklVolume) vklRelease(vklVolume); if (embreeGeometry) rtcReleaseGeometry(embreeGeometry); } std::string Volume::toString() const { return "ospray::Volume"; } void Volume::commit() { VKLDevice vklDevice = getISPCDevice().getVklDevice(); if (!vklDevice) { throw std::runtime_error("invalid Open VKL device"); } RTCDevice embreeDevice = getISPCDevice().getEmbreeDevice(); if (!embreeDevice) { throw std::runtime_error("invalid Embree device"); } if (vklSampler) vklRelease(vklSampler); if (vklVolume) vklRelease(vklVolume); vklVolume = vklNewVolume(vklDevice, vklType.c_str()); if (!vklVolume) throw std::runtime_error("unsupported volume type '" + vklType + "'"); if (!embreeGeometry) { embreeGeometry = rtcNewGeometry(embreeDevice, RTC_GEOMETRY_TYPE_USER); } handleParams(); vklCommit(vklVolume); (vkl_box3f &)bounds = vklGetBoundingBox(vklVolume); vklSampler = vklNewSampler(vklVolume); vklCommit(vklSampler); vklFeatureFlags = vklGetFeatureFlags(vklSampler); // Setup Embree user-defined geometry rtcSetGeometryUserData(embreeGeometry, getSh()); rtcSetGeometryUserPrimitiveCount(embreeGeometry, 1); rtcSetGeometryBoundsFunction( embreeGeometry, (RTCBoundsFunction)&ispc::Volume_embreeBounds, getSh()); rtcCommitGeometry(embreeGeometry); // Initialize shared structure getSh()->vklVolume = vklVolume; getSh()->vklSampler = vklSampler; getSh()->boundingBox = bounds; } void Volume::checkDataStride(const Data *data) const { if (data->stride().y != int64_t(data->numItems.x) * data->stride().x || data->stride().z != int64_t(data->numItems.y) * data->stride().y) { throw std::runtime_error( toString() + " Open VKL only supports 1D strides between elements"); } } void Volume::handleParams() { // pass all supported parameters through to VKL volume object std::for_each(params_begin(), params_end(), [&](std::shared_ptr &p) { auto ¶m = *p; param.query = true; if (param.data.is()) { vklSetBool(vklVolume, param.name.c_str(), param.data.get()); } else if (param.data.is()) { vklSetFloat(vklVolume, param.name.c_str(), param.data.get()); } else if (param.data.is()) { vklSetInt(vklVolume, param.name.c_str(), param.data.get()); } else if (param.data.is()) { vklSetInt(vklVolume, param.name.c_str(), param.data.get()); } else if (param.data.is()) { vklSetVec3f(vklVolume, param.name.c_str(), param.data.get().x, param.data.get().y, param.data.get().z); } else if (param.data.is()) { vklSetVoidPtr(vklVolume, param.name.c_str(), param.data.get()); } else if (param.data.is()) { vklSetString( vklVolume, param.name.c_str(), param.data.get()); } else if (param.data.is()) { vklSetVec3i(vklVolume, param.name.c_str(), param.data.get().x, param.data.get().y, param.data.get().z); } else if (param.data.is()) { VKLDevice vklDevice = getISPCDevice().getVklDevice(); Data *data = (Data *)param.data.get(); if (data->type == OSP_DATA) { auto &dataD = data->as(); std::vector vklBlockData; vklBlockData.reserve(data->size()); for (auto &&data : dataD) { checkDataStride(data); VKLData vklData = vklNewData(vklDevice, data->size(), (VKLDataType)data->type, data->data(), VKL_DATA_SHARED_BUFFER, data->stride().x); vklBlockData.push_back(vklData); } VKLData vklData = vklNewData( vklDevice, vklBlockData.size(), VKL_DATA, vklBlockData.data()); vklSetData(vklVolume, param.name.c_str(), vklData); vklRelease(vklData); for (VKLData vd : vklBlockData) vklRelease(vd); if (vklType == "vdb" && param.name == "node.data") { // deduce format std::vector format; format.reserve(data->size()); for (auto &&data : dataD) { bool isTile = data->size() == 1; if (!isTile) { if (data->numItems.x != data->numItems.y || data->numItems.x != data->numItems.z) throw std::runtime_error( toString() + " VDB leaf node data must have size n^3."); } format.push_back(isTile ? VKL_FORMAT_TILE : VKL_FORMAT_DENSE_ZYX); } VKLData vklData = vklNewData(vklDevice, format.size(), VKL_UINT, format.data()); vklSetData(vklVolume, "node.format", vklData); vklRelease(vklData); } } else { checkDataStride(data); VKLData vklData = vklNewData(vklDevice, data->size(), (VKLDataType)data->type, data->data(), VKL_DATA_SHARED_BUFFER, data->stride().x); std::string name(param.name); if (name == "data") { // structured volumes vec3ul &dim = data->numItems; vklSetVec3i(vklVolume, "dimensions", dim.x, dim.y, dim.z); } if (name == "nodesPackedDense" || name == "nodesPackedTile") { // packed VDB volumes: wrap attribute VKLData vklDataWrapper = vklNewData(vklDevice, 1, VKL_DATA, &vklData); vklRelease(vklData); vklData = vklDataWrapper; } vklSetData(vklVolume, name.c_str(), vklData); vklRelease(vklData); } } else { param.query = false; } }); } OSPTYPEFOR_DEFINITION(Volume *); } // namespace ospray #endif RenderKit-ospray-f2a61c2/modules/cpu/volume/Volume.h000066400000000000000000000025201456566705700225340ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #pragma once #include "ISPCDeviceObject.h" #include "common/FeatureFlagsEnum.h" #include "common/StructShared.h" // embree #include "common/Embree.h" // openvkl #include "openvkl/openvkl.h" // comment break to prevent clang-format from reordering openvkl includes #include "openvkl/device/openvkl.h" // ispc shared #include "VolumeShared.h" namespace ospray { struct OSPRAY_SDK_INTERFACE Volume : public AddStructShared { Volume(api::ISPCDevice &device, const std::string &vklType); ~Volume() override; std::string toString() const override; void commit() override; FeatureFlags getFeatureFlags() const; private: void checkDataStride(const Data *) const; void handleParams(); // Friends // friend struct Isosurfaces; friend struct VolumetricModel; // Data // RTCGeometry embreeGeometry{nullptr}; VKLVolume vklVolume = VKLVolume(); VKLSampler vklSampler = VKLSampler(); box3f bounds{empty}; std::string vklType; VKLFeatureFlags vklFeatureFlags = VKL_FEATURE_FLAGS_NONE; }; OSPTYPEFOR_SPECIALIZATION(Volume *, OSP_VOLUME); inline FeatureFlags Volume::getFeatureFlags() const { FeatureFlags ff; ff.volume = vklFeatureFlags; return ff; } } // namespace ospray #endif RenderKit-ospray-f2a61c2/modules/cpu/volume/Volume.ih000066400000000000000000000030521456566705700227060ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #pragma once #include "common/Embree.h" #ifdef ISPC #include "openvkl/openvkl.isph" // comment break to prevent clang-format from reordering openvkl includes #include "openvkl/device/openvkl.isph" #else #include "openvkl/openvkl.h" // comment break to prevent clang-format from reordering openvkl includes #include "openvkl/device/openvkl.h" #endif #include "common/FeatureFlags.ih" #include "rkcommon/math/box.ih" // c++ shared #include "VolumeShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE // Helper functions /////////////////////////////////////////////////////////// inline float Volume_getSample(const Volume *uniform volume, const vec3f &P) { return vklComputeSampleV(&volume->vklSampler, &((const vkl_vec3f &)P)); } inline vec3f Volume_getGradient(const Volume *uniform volume, const vec3f &P, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlags ff = getFeatureFlags(ffh); vkl_vec3f result = vklComputeGradientV(&volume->vklSampler, &((const vkl_vec3f &)P) #ifdef OSPRAY_TARGET_SYCL , 0, 0.f, ff.volume #endif ); // TODO: remove it once VKL no longer returns sporadic NaNs if (isnan(result.x)) result.x = 1.f; if (isnan(result.y)) result.y = 1.f; if (isnan(result.z)) result.z = 1.f; return *((varying vec3f *)&result); } RTC_SYCL_INDIRECTLY_CALLABLE unmasked void Volume_intersect_kernel( RTCIntersectFunctionNArguments *uniform args); OSPRAY_END_ISPC_NAMESPACE #endif RenderKit-ospray-f2a61c2/modules/cpu/volume/Volume.ispc000066400000000000000000000047001456566705700232450ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #include "common/Intersect.ih" #include "common/Ray.ih" #include "common/VolumeIntervals.ih" #include "volume/Volume.ih" OSPRAY_BEGIN_ISPC_NAMESPACE export void Volume_embreeBounds(const void *uniform _args) { const RTCBoundsFunctionArguments *uniform args = (const RTCBoundsFunctionArguments *uniform)_args; Volume *uniform self = (Volume * uniform) args->geometryUserPtr; box3fa *uniform out = (box3fa * uniform) args->bounds_o; *out = make_box3fa(self->boundingBox); } RTC_SYCL_INDIRECTLY_CALLABLE unmasked void Volume_intersect_kernel( RTCIntersectFunctionNArguments *uniform args) { // make sure to set the mask if (!args->valid[programIndex]) return; Volume *uniform self = (Volume * uniform) args->geometryUserPtr; varying Ray *uniform ray = (varying Ray * uniform) args->rayhit; box3f *uniform box = &self->boundingBox; const Intersections isect = intersectBox(ray->org, ray->dir, *box); const float t_min = max(ray->t0, isect.entry.t); const float t_max = min(ray->t, isect.exit.t); if (t_min < t_max) { ray->instID = args->context->instID[0]; ray->geomID = args->geomID; ray->primID = 0; RayQueryContextVolume *uniform ctx = (RayQueryContextVolume * uniform) args->context; varying VolumeIntervals *uniform vIntervals = (varying VolumeIntervals * uniform) ctx->intervals; #ifndef OSPRAY_TARGET_SYCL // Grow TLS pool if needed, note that we cannot grow it on the GPU b/c no // dymanic memory. With SYCL we just take the first hit found uniform unsigned int numNeeded = reduce_max(vIntervals->numVolumeIntervals) + 1; if (numNeeded > vIntervals->numAllocated) { vIntervals->intervals = (varying VolumeInterval * uniform) reallocTLS( vIntervals->intervals, numNeeded * sizeof(varying VolumeInterval)); vIntervals->numAllocated = numNeeded; } varying VolumeInterval *varying vInterval = (varying VolumeInterval * varying)(vIntervals->intervals + vIntervals->numVolumeIntervals); #else varying VolumeInterval *uniform vInterval = vIntervals->intervals; #endif vInterval->primID = 0; vInterval->geomID = args->geomID; vInterval->instID = args->context->instID[0]; vInterval->interval.lower = t_min; vInterval->interval.upper = t_max; vIntervals->numVolumeIntervals++; } } OSPRAY_END_ISPC_NAMESPACE #endif RenderKit-ospray-f2a61c2/modules/cpu/volume/VolumeShared.h000066400000000000000000000015101456566705700236610ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus // Variables and methods common to all subtypes of the Volume // class, an abstraction for the concrete object which performs the // volume sampling (this struct must be the first field of a struct // representing a "derived" class to allow casting to that class). struct Volume { VKLVolume vklVolume; VKLSampler vklSampler; // Bounding box for the volume in world coordinates. // This is an internal derived parameter and not meant to be // redefined externally. box3f boundingBox; #ifdef __cplusplus Volume() : vklVolume(VKLVolume()), vklSampler(VKLSampler()), boundingBox(0.f) {} }; } // namespace ispc #else }; #endif // __cplusplus #endif RenderKit-ospray-f2a61c2/modules/cpu/volume/VolumetricModel.cpp000066400000000000000000000056161456566705700247430ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #include "openvkl/openvkl.h" // ospray #include "VolumetricModel.h" namespace ospray { VolumetricModel::VolumetricModel(api::ISPCDevice &device, Volume *_volume) : AddStructShared(device.getIspcrtContext(), device), volumeAPI(_volume) { managedObjectType = OSP_VOLUMETRIC_MODEL; } VolumetricModel::~VolumetricModel() { if (vklIntervalContext) vklRelease(vklIntervalContext); } std::string VolumetricModel::toString() const { return "ospray::VolumetricModel"; } void VolumetricModel::commit() { volume = getParamObject("volume", volumeAPI.ptr); if (!volume) throw std::runtime_error(toString() + " received NULL 'volume'"); transferFunction = getParamObject("transferFunction"); if (!transferFunction) throw std::runtime_error(toString() + " must have 'transferFunction'"); // create value selector using transfer function and pass to volume if (volume->vklVolume) { if (vklIntervalContext) { vklRelease(vklIntervalContext); } vklIntervalContext = vklNewIntervalIteratorContext(volume->vklSampler); std::vector valueRanges = transferFunction->getPositiveOpacityValueRanges(); if (valueRanges.empty()) { // volume made completely transparent and could be removed, which is // awkward here // set an "empty" interesting value range instead, which will lead to a // quick out during volume iteration valueRanges.push_back(range1f(neg_inf, neg_inf)); } VKLData valueRangeData = vklNewData(getISPCDevice().getVklDevice(), valueRanges.size(), VKL_BOX1F, valueRanges.data()); vklSetData(vklIntervalContext, "valueRanges", valueRangeData); vklRelease(valueRangeData); vklCommit(vklIntervalContext); // Pass interval context to ISPC getSh()->vklIntervalContext = vklIntervalContext; } // Finish getting/setting other appearance information volumeBounds = volume->bounds; // Initialize shared structure getSh()->volume = getVolume()->getSh(); getSh()->transferFunction = transferFunction->getSh(); getSh()->boundingBox = volumeBounds; getSh()->densityScale = getParam("densityScale", 1.f); getSh()->anisotropy = getParam("anisotropy", 0.f); getSh()->gradientShadingScale = getParam("gradientShadingScale", 0.f); getSh()->userID = getParam("id", RTC_INVALID_GEOMETRY_ID); featureFlagsOther = FFO_VOLUME_IN_SCENE; if (getSh()->gradientShadingScale > 0.f) featureFlagsOther |= FFO_VOLUME_SCIVIS_SHADING; } RTCGeometry VolumetricModel::embreeGeometryHandle() const { return volume->embreeGeometry; } box3f VolumetricModel::bounds() const { return volumeBounds; } Ref VolumetricModel::getVolume() const { return volume; } OSPTYPEFOR_DEFINITION(VolumetricModel *); } // namespace ospray #endif RenderKit-ospray-f2a61c2/modules/cpu/volume/VolumetricModel.h000066400000000000000000000025601456566705700244030ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #pragma once #include "Volume.h" #include "common/FeatureFlagsEnum.h" #include "openvkl/openvkl.h" // comment break to prevent clang-format from reordering openvkl includes #include "openvkl/device/openvkl.h" #include "transferFunction/TransferFunction.h" // ispc shared #include "volume/VolumetricModelShared.h" namespace ospray { struct OSPRAY_SDK_INTERFACE VolumetricModel : public AddStructShared { VolumetricModel(api::ISPCDevice &device, Volume *geometry); ~VolumetricModel() override; std::string toString() const override; void commit() override; RTCGeometry embreeGeometryHandle() const; box3f bounds() const; Ref getVolume() const; FeatureFlags getFeatureFlags() const; private: box3f volumeBounds; Ref volume; Ref transferFunction; const Ref volumeAPI; VKLIntervalIteratorContext vklIntervalContext = VKLIntervalIteratorContext(); FeatureFlagsOther featureFlagsOther{FFO_VOLUME_IN_SCENE}; }; OSPTYPEFOR_SPECIALIZATION(VolumetricModel *, OSP_VOLUMETRIC_MODEL); inline FeatureFlags VolumetricModel::getFeatureFlags() const { FeatureFlags ff = volume->getFeatureFlags(); ff.other |= featureFlagsOther; return ff; } } // namespace ospray #endif RenderKit-ospray-f2a61c2/modules/cpu/volume/VolumetricModel.ih000066400000000000000000000015641456566705700245570ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #pragma once #include "../common/DifferentialGeometry.ih" #include "../common/Ray.ih" #include "Volume.ih" #include "transferFunction/TransferFunctionShared.h" // c++ shared #include "VolumetricModelShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE inline void VolumetricModel_postIntersect(const VolumetricModel *uniform self, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64) { dg.Ng = make_vec3f(0.f); dg.Ns = make_vec3f(0.f); dg.dPds = make_vec3f(0.f); dg.dPdt = make_vec3f(0.f); dg.st = make_vec2f(0); dg.color = make_vec4f(0.f); dg.primID = 0; dg.objID = (self->userID == RTC_INVALID_GEOMETRY_ID) ? ray.geomID : self->userID; dg.areaPDF = 0.f; dg.epsilon = 0.f; dg.material = NULL; } OSPRAY_END_ISPC_NAMESPACE #endif RenderKit-ospray-f2a61c2/modules/cpu/volume/VolumetricModelShared.h000066400000000000000000000017331456566705700255330ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifdef OSPRAY_ENABLE_VOLUMES #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct Volume; struct TransferFunction; struct VolumetricModel { Volume *volume; TransferFunction *transferFunction; VKLIntervalIteratorContext vklIntervalContext; box3f boundingBox; // Volume parameters understood by the pathtracer float densityScale; float anisotropy; // the anisotropy of the volume's phase function // (Heyney-Greenstein) float gradientShadingScale; unsigned int userID; #ifdef __cplusplus VolumetricModel() : volume(nullptr), transferFunction(nullptr), vklIntervalContext(VKLIntervalIteratorContext()), boundingBox(0.f), densityScale(1.f), anisotropy(0.f), gradientShadingScale(0.f), userID(RTC_INVALID_GEOMETRY_ID) {} }; } // namespace ispc #else }; #endif // __cplusplus #endif RenderKit-ospray-f2a61c2/modules/cpu/volume/transferFunction/000077500000000000000000000000001456566705700244475ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/cpu/volume/transferFunction/LinearTransferFunction.cpp000066400000000000000000000113201456566705700315750ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "LinearTransferFunction.h" #ifndef OSPRAY_TARGET_SYCL #include "volume/transferFunction/LinearTransferFunction_ispc.h" #else namespace ispc { void *LinearTransferFunction_get_addr(); void *LinearTransferFunction_getMaxOpacity_addr(); } // namespace ispc #endif namespace ospray { LinearTransferFunction::LinearTransferFunction(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device) { getSh()->super.valueRange = range1f(0.0f, 1.0f); } void LinearTransferFunction::commit() { TransferFunction::commit(); colorValues = getParamDataT("color", true); opacityValues = getParamDataT("opacity", true); getSh()->color = *ispc(colorValues); getSh()->opacity = *ispc(opacityValues); precomputeMaxOpacityRanges(); } std::string LinearTransferFunction::toString() const { return "ospray::LinearTransferFunction"; } std::vector LinearTransferFunction::getPositiveOpacityIndexRanges() const { std::vector intervals; range1i interval; bool rangeActive = false; const DataT &opacities = *opacityValues; for (int i = 0; i < int(opacities.size()); i++) { if (opacities[i] > 0.f && !rangeActive) { rangeActive = true; interval.lower = i; } else if (opacities[i] <= 0.f && rangeActive) { rangeActive = false; interval.upper = i; intervals.push_back(interval); } } // special case for final value if (opacities[opacities.size() - 1] > 0.f) { if (rangeActive) { rangeActive = false; interval.upper = opacities.size(); intervals.push_back(interval); } else { throw std::runtime_error("getPositiveOpacityIndexRanges() error"); } } return intervals; } std::vector LinearTransferFunction::getPositiveOpacityValueRanges() const { std::vector valueRanges; // determine index ranges for positive opacities std::vector indexRanges = getPositiveOpacityIndexRanges(); const DataT &opacities = *opacityValues; // convert index ranges to value ranges // note that a positive opacity value has a span of +/-1 due to the linear // interpolation, and returned index ranges are [min, max) intervals for (int i = 0; i < int(indexRanges.size()); i++) { int minValueIndex = indexRanges[i].lower - 1; int maxValueIndex = indexRanges[i].upper; range1f range(neg_inf, inf); if (minValueIndex >= 0) { range.lower = valueRange.lower + minValueIndex * valueRange.size() / (opacities.size() - 1.f); } if (maxValueIndex < int(opacities.size())) { range.upper = valueRange.lower + maxValueIndex * valueRange.size() / (opacities.size() - 1.f); } valueRanges.push_back(range); } return valueRanges; } void LinearTransferFunction::precomputeMaxOpacityRanges() { const DataT &opacities = *opacityValues; const int maxOpacityDim = opacities.size() - 1; const int maxPrecomputedDim = PRECOMPUTED_OPACITY_SUBRANGE_COUNT - 1; // compute the diagonal for (int i = 0; i < PRECOMPUTED_OPACITY_SUBRANGE_COUNT; i++) { // figure out the range of array indices we are going to compare; this is a // conservative range of feasible indices that may be used to lookup // opacities for any data value within the value range corresponding to [i, // i]. const int checkRangeLow = floor(maxOpacityDim * (float)i / maxPrecomputedDim); const int checkRangeHigh = ceil(maxOpacityDim * (float)i / maxPrecomputedDim); float maxOpacity = opacities[checkRangeLow]; for (int opacityIDX = checkRangeLow; opacityIDX <= checkRangeHigh; opacityIDX++) maxOpacity = std::max(maxOpacity, opacities[opacityIDX]); getSh()->maxOpacityInRange[i][i] = maxOpacity; } // fill out each column from the diagonal up for (int i = 0; i < PRECOMPUTED_OPACITY_SUBRANGE_COUNT; i++) { for (int j = i + 1; j < PRECOMPUTED_OPACITY_SUBRANGE_COUNT; j++) { // figure out the range of array indices we are going to compare; this is // a conservative range of feasible indices that may be used to lookup // opacities for any data value within the value range corresponding to // [i, j]. const int checkRangeLow = floor(maxOpacityDim * (float)i / maxPrecomputedDim); const int checkRangeHigh = ceil(maxOpacityDim * (float)j / maxPrecomputedDim); float maxOpacity = getSh()->maxOpacityInRange[i][i]; for (int opacityIDX = checkRangeLow; opacityIDX <= checkRangeHigh; opacityIDX++) maxOpacity = std::max(maxOpacity, opacities[opacityIDX]); getSh()->maxOpacityInRange[i][j] = maxOpacity; } } } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/volume/transferFunction/LinearTransferFunction.h000066400000000000000000000015231456566705700312460ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray #include "TransferFunction.h" #include "common/Data.h" // ispc shared #include "LinearTransferFunctionShared.h" namespace ospray { // piecewise linear transfer function struct OSPRAY_SDK_INTERFACE LinearTransferFunction : public AddStructShared { LinearTransferFunction(api::ISPCDevice &device); virtual void commit() override; virtual std::string toString() const override; virtual std::vector getPositiveOpacityValueRanges() const override; virtual std::vector getPositiveOpacityIndexRanges() const override; private: Ref> colorValues; Ref> opacityValues; void precomputeMaxOpacityRanges(); }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/volume/transferFunction/LinearTransferFunction.ih000066400000000000000000000006711456566705700314220ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/box.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct TransferFunction; SYCL_EXTERNAL vec4f LinearTransferFunction_get( const TransferFunction *uniform _self, float value); SYCL_EXTERNAL float LinearTransferFunction_getMaxOpacity( const TransferFunction *uniform _self, const range1f &valueRange); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/volume/transferFunction/LinearTransferFunction.ispc000066400000000000000000000037461456566705700317660ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "LinearTransferFunction.ih" #include "common/Data.ih" // c++ shared #include "LinearTransferFunctionShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL vec4f LinearTransferFunction_get( const TransferFunction *uniform _self, float value) { const LinearTransferFunction *uniform self = (const LinearTransferFunction *uniform)_self; // remap to [0.0, 1.0] value = (value - self->super.valueRange.lower) * rcp(box_size(self->super.valueRange)); // clamp to [0.0, 1.0) const uniform float nextBefore1 = 0x1.fffffep-1f; value = clamp(value, 0.0f, nextBefore1); const uniform int maxIdxC = self->color.numItems - 1; const float idxCf = value * maxIdxC; const float fracC = frac(idxCf); const int idxC = idxCf; const vec3f col = lerp(fracC, get_vec3f(self->color, idxC), get_vec3f(self->color, min(maxIdxC, idxC + 1))); const uniform int maxIdxO = self->opacity.numItems - 1; const float idxOf = value * maxIdxO; const float fracO = frac(idxOf); const int idxO = idxOf; const float opacity = lerp(fracO, get_float(self->opacity, idxO), get_float(self->opacity, min(maxIdxO, idxO + 1))); return make_vec4f(col, opacity); } SYCL_EXTERNAL float LinearTransferFunction_getMaxOpacity( const TransferFunction *uniform _self, const range1f &valueRange) { uniform LinearTransferFunction *uniform self = (uniform LinearTransferFunction * uniform) _self; const uniform int maxDim = PRECOMPUTED_OPACITY_SUBRANGE_COUNT - 1; const uniform float denom = self->super.valueRange.upper - self->super.valueRange.lower; const varying int i = floor(clamp((valueRange.lower - self->super.valueRange.lower) / denom) * maxDim); const varying int j = ceil(clamp((valueRange.upper - self->super.valueRange.lower) / denom) * maxDim); return self->maxOpacityInRange[min(i, maxDim)][min(j, maxDim)]; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/volume/transferFunction/LinearTransferFunctionShared.h000066400000000000000000000012431456566705700323740ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "TransferFunctionShared.h" #define PRECOMPUTED_OPACITY_SUBRANGE_COUNT 32 #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct LinearTransferFunction { TransferFunction super; Data1D color; Data1D opacity; // precomputed maximum opacity values per range float maxOpacityInRange[PRECOMPUTED_OPACITY_SUBRANGE_COUNT] [PRECOMPUTED_OPACITY_SUBRANGE_COUNT]; #ifdef __cplusplus LinearTransferFunction() { super.type = TRANSFER_FUNCTION_TYPE_LINEAR; } #endif }; #ifdef __cplusplus } // namespace ispc #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/volume/transferFunction/TransferFunction.cpp000066400000000000000000000012451456566705700304470ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "TransferFunction.h" namespace ospray { // TransferFunction definitions /////////////////////////////////////////////// TransferFunction::TransferFunction(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device) { managedObjectType = OSP_TRANSFER_FUNCTION; } void TransferFunction::commit() { valueRange = getParam("value", range1f(0.0f, 1.0f)); getSh()->valueRange = valueRange; } std::string TransferFunction::toString() const { return "ospray::TransferFunction"; } OSPTYPEFOR_DEFINITION(TransferFunction *); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/volume/transferFunction/TransferFunction.h000066400000000000000000000015061456566705700301140ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ISPCDeviceObject.h" #include "common/ObjectFactory.h" #include "common/StructShared.h" // ispc shared #include "TransferFunctionShared.h" namespace ospray { struct OSPRAY_SDK_INTERFACE TransferFunction : public AddStructShared, public ObjectFactory { TransferFunction(api::ISPCDevice &device); virtual void commit() override; virtual std::string toString() const override; range1f valueRange; virtual std::vector getPositiveOpacityValueRanges() const = 0; virtual std::vector getPositiveOpacityIndexRanges() const = 0; }; OSPTYPEFOR_SPECIALIZATION(TransferFunction *, OSP_TRANSFER_FUNCTION); } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/volume/transferFunction/TransferFunctionDispatch.ih000066400000000000000000000006751456566705700317530ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/math/box.ih" OSPRAY_BEGIN_ISPC_NAMESPACE struct TransferFunction; SYCL_EXTERNAL vec4f TransferFunction_dispatch_get( const TransferFunction *uniform self, float value); SYCL_EXTERNAL float TransferFunction_dispatch_getMaxOpacity( const TransferFunction *uniform self, const range1f &valueRange); OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/volume/transferFunction/TransferFunctionDispatch.ispc000066400000000000000000000014471456566705700323070ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "LinearTransferFunction.ih" #include "TransferFunctionDispatch.ih" #include "TransferFunctionShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE SYCL_EXTERNAL vec4f TransferFunction_dispatch_get( const TransferFunction *uniform self, float value) { switch (self->type) { case TRANSFER_FUNCTION_TYPE_LINEAR: return LinearTransferFunction_get(self, value); default: return make_vec4f(0.f); } } SYCL_EXTERNAL float TransferFunction_dispatch_getMaxOpacity( const TransferFunction *uniform self, const range1f &valueRange) { switch (self->type) { case TRANSFER_FUNCTION_TYPE_LINEAR: return LinearTransferFunction_getMaxOpacity(self, valueRange); default: return 0.f; } } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/cpu/volume/transferFunction/TransferFunctionShared.h000066400000000000000000000012231456566705700312370ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef __cplusplus namespace ispc { #endif // __cplusplus // We only have one transfer function type, but we still have the type enum and // "dispatch" function so that we can easily extend it with more in the future enum TransferFunctionType { TRANSFER_FUNCTION_TYPE_LINEAR = 0, TRANSFER_FUNCTION_TYPE_UNKNOWN = 1, }; struct TransferFunction { TransferFunctionType type; range1f valueRange; #ifdef __cplusplus TransferFunction() : type(TRANSFER_FUNCTION_TYPE_UNKNOWN), valueRange(0.f, 1.f) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/cpu/volume/transferFunction/registration.cpp000066400000000000000000000004211456566705700276620ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "LinearTransferFunction.h" namespace ospray { void registerAllTransferFunctions() { TransferFunction::registerType("piecewiseLinear"); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/cpu/volume/transferFunction/registration.h000066400000000000000000000002341456566705700273310ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 namespace ospray { void registerAllTransferFunctions(); } // namespace ospray RenderKit-ospray-f2a61c2/modules/denoiser/000077500000000000000000000000001456566705700206275ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/denoiser/CMakeLists.txt000066400000000000000000000012521456566705700233670ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 cmake_dependent_option( OSPRAY_MODULE_DENOISER "Build the Denoiser FrameOp module for denoising (requires OIDN)" OFF OSPRAY_MODULE_CPU OFF ) if (NOT OSPRAY_MODULE_DENOISER) return() endif() include(GenerateExportHeader) add_library(ospray_module_denoiser SHARED ${OSPRAY_RESOURCE} ModuleInit.cpp DenoiseFrameOp.cpp) generate_export_header(ospray_module_denoiser) target_link_libraries(ospray_module_denoiser PRIVATE OpenImageDenoise ospray ) target_include_directories(ospray_module_denoiser PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ) ospray_install_library(ospray_module_denoiser lib) RenderKit-ospray-f2a61c2/modules/denoiser/DenoiseFrameOp.cpp000066400000000000000000000137231456566705700242010ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "DenoiseFrameOp.h" #include "api/Device.h" #include "fb/FrameBufferView.h" namespace ospray { void checkError(oidn::DeviceRef oidnDevice) { const char *errorMessage = nullptr; auto error = oidnDevice.getError(errorMessage); if (error != oidn::Error::None && error != oidn::Error::Cancelled) { throw std::runtime_error( "Error running OIDN: " + std::string(errorMessage)); } } struct OSPRAY_MODULE_DENOISER_EXPORT LiveDenoiseFrameOp : public LiveFrameOpInterface { LiveDenoiseFrameOp(FrameBufferView &fbView, oidn::DeviceRef oidnDevice) : fbView(fbView), oidnDevice(oidnDevice), filter(oidnDevice.newFilter("RT")) { filter.set("hdr", true); } protected: FrameBufferView fbView; oidn::DeviceRef oidnDevice; oidn::FilterRef filter; }; struct OSPRAY_MODULE_DENOISER_EXPORT LiveDenoiseFrameOpShared : public LiveDenoiseFrameOp { LiveDenoiseFrameOpShared(FrameBufferView &fbView, oidn::DeviceRef oidnDevice) : LiveDenoiseFrameOp(fbView, oidnDevice), buffer(oidnDevice.newBuffer(fbView.colorBufferOutput, fbView.viewDims.long_product() * sizeof(vec4f))) { // Set up filter filter.setImage("color", buffer, oidn::Format::Float3, fbView.viewDims.x, fbView.viewDims.y, 0, 4 * sizeof(float)); filter.setImage("output", buffer, oidn::Format::Float3, fbView.viewDims.x, fbView.viewDims.y, 0, 4 * sizeof(float)); if (fbView.normalBuffer) filter.setImage("normal", const_cast(fbView.normalBuffer), oidn::Format::Float3, fbView.viewDims.x, fbView.viewDims.y); if (fbView.albedoBuffer) filter.setImage("albedo", const_cast(fbView.albedoBuffer), oidn::Format::Float3, fbView.viewDims.x, fbView.viewDims.y); filter.commit(); } void process(void *waitEvent) override { // TODO: Remove oidn::Buffer and copying after switching to OIDN 2.2 // OIDN cannot denoise alpha in a single pass so we copy input buffer to // output and then do in-place denoising to preserve alpha if (waitEvent) { buffer.writeAsync(0, fbView.viewDims.long_product() * sizeof(vec4f), fbView.colorBufferInput); // Using SYCL call without SYCL, that's supported in C99 API only oidnExecuteSYCLFilterAsync( filter.getHandle(), nullptr, 0, (sycl::event *)waitEvent); } else { buffer.write(0, fbView.viewDims.long_product() * sizeof(vec4f), fbView.colorBufferInput); filter.execute(); } checkError(oidnDevice); } private: oidn::BufferRef buffer; }; struct OSPRAY_MODULE_DENOISER_EXPORT LiveDenoiseFrameOpCopy : public LiveDenoiseFrameOp { LiveDenoiseFrameOpCopy(FrameBufferView &fbView, oidn::DeviceRef oidnDevice) : LiveDenoiseFrameOp(fbView, oidnDevice) { byteFloatBufferSize = sizeof(float) * fbView.fbDims.product(); size_t sz = 4 * byteFloatBufferSize; if (fbView.normalBuffer) { byteNormalOffset = sz; sz += 3 * byteFloatBufferSize; } if (fbView.albedoBuffer) { byteAlbedoOffset = sz; sz += 3 * byteFloatBufferSize; } buffer = oidnDevice.newBuffer(sz, oidn::Storage::Device); filter.setImage("color", buffer, oidn::Format::Float3, fbView.fbDims.x, fbView.fbDims.y, 0, sizeof(float) * 4); filter.setImage("output", buffer, oidn::Format::Float3, fbView.fbDims.x, fbView.fbDims.y, 0, sizeof(float) * 4, 0); if (fbView.normalBuffer) filter.setImage("normal", buffer, oidn::Format::Float3, fbView.fbDims.x, fbView.fbDims.y, byteNormalOffset); if (fbView.albedoBuffer) filter.setImage("albedo", buffer, oidn::Format::Float3, fbView.fbDims.x, fbView.fbDims.y, byteAlbedoOffset); filter.commit(); } void process(void * /*waitEvent*/) override { // TODO if (!fbView.originalFB->getSh()->numPixelsRendered) // return; // skip denoising when no new pixels XXX only works on CPU // Copy data to input buffers buffer.writeAsync(0, 4 * byteFloatBufferSize, fbView.colorBufferInput); if (fbView.normalBuffer) buffer.writeAsync( byteNormalOffset, 3 * byteFloatBufferSize, fbView.normalBuffer); if (fbView.albedoBuffer) buffer.writeAsync( byteAlbedoOffset, 3 * byteFloatBufferSize, fbView.albedoBuffer); // Execute denoising kernel filter.executeAsync(); // Copy denoised data to output buffer buffer.readAsync(0, 4 * byteFloatBufferSize, fbView.colorBufferOutput); oidnDevice.sync(); checkError(oidnDevice); } private: oidn::BufferRef buffer; size_t byteFloatBufferSize; size_t byteNormalOffset; size_t byteAlbedoOffset; }; DenoiseFrameOp::DenoiseFrameOp(api::Device &device) { // Get appropriate SYCL command queue for post-processing from device sycl::queue *syclQueuePtr = (sycl::queue *)device.getPostProcessingCommandQueuePtr(); if (syclQueuePtr) { // Using SYCL call without SYCL, that's supported in C99 API only oidnDevice = oidnNewSYCLDevice(syclQueuePtr, 1); } else { oidnDevice = oidn::newDevice(); } checkError(oidnDevice); if (device.debugMode) oidnDevice.set("verbose", 2); oidnDevice.commit(); sharedMem = syclQueuePtr || oidnDevice.get("systemMemorySupported"); } std::unique_ptr DenoiseFrameOp::attach( FrameBufferView &fbView) { if (sharedMem) return rkcommon::make_unique(fbView, oidnDevice); return rkcommon::make_unique(fbView, oidnDevice); } std::string DenoiseFrameOp::toString() const { return "ospray::DenoiseFrameOp"; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/denoiser/DenoiseFrameOp.h000066400000000000000000000011001456566705700236300ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // oidn #include "OpenImageDenoise/oidn.hpp" // ospray #include "fb/ImageOp.h" #include "ospray_module_denoiser_export.h" namespace ospray { struct OSPRAY_MODULE_DENOISER_EXPORT DenoiseFrameOp : public FrameOpInterface { DenoiseFrameOp(api::Device &device); std::unique_ptr attach( FrameBufferView &fbView) override; std::string toString() const override; private: oidn::DeviceRef oidnDevice; bool sharedMem{false}; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/denoiser/ModuleInit.cpp000066400000000000000000000013101456566705700233770ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // We don't want an instance of ObjectFactory static table in this library // so we have to include it with import define so the table will be imported // from 'ospray' library #define OBJECTFACTORY_IMPORT #include "common/ObjectFactory.h" #include "DenoiseFrameOp.h" #include "common/OSPCommon.h" extern "C" OSPError OSPRAY_DLLEXPORT ospray_module_init_denoiser( int16_t versionMajor, int16_t versionMinor, int16_t /*versionPatch*/) { auto status = ospray::moduleVersionCheck(versionMajor, versionMinor); if (status == OSP_NO_ERROR) ospray::ImageOp::registerType("denoiser"); return status; } RenderKit-ospray-f2a61c2/modules/mpi/000077500000000000000000000000001456566705700176045ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/mpi/CMakeLists.txt000066400000000000000000000017211456566705700223450ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 cmake_dependent_option( OSPRAY_MODULE_MPI "Build the MPI module (Requires the CPU module)" OFF OSPRAY_MODULE_CPU OFF ) if (NOT OSPRAY_MODULE_MPI) return() endif() find_package(MPI REQUIRED) if(NOT TARGET MPI::MPI_CXX) # pre CMake 3.9 add_library(MPI::MPI_CXX IMPORTED INTERFACE) set_property(TARGET MPI::MPI_CXX PROPERTY INTERFACE_COMPILE_OPTIONS ${MPI_CXX_COMPILE_FLAGS}) set_property(TARGET MPI::MPI_CXX PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${MPI_CXX_INCLUDE_DIRS}") set_property(TARGET MPI::MPI_CXX PROPERTY INTERFACE_LINK_LIBRARIES ${MPI_CXX_LINK_FLAGS} ${MPI_CXX_LIBRARIES}) endif() find_package(Snappy REQUIRED) rkcommon_configure_build_type() add_subdirectory(common) add_subdirectory(ospray) if (OSPRAY_ENABLE_APPS_EXAMPLES OR OSPRAY_ENABLE_APPS_TUTORIALS) add_subdirectory(tutorials) endif() if (OSPRAY_ENABLE_APPS_TESTING) add_subdirectory(testing) endif() RenderKit-ospray-f2a61c2/modules/mpi/common/000077500000000000000000000000001456566705700210745ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/mpi/common/CMakeLists.txt000066400000000000000000000012711456566705700236350ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 add_library(ospray_mpi_common SHARED Collectives.cpp MPIBcastFabric.cpp MPICommon.cpp ObjectHandle.cpp maml/maml.cpp maml/Context.cpp ) include(GenerateExportHeader) generate_export_header(ospray_mpi_common) target_link_libraries(ospray_mpi_common PRIVATE Snappy::snappy PUBLIC rkcommon::rkcommon ospray MPI::MPI_CXX ) target_include_directories(ospray_mpi_common PUBLIC $ $ $ ) ospray_install_library(ospray_mpi_common mpi) RenderKit-ospray-f2a61c2/modules/mpi/common/Collectives.cpp000066400000000000000000000214421456566705700240570ustar00rootroot00000000000000// Copyright 2016 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Collectives.h" #include #include #include #include #include "maml/maml.h" namespace mpicommon { using namespace rkcommon; OSPRAY_MPI_COMMON_EXPORT std::future bcast( void *buf, size_t count, MPI_Datatype datatype, int root, MPI_Comm comm) { int typeSize = 0; MPI_Type_size(datatype, &typeSize); auto view = std::make_shared>( static_cast(buf), count * typeSize); auto col = std::make_shared(view, count, datatype, root, comm); maml::queueCollective(col); return col->future(); } OSPRAY_MPI_COMMON_EXPORT std::future bcast( std::shared_ptr> &buffer, size_t count, MPI_Datatype datatype, int root, MPI_Comm comm) { auto col = std::make_shared(buffer, count, datatype, root, comm); maml::queueCollective(col); return col->future(); } OSPRAY_MPI_COMMON_EXPORT std::future barrier(MPI_Comm comm) { auto col = std::make_shared(comm); maml::queueCollective(col); return col->future(); } OSPRAY_MPI_COMMON_EXPORT std::future gather(const void *sendBuffer, int sendCount, MPI_Datatype sendType, void *recvBuffer, int recvCount, MPI_Datatype recvType, int root, MPI_Comm comm) { auto col = std::make_shared(sendBuffer, sendCount, sendType, recvBuffer, recvCount, recvType, root, comm); maml::queueCollective(col); return col->future(); } OSPRAY_MPI_COMMON_EXPORT std::future gatherv(const void *sendBuffer, int sendCount, MPI_Datatype sendType, void *recvBuffer, const std::vector &recvCounts, const std::vector &recvOffsets, MPI_Datatype recvType, int root, MPI_Comm comm) { auto col = std::make_shared(sendBuffer, sendCount, sendType, recvBuffer, recvCounts, recvOffsets, recvType, root, comm); maml::queueCollective(col); return col->future(); } OSPRAY_MPI_COMMON_EXPORT std::future send(void *buffer, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) { auto col = std::make_shared(buffer, count, datatype, dest, tag, comm); maml::queueCollective(col); return col->future(); } OSPRAY_MPI_COMMON_EXPORT std::future recv(void *buffer, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm) { auto col = std::make_shared(buffer, count, datatype, source, tag, comm); maml::queueCollective(col); return col->future(); } OSPRAY_MPI_COMMON_EXPORT std::future reduce(const void *sendBuffer, void *recvBuffer, int count, MPI_Datatype datatype, MPI_Op operation, int root, MPI_Comm comm) { auto col = std::make_shared( sendBuffer, recvBuffer, count, datatype, operation, root, comm); maml::queueCollective(col); return col->future(); } OSPRAY_MPI_COMMON_EXPORT std::future allreduce(const void *sendBuffer, void *recvBuffer, int count, MPI_Datatype datatype, MPI_Op operation, MPI_Comm comm) { auto col = std::make_shared( sendBuffer, recvBuffer, count, datatype, operation, comm); maml::queueCollective(col); return col->future(); } Collective::Collective(MPI_Comm comm) : comm(comm), request(MPI_REQUEST_NULL) {} bool Collective::finished() { int done = 0; MPI_CALL(Test(&request, &done, MPI_STATUS_IGNORE)); if (done) { onFinish(); } return done; } Barrier::Barrier(MPI_Comm comm) : Collective(comm) {} std::future Barrier::future() { return result.get_future(); } void Barrier::start() { MPI_CALL(Ibarrier(comm, &request)); } void Barrier::onFinish() { result.set_value(); } Bcast::Bcast(std::shared_ptr> buffer, size_t count, MPI_Datatype datatype, int root, MPI_Comm comm) : Collective(comm), buffer(buffer), count(count), datatype(datatype), root(root) { MPI_Type_size(datatype, &typeSize); } std::future Bcast::future() { return result.get_future(); } void Bcast::start() { // 1GB as the max bcast size const static size_t MAX_BCAST_SIZE = 1e9; size_t remaining = count; // TODO: This is Rust's slice::chunks iterator uint8_t *iter = buffer->begin(); do { MPI_Request req; const size_t toSend = std::min(MAX_BCAST_SIZE, remaining); MPI_CALL(Ibcast(iter, toSend, datatype, root, comm, &req)); requests.push_back(req); iter += toSend * typeSize; remaining -= toSend; } while (iter != buffer->end()); } bool Bcast::finished() { const size_t ndone = std::accumulate( requests.begin(), requests.end(), 0, [](const int &n, MPI_Request &r) { int d = 0; MPI_CALL(Test(&r, &d, MPI_STATUS_IGNORE)); if (d) { return n + 1; } return n; }); if (ndone == requests.size()) { onFinish(); } return ndone == requests.size(); } void Bcast::onFinish() { result.set_value(static_cast(buffer->data())); } Gather::Gather(const void *sendBuffer, int sendCount, MPI_Datatype sendType, void *recvBuffer, int recvCount, MPI_Datatype recvType, int root, MPI_Comm comm) : Collective(comm), sendBuffer(sendBuffer), sendCount(sendCount), sendType(sendType), recvBuffer(recvBuffer), recvCount(recvCount), recvType(recvType), root(root) {} std::future Gather::future() { return result.get_future(); } void Gather::start() { MPI_CALL(Igather(sendBuffer, sendCount, sendType, recvBuffer, recvCount, recvType, root, comm, &request)); } void Gather::onFinish() { result.set_value(recvBuffer); } Gatherv::Gatherv(const void *sendBuffer, int sendCount, MPI_Datatype sendType, void *recvBuffer, const std::vector &recvCounts, const std::vector &recvOffsets, MPI_Datatype recvType, int root, MPI_Comm comm) : Collective(comm), sendBuffer(sendBuffer), sendCount(sendCount), sendType(sendType), recvBuffer(recvBuffer), recvCounts(recvCounts), recvOffsets(recvOffsets), recvType(recvType), root(root) {} std::future Gatherv::future() { return result.get_future(); } void Gatherv::start() { MPI_CALL(Igatherv(sendBuffer, sendCount, sendType, recvBuffer, recvCounts.data(), recvOffsets.data(), recvType, root, comm, &request)); } void Gatherv::onFinish() { result.set_value(recvBuffer); } Reduce::Reduce(const void *sendBuffer, void *recvBuffer, int count, MPI_Datatype datatype, MPI_Op operation, int root, MPI_Comm comm) : Collective(comm), sendBuffer(sendBuffer), recvBuffer(recvBuffer), count(count), datatype(datatype), operation(operation), root(root) {} std::future Reduce::future() { return result.get_future(); } void Reduce::start() { MPI_CALL(Ireduce(sendBuffer, recvBuffer, count, datatype, operation, root, comm, &request)); } void Reduce::onFinish() { result.set_value(recvBuffer); } AllReduce::AllReduce(const void *sendBuffer, void *recvBuffer, int count, MPI_Datatype datatype, MPI_Op operation, MPI_Comm comm) : Collective(comm), sendBuffer(sendBuffer), recvBuffer(recvBuffer), count(count), datatype(datatype), operation(operation) {} std::future AllReduce::future() { return result.get_future(); } void AllReduce::start() { MPI_CALL(Iallreduce( sendBuffer, recvBuffer, count, datatype, operation, comm, &request)); } void AllReduce::onFinish() { result.set_value(recvBuffer); } Send::Send(void *buffer, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) : Collective(comm), buffer(buffer), count(count), datatype(datatype), dest(dest), tag(tag) {} std::future Send::future() { return result.get_future(); } void Send::start() { MPI_CALL(Isend(buffer, count, datatype, dest, tag, comm, &request)); } void Send::onFinish() { result.set_value(buffer); } Recv::Recv(void *buffer, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm) : Collective(comm), buffer(buffer), count(count), datatype(datatype), source(source), tag(tag) {} std::future Recv::future() { return result.get_future(); } void Recv::start() { MPI_CALL(Irecv(buffer, count, datatype, source, tag, comm, &request)); } void Recv::onFinish() { result.set_value(buffer); } } // namespace mpicommon RenderKit-ospray-f2a61c2/modules/mpi/common/Collectives.h000066400000000000000000000247151456566705700235320ustar00rootroot00000000000000// Copyright 2016 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include #include "MPICommon.h" #include "ospray_mpi_common_export.h" #include "rkcommon/utility/ArrayView.h" namespace mpicommon { // Convenient wrappers over the collectives // /* Start an asynchronous bcast and return the future to wait on * for completion. The caller owns the passed buffer, and must keep it * valid until the future completes. */ OSPRAY_MPI_COMMON_EXPORT std::future bcast( void *buffer, size_t count, MPI_Datatype datatype, int root, MPI_Comm comm); OSPRAY_MPI_COMMON_EXPORT std::future bcast( std::shared_ptr> &buffer, size_t count, MPI_Datatype datatype, int root, MPI_Comm comm); /* Start an asynchronous barrier and return the future to wait on for * completion of the barrier */ OSPRAY_MPI_COMMON_EXPORT std::future barrier(MPI_Comm comm); /* Start an asynchronous gather and return the future to wait on for * completion of the gather. The called owns both the send and recv buffers, * and must keep them valid until the future completes. The pointer returned * in the future is to the receive buffer. */ OSPRAY_MPI_COMMON_EXPORT std::future gather(const void *sendBuffer, int sendCount, MPI_Datatype sendType, void *recvBuffer, int recvCount, MPI_Datatype recvType, int root, MPI_Comm comm); /* Start an asynchronous gatherv and return the future to wait on for * completion of the gather. The called owns both the send and recv buffers, * and must keep them valid until the future completes. The pointer returned * in the future is to the receive buffer. The recvCounts and offsets * vectors are copied into the struct. */ OSPRAY_MPI_COMMON_EXPORT std::future gatherv(const void *sendBuffer, int sendCount, MPI_Datatype sendType, void *recvBuffer, const std::vector &recvCounts, const std::vector &recvOffsets, MPI_Datatype recvType, int root, MPI_Comm comm); /* Start an asynchronously run reduce. The send/recv buffers are owned * by the caller and must be kept valid until the future is set, indicating * completion of the reduction. */ OSPRAY_MPI_COMMON_EXPORT std::future reduce(const void *sendBuffer, void *recvBuffer, int count, MPI_Datatype datatype, MPI_Op operation, int root, MPI_Comm comm); /* Start an asynchronously run allreduce. The send/recv buffers are owned * by the caller and must be kept valid until the future is set, indicating * completion of the reduction. */ OSPRAY_MPI_COMMON_EXPORT std::future allreduce(const void *sendBuffer, void *recvBuffer, int count, MPI_Datatype datatype, MPI_Op operation, MPI_Comm comm); /* Start an asynchronously run send. The buffer is owned by * the caller and must be kept valid until the future is set, indicating * completion of the send. * TODO: Chunking */ OSPRAY_MPI_COMMON_EXPORT std::future send(void *buffer, int count, MPI_Datatype datatype, int destination, int tag, MPI_Comm comm); /* Start an asynchronously run recv. The buffer is owned by * the caller and must be kept valid until the future is set, indicating * completion of the recv. * TODO: Chunking */ OSPRAY_MPI_COMMON_EXPORT std::future recv(void *buffer, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm); // An asynchronously executed collective operation which can be run // on the MPI messaging layer class OSPRAY_MPI_COMMON_EXPORT Collective { public: Collective(MPI_Comm comm); virtual ~Collective() = default; // Start the collective virtual void start() = 0; // Check if the collective is done and notify the child classes onFinish virtual bool finished(); protected: virtual void onFinish() = 0; MPI_Comm comm; MPI_Request request; }; class OSPRAY_MPI_COMMON_EXPORT Barrier : public Collective { public: Barrier(MPI_Comm comm); // Get the future to wait on completion of this barrier std::future future(); void start() override; protected: void onFinish() override; private: std::promise result; }; class OSPRAY_MPI_COMMON_EXPORT Bcast : public Collective { public: /* Construct an asynchronously run broadcast. The buffer is owned by * the caller and must be kept valid until the future is set, indicating * completion of the broadcast. */ Bcast(std::shared_ptr> buffer, size_t count, MPI_Datatype datatype, int root, MPI_Comm comm); // Get the future which will receive the result of this bcast std::future future(); void start() override; bool finished() override; protected: void onFinish() override; private: std::shared_ptr> buffer; size_t count; int typeSize; MPI_Datatype datatype; int root; std::promise result; std::vector requests; }; class OSPRAY_MPI_COMMON_EXPORT Gather : public Collective { public: /* Construct an asynchronously run gather. The send/recv buffers are owned * by the caller and must be kept valid until the future is set, indicating * completion of the gather. */ Gather(const void *sendBuffer, int sendCount, MPI_Datatype sendType, void *recvBuffer, int recvCount, MPI_Datatype recvType, int root, MPI_Comm comm); /* Get the future which will receive the result of this gather. * The returned pointer will point to the recvBuffer containing the * received data. */ std::future future(); void start() override; protected: void onFinish() override; private: const void *sendBuffer; int sendCount; MPI_Datatype sendType; void *recvBuffer; int recvCount; MPI_Datatype recvType; int root; std::promise result; }; class OSPRAY_MPI_COMMON_EXPORT Gatherv : public Collective { public: /* Construct an asynchronously run gatherv. The send/recv buffers are owned * by the caller and must be kept valid until the future is set, indicating * completion of the gatherv. The recvOffsets and counts vectors are copied * into the struct. */ Gatherv(const void *sendBuffer, int sendCount, MPI_Datatype sendType, void *recvBuffer, const std::vector &recvCounts, const std::vector &recvOffsets, MPI_Datatype recvType, int root, MPI_Comm comm); /* Get the future which will receive the result of this gatherv. * The returned pointer will point to the recvBuffer containing the * received data. */ std::future future(); void start() override; protected: void onFinish() override; private: const void *sendBuffer; int sendCount; MPI_Datatype sendType; void *recvBuffer; std::vector recvCounts; std::vector recvOffsets; MPI_Datatype recvType; int root; std::promise result; }; class OSPRAY_MPI_COMMON_EXPORT Reduce : public Collective { public: /* Construct an asynchronously run reduce. The send/recv buffers are owned * by the caller and must be kept valid until the future is set, indicating * completion of the reduction. */ Reduce(const void *sendBuffer, void *recvBuffer, int count, MPI_Datatype datatype, MPI_Op operation, int root, MPI_Comm comm); /* Get the future which will receive the result of this reduction. * The returned pointer will point to the recvBuffer containing the * result of the reduction. */ std::future future(); void start() override; protected: void onFinish() override; private: const void *sendBuffer; void *recvBuffer; int count; MPI_Datatype datatype; MPI_Op operation; int root; std::promise result; }; class OSPRAY_MPI_COMMON_EXPORT AllReduce : public Collective { public: /* Construct an asynchronously run allreduce. The send/recv buffers are owned * by the caller and must be kept valid until the future is set, indicating * completion of the reduction. */ AllReduce(const void *sendBuffer, void *recvBuffer, int count, MPI_Datatype datatype, MPI_Op operation, MPI_Comm comm); /* Get the future which will receive the result of this reduction. * The returned pointer will point to the recvBuffer containing the * result of the reduction. */ std::future future(); void start() override; protected: void onFinish() override; private: const void *sendBuffer; void *recvBuffer; int count; MPI_Datatype datatype; MPI_Op operation; std::promise result; }; /* Send/recv are not really collectives, but are separate from the typical * fire and forget style of messaging that the mpicommon::Message uses. * With these we actually want the ability to wait for a specific send to * finish, and a specific recv from a process to be completed. With the * fire and forget messaging layer we don't care about this and just queue * stuff up and receive whatever is coming to us. */ class OSPRAY_MPI_COMMON_EXPORT Send : public Collective { public: /* Construct an asynchronously run send. The buffer is owned by * the caller and must be kept valid until the future is set, indicating * completion of the send. */ Send(void *buffer, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm); /* Get the future which will return when this send is done, returns the * pointer to the sent buffer */ std::future future(); void start() override; protected: void onFinish() override; private: void *buffer; int count; MPI_Datatype datatype; int dest; int tag; std::promise result; }; class OSPRAY_MPI_COMMON_EXPORT Recv : public Collective { public: /* Construct an asynchronously run recv. The buffer is owned by * the caller and must be kept valid until the future is set, indicating * completion of the recv. */ Recv(void *buffer, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm); /* Get the future which will return when this recv is done, returns the * pointer to the buffer containing the recv'd data */ std::future future(); void start() override; protected: void onFinish() override; private: void *buffer; int count; MPI_Datatype datatype; int source; int tag; std::promise result; }; } // namespace mpicommon RenderKit-ospray-f2a61c2/modules/mpi/common/MPIBcastFabric.cpp000066400000000000000000000046411456566705700243160ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include #include #include #include "Collectives.h" #include "MPIBcastFabric.h" #include "maml/maml.h" namespace mpicommon { MPIFabric::MPIFabric(const Group &parentGroup, int bcastRoot) : group(parentGroup.dup()), bcastRoot(bcastRoot) { if (!group.valid()) { throw std::runtime_error( "#osp:mpi: trying to set up an MPI fabric " "with an invalid MPI communicator"); } int isInter = 0; MPI_CALL(Comm_test_inter(group.comm, &isInter)); if (isInter && bcastRoot != MPI_ROOT) { throw std::runtime_error( "Invalid MPIFabric group config " "on an MPI intercomm group"); } } MPIFabric::~MPIFabric() { flushBcastSends(); MPI_Comm_free(&group.comm); } void MPIFabric::sendBcast(std::shared_ptr> buf) { auto future = mpicommon::bcast( buf->data(), buf->size(), MPI_BYTE, bcastRoot, group.comm); pendingSends.emplace_back( std::make_shared(std::move(future), buf)); checkPendingSends(); } void MPIFabric::flushBcastSends() { while (!pendingSends.empty()) { checkPendingSends(); } } void MPIFabric::recvBcast(utility::AbstractArray &buf) { mpicommon::bcast(buf.data(), buf.size(), MPI_BYTE, bcastRoot, group.comm) .wait(); checkPendingSends(); } void MPIFabric::send( std::shared_ptr> buf, int rank) { auto future = mpicommon::send(buf->data(), buf->size(), MPI_BYTE, rank, 0, group.comm); pendingSends.emplace_back( std::make_shared(std::move(future), buf)); checkPendingSends(); } void MPIFabric::recv(utility::AbstractArray &buf, int rank) { mpicommon::recv(buf.data(), buf.size(), MPI_BYTE, rank, 0, group.comm).wait(); checkPendingSends(); } void MPIFabric::checkPendingSends() { if (!pendingSends.empty()) { auto done = std::partition(pendingSends.begin(), pendingSends.end(), [](const std::shared_ptr &ps) { return ps->future.wait_for(std::chrono::milliseconds(0)) != std::future_status::ready; }); pendingSends.erase(done, pendingSends.end()); } } MPIFabric::PendingSend::PendingSend(std::future future, std::shared_ptr> &buf) : future(std::move(future)), buf(buf) {} } // namespace mpicommon RenderKit-ospray-f2a61c2/modules/mpi/common/MPIBcastFabric.h000066400000000000000000000032271456566705700237620ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include "rkcommon/networking/DataStreaming.h" #include "rkcommon/networking/Fabric.h" #include "rkcommon/utility/AbstractArray.h" #include "MPICommon.h" #include "ospray_mpi_common_export.h" namespace mpicommon { /*! a specific fabric based on MPI. Note that in the case of an * MPIFabric using an intercommunicator the send rank must * be MPI_ROOT and the recv rank must be 0. The group passed will * be duplicated to avoid MPI collective matching issues with other * fabrics and collectives. */ class OSPRAY_MPI_COMMON_EXPORT MPIFabric : public networking::Fabric { public: MPIFabric(const Group &parentGroup, int bcastRoot); virtual ~MPIFabric() override; void sendBcast(std::shared_ptr> buf) override; void flushBcastSends() override; void recvBcast(utility::AbstractArray &buf) override; void send( std::shared_ptr> buf, int rank) override; void recv(utility::AbstractArray &buf, int rank) override; private: void checkPendingSends(); Group group; int bcastRoot; struct PendingSend { std::future future; std::shared_ptr> buf = nullptr; PendingSend() = default; PendingSend(std::future future, std::shared_ptr> &buf); PendingSend(const PendingSend &) = delete; PendingSend &operator=(const PendingSend &) = delete; }; std::vector> pendingSends; }; } // namespace mpicommon RenderKit-ospray-f2a61c2/modules/mpi/common/MPICommon.cpp000066400000000000000000000066711456566705700234100ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "MPICommon.h" namespace mpicommon { static std::mutex mpiMutex; bool mpiIsThreaded = false; Group world; Group worker; // Group definitions //////////////////////////////////////////////////////// /*! constructor. sets the 'comm', 'rank', and 'size' fields */ Group::Group(MPI_Comm initComm) { setTo(initComm); } /*! constructor. sets the 'comm', 'rank', and 'size' fields */ Group::Group(const Group &other) : containsMe(other.containsMe), comm(other.comm), rank(other.rank), size(other.size) {} void Group::makeIntraComm() { MPI_CALL(Comm_rank(comm, &rank)); MPI_CALL(Comm_size(comm, &size)); containsMe = true; } void Group::makeIntraComm(MPI_Comm _comm) { this->comm = _comm; makeIntraComm(); } void Group::makeInterComm() { containsMe = false; rank = MPI_ROOT; MPI_CALL(Comm_remote_size(comm, &size)); } void Group::makeInterComm(MPI_Comm _comm) { this->comm = _comm; makeInterComm(); } /*! set to given intercomm, and properly set size, root, etc */ void Group::setTo(MPI_Comm _comm) { if (this->comm == _comm) return; this->comm = _comm; if (comm == MPI_COMM_NULL) { rank = size = -1; } else { int isInter; MPI_CALL(Comm_test_inter(comm, &isInter)); if (isInter) makeInterComm(comm); else makeIntraComm(comm); } } /*! do an MPI_Comm_dup, and return duplicated communicator */ Group Group::dup() const { MPI_Comm duped; MPI_CALL(Comm_dup(comm, &duped)); return Group(duped); } // Message definitions ////////////////////////////////////////////////////// /*! create a new message with given amount of bytes in storage */ Message::Message(size_t size) : size(size) { data = (rkcommon::byte_t *)malloc(size); } /*! create a new message with given amount of storage, and copy memory from the given address to it */ Message::Message(const void *copyMem, size_t size) : Message(size) { if (copyMem == nullptr) OSPRAY_THROW("#mpicommon: cannot create a message from a null pointer!"); memcpy(data, copyMem, size); } /*! create a new message (addressed to given comm:rank) with given amount of storage, and copy memory from the given address to it */ Message::Message(MPI_Comm comm, int rank, const void *copyMem, size_t size) : Message(copyMem, size) { this->comm = comm; this->rank = rank; } /*! destruct message and free allocated memory */ Message::~Message() { free(data); } bool Message::isValid() const { return comm != MPI_COMM_NULL && rank >= 0; } bool init(int *ac, const char **av, bool useCommWorld) { int initialized = false; MPI_CALL(Initialized(&initialized)); int provided = 0; if (!initialized) { /* MPI not initialized by the app - it's up to us */ MPI_CALL(Init_thread( ac, const_cast(&av), MPI_THREAD_MULTIPLE, &provided)); } else { /* MPI was already initialized by the app that called us! */ MPI_Query_thread(&provided); } if (provided != MPI_THREAD_MULTIPLE && provided != MPI_THREAD_SERIALIZED) { throw std::runtime_error( "MPI initialization error: The MPI runtime must" " support either MPI_THREAD_MULTIPLE or" " MPI_THREAD_SERIALIZED."); } mpiIsThreaded = provided == MPI_THREAD_MULTIPLE; if (useCommWorld) { world.setTo(MPI_COMM_WORLD); } return !initialized; } bool isManagedObject(OSPDataType type) { return type & OSP_OBJECT; } } // namespace mpicommon RenderKit-ospray-f2a61c2/modules/mpi/common/MPICommon.h000066400000000000000000000126321456566705700230470ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include #include #define OMPI_SKIP_MPICXX 1 #include #include "ospray/OSPEnums.h" #include "rkcommon/common.h" #include "ospray_mpi_common_export.h" // IMPI on Windows defines MPI_CALL already, erroneously #ifdef MPI_CALL #undef MPI_CALL #endif /*! helper macro that checks the return value of all MPI_xxx(...) calls via MPI_CALL(xxx(...)). */ #define MPI_CALL(a) \ { \ int rc = MPI_##a; \ if (rc != MPI_SUCCESS) \ throw std::runtime_error("MPI call returned error"); \ } #define OSPRAY_THROW(a) \ throw std::runtime_error( \ "in " + std::string(__PRETTY_FUNCTION__) + " : " + std::string(a)) #define OSPRAY_WORLD_GROUP_TAG 290374 namespace mpicommon { using namespace rkcommon; /*! global variable that turns on logging of MPI communication (for debugging) _may_ eventually turn this into a real logLevel, but for now this is cleaner here than in the MPI device */ OSPRAY_MPI_COMMON_EXPORT extern bool mpiIsThreaded; //! abstraction for an MPI group. /*! it's the responsibility of the respective mpi setup routines to fill in the proper values */ struct OSPRAY_MPI_COMMON_EXPORT Group { /*! constructor. sets the 'comm', 'rank', and 'size' fields */ Group(MPI_Comm initComm = MPI_COMM_NULL); Group(const Group &other); inline bool valid() const { return comm != MPI_COMM_NULL; } void makeIntraComm(); void makeIntraComm(MPI_Comm); void makeInterComm(); void makeInterComm(MPI_Comm); /*! set to given intercomm, and properly set size, root, etc */ void setTo(MPI_Comm comm); /*! do an MPI_Comm_dup, and return duplicated communicator */ Group dup() const; // whether the current process/thread is a member of this group bool containsMe{false}; // communictor for this group. intercommunicator if i'm a member of this // group; else it's an intracommunicator MPI_Comm comm{MPI_COMM_NULL}; /*! my rank in this group if i'm a member; else set to MPI_ROOT */ int rank{-1}; // size of this group if i'm a member, else size of remote group this // intracommunicator refers to int size{-1}; }; /*! object that handles a message. a message primarily consists of a pointer to data; the message itself "owns" this pointer, and will delete it once the message itself dies. the message itself is reference counted using the std::shared_ptr functionality. */ struct OSPRAY_MPI_COMMON_EXPORT Message { Message() = default; /*! create a new message with given amount of bytes in storage */ Message(size_t size); /*! create a new message with given amount of storage, and copy memory from the given address to it */ Message(const void *copyMem, size_t size); /*! create a new message (addressed to given comm:rank) with given amount of storage, and copy memory from the given address to it */ Message(MPI_Comm comm, int rank, const void *copyMem, size_t size); Message(const Message &) = delete; Message &operator=(const Message &) = delete; /*! destruct message and free allocated memory */ virtual ~Message(); bool isValid() const; /*! @{ sender/receiver of this message */ MPI_Comm comm{MPI_COMM_NULL}; int rank{-1}; int tag{0}; /*! @} */ /*! @{ actual payload of this message */ rkcommon::byte_t *data{nullptr}; size_t size{0}; /*! @} */ // TODO WILL: Profiling info, when this message started sending // or receiving std::chrono::high_resolution_clock::time_point started; }; /*! a message whose payload is owned by the user, and which we do NOT delete upon termination */ struct OSPRAY_MPI_COMMON_EXPORT UserMemMessage : public Message { UserMemMessage(void *nonCopyMem, size_t size) : Message() { data = (rkcommon::byte_t *)nonCopyMem; this->size = size; } /* set data to null to keep the parent from deleting it */ virtual ~UserMemMessage() override { data = nullptr; } }; //! MPI_COMM_WORLD OSPRAY_MPI_COMMON_EXPORT extern Group world; /* The communicator used for the OSPRay workers, may be equivalent to world * depending on the launch configuration */ OSPRAY_MPI_COMMON_EXPORT extern Group worker; // Initialize OSPRay's MPI groups, returns false if MPI // was already initialized. useCommWorld indicates if MPI_COMM_WORLD // should be set as the world group used for communication. If false, // it is up to the caller to configure the world group correctly. OSPRAY_MPI_COMMON_EXPORT bool init(int *ac, const char **av, bool useCommWorld); /* MPICommon has its own implementation so the offload worker can check for * managed objects without having to link ospray_module_cpu */ OSPRAY_MPI_COMMON_EXPORT bool isManagedObject(OSPDataType type); OSPRAY_MPI_COMMON_EXPORT inline int workerRank() { return worker.rank; } OSPRAY_MPI_COMMON_EXPORT inline int workerSize() { return worker.size; } OSPRAY_MPI_COMMON_EXPORT inline int masterRank() { return 0; } OSPRAY_MPI_COMMON_EXPORT inline bool IamTheMaster() { return workerRank() == masterRank(); } } // namespace mpicommon RenderKit-ospray-f2a61c2/modules/mpi/common/ObjectHandle.cpp000066400000000000000000000052301456566705700241220ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ObjectHandle.h" #include #include namespace ospray { static std::map objectByHandle; static std::stack freedHandles; //! next unassigned ID on this node /*! we start numbering with 1 to make sure that "0:0" is an invalid handle (so we can typecast between (64-bit) handles and (64-bit)OSPWhatEver pointers */ static int32 nextFreeLocalID = 1; void ObjectHandle::free() { freedHandles.push((int64) * this); } ObjectHandle::ObjectHandle() : i64(NULL_HANDLE) {} ObjectHandle::ObjectHandle(int64 i) : i64(i) {} ObjectHandle::ObjectHandle(const ObjectHandle &other) : i64(other.i64) {} ObjectHandle &ObjectHandle::operator=(const ObjectHandle &other) { if (this != &other) i64 = other.i64; return *this; } /*! define the given handle to refer to given object */ void ObjectHandle::assign(const ObjectHandle &handle, memory::RefCount *object) { objectByHandle[handle] = object; } void ObjectHandle::assign(memory::RefCount *object) const { objectByHandle[i64] = object; } void ObjectHandle::freeObject() const { auto it = objectByHandle.find(i64); if (it != objectByHandle.end()) { // let internal device handle this -> it->second->refDec(); objectByHandle.erase(it); } } int32 ObjectHandle::ownerRank() const { return i32.owner; } int32 ObjectHandle::objID() const { return i32.ID; } ospray::ObjectHandle::operator int64() const { return i64; } bool ObjectHandle::defined() const { return objectByHandle.find(i64) != objectByHandle.end(); } ObjectHandle ObjectHandle::allocateLocalHandle() { ObjectHandle handle; if (freedHandles.empty()) { handle.i32.ID = nextFreeLocalID++; handle.i32.owner = 0; } else { handle.i64 = freedHandles.top(); freedHandles.pop(); } return handle; } memory::RefCount *ObjectHandle::lookup() const { if (i64 == 0) return nullptr; auto it = objectByHandle.find(i64); if (it == objectByHandle.end()) { #ifndef NDEBUG // iw - made this into a warning only; the original code had // this throw an actual exceptoin, but that may be overkill std::cout << "#osp: WARNING: ospray is trying to look up object handle " + std::to_string(i64) + " that isn't defined!" << std::endl; #endif return nullptr; } return it->second; } ObjectHandle ObjectHandle::lookup(memory::RefCount *object) { for (auto it = objectByHandle.begin(); it != objectByHandle.end(); it++) { if (it->second == object) return (ObjectHandle(it->first)); } return (nullHandle); } const ObjectHandle nullHandle(0); } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/common/ObjectHandle.h000066400000000000000000000047741456566705700236030ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "MPICommon.h" #include "common/OSPCommon.h" #include "ospray_mpi_common_export.h" #include "rkcommon/memory/RefCount.h" namespace ospray { #define NULL_HANDLE (ObjectHandle(0)) //! (local) handle to a (remote) managed object /*! abstraction for a remotely-held 'managed object'. the handle refers to both 'owner' (the machine that has it) as well as to a local ID (by which that owner can look it up). Note that other ranks may also have copies of that object. note that the 'null handle' is '0', not -1. This allows an app to test the handled resturend from ospNewXXX calls for null just as if they were pointers (and thus, 'null' objects are consistent between local and mpi rendering) */ union OSPRAY_MPI_COMMON_EXPORT ObjectHandle { ObjectHandle(); ObjectHandle(int64 i); ObjectHandle(const ObjectHandle &other); ObjectHandle &operator=(const ObjectHandle &other); void free(); /*! look up an object by handle, and return it. must be a defined handle */ memory::RefCount *lookup() const; /* Allocate a local ObjectHandle */ static ObjectHandle allocateLocalHandle(); /*! Return the handle associated with the given object. */ static ObjectHandle lookup(memory::RefCount *object); /*! check whether the handle is defined *on this rank* */ bool defined() const; /*! define the given handle to refer to given object */ static void assign(const ObjectHandle &handle, memory::RefCount *object); /*! define the given handle to refer to given object */ void assign(memory::RefCount *object) const; void freeObject() const; int32 ownerRank() const; int32 objID() const; /*! cast to int64 to allow fast operations with this type */ operator int64() const; // Data members // struct { int32 ID; int32 owner; } i32; int64 i64; }; OSPRAY_MPI_COMMON_EXPORT extern const ObjectHandle nullHandle; // Inlined operator definitions ///////////////////////////////////////////// OSPRAY_MPI_COMMON_EXPORT inline bool operator==( const ObjectHandle &a, const ObjectHandle &b) { return a.i64 == b.i64; } OSPRAY_MPI_COMMON_EXPORT inline bool operator!=( const ObjectHandle &a, const ObjectHandle &b) { return !(a == b); } template inline OSPRAY_TYPE *lookupObject(OSPObject obj) { auto &handle = reinterpret_cast(obj); return handle.defined() ? (OSPRAY_TYPE *)handle.lookup() : (OSPRAY_TYPE *)obj; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/common/maml/000077500000000000000000000000001456566705700220225ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/mpi/common/maml/Context.cpp000066400000000000000000000213161456566705700241550ustar00rootroot00000000000000// Copyright 2016 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Context.h" #include #include #include #include #include "common/OSPCommon.h" #include "rkcommon/memory/malloc.h" #include "rkcommon/tasking/async.h" #include "rkcommon/tasking/tasking_system_init.h" #include "rkcommon/utility/getEnvVar.h" using rkcommon::byte_t; using rkcommon::make_unique; using rkcommon::tasking::AsyncLoop; using rkcommon::tasking::numTaskingThreads; using rkcommon::utility::getEnvVar; using namespace std::chrono; namespace maml { /*! the singleton object that handles all the communication */ std::unique_ptr Context::singleton; Context::Context(bool enableCompression) : compressMessages(enableCompression) {} Context::~Context() { try { stop(); } catch (const std::exception &e) { ospray::handleError(OSP_UNKNOWN_ERROR, e.what()); } } /*! register a new incoing-message handler. if any message comes in on the given communicator we'll call this handler */ void Context::registerHandlerFor(MPI_Comm comm, MessageHandler *handler) { if (handlers.find(comm) != handlers.end()) { std::cerr << CODE_LOCATION << ": Warning: handler for this MPI_Comm already installed" << std::endl; } handlers[comm] = handler; /*! todo: to avoid race conditions we MAY want to check if there's any messages we've already received that would match this handler */ } /*! put the given message in the outbox. note that this can be done even if the actual sending mechanism is currently stopped */ void Context::send(std::shared_ptr msg) { // The message uses malloc/free, so use that instead of new/delete if (compressMessages) { byte_t *compressed = (byte_t *)malloc(snappy::MaxCompressedLength(msg->size)); size_t compressedSize = 0; snappy::RawCompress(reinterpret_cast(msg->data), msg->size, reinterpret_cast(compressed), &compressedSize); free(msg->data); msg->data = compressed; msg->size = compressedSize; } outbox.push_back(std::move(msg)); } void Context::queueCollective(std::shared_ptr col) { // TODO WILL: auto-compress collectives? collectiveOutbox.push_back(std::move(col)); } void Context::processInboxMessages() { auto incomingMessages = inbox.consume(); for (auto &msg : incomingMessages) { auto *handler = handlers[msg->comm]; if (compressMessages) { // Decompress the message before handing it off size_t uncompressedSize = 0; snappy::GetUncompressedLength(reinterpret_cast(msg->data), msg->size, &uncompressedSize); byte_t *uncompressed = (byte_t *)malloc(uncompressedSize); snappy::RawUncompress(reinterpret_cast(msg->data), msg->size, reinterpret_cast(uncompressed)); free(msg->data); msg->data = uncompressed; msg->size = uncompressedSize; } handler->incoming(msg); } } void Context::sendMessagesFromOutbox() { auto outgoingMessages = outbox.consume(); auto outgoingCollectives = collectiveOutbox.consume(); for (auto &msg : outgoingMessages) { MPI_Request request; int rank = 0; MPI_CALL(Comm_rank(msg->comm, &rank)); // Don't send to ourself, just forward to the inbox directly if (rank == msg->rank) { inbox.push_back(std::move(msg)); } else { MPI_CALL(Isend(msg->data, msg->size, MPI_BYTE, msg->rank, msg->tag, msg->comm, &request)); msg->started = high_resolution_clock::now(); pendingSends.push_back(request); sendCache.push_back(std::move(msg)); } } for (auto &col : outgoingCollectives) { col->start(); pendingCollectives.push_back(col); } } void Context::pollForAndRecieveMessages() { for (auto &it : handlers) { MPI_Comm comm = it.first; /* probe if there's something incoming on this handler's comm */ int hasIncoming = 0; MPI_Status status; MPI_CALL(Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, comm, &hasIncoming, &status)); if (hasIncoming) { int size; MPI_CALL(Get_count(&status, MPI_BYTE, &size)); auto msg = std::make_shared(size); msg->rank = status.MPI_SOURCE; msg->tag = status.MPI_TAG; msg->comm = comm; MPI_Request request; MPI_CALL(Irecv( msg->data, size, MPI_BYTE, msg->rank, msg->tag, msg->comm, &request)); msg->started = high_resolution_clock::now(); pendingRecvs.push_back(request); recvCache.push_back(std::move(msg)); } } } void Context::waitOnSomeRequests() { if (!pendingSends.empty() || !pendingRecvs.empty()) { const size_t totalMessages = pendingSends.size() + pendingRecvs.size(); int *done = STACK_BUFFER(int, totalMessages); MPI_Request *mergedRequests = STACK_BUFFER(MPI_Request, totalMessages); for (size_t i = 0; i < totalMessages; ++i) { if (i < pendingSends.size()) { mergedRequests[i] = pendingSends[i]; } else { mergedRequests[i] = pendingRecvs[i - pendingSends.size()]; } } int numDone = 0; MPI_CALL(Testsome( totalMessages, mergedRequests, &numDone, done, MPI_STATUSES_IGNORE)); for (int i = 0; i < numDone; ++i) { size_t msgId = done[i]; if (msgId < pendingSends.size()) { pendingSends[msgId] = MPI_REQUEST_NULL; sendCache[msgId] = nullptr; } else { msgId -= pendingSends.size(); inbox.push_back(std::move(recvCache[msgId])); pendingRecvs[msgId] = MPI_REQUEST_NULL; recvCache[msgId] = nullptr; } } // Clean up anything we sent sendCache.erase(std::remove(sendCache.begin(), sendCache.end(), nullptr), sendCache.end()); pendingSends.erase( std::remove(pendingSends.begin(), pendingSends.end(), MPI_REQUEST_NULL), pendingSends.end()); // Clean up anything we received recvCache.erase(std::remove(recvCache.begin(), recvCache.end(), nullptr), recvCache.end()); pendingRecvs.erase( std::remove(pendingRecvs.begin(), pendingRecvs.end(), MPI_REQUEST_NULL), pendingRecvs.end()); } if (!pendingCollectives.empty()) { pendingCollectives.erase(std::remove_if(pendingCollectives.begin(), pendingCollectives.end(), [](const std::shared_ptr &col) { return col->finished(); }), pendingCollectives.end()); } } void Context::flushRemainingMessages() { while (!pendingRecvs.empty() || !pendingSends.empty() || !pendingCollectives.empty() || !inbox.empty() || !outbox.empty()) { sendMessagesFromOutbox(); pollForAndRecieveMessages(); waitOnSomeRequests(); processInboxMessages(); } } /*! start the service; from this point on maml is free to use MPI calls to send/receive messages; if your MPI library is not thread safe the app should _not_ do any MPI calls until 'stop()' has been called */ void Context::start() { std::lock_guard lock(tasksMutex); if (!isRunning()) { tasksAreRunning = true; auto launchMethod = AsyncLoop::LaunchMethod::AUTO; auto MAML_SPAWN_THREADS = getEnvVar("MAML_SPAWN_THREADS"); if (MAML_SPAWN_THREADS) { launchMethod = MAML_SPAWN_THREADS.value() ? AsyncLoop::LaunchMethod::THREAD : AsyncLoop::LaunchMethod::TASK; } if (!sendReceiveThread.get()) { sendReceiveThread = make_unique( [&]() { sendMessagesFromOutbox(); pollForAndRecieveMessages(); waitOnSomeRequests(); }, launchMethod); } if (!processInboxThread.get()) { processInboxThread = make_unique( [&]() { processInboxMessages(); }, launchMethod); } sendReceiveThread->start(); processInboxThread->start(); } } bool Context::isRunning() const { return tasksAreRunning; } /*! stops the maml layer; maml will no longer perform any MPI calls; if the mpi layer is not thread safe the app is then free to use MPI calls of its own, but it should not expect that this node receives any more messages (until the next 'start()' call) even if they are already in fligh WILL: Don't actually stop, for reasons described above flush messages */ void Context::stop() { std::lock_guard lock(tasksMutex); if (tasksAreRunning) { quitThreads = true; if (sendReceiveThread) { sendReceiveThread->stop(); } if (processInboxThread) { processInboxThread->stop(); } tasksAreRunning = false; flushRemainingMessages(); } } } // namespace maml RenderKit-ospray-f2a61c2/modules/mpi/common/maml/Context.h000066400000000000000000000073471456566705700236320ustar00rootroot00000000000000// Copyright 2016 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include #include #include "common/Collectives.h" #include "maml.h" #include "rkcommon/containers/TransactionalBuffer.h" #include "rkcommon/tasking/AsyncLoop.h" namespace maml { /*! the singleton object that handles all the communication */ struct OSPRAY_MPI_COMMON_EXPORT Context { Context(bool enableCompression = false); ~Context(); static std::unique_ptr singleton; /*! register a new incoing-message handler. if any message comes in on the given communicator we'll call this handler */ void registerHandlerFor(MPI_Comm comm, MessageHandler *handler); bool isRunning() const; /*! put the given message in the outbox. note that this can be done even if the actual sending mechanism is currently stopped */ void send(std::shared_ptr msg); /*! queue the given collective to be executed */ void queueCollective(std::shared_ptr col); /*! start the service; from this point on maml is free to use MPI calls to send/receive messages; if your MPI library is not thread safe the app should _not_ do any MPI calls until 'stop()' has been called */ void start(); /*! stops the maml layer; maml will no longer perform any MPI calls; if the mpi layer is not thread safe the app is then free to use MPI calls of its own, but it should not expect that this node receives any more messages (until the next 'start()' call) even if they are already in flight */ void stop(); private: // Helper functions // /*! the thread that executes messages that the receiver thread put into the inbox */ void processInboxTask(); void processInboxMessages(); /*! the thread (function) that executes all MPI commands to send/receive messages via MPI. Some notes: - it only looks for incoming messages on communicators for which a handler has been specified. if you don't add a handler to a comm, nothing will ever get received from this comm (you may still send on it, though!) - messages to be sent are retrieved from 'outbox'; messages that are received get put to 'inbox' and the 'inboxcondition' gets triggered. it's another thread's job to execute those messages */ void sendMessagesFromOutbox(); void pollForAndRecieveMessages(); void waitOnSomeRequests(); void flushRemainingMessages(); // Data members // rkcommon::containers::TransactionalBuffer> inbox; rkcommon::containers::TransactionalBuffer> outbox; rkcommon::containers::TransactionalBuffer> collectiveOutbox; // NOTE(jda) - sendCache/pendingSends MUST correspond with each other by // their index in their respective vectors... std::vector> sendCache; std::vector pendingSends; // NOTE(jda) - recvCache/pendingRecvs MUST correspond with each other by // their index in their respective vectors... std::vector> recvCache; std::vector pendingRecvs; std::vector> pendingCollectives; std::map handlers; bool useTaskingSystem{true}; bool compressMessages{false}; // NOTE(jda) - these are only used when _not_ using the tasking system... std::mutex tasksMutex; bool tasksAreRunning{false}; // std::thread sendReceiveThread, processInboxThread; std::atomic quitThreads{false}; std::unique_ptr sendReceiveThread; std::unique_ptr processInboxThread; }; } // namespace maml RenderKit-ospray-f2a61c2/modules/mpi/common/maml/maml.cpp000066400000000000000000000041401456566705700234530ustar00rootroot00000000000000// Copyright 2016 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "maml.h" #include "Context.h" namespace maml { using rkcommon::make_unique; // maml API definitions ///////////////////////////////////////////////////// /*! start the service; from this point on maml is free to use MPI calls to send/receive messages; if your MPI library is not thread safe the app should _not_ do any MPI calls until 'stop()' has been called */ OSPRAY_MPI_COMMON_EXPORT void init(bool enableCompression) { Context::singleton = make_unique(enableCompression); } /*! stops the maml layer; maml will no longer perform any MPI calls; if the mpi layer is not thread safe the app is then free to use MPI calls of its own, but it should not expect that this node receives any more messages (until the next 'start()' call) even if they are already in flight */ OSPRAY_MPI_COMMON_EXPORT void shutdown() { Context::singleton = nullptr; } /*! register a new incoing-message handler. if any message comes in on the given communicator we'll call this handler */ OSPRAY_MPI_COMMON_EXPORT void registerHandlerFor( MPI_Comm comm, MessageHandler *handler) { Context::singleton->registerHandlerFor(comm, handler); } OSPRAY_MPI_COMMON_EXPORT void start() { Context::singleton->start(); } OSPRAY_MPI_COMMON_EXPORT bool isRunning() { return Context::singleton && Context::singleton->isRunning(); } OSPRAY_MPI_COMMON_EXPORT void stop() { Context::singleton->stop(); } /*! send given message to given comm:rank. Once this function has called maml has full ownership of this message, and the user may no longer access it (because maml may delete it at any time) */ OSPRAY_MPI_COMMON_EXPORT void sendTo( MPI_Comm comm, int rank, std::shared_ptr msg) { if (!(rank >= 0 && msg.get())) OSPRAY_THROW("Incorrect argument values given to maml::sendTo(...)"); msg->rank = rank; msg->comm = comm; Context::singleton->send(msg); } OSPRAY_MPI_COMMON_EXPORT void queueCollective(std::shared_ptr col) { Context::singleton->queueCollective(col); } } // namespace maml RenderKit-ospray-f2a61c2/modules/mpi/common/maml/maml.h000066400000000000000000000071531456566705700231270ustar00rootroot00000000000000// Copyright 2016 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include "common/Collectives.h" #include "common/MPICommon.h" namespace maml { using Message = mpicommon::Message; // Only bcast for now, to test using Collective = mpicommon::Collective; /*! abstraction for an object that can receive messages. handlers get associated with MPI_Comm's, and get called automatically every time such a message comes in. maml receives the message, then passed it to the handler, from which point it is owned by - and the respsonsibility of - the handler */ struct OSPRAY_MPI_COMMON_EXPORT MessageHandler { virtual void incoming(const std::shared_ptr &message) = 0; virtual ~MessageHandler() = default; }; /*! initialize the service for this process and start the service; from this point on maml is free to use MPI calls to send/receive messages; if your MPI library is not thread safe the app should _not_ do any MPI calls until 'shutdown()' has been called */ OSPRAY_MPI_COMMON_EXPORT void init(bool enableCompression = false); /*! shutdown the service for this process. stops the maml layer; maml will no longer perform any MPI calls; if the mpi layer is not thread safe the app is then free to use MPI calls of its own, but it should not expect that this node receives any more messages (until the next 'init()' call) even if they are already in flight */ OSPRAY_MPI_COMMON_EXPORT void shutdown(); /*! register a new incoing-message handler. if any message comes in on the given communicator we'll call this handler */ OSPRAY_MPI_COMMON_EXPORT void registerHandlerFor( MPI_Comm comm, MessageHandler *handler); /*! start the service; from this point on maml is free to use MPI calls to send/receive messages; if your MPI library is not thread safe the app should _not_ do any MPI calls until 'stop()' has been called */ OSPRAY_MPI_COMMON_EXPORT void start(); OSPRAY_MPI_COMMON_EXPORT bool isRunning(); /*! stops the maml layer; maml will no longer perform any MPI calls; if the mpi layer is not thread safe the app is then free to use MPI calls of its own, but it should not expect that this node receives any more messages (until the next 'start()' call) even if they are already in flight */ OSPRAY_MPI_COMMON_EXPORT void stop(); /*! schedule the given message to be send to the given comm:rank. comm and rank have to be a valid address. Once this function has been called maml has full ownership of this message, and the user may no longer access it (because maml may delete it at any time). note this message will not be sent immediately if the mpi sending is stopped; it will, however, be placed in the outbox to be sent at the next possible opportunity. If a rank sends a message to itself the MPI communication layer will be skipped, however some cost may be incurred when compressing/decompressing the message and accessing the various inbox/outbox vectors. WARNING: calling flush does NOT guarantee that there's no more messages coming in to this node: it does mean that all the messages we've already MPI_Probe'd will get finished receiving, but it will NOT guarantee that another node(s) aren't just sending out some new message(s) that simply haven't even STARTED arriving on this node, yet!!! */ OSPRAY_MPI_COMMON_EXPORT void sendTo( MPI_Comm comm, int rank, std::shared_ptr msg); /*! Schedule a collective to be run on the messaging layer */ OSPRAY_MPI_COMMON_EXPORT void queueCollective(std::shared_ptr col); } // namespace maml RenderKit-ospray-f2a61c2/modules/mpi/ospray/000077500000000000000000000000001456566705700211215ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/mpi/ospray/CMakeLists.txt000066400000000000000000000151771456566705700236740ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ## Options ## set(OSPRAY_MPI_COMPRESSION_THRESHOLD 16 CACHE STRING "Min. number of ranks to enable message compression at (number)" ) mark_as_advanced(OSPRAY_MPI_COMPRESSION_THRESHOLD) ## Build the MPI Offload module ## add_library(ospray_module_mpi_offload SHARED OffloadModuleInit.cpp MPIOffloadWorker.cpp MPIOffloadDevice.cpp common/OSPWork.cpp common/ApplicationData.cpp ) target_link_libraries(ospray_module_mpi_offload PRIVATE rkcommon::rkcommon ospray_mpi_common ) target_include_directories(ospray_module_mpi_offload PUBLIC $ ) target_compile_definitions(ospray_module_mpi_offload PUBLIC OSP_MPI_COMPRESSION_THRESHOLD=${OSPRAY_MPI_COMPRESSION_THRESHOLD} # We don't want an instance of ObjectFactory static table in this library # so we have to include it with import define so the table will be imported # from 'ospray' library OBJECTFACTORY_IMPORT) ospray_install_library(ospray_module_mpi_offload mpi) ## Build the worker executable ## add_executable(ospray_mpi_worker ${OSPRAY_RESOURCE} mpi_offload_worker_main.cpp) target_link_libraries(ospray_mpi_worker PRIVATE ospray) install(TARGETS ospray_mpi_worker DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT mpi) ospray_sign_target(ospray_mpi_worker) ## Build the MPI Distributed CPU module ## set(OSPRAY_MPI_DISTRIBUTED_CPP_SOURCES ${OSPRAY_RESOURCE} MPIDistributedDevice.cpp DistributedModuleInit.cpp common/DistributedWorld.cpp common/Messaging.cpp common/DynamicLoadBalancer.cpp fb/DistributedFrameBuffer.cpp fb/DistributedFrameBuffer_TileMessages.cpp fb/TileOperation.cpp render/DistributedLoadBalancer.cpp render/WriteMultipleTileOperation.cpp render/distributed/DistributedRaycast.cpp render/distributed/DistributedRenderer.cpp render/distributed/AlphaCompositeTileOperation.cpp ) set(OSPRAY_MPI_DISTRIBUTED_ISPC_SOURCES MPIDistributedDevice.ispc fb/DistributedFrameBuffer.ispc render/distributed/DistributedRaycast.ispc render/distributed/DistributedRenderer.ispc ) include_directories_ispc( ${PROJECT_SOURCE_DIR}/ospray/include ${PROJECT_SOURCE_DIR}/ospray ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${RKCOMMON_INCLUDE_DIRS} ${EMBREE_INCLUDE_DIRS} ) add_definitions_ispc( -DOSPRAY_BEGIN_ISPC_NAMESPACE= -DOSPRAY_END_ISPC_NAMESPACE= -DSYCL_EXTERNAL= ) if (OSPRAY_ENABLE_VOLUMES) include_directories_ispc( ${OPENVKL_INCLUDE_DIRS} ) # Keep the NOTFOUND out of the ISPC include dirs list, because CMake will # see the variable ending with NOTFOUND and evaluate it to false and not # pass our include directories if (OPENVKL_CPU_DEVICE_INCLUDE_DIRS) include_directories_ispc( ${OPENVKL_CPU_DEVICE_INCLUDE_DIRS} ) endif() add_definitions_ispc( -DOSPRAY_ENABLE_VOLUMES ) endif() add_library(ospray_module_mpi_distributed_cpu SHARED) ispc_target_add_sources(ospray_module_mpi_distributed_cpu ${OSPRAY_MPI_DISTRIBUTED_CPP_SOURCES} ${OSPRAY_MPI_DISTRIBUTED_ISPC_SOURCES} ) target_link_libraries(ospray_module_mpi_distributed_cpu PRIVATE Snappy::snappy rkcommon::rkcommon ospray_mpi_common ospray_module_cpu ) target_include_directories(ospray_module_mpi_distributed_cpu PUBLIC $ $ PRIVATE ${CMAKE_CURRENT_BINARY_DIR} # For ISPC module generated ispc headers ${PROJECT_BINARY_DIR}/ospray/ ) # Note: GPU hybrid code defines are brought in for us by linking the CPU module target_compile_definitions(ospray_module_mpi_distributed_cpu PRIVATE OSP_MPI_COMPRESSION_THRESHOLD=${OSPRAY_MPI_COMPRESSION_THRESHOLD} # We don't want an instance of ObjectFactory static table in this library # so we have to include it with import define so the table will be imported # from 'ospray' library OBJECTFACTORY_IMPORT ) ospray_install_library(ospray_module_mpi_distributed_cpu mpi) ## Build the MPI Distributed GPU module ## if (OSPRAY_MODULE_GPU) include(${ISPCRT_DIR}/interop.cmake) # Have CMake's build infrastructure treat the ISPC files as C++ for SYCL set_source_files_properties(${OSPRAY_MPI_DISTRIBUTED_ISPC_SOURCES} PROPERTIES LANGUAGE CXX) add_library(ospray_module_mpi_distributed_gpu_kernels OBJECT ${OSPRAY_MPI_DISTRIBUTED_ISPC_SOURCES} ) target_link_libraries(ospray_module_mpi_distributed_gpu_kernels PRIVATE ospray_module_gpu_kernels ) target_include_directories(ospray_module_mpi_distributed_gpu_kernels PUBLIC $ $ PRIVATE ${CMAKE_CURRENT_BINARY_DIR} # For ISPC module generated ispc headers ${PROJECT_BINARY_DIR}/ospray/ ) if (OSPRAY_COMPILER_NEEDS_X_CPP) target_compile_options(ospray_module_mpi_distributed_gpu_kernels PRIVATE -x c++) endif() target_compile_options(ospray_module_mpi_distributed_gpu_kernels PRIVATE -g0 # XXX debug on device broken -Wdouble-promotion ) # Install and export without DESTINATION to turn it into INTERFACE library install(TARGETS ospray_module_mpi_distributed_gpu_kernels EXPORT ospray_Exports) add_library(ospray_module_mpi_distributed_gpu SHARED ${OSPRAY_MPI_DISTRIBUTED_CPP_SOURCES} ) # Note: GPU hybrid code defines are brought in for us by linking the CPU module target_compile_definitions(ospray_module_mpi_distributed_gpu PRIVATE OSP_MPI_COMPRESSION_THRESHOLD=${OSPRAY_MPI_COMPRESSION_THRESHOLD} # We don't want an instance of ObjectFactory static table in this library # so we have to include it with import define so the table will be imported # from 'ospray' library OBJECTFACTORY_IMPORT ) target_link_libraries(ospray_module_mpi_distributed_gpu PUBLIC ospray_module_gpu_kernels ospray_module_mpi_distributed_gpu_kernels PRIVATE Snappy::snappy rkcommon::rkcommon ospray_mpi_common ospray_module_gpu ) ospray_install_library(ospray_module_mpi_distributed_gpu lib) endif() # ------------------------------------------------------- # Install SDK headers # ------------------------------------------------------- get_subdirectories(SUBDIRS ${CMAKE_CURRENT_LIST_DIR}) foreach(dir ${SUBDIRS}) install(DIRECTORY ${dir} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ospray/SDK/modules/mpi COMPONENT devel FILES_MATCHING PATTERN *.h PATTERN *.ih ) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${dir} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ospray/SDK/modules/mpi COMPONENT devel FILES_MATCHING PATTERN *_ispc.h ) endforeach() RenderKit-ospray-f2a61c2/modules/mpi/ospray/DistributedModuleInit.cpp000066400000000000000000000021621456566705700261020ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // We don't want an instance of ObjectFactory static table in this library so // we set OBJECTFACTORY_IMPORT at the CMake build flag level for the module #include "common/ObjectFactory.h" #include "MPIDistributedDevice.h" #include "common/OSPCommon.h" #include "render/distributed/DistributedRaycast.h" extern "C" OSPError OSPRAY_DLLEXPORT #ifdef OSPRAY_TARGET_SYCL ospray_module_init_mpi_distributed_gpu( #else ospray_module_init_mpi_distributed_cpu( #endif int16_t versionMajor, int16_t versionMinor, int16_t /*versionPatch*/) { using namespace ospray; auto status = moduleVersionCheck(versionMajor, versionMinor); if (status == OSP_NO_ERROR) { // Run the CPU/GPU module's initialization function to register local types #ifdef OSPRAY_TARGET_SYCL status = ospLoadModule("gpu"); #else status = ospLoadModule("cpu"); #endif } if (status == OSP_NO_ERROR) { api::Device::registerType("mpiDistributed"); Renderer::registerType("mpiRaycast"); } return status; } RenderKit-ospray-f2a61c2/modules/mpi/ospray/MPIDistributedDevice.cpp000066400000000000000000000456031456566705700256050ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include #include #ifdef _WIN32 #define NOMINMAX #include #else #include #endif #include "ISPCDevice.h" #include "MPIDistributedDevice.h" #include "camera/Camera.h" #include "common/Data.h" #include "common/DistributedWorld.h" #include "common/Group.h" #include "common/Instance.h" #include "common/MPICommon.h" #include "fb/DistributedFrameBuffer.h" #include "geometry/GeometricModel.h" #include "lights/Light.h" #include "render/DistributedLoadBalancer.h" #include "render/Material.h" #include "render/ThreadedRenderTask.h" #include "render/distributed/DistributedRaycast.h" #include "rkcommon/tasking/tasking_system_init.h" #include "rkcommon/tracing/Tracing.h" #include "rkcommon/utility/CodeTimer.h" #include "rkcommon/utility/getEnvVar.h" #ifdef OSPRAY_ENABLE_VOLUMES #include "volume/Volume.h" #include "volume/VolumetricModel.h" #include "volume/transferFunction/TransferFunction.h" #endif namespace ospray { namespace mpi { // Helper functions /////////////////////////////////////////////////////// using SetParamFcn = void(OSPObject, const char *, const void *m, OSPDataType); template static void setParamOnObject( OSPObject _obj, const char *p, const T &v, OSPDataType) { auto *obj = lookupObject(_obj); obj->setParam(p, v); } #define declare_param_setter(TYPE) \ { \ OSPTypeFor::value, \ [](OSPObject o, const char *p, const void *v, OSPDataType t) { \ setParamOnObject(o, p, *(TYPE *)v, t); \ } \ } #define declare_param_setter_object(TYPE) \ { \ OSPTypeFor::value, \ [](OSPObject o, const char *p, const void *v, OSPDataType t) { \ auto *obj = lookupObject( \ *reinterpret_cast(v)); \ setParamOnObject(o, p, obj, t); \ } \ } #define declare_param_setter_string(TYPE) \ { \ OSPTypeFor::value, \ [](OSPObject o, const char *p, const void *v, OSPDataType t) { \ const char *str = (const char *)v; \ setParamOnObject(o, p, std::string(str), t); \ } \ } static std::map> setParamFcns = { declare_param_setter(api::Device *), declare_param_setter(void *), declare_param_setter(bool), declare_param_setter_object(ManagedObject *), declare_param_setter_object(Camera *), declare_param_setter_object(Data *), declare_param_setter_object(FrameBuffer *), declare_param_setter_object(Future *), declare_param_setter_object(Geometry *), declare_param_setter_object(GeometricModel *), declare_param_setter_object(Group *), declare_param_setter_object(ImageOp *), declare_param_setter_object(Instance *), declare_param_setter_object(Light *), declare_param_setter_object(Material *), declare_param_setter_object(Renderer *), declare_param_setter_object(Texture *), #ifdef OSPRAY_ENABLE_VOLUMES declare_param_setter_object(TransferFunction *), declare_param_setter_object(Volume *), declare_param_setter_object(VolumetricModel *), #endif declare_param_setter_object(World *), declare_param_setter_string(const char *), declare_param_setter(char *), declare_param_setter(char), declare_param_setter(vec2c), declare_param_setter(vec3c), declare_param_setter(vec4c), declare_param_setter(unsigned char), declare_param_setter(vec2uc), declare_param_setter(vec3uc), declare_param_setter(vec4uc), declare_param_setter(short), declare_param_setter(vec2s), declare_param_setter(vec3s), declare_param_setter(vec4s), declare_param_setter(unsigned short), declare_param_setter(vec2us), declare_param_setter(vec3us), declare_param_setter(vec4us), declare_param_setter(int), declare_param_setter(vec2i), declare_param_setter(vec3i), declare_param_setter(vec4i), declare_param_setter(unsigned int), declare_param_setter(vec2ui), declare_param_setter(vec3ui), declare_param_setter(vec4ui), declare_param_setter(int64_t), declare_param_setter(vec2l), declare_param_setter(vec3l), declare_param_setter(vec4l), declare_param_setter(uint64_t), declare_param_setter(vec2ul), declare_param_setter(vec3ul), declare_param_setter(vec4ul), declare_param_setter(float), declare_param_setter(vec2f), declare_param_setter(vec3f), declare_param_setter(vec4f), declare_param_setter(double), declare_param_setter(vec2d), declare_param_setter(vec3d), declare_param_setter(vec4d), declare_param_setter(box1i), declare_param_setter(box2i), declare_param_setter(box3i), declare_param_setter(box4i), declare_param_setter(box1f), declare_param_setter(box2f), declare_param_setter(box3f), declare_param_setter(box4f), declare_param_setter(linear2f), declare_param_setter(linear3f), declare_param_setter(affine2f), declare_param_setter(affine3f)}; #undef declare_param_setter template inline API_TYPE createDistributedObject( const char *type, api::ISPCDevice &device, ObjectHandle handle) { auto *instance = OSPRAY_TYPE::createInstance(type, device); handle.assign(instance); return (API_TYPE)(int64)handle; } // MPIDistributedDevice definitions /////////////////////////////////////// MPIDistributedDevice::MPIDistributedDevice() { internalDevice = std::make_shared(); } MPIDistributedDevice::~MPIDistributedDevice() { messaging::shutdown(); if (shouldFinalizeMPI) { try { MPI_CALL(Finalize()); } catch (...) { // Silently move on if finalize fails } } RKCOMMON_IF_TRACING_ENABLED({ char hostname[512] = {0}; gethostname(hostname, 511); const std::string workerTraceFile = std::string(hostname) + "_" + std::to_string(mpicommon::workerRank()) + ".json"; rkcommon::tracing::saveLog( workerTraceFile.c_str(), workerTraceFile.c_str()); }); } static void internalDeviceErrorFunc( void *, const OSPError code, const char *str) { postStatusMsg() << "#OSPRay MPI InternalDevice: internal error " << code << " : " << str; throw std::runtime_error( "OSPRay MPIInternalDevice internal error '" + std::string(str) + "'"); } void MPIDistributedDevice::commit() { Device::commit(); // MPI Device defaults to not setting affinity if (threadAffinity == AUTO_DETECT) { threadAffinity = DEAFFINITIZE; } if (!initialized) { internalDevice->error_fcn = internalDeviceErrorFunc; int _ac = 1; const char *_av[] = {"ospray_mpi_distributed_device"}; auto *setComm = static_cast(getParam("worldCommunicator", nullptr)); shouldFinalizeMPI = mpicommon::init(&_ac, _av, setComm == nullptr); if (setComm) mpicommon::worker.setTo(*setComm); else mpicommon::worker = mpicommon::world; initialized = true; auto OSPRAY_FORCE_COMPRESSION = utility::getEnvVar("OSPRAY_FORCE_COMPRESSION"); // Turning on the compression past 64 ranks seems to be a good // balancing point for cost of compressing vs. performance gain auto enableCompression = OSPRAY_FORCE_COMPRESSION.value_or( mpicommon::workerSize() >= OSP_MPI_COMPRESSION_THRESHOLD); maml::init(enableCompression); messaging::init(mpicommon::worker); maml::start(); RKCOMMON_IF_TRACING_ENABLED({ mpicommon::barrier(mpicommon::worker.comm).wait(); rkcommon::tracing::setMarker("clockSync", "mpiDistributed"); char hostname[512] = {0}; gethostname(hostname, 511); const std::string worker_log_file = std::string(hostname) + "_" + std::to_string(mpicommon::workerRank()) + "_worker_proc_status.txt"; std::ofstream fout(worker_log_file.c_str()); fout << "Worker on '" << hostname << "' /proc/self/status:\n" << rkcommon::tracing::getProcStatus() << "\n"; }); } // Pass down application's GPU selection made via SYCL or L0 (if any) void *appSyclCtx = getParam("syclContext", nullptr); internalDevice->setParam("syclContext", appSyclCtx); void *appSyclDevice = getParam("syclDevice", nullptr); internalDevice->setParam("syclDevice", appSyclDevice); void *appZeCtx = getParam("zeContext", nullptr); internalDevice->setParam("zeContext", appZeCtx); void *appZeDevice = getParam("zeDevice", nullptr); internalDevice->setParam("zeDevice", appZeDevice); internalDevice->commit(); } OSPFrameBuffer MPIDistributedDevice::frameBufferCreate( const vec2i &size, const OSPFrameBufferFormat mode, const uint32 channels) { ObjectHandle handle = allocateHandle(); auto *instance = new DistributedFrameBuffer( *(ospray::api::ISPCDevice *)internalDevice.get(), size, handle, mode, channels); handle.assign(instance); return (OSPFrameBuffer)(int64)handle; } const void *MPIDistributedDevice::frameBufferMap( OSPFrameBuffer _fb, OSPFrameBufferChannel channel) { if (!mpicommon::IamTheMaster()) throw std::runtime_error("Can only map framebuffer on the master!"); auto *fb = lookupDistributedObject(_fb); return fb->mapBuffer(channel); } void MPIDistributedDevice::frameBufferUnmap( const void *mapped, OSPFrameBuffer _fb) { auto *fb = lookupDistributedObject(_fb); fb->unmap(mapped); } void MPIDistributedDevice::resetAccumulation(OSPFrameBuffer _fb) { auto *fb = lookupDistributedObject(_fb); fb->clear(); } OSPGroup MPIDistributedDevice::newGroup() { return internalDevice->newGroup(); } OSPInstance MPIDistributedDevice::newInstance(OSPGroup _group) { return internalDevice->newInstance(_group); } OSPWorld MPIDistributedDevice::newWorld() { ObjectHandle handle = allocateHandle(); auto *instance = new DistributedWorld(*(ospray::api::ISPCDevice *)internalDevice.get()); handle.assign(instance); return (OSPWorld)(int64)(handle); } box3f MPIDistributedDevice::getBounds(OSPObject _obj) { auto *obj = lookupObject(_obj); return internalDevice->getBounds((OSPObject)obj); } OSPData MPIDistributedDevice::newSharedData(const void *sharedData, OSPDataType type, const vec3ul &numItems, const vec3l &byteStride, OSPDeleterCallback freeFunction, const void *userPtr) { return internalDevice->newSharedData( sharedData, type, numItems, byteStride, freeFunction, userPtr); } OSPData MPIDistributedDevice::newData(OSPDataType type, const vec3ul &numItems) { return internalDevice->newData(type, numItems); } void MPIDistributedDevice::copyData( const OSPData source, OSPData destination, const vec3ul &destinationIndex) { internalDevice->copyData(source, destination, destinationIndex); } int MPIDistributedDevice::loadModule(const char *name) { return loadLocalModule(name); } OSPImageOperation MPIDistributedDevice::newImageOp(const char *type) { return internalDevice->newImageOp(type); } OSPRenderer MPIDistributedDevice::newRenderer(const char *type) { ObjectHandle handle = allocateHandle(); return createDistributedObject( type, *(api::ISPCDevice *)internalDevice.get(), handle); } OSPCamera MPIDistributedDevice::newCamera(const char *type) { return internalDevice->newCamera(type); } OSPVolume MPIDistributedDevice::newVolume(const char *type) { #ifdef OSPRAY_ENABLE_VOLUMES return internalDevice->newVolume(type); #else return nullptr; #endif } OSPGeometry MPIDistributedDevice::newGeometry(const char *type) { return internalDevice->newGeometry(type); } OSPGeometricModel MPIDistributedDevice::newGeometricModel(OSPGeometry _geom) { auto *geom = lookupObject(_geom); return internalDevice->newGeometricModel((OSPGeometry)geom); } OSPVolumetricModel MPIDistributedDevice::newVolumetricModel(OSPVolume _vol) { #ifdef OSPRAY_ENABLE_VOLUMES auto *volume = lookupObject(_vol); return internalDevice->newVolumetricModel((OSPVolume)volume); #else return nullptr; #endif } OSPMaterial MPIDistributedDevice::newMaterial(const char *material_type) { return internalDevice->newMaterial(material_type); } OSPTransferFunction MPIDistributedDevice::newTransferFunction(const char *type) { return internalDevice->newTransferFunction(type); } OSPLight MPIDistributedDevice::newLight(const char *type) { return internalDevice->newLight(type); } OSPFuture MPIDistributedDevice::renderFrame(OSPFrameBuffer _fb, OSPRenderer _renderer, OSPCamera _camera, OSPWorld _world) { RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::beginEvent("renderFrame", "MPIDD"); rkcommon::tracing::beginEvent("renderFrame-mpibarrier", "MPIDD"); }); mpicommon::barrier(mpicommon::worker.comm).wait(); RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent("renderFrame-lookupObjects", "MPIDD"); }); auto *fb = lookupDistributedObject(_fb); auto *renderer = lookupDistributedObject(_renderer); auto *camera = lookupObject(_camera); auto *world = lookupObject(_world); RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent("renderFrame-createDLB", "MPIDD"); }); auto loadBalancer = std::make_shared(allocateHandle()); RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); fb->setCompletedEvent(OSP_NONE_FINISHED); fb->refInc(); renderer->refInc(); camera->refInc(); world->refInc(); RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::setMarker("renderFrame-spawnRenderThread", "MPIDD")); auto *f = new ThreadedRenderTask(fb, loadBalancer, [=]() { RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::setThreadName("MPIDD::threadedRenderTask"); rkcommon::tracing::beginEvent("renderFrameTask", "MPIDD"); }); utility::CodeTimer timer; timer.start(); loadBalancer->renderFrame(fb, renderer, camera, world); timer.stop(); RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); fb->refDec(); renderer->refDec(); camera->refDec(); world->refDec(); return timer.seconds(); }); RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); return (OSPFuture)f; } int MPIDistributedDevice::isReady(OSPFuture _task, OSPSyncEvent event) { auto *task = (Future *)_task; return task->isFinished(event); } void MPIDistributedDevice::wait(OSPFuture _task, OSPSyncEvent event) { auto *task = (Future *)_task; task->wait(event); } void MPIDistributedDevice::cancel(OSPFuture _task) { auto *task = (Future *)_task; return task->cancel(); } float MPIDistributedDevice::getProgress(OSPFuture _task) { auto *task = (Future *)_task; return task->getProgress(); } float MPIDistributedDevice::getTaskDuration(OSPFuture _task) { return internalDevice->getTaskDuration(_task); } float MPIDistributedDevice::getVariance(OSPFrameBuffer _fb) { auto *fb = lookupDistributedObject(_fb); return internalDevice->getVariance((OSPFrameBuffer)fb); } void *MPIDistributedDevice::getPostProcessingCommandQueuePtr() { // Run post-processing on internal device only return internalDevice->getPostProcessingCommandQueuePtr(); } void MPIDistributedDevice::setObjectParam( OSPObject object, const char *name, OSPDataType type, const void *mem) { if (type == OSP_UNKNOWN) throw std::runtime_error("cannot set OSP_UNKNOWN parameter type"); if (type == OSP_BYTE || type == OSP_RAW) { setParamOnObject(object, name, *(const byte_t *)mem, type); return; } setParamFcns[type](object, name, mem, type); } void MPIDistributedDevice::removeObjectParam( OSPObject _object, const char *name) { auto *object = lookupObject(_object); return internalDevice->removeObjectParam((OSPObject)object, name); } void MPIDistributedDevice::commit(OSPObject _object) { auto *object = lookupObject(_object); internalDevice->commit((OSPObject)object); } void MPIDistributedDevice::release(OSPObject _obj) { if (!_obj) return; auto &handle = reinterpret_cast(_obj); auto *object = lookupObject(_obj); if (object->useCount() == 1 && handle.defined()) { handle.freeObject(); } object->refDec(); } void MPIDistributedDevice::retain(OSPObject _obj) { auto *object = lookupObject(_obj); object->refInc(); } OSPTexture MPIDistributedDevice::newTexture(const char *type) { return internalDevice->newTexture(type); } OSPPickResult MPIDistributedDevice::pick(OSPFrameBuffer _fb, OSPRenderer _renderer, OSPCamera _camera, OSPWorld _world, const vec2f &screenPos) { auto *fb = lookupDistributedObject(_fb); auto *renderer = lookupDistributedObject(_renderer); auto *camera = lookupObject(_camera); auto *world = lookupObject(_world); return renderer->pick(fb, camera, world, screenPos); } ObjectHandle MPIDistributedDevice::allocateHandle() { mpicommon::barrier(mpicommon::worker.comm).wait(); ObjectHandle handle = ObjectHandle::allocateLocalHandle(); // For debugging check that all ranks did in fact allocate the same handle. // Typically we assume this is the case, as the app should be creating // distributed objects in lock-step, even if their local objects differ. if (logLevel == OSP_LOG_DEBUG) { int maxID = handle.i32.ID; int minID = handle.i32.ID; auto reduceMax = mpicommon::reduce( &handle.i32.ID, &maxID, 1, MPI_INT, MPI_MAX, 0, mpicommon::worker.comm); auto reduceMin = mpicommon::reduce( &handle.i32.ID, &minID, 1, MPI_INT, MPI_MIN, 0, mpicommon::worker.comm); reduceMax.wait(); reduceMin.wait(); if (maxID != minID) { // Log it, but this is a fatal error postStatusMsg( "Error allocating distributed handles: Ranks do not all have the same handle!"); throw std::runtime_error( "Error allocating distributed handles: Ranks do not all have the same handle!"); } } return handle; } } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/MPIDistributedDevice.h000066400000000000000000000102641456566705700252450ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "api/Device.h" #include "common/MPICommon.h" #include "common/Managed.h" #include "common/ObjectHandle.h" #include "render/DistributedLoadBalancer.h" #include "render/LoadBalancer.h" #include "rkcommon/platform.h" namespace ospray { namespace mpi { template inline OSPRAY_TYPE *lookupDistributedObject(OSPObject obj) { auto &handle = reinterpret_cast(obj); auto *object = (OSPRAY_TYPE *)handle.lookup(); if (!object) { throw std::runtime_error("#dmpi: ObjectHandle doesn't exist!"); } return object; } struct MPIDistributedDevice : public api::Device { MPIDistributedDevice(); ~MPIDistributedDevice() override; // ManagedObject Implementation ///////////////////////////////////////// void commit() override; // Device Implementation //////////////////////////////////////////////// /*! create a new frame buffer */ OSPFrameBuffer frameBufferCreate(const vec2i &size, const OSPFrameBufferFormat mode, const uint32 channels) override; /*! create a new transfer function object (out of list of registered transfer function types) */ OSPTransferFunction newTransferFunction(const char *type) override; /*! have given renderer create a new Light */ OSPLight newLight(const char *light_type) override; /*! map frame buffer */ const void *frameBufferMap( OSPFrameBuffer fb, OSPFrameBufferChannel channel) override; /*! unmap previously mapped frame buffer */ void frameBufferUnmap(const void *mapped, OSPFrameBuffer fb) override; /*! create a new ImageOp object (out of list of registered ImageOps) */ OSPImageOperation newImageOp(const char *type) override; void resetAccumulation(OSPFrameBuffer _fb) override; // Instancing /////////////////////////////////////////////////////////// OSPGroup newGroup() override; OSPInstance newInstance(OSPGroup group) override; // Top-level Worlds ///////////////////////////////////////////////////// OSPWorld newWorld() override; box3f getBounds(OSPObject) override; // OSPRay Data Arrays /////////////////////////////////////////////////// OSPData newSharedData(const void *sharedData, OSPDataType, const vec3ul &numItems, const vec3l &byteStride, OSPDeleterCallback, const void *userPtr) override; OSPData newData(OSPDataType, const vec3ul &numItems) override; void copyData(const OSPData source, OSPData destination, const vec3ul &destinationIndex) override; OSPRenderer newRenderer(const char *type) override; OSPGeometry newGeometry(const char *type) override; OSPMaterial newMaterial(const char *material_type) override; OSPCamera newCamera(const char *type) override; OSPVolume newVolume(const char *type) override; OSPGeometricModel newGeometricModel(OSPGeometry geom) override; OSPVolumetricModel newVolumetricModel(OSPVolume volume) override; OSPFuture renderFrame( OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld) override; int isReady(OSPFuture, OSPSyncEvent) override; void wait(OSPFuture, OSPSyncEvent) override; void cancel(OSPFuture) override; float getProgress(OSPFuture) override; float getTaskDuration(OSPFuture) override; float getVariance(OSPFrameBuffer) override; void *getPostProcessingCommandQueuePtr() override; /*! load module */ int loadModule(const char *name) override; // Object + Parameter Lifetime Management /////////////////////////////// void setObjectParam(OSPObject object, const char *name, OSPDataType type, const void *mem) override; void removeObjectParam(OSPObject object, const char *name) override; void commit(OSPObject object) override; void release(OSPObject _obj) override; void retain(OSPObject _obj) override; /*! create a new Texture object */ OSPTexture newTexture(const char *type) override; OSPPickResult pick( OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld, const vec2f &) override; private: ObjectHandle allocateHandle(); bool initialized{false}; bool shouldFinalizeMPI{false}; std::shared_ptr internalDevice = nullptr; }; } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/MPIDistributedDevice.ispc000066400000000000000000000003261456566705700257520ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 OSPRAY_BEGIN_ISPC_NAMESPACE export uniform int MPIDistributedDevice_programCount() { return programCount; } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/mpi/ospray/MPIOffloadDevice.cpp000066400000000000000000001023031456566705700246640ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifndef _WIN32 #include #include #endif #ifdef OPEN_MPI #include #include #endif #include "MPIOffloadDevice.h" #include "common/Library.h" #include "common/MPIBcastFabric.h" #include "common/MPICommon.h" #include "common/OSPWork.h" #include "common/maml/maml.h" #include "rkcommon/networking/DataStreaming.h" #include "rkcommon/tracing/Tracing.h" #include "rkcommon/utility/ArrayView.h" #include "rkcommon/utility/FixedArrayView.h" #include "rkcommon/utility/OwnedArray.h" #include "rkcommon/utility/getEnvVar.h" namespace ospray { namespace mpi { using namespace mpicommon; using namespace rkcommon; /////////////////////////////////////////////////////////////////////////// // Forward declarations /////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// //! this runs an ospray worker process. /*! it's up to the proper init routine to decide which processes call this function and which ones don't. This function will not return. */ void runWorker(bool useMPIFabric, MPIOffloadDevice *offloadDevice); /////////////////////////////////////////////////////////////////////////// // Misc helper functions ////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// static inline void throwIfNotMpiParallel() { if (world.size <= 1) { throw std::runtime_error( "No MPI workers found.\n#osp:mpi: Fatal Error " "- OSPRay told to run in MPI mode, but there " "seems to be no MPI peers!?\n#osp:mpi: (Did " "you forget an 'mpirun' in front of your " "application?)"); } } static inline void setupMaster() { MPI_Comm appComm; MPI_CALL(Comm_split(world.comm, 1, world.rank, &appComm)); int size = 0; int rank = 0; MPI_Comm_size(appComm, &size); MPI_Comm_rank(appComm, &rank); postStatusMsg(OSP_LOG_INFO) << "#w: app process " << rank << '/' << size << " (global " << world.rank << '/' << world.size << ')'; MPI_CALL(Barrier(world.comm)); MPI_CALL(Comm_free(&appComm)); // ------------------------------------------------------- // at this point, all processes should be set up and synced. in // particular: // - app has intracommunicator to all workers (and vica versa) // - app process(es) are in one intercomm ("app"); workers all in // another ("worker") // - all processes (incl app) have barrier'ed, and thus now in sync. } static inline void setupWorker() { MPI_CALL(Comm_split(world.comm, 0, world.rank, &worker.comm)); worker.makeIntraComm(); postStatusMsg(OSP_LOG_INFO) << "master: Made 'worker' intercomm (through split): " << std::hex << std::showbase << worker.comm << std::noshowbase << std::dec; MPI_CALL(Barrier(world.comm)); // ------------------------------------------------------- // at this point, all processes should be set up and synced. in // particular: // - app has intracommunicator to all workers (and vica versa) // - app process(es) are in one intercomm ("app"); workers all in // another ("worker") // - all processes (incl app) have barrier'ed, and thus now in sync. } /////////////////////////////////////////////////////////////////////////// // MPI initialization helper functions //////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /*! TODO WILL: Update these comments in this mode ("ospray on ranks" mode, or "ranks" mode), the user has launched the app across all ranks using mpirun " "; no new processes need to get launched. Based on the 'startworkers' flag, this function can set up ospray in one of two modes: in "workers" mode (startworkers=true) all ranks > 0 become workers, and will NOT return to the application; rank 0 is the master that controls those workers but doesn't do any rendering (we may at some point allow the master to join in working as well, but currently this is not implemented). to reach that mode we call this function with 'startworkers=true', which will make sure that, even though all ranks _called_ mpiinit, only rank 0 will ever return to the app, while all other ranks will automatically go to running worker code, and never ever return from this function. b) in "distributed" mode the app itself is distributed, and will use the ospray distributed api to control ospray in a data-distributed mode. in this way, we'll call this function with startWorkers=false, which will let all ranks return from this function to do further work in the app. For this function, we assume: - all *all* MPI_COMM_WORLD processes are going into this function - this fct is called from ospInit (with ranksBecomeWorkers=true) or from ospdMpiInit (w/ ranksBecomeWorkers = false) */ void createMPI_RanksBecomeWorkers( int *ac, const char **av, MPIOffloadDevice *offloadDevice) { mpi::init(ac, av, true); postStatusMsg(OSP_LOG_INFO) << "#o: initMPI::OSPonRanks: " << world.rank << '/' << world.size; // Note: here we don't run this collective through MAML, since we // haven't started it yet. MPI_CALL(Barrier(world.comm)); RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::setMarker("clockSync", "mpiOffload")); throwIfNotMpiParallel(); if (world.rank == 0) setupMaster(); else { setupWorker(); // now, all workers will enter their worker loop (ie, they will *not* // return) mpi::runWorker(true, offloadDevice); throw std::runtime_error("should never reach here!"); /* no return here - 'runWorker' will never return */ } } void createMPI_ListenForClient( int *ac, const char **av, MPIOffloadDevice *offloadDevice) { mpi::init(ac, av, true); if (world.rank == 0) { postStatusMsg(OSP_LOG_INFO) << "#o: Initialize OSPRay MPI in 'Listen for Client' Mode"; } worker.comm = world.comm; worker.makeIntraComm(); mpi::runWorker(false, offloadDevice); } /////////////////////////////////////////////////////////////////////////// // MPIDevice definitions ////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// MPIOffloadDevice::~MPIOffloadDevice() { try { if (dynamic_cast(fabric.get()) && world.rank == 0) { postStatusMsg(OSP_LOG_INFO) << "shutting down mpi device"; sendWork( [](networking::WriteStream &writer) { writer << work::FINALIZE; }, true); fabric = nullptr; maml::shutdown(); MPI_Finalize(); RKCOMMON_IF_TRACING_ENABLED({ char hostname[512] = {0}; gethostname(hostname, 511); const std::string masterTraceFile = std::string(hostname) + "_master.json"; rkcommon::tracing::saveLog( masterTraceFile.c_str(), masterTraceFile.c_str()); }); } } catch (const std::exception &e) { handleError(OSP_UNKNOWN_ERROR, e.what()); } } void MPIOffloadDevice::initializeDevice() { initialized = true; int _ac = 1; const char *_av[] = {"ospray_mpi_worker"}; std::string mode = getParam("mpiMode", "mpi"); if (mode == "mpi") { createMPI_RanksBecomeWorkers(&_ac, _av, this); RKCOMMON_IF_TRACING_ENABLED({ char hostname[512] = {0}; gethostname(hostname, 511); const std::string master_log_file = std::string(hostname) + "_master_proc_status.txt"; std::ofstream fout(master_log_file.c_str()); fout << "Master on '" << hostname << "' /proc/self/status:\n" << rkcommon::tracing::getProcStatus() << "\n"; }); // Only the master returns from this call fabric = rkcommon::make_unique(world, 0); maml::init(false); maml::start(); } else { throw std::runtime_error("Invalid MPI mode!"); } // Setup the command buffer on the app rank maxCommandBufferEntries = getParam("maxCommandBufferEntries", 8192); commandBufferSize = getParam("commandBufferSize", 512) * (1 << 20); maxInlineDataSize = getParam("maxInlineDataSize", 32) * (1 << 20); auto OSPRAY_MPI_MAX_COMMAND_BUFFER_ENTRIES = utility::getEnvVar("OSPRAY_MPI_MAX_COMMAND_BUFFER_ENTRIES"); if (OSPRAY_MPI_MAX_COMMAND_BUFFER_ENTRIES) { maxCommandBufferEntries = OSPRAY_MPI_MAX_COMMAND_BUFFER_ENTRIES.value(); } auto OSPRAY_MPI_COMMAND_BUFFER_SIZE = utility::getEnvVar("OSPRAY_MPI_COMMAND_BUFFER_SIZE"); if (OSPRAY_MPI_COMMAND_BUFFER_SIZE) { commandBufferSize = OSPRAY_MPI_COMMAND_BUFFER_SIZE.value() * (1 << 20); } auto OSPRAY_MPI_MAX_INLINE_DATA_SIZE = utility::getEnvVar("OSPRAY_MPI_MAX_INLINE_DATA_SIZE"); if (OSPRAY_MPI_MAX_INLINE_DATA_SIZE) { maxInlineDataSize = OSPRAY_MPI_MAX_INLINE_DATA_SIZE.value() * (1 << 20); } if (commandBufferSize >= 1.8f * (1 << 30)) { static WarnOnce warn( "Command buffer size must be less than 1.8GB, resetting to 1.8GB"); commandBufferSize = 1.8f * (1 << 30); } if (maxInlineDataSize >= commandBufferSize / 2.f) { static WarnOnce warn( "Max inline data size must be less than half command buffer size"); maxInlineDataSize = std::ceil(commandBufferSize / 2.f); } commandBuffer = networking::FixedBufferWriter(commandBufferSize); } /////////////////////////////////////////////////////////////////////////// // ManagedObject Implementation /////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// void MPIOffloadDevice::commit() { Device::commit(); // MPI Device defaults to not setting affinity if (threadAffinity == AUTO_DETECT) { threadAffinity = DEAFFINITIZE; } if (!initialized) initializeDevice(); } /////////////////////////////////////////////////////////////////////////// // Device Implementation ////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// int MPIOffloadDevice::loadModule(const char *name) { sendWork( [&](networking::WriteStream &writer) { writer << work::LOAD_MODULE << name; }, false); // TODO: Error reporting from the workers return 0; } /////////////////////////////////////////////////////////////////////////// // Renderable Objects ///////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// OSPLight MPIOffloadDevice::newLight(const char *type) { ObjectHandle handle = allocateHandle(); sendWork( [&](networking::WriteStream &writer) { writer << work::NEW_LIGHT << handle.i64 << type; }, false); return (OSPLight)(int64)handle; } OSPCamera MPIOffloadDevice::newCamera(const char *type) { ObjectHandle handle = allocateHandle(); sendWork( [&](networking::WriteStream &writer) { writer << work::NEW_CAMERA << handle.i64 << type; }, false); return (OSPCamera)(int64)handle; } OSPGeometry MPIOffloadDevice::newGeometry(const char *type) { ObjectHandle handle = allocateHandle(); sendWork( [&](networking::WriteStream &writer) { writer << work::NEW_GEOMETRY << handle.i64 << type; }, false); return (OSPGeometry)(int64)handle; } OSPVolume MPIOffloadDevice::newVolume(const char *type) { ObjectHandle handle = allocateHandle(); sendWork( [&](networking::WriteStream &writer) { writer << work::NEW_VOLUME << handle.i64 << type; }, false); return (OSPVolume)(int64)handle; } OSPGeometricModel MPIOffloadDevice::newGeometricModel(OSPGeometry geom) { ObjectHandle handle = allocateHandle(); ObjectHandle geomHandle = (ObjectHandle &)geom; sendWork( [&](networking::WriteStream &writer) { writer << work::NEW_GEOMETRIC_MODEL << handle.i64 << geomHandle.i64; }, false); return (OSPGeometricModel)(int64)handle; } OSPVolumetricModel MPIOffloadDevice::newVolumetricModel(OSPVolume volume) { ObjectHandle handle = allocateHandle(); ObjectHandle volHandle = (ObjectHandle &)volume; sendWork( [&](networking::WriteStream &writer) { writer << work::NEW_VOLUMETRIC_MODEL << handle.i64 << volHandle.i64; }, false); return (OSPVolumetricModel)(int64)handle; } /////////////////////////////////////////////////////////////////////////// // Model Meta-Data //////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// OSPMaterial MPIOffloadDevice::newMaterial(const char *material_type) { ObjectHandle handle = allocateHandle(); sendWork( [&](networking::WriteStream &writer) { writer << work::NEW_MATERIAL << handle.i64 << material_type; }, false); return (OSPMaterial)(int64)handle; } OSPTransferFunction MPIOffloadDevice::newTransferFunction(const char *type) { ObjectHandle handle = allocateHandle(); sendWork( [&](networking::WriteStream &writer) { writer << work::NEW_TRANSFER_FUNCTION << handle.i64 << type; }, false); return (OSPTransferFunction)(int64)handle; } OSPTexture MPIOffloadDevice::newTexture(const char *type) { ObjectHandle handle = allocateHandle(); sendWork( [&](networking::WriteStream &writer) { writer << work::NEW_TEXTURE << handle.i64 << type; }, false); return (OSPTexture)(int64)handle; } /////////////////////////////////////////////////////////////////////////// // Instancing ///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// OSPGroup MPIOffloadDevice::newGroup() { ObjectHandle handle = allocateHandle(); sendWork( [&](networking::WriteStream &writer) { writer << work::NEW_GROUP << handle.i64; }, false); return (OSPGroup)(int64)handle; } OSPInstance MPIOffloadDevice::newInstance(OSPGroup group) { ObjectHandle handle = allocateHandle(); ObjectHandle groupHandle = (ObjectHandle &)group; sendWork( [&](networking::WriteStream &writer) { writer << work::NEW_INSTANCE << handle.i64 << groupHandle.i64; }, false); return (OSPInstance)(int64)handle; } /////////////////////////////////////////////////////////////////////////// // World Manipulation ///////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// OSPWorld MPIOffloadDevice::newWorld() { ObjectHandle handle = allocateHandle(); sendWork( [&](networking::WriteStream &writer) { writer << work::NEW_WORLD << handle.i64; }, false); return (OSPWorld)(int64)handle; } box3f MPIOffloadDevice::getBounds(OSPObject _obj) { const ObjectHandle obj = (ObjectHandle &)_obj; sendWork( [&](networking::WriteStream &writer) { writer << work::GET_BOUNDS << obj; }, true); box3f result; utility::ArrayView view( reinterpret_cast(&result), sizeof(box3f)); fabric->recv(view, rootWorkerRank()); return result; } /////////////////////////////////////////////////////////////////////////// // OSPRay Data Arrays ///////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// OSPData MPIOffloadDevice::newSharedData(const void *sharedData, OSPDataType format, const vec3ul &numItems, const vec3l &byteStride, OSPDeleterCallback freeFunction, const void *userPtr) { ObjectHandle handle = allocateHandle(); this->sharedData[handle.i64] = ApplicationData( sharedData, format, numItems, byteStride, freeFunction, userPtr); sendWork( [&](networking::WriteStream &writer) { // Data on the workers is always compact, so we don't send the stride writer << work::NEW_SHARED_DATA << handle.i64 << format << numItems; sendDataWork(writer, this->sharedData[handle.i64]); }, false); return (OSPData)(int64)handle; } OSPData MPIOffloadDevice::newData(OSPDataType format, const vec3ul &numItems) { ObjectHandle handle = allocateHandle(); sendWork( [&](networking::WriteStream &writer) { writer << work::NEW_DATA << handle.i64 << format << numItems; }, false); return (OSPData)(int64)handle; } void MPIOffloadDevice::copyData( const OSPData source, OSPData destination, const vec3ul &destinationIndex) { const ObjectHandle sourceHandle = (const ObjectHandle &)source; ObjectHandle destinationHandle = (ObjectHandle &)destination; sendWork( [&](networking::WriteStream &writer) { writer << work::COPY_DATA << sourceHandle.i64 << destinationHandle.i64 << destinationIndex; }, false); } /////////////////////////////////////////////////////////////////////////// // Object + Parameter Lifetime Management ///////////////////////////////// /////////////////////////////////////////////////////////////////////////// void MPIOffloadDevice::setObjectParam( OSPObject object, const char *name, OSPDataType type, const void *mem) { ObjectHandle handle = (ObjectHandle &)object; switch (type) { // All OSP_OBJECT fall through the same style of setting param since it's // just a handle case OSP_DEVICE: case OSP_OBJECT: case OSP_CAMERA: case OSP_DATA: case OSP_FRAMEBUFFER: case OSP_FUTURE: case OSP_GEOMETRIC_MODEL: case OSP_GEOMETRY: case OSP_GROUP: case OSP_IMAGE_OPERATION: case OSP_INSTANCE: case OSP_LIGHT: case OSP_MATERIAL: case OSP_RENDERER: case OSP_TEXTURE: case OSP_TRANSFER_FUNCTION: case OSP_VOLUME: case OSP_VOLUMETRIC_MODEL: case OSP_WORLD: setParam(handle, name, mem, type); break; case OSP_BOOL: setParam(handle, name, mem, type); break; case OSP_STRING: { sendWork( [&](networking::WriteStream &writer) { writer << work::SET_PARAM << handle.i64 << name << type << (const char *)mem; }, false); break; } case OSP_CHAR: case OSP_BYTE: setParam(handle, name, mem, type); break; case OSP_VEC2UC: setParam(handle, name, mem, type); break; case OSP_VEC3UC: setParam(handle, name, mem, type); break; case OSP_VEC4UC: setParam(handle, name, mem, type); break; case OSP_SHORT: setParam(handle, name, mem, type); break; // Will note: looks like ushort is missing in ispcdevice case OSP_USHORT: setParam(handle, name, mem, type); break; case OSP_INT: setParam(handle, name, mem, type); break; case OSP_VEC2I: setParam(handle, name, mem, type); break; case OSP_VEC3I: setParam(handle, name, mem, type); break; case OSP_VEC4I: setParam(handle, name, mem, type); break; case OSP_UINT: setParam(handle, name, mem, type); break; case OSP_VEC2UI: setParam(handle, name, mem, type); break; case OSP_VEC3UI: setParam(handle, name, mem, type); break; case OSP_VEC4UI: setParam(handle, name, mem, type); break; case OSP_LONG: setParam(handle, name, mem, type); break; case OSP_VEC2L: setParam(handle, name, mem, type); break; case OSP_VEC3L: setParam(handle, name, mem, type); break; case OSP_VEC4L: setParam(handle, name, mem, type); break; case OSP_ULONG: setParam(handle, name, mem, type); break; case OSP_VEC2UL: setParam(handle, name, mem, type); break; case OSP_VEC3UL: setParam(handle, name, mem, type); break; case OSP_VEC4UL: setParam(handle, name, mem, type); break; case OSP_FLOAT: setParam(handle, name, mem, type); break; case OSP_VEC2F: setParam(handle, name, mem, type); break; case OSP_VEC3F: setParam(handle, name, mem, type); break; case OSP_VEC4F: setParam(handle, name, mem, type); break; case OSP_DOUBLE: setParam(handle, name, mem, type); break; case OSP_BOX1I: setParam(handle, name, mem, type); break; case OSP_BOX2I: setParam(handle, name, mem, type); break; case OSP_BOX3I: setParam(handle, name, mem, type); break; case OSP_BOX4I: setParam(handle, name, mem, type); break; case OSP_BOX1F: setParam(handle, name, mem, type); break; case OSP_BOX2F: setParam(handle, name, mem, type); break; case OSP_BOX3F: setParam(handle, name, mem, type); break; case OSP_BOX4F: setParam(handle, name, mem, type); break; case OSP_LINEAR2F: setParam(handle, name, mem, type); break; case OSP_LINEAR3F: setParam(handle, name, mem, type); break; case OSP_AFFINE2F: setParam(handle, name, mem, type); break; case OSP_AFFINE3F: setParam(handle, name, mem, type); break; default: throw std::runtime_error("Unrecognized param type!"); } } void MPIOffloadDevice::removeObjectParam(OSPObject object, const char *name) { const ObjectHandle handle = (const ObjectHandle &)object; sendWork( [&](networking::WriteStream &writer) { writer << work::REMOVE_PARAM << handle.i64 << name; }, false); } void MPIOffloadDevice::commit(OSPObject _object) { const ObjectHandle handle = (const ObjectHandle &)_object; auto d = sharedData.find(handle.i64); sendWork( [&](networking::WriteStream &writer) { writer << work::COMMIT << handle.i64 << (d != sharedData.end() ? uint32_t(1) : uint32_t(0)); if (d != sharedData.end()) { writer << d->second.type << d->second.numItems; sendDataWork(writer, d->second); } }, false); } void MPIOffloadDevice::release(OSPObject _object) { const ObjectHandle handle = (const ObjectHandle &)_object; appRefCount[handle.i64]--; // If the app still has references to the object there's no need to // cleanup or send a release command if (appRefCount[handle.i64] > 0) { return; } if (futures.find(handle.i64) != futures.end()) { wait((OSPFuture)_object, OSP_TASK_FINISHED); futures.erase(handle.i64); } sendWork( [&](networking::WriteStream &writer) { writer << work::RELEASE << handle.i64; }, false); // If this object was sharing a data view with the application we need to // make sure the data has been transferred before letting the application // potentially release the buffer. We only need to flush any early data // sends here, since if the data was small enough to inline in the command // buffer we aren't actually sharing the pointer with the app anymore auto d = sharedData.find(handle.i64); if (d != sharedData.end()) { // Make sure there's no pending send referencing this data if we're going // to delete it if (d->second.releaseHazard) { postStatusMsg(OSP_LOG_DEBUG) << "#osp.mpi.app: ospRelease: data reference hazard exists, " << " flushing pending sends"; fabric->flushBcastSends(); } d->second.release(); sharedData.erase(handle.i64); } } void MPIOffloadDevice::retain(OSPObject _obj) { const ObjectHandle handle = (const ObjectHandle &)_obj; appRefCount[handle.i64]++; } /////////////////////////////////////////////////////////////////////////// // FrameBuffer Manipulation /////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// OSPFrameBuffer MPIOffloadDevice::frameBufferCreate( const vec2i &size, const OSPFrameBufferFormat format, const uint32 channels) { ObjectHandle handle = allocateHandle(); sendWork( [&](networking::WriteStream &writer) { writer << work::CREATE_FRAMEBUFFER << handle.i64 << size << (uint32_t)format << channels; }, false); return (OSPFrameBuffer)(int64)handle; } OSPImageOperation MPIOffloadDevice::newImageOp(const char *type) { ObjectHandle handle = allocateHandle(); sendWork( [&](networking::WriteStream &writer) { writer << work::NEW_IMAGE_OPERATION << handle.i64 << type; }, false); return (OSPImageOperation)(int64)handle; } const void *MPIOffloadDevice::frameBufferMap( OSPFrameBuffer _fb, OSPFrameBufferChannel channel) { using namespace utility; RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::beginEvent("mapFramebuffer", "mpiOffloadDevice")); ObjectHandle handle = (ObjectHandle &)_fb; sendWork( [&](networking::WriteStream &writer) { writer << work::MAP_FRAMEBUFFER << handle.i64 << (uint32_t)channel; }, true); uint64_t nbytes = 0; auto bytesView = ArrayView(reinterpret_cast(&nbytes), sizeof(nbytes)); fabric->recv(bytesView, rootWorkerRank()); if (nbytes == 0) { throw std::runtime_error( "Attempt to map framebuffer channel which does not exist!"); } auto mapping = rkcommon::make_unique>(); mapping->resize(nbytes, 0); fabric->recv(*mapping, rootWorkerRank()); void *ptr = mapping->data(); framebufferMappings[handle.i64] = std::move(mapping); RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); return ptr; } void MPIOffloadDevice::frameBufferUnmap(const void *, OSPFrameBuffer _fb) { ObjectHandle handle = (ObjectHandle &)_fb; auto fnd = framebufferMappings.find(handle.i64); if (fnd != framebufferMappings.end()) { framebufferMappings.erase(fnd); } } float MPIOffloadDevice::getVariance(OSPFrameBuffer _fb) { using namespace utility; ObjectHandle handle = (ObjectHandle &)_fb; sendWork( [&](networking::WriteStream &writer) { writer << work::GET_VARIANCE << handle.i64; }, true); float variance = 0; auto view = ArrayView( reinterpret_cast(&variance), sizeof(variance)); fabric->recv(view, rootWorkerRank()); return variance; } void MPIOffloadDevice::resetAccumulation(OSPFrameBuffer _fb) { ObjectHandle handle = (ObjectHandle &)_fb; sendWork( [&](networking::WriteStream &writer) { writer << work::RESET_ACCUMULATION << handle.i64; }, false); } /////////////////////////////////////////////////////////////////////////// // Frame Rendering //////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// OSPRenderer MPIOffloadDevice::newRenderer(const char *type) { ObjectHandle handle = allocateHandle(); sendWork( [&](networking::WriteStream &writer) { writer << work::NEW_RENDERER << handle.i64 << type; }, false); return (OSPRenderer)(int64)handle; } OSPFuture MPIOffloadDevice::renderFrame(OSPFrameBuffer _fb, OSPRenderer _renderer, OSPCamera _camera, OSPWorld _world) { ObjectHandle futureHandle = allocateHandle(); const ObjectHandle fbHandle = (ObjectHandle &)_fb; const ObjectHandle rendererHandle = (ObjectHandle &)_renderer; const ObjectHandle cameraHandle = (ObjectHandle &)_camera; const ObjectHandle worldHandle = (ObjectHandle &)_world; sendWork( [&](networking::WriteStream &writer) { writer << work::RENDER_FRAME << fbHandle << rendererHandle << cameraHandle << worldHandle << futureHandle; }, true); futures.insert(futureHandle.i64); return (OSPFuture)(int64)futureHandle; } int MPIOffloadDevice::isReady(OSPFuture _task, OSPSyncEvent event) { const ObjectHandle handle = (ObjectHandle &)_task; sendWork( [&](networking::WriteStream &writer) { writer << work::FUTURE_IS_READY << handle.i64 << (uint32_t)event; }, true); int result = 0; utility::ArrayView view( reinterpret_cast(&result), sizeof(result)); fabric->recv(view, rootWorkerRank()); return result; } void MPIOffloadDevice::wait(OSPFuture _task, OSPSyncEvent event) { const ObjectHandle handle = (ObjectHandle &)_task; sendWork( [&](networking::WriteStream &writer) { writer << work::FUTURE_WAIT << handle.i64 << (uint32_t)event; }, true); int result = 0; utility::ArrayView view( reinterpret_cast(&result), sizeof(result)); fabric->recv(view, rootWorkerRank()); } void MPIOffloadDevice::cancel(OSPFuture _task) { const ObjectHandle handle = (ObjectHandle &)_task; sendWork( [&](networking::WriteStream &writer) { writer << work::FUTURE_CANCEL << handle.i64; }, true); } float MPIOffloadDevice::getProgress(OSPFuture _task) { const ObjectHandle handle = (ObjectHandle &)_task; sendWork( [&](networking::WriteStream &writer) { writer << work::FUTURE_GET_PROGRESS << handle.i64; }, true); float result = 0; utility::ArrayView view( reinterpret_cast(&result), sizeof(result)); fabric->recv(view, rootWorkerRank()); return result; } float MPIOffloadDevice::getTaskDuration(OSPFuture _task) { const ObjectHandle handle = (ObjectHandle &)_task; sendWork( [&](networking::WriteStream &writer) { writer << work::FUTURE_GET_TASK_DURATION << handle.i64; }, true); float result = 0; utility::ArrayView view( reinterpret_cast(&result), sizeof(result)); fabric->recv(view, rootWorkerRank()); return result; } void *MPIOffloadDevice::getPostProcessingCommandQueuePtr() { // We don't support running external GPU post-processing through // offload device return nullptr; } OSPPickResult MPIOffloadDevice::pick(OSPFrameBuffer fb, OSPRenderer renderer, OSPCamera camera, OSPWorld world, const vec2f &screenPos) { const ObjectHandle fbHandle = (ObjectHandle &)fb; const ObjectHandle rendererHandle = (ObjectHandle &)renderer; const ObjectHandle cameraHandle = (ObjectHandle &)camera; const ObjectHandle worldHandle = (ObjectHandle &)world; sendWork( [&](networking::WriteStream &writer) { writer << work::PICK << fbHandle << rendererHandle << cameraHandle << worldHandle << screenPos; }, true); OSPPickResult result; utility::ArrayView view( reinterpret_cast(&result), sizeof(OSPPickResult)); fabric->recv(view, rootWorkerRank()); return result; } void MPIOffloadDevice::sendDataWork( networking::WriteStream &writer, ApplicationData &appData) { const uint64_t compactSize = appData.size() * sizeOf(appData.type); if (compactSize < maxInlineDataSize) { // Small data gets inline'd into the command buffer writer << (uint32_t)1; if (appData.compact()) { writer.write(appData.data(0), compactSize); } else { auto *sizer = dynamic_cast(&writer); if (sizer) { sizer->write(nullptr, compactSize); } else { // Reserve space and copy the compact data into the buffer auto *bufWriter = dynamic_cast(&writer); appData.compactTo(bufWriter->reserve(compactSize)); } } } else { // For large data we start sending it early as an early data command writer << (uint32_t)0; // Only send the data if we're not doing the size calculation step if (!dynamic_cast(&writer)) { networking::BufferWriter dataTransferCmd; dataTransferCmd << work::DATA_TRANSFER << appData.type << appData.numItems; networking::BufferWriter header; header << dataTransferCmd.buffer->size(); fabric->sendBcast(header.buffer); fabric->sendBcast(dataTransferCmd.buffer); std::shared_ptr> dataView = nullptr; if (appData.compact()) { appData.releaseHazard = true; dataView = appData.sharedData; } else { // Allocate space to store the compact data and compact into it, // we send from this compacted buffer directly auto mem = std::make_shared>(compactSize); appData.compactTo(mem->begin()); dataView = mem; } fabric->sendBcast(dataView); } } } void MPIOffloadDevice::submitWork() { if (commandBuffer.available() == commandBuffer.capacity()) { postStatusMsg(OSP_LOG_ERROR) << "submit on empty command buffer attempted, should not happen!"; return; } auto view = commandBuffer.getWrittenView(); networking::BufferWriter header; header << view->size(); fabric->sendBcast(header.buffer); postStatusMsg(OSP_LOG_DEBUG) << "#osp.mpi.app: submitting buffer with " << nBufferedCommands << " commands, size: " << view->size(); // Make view of the valid set of commands in the buffer and submit them fabric->sendBcast(view); nBufferedCommands = 0; // Write new commands to a new buffer while the previous buffer is sent // out asynchronously commandBuffer = networking::FixedBufferWriter(commandBufferSize); } int MPIOffloadDevice::rootWorkerRank() const { // TODO: we may also want to support MPI intercomm setups w/ comm // accept/connect? return 1; } ObjectHandle MPIOffloadDevice::allocateHandle() { auto handle = ObjectHandle::allocateLocalHandle(); // Assign an app refcount of 1 for new handles appRefCount[handle.i64] = 1; return handle; } } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/MPIOffloadDevice.h000066400000000000000000000160531456566705700243370ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include "api/Device.h" #include "common/ApplicationData.h" #include "common/MPICommon.h" #include "common/OSPWork.h" #include "rkcommon/utility/FixedArray.h" /*! \file MPIDevice.h Implements the "mpi" device for mpi rendering */ namespace ospray { namespace mpi { struct MPIOffloadDevice : public api::Device { MPIOffloadDevice() = default; ~MPIOffloadDevice() override; ///////////////////////////////////////////////////////////////////////// // Device Implementation //////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// void commit() override; int loadModule(const char *name) override; // Renderable Objects /////////////////////////////////////////////////// OSPLight newLight(const char *type) override; OSPCamera newCamera(const char *type) override; OSPGeometry newGeometry(const char *type) override; OSPVolume newVolume(const char *type) override; OSPGeometricModel newGeometricModel(OSPGeometry geom) override; OSPVolumetricModel newVolumetricModel(OSPVolume volume) override; // Model Meta-Data ////////////////////////////////////////////////////// OSPMaterial newMaterial(const char *material_type) override; OSPTransferFunction newTransferFunction(const char *type) override; OSPTexture newTexture(const char *type) override; // Instancing /////////////////////////////////////////////////////////// OSPGroup newGroup() override; OSPInstance newInstance(OSPGroup group) override; // Top-level Worlds ///////////////////////////////////////////////////// OSPWorld newWorld() override; box3f getBounds(OSPObject) override; // OSPRay Data Arrays /////////////////////////////////////////////////// OSPData newSharedData(const void *sharedData, OSPDataType, const vec3ul &numItems, const vec3l &byteStride, OSPDeleterCallback, const void *userPtr) override; OSPData newData(OSPDataType, const vec3ul &numItems) override; void copyData(const OSPData source, OSPData destination, const vec3ul &destinationIndex) override; // Object + Parameter Lifetime Management /////////////////////////////// void setObjectParam(OSPObject object, const char *name, OSPDataType type, const void *mem) override; void removeObjectParam(OSPObject object, const char *name) override; void commit(OSPObject object) override; void release(OSPObject _obj) override; void retain(OSPObject _obj) override; // FrameBuffer Manipulation ///////////////////////////////////////////// OSPFrameBuffer frameBufferCreate(const vec2i &size, const OSPFrameBufferFormat mode, const uint32 channels) override; OSPImageOperation newImageOp(const char *type) override; const void *frameBufferMap( OSPFrameBuffer fb, const OSPFrameBufferChannel) override; void frameBufferUnmap(const void *mapped, OSPFrameBuffer fb) override; float getVariance(OSPFrameBuffer) override; void resetAccumulation(OSPFrameBuffer _fb) override; // Frame Rendering ////////////////////////////////////////////////////// OSPRenderer newRenderer(const char *type) override; OSPFuture renderFrame( OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld) override; int isReady(OSPFuture, OSPSyncEvent) override; void wait(OSPFuture, OSPSyncEvent) override; void cancel(OSPFuture) override; float getProgress(OSPFuture) override; float getTaskDuration(OSPFuture) override; void *getPostProcessingCommandQueuePtr() override; OSPPickResult pick( OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld, const vec2f &) override; private: void initializeDevice(); template void setParam(ObjectHandle obj, const char *param, const void *_val, const OSPDataType tag); /*! Send work will use the write command function to pack the command into the * command buffer. The writeCmd method is called twice, once to compute the * size being written and a second time to output the data to the writer. */ template void sendWork(const Fcn &writeCmd, bool submitImmediately); /*! Send data work should be called by data transfer writeCmd lambdas, to * insert inline data or start the data transfer for large data. If doing * a large data transfer the transfer is started on the second time the * lambda is called (i.e., when writing to the command buffer, not when * computing the size) */ void sendDataWork( rkcommon::networking::WriteStream &writer, ApplicationData &appData); void submitWork(); int rootWorkerRank() const; ObjectHandle allocateHandle(); /*! @{ read and write stream for the work commands */ std::unique_ptr fabric; using FrameBufferMapping = std::unique_ptr>; std::unordered_map framebufferMappings; // Refcount from the app side is managed by appRefCount std::unordered_map sharedData; std::unordered_set futures; /* We track app ref counts locally to reduce how many retain/release commands * we need to send to the worker nodes. This reduces communication costs for * apps using the C++ wrappers or some automatic refcounting wrapper that * calls retain/release a lot. */ std::unordered_map appRefCount; uint32_t maxCommandBufferEntries; uint32_t commandBufferSize; uint32_t maxInlineDataSize; size_t nBufferedCommands = 0; rkcommon::networking::FixedBufferWriter commandBuffer; bool initialized{false}; }; template void MPIOffloadDevice::sendWork(const Fcn &writeCmd, bool submitImmediately) { networking::WriteSizeCalculator sizeCalc; writeCmd(sizeCalc); // Note: curious if this ever happens, with a reasonable command buffer size // (anything >= 1MB) I don't think this should be an issue since commands are // quite small, and limiting the inline data size to be half the command // buffer size should avoid this. if (sizeCalc.writtenSize >= commandBuffer.capacity()) { throw std::runtime_error("Work size is too large for command buffer!"); } if (sizeCalc.writtenSize >= commandBuffer.available()) { submitWork(); } const size_t dbgWriteStart = commandBuffer.cursor; writeCmd(commandBuffer); postStatusMsg(OSP_LOG_DEBUG) << "#osp.mpi.app: buffering command: " << work::tagName(*(reinterpret_cast( commandBuffer.buffer->begin() + dbgWriteStart))); ++nBufferedCommands; if (submitImmediately || nBufferedCommands >= maxCommandBufferEntries) { submitWork(); } } template void MPIOffloadDevice::setParam(ObjectHandle obj, const char *param, const void *_val, const OSPDataType type) { const T &val = *(const T *)_val; sendWork( [&](rkcommon::networking::WriteStream &writer) { writer << work::SET_PARAM << obj.i64 << param << type << val; }, false); } } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/MPIOffloadWorker.cpp000066400000000000000000000112771456566705700247470ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ospray/ospray.h" #include "rkcommon/platform.h" #include #include #include "MPIOffloadDevice.h" #include "common/Library.h" #include "common/MPIBcastFabric.h" #include "common/MPICommon.h" #include "common/OSPWork.h" // Only temporary location for these files anyways #include "rkcommon/tracing/Tracing.h" #include "rkcommon/utility/getEnvVar.h" namespace ospray { namespace mpi { using namespace mpicommon; /*! it's up to the proper init routine to decide which processes call this function and which ones don't. This function will not return. This function takes the offload device that spawned the workers so that it can be cleaned up at exit properly, as the workers are started on commit and do not return back to the application code. ospShutdown is not called as it would unload the shared library with the code and object being used here, and when created explicitly the offload device would not be set as the current device or visible to be cleaned up. \internal We assume that mpi::worker and mpi::app have already been set up */ void runWorker(bool useMPIFabric, MPIOffloadDevice *offloadDevice) { // Nested scope to ensure all OSPRay objects/etc. are cleaned up // before we exit { // We need to remove the offload device so that we call loadLocalModule // directly to load the mpi_distributed module, instead of trying to go // through the offload device's loadModule implementation which would try to // send the command to some "workers". ospSetCurrentDevice(nullptr); auto OSPRAY_MPI_DISTRIBUTED_GPU = utility::getEnvVar("OSPRAY_MPI_DISTRIBUTED_GPU").value_or(0); if (OSPRAY_MPI_DISTRIBUTED_GPU) { ospLoadModule("mpi_distributed_gpu"); } else { ospLoadModule("mpi_distributed_cpu"); } OSPDevice distribDevice = ospNewDevice("mpiDistributed"); ospDeviceSetParam( distribDevice, "worldCommunicator", OSP_VOID_PTR, &worker.comm); ospDeviceCommit(distribDevice); ospSetCurrentDevice(distribDevice); // Release our local reference to the device ospDeviceRelease(distribDevice); RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::beginEvent("start", "mpiOffloadWorker")); std::unique_ptr fabric; if (useMPIFabric) fabric = make_unique(mpicommon::world, 0); else throw std::runtime_error("Invalid non-MPI connection mode"); work::OSPState ospState; uint64_t commandSize = 0; utility::ArrayView cmdView( reinterpret_cast(&commandSize), sizeof(uint64_t)); std::shared_ptr> recvBuffer = std::make_shared>(); RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::setThreadName("main")); bool exitWorker = false; while (!exitWorker) { fabric->recvBcast(cmdView); recvBuffer->resize(commandSize, 0); fabric->recvBcast(*recvBuffer); RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::setCounter("CmdBufSize", commandSize); rkcommon::tracing::beginEvent( "processCommandBuffer", "mpiOffloadWorker"); }); // Read each command in the buffer and execute it networking::BufferReader reader(recvBuffer); while (!reader.end()) { work::TAG workTag = work::NONE; reader >> workTag; RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::setMarker( work::tagName(workTag), "mpiOffloadWorker")); if (workTag == work::FINALIZE) { exitWorker = true; } else { dispatchWork(workTag, ospState, reader, *fabric); } RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::recordMemUse()); } RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::setCounter("CmdBufSize", 0); }); } RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); // The API no longer knows about the offload device and we won't return back // to the app to release it, so we need to free it now offloadDevice->refDec(); // Explicitly release the distributed device by unsetting the current // device, to avoid it attempting to be freed again on exit ospray::api::Device::current = nullptr; } MPI_CALL(Comm_free(&worker.comm)); // The offload device initialized MPI, so the distributed device will see // the "app" as having already initialized MPI and assume it should not call // finalize. So the worker loop must call MPI finalize here as if it was a // distributed app. MPI_CALL(Finalize()); std::exit(0); } } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/OffloadModuleInit.cpp000066400000000000000000000012601456566705700251700ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // We don't want an instance of ObjectFactory static table in this library so // we set OBJECTFACTORY_IMPORT at the CMake build flag level for the module #include "common/ObjectFactory.h" #include "MPIOffloadDevice.h" #include "common/OSPCommon.h" extern "C" OSPError OSPRAY_DLLEXPORT ospray_module_init_mpi_offload( int16_t versionMajor, int16_t versionMinor, int16_t /*versionPatch*/) { using namespace ospray; auto status = moduleVersionCheck(versionMajor, versionMinor); if (status == OSP_NO_ERROR) { api::Device::registerType("mpiOffload"); } return status; } RenderKit-ospray-f2a61c2/modules/mpi/ospray/common/000077500000000000000000000000001456566705700224115ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/mpi/ospray/common/ApplicationData.cpp000066400000000000000000000042141456566705700261530ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ApplicationData.h" #include #include #include "MPICommon.h" #include "common/OSPCommon.h" #include "rkcommon/utility/ArrayView.h" #include "rkcommon/utility/multidim_index_sequence.h" namespace ospray { namespace mpi { ApplicationData::ApplicationData(const void *appData, OSPDataType type, const vec3ul &nItems, const vec3l &bStride, OSPDeleterCallback freeFunction, const void *userData) : type(type), numItems(nItems), byteStride(bStride), freeFunction(freeFunction), userData(userData) { // compute strides if requested if (byteStride.x == 0) byteStride.x = sizeOf(type); if (byteStride.y == 0) byteStride.y = numItems.x * byteStride.x; if (byteStride.z == 0) byteStride.z = numItems.y * byteStride.y; sharedData = std::make_shared>( const_cast(reinterpret_cast(appData)), byteStride.z * numItems.z); } void ApplicationData::release() { if (freeFunction) freeFunction(userData, sharedData->data()); } bool ApplicationData::compact() const { // Compare the last offset using the byte stride vs. the last offset we'd have // if using a compact stride return sharedData->data() + sizeOf(type) * (size() - 1) == data(numItems - 1); } // Copy/Compact the data to the output dst passed. If the data is already // compact this is equivalent to a memcpy. void ApplicationData::compactTo(void *dst) const { if (compact()) { std::memcpy(dst, sharedData->data(), sharedData->size()); } else { // Probably ok with assuming sizeof(void*) == 8b ? I don't think we support // 32bit builds? const size_t typeSize = mpicommon::isManagedObject(type) ? sizeof(int64_t) : sizeOf(type); uint8_t *out = reinterpret_cast(dst); index_sequence_3D srcIndices(numItems); size_t destIdx = 0; for (auto srcIdx : srcIndices) { const uint8_t *src = data(srcIdx); std::memcpy(out + destIdx * typeSize, src, typeSize); ++destIdx; } } } } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/common/ApplicationData.h000066400000000000000000000032711456566705700256220ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include #include #include "ospray/ospray.h" #include "rkcommon/math/vec.h" #include "rkcommon/utility/ArrayView.h" namespace ospray { namespace mpi { using namespace rkcommon; using namespace rkcommon::math; /* The data shared with the application. The workerType may not be the same * as the type of the data, because managed objects are unknown on the * application rank, and are represented just as uint64 handles. Thus the * local data objects see them as OSP_ULONG types, while the worker type * is the true managed object type */ struct ApplicationData { std::shared_ptr> sharedData; OSPDataType type = OSP_UNKNOWN; vec3ul numItems = 0; vec3l byteStride = 0; OSPDeleterCallback freeFunction = nullptr; const void *userData = nullptr; bool releaseHazard = false; ApplicationData() = default; ApplicationData(const void *sharedData, OSPDataType type, const vec3ul &numItems, const vec3l &byteStride, OSPDeleterCallback, const void *userData); void release(); uint8_t *data(const vec3ul &idx) const; size_t size() const; bool compact() const; // Copy/Compact the data to the output dst passed. If the data is already // compact this is equivalent to a memcpy. void compactTo(void *dst) const; }; inline uint8_t *ApplicationData::data(const vec3ul &idx) const { return sharedData->data() + idx.x * byteStride.x + idx.y * byteStride.y + idx.z * byteStride.z; } inline size_t ApplicationData::size() const { return numItems.long_product(); } } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/common/DistributedWorld.cpp000066400000000000000000000140111456566705700264040ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "DistributedWorld.h" #include #include #include "ISPCDevice.h" #include "MPICommon.h" #include "Messaging.h" #include "common/Data.h" namespace ospray { namespace mpi { using namespace rkcommon; DistributedWorld::DistributedWorld(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device), mpiGroup(mpicommon::worker.dup()) { managedObjectType = OSP_WORLD; } DistributedWorld::~DistributedWorld() { MPI_Comm_free(&mpiGroup.comm); } box3f DistributedWorld::getBounds() const { box3f bounds; for (const auto &b : allRegions) { bounds.extend(b); } return bounds; } std::string DistributedWorld::toString() const { return "ospray::mpi::DistributedWorld"; } void DistributedWorld::commit() { World::commit(); allRegions.clear(); myRegions.clear(); myRegionIds.clear(); regionOwners.clear(); localRegions = getParamDataT("region"); if (localRegions) { std::copy(localRegions->begin(), localRegions->end(), std::back_inserter(myRegions)); } else { // Assume we're going to treat everything on this node as a one region, // either for data-parallel rendering or to switch to replicated // rendering box3f localBounds; if (getSh()->super.embreeSceneHandleGeometries) { box4f b; rtcGetSceneBounds( getSh()->super.embreeSceneHandleGeometries, (RTCBounds *)&b); localBounds.extend(box3f(vec3f(b.lower.x, b.lower.y, b.lower.z), vec3f(b.upper.x, b.upper.y, b.upper.z))); } #ifdef OSPRAY_ENABLE_VOLUMES if (getSh()->super.embreeSceneHandleVolumes) { box4f b; rtcGetSceneBounds( getSh()->super.embreeSceneHandleVolumes, (RTCBounds *)&b); localBounds.extend(box3f(vec3f(b.lower.x, b.lower.y, b.lower.z), vec3f(b.upper.x, b.upper.y, b.upper.z))); } #endif myRegions.push_back(localBounds); } // Figure out the unique regions on this node which we can send // to the others to build the distributed world std::sort( myRegions.begin(), myRegions.end(), [](const box3f &a, const box3f &b) { return a.lower < b.lower || (a.lower == b.lower && a.upper < b.upper); }); auto last = std::unique(myRegions.begin(), myRegions.end()); myRegions.erase(last, myRegions.end()); exchangeRegions(); if (regionScene) { rtcReleaseScene(regionScene); regionScene = nullptr; } if (allRegions.size() > 0) { // Setup the boxes geometry which we'll use to leverage Embree for // accurately determining region visibility Data *allRegionsData = new Data(getISPCDevice(), allRegions.data(), OSP_BOX3F, vec3ul(allRegions.size(), 1, 1), vec3l(0)); regionGeometry = new Boxes(getISPCDevice()); regionGeometry->setParam("box", (ManagedObject *)allRegionsData); regionGeometry->commit(); regionScene = rtcNewScene(getISPCDevice().getEmbreeDevice()); rtcAttachGeometry(regionScene, regionGeometry->getEmbreeGeometry()); rtcSetSceneFlags(regionScene, RTC_SCENE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS); rtcCommitScene(regionScene); // Remove the extra local refs regionGeometry->refDec(); allRegionsData->refDec(); } getSh()->localRegions = myRegions.data(); getSh()->numLocalRegions = myRegions.size(); getSh()->numRegions = allRegions.size(); getSh()->regionScene = regionScene; } void DistributedWorld::exchangeRegions() { // Exchange regions between the ranks in world to find which other // ranks may be sharing a region with this one, and the other regions // to expect to be rendered for each tile for (int i = 0; i < mpiGroup.size; ++i) { if (i == mpiGroup.rank) { int nRegions = myRegions.size(); auto sizeBcast = mpicommon::bcast(&nRegions, 1, MPI_INT, i, mpiGroup.comm); int nBytes = nRegions * sizeof(box3f); auto regionBcast = mpicommon::bcast( myRegions.data(), nBytes, MPI_BYTE, i, mpiGroup.comm); for (const auto &b : myRegions) { auto fnd = std::find_if(allRegions.begin(), allRegions.end(), [&](const box3f &r) { return r == b; }); int id = -1; if (fnd == allRegions.end()) { id = allRegions.size(); allRegions.push_back(b); } else { id = std::distance(allRegions.begin(), fnd); } regionOwners[id].insert(i); myRegionIds.push_back(id); } // As we recv/send regions see if they're unique or not sizeBcast.wait(); regionBcast.wait(); } else { int nRegions = 0; mpicommon::bcast(&nRegions, 1, MPI_INT, i, mpiGroup.comm).wait(); std::vector recv; recv.resize(nRegions); int nBytes = nRegions * sizeof(box3f); mpicommon::bcast(recv.data(), nBytes, MPI_BYTE, i, mpiGroup.comm).wait(); for (const auto &b : recv) { auto fnd = std::find_if(allRegions.begin(), allRegions.end(), [&](const box3f &r) { return r == b; }); int id = -1; if (fnd == allRegions.end()) { id = allRegions.size(); allRegions.push_back(b); } else { id = std::distance(allRegions.begin(), fnd); } regionOwners[id].insert(i); } } } if (logLevel() >= OSP_LOG_DEBUG) { StatusMsgStream debugLog; for (int i = 0; i < mpiGroup.size; ++i) { if (i == mpiGroup.rank) { debugLog << "Rank " << mpiGroup.rank << ": All regions in world {\n"; for (const auto &b : allRegions) { debugLog << "\t" << b << ",\n"; } debugLog << "}\n\n"; debugLog << "Ownership Information: {\n"; for (const auto &r : regionOwners) { debugLog << "(" << r.first << ": ["; for (const auto &i : r.second) { debugLog << i << ", "; } debugLog << "])\n"; } debugLog << "\n"; } mpicommon::barrier(mpiGroup.comm).wait(); } } } } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/common/DistributedWorld.h000066400000000000000000000035731456566705700260640ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include "camera/Camera.h" #include "common/Embree.h" #include "common/MPICommon.h" #include "common/World.h" #include "geometry/Boxes.h" #include "rkcommon/math/box.h" // ispc shared #include "DistributedWorldShared.h" namespace ospray { namespace mpi { /* The distributed world provides the renderer with the view of the local * and distributed objects in the entire scene across the cluster. For * remote objects we only store their bounds and the ID of the rank which * owns them. A region is some "clip box" within the world, which contains * some mix of volumes and geometries to be rendered, with rays clipped * against the bounds of this box. */ struct DistributedWorld : public AddStructShared { DistributedWorld(api::ISPCDevice &device); ~DistributedWorld() override; box3f getBounds() const override; virtual std::string toString() const override; // commit synchronizes the distributed models between processes // so that ranks know how many tiles to expect for sort-last // compositing. virtual void commit() override; private: /* Perform the region bounds exchange among the ranks to build the * distributed view of the world */ void exchangeRegions(); // The communicator to use for collectives in the world mpicommon::Group mpiGroup; public: Ref> localRegions; std::vector myRegions; // The global list of unique regions across all nodes, (including this // one), sorted by region id. std::vector allRegions; std::vector myRegionIds; // The ranks which own each region std::unordered_map> regionOwners; Ref regionGeometry; RTCScene regionScene = nullptr; }; } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/common/DistributedWorldShared.h000066400000000000000000000010131456566705700271760ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/WorldShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct DistributedWorld { World super; box3f *localRegions; int numLocalRegions; int numRegions; RTCScene regionScene; #ifdef __cplusplus DistributedWorld() : localRegions(nullptr), numLocalRegions(0), numRegions(0), regionScene(nullptr) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/mpi/ospray/common/DynamicLoadBalancer.cpp000066400000000000000000000226111456566705700267330ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // This code is for DynamicLoadBalancer using the lifeline scheduling method #include "DynamicLoadBalancer.h" #include #include "Messaging.h" #include "rkcommon/tracing/Tracing.h" #include "rkcommon/utility/ArrayView.h" namespace ospray { namespace mpi { using namespace mpicommon; DynamicLoadBalancer::DynamicLoadBalancer(ObjectHandle myId, int numTasks) : MessageHandler(myId) { activeTasks = numTasks; } void DynamicLoadBalancer::setActiveTasks(int numTasks) { std::lock_guard guard(termMutex); activeTasks = numTasks; } void DynamicLoadBalancer::updateActiveTasks(int term) { std::lock_guard guard(termMutex); activeTasks = activeTasks - term; } int DynamicLoadBalancer::getActiveTasks() { int updatedActiveTasks = 0; { std::lock_guard guard(termMutex); updatedActiveTasks = activeTasks; } return updatedActiveTasks; } void DynamicLoadBalancer::addWork(Work workItem) { std::lock_guard guard(workMutex); workQueue.push_back(workItem); } int DynamicLoadBalancer::getWorkSize() { int workSize; { std::lock_guard guard(workMutex); workSize = workQueue.size(); } return workSize; } Work DynamicLoadBalancer::getWorkItemFront() { Work workItem; std::lock_guard guard(workMutex); workItem.ntasks = workQueue[0].ntasks; workItem.offset = workQueue[0].offset; workItem.ownerRank = workQueue[0].ownerRank; workQueue.pop_front(); return workItem; } Work DynamicLoadBalancer::getWorkItemBack() { std::lock_guard guard(workMutex); Work workItem = workQueue.back(); workQueue.pop_back(); return workItem; } // This function takes the rank id and convert it into coords based on the base // we are using to represent the ranks std::vector DynamicLoadBalancer::rankToCoords( int rank, unsigned int base, unsigned int power) { std::vector result; if (rank >= pow(base, power)) { postStatusMsg(OSP_LOG_DEBUG) << "ERROR: Requested rank (" << rank << ") out of bond. Increase base or power.\n"; return result; } result.resize(power); int left = rank; for (unsigned int i = 0; i < power; i++) { result[i] = left / pow(base, power - i - 1); left -= result[i] * pow(base, power - i - 1); } return result; } // -------------------------------------------------------------------- // This function Takes coords of a rank and returns the rank id int DynamicLoadBalancer::coordsToRank(std::vector &coords, unsigned int base, unsigned int power, int numRanks) { if (coords.size() != power) { postStatusMsg(OSP_LOG_DEBUG) << "ERROR: Coords do not match the requested dimensions.\n"; return -1; } int result = 0; for (unsigned int i = 0; i < power; i++) result += coords[i] * pow(base, power - i - 1); if (numRanks <= result) result -= numRanks; return result; } // -------------------------------------------------------------------- // This function takes the rank coords and compute the lifelines IDs std::vector DynamicLoadBalancer::getLifelineID( std::vector &rankCoords, unsigned base, unsigned int power, int numRanks) { std::vector result; if (rankCoords.size() != power) { return result; } int myLifeLineID; std::vector lifelineCoords(power); // loop over rank lifelines for (unsigned int i = 0; i < power; i++) { // loop over coords of lifeline i for (unsigned int j = 0; j < power; j++) { if (i == j) { if (int(base - 1) <= rankCoords[i]) lifelineCoords[j] = 0; else lifelineCoords[j] = rankCoords[i] + 1; } else lifelineCoords[j] = rankCoords[j]; } myLifeLineID = coordsToRank(lifelineCoords, base, power, numRanks); if (-1 < myLifeLineID) result.push_back(myLifeLineID); } return result; } // This function compute the lifelines of the passed rank std::vector DynamicLoadBalancer::getMyLifeLines( int rank, int numRanks, unsigned int base, unsigned int power) { std::vector ranksCoords = rankToCoords(rank, base, power); std::vector lifelines = getLifelineID(ranksCoords, base, power, numRanks); return lifelines; } // -------------------------------------------------------------------- void DynamicLoadBalancer::incoming( const std::shared_ptr &message) { auto *header = (DynamicLBMessage *)message->data; if (header->type == TERMINATED) { RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::setMarker("TERMINATED", "DynamicLB")); int numTerm = ((DynamicLBTerminatedMessage *)message->data)->numTerm; updateActiveTasks(numTerm); } // TERMINATED else if (header->type == NEED_WORK) { RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::setMarker("NEED_WORK", "DynamicLB")); sendWork(header->senderRank); } // NEED_WORK else if (header->type == RECV_WORK) { RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::setMarker("RECV_WORK", "DynamicLB")); auto *workMsg = (DynamicLBSendWorkMessage *)message->data; int numRecvWork = workMsg->numWorkItems; auto *workItems = (Work *)(message->data + sizeof(DynamicLBSendWorkMessage)); Work myWork; int workSize; for (int i = 0; i < numRecvWork; i++) { myWork.ntasks = workItems[i].ntasks; myWork.offset = workItems[i].offset; myWork.ownerRank = workItems[i].ownerRank; addWork(myWork); } workSize = getWorkSize(); if (1 < workSize) { sendMultiWork(); } } // RECV_WORK else { postStatusMsg(OSP_LOG_ERROR) << "Rank " << workerRank() << " Recv Unknown message\n"; } } // -------------------------------------------------------------------- void DynamicLoadBalancer::requestWork() { RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::setMarker("requestWork", "DynamicLB")); const int msgSize = sizeof(DynamicLBMessage); int base, power; base = 2; float p = log2(workerSize()); if (pow(base, p) - workerSize() == 0) power = p; else power = int(p) + 1; myLifelines = getMyLifeLines(workerRank(), workerSize(), base, power); for (size_t i = 0; i < myLifelines.size(); i++) { if (myLifelines[i] == (unsigned int)workerRank()) continue; else { auto msg = std::make_shared(msgSize); auto *header = reinterpret_cast(msg->data); header->type = NEED_WORK; header->senderRank = workerRank(); mpi::messaging::sendTo(myLifelines[i], myId, msg); } } } // -------------------------------------------------------------------- void DynamicLoadBalancer::sendMultiWork() { std::lock_guard lockThieves(thiefMutex); if (thiefIds.empty()) { return; } // Try to steal as much work as we can for the thieves, while leaving some for // this rank too std::vector stolenWork = getWorkItems([&](size_t workSize) { // +1 here to pretend that this rank is also a thief, so that we leave some // work for it in the queue const size_t workPerRank = workSize / (thiefIds.size() + 1); return workPerRank * thiefIds.size(); }); if (stolenWork.empty()) { return; } RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::setMarker("sendMultiWork", "DynamicLB")); // Each thief will be sent workPerRank work items const size_t workPerThief = stolenWork.size() / thiefIds.size(); size_t nextWorkSet = 0; for (auto &thief : thiefIds) { sendWorkToThief(thief, stolenWork.data() + nextWorkSet, workPerThief); nextWorkSet += workPerThief; } thiefIds.clear(); } // -------------------------------------------------------------------- void DynamicLoadBalancer::sendWork(int thiefID) { if (thiefID != -1 && thiefID != workerRank()) { std::vector stolenWork = getWorkItems([&](size_t workSize) { return workSize / 2; }); if (!stolenWork.empty()) { sendWorkToThief(thiefID, stolenWork.data(), stolenWork.size()); } else { std::lock_guard lockThieves(thiefMutex); thiefIds.insert(thiefID); } } } void DynamicLoadBalancer::sendWorkToThief( int thiefID, const Work *toSend, const size_t numWorkItems) { const int msgSize = sizeof(DynamicLBSendWorkMessage) + numWorkItems * sizeof(Work); auto msg = std::make_shared(msgSize); auto *header = reinterpret_cast(msg->data); header->type = RECV_WORK; header->senderRank = workerRank(); header->numWorkItems = numWorkItems; auto *workItems = reinterpret_cast(msg->data + sizeof(DynamicLBSendWorkMessage)); std::memcpy(workItems, toSend, numWorkItems * sizeof(Work)); mpi::messaging::sendTo(thiefID, myId, msg); } // -------------------------------------------------------------------- void DynamicLoadBalancer::sendTerm(int term) { const int msgSize = sizeof(DynamicLBTerminatedMessage); if (0 < term) { for (int i = 0; i < workerSize(); i++) if (i != workerRank()) { auto msg = std::make_shared(msgSize); auto *header = reinterpret_cast(msg->data); header->type = TERMINATED; header->senderRank = workerRank(); header->numTerm = term; mpi::messaging::sendTo(i, myId, msg); } } } } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/common/DynamicLoadBalancer.h000066400000000000000000000076571456566705700264150ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include #include #include "../common/Messaging.h" namespace ospray { namespace mpi { enum MSG { TERMINATED = 1000, NEED_WORK = 2000, VICTIM_NO_WORK = 3000, RECV_WORK = 4000 }; struct Work { int ntasks = 0; int offset = 0; int ownerRank = -1; }; struct DynamicLBMessage { int type; int senderRank; }; struct DynamicLBTerminatedMessage : DynamicLBMessage { int numTerm; }; struct DynamicLBSendWorkMessage : DynamicLBMessage { int numWorkItems; }; struct DynamicLoadBalancer : public mpi::messaging::MessageHandler { DynamicLoadBalancer(ObjectHandle myHandle, int numTasks); ~DynamicLoadBalancer() override = default; void setActiveTasks(int numTasks); void updateActiveTasks(int term); int getActiveTasks(); void addWork(Work workItem); int getWorkSize(); Work getWorkItemFront(); Work getWorkItemBack(); void requestWork(); void sendTerm(int term); void incoming(const std::shared_ptr &message) override; private: void sendWork(int thiefID); void sendMultiWork(); void sendWorkToThief( int thiefID, const Work *toSend, const size_t numWorkItems); /* Request a variable size number of work items based on the current size of * the workQueue. computeItemsRequested will be called after acquiring the * workMutex to compute the number of items to be returned. * computeItemsRequested should take a size_t and return a size_t representing * the number of items to return. If computeItemsRequested returns 0 or more * than workQueue.size(), an empty vector will be returned */ template std::vector getWorkItems(const Fn computeItemsRequested); /* The number of lifelines is determined using the following formula: base ^ L-1 < #ranks <= base ^ L, where L = number of lifelines for example 8 ranks can be represented as one of the following options: 1- base 2, L = 3: 2 ^ 2 < 8 <= 2 ^ 3 2- base 3, L = 2, 3 ^ 1 < 8 <= 3 ^ 2 3- base 4, L = 2, 4 ^ 1 < 8 <= 4 ^ 2 After choosing the base, rankToCoords creates a virtual cyclic graph, where ranks are the graph nodes, and the coords for each graph node(rank) is represented in that base. The function rankToCoords returns the coords for the passed rank depending on the base and power. For example if the base is 2 and power then the coords are represented in zeros and ones, the power identify the number of digits representing each rank coords, if the power is 3, then the coords are represented as 3 digits. The function coordsToRank, takes the rank coords and return the rank id. */ std::vector rankToCoords( int rank, unsigned int base, unsigned int power); int coordsToRank(std::vector &coords, unsigned int base, unsigned int power, int numRanks); std::vector getLifelineID(std::vector &coords, unsigned base, unsigned int power, int numRanks); std::vector getMyLifeLines( int myRank, int numRanks, unsigned int base, unsigned int power); std::vector myLifelines; std::set thiefIds; std::deque workQueue; int activeTasks; std::mutex termMutex; std::mutex workMutex; std::mutex thiefMutex; }; // struct DynamicLoadBalancer template std::vector DynamicLoadBalancer::getWorkItems( const Fn computeItemsRequested) { std::vector reqWorkItems; std::lock_guard guard(workMutex); const size_t numReqWorkItems = computeItemsRequested(workQueue.size()); if (numReqWorkItems == 0 || numReqWorkItems > workQueue.size()) { return reqWorkItems; } for (size_t i = 0; i < numReqWorkItems; i++) { Work workItem = workQueue.back(); workQueue.pop_back(); reqWorkItems.push_back(workItem); } return reqWorkItems; } } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/common/Messaging.cpp000066400000000000000000000101501456566705700250270ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Messaging.h" #include #include #include "rkcommon/memory/DeletedUniquePtr.h" namespace ospray { namespace mpi { namespace messaging { using namespace mpicommon; using rkcommon::memory::DeletedUniquePtr; using rkcommon::memory::make_deleted_unique; // Internal maml message handler for all of OSPRay ////////////////////// struct ObjectMessageHandler : maml::MessageHandler { virtual ~ObjectMessageHandler() override; void registerMessageListener(int handleObjID, maml::MessageHandler *listener); void removeMessageListener(int handleObjID); void incoming(const std::shared_ptr &message) override; // Data members // // The communicator used for object messages, to avoid conflicting // with other communication mpicommon::Group group; private: std::mutex objectListenersMutex; std::unordered_map objectListeners; }; // Inlined ObjectMessageHandler definitions ///////////////////////////// ObjectMessageHandler::~ObjectMessageHandler() { if (group.comm != MPI_COMM_NULL) { MPI_Comm_free(&group.comm); } } inline void ObjectMessageHandler::registerMessageListener( int handleObjID, maml::MessageHandler *listener) { std::lock_guard lock(objectListenersMutex); if (objectListeners.find(handleObjID) != objectListeners.end()) postStatusMsg() << "WARNING: overwriting an existing listener!"; objectListeners[handleObjID] = listener; } inline void ObjectMessageHandler::removeMessageListener(int handleObjID) { std::lock_guard lock(objectListenersMutex); objectListeners.erase(handleObjID); } inline void ObjectMessageHandler::incoming( const std::shared_ptr &message) { std::lock_guard lock(objectListenersMutex); auto obj = objectListeners.find(message->tag); if (obj != objectListeners.end()) { obj->second->incoming(message); } else { postStatusMsg() << "WARNING: No destination for incoming message " << "with tag " << message->tag << ", size = " << message->size; } } // Singleton instance (hidden) and helper creation function ///////////// static DeletedUniquePtr handler = nullptr; static bool handlerValid = false; // MessageHandler definitions /////////////////////////////////////////// MessageHandler::MessageHandler(ObjectHandle handle) : myId(handle) { registerMessageListener(myId, this); } MessageHandler::~MessageHandler() { removeMessageListener(myId); } // ospray::mpi::messaging definitions /////////////////////////////////// void init(mpicommon::Group parentGroup) { if (handlerValid) throw std::runtime_error("Error: Object Messaging was already init"); Group group = parentGroup.dup(); handler = make_deleted_unique( [](ObjectMessageHandler *_handler) { handlerValid = false; delete _handler; }); handler->group = group; maml::registerHandlerFor(group.comm, handler.get()); handlerValid = true; } void shutdown() { maml::shutdown(); handler = nullptr; } void registerMessageListener(int handleObjID, maml::MessageHandler *listener) { if (!handlerValid) throw std::runtime_error("ObjectMessageHandler was not created!"); handler->registerMessageListener(handleObjID, listener); } void removeMessageListener(int handleObjID) { if (handlerValid) handler->removeMessageListener(handleObjID); } void enableAsyncMessaging() { // TODO WILL: Supporting thread serialized is a pain and I don't // think it's necessary // maml::start(); } void sendTo(int globalRank, ObjectHandle object, std::shared_ptr msg) { #ifdef DEBUG if (!handlerValid) throw std::runtime_error( "ObjMessageHandler must be created before" " sending object messages"); #endif msg->tag = object.objID(); maml::sendTo(handler->group.comm, globalRank, msg); } bool asyncMessagingEnabled() { return maml::isRunning(); } void disableAsyncMessaging() { // maml::stop(); } } // namespace messaging } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/common/Messaging.h000066400000000000000000000024611456566705700245020ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/MPIBcastFabric.h" #include "common/MPICommon.h" #include "common/ObjectHandle.h" #include "maml/maml.h" namespace ospray { namespace mpi { namespace messaging { // message handling base //////////////////////////////////////////////// struct MessageHandler : public maml::MessageHandler { //! NOTE: automatically register/de-registers itself MessageHandler(ObjectHandle handle); virtual ~MessageHandler() override; protected: ObjectHandle myId; }; // async point messaging interface ////////////////////////////////////// /* Register the object message handler and dispatcher to run all object * fire & forget messaging on the specified group. The internal * communicator used will be a dup'd from this group, to avoid * conflicting with other messaging. */ void init(mpicommon::Group parentGroup); void shutdown(); void registerMessageListener(int handleObjID, maml::MessageHandler *listener); void removeMessageListener(int handleObjID); void enableAsyncMessaging(); bool asyncMessagingEnabled(); void sendTo(int globalRank, ObjectHandle object, std::shared_ptr msg); void disableAsyncMessaging(); } // namespace messaging } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/common/OSPWork.cpp000066400000000000000000000632751456566705700244360ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include #include #include "MPICommon.h" #include "OSPWork.h" #include "common/ObjectHandle.h" #include "rkcommon/array3D/for_each.h" #include "rkcommon/memory/RefCount.h" #include "rkcommon/tracing/Tracing.h" #include "rkcommon/utility/AbstractArray.h" #include "rkcommon/utility/ArrayView.h" #include "rkcommon/utility/FixedArray.h" #include "rkcommon/utility/OwnedArray.h" namespace ospray { namespace mpi { namespace work { FrameBufferInfo::FrameBufferInfo( const vec2i &size, OSPFrameBufferFormat format, uint32_t channels) : size(size), format(format), channels(channels) {} size_t FrameBufferInfo::pixelSize(uint32_t channel) const { switch (channel) { case OSP_FB_COLOR: switch (format) { case OSP_FB_RGBA8: case OSP_FB_SRGBA: return sizeof(uint32_t); case OSP_FB_RGBA32F: return sizeof(vec4f); default: return 0; } case OSP_FB_DEPTH: return channels & OSP_FB_DEPTH ? sizeof(float) : 0; case OSP_FB_NORMAL: return channels & OSP_FB_NORMAL ? sizeof(vec3f) : 0; case OSP_FB_ALBEDO: return channels & OSP_FB_ALBEDO ? sizeof(vec3f) : 0; case OSP_FB_ID_PRIMITIVE: return channels & OSP_FB_ID_PRIMITIVE ? sizeof(uint32) : 0; case OSP_FB_ID_OBJECT: return channels & OSP_FB_ID_OBJECT ? sizeof(uint32) : 0; case OSP_FB_ID_INSTANCE: return channels & OSP_FB_ID_INSTANCE ? sizeof(uint32) : 0; default: return 0; } } size_t FrameBufferInfo::getNumPixels() const { return size.x * size.y; } void newRenderer( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; std::string type; cmdBuf >> handle >> type; state.objects[handle] = ospNewRenderer(type.c_str()); } void newWorld( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; cmdBuf >> handle; state.objects[handle] = ospNewWorld(); } void newGeometry( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; std::string type; cmdBuf >> handle >> type; state.objects[handle] = ospNewGeometry(type.c_str()); } void newGeometricModel( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; int64_t geomHandle = 0; cmdBuf >> handle >> geomHandle; state.objects[handle] = ospNewGeometricModel(state.getObject(geomHandle)); } void newVolume( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; std::string type; cmdBuf >> handle >> type; state.objects[handle] = ospNewVolume(type.c_str()); } void newVolumetricModel( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; int64_t volHandle = 0; cmdBuf >> handle >> volHandle; state.objects[handle] = ospNewVolumetricModel(state.getObject(volHandle)); } void newCamera( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; std::string type; cmdBuf >> handle >> type; state.objects[handle] = ospNewCamera(type.c_str()); } void newTransferFunction( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; std::string type; cmdBuf >> handle >> type; state.objects[handle] = ospNewTransferFunction(type.c_str()); } void newImageOperation( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; std::string type; cmdBuf >> handle >> type; state.objects[handle] = ospNewImageOperation(type.c_str()); } void newMaterial( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; std::string type; cmdBuf >> handle >> type; state.objects[handle] = ospNewMaterial(type.c_str()); } void newLight( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; std::string type; cmdBuf >> handle >> type; state.objects[handle] = ospNewLight(type.c_str()); } void dataTransfer(OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &fabric) { using namespace utility; OSPDataType type; vec3ul numItems = 0; cmdBuf >> type >> numItems; auto data = std::make_shared>( array3D::longProduct(numItems) * sizeOf(type)); fabric.recvBcast(*data); state.dataTransfers.push(data); } std::shared_ptr> retrieveData(OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &, const OSPDataType type, const vec3ul numItems) { uint32_t dataInline = 0; cmdBuf >> dataInline; std::shared_ptr> outputData = nullptr; if (dataInline) { const uint64_t nbytes = numItems.x * numItems.y * numItems.z * sizeOf(type); outputData = cmdBuf.getView(nbytes); } else { // All large data is sent before the command buffer using it, and will be // in the state's data transfers list in order by the command referencing it outputData = state.dataTransfers.front(); state.dataTransfers.pop(); } // If the data type is managed we need to convert the handles back into // OSPObjects and increment the refcount because we're populating the data // object manually if (mpicommon::isManagedObject(type)) { for (size_t i = 0; i < array3D::longProduct(numItems); ++i) { uint8_t *addr = outputData->data() + i * sizeOf(type); int64_t *h = reinterpret_cast(addr); OSPObject *obj = reinterpret_cast(addr); *obj = state.objects[*h]; } } return outputData; } void newSharedData(OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &fabric) { using namespace utility; int64_t handle = 0; OSPDataType format = OSP_UNKNOWN; vec3ul numItems = 0; cmdBuf >> handle >> format >> numItems; auto data = retrieveData(state, cmdBuf, fabric, format, numItems); // gives an opportunity to pass off to internal device(s) auto forsubs = ospNewSharedData( data->data(), format, numItems.x, 0, numItems.y, 0, numItems.z, 0); auto subscopy = ospNewData(format, numItems.x, numItems.y, numItems.z); ospCopyData(forsubs, subscopy); ospCommit(subscopy); ospRelease(forsubs); state.objects[handle] = (OSPData)subscopy; } void newData( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; OSPDataType format; vec3ul numItems = 0; cmdBuf >> handle >> format >> numItems; state.objects[handle] = ospNewData(format, numItems.x, numItems.y, numItems.z); } void copyData( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t sourceHandle = 0; int64_t destinationHandle = 0; vec3ul destinationIndex = 0; cmdBuf >> sourceHandle >> destinationHandle >> destinationIndex; ospCopyData(state.getObject(sourceHandle), state.getObject(destinationHandle), destinationIndex.x, destinationIndex.y, destinationIndex.z); } void newTexture( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; std::string type; cmdBuf >> handle >> type; state.objects[handle] = ospNewTexture(type.c_str()); } void newGroup( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; cmdBuf >> handle; state.objects[handle] = ospNewGroup(); } void newInstance( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; int64_t groupHandle = 0; cmdBuf >> handle >> groupHandle; state.objects[handle] = ospNewInstance(state.getObject(groupHandle)); } void commit(OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &fabric) { int64_t handle = 0; uint32_t isSharedData = 0; cmdBuf >> handle >> isSharedData; // If it's a data being committed, we need to retrieve the updated data if (isSharedData) { OSPDataType format = OSP_UNKNOWN; vec3ul numItems = 0; cmdBuf >> format >> numItems; auto data = retrieveData(state, cmdBuf, fabric, format, numItems); auto subscopy = (OSPData)state.objects[handle]; // gives an opportunity to pass off to internal device(s) auto forsubs = ospNewSharedData( data->data(), format, numItems.x, 0, numItems.y, 0, numItems.z, 0); ospCopyData(forsubs, subscopy); ospCommit(subscopy); ospRelease(forsubs); } ospCommit(state.objects[handle]); } void release( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; cmdBuf >> handle; ospRelease(state.objects[handle]); // Note: we keep the handle in the state.objects list as it may be referenced // by other objects in the scene as a parameter or data. // Check if we should release a framebuffer info for this object { auto fnd = state.framebuffers.find(handle); if (fnd != state.framebuffers.end()) { if (fnd->second->useCount() == 1) { state.framebuffers.erase(fnd); } else { fnd->second->refDec(); } } } } // namespace work void retain( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; cmdBuf >> handle; ospRetain(state.objects[handle]); // Mirror the app's ref count for framebuffer info { auto fnd = state.framebuffers.find(handle); if (fnd != state.framebuffers.end()) { fnd->second->refInc(); } } } void loadModule( OSPState &, networking::BufferReader &cmdBuf, networking::Fabric &) { std::string module; cmdBuf >> module; ospLoadModule(module.c_str()); } void createFramebuffer( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; vec2i size(0, 0); uint32_t format; uint32_t channels = 0; cmdBuf >> handle >> size >> format >> channels; state.objects[handle] = ospNewFrameBuffer(size.x, size.y, (OSPFrameBufferFormat)format, channels); Ref fbInfo = new FrameBufferInfo(size, (OSPFrameBufferFormat)format, channels); state.framebuffers[handle] = fbInfo; // Release the local scope ref (see open issue about Ref) fbInfo->refDec(); } void mapFramebuffer(OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &fabric) { RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::beginEvent("mapFramebuffer", "mpiOffloadWorker")); // Map the channel and send the image back over the fabric int64_t handle = 0; uint32_t channel = 0; cmdBuf >> handle >> channel; if (mpicommon::worker.rank == 0) { using namespace utility; const FrameBufferInfo *fbInfo = state.framebuffers[handle].ptr; uint64_t nbytes = fbInfo->pixelSize(channel) * fbInfo->getNumPixels(); auto bytesView = std::make_shared>( reinterpret_cast(&nbytes), sizeof(nbytes)); fabric.send(bytesView, 0); if (nbytes != 0) { OSPFrameBuffer fb = state.getObject(handle); void *map = const_cast( ospMapFrameBuffer(fb, (OSPFrameBufferChannel)channel)); auto fbView = std::make_shared>( reinterpret_cast(map), nbytes); fabric.send(fbView, 0); ospUnmapFrameBuffer(map, fb); } } RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); } void getVariance(OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &fabric) { // Map the channel and send the image back over the fabric int64_t handle = 0; cmdBuf >> handle; if (mpicommon::worker.rank == 0) { using namespace utility; float variance = ospGetVariance(state.getObject(handle)); auto bytesView = std::make_shared>( reinterpret_cast(&variance), sizeof(variance)); fabric.send(bytesView, 0); } } void resetAccumulation( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; cmdBuf >> handle; ospResetAccumulation(state.getObject(handle)); } void renderFrame( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t futureHandle = 0; int64_t fbHandle = 0; int64_t rendererHandle = 0; int64_t cameraHandle = 0; int64_t worldHandle = 0; cmdBuf >> fbHandle >> rendererHandle >> cameraHandle >> worldHandle >> futureHandle; state.objects[futureHandle] = ospRenderFrame(state.getObject(fbHandle), state.getObject(rendererHandle), state.getObject(cameraHandle), state.getObject(worldHandle)); } template void setParam(networking::BufferReader &cmdBuf, OSPObject obj, const std::string ¶m, OSPDataType type) { T val; cmdBuf >> val; ospSetParam(obj, param.c_str(), type, &val); } void setParam( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; std::string param; OSPDataType type; cmdBuf >> handle >> param >> type; // OSP_OBJECT use the same style of setting param since it's just a handle if (mpicommon::isManagedObject(type)) { int64_t val = 0; cmdBuf >> val; ospSetParam( state.objects[handle], param.c_str(), type, &state.objects[val]); } else { switch (type) { case OSP_STRING: { std::string val; cmdBuf >> val; ospSetParam(state.objects[handle], param.c_str(), type, val.c_str()); break; } case OSP_BOOL: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_CHAR: case OSP_BYTE: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC2UC: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC3UC: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC4UC: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_SHORT: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_USHORT: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_INT: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC2I: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC3I: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC4I: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_UINT: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC2UI: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC3UI: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC4UI: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_LONG: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC2L: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC3L: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC4L: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_ULONG: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC2UL: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC3UL: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC4UL: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_FLOAT: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC2F: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC3F: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_VEC4F: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_DOUBLE: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_BOX1I: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_BOX2I: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_BOX3I: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_BOX4I: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_BOX1F: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_BOX2F: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_BOX3F: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_BOX4F: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_LINEAR2F: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_LINEAR3F: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_AFFINE2F: setParam(cmdBuf, state.objects[handle], param, type); break; case OSP_AFFINE3F: setParam(cmdBuf, state.objects[handle], param, type); break; default: throw std::runtime_error("Unrecognized param type!"); } } } void removeParam( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; std::string param; cmdBuf >> handle >> param; ospRemoveParam(state.objects[handle], param.c_str()); } void pick(OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &fabric) { int64_t fbHandle = 0; int64_t rendererHandle = 0; int64_t cameraHandle = 0; int64_t worldHandle = 0; vec2f screenPos; cmdBuf >> fbHandle >> rendererHandle >> cameraHandle >> worldHandle >> screenPos; OSPPickResult res; ospPick(&res, state.getObject(fbHandle), state.getObject(rendererHandle), state.getObject(cameraHandle), state.getObject(worldHandle), screenPos.x, screenPos.y); if (mpicommon::worker.rank == 0) { using namespace utility; auto view = std::make_shared>( reinterpret_cast(&res), sizeof(OSPPickResult)); fabric.send(view, 0); } } void getBounds(OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &fabric) { int64_t handle = 0; cmdBuf >> handle; OSPBounds res = ospGetBounds(state.objects[handle]); if (mpicommon::worker.rank == 0) { using namespace utility; auto view = std::make_shared>( reinterpret_cast(&res), sizeof(OSPBounds)); fabric.send(view, 0); } } void futureIsReady(OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &fabric) { int64_t handle = 0; uint32_t event = 0; cmdBuf >> handle >> event; int ready = ospIsReady(state.getObject(handle), (OSPSyncEvent)event); if (mpicommon::worker.rank == 0) { using namespace utility; auto view = std::make_shared>( reinterpret_cast(&ready), sizeof(ready)); fabric.send(view, 0); } } void futureWait(OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &fabric) { int64_t handle = 0; uint32_t event = 0; cmdBuf >> handle >> event; ospWait(state.getObject(handle), (OSPSyncEvent)event); if (mpicommon::worker.rank == 0) { using namespace utility; auto view = std::make_shared>( reinterpret_cast(&event), sizeof(event)); fabric.send(view, 0); } } void futureCancel( OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &) { int64_t handle = 0; cmdBuf >> handle; ospCancel(state.getObject(handle)); } void futureGetProgress(OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &fabric) { int64_t handle = 0; cmdBuf >> handle; float progress = ospGetProgress(state.getObject(handle)); if (mpicommon::worker.rank == 0) { using namespace utility; auto view = std::make_shared>( reinterpret_cast(&progress), sizeof(progress)); fabric.send(view, 0); } } void futureGetTaskDuration(OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &fabric) { int64_t handle = 0; cmdBuf >> handle; float progress = ospGetTaskDuration(state.getObject(handle)); if (mpicommon::worker.rank == 0) { using namespace utility; auto view = std::make_shared>( reinterpret_cast(&progress), sizeof(progress)); fabric.send(view, 0); } } void dispatchWork(TAG t, OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &fabric) { switch (t) { case NEW_RENDERER: newRenderer(state, cmdBuf, fabric); break; case NEW_WORLD: newWorld(state, cmdBuf, fabric); break; case NEW_GEOMETRY: newGeometry(state, cmdBuf, fabric); break; case NEW_GEOMETRIC_MODEL: newGeometricModel(state, cmdBuf, fabric); break; case NEW_VOLUME: newVolume(state, cmdBuf, fabric); break; case NEW_VOLUMETRIC_MODEL: newVolumetricModel(state, cmdBuf, fabric); break; case NEW_CAMERA: newCamera(state, cmdBuf, fabric); break; case NEW_TRANSFER_FUNCTION: newTransferFunction(state, cmdBuf, fabric); break; case NEW_IMAGE_OPERATION: newImageOperation(state, cmdBuf, fabric); break; case NEW_MATERIAL: newMaterial(state, cmdBuf, fabric); break; case NEW_LIGHT: newLight(state, cmdBuf, fabric); break; case DATA_TRANSFER: dataTransfer(state, cmdBuf, fabric); break; case NEW_SHARED_DATA: newSharedData(state, cmdBuf, fabric); break; case NEW_DATA: newData(state, cmdBuf, fabric); break; case COPY_DATA: copyData(state, cmdBuf, fabric); break; case NEW_TEXTURE: newTexture(state, cmdBuf, fabric); break; case NEW_GROUP: newGroup(state, cmdBuf, fabric); break; case NEW_INSTANCE: newInstance(state, cmdBuf, fabric); break; case COMMIT: commit(state, cmdBuf, fabric); break; case RELEASE: release(state, cmdBuf, fabric); break; case RETAIN: retain(state, cmdBuf, fabric); break; case LOAD_MODULE: loadModule(state, cmdBuf, fabric); break; case CREATE_FRAMEBUFFER: createFramebuffer(state, cmdBuf, fabric); break; case MAP_FRAMEBUFFER: mapFramebuffer(state, cmdBuf, fabric); break; case GET_VARIANCE: getVariance(state, cmdBuf, fabric); break; case RESET_ACCUMULATION: resetAccumulation(state, cmdBuf, fabric); break; case RENDER_FRAME: renderFrame(state, cmdBuf, fabric); break; case SET_PARAM: setParam(state, cmdBuf, fabric); break; case REMOVE_PARAM: removeParam(state, cmdBuf, fabric); break; case PICK: pick(state, cmdBuf, fabric); break; case GET_BOUNDS: getBounds(state, cmdBuf, fabric); break; case FUTURE_IS_READY: futureIsReady(state, cmdBuf, fabric); break; case FUTURE_WAIT: futureWait(state, cmdBuf, fabric); break; case FUTURE_CANCEL: futureCancel(state, cmdBuf, fabric); break; case FUTURE_GET_PROGRESS: futureGetProgress(state, cmdBuf, fabric); break; case FUTURE_GET_TASK_DURATION: futureGetTaskDuration(state, cmdBuf, fabric); break; case NONE: default: throw std::runtime_error("Invalid work tag!"); } } const char *tagName(work::TAG t) { switch (t) { case NEW_RENDERER: return "NEW_RENDERER"; case NEW_WORLD: return "NEW_WORLD"; case NEW_GEOMETRY: return "NEW_GEOMETRY"; case NEW_GEOMETRIC_MODEL: return "NEW_GEOMETRIC_MODEL"; case NEW_VOLUME: return "NEW_VOLUME"; case NEW_VOLUMETRIC_MODEL: return "NEW_VOLUMETRIC_MODEL"; case NEW_CAMERA: return "NEW_CAMERA"; case NEW_TRANSFER_FUNCTION: return "NEW_TRANSFER_FUNCTION"; case NEW_IMAGE_OPERATION: return "NEW_IMAGE_OPERATION"; case NEW_MATERIAL: return "NEW_MATERIAL"; case NEW_LIGHT: return "NEW_LIGHT"; case DATA_TRANSFER: return "DATA_TRANSFER"; case NEW_SHARED_DATA: return "NEW_SHARED_DATA"; case NEW_DATA: return "NEW_DATA"; case COPY_DATA: return "COPY_DATA"; case NEW_TEXTURE: return "NEW_TEXTURE"; case NEW_GROUP: return "NEW_GROUP"; case NEW_INSTANCE: return "NEW_INSTANCE"; case COMMIT: return "COMMIT"; case RELEASE: return "RELEASE"; case RETAIN: return "RETAIN"; case LOAD_MODULE: return "LOAD_MODULE"; case CREATE_FRAMEBUFFER: return "CREATE_FRAMEBUFFER"; case MAP_FRAMEBUFFER: return "MAP_FRAMEBUFFER"; case GET_VARIANCE: return "GET_VARIANCE"; case RESET_ACCUMULATION: return "RESET_ACCUMULATION"; case RENDER_FRAME: return "RENDER_FRAME"; case SET_PARAM: return "SET_PARAM"; case REMOVE_PARAM: return "REMOVE_PARAM"; case PICK: return "PICK"; case GET_BOUNDS: return "GET_BOUNDS"; case FUTURE_IS_READY: return "FUTURE_IS_READY"; case FUTURE_WAIT: return "FUTURE_WAIT"; case FUTURE_CANCEL: return "FUTURE_CANCEL"; case FUTURE_GET_PROGRESS: return "FUTURE_GET_PROGRESS"; case FUTURE_GET_TASK_DURATION: return "FUTURE_GET_TASK_DURATION"; case FINALIZE: return "FINALIZE"; case NONE: default: return "NONE/UNKNOWN/INVALID"; } } } // namespace work } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/common/OSPWork.h000066400000000000000000000042531456566705700240720ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include #include #include #include "MPICommon.h" #include "common/ObjectHandle.h" #include "rkcommon/memory/RefCount.h" #include "rkcommon/networking/DataStreaming.h" #include "rkcommon/networking/Fabric.h" #include "rkcommon/platform.h" #include "rkcommon/utility/ArrayView.h" #include "rkcommon/utility/FixedArray.h" namespace ospray { namespace mpi { namespace work { using namespace rkcommon; enum TAG { NONE, NEW_RENDERER, NEW_WORLD, NEW_GEOMETRY, NEW_GEOMETRIC_MODEL, NEW_VOLUME, NEW_VOLUMETRIC_MODEL, NEW_CAMERA, NEW_TRANSFER_FUNCTION, NEW_IMAGE_OPERATION, NEW_MATERIAL, NEW_LIGHT, DATA_TRANSFER, NEW_SHARED_DATA, NEW_DATA, COPY_DATA, NEW_TEXTURE, NEW_GROUP, NEW_INSTANCE, COMMIT, RELEASE, RETAIN, LOAD_MODULE, CREATE_FRAMEBUFFER, MAP_FRAMEBUFFER, GET_VARIANCE, RESET_ACCUMULATION, RENDER_FRAME, SET_PARAM, REMOVE_PARAM, PICK, GET_BOUNDS, FUTURE_IS_READY, FUTURE_WAIT, FUTURE_CANCEL, FUTURE_GET_PROGRESS, FUTURE_GET_TASK_DURATION, FINALIZE }; struct FrameBufferInfo : rkcommon::memory::RefCountedObject { vec2i size = vec2i(0, 0); OSPFrameBufferFormat format = OSP_FB_NONE; uint32_t channels = 0; FrameBufferInfo() = default; FrameBufferInfo( const vec2i &size, OSPFrameBufferFormat format, uint32_t channels); size_t pixelSize(uint32_t channel) const; size_t getNumPixels() const; }; struct OSPState { std::unordered_map objects; std::unordered_map> framebuffers; // Large data which is transferred separately from the command buffer, // prior to sending the command buffer std::queue>> dataTransfers; template T getObject(int64_t handle) { return reinterpret_cast(objects[handle]); } }; void dispatchWork(TAG t, OSPState &state, networking::BufferReader &cmdBuf, networking::Fabric &fabric); const char *tagName(work::TAG t); } // namespace work } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/fb/000077500000000000000000000000001456566705700215105ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/mpi/ospray/fb/DistributedFrameBuffer.cpp000066400000000000000000000654631456566705700266210ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "DistributedFrameBuffer.h" #include "DistributedFrameBuffer_TileMessages.h" #include "ISPCDevice.h" #include "TileOperation.h" #include "fb/FrameBufferView.h" #include "rkcommon/tracing/Tracing.h" #ifndef OSPRAY_TARGET_SYCL #include "fb/DistributedFrameBuffer_ispc.h" #endif #include "rkcommon/tasking/parallel_for.h" #include "rkcommon/tasking/schedule.h" #include "api/Device.h" #include "common/Collectives.h" #include "common/MPICommon.h" #include #include #include using namespace std::chrono; namespace ospray { // Helper types ///////////////////////////////////////////////////////////// using DFB = DistributedFrameBuffer; // DistributedTileError definitions ///////////////////////////////////////// DistributedTileError::DistributedTileError( api::ISPCDevice &device, const vec2i &numTiles, mpicommon::Group group) : TaskError(device.getIspcrtContext(), numTiles), group(group) {} void DistributedTileError::sync() { if (!taskErrorBuffer || taskErrorBuffer->size() == 0) { return; } // TODO: USM thrashing possible issue mpicommon::bcast(taskErrorBuffer->data(), taskErrorBuffer->size(), MPI_FLOAT, 0, group.comm) .wait(); } // DistributedFrameBuffer definitions /////////////////////////////////////// DFB::DistributedFrameBuffer(api::ISPCDevice &device, const vec2i &numPixels, ObjectHandle myId, ColorBufferFormat colorBufferFormat, const uint32 channels) // TODO WILL: The DFB should use a separate identifier than myID // since large scenes can push this ID beyond the max value we can use // for MPI Tag (i.e., Moana). The IDs for the message handler should not // be set from the object handle but pulled from some other ID pool // specific to those objects using the messaging layer : MessageHandler(myId), FrameBuffer(device, numPixels, colorBufferFormat, channels, FFO_NONE), mpiGroup(mpicommon::worker.dup()), totalTiles(divRoundUp(size, vec2i(TILE_SIZE))), numRenderTasks((totalTiles * TILE_SIZE) / getRenderTaskSize()), tileErrorRegion( device, hasVarianceBuffer ? totalTiles : vec2i(0), mpiGroup), localFBonMaster(nullptr), frameIsActive(false), frameIsDone(false) { if (mpicommon::IamTheMaster() && colorBufferFormat != OSP_FB_NONE) { localFBonMaster = rkcommon::make_unique(device, numPixels, colorBufferFormat, channels & ~(OSP_FB_ACCUM | OSP_FB_VARIANCE)); } } DFB::~DistributedFrameBuffer() { MPI_Comm_free(&mpiGroup.comm); } void DFB::commit() { FrameBuffer::commit(); if (localFBonMaster) { // We need image operations to be added to inner local FB as well, the local // FB possess complete image and is responsible for post-processing // execution if (hasParam("imageOperation")) localFBonMaster->setParam("imageOperation", static_cast(getParamObject("imageOperation"))); localFBonMaster->commit(); } } mpicommon::Group DFB::getMPIGroup() { return mpiGroup; } void DFB::startNewFrame(const float errorThreshold) { { std::lock_guard lock(finalTileBufferMutex); nextTileWrite = 0; tileBufferOffsets.clear(); } if (colorBufferFormat != OSP_FB_NONE) { RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::beginEvent( "startFrame::reserveTileGatherBuf", "DFB")); // Allocate a conservative upper bound of space which we'd need to // store the compressed tiles const size_t uncompressedSize = masterMsgSize( hasDepthBuffer, hasNormalBuffer, hasAlbedoBuffer, hasIDBuf()); const size_t compressedSize = snappy::MaxCompressedLength(uncompressedSize); tileGatherBuffer.resize(myTiles.size() * compressedSize, 0); RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); } RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::beginEvent("startFrame::initTilesInfo", "DFB")); { std::lock_guard fbLock(mutex); std::lock_guard numTilesLock(numTilesMutex); if (frameIsActive) { throw std::runtime_error( "Attempt to start frame on already started frame!"); } frameProgress = 0.f; FrameBuffer::beginFrame(); lastProgressReport = std::chrono::steady_clock::now(); renderingProgressTiles = 0; tileErrorRegion.sync(); if (colorBufferFormat == OSP_FB_NONE) { std::lock_guard errsLock(tileErrorsMutex); tileIDs.clear(); tileErrors.clear(); tileIDs.reserve(myTiles.size()); tileErrors.reserve(myTiles.size()); } // May be worth parallelizing if we have tile ops where // new frame becomes expensive for (auto &tile : myTiles) tile->newFrame(); for (auto &l : layers) { l->beginFrame(); } if (mpicommon::IamTheMaster()) { numTilesExpected.resize(mpicommon::workerSize(), 0); std::fill(numTilesExpected.begin(), numTilesExpected.end(), 0); } globalTilesCompletedThisFrame = 0; numTilesCompletedThisFrame = 0; for (uint32_t t = 0; t < getGlobalTotalTiles(); t++) { if (doAccumulation() && tileError(t) <= errorThreshold) { if (allTiles[t]->mine()) { numTilesCompletedThisFrame++; } } else if (mpicommon::IamTheMaster()) { ++numTilesExpected[allTiles[t]->ownerID]; } } frameIsDone = false; frameIsActive = true; } RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); mpicommon::barrier(mpiGroup.comm).wait(); if (isFrameComplete(0)) closeCurrentFrame(); } bool DFB::isFrameComplete(const size_t numTiles) { std::lock_guard numTilesLock(numTilesMutex); numTilesCompletedThisFrame += numTiles; renderingProgressTiles += numTiles; auto now = std::chrono::steady_clock::now(); auto timeSinceUpdate = duration_cast(now - lastProgressReport); if (timeSinceUpdate.count() >= 1000) { auto msg = std::make_shared(sizeof(ProgressMessage)); ProgressMessage *msgData = reinterpret_cast(msg->data); msgData->command = PROGRESS_MESSAGE; msgData->numCompleted = renderingProgressTiles; msgData->frameID = getSh()->frameID; mpi::messaging::sendTo(mpicommon::masterRank(), myId, msg); renderingProgressTiles = 0; lastProgressReport = now; } return numTilesCompletedThisFrame == myTiles.size(); } size_t DFB::ownerIDFromTileID(size_t tileID) const { return tileID % mpicommon::workerSize(); } void DistributedFrameBuffer::setSparseFBLayerCount(size_t numLayers) { // Layer 0 is the base owned tiles layer created by the DFB, so we'll always // have numLayers + 1 layers layers.resize(numLayers + 1, nullptr); // The sparse layers don't do accumulation and variance calculation because // this needs data from all ranks rendering a given tile const int channelFlags = getChannelFlags() & ~(OSP_FB_ACCUM | OSP_FB_VARIANCE); // Allocate any new layers that have been added to the DFB for (size_t i = 1; i < layers.size(); ++i) { if (!layers[i]) { layers[i] = rkcommon::make_unique( getISPCDevice(), size, getColorBufferFormat(), channelFlags); } } } size_t DistributedFrameBuffer::getSparseLayerCount() const { return layers.size(); } SparseFrameBuffer *DistributedFrameBuffer::getSparseFBLayer(size_t l) { return layers[l].get(); } void DFB::cancelFrame() { FrameBuffer::cancelFrame(); // Propagate the frame cancellation to the sparse fb layers as well for (auto &l : layers) { l->cancelFrame(); } } float DFB::getCurrentProgress() const { if (stagesCompleted == OSP_FRAME_FINISHED) { return 1.f; } return frameProgress; } void DFB::createTiles() { allTiles.clear(); myTiles.clear(); const vec2i totalTiles = divRoundUp(size, vec2i(TILE_SIZE)); std::vector myTileIDs; for (int y = 0; y < totalTiles.y; ++y) { for (int x = 0; x < totalTiles.x; ++x) { size_t tileID = size_t(x) + size_t(totalTiles.x) * size_t(y); const size_t ownerID = ownerIDFromTileID(tileID); const vec2i tileStart(x * TILE_SIZE, y * TILE_SIZE); if (ownerID == size_t(mpicommon::workerRank())) { auto td = tileOperation->makeTile(this, tileStart, tileID, ownerID); myTiles.push_back(td.get()); allTiles.push_back(std::move(td)); myTileIDs.push_back(tileID); } else { allTiles.push_back(make_unique(tileStart, tileID, ownerID)); } } } // Allocate the sparse fb for the tiles we own uint32 channels = OSP_FB_DEPTH; // Accum and variance are not done in the sparse FB for the DFB if (hasNormalBuf()) { channels |= OSP_FB_NORMAL; } if (hasAlbedoBuf()) { channels |= OSP_FB_ALBEDO; } if (layers.empty()) { layers.push_back(rkcommon::make_unique( getISPCDevice(), size, OSP_FB_NONE, channels, myTileIDs)); } else { layers[0]->setTiles(myTileIDs); layers[0]->clear(); } layers[0]->commit(); } void DFB::setTileOperation( std::shared_ptr tileOp, const Renderer *renderer) { // TODO WILL: Is this really the best way to avoid re-attaching all the // tiles each frame? Maybe take a string identifying it and find the // obj. creation method instead? if (tileOperation && lastRenderer == renderer) return; tileOperation = tileOp; tileOperation->attach(this); lastRenderer = renderer; createTiles(); } std::shared_ptr DFB::getTileOperation() { return tileOperation; } const Renderer *DFB::getLastRenderer() const { return lastRenderer; } const void *DFB::mapBuffer(OSPFrameBufferChannel channel) { if (!localFBonMaster) { throw std::runtime_error( "#osp:mpi:dfb: tried to 'ospMap()' a frame " "buffer that doesn't have a host-side correspondence"); } return localFBonMaster->mapBuffer(channel); } void DFB::unmap(const void *mappedMem) { if (!localFBonMaster) { throw std::runtime_error( "#osp:mpi:dfb: tried to 'ospUnmap()' a frame " "buffer that doesn't have a host-side color " "buffer"); } localFBonMaster->unmap(mappedMem); } void DFB::waitUntilFinished() { using namespace mpicommon; using namespace std::chrono; RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::beginEvent("waitUntilDoneCond", "DFB")); std::unique_lock lock(mutex); frameDoneCond.wait(lock, [&] { return frameIsDone; }); frameIsActive = false; RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); setCompletedEvent(OSP_WORLD_RENDERED); if (frameCancelled()) { return; } RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::beginEvent("finalGather", "DFB")); if (colorBufferFormat != OSP_FB_NONE) { gatherFinalTiles(); } else if (hasVarianceBuf()) { gatherFinalErrors(); } RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); } void DFB::processMessage(WriteTileMessage *msg) { ispc::Tile tile; unpackWriteTileMessage( msg, tile, hasNormalBuffer || hasAlbedoBuffer || hasIDBuf()); auto *tileDesc = this->getTileDescFor(tile.region.lower); LiveTileOperation *td = (LiveTileOperation *)tileDesc; td->process(tile); } void DistributedFrameBuffer::processMessage(MasterTileMessage_FB *msg) { if (hasVarianceBuffer) { const vec2i tileID = msg->coords / TILE_SIZE; if (msg->error < (float)inf) { tileErrorRegion.update(tileID, msg->error); } } vec2i numPixels = getNumPixels(); MasterTileMessage_FB_Depth *depth = nullptr; if (hasDepthBuffer && msg->command & MASTER_TILE_HAS_DEPTH) { depth = reinterpret_cast(msg); } MasterTileMessage_FB_Depth_Aux *aux = nullptr; if (msg->command & MASTER_TILE_HAS_AUX) aux = reinterpret_cast(msg); uint32 *pidBuf = nullptr; uint32 *gidBuf = nullptr; uint32 *iidBuf = nullptr; // TODO: Make the rest of the tile more dynamically sized and use a buffer // cursor style to get the pointers to the individual tile components if (msg->command & MASTER_TILE_HAS_ID) { // The ID buffer data comes at the end of the tile message uint8 *data = reinterpret_cast(msg); if (!aux) { if (depth) { data += sizeof(MasterTileMessage_FB_Depth); } else { data += sizeof(MasterTileMessage_FB); } } else { data += sizeof(MasterTileMessage_FB_Depth_Aux); } // All IDs are sent if any were requested, however we need to write only the // ones that actually exist in the local FB since it doesn't allocate // buffers for the non-existant channels if (hasPrimitiveIDBuffer) { pidBuf = reinterpret_cast(data); } if (hasObjectIDBuffer) { gidBuf = reinterpret_cast( data + sizeof(uint32) * TILE_SIZE * TILE_SIZE); } if (hasInstanceIDBuffer) { iidBuf = reinterpret_cast( data + 2 * sizeof(uint32) * TILE_SIZE * TILE_SIZE); } } // TODO: Here we're just accessing the local fb on the host, but have it // allocated in USM. Will work, but maybe wasting some USM space? vec4f *color = (localFBonMaster->colorBuffer) ? localFBonMaster->colorBuffer->data() : nullptr; for (int iy = 0; iy < TILE_SIZE; iy++) { int iiy = iy + msg->coords.y; if (iiy >= numPixels.y) { continue; } for (int ix = 0; ix < TILE_SIZE; ix++) { int iix = ix + msg->coords.x; if (iix >= numPixels.x) { continue; } if (color) { color[iix + iiy * numPixels.x] = msg->color[ix + iy * TILE_SIZE]; } if (depth) { (*localFBonMaster->depthBuffer)[iix + iiy * numPixels.x] = depth->depth[ix + iy * TILE_SIZE]; } if (aux) { if (hasNormalBuffer) (*localFBonMaster->normalBuffer)[iix + iiy * numPixels.x] = aux->normal[ix + iy * TILE_SIZE]; if (hasAlbedoBuffer) (*localFBonMaster->albedoBuffer)[iix + iiy * numPixels.x] = aux->albedo[ix + iy * TILE_SIZE]; } if (pidBuf) { (*localFBonMaster->primitiveIDBuffer)[iix + iiy * numPixels.x] = pidBuf[ix + iy * TILE_SIZE]; } if (gidBuf) { (*localFBonMaster->objectIDBuffer)[iix + iiy * numPixels.x] = gidBuf[ix + iy * TILE_SIZE]; } if (iidBuf) { (*localFBonMaster->instanceIDBuffer)[iix + iiy * numPixels.x] = iidBuf[ix + iy * TILE_SIZE]; } } } } bool DFB::hasIDBuf() const { // ID buffers are only needed on the first frame when rendering with // accumulation return getFrameID() == 0 && (hasPrimitiveIDBuffer || hasObjectIDBuffer || hasInstanceIDBuffer); } void DFB::tileIsFinished(LiveTileOperation *tile) { // Write the final colors into the color buffer // normalize and write final color, and compute error if (colorBufferFormat != OSP_FB_NONE) DFB_writeTile((ispc::VaryingTile *)&tile->finished, &tile->color); auto msg = [&] { MasterTileMessageBuilder msg(hasDepthBuffer, hasNormalBuffer, hasAlbedoBuffer, hasIDBuf(), tile->begin, tile->error); msg.setColor(tile->color); msg.setDepth(tile->finished.z); msg.setNormal((vec3f *)tile->finished.nx); msg.setAlbedo((vec3f *)tile->finished.ar); msg.setPrimitiveID(tile->finished.pid); msg.setObjectID(tile->finished.gid); msg.setInstanceID(tile->finished.iid); return msg; }; // TODO still send normal & albedo? if (colorBufferFormat == OSP_FB_NONE) { std::lock_guard lock(tileErrorsMutex); tileIDs.push_back(tile->begin / TILE_SIZE); tileErrors.push_back(tile->error); } else { auto tileMsg = msg().message; size_t compressedSize = snappy::MaxCompressedLength(tileMsg->size); std::vector compressedTile(compressedSize, 0); snappy::RawCompress(reinterpret_cast(tileMsg->data), tileMsg->size, compressedTile.data(), &compressedSize); uint32_t tileOffset; { std::lock_guard lock(finalTileBufferMutex); tileOffset = nextTileWrite; tileBufferOffsets.push_back(tileOffset); nextTileWrite += compressedSize; } std::memcpy( &tileGatherBuffer[tileOffset], compressedTile.data(), compressedSize); } if (isFrameComplete(1)) { closeCurrentFrame(); } } void DFB::updateProgress(ProgressMessage *msg) { globalTilesCompletedThisFrame += msg->numCompleted; frameProgress = globalTilesCompletedThisFrame / (float)getGlobalTotalTiles(); } size_t DFB::numMyTiles() const { return myTiles.size(); } TileDesc *DFB::getTileDescFor(const vec2i &coords) const { return allTiles[getTileIDof(coords)].get(); } size_t DFB::getTileIDof(const vec2i &c) const { return (c.x / TILE_SIZE) + (c.y / TILE_SIZE) * totalTiles.x; } std::string DFB::toString() const { return "ospray::DFB"; } void DFB::incoming(const std::shared_ptr &message) { auto *msg = (TileMessage *)message->data; /* if (msg->command & CANCEL_RENDERING) { std::cout << "Rank " << mpicommon::globalRank() << " rendering was cancelled\n" << std::flush; cancelRendering = true; // TODO: We need to mark the frame as done as well here, in case // this rank had already finished the frame and was waiting. // We also then need to know to discard any additional tile messages // we receive until we start the next frame. closeCurrentFrame(); return; } */ // Any delayed progress messages are about the previous frame anyways, // so we don't care. if (!frameIsActive && !(msg->command & PROGRESS_MESSAGE)) { std::lock_guard lock(mutex); if (!frameIsActive) { throw std::runtime_error( "Somehow received a tile message when frame inactive!?"); } } scheduleProcessing(message); } void DFB::scheduleProcessing(const std::shared_ptr &message) { tasking::schedule([=]() { auto *msg = (TileMessage *)message->data; if (msg->command & MASTER_WRITE_TILE) { throw std::runtime_error("#dfb: master msg should not be scheduled!"); } else if (msg->command & WORKER_WRITE_TILE) { this->processMessage((WriteTileMessage *)msg); } else if (msg->command & PROGRESS_MESSAGE) { updateProgress((ProgressMessage *)msg); } else { throw std::runtime_error("#dfb: unknown tile type processed!"); } }); } void DFB::gatherFinalTiles() { using namespace mpicommon; using namespace std::chrono; RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::beginEvent("preGatherComputeStart", "DFB")); const size_t tileSize = masterMsgSize( hasDepthBuffer, hasNormalBuffer, hasAlbedoBuffer, hasIDBuf()); const int totalTilesExpected = std::accumulate(numTilesExpected.begin(), numTilesExpected.end(), 0); std::vector processOffsets; if (IamTheMaster()) { processOffsets.resize(workerSize(), 0); int recvOffset = 0; for (int i = 0; i < workerSize(); ++i) { processOffsets[i] = recvOffset; recvOffset += numTilesExpected[i]; } } RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent("gatherTileData", "DFB"); }); // Each rank sends us the offset lists of the individually compressed tiles // in its compressed data buffer std::vector compressedTileOffsets; if (IamTheMaster()) { compressedTileOffsets.resize(totalTilesExpected, 0); } auto tileOffsetsGather = gatherv(tileBufferOffsets.data(), tileBufferOffsets.size(), MPI_INT, compressedTileOffsets.data(), numTilesExpected, processOffsets, MPI_INT, masterRank(), mpiGroup.comm); // We've got to use an int since Gatherv only takes int counts. // However, it's pretty unlikely we'll reach the point where someone // is sending 2GB in final tile data from a single process const int sendCompressedSize = static_cast(nextTileWrite); // Get info about how many bytes each proc is sending us std::vector gatherSizes; if (IamTheMaster()) { gatherSizes.resize(workerSize(), 0); } gather(&sendCompressedSize, 1, MPI_INT, gatherSizes.data(), 1, MPI_INT, masterRank(), mpiGroup.comm) .wait(); std::vector compressedOffsets; if (IamTheMaster()) { compressedOffsets.resize(workerSize(), 0); int offset = 0; for (size_t i = 0; i < gatherSizes.size(); ++i) { compressedOffsets[i] = offset; offset += gatherSizes[i]; } compressedResults.resize(offset, 0); } gatherv(tileGatherBuffer.data(), sendCompressedSize, MPI_BYTE, compressedResults.data(), gatherSizes, compressedOffsets, MPI_BYTE, masterRank(), mpiGroup.comm) .wait(); tileOffsetsGather.wait(); RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); // Now we must decompress each ranks data to process it, though we // already know how much data each is sending us and where to write it. if (IamTheMaster()) { RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::beginEvent("masterTileWrite", "DFB")); tasking::parallel_for(workerSize(), [&](int i) { tasking::parallel_for(numTilesExpected[i], [&](int tid) { int processTileOffset = processOffsets[i] + tid; int compressedSize = 0; if (tid + 1 < numTilesExpected[i]) { compressedSize = compressedTileOffsets[processTileOffset + 1] - compressedTileOffsets[processTileOffset]; } else { compressedSize = gatherSizes[i] - compressedTileOffsets[processTileOffset]; } char *decompressedTile = STACK_BUFFER(char, tileSize); snappy::RawUncompress(&compressedResults[compressedOffsets[i] + compressedTileOffsets[processTileOffset]], compressedSize, decompressedTile); MasterTileMessage_FB *msg = reinterpret_cast(decompressedTile); this->processMessage(msg); }); }); RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); // not accurate, did we render something at all localFBonMaster->getSh()->super.numPixelsRendered = totalTilesExpected; } } void DFB::gatherFinalErrors() { using namespace mpicommon; using namespace rkcommon; std::vector tilesFromRank(workerSize(), 0); const int myTileCount = tileIDs.size(); gather(&myTileCount, 1, MPI_INT, tilesFromRank.data(), 1, MPI_INT, masterRank(), mpiGroup.comm) .wait(); std::vector tileGatherResult; std::vector tileBytesExpected(workerSize(), 0); std::vector processOffsets(workerSize(), 0); const size_t tileInfoSize = sizeof(float) + sizeof(vec2i); if (IamTheMaster()) { size_t recvOffset = 0; for (int i = 0; i < workerSize(); ++i) { processOffsets[i] = recvOffset; tileBytesExpected[i] = tilesFromRank[i] * tileInfoSize; recvOffset += tileBytesExpected[i]; } tileGatherResult.resize(recvOffset); } std::vector sendBuffer(myTileCount * tileInfoSize); std::memcpy( sendBuffer.data(), tileIDs.data(), tileIDs.size() * sizeof(vec2i)); std::memcpy(sendBuffer.data() + tileIDs.size() * sizeof(vec2i), tileErrors.data(), tileErrors.size() * sizeof(float)); gatherv(sendBuffer.data(), sendBuffer.size(), MPI_BYTE, tileGatherResult.data(), tileBytesExpected, processOffsets, MPI_BYTE, masterRank(), mpiGroup.comm) .wait(); if (IamTheMaster()) { tasking::parallel_for(workerSize(), [&](int rank) { const vec2i *tileID = reinterpret_cast( tileGatherResult.data() + processOffsets[rank]); const float *error = reinterpret_cast(tileGatherResult.data() + processOffsets[rank] + tilesFromRank[rank] * sizeof(vec2i)); for (int i = 0; i < tilesFromRank[rank]; ++i) { if (error[i] < (float)inf) { tileErrorRegion.update(tileID[i], error[i]); } } }); } } void DFB::closeCurrentFrame() { std::lock_guard lock(mutex); frameIsDone = true; frameDoneCond.notify_all(); } //! write given tile data into the frame buffer, sending to remote owner if //! required void DFB::setTile(const ispc::Tile &tile) { auto *tileDesc = this->getTileDescFor(tile.region.lower); // Note my tile, send to the owner if (!tileDesc->mine()) { auto msg = makeWriteTileMessage( tile, hasNormalBuffer || hasAlbedoBuffer || hasIDBuf()); int dstRank = tileDesc->ownerID; mpi::messaging::sendTo(dstRank, myId, msg); } else { if (!frameIsActive) throw std::runtime_error("#dfb: cannot setTile if frame is inactive!"); LiveTileOperation *td = (LiveTileOperation *)tileDesc; td->process(tile); } } void DFB::clear() { FrameBuffer::clear(); if (hasVarianceBuffer) { tileErrorRegion.clear(); } if (localFBonMaster) { localFBonMaster->clear(); } for (auto &l : layers) { l->clear(); } } vec2i DFB::getNumRenderTasks() const { return numRenderTasks; } uint32_t DFB::getTotalRenderTasks() const { return numRenderTasks.product(); } vec2i DFB::getGlobalNumTiles() const { return totalTiles; } uint32_t DFB::getGlobalTotalTiles() const { return totalTiles.product(); } utility::ArrayView DFB::getRenderTaskIDs( const float errorThreshold, const uint32_t spp) { return layers[0]->getRenderTaskIDs(errorThreshold, spp); } float DFB::getVariance() const { // TODO: No proper error calculation for DFB now, // need to use FrameOp via LocalFB if (mpicommon::IamTheMaster()) return 1.f; // Return set value otherwise return FrameBuffer::getVariance(); } float DFB::taskError(const uint32_t) const { NOT_IMPLEMENTED; } float DFB::tileError(const uint32_t tileID) { return tileErrorRegion[tileID]; } AsyncEvent DFB::postProcess(bool wait) { AsyncEvent event; if (localFBonMaster) { // FrameOps are run on the device, but the DFB receives the final image // data over MPI into host-memory, and returns host-memory pointers // directly. So, we need to copy the host data to the device, run the frame // ops. If we can receive with MPI directly into device // memory we can drop this first copy step. When running on the CPU device, // these copies will become no-ops. ispcrt::TaskQueue &tq = getISPCDevice().getIspcrtQueue(); if (localFBonMaster->colorBuffer) { tq.copyToDevice(*localFBonMaster->colorBuffer); } if (localFBonMaster->depthBuffer) { tq.copyToDevice(*localFBonMaster->depthBuffer); } if (localFBonMaster->normalBuffer) { tq.copyToDevice(*localFBonMaster->normalBuffer); } if (localFBonMaster->albedoBuffer) { tq.copyToDevice(*localFBonMaster->albedoBuffer); } tq.sync(); event = localFBonMaster->postProcess(wait); } return event; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/fb/DistributedFrameBuffer.h000066400000000000000000000245741456566705700262640ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include "../common/Messaging.h" #include "DistributedFrameBuffer_TileMessages.h" #include "ISPCDevice.h" #include "fb/LocalFB.h" #include "fb/SparseFB.h" #include "fb/TaskError.h" #include "render/Renderer.h" #include "rkcommon/containers/AlignedVector.h" #include "rkcommon/math/vec.h" #include "DistributedFrameBufferShared.h" namespace ospray { struct TileDesc; struct TileOperation; struct LiveTileOperation; class DistributedTileError : public TaskError { mpicommon::Group group; public: DistributedTileError( api::ISPCDevice &device, const vec2i &numTiles, mpicommon::Group group); // broadcast tileErrorBuffer to all workers in this group void sync(); }; struct DistributedFrameBuffer : public mpi::messaging::MessageHandler, public FrameBuffer { DistributedFrameBuffer(api::ISPCDevice &device, const vec2i &numPixels, ObjectHandle myHandle, ColorBufferFormat, const uint32 channels); ~DistributedFrameBuffer() override; // ================================================================== // framebuffer / device interface // ================================================================== void commit() override; const void *mapBuffer(OSPFrameBufferChannel channel) override; void unmap(const void *mappedMem) override; /*! \brief clear (the specified channels of) this frame buffer \details for the *distributed* frame buffer, we assume that *all* nodes get this command, and that each instance therefore can clear only its own tiles without having to tell any other node about it */ void clear() override; // ================================================================== // framebuffer-renderer/loadbalancer interface // ================================================================== // Return the number of render tasks in the x and y direction // This is the kernel launch dims to render the image vec2i getNumRenderTasks() const override; uint32_t getTotalRenderTasks() const override; vec2i getGlobalNumTiles() const; uint32_t getGlobalTotalTiles() const; /* Get render task IDs will return the render task IDs for layer 0, * the tiles owned by the DFB for compositing. */ utility::ArrayView getRenderTaskIDs( const float errorThreshold, const uint32_t spp) override; virtual float getVariance() const override; // Task error is not valid for the DFB, as error is tracked at a per-tile // level. Use tileError to get rendering error float taskError(const uint32_t taskID) const override; float tileError(const uint32_t tileID); /*! framebuffer-renderer/loadbalancer interface: loadbalancer calls this function whenever a local node has finished a tile, and wants the (distributed) frame buffer to process it */ void setTile(const ispc::Tile &tile); void startNewFrame(const float errorThreshold); void closeCurrentFrame(); void waitUntilFinished(); AsyncEvent postProcess(bool wait) override; void setTileOperation( std::shared_ptr tileOp, const Renderer *renderer); std::shared_ptr getTileOperation(); const Renderer *getLastRenderer() const; mpicommon::Group getMPIGroup(); // ================================================================== // interface for maml messaging, enables communication between // different instances of same object // ================================================================== //! handle incoming message from commlayer. it's the //! recipient's job to properly delete the message. void incoming(const std::shared_ptr &message) override; //! process a (non-empty) write tile message at the master void processMessage(MasterTileMessage_FB *msg); //! process a client-to-client write tile message */ void processMessage(WriteTileMessage *msg); size_t ownerIDFromTileID(size_t tileID) const; void setSparseFBLayerCount(size_t numLayers); size_t getSparseLayerCount() const; SparseFrameBuffer *getSparseFBLayer(size_t l); void cancelFrame() override; float getCurrentProgress() const override; private: friend struct LiveTileOperation; bool hasIDBuf() const; // ================================================================== // internal helper functions // ================================================================== /*! this function gets called whenever one of our tiles is done writing/compositing/blending/etc; i.e., as soon as we know that all the ingredient tile data for that tile have been received from the client(s) that generated them. By the time the tile gets called we do know that 'accum' field of the tile has been set; it is this function's job to make sure we properly call the post-op(s), properly send final color data to the master (if required), and properly do the bookkeeping that this tile is now done. */ void tileIsFinished(LiveTileOperation *tile); /*! This function is called when a worker reports how many tiles it's completed to the master, to update the user's progress callback. This is only used if the user has set a progress callback. */ void updateProgress(ProgressMessage *msg); //! number of tiles that "I" own size_t numMyTiles() const; //! \brief common function to help printf-debugging /*! \detailed Every derived class should override this! */ std::string toString() const override; /*! return tile descriptor for given pixel coordinates. this tile ! may or may not belong to current instance */ TileDesc *getTileDescFor(const vec2i &coords) const; /*! return the tile ID for given pair of coordinates. this tile may or may not belong to current instance */ size_t getTileIDof(const vec2i &c) const; void createTiles(); /*! atomic update and check if frame is complete with given tiles */ bool isFrameComplete(size_t numTiles); /*! Offloads processing of incoming message to tasking system */ void scheduleProcessing(const std::shared_ptr &message); /*! Gather the final tiles from the other ranks to the master rank to * copy into the framebuffer */ void gatherFinalTiles(); /*! Gather the tile IDs and error info from the other ranks to the master, * for OSP_FB_NONE rendering, where we only track that info on the master */ void gatherFinalErrors(); // Data members /////////////////////////////////////////////////////////// // The communicator used by this DFB instance for collectives, to avoid // conflicts with other framebuffers mpicommon::Group mpiGroup; // Total number of tiles that the framebuffer is divided into, including those // not owned by this sparsefb vec2i totalTiles; // Total number of render tasks that the framebuffer is divided into, // including those not owned by this sparsefb vec2i numRenderTasks; std::vector tileGatherBuffer; std::vector compressedResults; // Locations of the compressed tiles in the tileGatherBuffer std::vector tileBufferOffsets; uint32_t nextTileWrite{0}; std::mutex finalTileBufferMutex; /*! holds error per tile and adaptive regions, for variance estimation / stopping */ DistributedTileError tileErrorRegion; /*! local frame buffer on the master used for storing the final tiles. will be null on all workers, and _may_ be null on the master if the master does not have a color buffer */ std::unique_ptr localFBonMaster; /* SparseFrameBuffer layers in the DFB, layer 0 stores the tiles owned by DFB * for compositing, and layers 1-N are those added by the renderer. For * renderers whose local rendering work is dynamic/data-dependent (e.g., * data-parallel rendering), layers can be allocated and resized as needed to * avoid having to reallocate the set of SparseFrameBuffer(s) needed each * frame. */ std::vector> layers; /*! #tiles we've (already) sent to / received by the master this frame (used to track when current node is done with this frame - we are done exactly once we've completed sending / receiving the last tile to / by the master) */ size_t numTilesCompletedThisFrame{0}; /*! The total number of tiles completed by all workers during this frame, to track progress for the user's progress callback. NOTE: This is not the numTilesCompletedThisFrame , which tracks how many tiles this rank has finished of the ones it's responsible for completing */ size_t globalTilesCompletedThisFrame{0}; /*! The number of tiles the master is expecting to receive from each rank */ std::vector numTilesExpected; /* protected numTilesCompletedThisFrame to ensure atomic update and compare */ std::mutex numTilesMutex; /* vector of info for *all* tiles. Each logical tile in the screen has an * entry here. allTiles owns the lifetime for tiles in myTiles as well, which * is a subset of those in allTiles containing the live tile operations for * the tiles this rank owns */ std::vector> allTiles; /* list of *our* tiles ('our' as in 'that belong to the given node'), with the actual data of those tiles. NOTE: for msvc15 issue with shared_ptr, the tile operation lifetime is managed in allTiles which holds a unique_ptr for all tiles (both ones we own, and don't). */ std::vector myTiles; std::shared_ptr tileOperation = nullptr; const Renderer *lastRenderer = nullptr; /*! mutex used to protect all threading-sensitive data in this object */ std::mutex mutex; //! set to true when the frame becomes 'active', and write tile //! messages can be consumed. std::atomic frameIsActive{false}; /*! set to true when the framebuffer is done for the given frame */ bool frameIsDone{false}; int renderingProgressTiles{0}; std::chrono::steady_clock::time_point lastProgressReport; std::atomic frameProgress{0.f}; //! condition that gets triggered when the frame is done std::condition_variable frameDoneCond; /*! Gather all tile errors in the optimized FB_NONE case to send them out in the single gatherv. */ std::mutex tileErrorsMutex; std::vector tileIDs; std::vector tileErrors; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/fb/DistributedFrameBuffer.ispc000066400000000000000000000304111456566705700267560ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "rkcommon/math/box.ih" #include "rkcommon/math/vec.ih" #include "fb/FrameBuffer.ih" #include "fb/TileShared.h" #include "rkcommon/math/vec.ih" #include "fb/FrameBufferShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE // accumulates the colors in a tile, writes the final normalized colors into a // separate tile, and computes the error export uniform float DFB_accumulateTile(const VaryingTile *uniform tile, VaryingTile *uniform final, VaryingTile *uniform accum, VaryingTile *uniform variance, uniform bool doAccumulation, uniform bool hasVarianceBuffer) { const uniform int accumID = tile->accumID; const uniform vec2i size = box_size(tile->region); const uniform int maxi = size.y * (TILE_SIZE / programCount); uniform float errf = inf; /* variance buffer accumulates every other frame */ const uniform bool accumulateVariance = hasVarianceBuffer && (accumID & 1) == 1; if (!doAccumulation || accumID < 1) { for (uniform int i = 0; i < maxi; i++) { vec4f col = make_vec4f(tile->r[i], tile->g[i], tile->b[i], tile->a[i]); accum->r[i] = col.x; accum->g[i] = col.y; accum->b[i] = col.z; accum->a[i] = col.w; accum->z[i] = tile->z[i]; final->r[i] = col.x; final->g[i] = col.y; final->b[i] = col.z; final->a[i] = col.w; final->z[i] = tile->z[i]; // ID buffers only written on the first frame final->pid[i] = tile->pid[i]; final->gid[i] = tile->gid[i]; final->iid[i] = tile->iid[i]; } } else { const uniform float rcpAccumID = rcpf(accumID + 1); const uniform float accHalfScale = rcpf(accumID / 2 + 1); float err = 0.f; int cnt = 0; for (uniform int i = 0; i < maxi; i++) { vec4f col = make_vec4f(tile->r[i], tile->g[i], tile->b[i], tile->a[i]); vec4f acc = col + make_vec4f(accum->r[i], accum->g[i], accum->b[i], accum->a[i]); accum->r[i] = acc.x; accum->g[i] = acc.y; accum->b[i] = acc.z; accum->a[i] = acc.w; acc = acc * rcpAccumID; if (accumulateVariance) { varying vec4f vari = make_vec4f(0.f); if (accumID > 1) vari = make_vec4f( variance->r[i], variance->g[i], variance->b[i], variance->a[i]); vari = vari + col; variance->r[i] = vari.x; variance->g[i] = vari.y; variance->b[i] = vari.z; variance->a[i] = vari.w; /* invert alpha (bright alpha is more important */ const float den2 = reduce_add(make_vec3f(acc)) + (1.f - acc.w); if (den2 > 0.0f) { const vec4f diff = absf(acc - accHalfScale * vari); if ((i * programCount % TILE_SIZE) + programIndex < size.x) { err += reduce_add(diff) * rsqrtf(den2); cnt++; } } } final->r[i] = acc.x; final->g[i] = acc.y; final->b[i] = acc.z; final->a[i] = acc.w; } /* error is also only updated every other frame to avoid alternating * error (get a monotone sequence) */ if (accumulateVariance) { // scaling factor to stay backward compatible to default TILE_SIZE=64 errf = reduce_add(err) * rcp((uniform float)reduce_add(cnt)) * 64.f; } } return errf; } // variant that only accumulates (without computing error) // assumption: there is always ACCUM and VARIANCE buffer (otherwise variance // will always be inf and WriteMultipleTiles mode won't be used) export void DFB_accumulateTileSimple(const VaryingTile *uniform tile, VaryingTile *uniform accum, VaryingTile *uniform variance) { // variance buffer accumulates every other frame const uniform bool accumulateVariance = (tile->accumID & 1) == 1; const uniform vec2i size = box_size(tile->region); const uniform int maxi = size.y * (TILE_SIZE / programCount); for (uniform int i = 0; i < maxi; i++) { vec4f col = make_vec4f(tile->r[i], tile->g[i], tile->b[i], tile->a[i]); accum->r[i] += col.x; accum->g[i] += col.y; accum->b[i] += col.z; accum->a[i] += col.w; if (accumulateVariance) { variance->r[i] += col.x; variance->g[i] += col.y; variance->b[i] += col.z; variance->a[i] += col.w; } } } // accumulate normal and albedo export void DFB_accumulateAuxTile(const VaryingTile *uniform tile, void *uniform _final, VaryingTile *uniform accum) { Tile *uniform final = (Tile * uniform) _final; const uniform vec2i size = box_size(tile->region); const uniform int maxi = size.y * (TILE_SIZE / programCount); if (tile->accumID < 1) { for (uniform int i = 0; i < maxi; i++) { const float fnx = tile->nx[i]; const float fny = tile->ny[i]; const float fnz = tile->nz[i]; accum->nx[i] = fnx; accum->ny[i] = fny; accum->nz[i] = fnz; #ifdef OSPRAY_TARGET_SYCL final->nx[3 * i] = fnx; final->nx[3 * i + 1] = fny; final->nx[3 * i + 2] = fnz; /* final->nx[i] = fnx; final->ny[i] = fny; final->nz[i] = fnz; */ #else // TODO: This is not right but some other bug/data use cancels it out. // The tile struct stores SoA layout memory too, but here we treat it // like SoA for some reason, so final->nx will hold: // {fnx0, fny0, fnz0, fnx1, fny1, fnz1, ..., progCount,...} // after the write here soa_to_aos3(fnx, fny, fnz, final->nx + 3 * programCount * i); #endif const float far = tile->ar[i]; const float fag = tile->ag[i]; const float fab = tile->ab[i]; accum->ar[i] = far; accum->ag[i] = fag; accum->ab[i] = fab; #ifdef OSPRAY_TARGET_SYCL final->ar[3 * i] = far; final->ar[3 * i + 1] = fag; final->ar[3 * i + 2] = fab; /* final->ar[i] = far; final->ag[i] = fag; final->ab[i] = fab; */ #else soa_to_aos3(far, fag, fab, final->ar + 3 * programCount * i); #endif } } else { const uniform float rcpAccumID = rcpf(tile->accumID + 1); for (uniform int i = 0; i < maxi; i++) { accum->nx[i] += tile->nx[i]; accum->ny[i] += tile->ny[i]; accum->nz[i] += tile->nz[i]; const float fnx = accum->nx[i] * rcpAccumID; const float fny = accum->ny[i] * rcpAccumID; const float fnz = accum->nz[i] * rcpAccumID; #ifdef OSPRAY_TARGET_SYCL final->nx[3 * i] = fnx; final->nx[3 * i + 1] = fny; final->nx[3 * i + 2] = fnz; /* final->nx[i] = fnx; final->ny[i] = fny; final->nz[i] = fnz; */ #else soa_to_aos3(fnx, fny, fnz, final->nx + 3 * programCount * i); #endif accum->ar[i] += tile->ar[i]; accum->ag[i] += tile->ag[i]; accum->ab[i] += tile->ab[i]; const float far = accum->ar[i] * rcpAccumID; const float fag = accum->ag[i] * rcpAccumID; const float fab = accum->ab[i] * rcpAccumID; #ifdef OSPRAY_TARGET_SYCL final->ar[3 * i] = far; final->ar[3 * i + 1] = fag; final->ar[3 * i + 2] = fab; /* final->ar[i] = far; final->ag[i] = fag; final->ab[i] = fab; */ #else soa_to_aos3(far, fag, fab, final->ar + 3 * programCount * i); #endif } } } // computes the error for a tile export uniform float DFB_computeErrorForTile( const uniform int *uniform const size_, // vec2i const VaryingTile *uniform accum, const VaryingTile *uniform variance, const uniform float accumID) { const uniform vec2i size = make_vec2i(size_[0], size_[1]); const uniform int maxi = size.y * (TILE_SIZE / programCount); const uniform float rcpAccumID = rcpf(accumID + 1); const uniform float accHalfScale = rcpf(accumID / 2 + 1); float err = 0.f; for (uniform int i = 0; i < maxi; i++) { vec4f acc = make_vec4f(accum->r[i], accum->g[i], accum->b[i], accum->a[i]); acc = acc * rcpAccumID; /* invert alpha (bright alpha is more important */ const float den2 = reduce_add(make_vec3f(acc)) + (1.f - acc.w); if (den2 > 0.0f) { const vec4f vari = make_vec4f( variance->r[i], variance->g[i], variance->b[i], variance->a[i]); const vec4f diff = absf(acc - accHalfScale * vari); if ((i * programCount % TILE_SIZE) + programIndex < size.x) err += reduce_add(diff) * rsqrtf(den2); } } uniform float cntu = (uniform float)size.x * size.y; // scaling factor to stay backward compatible to default TILE_SIZE=64 return reduce_add(err) * rcp(cntu) * 64.f; } // writes the final normalized colors in a tile into a color buffer export void DFB_writeTile(const VaryingTile *uniform tile, void *uniform _color) { const uniform vec2i size = box_size(tile->region); const uniform int maxi = size.y * (TILE_SIZE / programCount); varying vec4f *uniform color = (varying vec4f * uniform) _color; for (uniform int i = 0; i < maxi; i++) { const vec4f c = make_vec4f(tile->r[i], tile->g[i], tile->b[i], tile->a[i]); #ifndef OSPRAY_TARGET_SYCL soa_to_aos4(c.x, c.y, c.z, c.w, (uniform float *uniform) & color[i]); #else color[i] = c; #endif } } export void DFB_zComposite( const VaryingTile *uniform delta, VaryingTile *uniform current) { for (uniform int i = 0; i < TILE_SIZE * TILE_SIZE / programCount; i++) { const bool closer = delta->z[i] < current->z[i]; current->r[i] = closer ? delta->r[i] : current->r[i]; current->g[i] = closer ? delta->g[i] : current->g[i]; current->b[i] = closer ? delta->b[i] : current->b[i]; current->a[i] = closer ? delta->a[i] : current->a[i]; current->z[i] = closer ? delta->z[i] : current->z[i]; } } inline void swapFragments( VaryingTile *uniform t0, VaryingTile *uniform t1, uniform int fragID) { float r = t0->r[fragID]; t0->r[fragID] = t1->r[fragID]; t1->r[fragID] = r; float g = t0->g[fragID]; t0->g[fragID] = t1->g[fragID]; t1->g[fragID] = g; float b = t0->b[fragID]; t0->b[fragID] = t1->b[fragID]; t1->b[fragID] = b; float a = t0->a[fragID]; t0->a[fragID] = t1->a[fragID]; t1->a[fragID] = a; float z = t0->z[fragID]; t0->z[fragID] = t1->z[fragID]; t1->z[fragID] = z; float nx = t0->nx[fragID]; t0->nx[fragID] = t1->nx[fragID]; t1->nx[fragID] = nx; float ny = t0->ny[fragID]; t0->ny[fragID] = t1->ny[fragID]; t1->ny[fragID] = ny; float nz = t0->nz[fragID]; t0->nz[fragID] = t1->nz[fragID]; t1->nz[fragID] = nz; float ar = t0->ar[fragID]; t0->ar[fragID] = t1->ar[fragID]; t1->ar[fragID] = ar; float ag = t0->ag[fragID]; t0->ag[fragID] = t1->ag[fragID]; t1->ag[fragID] = ag; float ab = t0->ab[fragID]; t0->ab[fragID] = t1->ab[fragID]; t1->ab[fragID] = ab; uint32 pid = t0->pid[fragID]; t0->pid[fragID] = t1->pid[fragID]; t1->pid[fragID] = pid; uint32 gid = t0->gid[fragID]; t0->gid[fragID] = t1->gid[fragID]; t1->gid[fragID] = gid; uint32 iid = t0->iid[fragID]; t0->iid[fragID] = t1->iid[fragID]; t1->iid[fragID] = iid; } #define PIXELS_PER_BLEND_JOB 64 inline void sortAndBlendFragments(VaryingTile *uniform *uniform tileArray, uniform int32 numTiles, uniform int begin_frag, uniform int end_frag) { for (uniform int frag = begin_frag; frag < end_frag; ++frag) { #if 1 for (uniform int i = 1; i < numTiles; ++i) { for (uniform int j = i; j > 0; --j) { VaryingTile *uniform ta = tileArray[j]; VaryingTile *uniform tb = tileArray[j - 1]; if (ta->z[frag] < tb->z[frag]) break; swapFragments(ta, tb, frag); } } #endif vec3f acc_col = make_vec3f(0, 0, 0); float acc_alpha = 0.f; for (uniform int i = 0; i < numTiles; ++i) { VaryingTile *uniform tile = tileArray[i]; vec3f frag_col = make_vec3f(tile->r[frag], tile->g[frag], tile->b[frag]); float frag_alpha = tile->a[frag]; // Note: back-to-front blending acc_col = frag_col + (1.f - frag_alpha) * acc_col; acc_alpha = frag_alpha + (1.f - frag_alpha) * acc_alpha; } VaryingTile *uniform tile = tileArray[0]; tile->r[frag] = acc_col.x; tile->g[frag] = acc_col.y; tile->b[frag] = acc_col.z; tile->a[frag] = acc_alpha; // Since we blend back-to-front, the nearest depth sample is // on the last tile after sorting. tile->z[frag] = tileArray[numTiles - 1]->z[frag]; } } export void DFB_sortAndBlendFragments( VaryingTile *uniform *uniform tileArray, uniform int32 numTiles) { sortAndBlendFragments( tileArray, numTiles, 0, TILE_SIZE * TILE_SIZE / programCount); } OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/mpi/ospray/fb/DistributedFrameBufferShared.h000066400000000000000000000022311456566705700273750ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "fb/FrameBufferShared.h" #include "fb/TileShared.h" #ifdef __cplusplus #include "common/StructShared.h" namespace ispc { #endif // __cplusplus #ifdef OSPRAY_TARGET_SYCL float DFB_accumulateTile(const VaryingTile *uniform tile, VaryingTile *uniform final, VaryingTile *uniform accum, VaryingTile *uniform variance, uniform bool doAccumulation, uniform bool hasVarianceBuffer); void DFB_accumulateTileSimple(const VaryingTile *uniform tile, VaryingTile *uniform accum, VaryingTile *uniform variance); void DFB_accumulateAuxTile(const VaryingTile *uniform tile, void *uniform _final, VaryingTile *uniform accum); export uniform float DFB_computeErrorForTile( const uniform int *uniform const size_, // vec2i const VaryingTile *uniform accum, const VaryingTile *uniform variance, const uniform float accumID); void DFB_writeTile(const VaryingTile *tile, void *_color); void DFB_sortAndBlendFragments( VaryingTile *uniform *uniform tileArray, uniform int32 numTiles); #endif #ifdef __cplusplus } #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/mpi/ospray/fb/DistributedFrameBuffer_TileMessages.cpp000066400000000000000000000122161456566705700312520ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "DistributedFrameBuffer_TileMessages.h" #include "../common/Messaging.h" namespace ospray { std::shared_ptr makeWriteTileMessage( const ispc::Tile &tile, bool hasAux) { const size_t msgSize = hasAux ? sizeof(ispc::Tile) : sizeof(WriteTileMessage); auto msg = std::make_shared(msgSize + sizeof(int)); const static int header = WORKER_WRITE_TILE; std::memcpy(msg->data, &header, sizeof(int)); std::memcpy(msg->data + sizeof(int), &tile, msgSize); return msg; } void unpackWriteTileMessage( WriteTileMessage *msg, ispc::Tile &tile, bool hasAux) { const size_t msgSize = hasAux ? sizeof(ispc::Tile) : sizeof(WriteTileMessage); std::memcpy(&tile, reinterpret_cast(msg) + sizeof(int), msgSize); } size_t masterMsgSize( bool hasDepth, bool hasNormal, bool hasAlbedo, bool hasIDBuffers) { size_t msgSize = sizeof(MasterTileMessage_FB); // Normal and Albedo also imply Depth if (hasDepth || hasNormal || hasAlbedo) { msgSize += sizeof(float) * TILE_SIZE * TILE_SIZE; } if (hasNormal || hasAlbedo) { msgSize += 2 * sizeof(vec3f) * TILE_SIZE * TILE_SIZE; } // If any ID buffer is present we allocate space for all of them to be sent if (hasIDBuffers) { msgSize += 3 * sizeof(uint32) * TILE_SIZE * TILE_SIZE; } return msgSize; } MasterTileMessageBuilder::MasterTileMessageBuilder(bool hasDepth, bool hasNormal, bool hasAlbedo, bool hasIDBuffers, vec2i coords, float error) : hasDepth(hasDepth), hasNormal(hasNormal), hasAlbedo(hasAlbedo), hasIDBuffers(hasIDBuffers) { int command = MASTER_WRITE_TILE; const size_t msgSize = masterMsgSize(hasDepth, hasNormal, hasAlbedo, hasIDBuffers); // AUX also includes depth if (hasDepth || hasNormal || hasAlbedo) { command |= MASTER_TILE_HAS_DEPTH; } if (hasNormal || hasAlbedo) { command |= MASTER_TILE_HAS_AUX; } if (hasIDBuffers) { command |= MASTER_TILE_HAS_ID; } message = std::make_shared(msgSize); header = reinterpret_cast(message->data); header->command = command; header->coords = coords; header->error = error; } void MasterTileMessageBuilder::setColor(const vec4f *color) { vec4f *out = reinterpret_cast(message->data + sizeof(MasterTileMessage)); std::copy(color, color + TILE_SIZE * TILE_SIZE, out); } void MasterTileMessageBuilder::setDepth(const float *depth) { if (hasDepth) { float *out = reinterpret_cast( message->data + sizeof(MasterTileMessage) + colorBufferSize()); std::copy(depth, depth + TILE_SIZE * TILE_SIZE, out); } } void MasterTileMessageBuilder::setNormal(const vec3f *normal) { if (hasNormal) { vec3f *out = reinterpret_cast(message->data + sizeof(MasterTileMessage) + colorBufferSize() + depthBufferSize()); std::copy(normal, normal + TILE_SIZE * TILE_SIZE, out); } } void MasterTileMessageBuilder::setAlbedo(const vec3f *albedo) { if (hasAlbedo) { vec3f *out = reinterpret_cast(message->data + sizeof(MasterTileMessage) + colorBufferSize() + depthBufferSize() + normalBufferSize()); std::copy(albedo, albedo + TILE_SIZE * TILE_SIZE, out); } } void MasterTileMessageBuilder::setPrimitiveID(const uint32 *primID) { if (hasIDBuffers) { size_t offset = sizeof(MasterTileMessage) + colorBufferSize() + depthBufferSize() + normalBufferSize() + albedoBufferSize(); uint32 *out = reinterpret_cast(message->data + offset); std::copy(primID, primID + TILE_SIZE * TILE_SIZE, out); } } void MasterTileMessageBuilder::setObjectID(const uint32 *geomID) { if (hasIDBuffers) { size_t offset = sizeof(MasterTileMessage) + colorBufferSize() + depthBufferSize() + normalBufferSize() + albedoBufferSize() + sizeof(uint32) * TILE_SIZE * TILE_SIZE; uint32 *out = reinterpret_cast(message->data + offset); std::copy(geomID, geomID + TILE_SIZE * TILE_SIZE, out); } } void MasterTileMessageBuilder::setInstanceID(const uint32 *instID) { if (hasIDBuffers) { size_t offset = sizeof(MasterTileMessage) + colorBufferSize() + depthBufferSize() + normalBufferSize() + albedoBufferSize() + 2 * sizeof(uint32) * TILE_SIZE * TILE_SIZE; uint32 *out = reinterpret_cast(message->data + offset); std::copy(instID, instID + TILE_SIZE * TILE_SIZE, out); } } size_t MasterTileMessageBuilder::colorBufferSize() const { return sizeof(vec4f) * TILE_SIZE * TILE_SIZE; } size_t MasterTileMessageBuilder::depthBufferSize() const { return hasDepth || hasNormal || hasAlbedo ? sizeof(float) * TILE_SIZE * TILE_SIZE : 0; } size_t MasterTileMessageBuilder::normalBufferSize() const { return (hasNormal || hasAlbedo) ? sizeof(vec3f) * TILE_SIZE * TILE_SIZE : 0; } size_t MasterTileMessageBuilder::albedoBufferSize() const { return (hasNormal || hasAlbedo) ? sizeof(vec3f) * TILE_SIZE * TILE_SIZE : 0; } size_t MasterTileMessageBuilder::idBufferSize() const { return hasIDBuffers ? 3 * sizeof(uint32) * TILE_SIZE * TILE_SIZE : 0; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/fb/DistributedFrameBuffer_TileMessages.h000066400000000000000000000106701456566705700307210ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "../common/Messaging.h" #include "fb/LocalFB.h" #include "fb/TileShared.h" namespace ospray { /*! color buffer and depth buffer on master */ enum COMMANDTAG { /*! command tag that identifies a CommLayer::message as a write tile command. this is a command using for sending a tile of new samples to another instance of the framebuffer (the one that actually owns that tile) for processing and 'writing' of that tile on that owner node. */ WORKER_WRITE_TILE = 1 << 1, /*! command tag used for sending 'final' tiles from the tile owner to the master frame buffer. Note that we *do* send a message back to the master even in cases where the master does not actually care about the pixel data - we still have to let the master know when we're done. */ MASTER_WRITE_TILE = 1 << 2, // Modifier to indicate the tile has depth values MASTER_TILE_HAS_DEPTH = 1 << 3, // Indicates that the tile has normal and/or albedo values MASTER_TILE_HAS_AUX = 1 << 4, // Indicates that the tile has ID buffer values MASTER_TILE_HAS_ID = 1 << 5, // abort rendering the current frame CANCEL_RENDERING = 1 << 6, // Worker updating us on tiles completed PROGRESS_MESSAGE = 1 << 7 }; struct TileMessage { int command{-1}; }; struct ProgressMessage : public TileMessage { uint64_t numCompleted; int frameID; }; struct MasterTileMessage : public TileMessage { vec2i coords; float error; }; /*! message sent to the master when a tile is finished. TODO: compress the color data */ struct MasterTileMessage_FB : public MasterTileMessage { vec4f color[TILE_SIZE * TILE_SIZE]; }; struct MasterTileMessage_FB_Depth : public MasterTileMessage_FB { float depth[TILE_SIZE * TILE_SIZE]; }; struct MasterTileMessage_FB_Depth_Aux : public MasterTileMessage_FB_Depth { vec3f normal[TILE_SIZE * TILE_SIZE]; vec3f albedo[TILE_SIZE * TILE_SIZE]; }; /*! message sent from one node's instance to another, to tell that instance to write that tile */ struct WriteTileMessage : public TileMessage { region2i region; // screen region that this corresponds to vec2i fbSize; // total frame buffer size, for the camera vec2f rcp_fbSize; int32 generation; int32 children; int32 sortOrder; int32 accumID; //!< how often has been accumulated into this tile float pad[4]; //!< padding to match the ISPC-side layout float r[TILE_SIZE * TILE_SIZE]; // 'red' component float g[TILE_SIZE * TILE_SIZE]; // 'green' component float b[TILE_SIZE * TILE_SIZE]; // 'blue' component float a[TILE_SIZE * TILE_SIZE]; // 'alpha' component float z[TILE_SIZE * TILE_SIZE]; // 'depth' component }; std::shared_ptr makeWriteTileMessage( const ispc::Tile &tile, bool hasAux); void unpackWriteTileMessage( WriteTileMessage *msg, ispc::Tile &tile, bool hasAux); size_t masterMsgSize( bool hasDepth, bool hasNormal, bool hasAlbedo, bool hasIDBuffers); /*! The message builder lets us abstractly fill messages of different * types, while keeping the underlying message structs POD so they're * easy to send around. */ class MasterTileMessageBuilder { bool hasDepth; bool hasNormal; bool hasAlbedo; bool hasIDBuffers; MasterTileMessage *header; public: std::shared_ptr message; MasterTileMessageBuilder(bool hasDepth, bool hasNormal, bool hasAlbedo, bool hasIDBuffers, vec2i coords, float error); void setColor(const vec4f *color); void setDepth(const float *depth); void setNormal(const vec3f *normal); void setAlbedo(const vec3f *albedo); void setPrimitiveID(const uint32 *primID); void setObjectID(const uint32 *geomID); void setInstanceID(const uint32 *instID); private: // Return the size in bytes of the color data in the message size_t colorBufferSize() const; // Return the size in bytes of the depth data in the message. Returns 0 if // depth is not being sent size_t depthBufferSize() const; // Return the size in bytes of the normal data in the message. Returns 0 if // normals are not being sent size_t normalBufferSize() const; // Return the size in bytes of the albedo data in the message. Returns 0 if // albedo is not being sent size_t albedoBufferSize() const; // Return the size in bytes of the ID data in the message. Returns 0 if // IDs are not being sent size_t idBufferSize() const; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/fb/TileOperation.cpp000066400000000000000000000026131456566705700247740ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "TileOperation.h" #include "DistributedFrameBuffer.h" #ifndef OSPRAY_TARGET_SYCL #include "fb/DistributedFrameBuffer_ispc.h" #endif namespace ospray { using DFB = DistributedFrameBuffer; void TileOperation::attach(DistributedFrameBuffer *) {} TileDesc::TileDesc(const vec2i &begin, size_t tileID, size_t ownerID) : begin(begin), tileID(tileID), ownerID(ownerID) {} LiveTileOperation::LiveTileOperation( DFB *dfb, const vec2i &begin, size_t tileID, size_t ownerID) : TileDesc(begin, tileID, ownerID), dfb(dfb) {} void LiveTileOperation::accumulate(const ispc::Tile &tile) { // accumulate, compute the finished normalized colors, and compute the // error, but don't write the finished colors into the color buffer yet // because pixel ops might modify them later Note: also used for FB_NONE error = DFB_accumulateTile((const ispc::VaryingTile *)&tile, (ispc::VaryingTile *)&finished, (ispc::VaryingTile *)&accum, (ispc::VaryingTile *)&variance, dfb->doAccum, dfb->hasVarianceBuffer); if (dfb->hasNormalBuffer || dfb->hasAlbedoBuffer) { ispc::DFB_accumulateAuxTile((const ispc::VaryingTile *)&tile, (ispc::Tile *)&finished, (ispc::VaryingTile *)&accum); } } void LiveTileOperation::tileIsFinished() { dfb->tileIsFinished(this); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/fb/TileOperation.h000066400000000000000000000074451456566705700244510ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include "common/OSPCommon.h" #include "common/StructShared.h" #include "fb/TileShared.h" #include "rkcommon/math/range.h" #include "rkcommon/math/vec.h" using namespace ospray; using namespace rkcommon::math; namespace ospray { struct DistributedFrameBuffer; struct LiveTileOperation; // TODO: Probably should all be under mpi namespace as well /* Base class for tile operations which can be attached to a distributed * framebuffer. The attach method will be called multiple times on each * rank, to make an instance of the live tile operation for each tile owned * by the rank. * * The tileoperation will be kept associated with the specific renderFrame * call, and can track additional state as needed by the renderer. */ struct TileOperation { virtual ~TileOperation() = default; /* The attach method is called when the tile operation is first attached * to the framebuffer. */ virtual void attach(DistributedFrameBuffer *dfb); /* The makeTile method is called to make the live tile operation for each * live tile owned by the rank. */ virtual std::unique_ptr makeTile( DistributedFrameBuffer *dfb, const vec2i &tileBegin, size_t tileID, size_t ownerID) = 0; virtual std::string toString() const = 0; }; /* Base descriptor for a tile: its position in the frame buffer, * its ID and which rank actually owns the tile for running tile operations */ struct TileDesc { TileDesc(const vec2i &begin, size_t tileID, size_t ownerID); virtual ~TileDesc() = default; /*! returns whether this tile is one of this particular node's tiles */ virtual bool mine() const { return false; } vec2i begin; size_t tileID, ownerID; }; /* Base class for a tile operation which the current rank is responsible for * executing. Includes scratch space for storing results computed by the * tile operation */ struct LiveTileOperation : public TileDesc { LiveTileOperation(DistributedFrameBuffer *dfb, const vec2i &begin, size_t tileID, size_t ownerID); virtual ~LiveTileOperation() override = default; // Called at the beginning of each frame virtual void newFrame() = 0; bool mine() const override { return true; } /* Called for each Tile rendered locally or received over the * network for this image tile. */ virtual void process(const ispc::Tile &tile) = 0; /* Utility method provided to accumulate the finished tile data from the * passed tile into the "finished" tile data, which will be passed on to any * ImageOps or written to the framebuffer. * TODO: Maybe just manage this on the DFB side? */ void accumulate(const ispc::Tile &tile); /* Method to be called when the tile operation is finished and the computed * image written to the "finished" member of the struct */ void tileIsFinished(); DistributedFrameBuffer *dfb; // estimated variance of this tile float error{0.f}; // TODO: dynamically allocate to save memory when no ACCUM or VARIANCE // even more TODO: Tile contains much more data (e.g. AUX), but using only // the color buffer here ==> much wasted memory // also holds accumulated normal&albedo ispc::Tile __aligned(64) accum; ispc::Tile __aligned(64) variance; /* To be able to give the 'postaccum' pixel op a readily normalized tile we have to create a local copy (the tile stores only the accum value, and we cannot change this) */ // also holds normalized normal&albedo in AOS format ispc::Tile __aligned(64) finished; //! the rbga32-converted colors // TODO: dynamically allocate to save memory when only uint32 / I8 colors vec4f __aligned(64) color[TILE_SIZE * TILE_SIZE]; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/mpi_offload_worker_main.cpp000066400000000000000000000007051456566705700265030ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include #include #include #include #include #include "ospray/ospray.h" int main(int argc, const char **av) { std::vector args(av, av + argc); args.push_back("--osp:load-modules=mpi_offload"); args.push_back("--osp:device=mpiOffload"); argc = args.size(); ospInit(&argc, args.data()); return 0; } RenderKit-ospray-f2a61c2/modules/mpi/ospray/render/000077500000000000000000000000001456566705700224005ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/mpi/ospray/render/DistributedLoadBalancer.cpp000066400000000000000000000531201456566705700276170ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "DistributedLoadBalancer.h" #include #include #include #include #include "ObjectHandle.h" #include "WriteMultipleTileOperation.h" #include "camera/Camera.h" #include "common/DistributedWorld.h" #include "common/DynamicLoadBalancer.h" #include "common/MPICommon.h" #include "distributed/DistributedRenderer.h" #include "fb/DistributedFrameBuffer.h" #include "rkcommon/tasking/parallel_for.h" #include "rkcommon/tracing/Tracing.h" #include "rkcommon/utility/ArrayView.h" #include "rkcommon/utility/getEnvVar.h" namespace ospray { namespace mpi { using namespace mpicommon; using namespace rkcommon; DistributedLoadBalancer::DistributedLoadBalancer(ObjectHandle handle) : handle(handle) {} DistributedLoadBalancer::~DistributedLoadBalancer() { handle.free(); } std::pair DistributedLoadBalancer::renderFrame( FrameBuffer *_fb, Renderer *_renderer, Camera *camera, World *_world, bool /*wait*/) { auto *dfb = dynamic_cast(_fb); if (!dfb) { throw std::runtime_error( "Distributed Load Balancer only supports DistributedFrameBuffer!"); } auto *world = dynamic_cast(_world); if (!world) { throw std::runtime_error( "Distributed Load Balancer only supports DistributedWorld!"); } auto *renderer = dynamic_cast(_renderer); if (!renderer) { if (world->allRegions.size() == 1) { renderFrameReplicated(dfb, _renderer, camera, world); return std::make_pair(AsyncEvent(), AsyncEvent()); } else { throw std::runtime_error( "Distributed rendering requires a distributed renderer!"); } } if (dfb->getLastRenderer() != renderer) { dfb->setTileOperation(renderer->tileOperation(), renderer); } RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::beginEvent("renderFrameDistributed", "DistributedLB")); dfb->startNewFrame(renderer->errorThreshold); void *perFrameData = renderer->beginFrame(dfb, world); const size_t numRegions = world->allRegions.size(); RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::beginEvent("determineTilesForFrame", "DistributedLB")); std::vector> regionTileIds(world->myRegionIds.size()); const vec2i numTiles = dfb->getGlobalNumTiles(); const vec2i fbSize = dfb->getNumPixels(); for (size_t i = 0; i < world->myRegionIds.size(); ++i) { const size_t id = world->myRegionIds[i]; const auto &r = world->allRegions[id]; box3f proj = camera->projectBox(r); box2f screenRegion(vec2f(proj.lower) * fbSize, vec2f(proj.upper) * fbSize); // Pad the region a bit screenRegion.lower = max(screenRegion.lower - TILE_SIZE, vec2f(0.f)); screenRegion.upper = min(screenRegion.upper + TILE_SIZE, vec2f(fbSize)); // Skip regions that are completely behind the camera if (proj.upper.z < 0.f) { continue; } box2i tileRegion; tileRegion.lower = screenRegion.lower / TILE_SIZE; tileRegion.upper = vec2i(std::ceil(screenRegion.upper.x / TILE_SIZE), std::ceil(screenRegion.upper.y / TILE_SIZE)); tileRegion.upper = min(tileRegion.upper, numTiles); for (int y = tileRegion.lower.y; y < tileRegion.upper.y; ++y) { for (int x = tileRegion.lower.x; x < tileRegion.upper.x; ++x) { const uint32_t tileIndex = x + y * numTiles.x; const auto &owners = world->regionOwners[id]; const size_t numRegionOwners = owners.size(); const size_t ownerRank = std::distance(owners.begin(), owners.find(workerRank())); // TODO: Can we do a better than round-robin over all tiles // assignment here? It could be that we end up not evenly dividing // the workload. const bool regionTileOwner = (tileIndex % numRegionOwners) == ownerRank; // If we're the owner and this tile isn't completed by adaptive // refinement, we need to render it if (regionTileOwner) { regionTileIds[i].push_back(tileIndex); } } } } // Set up the DFB sparse layers for each region we're rendering locally // We need one SparseFB layer in the DFB per region we're rendering locally dfb->setSparseFBLayerCount(world->myRegionIds.size()); for (size_t i = 0; i < world->myRegionIds.size(); ++i) { // Layer 0 is the base "background" tiles, regions are rendered to // layers 1..# regions + 1 auto *layer = dfb->getSparseFBLayer(i + 1); // Check if this layer already stores the tiles we want, and if so don't // reset it const utility::ArrayView layerTiles = layer->getTileIDs(); // TODO: it'd be nice if we had some other change tracking that would let us // know when we have different tiles rather than having to check the lists // of IDs against each other. // If this is a new FB, or the camera/scene has changed, we should set the // new tiles because they've probably changed. If nothing in the scene is // different from the previous render, then we don't need to set new tiles // because we're just accumulating. if (layerTiles.size() != regionTileIds[i].size() || !std::equal( layerTiles.begin(), layerTiles.end(), regionTileIds[i].begin())) { layer->setTiles(regionTileIds[i]); } } RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent("renderLocalData", "DistributedLB"); }); #ifdef OSPRAY_TARGET_SYCL /* For GPU: Need further refactoring to run rendering async for multiple * region per rank configs. Right now this is serial to avoid a race condition * on the SYCL queue. */ tasking::serial_for(dfb->getSparseLayerCount(), [&](size_t layer) #else tasking::parallel_for(dfb->getSparseLayerCount(), [&](size_t layer) #endif { // Just render the background color and compute visibility information for // the tiles we own for layer "0" SparseFrameBuffer *sparseFb = dfb->getSparseFBLayer(layer); if (sparseFb->getNumTiles() == 0) { return; } RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::beginEvent("setupLayerRendering", "DistributedLB")); // Explicitly avoiding std::vector because we need to match ISPC's // memory layout const utility::ArrayView tileIDs = sparseFb->getTileIDs(); // We use uint8 instead of bool to avoid hitting UB with differing "true" // values used by ISPC and C++ BufferShared regionVisible( sparseFb->getISPCDevice().getIspcrtContext(), numRegions * sparseFb->getNumTiles()); std::memset(regionVisible.sharedPtr(), 0, regionVisible.size()); // Compute visibility for the tasks we're rendering RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent("computeRegionVisibility", "DistributedLB"); }); renderer->computeRegionVisibility(sparseFb, camera, world, regionVisible.sharedPtr(), perFrameData, sparseFb->getRenderTaskIDs()); RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); // If we're rendering the background tiles send them over now if (layer == 0) { RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::beginEvent("sendLayer0Tiles", "DistributedLB")); tasking::parallel_for(sparseFb->getNumTiles(), [&](size_t i) { // Don't send anything if this tile was finished due to adaptive // refinement if (dfb->tileError(tileIDs[i]) <= renderer->errorThreshold) { return; } // Just generate the bgtile properties the same way as the SparseFB // does to avoid having to read them back to the host Tile bgtile; bgtile.fbSize = sparseFb->getNumPixels(); bgtile.rcp_fbSize = rcp(vec2f(sparseFb->getNumPixels())); bgtile.region = sparseFb->getTileRegion(tileIDs[i]); bgtile.accumID = 0; bgtile.sortOrder = std::numeric_limits::max(); bgtile.generation = 0; bgtile.children = 0; bgtile.accumID = dfb->getFrameID(); for (size_t r = 0; r < numRegions; ++r) { if (regionVisible[numRegions * i + r]) { ++bgtile.children; } } // Fill the tile with the background color // TODO: Should replace this with a smaller metadata message so we don't // need to send a full tile std::fill( bgtile.r, bgtile.r + TILE_SIZE * TILE_SIZE, renderer->bgColor.x); std::fill( bgtile.g, bgtile.g + TILE_SIZE * TILE_SIZE, renderer->bgColor.y); std::fill( bgtile.b, bgtile.b + TILE_SIZE * TILE_SIZE, renderer->bgColor.z); std::fill( bgtile.a, bgtile.a + TILE_SIZE * TILE_SIZE, renderer->bgColor.w); std::fill(bgtile.z, bgtile.z + TILE_SIZE * TILE_SIZE, std::numeric_limits::infinity()); dfb->setTile(bgtile); }); RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); } else { // If we're rendering a region, render it and send over the tile data RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::beginEvent("renderRegionData", "DistributedLB"); rkcommon::tracing::beginEvent("initRegionTaskIDs", "DistributedLB"); rkcommon::tracing::setCounter( "regionTileCount", sparseFb->getNumTiles()); }); sparseFb->beginFrame(); const size_t rid = world->myRegionIds[layer - 1]; RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent("renderRegionTasks", "DistributedLB"); }); renderer->renderRegionTasks(sparseFb, camera, world, world->allRegions[rid], perFrameData, sparseFb->getRenderTaskIDs()); RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent("readbackRegionTiles", "DistributedLB"); }); const auto tiles = sparseFb->getTiles(); RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent("sendRegionTiles", "DistributedLB"); }); tasking::parallel_for(tiles.size(), [&](size_t i) { if (!regionVisible[numRegions * i + rid] || dfb->tileError(tileIDs[i]) <= renderer->errorThreshold) { return; } Tile ®ionTile = tiles[i]; regionTile.generation = 1; regionTile.children = 0; regionTile.accumID = dfb->getFrameID(); dfb->setTile(regionTile); }); RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::endEvent(); }); } }); RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent("waitUntilFinished", "DistributedLB"); }); dfb->waitUntilFinished(); RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent("postProcess", "DistributedLB"); }); // TODO: We can start to pipeline the post processing here, // but needs support from the rest of the async tasking from // MPI tasks. Right now we just run on a separate thread. dfb->postProcess(true); dfb->setCompletedEvent(OSP_FRAME_FINISHED); RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::endEvent(); }); return std::make_pair(AsyncEvent(), AsyncEvent()); } void DistributedLoadBalancer::renderFrameReplicated(DistributedFrameBuffer *dfb, Renderer *renderer, Camera *camera, DistributedWorld *world) { int enableStaticBalancer = 0; auto OSPRAY_STATIC_BALANCER = utility::getEnvVar("OSPRAY_STATIC_BALANCER"); enableStaticBalancer = OSPRAY_STATIC_BALANCER.value_or(0); RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::beginEvent("renderFrameReplicated", "DistributedLB")); std::shared_ptr tileOperation = nullptr; if (dfb->getLastRenderer() != renderer) { tileOperation = std::make_shared(); dfb->setTileOperation(tileOperation, renderer); } else { tileOperation = dfb->getTileOperation(); } RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::beginEvent("startNewFrame", "DistributedLB")); dfb->startNewFrame(renderer->errorThreshold); void *perFrameData = renderer->beginFrame(dfb, world); RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent("renderLocalTiles", "DistributedLB"); }); if (enableStaticBalancer) { renderFrameReplicatedStaticLB(dfb, renderer, camera, world, perFrameData); } else { renderFrameReplicatedDynamicLB(dfb, renderer, camera, world, perFrameData); } RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent("waitUntilFinished", "DistributedLB"); }); dfb->waitUntilFinished(); RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent("postProcess", "DistributedLB"); }); // TODO: We can start to pipeline the post processing here, // but needs support from the rest of the async tasking from // MPI tasks. Right now we just run on a separate thread. dfb->postProcess(true); dfb->setCompletedEvent(OSP_FRAME_FINISHED); RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::endEvent(); }); } std::string DistributedLoadBalancer::toString() const { return "ospray::mpi::Distributed"; } void DistributedLoadBalancer::renderFrameReplicatedDynamicLB( DistributedFrameBuffer *dfb, Renderer *renderer, Camera *camera, DistributedWorld *world, void *perFrameData) { bool askedForWork = false; const int ALLTILES = dfb->getGlobalTotalTiles(); int NTILES = ALLTILES / workerSize(); // NOTE(jda) - If all tiles do not divide evenly among all worker ranks // (a.k.a. ALLTILES / worker.size has a remainder), then // some ranks will have one extra tile to do. Thus NTILES // is incremented if we are one of those ranks. if ((ALLTILES % workerSize()) > workerRank()) NTILES++; // Do not pass all tiles at once, this way if other ranks want to steal // work, they can // We target 1/3rd of tiles per-round by default to balance between executing // work locally and allowing work to be stolen for load balancing. // This can be overridden by the environment variable // OSPRAY_MPI_LB_TILES_PER_ROUND const float percentTilesPerRound = utility::getEnvVar("OSPRAY_MPI_LB_TILES_PER_ROUND") .value_or(0.33f); const int maxTilesPerRound = std::ceil(NTILES * percentTilesPerRound); const float minActiveTilesPercent = utility::getEnvVar("OSPRAY_MPI_LB_MIN_ACTIVE_TILES") .value_or(0.25f); const int minActiveTiles = (ALLTILES / workerSize()) * minActiveTilesPercent; // Avoid division by 0 for the case that this rank doesn't have any tiles int numRounds = 0; int tilesPerRound = 0; int remainTiles = 0; if (NTILES > 0) { numRounds = std::max(NTILES / maxTilesPerRound, 1); tilesPerRound = NTILES / numRounds; remainTiles = NTILES % numRounds; } int terminatedTiles = 0; auto dynamicLB = make_unique(handle, ALLTILES); mpicommon::barrier(dfb->getMPIGroup().comm).wait(); int totalActiveTiles = ALLTILES; // push current work to workQueue for (int i = 0; i < numRounds; i++) { Work myWork; myWork.ntasks = tilesPerRound; myWork.offset = i * tilesPerRound; myWork.ownerRank = workerRank(); dynamicLB->addWork(myWork); } // Extra round for any remainder tiles if (remainTiles > 0) { Work myWork; myWork.ntasks = remainTiles; myWork.offset = numRounds * tilesPerRound; myWork.ownerRank = workerRank(); dynamicLB->addWork(myWork); } RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::beginEvent( "localRenderLoop", "DistributedLB,Dynamic")); const int sparseFbChannelFlags = dfb->getChannelFlags() & ~(OSP_FB_ACCUM | OSP_FB_VARIANCE); auto sparseFb = rkcommon::make_unique(dfb->getISPCDevice(), dfb->getNumPixels(), dfb->getColorBufferFormat(), sparseFbChannelFlags); while (0 < totalActiveTiles) { Work currentWorkItem; if (0 < dynamicLB->getWorkSize()) { currentWorkItem = dynamicLB->getWorkItemFront(); askedForWork = false; } if (0 < currentWorkItem.ntasks) { RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::beginEvent( "initTaskTileIDs", "DistributedLB,Dynamic")); // Allocate a sparse framebuffer to hold the render output data std::vector taskTileIDs; taskTileIDs.reserve(currentWorkItem.ntasks); for (int i = 0; i < currentWorkItem.ntasks; ++i) { const int tileID = (i + currentWorkItem.offset) * workerSize() + currentWorkItem.ownerRank; // Only render tiles if they haven't reached the error threshold if (dfb->tileError(tileID) > renderer->errorThreshold) { taskTileIDs.push_back(tileID); } } RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); // If all the tiles we were assigned are already finished due to adaptive // termination we have nothing to render locally so just mark the tasks // complete if (!taskTileIDs.empty()) { RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::beginEvent( "setSparseFBTiles", "DistributedLB,Dynamic")); // Set the tiles and fill the right accumID for them sparseFb->setTiles(taskTileIDs); sparseFb->beginFrame(); sparseFb->setFrameID(dfb->getFrameID()); RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent("renderTasks", "DistributedLB,Dynamic"); }); renderer->renderTasks(sparseFb.get(), camera, world, perFrameData, sparseFb->getRenderTaskIDs( renderer->errorThreshold, renderer->spp)); RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent( "readbackTiles", "DistributedLB,Dynamic"); }); // TODO: Now the tile setting happens as a bulk-sync operation after // rendering, because we still need to send them through the compositing // pipeline. The ISPC-side rendering code doesn't know about this and in // the future wouldn't be able to do it // One option with the Dynamic LB would be to at least ping-poing // sparseFb's, one is being rendered into while tiles from the previous // task set are sent out const utility::ArrayView tiles = sparseFb->getTiles(); RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent("sendTiles", "DistributedLB,Dynamic"); }); tasking::parallel_for(tiles.size(), [&](size_t i) { Tile &tile = tiles[i]; tile.accumID = dfb->getFrameID(); dfb->setTile(tile); }); } RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); // Mark the set of tasks as complete dynamicLB->sendTerm(currentWorkItem.ntasks); terminatedTiles = terminatedTiles + currentWorkItem.ntasks; } if (0 < terminatedTiles) { dynamicLB->updateActiveTasks(terminatedTiles); } totalActiveTiles = dynamicLB->getActiveTasks(); terminatedTiles = 0; // if the total active tiles over all workers is more than some min, // request work if (currentWorkItem.ntasks <= 0 && minActiveTiles < totalActiveTiles && !askedForWork) { dynamicLB->requestWork(); askedForWork = true; } } RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); // We need to wait for the other ranks to finish here to keep our local DLB // alive to respond to any work requests that come in while other ranks // finish their final local set of tasks mpicommon::barrier(dfb->getMPIGroup().comm).wait(); } void DistributedLoadBalancer::renderFrameReplicatedStaticLB( DistributedFrameBuffer *dfb, Renderer *renderer, Camera *camera, DistributedWorld *world, void *perFrameData) { SparseFrameBuffer *ownedTilesFb = dfb->getSparseFBLayer(0); // Note: these views are already in USM const utility::ArrayView tileIDs = ownedTilesFb->getTileIDs(); RKCOMMON_IF_TRACING_ENABLED( rkcommon::tracing::beginEvent("localRenderLoop", "DistributedLB,Static")); renderer->renderTasks(ownedTilesFb, camera, world, perFrameData, ownedTilesFb->getRenderTaskIDs(renderer->errorThreshold, renderer->spp)); RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent("readbackTiles", "DistributedLB,Static"); }); const utility::ArrayView tiles = ownedTilesFb->getTiles(); RKCOMMON_IF_TRACING_ENABLED({ rkcommon::tracing::endEvent(); rkcommon::tracing::beginEvent("sendTiles", "DistributedLB,Static"); }); // TODO: Now the tile setting happens as a bulk-sync operation after // rendering, because we still need to send them through the compositing // pipeline. The ISPC-side rendering code doesn't know about this and in the // future wouldn't be able to do it tasking::parallel_for(tiles.size(), [&](size_t i) { // Don't send anything if this tile was finished due to adaptive // refinement if (dfb->tileError(tileIDs[i]) <= renderer->errorThreshold) { return; } dfb->setTile(tiles[i]); }); RKCOMMON_IF_TRACING_ENABLED(rkcommon::tracing::endEvent()); } } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/render/DistributedLoadBalancer.h000066400000000000000000000031031456566705700272600ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef OSPRAY_TARGET_SYCL #include #endif #include "../fb/DistributedFrameBuffer.h" #include "ObjectHandle.h" #include "camera/Camera.h" #include "common/World.h" #include "render/LoadBalancer.h" namespace ospray { namespace mpi { struct DistributedWorld; /* The distributed load balancer manages both data and image * parallel distributed rendering, based on the renderer and * world configuration. Distributed renderers will use distributed * rendering, while a non-distributed renderer with a world with * one global region will give image-parallel rendering */ struct DistributedLoadBalancer : public TiledLoadBalancer { DistributedLoadBalancer(ObjectHandle handle); ~DistributedLoadBalancer() override; std::pair renderFrame(FrameBuffer *fb, Renderer *renderer, Camera *camera, World *world, bool wait = true) override; void renderFrameReplicated(DistributedFrameBuffer *dfb, Renderer *renderer, Camera *camera, DistributedWorld *world); std::string toString() const override; private: void renderFrameReplicatedDynamicLB(DistributedFrameBuffer *dfb, Renderer *renderer, Camera *camera, DistributedWorld *world, void *perFrameData); void renderFrameReplicatedStaticLB(DistributedFrameBuffer *dfb, Renderer *renderer, Camera *camera, DistributedWorld *world, void *perFrameData); ObjectHandle handle; }; } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/render/ThreadedRenderTask.h000066400000000000000000000040321456566705700262530ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include // ospray #include "DistributedLoadBalancer.h" #include "common/Future.h" #include "fb/FrameBuffer.h" namespace ospray { namespace mpi { /* An asynchronous render task which runs on a thread independent * of the tasking system's thread pool */ struct ThreadedRenderTask : public Future { ThreadedRenderTask(FrameBuffer *, const std::shared_ptr &, std::function fcn); ~ThreadedRenderTask() override; bool isFinished(OSPSyncEvent event = OSP_TASK_FINISHED) override; void wait(OSPSyncEvent event) override; void cancel() override; float getProgress() override; float getTaskDuration() override; private: Ref fb; std::shared_ptr loadBalancer; std::atomic taskDuration{0.f}; std::atomic finished; std::thread thread; }; // Inlined definitions ////////////////////////////////////////////////////// inline ThreadedRenderTask::ThreadedRenderTask(FrameBuffer *_fb, const std::shared_ptr &_loadBalancer, std::function fcn) : fb(_fb), loadBalancer(_loadBalancer), finished(false) { thread = std::thread([this, fcn]() { taskDuration = fcn(); finished = true; }); } inline ThreadedRenderTask::~ThreadedRenderTask() { if (thread.joinable()) { thread.join(); } } inline bool ThreadedRenderTask::isFinished(OSPSyncEvent event) { return finished == true || fb->getLatestCompleteEvent() >= event; } inline void ThreadedRenderTask::wait(OSPSyncEvent event) { if (event == OSP_TASK_FINISHED) { while (!finished) { std::this_thread::yield(); } } else fb->waitForEvent(event); } inline void ThreadedRenderTask::cancel() { fb->cancelFrame(); } inline float ThreadedRenderTask::getProgress() { return fb->getCurrentProgress(); } inline float ThreadedRenderTask::getTaskDuration() { return taskDuration.load(); } } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/render/WriteMultipleTileOperation.cpp000066400000000000000000000124751456566705700304220ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "WriteMultipleTileOperation.h" #include "fb/DistributedFrameBuffer.h" #include "fb/DistributedFrameBufferShared.h" #ifndef OSPRAY_TARGET_SYCL #include "fb/DistributedFrameBuffer_ispc.h" #endif namespace ospray { using namespace rkcommon; /* LiveTileOperation for image-parallel rendering, where the same image tile * could optionally be rendered by multiple ranks. */ struct LiveWriteMultipleTile : public LiveTileOperation { LiveWriteMultipleTile(DistributedFrameBuffer *dfb, const vec2i &begin, size_t tileID, size_t ownerID, WriteMultipleTileOperation *parent); void newFrame() override; // accumulate into ACCUM and VARIANCE, and for last tile read-out void process(const ispc::Tile &tile) override; private: int maxAccumID = 0; size_t instances = 1; bool writeOnceTile = true; // defer accumulation to get correct variance estimate ispc::Tile bufferedTile; bool tileBuffered = false; WriteMultipleTileOperation *parent = nullptr; // serialize when multiple instances of this tile arrive at the same time std::mutex mutex; }; LiveWriteMultipleTile::LiveWriteMultipleTile(DistributedFrameBuffer *dfb, const vec2i &begin, size_t tileID, size_t ownerID, WriteMultipleTileOperation *parent) : LiveTileOperation(dfb, begin, tileID, ownerID), parent(parent) {} void LiveWriteMultipleTile::newFrame() { maxAccumID = 0; instances = parent->tileInstances[tileID]; writeOnceTile = instances <= 1; tileBuffered = false; } void LiveWriteMultipleTile::process(const ispc::Tile &tile) { if (writeOnceTile) { finished.region = tile.region; finished.fbSize = tile.fbSize; finished.rcp_fbSize = tile.rcp_fbSize; accumulate(tile); tileIsFinished(); return; } bool done = false; if (tile.accumID == 0) { finished.region = tile.region; finished.fbSize = tile.fbSize; finished.rcp_fbSize = tile.rcp_fbSize; const auto bytes = tile.region.size().y * (TILE_SIZE * sizeof(float)); memcpy(accum.z, tile.z, bytes); memcpy(finished.z, tile.z, bytes); } { std::lock_guard lock(mutex); maxAccumID = std::max(maxAccumID, tile.accumID); if (!tileBuffered && (tile.accumID & 1) == 0) { memcpy(&bufferedTile, &tile, sizeof(ispc::Tile)); tileBuffered = true; } else { ispc::DFB_accumulateTileSimple((const ispc::VaryingTile *)&tile, (ispc::VaryingTile *)&accum, (ispc::VaryingTile *)&variance); if (dfb->hasNormalBuf() || dfb->hasAlbedoBuf()) { ispc::DFB_accumulateAuxTile((const ispc::VaryingTile *)&tile, (ispc::Tile *)&finished, (ispc::VaryingTile *)&accum); } } done = --instances == 0; } if (done) { auto sz = tile.region.size(); if ((maxAccumID & 1) == 0) { // if maxAccumID is even, variance buffer is one accumulated tile // short, which leads to vast over-estimation of variance; thus // estimate variance now, when accum buffer is also one (the buffered) // tile short const float prevErr = DFB_computeErrorForTile(sz, (ispc::VaryingTile *)&accum, (ispc::VaryingTile *)&variance, maxAccumID - 1); // use maxAccumID for correct normalization // this is OK, because both accumIDs are even bufferedTile.accumID = maxAccumID; accumulate(bufferedTile); error = prevErr; } else { // correct normalization is with maxAccumID, which is odd here bufferedTile.accumID = maxAccumID; // but original bufferedTile.accumID is always even and thus won't be // accumulated into variance buffer DFB_accumulateTile((const ispc::VaryingTile *)&bufferedTile, (ispc::VaryingTile *)&finished, (ispc::VaryingTile *)&accum, (ispc::VaryingTile *)&variance, dfb->doAccumulation(), // disable accumulation of variance false); if (dfb->hasNormalBuf() || dfb->hasAlbedoBuf()) { ispc::DFB_accumulateAuxTile((const ispc::VaryingTile *)&bufferedTile, (ispc::Tile *)&finished, (ispc::VaryingTile *)&accum); } // but still need to update the error error = DFB_computeErrorForTile(sz, (ispc::VaryingTile *)&accum, (ispc::VaryingTile *)&variance, maxAccumID); } tileIsFinished(); } } WriteMultipleTileOperation::~WriteMultipleTileOperation() { if (mpiGroup.comm != MPI_COMM_NULL) { MPI_Comm_free(&mpiGroup.comm); } } void WriteMultipleTileOperation::attach(DistributedFrameBuffer *dfb) { if (mpiGroup.comm != MPI_COMM_NULL) { MPI_Comm_free(&mpiGroup.comm); } mpiGroup = mpicommon::worker.dup(); tileInstances.resize(dfb->getGlobalTotalTiles(), 1); } std::unique_ptr WriteMultipleTileOperation::makeTile( DistributedFrameBuffer *dfb, const vec2i &tileBegin, size_t tileID, size_t ownerID) { return make_unique( dfb, tileBegin, tileID, ownerID, this); } std::string WriteMultipleTileOperation::toString() const { return "ospray::WriteMultipleTileOperation"; } void WriteMultipleTileOperation::syncTileInstances() { mpicommon::bcast( tileInstances.data(), tileInstances.size(), MPI_INT, 0, mpiGroup.comm) .wait(); } } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/render/WriteMultipleTileOperation.h000066400000000000000000000013771456566705700300660ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include "../fb/TileOperation.h" #include "common/MPICommon.h" #include "rkcommon/containers/AlignedVector.h" namespace ospray { struct WriteMultipleTileOperation : public TileOperation { virtual ~WriteMultipleTileOperation() override; void attach(DistributedFrameBuffer *dfb) override; std::unique_ptr makeTile(DistributedFrameBuffer *dfb, const vec2i &tileBegin, size_t tileID, size_t ownerID) override; std::string toString() const override; void syncTileInstances(); rkcommon::containers::AlignedVector tileInstances; mpicommon::Group mpiGroup; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/render/distributed/000077500000000000000000000000001456566705700247225ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/mpi/ospray/render/distributed/AlphaCompositeTileOperation.cpp000066400000000000000000000111411456566705700330330ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "AlphaCompositeTileOperation.h" #include #include "fb/DistributedFrameBuffer.h" #ifndef OSPRAY_TARGET_SYCL #include "fb/DistributedFrameBuffer_ispc.h" #endif namespace ospray { struct BufferedTile { ispc::Tile tile; /*! determines order of this tile relative to other tiles. Tiles will get blended with the 'over' operator in increasing 'BufferedTile::sortOrder' value */ float sortOrder; }; /* LiveTileOperation for data-parallel or hybrid-parallel rendering, where * different (or partially shared) data is rendered on each rank */ struct LiveAlphaCompositeTile : public LiveTileOperation { LiveAlphaCompositeTile(DistributedFrameBuffer *dfb, const vec2i &begin, size_t tileID, size_t ownerID); void newFrame() override; void process(const ispc::Tile &tile) override; private: std::vector> bufferedTiles; int currentGeneration{0}; int expectedInNextGeneration{0}; int missingInCurrentGeneration{1}; std::mutex mutex; void reportCompositingError(const vec2i &tile); }; LiveAlphaCompositeTile::LiveAlphaCompositeTile(DistributedFrameBuffer *dfb, const vec2i &begin, size_t tileID, size_t ownerID) : LiveTileOperation(dfb, begin, tileID, ownerID) {} void LiveAlphaCompositeTile::newFrame() { std::lock_guard lock(mutex); currentGeneration = 0; expectedInNextGeneration = 0; missingInCurrentGeneration = 1; if (!bufferedTiles.empty()) { handleError(OSP_INVALID_OPERATION, std::to_string(mpicommon::workerRank()) + " is starting with buffered tiles!"); } } void LiveAlphaCompositeTile::process(const ispc::Tile &tile) { std::lock_guard lock(mutex); { auto addTile = rkcommon::make_unique(); std::memcpy(&addTile->tile, &tile, sizeof(tile)); bufferedTiles.push_back(std::move(addTile)); } if (tile.generation == currentGeneration) { --missingInCurrentGeneration; expectedInNextGeneration += tile.children; if (missingInCurrentGeneration < 0) { reportCompositingError(tile.region.lower); } while (missingInCurrentGeneration == 0 && expectedInNextGeneration > 0) { currentGeneration++; missingInCurrentGeneration = expectedInNextGeneration; expectedInNextGeneration = 0; for (uint32_t i = 0; i < bufferedTiles.size(); i++) { const BufferedTile *bt = bufferedTiles[i].get(); if (bt->tile.generation == currentGeneration) { --missingInCurrentGeneration; expectedInNextGeneration += bt->tile.children; } if (missingInCurrentGeneration < 0) { reportCompositingError(tile.region.lower); } } } } if (missingInCurrentGeneration < 0) { reportCompositingError(tile.region.lower); } if (missingInCurrentGeneration == 0) { // Sort for back-to-front blending // TODO: This is redundant with sortAndBlend. We should actually just do // this tile level sort, not sorting each pixel /* std::sort(bufferedTiles.begin(), bufferedTiles.end(), [](const std::unique_ptr &a, const std::unique_ptr &b) { return a->tile.sortOrder > b->tile.sortOrder; }); */ Tile **tileArray = STACK_BUFFER(Tile *, bufferedTiles.size()); std::transform(bufferedTiles.begin(), bufferedTiles.end(), tileArray, [](std::unique_ptr &t) { return &t->tile; }); ispc::DFB_sortAndBlendFragments( (ispc::VaryingTile **)tileArray, bufferedTiles.size()); finished.region = tile.region; finished.fbSize = tile.fbSize; finished.rcp_fbSize = tile.rcp_fbSize; accumulate(bufferedTiles[0]->tile); bufferedTiles.clear(); tileIsFinished(); } } void LiveAlphaCompositeTile::reportCompositingError(const vec2i &tile) { std::stringstream str; str << "negative missing on " << mpicommon::workerRank() << ", missingInCurrent = " << missingInCurrentGeneration << ", expectedInNext = " << expectedInNextGeneration << ", currentGeneration = " << currentGeneration << ", tile = " << tile; handleError(OSP_INVALID_OPERATION, str.str()); } std::unique_ptr AlphaCompositeTileOperation::makeTile( DistributedFrameBuffer *dfb, const vec2i &tileBegin, size_t tileID, size_t ownerID) { return make_unique(dfb, tileBegin, tileID, ownerID); } std::string AlphaCompositeTileOperation::toString() const { return "ospray::AlphaCompositeTileOperation"; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/render/distributed/AlphaCompositeTileOperation.h000066400000000000000000000007231456566705700325040ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include "../../fb/TileOperation.h" namespace ospray { struct AlphaCompositeTileOperation : public TileOperation { std::unique_ptr makeTile(DistributedFrameBuffer *dfb, const vec2i &tileBegin, size_t tileID, size_t ownerID) override; std::string toString() const override; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/render/distributed/DistributedRaycast.cpp000066400000000000000000000104011456566705700312330ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include #include #include #include #include #include "common/Data.h" #include "lights/AmbientLight.h" #include "lights/Light.h" #include "rkcommon/tasking/parallel_for.h" #include "rkcommon/utility/getEnvVar.h" #include "AlphaCompositeTileOperation.h" #include "DistributedRaycast.h" #include "common/DistributedWorld.h" #include "fb/DistributedFrameBuffer.h" // ispc exports #ifndef OSPRAY_TARGET_SYCL #include "render/distributed/DistributedRaycast_ispc.h" #else #include "common/FeatureFlags.ih" namespace ispc { SYCL_EXTERNAL void DistributedRaycast_renderRegionToTileTask(void *_self, void *_fb, void *_camera, void *_world, const void *_region, void *perFrameData, const void *_taskIDs, const int taskIndex0, const uniform FeatureFlagsHandler &ffh); } #endif namespace ospray { namespace mpi { using namespace std::chrono; using namespace mpicommon; static bool DETAILED_LOGGING = false; // DistributedRaycastRenderer definitions ///////////////////////////////// DistributedRaycastRenderer::DistributedRaycastRenderer(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device), mpiGroup(mpicommon::worker.dup()) { DETAILED_LOGGING = utility::getEnvVar("OSPRAY_DP_API_TRACING").value_or(0); if (DETAILED_LOGGING) { auto job_name = utility::getEnvVar("OSPRAY_JOB_NAME").value_or("log"); std::string statsLogFile = job_name + std::string("-rank") + std::to_string(mpiGroup.rank) + ".txt"; statsLog = rkcommon::make_unique(statsLogFile.c_str()); } } DistributedRaycastRenderer::~DistributedRaycastRenderer() { MPI_Comm_free(&mpiGroup.comm); if (DETAILED_LOGGING) { *statsLog << "\n" << std::flush; } } void DistributedRaycastRenderer::commit() { Renderer::commit(); getSh()->aoSamples = getParam("aoSamples", 0); getSh()->aoRadius = getParam("aoDistance", 1e20f); getSh()->shadowsEnabled = getParam("shadows", false); getSh()->volumeSamplingRate = getParam("volumeSamplingRate", 1.f); } std::shared_ptr DistributedRaycastRenderer::tileOperation() { return std::make_shared(); } #ifndef OSPRAY_TARGET_SYCL void DistributedRaycastRenderer::renderRegionTasks(SparseFrameBuffer *fb, Camera *camera, DistributedWorld *world, const box3f ®ion, void *perFrameData, const utility::ArrayView &taskIDs) const { ispc::DistributedRaycast_renderRegionToTileTask(getSh(), fb->getSh(), camera->getSh(), world->getSh(), (ispc::box3f *)®ion, perFrameData, taskIDs.data(), taskIDs.size()); } #else void DistributedRaycastRenderer::renderRegionTasks(SparseFrameBuffer *fb, Camera *camera, DistributedWorld *world, const box3f ®ion, void *perFrameData, const utility::ArrayView &taskIDs) const { auto *rendererSh = getSh(); auto *fbSh = fb->getSh(); auto *cameraSh = camera->getSh(); auto *worldSh = world->getSh(); const uint32_t *taskIDsPtr = taskIDs.data(); const size_t numTasks = taskIDs.size(); auto event = device.getSyclQueue().submit([&](sycl::handler &cgh) { FeatureFlags ff = world->getFeatureFlags(); ff |= featureFlags; ff |= fb->getFeatureFlags(); ff |= camera->getFeatureFlags(); cgh.set_specialization_constant(ff); cgh.parallel_for(fb->getDispatchRange(numTasks), [=](sycl::nd_item<3> taskIndex, sycl::kernel_handler kh) { const box3f regionCopy = region; if (taskIndex.get_global_id(0) < numTasks) { ispc::FeatureFlagsHandler ffh(kh); ispc::DistributedRaycast_renderRegionToTileTask(&rendererSh->super, fbSh, cameraSh, worldSh, (ispc::box3f *)®ionCopy, perFrameData, taskIDsPtr, taskIndex.get_global_id(0), ffh); } }); }); event.wait_and_throw(); } #endif std::string DistributedRaycastRenderer::toString() const { return "ospray::mpi::DistributedRaycastRenderer"; } } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/render/distributed/DistributedRaycast.h000066400000000000000000000035701456566705700307110ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include // ospray #include "../../common/DistributedWorld.h" #include "DistributedRenderer.h" #include "camera/PerspectiveCamera.h" #include "common/MPICommon.h" // ispc shared #include "DistributedRaycastShared.h" namespace ospray { namespace mpi { /* The distributed raycast renderer supports rendering distributed * geometry and volume data, assuming that the data distribution is suitable * for sort-last compositing. Specifically, the data must be organized * among nodes such that each nodes region is convex and disjoint from the * others. The renderer uses the 'regions' data set on the distributed world * from the MPIDistributedDevice to determine the number of tiles to * render and expect for compositing. */ struct DistributedRaycastRenderer : public AddStructShared { DistributedRaycastRenderer(api::ISPCDevice &device); virtual ~DistributedRaycastRenderer() override; void commit() override; std::string toString() const override; std::shared_ptr tileOperation() override; #ifndef OSPRAY_TARGET_SYCL void renderRegionTasks(SparseFrameBuffer *fb, Camera *camera, DistributedWorld *world, const box3f ®ion, void *perFrameData, const utility::ArrayView &taskIDs) const override; #else void renderRegionTasks(SparseFrameBuffer *fb, Camera *camera, DistributedWorld *world, const box3f ®ion, void *perFrameData, const utility::ArrayView &taskIDs) const override; #endif private: // The communicator to use for collectives in the renderer mpicommon::Group mpiGroup; std::unique_ptr statsLog; }; } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/render/distributed/DistributedRaycast.ispc000066400000000000000000000356461456566705700314310ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "rkcommon/math/box.ih" #include "camera/Camera.ih" #include "camera/CameraDispatch.ih" #include "common/FeatureFlags.ih" #include "common/Instance.ih" #include "common/Intersect.ih" #include "common/VolumeIntervals.ih" #include "common/World.ih" #include "fb/FrameBufferDispatch.ih" #include "fb/RenderTaskDesc.ih" #include "math/random.ih" #include "math/sampling.ih" #include "render/Renderer.ih" #include "render/ScreenSample.ih" #include "render/materials/OBJ.ih" #include "render/scivis/surfaces.ih" #include "render/scivis/volumes.ih" #include "render/util.ih" #include "texture/Texture2D.ih" #include "volume/VolumetricModel.ih" #ifdef OSPRAY_ENABLE_VOLUMES #include "volume/Volume.ih" #include "volume/VolumetricModel.ih" #include "volume/transferFunction/LinearTransferFunction.ih" #include "volume/transferFunction/TransferFunctionDispatch.ih" #endif // c++ shared #include "DistributedRaycastShared.h" #include "common/DistributedWorldShared.h" #include "fb/FrameBufferShared.h" #include "fb/SparseFBShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE #ifdef OSPRAY_ENABLE_VOLUMES // The distributed raycast renderer uses its own volume interval integration // because we want to apply the jitter before offsetting our step size to stay // inside the region, not after. inline vec4f DRR_integrateVolumeInterval(const ScreenSample &sample, const VolumeInterval &interval, Ray &ray, uniform float samplingRate, const uniform FeatureFlagsHandler &ffh) { const uniform FeatureFlags ff = getFeatureFlags(ffh); VolumetricModel *varying volModel = interval.volumetricModel; // Note: required to WA compiler dropping symbols on link incorrectly if (volModel == NULL) { LinearTransferFunction_get(NULL, 0.f); } Ray transformedRay = ray; AffineSpace3f instanceRcpXfm = interval.instance->rcp_xfm; transformRay(transformedRay, instanceRcpXfm); uniform uint8 intervalIteratorBuffer[VKL_MAX_INTERVAL_ITERATOR_SIZE]; vec3f color = make_vec3f(0.f); float alpha = 0.f; foreach_unique (vm in volModel) { Volume *uniform volume = vm->volume; TransferFunction *uniform tf = vm->transferFunction; float time = 0.5f; VKLIntervalIterator intervalIterator = vklInitIntervalIteratorV(&vm->vklIntervalContext, (varying vkl_vec3f *)&ray.org, (varying vkl_vec3f *)&ray.dir, (varying vkl_range1f *)&interval.interval, #ifndef OSPRAY_TARGET_SYCL & #endif time, (void *uniform)intervalIteratorBuffer #ifdef OSPRAY_TARGET_SYCL , ff.volume #endif ); VKLInterval interval; while (vklIterateIntervalV(intervalIterator, &interval #ifdef OSPRAY_TARGET_SYCL , ff.volume #endif ) && alpha < 0.99f) { const float nominalSamplingDt = interval.nominalDeltaT / samplingRate; // initial sub interval, based on our renderer-defined sampling rate // and the volume's nominal dt box1f subInterval = make_box1f(interval.tRange.lower, min(interval.tRange.lower + nominalSamplingDt, interval.tRange.upper)); while (subInterval.upper - subInterval.lower > 0.f && alpha < 0.99f) { transformedRay.t0 = subInterval.lower + (subInterval.upper - subInterval.lower); const float dt = subInterval.upper - subInterval.lower; // Get volume sample vec3f p = transformedRay.org + transformedRay.t0 * transformedRay.dir; const float sample = vklComputeSampleV(&volume->vklSampler, (const varying vkl_vec3f *uniform) & p #ifdef OSPRAY_TARGET_SYCL , 0, time, ff.volume #endif ); if (!isnan(sample)) { vec4f sampleColorOpacity = TransferFunction_dispatch_get(vm->transferFunction, sample); sampleColorOpacity.w = 1.f - pow(1.f - sampleColorOpacity.w * vm->densityScale, dt / interval.nominalDeltaT); const float clampedOpacity = clamp(sampleColorOpacity.w); color = color + ((1.f - alpha) * clampedOpacity * make_vec3f(sampleColorOpacity)); alpha = alpha + ((1.f - alpha) * clampedOpacity); } // compute next sub interval subInterval.lower = subInterval.upper; subInterval.upper = min(subInterval.lower + nominalSamplingDt, interval.tRange.upper); } } } return make_vec4f(color, alpha); } #endif inline float computeAO(const DistributedRaycastRenderer *uniform self, const FrameBuffer *uniform fb, const World *uniform world, const varying vec3i &sampleID, const varying DifferentialGeometry &dg, const uniform FeatureFlagsHandler &ffh) { const uniform int &sampleCnt = self->aoSamples; const uniform int accumID = reduce_max(sampleID.z) * sampleCnt; // init TEA RNG // RandomTEA rng_state; varying RandomTEA *const uniform rng = &rng_state; RandomTEA_Constructor(rng, 0x290374, (fb->size.x * sampleID.y) + sampleID.x); const vec2f rot = RandomTEA_getFloats(rng); int hits = 0; const linear3f localToWorld = frame(dg.Ns); for (uniform int i = 0; i < sampleCnt; i++) { const vec2f halton = HaltonSequence_get2D(self->super.mathConstants, accumID + i); const vec2f r = CranleyPattersonRotation(halton, rot); const vec3f local_ao_dir = cosineSampleHemisphere(r); const vec3f ao_dir = localToWorld * local_ao_dir; if (dot(ao_dir, dg.Ns) < 0.05f) { // check below surface hits++; continue; } Ray ao_ray; setRay(ao_ray, dg.P, ao_dir, dg.epsilon, self->aoRadius); if (isOccluded(world, ao_ray, ffh)) hits++; } // the cosTheta of cosineSampleHemispherePDF and dot(shadingNormal, ao_dir) // cancel return 1.0f - (hits / (float)sampleCnt); } inline vec4f DRR_shadeSurface(const DistributedRaycastRenderer *uniform self, const FrameBuffer *uniform fb, const DistributedWorld *uniform world, const vec3i &sampleID, const Ray &ray, const DifferentialGeometry &dg, const uniform FeatureFlagsHandler &ffh) { // TODO: DRR should have its own support for OBJ material and lighting model vec3f surfaceColor = make_vec3f(dg.color); float opacity = 1.f; const OBJ *mat = (const OBJ *)dg.material; if (mat) { foreach_unique (m in mat) { surfaceColor = surfaceColor * m->Kd; opacity = m->d; if (valid(m->KdMap)) { vec4f kdFromMap = get4f(m->KdMap, dg); surfaceColor = surfaceColor * make_vec3f(kdFromMap); } } } // Just eyelight for now... const float eyeLightIntensity = absf(dot(dg.Ns, ray.dir)); vec3f color = surfaceColor * eyeLightIntensity; if (self->aoSamples > 0) { float ao = computeAO(self, fb, &world->super, sampleID, dg, ffh); color = color * ao; } return make_vec4f(color, opacity); #if 0 // TODO LIGHTS // Calculate shading for all lights for (uniform int i = 0; self->lights && i < self->numLights; i++) { const uniform Light *uniform l = self->lights[i]; const vec2f s = make_vec2f(0.0f); // sample center of area lights const Light_SampleRes light = l->sample(l, dg, s); // any potential contribution? if (reduce_max(light.weight) > 0.f) { float cosNL = dot(light.dir, info.shadingNormal); if (cosNL < 0.0f) continue; cosNL = abs(cosNL); const vec3f H = normalize(light.dir - ray.dir); const float cosNH = dot(H, info.shadingNormal); const vec3f specular = info.Ks * powf(cosNH, info.Ns); const vec3f diffuse = info.Kd * cosNL; const vec3f light_contrib = info.local_opacity * (diffuse + specular) * light.weight; if (self->shadowsEnabled) { const float max_contrib = reduce_max(light_contrib); if (max_contrib > self->super.minContribution) { vec3f P = dg.P; if (dot(dg.Ng, light.dir) < 0.0f) { P = P - (2.f * dg.epsilon) * dg.Ng; } Ray shadowRay; setRay(shadowRay, P, light.dir, 0.0f, light.dist, 0.5f); if (!isOccluded(model, shadowRay) && !(ghostModel && isOccluded(ghostModel, shadowRay))) { color = color + light_contrib; } } } else { color = color + light_contrib; } } } #endif } // TODO: Better separate geometry and volume code in this function inline void DRR_renderRegionSample(Renderer *uniform _self, SparseFB *uniform fb, DistributedWorld *uniform world, const box3f *uniform region, const vec2f ®ionInterval, void *uniform perFrameData, varying ScreenSample &sample, const uniform FeatureFlagsHandler &ffh) { DistributedRaycastRenderer *uniform self = (DistributedRaycastRenderer * uniform) _self; const uniform FeatureFlags ff = getFeatureFlags(ffh); Ray &geomRay = sample.ray; Ray volumeRay = sample.ray; traceRay(&world->super, geomRay, ffh); #ifdef OSPRAY_ENABLE_VOLUMES VolumeInterval volumeInterval; if (ff.volume) { traceVolumeRay(&world->super, volumeRay, volumeInterval); volumeInterval.interval.lower = max(volumeInterval.interval.lower, regionInterval.x); volumeInterval.interval.upper = min(volumeInterval.interval.upper, regionInterval.y); sample.z = min(geomRay.t, volumeInterval.interval.lower); } else #endif { sample.z = geomRay.t; } // TODO: Doesn't seem like much jittering happens with the volume integration vec4f outputColor = make_vec4f(0.f); while (outputColor.w < 0.99f) { const bool haveGeometryHit = ff.geometry ? hadHit(geomRay) && geomRay.t >= regionInterval.x && geomRay.t <= regionInterval.y : false; #ifdef OSPRAY_ENABLE_VOLUMES const bool haveVolumeHit = ff.volume ? hasInterval(volumeInterval) : false; const bool bothHit = haveGeometryHit && haveVolumeHit; const bool eitherHit = haveGeometryHit || haveVolumeHit; const bool volumeFirst = ff.volume ? volumeInterval.interval.lower < geomRay.t : false; #else const bool bothHit = false; const bool eitherHit = haveGeometryHit; #endif if (!eitherHit) { break; } vec4f volumeColor = make_vec4f(0.f); vec4f surfaceColor = make_vec4f(0.f); DifferentialGeometry dg; if (haveGeometryHit && ff.geometry) { postIntersect(&world->super, &self->super, dg, geomRay, DG_NG | DG_NS | DG_NORMALIZE | DG_FACEFORWARD | DG_COLOR | DG_TEXCOORD, ffh); surfaceColor = DRR_shadeSurface( self, &fb->super, world, sample.sampleID, geomRay, dg, ffh); } #ifdef OSPRAY_ENABLE_VOLUMES // Always just integrate the volume when it comes in front of the geometry if (haveVolumeHit && volumeFirst && ff.volume) { volumeInterval.interval.upper = min(geomRay.t, volumeInterval.interval.upper); // Keep the interval within the region volumeInterval.interval.lower = max(volumeInterval.interval.lower, regionInterval.x); volumeInterval.interval.upper = min(volumeInterval.interval.upper, regionInterval.y); // Offset the volume interval start to align to the same sampling steps // across each rank, and apply the same jitter for each pixel on all ranks float dt = 1.f /*was 'volModel->samplingStep*/ / self->volumeSamplingRate; float t0 = volumeInterval.interval.lower; volumeInterval.interval.lower = floor(t0 / dt) * dt; float jitter = Halton_sample2(sample.sampleID.z); int ix = sample.sampleID.x % 4; int iy = sample.sampleID.y % 4; int patternID = ix + 4 * iy; jitter += Halton_sample3(self->super.mathConstants, patternID); if (jitter > 1.f) { jitter -= 1.f; } volumeInterval.interval.lower += jitter * dt; if (volumeInterval.interval.lower < t0) { volumeInterval.interval.lower += dt; } // TODO: At edges when coloring all bricks the same I do still see // some edge/border artifacts setRay(volumeRay, volumeInterval.interval.lower, volumeInterval.interval.upper); volumeColor = DRR_integrateVolumeInterval( sample, volumeInterval, volumeRay, self->volumeSamplingRate, ffh); } #endif vec4f blendedColor = make_vec4f(0.f); if (bothHit) { blendedColor = volumeColor + (1.0f - volumeColor.w) * surfaceColor; } else { if (haveGeometryHit) blendedColor = surfaceColor; else blendedColor = volumeColor; } outputColor = outputColor + (1.0f - outputColor.w) * blendedColor; if (haveGeometryHit) setRay(geomRay, geomRay.t + dg.epsilon, regionInterval.y + 0.0001f); else setRay(geomRay, geomRay.t, geomRay.t0); // Step the volume ray forwards as well volumeRay = geomRay; traceRay(&world->super, geomRay, ffh); #ifdef OSPRAY_ENABLE_VOLUMES if (ff.volume) { traceVolumeRay(&world->super, volumeRay, volumeInterval); } #endif } sample.rgb = make_vec3f(outputColor); sample.alpha = outputColor.w; } // Exported functions ///////////////////////////////////////////////////////// #define renderRegionSampleFn DRR_renderRegionSample #include "render/distributed/DistributedRendererRenderTaskFn.inl" #undef renderRegionSampleFn #ifdef OSPRAY_TARGET_SYCL SYCL_EXTERNAL void DistributedRaycast_renderRegionToTileTask( void *uniform _self, void *uniform _fb, void *uniform _camera, void *uniform _world, const void *uniform _region, void *uniform perFrameData, const void *uniform _taskIDs, const int taskIndex0, const uniform FeatureFlagsHandler &ffh) { Renderer *uniform self = (Renderer * uniform) _self; SparseFB *uniform fb = (SparseFB * uniform) _fb; Camera *uniform camera = (Camera * uniform) _camera; DistributedWorld *uniform world = (DistributedWorld * uniform) _world; const box3f *uniform region = (const box3f *uniform)_region; const uint32 *uniform taskIDs = (const uint32 *uniform)_taskIDs; DR_default_renderRegionToTile( self, fb, camera, world, region, perFrameData, taskIDs, taskIndex0, ffh); } #else export void DistributedRaycast_renderRegionToTileTask(void *uniform _self, void *uniform _fb, void *uniform _camera, void *uniform _world, void *uniform _region, void *uniform perFrameData, void *uniform _taskIDs, uniform uint32 numTasks) { Renderer *uniform self = (Renderer * uniform) _self; SparseFB *uniform fb = (SparseFB * uniform) _fb; Camera *uniform camera = (Camera * uniform) _camera; DistributedWorld *uniform world = (DistributedWorld * uniform) _world; const box3f *uniform region = (const box3f *uniform)_region; const uint32 *uniform taskIDs = (const uint32 *uniform)_taskIDs; uniform FeatureFlagsHandler ffh; launch[numTasks] DR_default_renderRegionToTile( self, fb, camera, world, region, perFrameData, taskIDs, ffh); sync; } #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/mpi/ospray/render/distributed/DistributedRaycastShared.h000066400000000000000000000010411456566705700320270ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "render/RendererShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus struct DistributedRaycastRenderer { Renderer super; int aoSamples; float aoRadius; bool shadowsEnabled; float volumeSamplingRate; #ifdef __cplusplus DistributedRaycastRenderer() : aoSamples(0), aoRadius(1e20f), shadowsEnabled(false), volumeSamplingRate(1.f) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/mpi/ospray/render/distributed/DistributedRenderer.cpp000066400000000000000000000102541456566705700314010ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "DistributedRenderer.h" #include "../../common/DistributedWorld.h" #include "common/Instance.h" #include "geometry/GeometricModel.h" // ispc exports #ifndef OSPRAY_TARGET_SYCL #include "render/distributed/DistributedRenderer_ispc.h" #else #include "common/FeatureFlags.ih" namespace ispc { SYCL_EXTERNAL void DR_default_computeRegionVisibility(Renderer *uniform self, SparseFB *uniform fb, Camera *uniform camera, DistributedWorld *uniform world, uint8 *uniform regionVisible, void *uniform perFrameData, const uint32 *uniform taskIDs, const int taskIndex0, const uniform FeatureFlagsHandler &ff); } #endif namespace ospray { namespace mpi { DistributedRenderer::DistributedRenderer(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device), mpiGroup(mpicommon::worker.dup()) {} DistributedRenderer::~DistributedRenderer() { MPI_Comm_free(&mpiGroup.comm); } void DistributedRenderer::computeRegionVisibility(SparseFrameBuffer *fb, Camera *camera, DistributedWorld *world, uint8_t *regionVisible, void *perFrameData, const utility::ArrayView &taskIDs) const { #ifndef OSPRAY_TARGET_SYCL ispc::DistributedRenderer_computeRegionVisibility(getSh(), fb->getSh(), camera->getSh(), world->getSh(), regionVisible, perFrameData, taskIDs.data(), taskIDs.size()); #else auto *rendererSh = getSh(); auto *fbSh = fb->getSh(); auto *cameraSh = camera->getSh(); auto *worldSh = world->getSh(); const uint32_t *taskIDsPtr = taskIDs.data(); const size_t numTasks = taskIDs.size(); auto event = device.getSyclQueue().submit([&](sycl::handler &cgh) { FeatureFlags ff = world->getFeatureFlags(); ff.other = FFO_NONE; ff |= fb->getFeatureFlags(); ff |= camera->getFeatureFlags(); // Disable features we don't need for the region visibility computation ff.geometry = FFG_BOX; #ifdef OSPRAY_ENABLE_VOLUMES ff.volume = VKL_FEATURE_FLAGS_NONE; #endif cgh.set_specialization_constant(ff); cgh.parallel_for(fb->getDispatchRange(numTasks), [=](sycl::nd_item<3> taskIndex, sycl::kernel_handler kh) { if (taskIndex.get_global_id(0) < numTasks) { ispc::FeatureFlagsHandler ffh(kh); ispc::DR_default_computeRegionVisibility(rendererSh, fbSh, cameraSh, worldSh, regionVisible, perFrameData, taskIDsPtr, taskIndex.get_global_id(0), ffh); } }); }); event.wait_and_throw(); #endif } OSPPickResult DistributedRenderer::pick( FrameBuffer *fb, Camera *camera, World *world, const vec2f &screenPos) { OSPPickResult res; res.instance = nullptr; res.model = nullptr; res.primID = RTC_INVALID_GEOMETRY_ID; res.hasHit = false; int instID = RTC_INVALID_GEOMETRY_ID; int geomID = RTC_INVALID_GEOMETRY_ID; int primID = RTC_INVALID_GEOMETRY_ID; float depth = 1e20f; #ifndef OSPRAY_TARGET_SYCL // TODO for SYCL need to dispatch a kernel ispc::DistributedRenderer_pick(getSh(), fb->getSh(), camera->getSh(), world->getSh(), (const ispc::vec2f &)screenPos, (ispc::vec3f &)res.worldPosition[0], instID, geomID, primID, depth, res.hasHit); #endif // Find the closest picked object globally, only the rank // with this object will report the pick float globalDepth = 1e20f; mpicommon::allreduce( &depth, &globalDepth, 1, MPI_FLOAT, MPI_MIN, mpiGroup.comm) .wait(); res.hasHit = globalDepth < 1e20f && globalDepth == depth; if (res.hasHit) { auto *instance = (*world->instances)[instID]; auto *group = instance->group.ptr; if (!group->geometricModels) { res.hasHit = false; return res; } auto *model = (*group->geometricModels)[geomID]; instance->refInc(); model->refInc(); res.instance = (OSPInstance)instance; res.model = (OSPGeometricModel)model; res.primID = static_cast(primID); } return res; } } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/render/distributed/DistributedRenderer.h000066400000000000000000000036521456566705700310520ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "camera/Camera.h" #include "fb/DistributedFrameBuffer.h" #include "fb/TileOperation.h" #include "render/Renderer.h" // ispc shared #include "render/RendererShared.h" namespace ospray { namespace mpi { struct DistributedWorld; struct RegionInfo { int numRegions = 0; box3f *regions = nullptr; uint8_t *regionVisible = nullptr; }; struct DistributedRenderer : public AddStructShared { DistributedRenderer(api::ISPCDevice &device); ~DistributedRenderer() override; void computeRegionVisibility(SparseFrameBuffer *fb, Camera *camera, DistributedWorld *world, uint8_t *regionVisible, void *perFrameData, const utility::ArrayView &taskIDs) const; // Not used by distributed renderers AsyncEvent renderTasks(FrameBuffer *, Camera *, World *, void * /*perFrameData*/, const utility::ArrayView & /*taskIDs*/, bool /*wait*/) const override { return AsyncEvent(); } #ifndef OSPRAY_TARGET_SYCL virtual void renderRegionTasks(SparseFrameBuffer *fb, Camera *camera, DistributedWorld *world, const box3f ®ion, void *perFrameData, const utility::ArrayView &taskIDs) const = 0; #else virtual void renderRegionTasks(SparseFrameBuffer *fb, Camera *camera, DistributedWorld *world, const box3f ®ion, void *perFrameData, const utility::ArrayView &taskIDs) const = 0; #endif virtual std::shared_ptr tileOperation() = 0; // Picking in the distributed renderer needs to be clipped to the regions // specified to bound the local data OSPPickResult pick(FrameBuffer *fb, Camera *camera, World *world, const vec2f &screenPos) override; private: mpicommon::Group mpiGroup; }; } // namespace mpi } // namespace ospray RenderKit-ospray-f2a61c2/modules/mpi/ospray/render/distributed/DistributedRenderer.ispc000066400000000000000000000227641456566705700315660ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "OSPConfig.h" #include "fb/RenderTaskDesc.ih" #include "render/ScreenSample.ih" #include "rkcommon/math/vec.ih" #include "rkcommon/utility/random.ih" #include "camera/Camera.ih" #include "camera/CameraDispatch.ih" #include "common/FilterIntersect.ih" #include "common/Intersect.ih" #include "common/Ray.ih" #include "common/RayQueryContext.ih" #include "common/World.ih" #include "fb/RenderTaskDesc.ih" #include "fb/SparseFB.ih" #include "geometry/BoxesShared.h" #include "geometry/GeometryDispatch.ih" #include "math/random.ih" #include "render/ScreenSample.ih" #include "rkcommon/utility/random.ih" #include "texture/Texture2D.ih" // c++ shared #include "common/DistributedWorldShared.h" #include "fb/FrameBufferDispatch.ih" #include "fb/FrameBufferShared.h" #include "fb/SparseFBShared.h" #include "render/RendererShared.h" OSPRAY_BEGIN_ISPC_NAMESPACE struct RayQueryContextRegion { RTCRayQueryContext ectx; const FeatureFlagsHandler *uniform ffh; uint8 *regionVisible; }; RTC_SYCL_INDIRECTLY_CALLABLE unmasked void Regions_intersect_kernel( const RTCIntersectFunctionNArguments *uniform args) { // make sure to set the mask if (!args->valid[programIndex]) { return; } // We never mark hits because we want to find all hits along the ray to get // all visible regions args->valid[programIndex] = 0; Boxes *uniform self = (Boxes * uniform) args->geometryUserPtr; varying Ray *uniform ray = (varying Ray * uniform) args->rayhit; uniform int primID = args->primID; uniform box3f box = get_box3f(self->boxes, primID); // Note: not calling filterIntersectionBoth here because it will set the hit // on the ray, we don't want to record any hits so that we can find all // regions along the ray const Intersections isect = intersectBox(ray->org, ray->dir, box); if ((isect.entry.hit && isect.entry.t > ray->t0 && isect.entry.t <= ray->t) || (isect.exit.hit && isect.exit.t > ray->t0 && isect.exit.t <= ray->t)) { RayQueryContextRegion *uniform ctx = (RayQueryContextRegion * uniform) args->context; uint8 *uniform regionVisible = (uint8 * uniform) ctx->regionVisible; regionVisible[primID] = 0xff; } } #ifndef OSPRAY_TARGET_SYCL task #endif SYCL_EXTERNAL void DR_default_computeRegionVisibility(Renderer *uniform self, SparseFB *uniform fb, Camera *uniform camera, DistributedWorld *uniform world, uint8 *uniform regionVisible, void *uniform perFrameData, const uint32 *uniform taskIDs, #ifdef OSPRAY_TARGET_SYCL const int taskIndex0, #endif const uniform FeatureFlagsHandler &ffh) { ScreenSample screenSample; screenSample.z = inf; screenSample.alpha = 0.f; CameraSample cameraSample; uniform RenderTaskDesc taskDesc = FrameBuffer_dispatch_getRenderTaskDesc( &fb->super, taskIDs[taskIndex0], ffh); if (fb->super.cancelRender || isEmpty(taskDesc.region)) { return; } // Get the region visibility info for this tile uint8 *uniform tileRegionVisible = regionVisible + world->numRegions * SparseFB_getTileIndexForTask(fb, taskDesc.taskID); // Take fixed, consistent samples to determine if a region is really visible // for a tile. We can trace up to 5 rays, one through the center of the pixel // and one through each corner, or 4 (one through each corner), or just 1 // (through the middle). Tracing 5 against the boxes may be a bit much? It // shouldn't impact performance too badly, but is actually a lot of rays being // traced Alternatively we could just base this on the region projection, and // accept the more conservative bounds. This would require some benchmarking // to see where the scaling trade off hits of sending tiles we don't actually // need. // Right now just taking 1 sample, can benchmark this in the future and/or // refactor code further to use this result to do a scan/compaction on the // render task IDs to reduce tasks launched. Then the accumIDs can be sync'd // up again const uniform int nVisibilitySamples = 1; const uniform vec2f visibilitySamples[5] = {make_vec2f(0.5f, 0.5f), make_vec2f(0.0f, 0.0f), make_vec2f(1.0f, 0.0f), make_vec2f(0.0f, 1.0f), make_vec2f(1.0f, 1.0f)}; #ifdef OSPRAY_TARGET_SYCL for (int32 y = taskDesc.region.lower.y; y < taskDesc.region.upper.y; ++y) for (int32 x = taskDesc.region.lower.x; x < taskDesc.region.upper.x; ++x) { #else foreach_tiled (y = taskDesc.region.lower.y... taskDesc.region.upper.y, x = taskDesc.region.lower.x... taskDesc.region.upper.x) { #endif screenSample.sampleID.x = x; screenSample.sampleID.y = y; // set ray t value for early ray termination if we have a maximum depth // texture vec2f center = make_vec2f(screenSample.sampleID.x, screenSample.sampleID.y) + 0.5f; const float tMax = inf; // Renderer_getMaxDepth(&self->super, center * fb->super.rcpSize); for (uniform uint32 s = 0; s < nVisibilitySamples; s++) { screenSample.sampleID.z = s; cameraSample.screen.x = (screenSample.sampleID.x + visibilitySamples[s].x) * fb->super.rcpSize.x; cameraSample.screen.y = (screenSample.sampleID.y + visibilitySamples[s].y) * fb->super.rcpSize.y; // no DoF or MB per default cameraSample.lens.x = 0.0f; cameraSample.lens.y = 0.0f; cameraSample.time = 0.5f; Camera_dispatch_initRay(camera, screenSample.ray, cameraSample, ffh); screenSample.ray.t = min(screenSample.ray.t, tMax); if (world->regionScene) { uniform RayQueryContextRegion context; rtcInitRayQueryContext(&context.ectx); context.ffh = &ffh; context.regionVisible = tileRegionVisible; uniform RTCIntersectArguments intersectArgs; rtcInitIntersectArguments(&intersectArgs); // Use a custom intersection function instead of a global filter // function, since global filter functions were removed in Embree4 intersectArgs.intersect = (RTCIntersectFunctionN)Regions_intersect_kernel; intersectArgs.flags = RTC_RAY_QUERY_FLAG_COHERENT; intersectArgs.feature_mask = (uniform RTCFeatureFlags)(RTC_FEATURE_FLAG_INSTANCE | RTC_FEATURE_FLAG_USER_GEOMETRY_CALLBACK_IN_ARGUMENTS); intersectArgs.context = &context.ectx; rtcIntersectV(world->regionScene, (varying RTCRayHit * uniform) & screenSample.ray, &intersectArgs); } } } } #ifndef OSPRAY_TARGET_SYCL export void DistributedRenderer_computeRegionVisibility(void *uniform _self, void *uniform fb, void *uniform camera, void *uniform world, uint8 *uniform regionVisible, void *uniform perFrameData, void *uniform _taskIDs, uniform int numTasks) { Renderer *uniform self = (uniform Renderer * uniform) _self; const uint32 *uniform taskIDs = (const uint32 *uniform)_taskIDs; uniform FeatureFlagsHandler ffh; launch[numTasks] DR_default_computeRegionVisibility(self, (SparseFB * uniform) fb, (Camera * uniform) camera, (DistributedWorld * uniform) world, regionVisible, perFrameData, taskIDs, ffh); } #ifndef OSPRAY_TARGET_SYCL export void DistributedRenderer_pick(const void *uniform _self, const void *uniform _fb, const void *uniform _camera, const void *uniform _world, const uniform vec2f &screenPos, uniform vec3f &pos, uniform int32 &instID, uniform int32 &geomID, uniform int32 &primID, uniform float &depth, uniform int32 &hit) { uniform FeatureFlagsHandler ffh; const Renderer *uniform self = (const Renderer *uniform)_self; const FrameBuffer *uniform fb = (const FrameBuffer *uniform)_fb; const Camera *uniform camera = (const Camera *uniform)_camera; const DistributedWorld *uniform world = (const DistributedWorld *uniform)_world; CameraSample cameraSample; cameraSample.screen.x = screenPos.x; cameraSample.screen.y = screenPos.y; // use center of lens and shutter time cameraSample.lens.x = 0.0f; cameraSample.lens.y = 0.0f; cameraSample.time = 0.5f; Ray ray; Camera_dispatch_initRay(camera, ray, cameraSample, ffh); ray.t = min(ray.t, Renderer_getMaxDepth(self, cameraSample.screen, ffh)); // Clip the ray to each region this rank owns and trace the clipped ray to // find the picked object float closestHit = 1e20f; for (uniform int i = 0; i < world->numLocalRegions; ++i) { // Separate ray per-region to allow clipping by the region's bounds Ray regionRay = ray; regionRay.t = min(ray.t, closestHit); const Intersections isect = intersectBox(regionRay.org, regionRay.dir, world->localRegions[i]); if (isect.entry.t < isect.exit.t && isect.exit.t >= regionRay.t0 && isect.entry.t <= regionRay.t) { regionRay.t0 = isect.entry.t; regionRay.t = min(regionRay.t, isect.exit.t); traceRay(&world->super, regionRay, ffh); if (hadHit(regionRay)) { closestHit = regionRay.t; vec3f p = regionRay.org + regionRay.dir * regionRay.t; pos.x = extract(p.x, 0); pos.y = extract(p.y, 0); pos.z = extract(p.z, 0); hit = extract((int)(hadHit(regionRay)), 0); instID = extract(regionRay.instID, 0); geomID = extract(regionRay.geomID, 0); primID = extract(regionRay.primID, 0); depth = extract(regionRay.t, 0); } } } } #endif #endif OSPRAY_END_ISPC_NAMESPACE RenderKit-ospray-f2a61c2/modules/mpi/ospray/render/distributed/DistributedRendererRenderTaskFn.inl000066400000000000000000000103311456566705700336440ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #ifndef OSPRAY_TARGET_SYCL task #endif static void DR_default_renderRegionToTile(Renderer *uniform self, SparseFB *uniform fb, Camera *uniform camera, DistributedWorld *uniform world, const box3f *uniform region, void *uniform perFrameData, const uint32 *uniform taskIDs, #ifdef OSPRAY_TARGET_SYCL const int taskIndex0, #endif const uniform FeatureFlagsHandler &ffh) { const uniform int32 spp = self->spp; ScreenSample screenSample; screenSample.z = inf; screenSample.alpha = 0.f; CameraSample cameraSample; uniform RenderTaskDesc taskDesc = FrameBuffer_dispatch_getRenderTaskDesc( &fb->super, taskIDs[taskIndex0], ffh); const uniform int startSampleID = (fb->super.doAccumulation ? max(fb->super.frameID, 0) * spp : 0) + 1; // Halton Sequence starts with 1 #ifdef OSPRAY_TARGET_SYCL #if 0 // Dummy top level print so that prints at lower levels of the kernel // will work See JIRA https://jira.devtools.intel.com/browse/XDEPS-4729 if (taskIndex0 == 0) { cl::sycl::ext::oneapi::experimental::printf(""); } #endif #endif if (isEmpty(taskDesc.region)) { return; } #ifdef OSPRAY_TARGET_SYCL for (int32 y = taskDesc.region.lower.y; y < taskDesc.region.upper.y; ++y) for (int32 x = taskDesc.region.lower.x; x < taskDesc.region.upper.x; ++x) { #else foreach_tiled (y = taskDesc.region.lower.y... taskDesc.region.upper.y, x = taskDesc.region.lower.x... taskDesc.region.upper.x) { #endif screenSample.sampleID.x = x; screenSample.sampleID.y = y; // set ray t value for early ray termination (from maximum depth texture) vec2f center = make_vec2f(screenSample.sampleID.x, screenSample.sampleID.y) + 0.5f; const float tMax = Renderer_getMaxDepth(self, center * fb->super.rcpSize, ffh); vec3f col = make_vec3f(0.f); float alpha = 0.f; vec3f normal = make_vec3f(0.f); vec3f albedo = make_vec3f(0.f); // TODO: same note on spp > 1 issues for (uniform uint32 s = 0; s < spp; s++) { const float pixel_du = Halton_sample2(startSampleID + s); const float pixel_dv = CranleyPattersonRotation( Halton_sample3(self->mathConstants, startSampleID + s), 1.f / 6.f); screenSample.sampleID.z = startSampleID + s; cameraSample.screen.x = (screenSample.sampleID.x + pixel_du) * fb->super.rcpSize.x; cameraSample.screen.y = (screenSample.sampleID.y + pixel_dv) * fb->super.rcpSize.y; // no DoF or MB per default cameraSample.lens.x = 0.0f; cameraSample.lens.y = 0.0f; cameraSample.time = 0.5f; Camera_dispatch_initRay(camera, screenSample.ray, cameraSample, ffh); screenSample.ray.t = min(screenSample.ray.t, tMax); // TODO: We could store and use the region t intervals from when // we did the visibility test? Intersections isect = intersectBox(screenSample.ray.org, screenSample.ray.dir, *region); if (isect.entry.t < isect.exit.t && isect.exit.t >= screenSample.ray.t0 && isect.entry.t <= screenSample.ray.t) { const float regionEnter = max(isect.entry.t, screenSample.ray.t0); const float regionExit = min(isect.exit.t, screenSample.ray.t); screenSample.ray.t0 = regionEnter; screenSample.ray.t = regionExit; renderRegionSampleFn(self, fb, world, region, make_vec2f(regionEnter, regionExit), perFrameData, screenSample, ffh); col = col + screenSample.rgb; alpha += screenSample.alpha; normal = normal + screenSample.normal; albedo = albedo + screenSample.albedo; } } const float rspp = rcpf(spp); screenSample.rgb = col * rspp; screenSample.alpha = alpha * rspp; screenSample.normal = normal * rspp; screenSample.albedo = albedo * rspp; FrameBuffer_dispatch_accumulateSample( &fb->super, screenSample, taskDesc, ffh); } FrameBuffer_dispatch_completeTask(&fb->super, taskDesc, ffh); } RenderKit-ospray-f2a61c2/modules/mpi/testing/000077500000000000000000000000001456566705700212615ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/mpi/testing/CMakeLists.txt000066400000000000000000000007641456566705700240300ustar00rootroot00000000000000## Copyright 2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ospray_disable_compiler_warnings() add_executable(ospMPIDistribTestSuite ${OSPRAY_RESOURCE} distributed_test_fixture.cpp ospMPIDistribTestSuite.cpp ) target_link_libraries(ospMPIDistribTestSuite PRIVATE arcball_camera ospray_testing ospray_gtest_utils MPI::MPI_CXX ) ospray_sign_target(ospMPIDistribTestSuite) install(TARGETS ospMPIDistribTestSuite DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT apps ) RenderKit-ospray-f2a61c2/modules/mpi/testing/distributed_test_fixture.cpp000066400000000000000000000073121456566705700271170ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "distributed_test_fixture.h" #include #include "ArcballCamera.h" #include "ospray_testing.h" extern OSPRayEnvironment *ospEnv; namespace MPIDistribOSPRayTestScenes { bool computeDivisor(int x, int &divisor) { int upperBound = std::sqrt(x); for (int i = 2; i <= upperBound; ++i) { if (x % i == 0) { divisor = i; return true; } } return false; } // Compute an X x Y x Z grid to have 'num' grid cells, // only gives a nice grid for numbers with even factors since // we don't search for factors of the number, we just try dividing by two vec3i computeGrid(int num) { vec3i grid(1); int axis = 0; int divisor = 0; while (computeDivisor(num, divisor)) { grid[axis] *= divisor; num /= divisor; axis = (axis + 1) % 3; } if (num != 1) { grid[axis] *= num; } return grid; } MPIDistribBase::MPIDistribBase() { MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); rankGridDims = computeGrid(mpiSize); rankBrickId = vec3i(mpiRank % rankGridDims.x, (mpiRank / rankGridDims.x) % rankGridDims.y, mpiRank / (rankGridDims.x * rankGridDims.y)); } void MPIDistribBase::AddInstance(cpp::Instance instance) { worldBounds.extend(instance.getBounds()); Base::AddInstance(instance); } void MPIDistribBase::PerformRenderTest() { SetLights(); if (!instances.empty()) { world.setParam("instance", cpp::CopiedData(instances)); // Determine the bounds of this rank's region in world space const vec3f regionDims = worldBounds.size() / vec3f(rankGridDims); box3f localRegion(rankBrickId * regionDims + worldBounds.lower, rankBrickId * regionDims + regionDims + worldBounds.lower); // Special case for the ospray test data: we might have geometry right at // the region bounding box which will z-fight with the clipping region. If // we have a region at the edge of the domain, apply some padding for (int i = 0; i < 3; ++i) { if (localRegion.lower[i] == worldBounds.lower[i]) { localRegion.lower[i] -= 0.001; } if (localRegion.upper[i] == worldBounds.upper[i]) { localRegion.upper[i] += 0.001; } } world.setParam("region", cpp::CopiedData(localRegion)); } camera.commit(); world.commit(); renderer.commit(); framebuffer.resetAccumulation(); RenderFrame(); if (mpiRank == 0) { auto *framebuffer_data = (uint32_t *)framebuffer.map(OSP_FB_COLOR); if (ospEnv->GetDumpImg()) { EXPECT_EQ(imageTool->saveTestImage(framebuffer_data), OsprayStatus::Ok); } else { EXPECT_EQ(imageTool->compareImgWithBaseline(framebuffer_data), OsprayStatus::Ok); } framebuffer.unmap(framebuffer_data); } } MPIFromOsprayTesting::MPIFromOsprayTesting() { auto params = GetParam(); sceneName = std::get<0>(params); rendererType = "mpiRaycast"; samplesPerPixel = std::get<1>(params); } void MPIFromOsprayTesting::SetUp() { MPIDistribBase::SetUp(); instances.clear(); auto builder = ospray::testing::newBuilder(sceneName); ospray::testing::setParam(builder, "rendererType", rendererType); ospray::testing::commit(builder); // Build the group to get the bounds auto group = ospray::testing::buildGroup(builder); worldBounds = group.getBounds(); cpp::Instance instance(group); instance.commit(); instances.push_back(instance); ospray::testing::release(builder); ArcballCamera arcballCamera(worldBounds, imgSize); camera.setParam("position", arcballCamera.eyePos()); camera.setParam("direction", arcballCamera.lookDir()); camera.setParam("up", arcballCamera.upDir()); } } // namespace MPIDistribOSPRayTestScenes RenderKit-ospray-f2a61c2/modules/mpi/testing/distributed_test_fixture.h000066400000000000000000000022351456566705700265630ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "test_fixture.h" namespace MPIDistribOSPRayTestScenes { // Base class for all distributed test fixtures // The base class assumes the data is partitioned in a 3D // grid with each rank assigned a cell in this grid that it owns. // The base class will set the world region parameter to match this class MPIDistribBase : public OSPRayTestScenes::Base { public: MPIDistribBase(); // We override these to get the bounds of objects as they're added // so we can set the regions parameter on the world. virtual void AddInstance(cpp::Instance instance) override; virtual void PerformRenderTest(); protected: int mpiRank; int mpiSize; vec3i rankGridDims; vec3i rankBrickId; box3f worldBounds; }; // Fixture class used for tests that uses 'ospray_testing' scenes class MPIFromOsprayTesting : public MPIDistribBase, public ::testing::TestWithParam< std::tuple> { public: MPIFromOsprayTesting(); void SetUp() override; protected: std::string sceneName; }; } // namespace MPIDistribOSPRayTestScenes RenderKit-ospray-f2a61c2/modules/mpi/testing/ospMPIDistribTestSuite.cpp000066400000000000000000000047411456566705700263350ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include #include "distributed_test_fixture.h" #include "rkcommon/utility/getEnvVar.h" OSPRayEnvironment *ospEnv; namespace MPIDistribOSPRayTestScenes { TEST_P(MPIFromOsprayTesting, test_scenes) { PerformRenderTest(); } #ifdef OSPRAY_ENABLE_VOLUMES INSTANTIATE_TEST_SUITE_P(MPIDistribTestScenesVolumes, MPIFromOsprayTesting, ::testing::Combine( ::testing::Values( "gravity_spheres_isosurface", "vdb_volume", "particle_volume"), ::testing::Values(1))); #endif INSTANTIATE_TEST_SUITE_P(MPIDistribTestScenesGeometry, MPIFromOsprayTesting, ::testing::Combine(::testing::Values("planes", "boxes", "random_spheres"), ::testing::Values(1))); } // namespace MPIDistribOSPRayTestScenes int main(int argc, char **argv) { int mpiThreadCapability = 0; MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &mpiThreadCapability); if (mpiThreadCapability != MPI_THREAD_MULTIPLE && mpiThreadCapability != MPI_THREAD_SERIALIZED) { fprintf(stderr, "OSPRay requires the MPI runtime to support thread " "multiple or thread serialized.\n"); return 1; } int result = 0; // load the MPI module, and select the MPI distributed device. Here we // do not call ospInit, as we want to explicitly pick the distributed // device auto OSPRAY_MPI_DISTRIBUTED_GPU = rkcommon::utility::getEnvVar("OSPRAY_MPI_DISTRIBUTED_GPU").value_or(0); if (OSPRAY_MPI_DISTRIBUTED_GPU) { ospLoadModule("mpi_distributed_gpu"); } else { ospLoadModule("mpi_distributed_cpu"); } { cpp::Device device("mpiDistributed"); device.setErrorCallback( [](void *, OSPError error, const char *errorDetails) { std::cerr << "OSPRay error: " << errorDetails << std::endl; std::exit(EXIT_FAILURE); }); device.setStatusCallback([](void *, const char *msg) { std::cout << msg; }); // First commit with INFO log Level to output device info string device.setParam("warnAsError", true); device.setParam("logLevel", OSP_LOG_INFO); device.commit(); // Then use WARNING log level for tests execution device.setParam("logLevel", OSP_LOG_WARNING); device.commit(); device.setCurrent(); ::testing::InitGoogleTest(&argc, argv); ospEnv = new OSPRayEnvironment(argc, argv); AddGlobalTestEnvironment(ospEnv); result = RUN_ALL_TESTS(); } ospShutdown(); MPI_Finalize(); return result; } RenderKit-ospray-f2a61c2/modules/mpi/tutorials/000077500000000000000000000000001456566705700216325ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/mpi/tutorials/CMakeLists.txt000066400000000000000000000065711456566705700244030ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 find_package(MPI REQUIRED) if (OSPRAY_ENABLE_APPS_TUTORIALS) # build ospTutorial, for demonstration and API testing add_executable(ospMPIDistribTutorial ${OSPRAY_RESOURCE} ospMPIDistribTutorial.c) target_link_libraries(ospMPIDistribTutorial PRIVATE ospray ${MPI_C_LIBRARIES}) target_include_directories(ospMPIDistribTutorial PRIVATE ${MPI_C_INCLUDE_DIRS}) install(TARGETS ospMPIDistribTutorial DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT mpi ) ospray_sign_target(ospMPIDistribTutorial) # C++ version add_executable(ospMPIDistribTutorialCpp ${OSPRAY_RESOURCE} ospMPIDistribTutorial.cpp) target_link_libraries(ospMPIDistribTutorialCpp PRIVATE ospray rkcommon::rkcommon MPI::MPI_CXX ) target_compile_definitions(ospMPIDistribTutorialCpp PRIVATE -DOSPRAY_CPP_RKCOMMON_TYPES) install(TARGETS ospMPIDistribTutorialCpp DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT mpi ) ospray_sign_target(ospMPIDistribTutorialCpp) # async version add_executable(ospMPIDistribTutorialAsync ${OSPRAY_RESOURCE} ospMPIDistribTutorialAsync.c) target_link_libraries(ospMPIDistribTutorialAsync PRIVATE ospray ${MPI_C_LIBRARIES}) target_include_directories(ospMPIDistribTutorialAsync PRIVATE ${MPI_C_INCLUDE_DIRS}) install(TARGETS ospMPIDistribTutorialAsync DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT mpi ) ospray_sign_target(ospMPIDistribTutorialAsync) endif() if (OSPRAY_ENABLE_APPS_EXAMPLES) # prefer libGL over libOpenGl for better compatibility with SWR set(OpenGL_GL_PREFERENCE "LEGACY") find_package(OpenGL 2 REQUIRED) macro(ospray_create_mpi_tutorial tutorial_name) add_executable(${tutorial_name} ${OSPRAY_RESOURCE} ${ARGN}) target_link_libraries(${tutorial_name} PRIVATE mpi_tutorial_common) install(TARGETS ${tutorial_name} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT mpi ) endmacro() # MPI Tutorial utilities library add_library(mpi_tutorial_common STATIC GLFWDistribOSPRayWindow.cpp ) target_include_directories(mpi_tutorial_common PRIVATE ${CMAKE_SOURCE_DIR}/apps/ospExamples/) target_link_libraries(mpi_tutorial_common PUBLIC rkcommon::rkcommon ospray ospray_imgui ${OPENGL_LIBRARIES} arcball_camera MPI::MPI_CXX ) target_compile_definitions(mpi_tutorial_common PUBLIC -DOSPRAY_CPP_RKCOMMON_TYPES) ospray_create_mpi_tutorial(ospMPIDistribTutorialSpheres ospMPIDistribTutorialSpheres.cpp ) ospray_sign_target(ospMPIDistribTutorialSpheres) ospray_create_mpi_tutorial(ospMPIDistribTutorialVolume ospMPIDistribTutorialVolume.cpp ) ospray_sign_target(ospMPIDistribTutorialVolume) ospray_create_mpi_tutorial(ospMPIDistribTutorialPartialRepl ospMPIDistribTutorialPartialRepl.cpp ) ospray_sign_target(ospMPIDistribTutorialPartialRepl) ospray_create_mpi_tutorial(ospMPIDistribTutorialReplicated ospMPIDistribTutorialReplicated.cpp ) ospray_sign_target(ospMPIDistribTutorialReplicated) target_link_libraries(ospMPIDistribTutorialReplicated PUBLIC ospray_testing ) ospray_create_mpi_tutorial(ospMPIDistributedExamples ospMPIDistributedExamples.cpp ) ospray_sign_target(ospMPIDistributedExamples) target_link_libraries(ospMPIDistributedExamples PUBLIC ospray_testing ) endif() RenderKit-ospray-f2a61c2/modules/mpi/tutorials/GLFWDistribOSPRayWindow.cpp000066400000000000000000000266201456566705700266520ustar00rootroot00000000000000// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "GLFWDistribOSPRayWindow.h" #include #include #include #include #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" using namespace ospray; using namespace rkcommon::math; GLFWDistribOSPRayWindow *GLFWDistribOSPRayWindow::activeWindow = nullptr; static bool g_quitNextFrame = false; WindowState::WindowState() : quit(false), cameraChanged(false), fbSizeChanged(false), spp(1), windowSize(0), eyePos(0.f), lookDir(0.f), upDir(0.f) {} GLFWDistribOSPRayWindow::GLFWDistribOSPRayWindow(const vec2i &windowSize, const box3f &worldBounds, cpp::World world, cpp::Renderer renderer) : windowSize(windowSize), worldBounds(worldBounds), world(world), renderer(renderer) { MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); MPI_Comm_size(MPI_COMM_WORLD, &mpiWorldSize); if (mpiRank == 0) { if (activeWindow != nullptr) { throw std::runtime_error( "Cannot create more than one GLFWDistribOSPRayWindow!"); } activeWindow = this; // initialize GLFW if (!glfwInit()) { throw std::runtime_error("Failed to initialize GLFW!"); } glfwWindowHint(GLFW_SRGB_CAPABLE, GLFW_TRUE); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); #ifdef __APPLE_ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); const char *glslVersion = "#version 150"; #else glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); const char *glslVersion = "#version 130"; #endif glfwWindow = glfwCreateWindow( windowSize.x, windowSize.y, "OSPRay Tutorial", NULL, NULL); if (!glfwWindow) { glfwTerminate(); throw std::runtime_error("Failed to create GLFW window!"); } // make the window's context current glfwMakeContextCurrent(glfwWindow); // Setup Dear ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO &io = ImGui::GetIO(); io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; ImGui_ImplGlfw_InitForOpenGL(glfwWindow, false); // set GLFW callbacks glfwSetFramebufferSizeCallback( glfwWindow, [](GLFWwindow *, int newWidth, int newHeight) { activeWindow->reshape(vec2i{newWidth, newHeight}); }); glfwSetCursorPosCallback(glfwWindow, [](GLFWwindow *, double x, double y) { ImGuiIO &io = ImGui::GetIO(); if (!io.WantCaptureMouse) { activeWindow->motion(vec2f{float(x), float(y)}); } }); glfwSetKeyCallback( glfwWindow, [](GLFWwindow *, int key, int, int action, int) { if (action == GLFW_PRESS) { switch (key) { case GLFW_KEY_G: activeWindow->showUi = !(activeWindow->showUi); break; case GLFW_KEY_Q: g_quitNextFrame = true; break; } } }); // will chain our callbacks above ImGui_ImplGlfw_InstallCallbacks(glfwWindow); ImGui_ImplOpenGL3_Init(glslVersion); // set initial OpenGL state glEnable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); // create OpenGL frame buffer texture glGenTextures(1, &framebufferTexture); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, framebufferTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } // OSPRay setup // create the arcball camera model arcballCamera = std::unique_ptr( new ArcballCamera(worldBounds, windowSize)); // create camera camera = cpp::Camera("perspective"); camera.setParam("aspect", windowSize.x / float(windowSize.y)); camera.setParam("position", arcballCamera->eyePos()); camera.setParam("direction", arcballCamera->lookDir()); camera.setParam("up", arcballCamera->upDir()); camera.commit(); renderer.commit(); windowState.windowSize = windowSize; windowState.eyePos = arcballCamera->eyePos(); windowState.lookDir = arcballCamera->lookDir(); windowState.upDir = arcballCamera->upDir(); if (mpiRank == 0) { // trigger window reshape events with current window size glfwGetFramebufferSize( glfwWindow, &this->windowSize.x, &this->windowSize.y); reshape(this->windowSize); } } GLFWDistribOSPRayWindow::~GLFWDistribOSPRayWindow() { if (mpiRank == 0) { ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); glfwDestroyWindow(glfwWindow); glfwTerminate(); } } GLFWDistribOSPRayWindow *GLFWDistribOSPRayWindow::getActiveWindow() { return activeWindow; } cpp::World GLFWDistribOSPRayWindow::getWorld() { return world; } void GLFWDistribOSPRayWindow::setWorld(cpp::World newWorld) { world = newWorld; addObjectToCommit(world.handle()); } void GLFWDistribOSPRayWindow::resetAccumulation() { framebuffer.resetAccumulation(); } void GLFWDistribOSPRayWindow::registerDisplayCallback( std::function callback) { displayCallback = callback; } void GLFWDistribOSPRayWindow::registerImGuiCallback( std::function callback) { uiCallback = callback; } void GLFWDistribOSPRayWindow::mainLoop() { while (true) { MPI_Bcast(&windowState, sizeof(WindowState), MPI_BYTE, 0, MPI_COMM_WORLD); if (windowState.quit) { break; } // TODO: Actually render asynchronously, if we have MPI thread multiple // support startNewOSPRayFrame(); waitOnOSPRayFrame(); if (mpiRank == 0) { glfwPollEvents(); ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); if (displayCallback) displayCallback(this); display(); windowState.quit = glfwWindowShouldClose(glfwWindow) || g_quitNextFrame; } } } void GLFWDistribOSPRayWindow::reshape(const vec2i &newWindowSize) { windowSize = newWindowSize; windowState.windowSize = windowSize; windowState.fbSizeChanged = true; // update camera arcballCamera->updateWindowSize(windowSize); // reset OpenGL viewport and orthographic projection glViewport(0, 0, windowSize.x, windowSize.y); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, windowSize.x, 0.0, windowSize.y, -1.0, 1.0); } void GLFWDistribOSPRayWindow::motion(const vec2f &position) { static vec2f previousMouse(-1); const vec2f mouse(position.x, position.y); if (previousMouse != vec2f(-1)) { const bool leftDown = glfwGetMouseButton(glfwWindow, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS; const bool rightDown = glfwGetMouseButton(glfwWindow, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS; const bool middleDown = glfwGetMouseButton(glfwWindow, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS; const vec2f prev = previousMouse; bool cameraChanged = leftDown || rightDown || middleDown; if (leftDown) { const vec2f mouseFrom(clamp(prev.x * 2.f / windowSize.x - 1.f, -1.f, 1.f), clamp(prev.y * 2.f / windowSize.y - 1.f, -1.f, 1.f)); const vec2f mouseTo(clamp(mouse.x * 2.f / windowSize.x - 1.f, -1.f, 1.f), clamp(mouse.y * 2.f / windowSize.y - 1.f, -1.f, 1.f)); arcballCamera->rotate(mouseFrom, mouseTo); } else if (rightDown) { arcballCamera->zoom(mouse.y - prev.y); } else if (middleDown) { arcballCamera->pan(vec2f(mouse.x - prev.x, prev.y - mouse.y)); } if (cameraChanged) { windowState.cameraChanged = true; windowState.eyePos = arcballCamera->eyePos(); windowState.lookDir = arcballCamera->lookDir(); windowState.upDir = arcballCamera->upDir(); } } previousMouse = mouse; } void GLFWDistribOSPRayWindow::display() { // clock used to compute frame rate static auto displayStart = std::chrono::high_resolution_clock::now(); if (showUi && uiCallback) { ImGuiWindowFlags flags = ImGuiWindowFlags_AlwaysAutoResize; ImGui::Begin( "Tutorial Controls (press 'g' to hide / show)", nullptr, flags); uiCallback(); ImGui::End(); } updateTitleBar(); static bool firstFrame = true; if (firstFrame || currentFrame.isReady()) { // display frame rate in window title auto displayEnd = std::chrono::high_resolution_clock::now(); auto durationMilliseconds = std::chrono::duration_cast( displayEnd - displayStart); latestFPS = 1000.f / float(durationMilliseconds.count()); // map OSPRay frame buffer, update OpenGL texture with its contents, then // unmap uint32_t *fb = (uint32_t *)framebuffer.map(OSP_FB_COLOR); glBindTexture(GL_TEXTURE_2D, framebufferTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, windowSize.x, windowSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, fb); framebuffer.unmap(fb); // Start new frame and reset frame timing interval start displayStart = std::chrono::high_resolution_clock::now(); firstFrame = false; } // clear current OpenGL color buffer glClear(GL_COLOR_BUFFER_BIT); // render textured quad with OSPRay frame buffer contents glBegin(GL_QUADS); glTexCoord2f(0.f, 0.f); glVertex2f(0.f, 0.f); glTexCoord2f(0.f, 1.f); glVertex2f(0.f, windowSize.y); glTexCoord2f(1.f, 1.f); glVertex2f(windowSize.x, windowSize.y); glTexCoord2f(1.f, 0.f); glVertex2f(windowSize.x, 0.f); glEnd(); ImGui::Render(); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); glfwSwapBuffers(glfwWindow); } void GLFWDistribOSPRayWindow::startNewOSPRayFrame() { bool fbNeedsClear = false; auto handles = objectsToCommit.consume(); if (!handles.empty()) { for (auto &h : handles) ospCommit(h); fbNeedsClear = true; } if (windowState.fbSizeChanged) { windowState.fbSizeChanged = false; windowSize = windowState.windowSize; framebuffer = cpp::FrameBuffer( windowSize.x, windowSize.y, OSP_FB_SRGBA, OSP_FB_COLOR | OSP_FB_ACCUM); camera.setParam("aspect", windowSize.x / float(windowSize.y)); camera.commit(); fbNeedsClear = true; } if (windowState.cameraChanged) { windowState.cameraChanged = false; camera.setParam("aspect", windowSize.x / float(windowSize.y)); camera.setParam("position", windowState.eyePos); camera.setParam("direction", windowState.lookDir); camera.setParam("up", windowState.upDir); camera.commit(); fbNeedsClear = true; } if (fbNeedsClear) { resetAccumulation(); } currentFrame = framebuffer.renderFrame(renderer, camera, world); } void GLFWDistribOSPRayWindow::waitOnOSPRayFrame() { if (currentFrame.handle() != nullptr) { currentFrame.wait(OSP_FRAME_FINISHED); } } void GLFWDistribOSPRayWindow::addObjectToCommit(OSPObject obj) { objectsToCommit.push_back(obj); } void GLFWDistribOSPRayWindow::updateTitleBar() { std::stringstream windowTitle; windowTitle << "OSPRay: " << std::setprecision(3) << latestFPS << " fps"; if (latestFPS < 2.f) { float progress = currentFrame.progress(); windowTitle << " | "; int barWidth = 20; std::string progBar; progBar.resize(barWidth + 2); auto start = progBar.begin() + 1; auto end = start + progress * barWidth; std::fill(start, end, '='); std::fill(end, progBar.end(), '_'); *end = '>'; progBar.front() = '['; progBar.back() = ']'; windowTitle << progBar; } glfwSetWindowTitle(glfwWindow, windowTitle.str().c_str()); } RenderKit-ospray-f2a61c2/modules/mpi/tutorials/GLFWDistribOSPRayWindow.h000066400000000000000000000053471456566705700263220ustar00rootroot00000000000000// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include "ArcballCamera.h" #include "rkcommon/containers/TransactionalBuffer.h" #include "rkcommon/math/box.h" #include "rkcommon/math/vec.h" // ospray #include "ospray/ospray.h" #include "ospray/ospray_cpp.h" #include "ospray/ospray_cpp/ext/rkcommon.h" struct WindowState { bool quit; bool cameraChanged; bool fbSizeChanged; int spp; rkcommon::math::vec2i windowSize; rkcommon::math::vec3f eyePos; rkcommon::math::vec3f lookDir; rkcommon::math::vec3f upDir; WindowState(); }; class GLFWDistribOSPRayWindow { public: GLFWDistribOSPRayWindow(const rkcommon::math::vec2i &windowSize, const rkcommon::math::box3f &worldBounds, ospray::cpp::World world, ospray::cpp::Renderer renderer); ~GLFWDistribOSPRayWindow(); static GLFWDistribOSPRayWindow *getActiveWindow(); ospray::cpp::World getWorld(); void setWorld(ospray::cpp::World newWorld); void resetAccumulation(); void registerDisplayCallback( std::function callback); void registerImGuiCallback(std::function callback); void mainLoop(); void addObjectToCommit(OSPObject obj); protected: void reshape(const rkcommon::math::vec2i &newWindowSize); void motion(const rkcommon::math::vec2f &position); void display(); void startNewOSPRayFrame(); void waitOnOSPRayFrame(); void updateTitleBar(); static GLFWDistribOSPRayWindow *activeWindow; rkcommon::math::vec2i windowSize; rkcommon::math::box3f worldBounds; ospray::cpp::World world = nullptr; ospray::cpp::Renderer renderer = nullptr; int mpiRank = -1; int mpiWorldSize = -1; // GLFW window instance GLFWwindow *glfwWindow = nullptr; // Arcball camera instance std::unique_ptr arcballCamera; // OSPRay objects managed by this class ospray::cpp::Camera camera = nullptr; ospray::cpp::FrameBuffer framebuffer = nullptr; ospray::cpp::Future currentFrame = nullptr; // List of OSPRay handles to commit before the next frame rkcommon::containers::TransactionalBuffer objectsToCommit; // OpenGL framebuffer texture GLuint framebufferTexture = 0; // optional registered display callback, called before every display() std::function displayCallback; // toggles display of ImGui UI, if an ImGui callback is provided bool showUi = true; // optional registered ImGui callback, called during every frame to build UI std::function uiCallback; // FPS measurement of last frame float latestFPS{0.f}; // The window state to be sent out over MPI to the other rendering processes WindowState windowState; }; RenderKit-ospray-f2a61c2/modules/mpi/tutorials/ospMPIDistribTutorial.c000066400000000000000000000202071456566705700262130ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This is a small example tutorial how to use OSPRay and the * MPIDistributedDevice in a data-parallel application. * Each rank must specify the same render parameters, however the data * to render on each rank can differ for distributed rendering. In this * tutorial each rank renders a unique quad, which is colored by the rank. * * On Linux build it in the build_directory with: * mpicc -std=c99 ../modules/mpi/tutorials/ospMPIDistributedTutorial.c \ * -I ../ospray/include \ * -L . -lospray -Wl,-rpath,. \ * -o ospMPIDistributedTutorial * * Then run it with MPI on some number of processes * mpirun -n ./ospMPIDistributedTutorial * * The output image should show a sequence of quads, from dark to light blue */ #include #include #include #include #ifdef _WIN32 #include #else #include #endif #include #include // helper function to write the rendered image as PPM file void writePPM( const char *fileName, int size_x, int size_y, const uint32_t *pixel) { FILE *file = fopen(fileName, "wb"); if (!file) { fprintf(stderr, "fopen('%s', 'wb') failed: %d", fileName, errno); return; } fprintf(file, "P6\n%i %i\n255\n", size_x, size_y); unsigned char *out = (unsigned char *)alloca(3 * size_x); for (int y = 0; y < size_y; y++) { const unsigned char *in = (const unsigned char *)&pixel[(size_y - 1 - y) * size_x]; for (int x = 0; x < size_x; x++) { out[3 * x + 0] = in[4 * x + 0]; out[3 * x + 1] = in[4 * x + 1]; out[3 * x + 2] = in[4 * x + 2]; } fwrite(out, 3 * size_x, sizeof(char), file); } fprintf(file, "\n"); fclose(file); } int main(int argc, char **argv) { int mpiThreadCapability = 0; MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &mpiThreadCapability); if (mpiThreadCapability != MPI_THREAD_MULTIPLE && mpiThreadCapability != MPI_THREAD_SERIALIZED) { fprintf(stderr, "OSPRay requires the MPI runtime to support thread " "multiple or thread serialized.\n"); return 1; } int mpiRank = 0; int mpiWorldSize = 0; MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); MPI_Comm_size(MPI_COMM_WORLD, &mpiWorldSize); // image size int imgSizeX = 1024; // width int imgSizeY = 768; // height // camera float cam_pos[] = {(mpiWorldSize + 1.f) / 2.f, 0.5f, -mpiWorldSize * 0.5f}; float cam_up[] = {0.f, 1.f, 0.f}; float cam_view[] = {0.0f, 0.f, 1.f}; // all ranks specify the same rendering parameters, with the exception of // the data to be rendered, which is distributed among the ranks // triangle mesh data float vertex[] = { mpiRank, 0.0f, 3.5f, mpiRank, 1.0f, 3.0f, 1.0f * (mpiRank + 1.f), 0.0f, 3.0f, 1.0f * (mpiRank + 1.f), 1.0f, 2.5f, }; float color[] = {0.0f, 0.0f, (mpiRank + 1.f) / mpiWorldSize, 1.0f, 0.0f, 0.0f, (mpiRank + 1.f) / mpiWorldSize, 1.0f, 0.0f, 0.0f, (mpiRank + 1.f) / mpiWorldSize, 1.0f, 0.0f, 0.0f, (mpiRank + 1.f) / mpiWorldSize, 1.0f}; int32_t index[] = {0, 1, 2, 1, 2, 3}; // load the MPI module, and select the MPI distributed device. Here we // do not call ospInit, as we want to explicitly pick the distributed // device. This can also be done by passing --osp:mpi-distributed when // using ospInit, however if the user doesn't pass this argument your // application will likely not behave as expected ospLoadModule("mpi_distributed_cpu"); OSPDevice mpiDevice = ospNewDevice("mpiDistributed"); ospDeviceCommit(mpiDevice); ospSetCurrentDevice(mpiDevice); // create and setup camera OSPCamera camera = ospNewCamera("perspective"); ospSetFloat(camera, "aspect", imgSizeX / (float)imgSizeY); ospSetParam(camera, "position", OSP_VEC3F, cam_pos); ospSetParam(camera, "direction", OSP_VEC3F, cam_view); ospSetParam(camera, "up", OSP_VEC3F, cam_up); ospCommit(camera); // commit each object to indicate modifications are done // create and setup model and mesh OSPGeometry mesh = ospNewGeometry("mesh"); OSPData data = ospNewSharedData1D(vertex, OSP_VEC3F, 4); ospCommit(data); ospSetObject(mesh, "vertex.position", data); ospRelease(data); // we are done using this handle data = ospNewSharedData1D(color, OSP_VEC4F, 4); ospCommit(data); ospSetObject(mesh, "vertex.color", data); ospRelease(data); // we are done using this handle data = ospNewSharedData1D(index, OSP_VEC3UI, 2); ospCommit(data); ospSetObject(mesh, "index", data); ospRelease(data); // we are done using this handle ospCommit(mesh); // put the mesh into a model OSPGeometricModel model = ospNewGeometricModel(mesh); ospCommit(model); ospRelease(mesh); // put the model into a group (collection of models) OSPGroup group = ospNewGroup(); OSPData geometricModels = ospNewSharedData1D(&model, OSP_GEOMETRIC_MODEL, 1); ospSetObject(group, "geometry", geometricModels); ospCommit(group); ospRelease(model); ospRelease(geometricModels); // put the group into an instance (give the group a world transform) OSPInstance instance = ospNewInstance(group); ospCommit(instance); ospRelease(group); // put the instance in the world OSPWorld world = ospNewWorld(); OSPData instances = ospNewSharedData1D(&instance, OSP_INSTANCE, 1); ospSetObject(world, "instance", instances); ospRelease(instance); ospRelease(instances); // In the distributed device we set a clipping region to clip to the data // owned uniquely by this rank which it should be rendering float regionBounds[] = {mpiRank, 0.f, 2.5f, 1.f * (mpiRank + 1.f), 1.f, 3.5f}; data = ospNewSharedData1D(regionBounds, OSP_BOX3F, 1); ospCommit(data); ospSetObject(world, "region", data); ospRelease(data); ospCommit(world); // create the mpi_raycast renderer (required for distributed rendering) OSPRenderer renderer = ospNewRenderer("mpiRaycast"); // create and setup light for Ambient Occlusion // TODO: Who gets the lights now? OSPLight light = ospNewLight("ambient"); ospCommit(light); OSPData lights = ospNewSharedData1D(&light, OSP_LIGHT, 1); ospCommit(lights); // complete setup of renderer ospSetFloat(renderer, "backgroundColor", 1.0f); // white, transparent ospSetObject(renderer, "light", lights); ospCommit(renderer); // create and setup framebuffer OSPFrameBuffer framebuffer = ospNewFrameBuffer(imgSizeX, imgSizeY, OSP_FB_SRGBA, OSP_FB_COLOR | /*OSP_FB_DEPTH |*/ OSP_FB_ACCUM); ospResetAccumulation(framebuffer); // Try picking an object OSPPickResult pickResult; ospPick(&pickResult, framebuffer, renderer, camera, world, 0.5f, 0.5f); if (pickResult.hasHit) { printf( "Rank %d: ospPick() center of screen --> [inst: %p, model: %p, prim: %u]\n", mpiRank, pickResult.instance, pickResult.model, pickResult.primID); ospRelease(pickResult.instance); ospRelease(pickResult.model); } else { printf("Rank %d: ospPick() center of screen did not hit\n", mpiRank); } // render one frame ospRenderFrameBlocking(framebuffer, renderer, camera, world); // on rank 0, access framebuffer and write its content as PPM file if (mpiRank == 0) { const uint32_t *fb = (uint32_t *)ospMapFrameBuffer(framebuffer, OSP_FB_COLOR); writePPM("firstFrame.ppm", imgSizeX, imgSizeY, fb); ospUnmapFrameBuffer(fb, framebuffer); } // render 10 more frames, which are accumulated to result in a better // converged image for (int frames = 0; frames < 10; frames++) ospRenderFrameBlocking(framebuffer, renderer, camera, world); if (mpiRank == 0) { const uint32_t *fb = (uint32_t *)ospMapFrameBuffer(framebuffer, OSP_FB_COLOR); writePPM("accumulatedFrame.ppm", imgSizeX, imgSizeY, fb); ospUnmapFrameBuffer(fb, framebuffer); } // final cleanups ospRelease(renderer); ospRelease(camera); ospRelease(lights); ospRelease(light); ospRelease(framebuffer); ospRelease(world); ospDeviceRelease(mpiDevice); ospShutdown(); MPI_Finalize(); return 0; } RenderKit-ospray-f2a61c2/modules/mpi/tutorials/ospMPIDistribTutorial.cpp000066400000000000000000000145661456566705700265660ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This is a small example tutorial how to use OSPRay and the * MPIDistributedDevice in a data-parallel application. * Each rank must specify the same render parameters, however the data * to render on each rank can differ for distributed rendering. In this * tutorial each rank renders a unique quad, which is colored by the rank. * * On Linux build it in the build_directory with: * mpicxx ../modules/mpi/tutorials/ospMPIDistributedTutorial.cpp \ * -I ../ospray/include -I ../components \ * -L . -lospray -lospray_common -Wl,-rpath,. \ * -o ospMPIDistributedTutorialCpp * * Then run it with MPI on some number of processes * mpirun -n ./ospMPIDistributedTutorialCpp * * The output image should show a sequence of quads, from dark to light blue */ #include #include #include #include #ifdef _WIN32 #define NOMINMAX #include #else #include #endif #include "rkcommon/math/box.h" #include "rkcommon/math/vec.h" #include "rkcommon/utility/SaveImage.h" #include "rkcommon/utility/getEnvVar.h" // Note: we define OSPRAY_CPP_RKCOMMON_TYPES in CMAke to use rkcommon types // natively through the C++ wrappers #include "ospray/ospray_cpp.h" #include "ospray/ospray_cpp/ext/rkcommon.h" using namespace ospray; using namespace rkcommon; using namespace rkcommon::math; int main(int argc, char **argv) { int mpiThreadCapability = 0; MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &mpiThreadCapability); if (mpiThreadCapability != MPI_THREAD_MULTIPLE && mpiThreadCapability != MPI_THREAD_SERIALIZED) { fprintf(stderr, "OSPRay requires the MPI runtime to support thread " "multiple or thread serialized.\n"); return 1; } int mpiRank = 0; int mpiWorldSize = 0; MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); MPI_Comm_size(MPI_COMM_WORLD, &mpiWorldSize); // image size vec2i imgSize; imgSize.x = 1024; // width imgSize.y = 768; // height // camera vec3f cam_pos{(mpiWorldSize + 1.f) / 2.f, 0.5f, -mpiWorldSize * 0.5f}; vec3f cam_up{0.f, 1.f, 0.f}; vec3f cam_view{0.f, 0.f, 1.f}; // all ranks specify the same rendering parameters, with the exception of // the data to be rendered, which is distributed among the ranks // triangle mesh data vec3f vertex[] = {vec3f(mpiRank, 0.0f, 3.5f), vec3f(mpiRank, 1.0f, 3.0f), vec3f(1.0f * (mpiRank + 1.f), 0.0f, 3.0f), vec3f(1.0f * (mpiRank + 1.f), 1.0f, 2.5f)}; vec4f color[] = {vec4f(0.0f, 0.0f, (mpiRank + 1.f) / mpiWorldSize, 1.0f), vec4f(0.0f, 0.0f, (mpiRank + 1.f) / mpiWorldSize, 1.0f), vec4f(0.0f, 0.0f, (mpiRank + 1.f) / mpiWorldSize, 1.0f), vec4f(0.0f, 0.0f, (mpiRank + 1.f) / mpiWorldSize, 1.0f)}; vec3ui index[] = {vec3ui(0, 1, 2), vec3ui(1, 2, 3)}; // load the MPI module, and select the MPI distributed device. Here we // do not call ospInit, as we want to explicitly pick the distributed // device auto OSPRAY_MPI_DISTRIBUTED_GPU = utility::getEnvVar("OSPRAY_MPI_DISTRIBUTED_GPU").value_or(0); if (OSPRAY_MPI_DISTRIBUTED_GPU) { ospLoadModule("mpi_distributed_gpu"); } else { ospLoadModule("mpi_distributed_cpu"); } // use scoped lifetimes of wrappers to release everything before ospShutdown() { cpp::Device mpiDevice("mpiDistributed"); mpiDevice.commit(); mpiDevice.setCurrent(); // create and setup camera cpp::Camera camera("perspective"); camera.setParam("aspect", imgSize.x / (float)imgSize.y); camera.setParam("position", cam_pos); camera.setParam("direction", cam_view); camera.setParam("up", cam_up); camera.commit(); // commit each object to indicate modifications are done // create and setup model and mesh cpp::Geometry mesh("mesh"); cpp::CopiedData data(vertex, 4); data.commit(); mesh.setParam("vertex.position", data); data = cpp::CopiedData(color, 4); data.commit(); mesh.setParam("vertex.color", data); data = cpp::CopiedData(index, 2); data.commit(); mesh.setParam("index", data); mesh.commit(); // put the mesh into a model cpp::GeometricModel model(mesh); model.commit(); // put the model into a group (collection of models) cpp::Group group; group.setParam("geometry", cpp::CopiedData(model)); group.commit(); // put the group into an instance (give the group a world transform) cpp::Instance instance(group); instance.commit(); cpp::World world; world.setParam("instance", cpp::CopiedData(instance)); // Specify the region of the world this rank owns box3f regionBounds( vec3f(mpiRank, 0.f, 2.5f), vec3f(1.f * (mpiRank + 1.f), 1.f, 3.5f)); world.setParam("region", cpp::CopiedData(regionBounds)); world.commit(); // create the mpi_raycast renderer (required for distributed rendering) cpp::Renderer renderer("mpiRaycast"); renderer.commit(); // create and setup framebuffer cpp::FrameBuffer framebuffer(imgSize.x, imgSize.y, OSP_FB_SRGBA, OSP_FB_COLOR | /*OSP_FB_DEPTH |*/ OSP_FB_ACCUM); framebuffer.clear(); ospray::cpp::PickResult res = framebuffer.pick(renderer, camera, world, 0.5f, 0.5f); if (res.hasHit) { std::cout << "Rank " << mpiRank << " picked geometry [instance: " << res.instance.handle() << ", model: " << res.model.handle() << ", primitive: " << res.primID << "]" << std::endl; } else { std::cout << "Rank " << mpiRank << " pick missed" << std::endl; } // render one frame framebuffer.renderFrame(renderer, camera, world); // on rank 0, access framebuffer and write its content as PPM file if (mpiRank == 0) { uint32_t *fb = (uint32_t *)framebuffer.map(OSP_FB_COLOR); rkcommon::utility::writePPM( "firstFrameCpp.ppm", imgSize.x, imgSize.y, fb); framebuffer.unmap(fb); } // render 10 more frames, which are accumulated to result in a better // converged image for (int frames = 0; frames < 10; frames++) framebuffer.renderFrame(renderer, camera, world); if (mpiRank == 0) { uint32_t *fb = (uint32_t *)framebuffer.map(OSP_FB_COLOR); rkcommon::utility::writePPM( "accumulatedFrameCpp.ppm", imgSize.x, imgSize.y, fb); framebuffer.unmap(fb); } } ospShutdown(); MPI_Finalize(); return 0; } RenderKit-ospray-f2a61c2/modules/mpi/tutorials/ospMPIDistribTutorialAsync.c000066400000000000000000000174231456566705700272170ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This is a small example tutorial how to use OSPRay and the * MPIDistributedDevice in a data-parallel application. * Each rank must specify the same render parameters, however the data * to render on each rank can differ for distributed rendering. In this * tutorial each rank renders a unique quad, which is colored by the rank. * * On Linux build it in the build_directory with: * mpicc -std=c99 ../modules/mpi/tutorials/ospMPIDistributedTutorialAsync.c \ * -I ../ospray/include \ * -L . -lospray -Wl,-rpath,. \ * -o ospMPIDistributedTutorialAsync * * Then run it with MPI on some number of processes * mpirun -n ./ospMPIDistributedTutorialAsync * * The output image should show a sequence of quads, from dark to light blue */ #include #include #include #include #ifdef _WIN32 #include #else #include #endif #include #include // helper function to write the rendered image as PPM file void writePPM( const char *fileName, int size_x, int size_y, const uint32_t *pixel) { FILE *file = fopen(fileName, "wb"); if (!file) { fprintf(stderr, "fopen('%s', 'wb') failed: %d", fileName, errno); return; } fprintf(file, "P6\n%i %i\n255\n", size_x, size_y); unsigned char *out = (unsigned char *)alloca(3 * size_x); for (int y = 0; y < size_y; y++) { const unsigned char *in = (const unsigned char *)&pixel[(size_y - 1 - y) * size_x]; for (int x = 0; x < size_x; x++) { out[3 * x + 0] = in[4 * x + 0]; out[3 * x + 1] = in[4 * x + 1]; out[3 * x + 2] = in[4 * x + 2]; } fwrite(out, 3 * size_x, sizeof(char), file); } fprintf(file, "\n"); fclose(file); } int main(int argc, char **argv) { int mpiThreadCapability = 0; MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &mpiThreadCapability); if (mpiThreadCapability != MPI_THREAD_MULTIPLE && mpiThreadCapability != MPI_THREAD_SERIALIZED) { fprintf(stderr, "OSPRay requires the MPI runtime to support thread " "multiple or thread serialized.\n"); return 1; } int mpiRank = 0; int mpiWorldSize = 0; MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); MPI_Comm_size(MPI_COMM_WORLD, &mpiWorldSize); // image size int imgSizeX = 1024; // width int imgSizeY = 768; // height // camera float cam_pos[] = {(mpiWorldSize + 1.f) / 2.f, 0.5f, -mpiWorldSize * 0.5f}; float cam_up[] = {0.f, 1.f, 0.f}; float cam_view[] = {0.0f, 0.f, 1.f}; // all ranks specify the same rendering parameters, with the exception of // the data to be rendered, which is distributed among the ranks // triangle mesh data float vertex[] = { mpiRank, 0.0f, 3.5f, mpiRank, 1.0f, 3.0f, 1.0f * (mpiRank + 1.f), 0.0f, 3.0f, 1.0f * (mpiRank + 1.f), 1.0f, 2.5f, }; float color[] = {0.0f, 0.0f, (mpiRank + 1.f) / mpiWorldSize, 1.0f, 0.0f, 0.0f, (mpiRank + 1.f) / mpiWorldSize, 1.0f, 0.0f, 0.0f, (mpiRank + 1.f) / mpiWorldSize, 1.0f, 0.0f, 0.0f, (mpiRank + 1.f) / mpiWorldSize, 1.0f}; int32_t index[] = {0, 1, 2, 1, 2, 3}; // load the MPI module, and select the MPI distributed device. Here we // do not call ospInit, as we want to explicitly pick the distributed // device. ospLoadModule("mpi_distributed_cpu"); OSPDevice mpiDevice = ospNewDevice("mpiDistributed"); ospDeviceCommit(mpiDevice); ospSetCurrentDevice(mpiDevice); // create and setup camera OSPCamera camera = ospNewCamera("perspective"); ospSetFloat(camera, "aspect", imgSizeX / (float)imgSizeY); ospSetParam(camera, "position", OSP_VEC3F, cam_pos); ospSetParam(camera, "direction", OSP_VEC3F, cam_view); ospSetParam(camera, "up", OSP_VEC3F, cam_up); ospCommit(camera); // commit each object to indicate modifications are done // create and setup model and mesh OSPGeometry mesh = ospNewGeometry("mesh"); OSPData data = ospNewSharedData1D(vertex, OSP_VEC3F, 4); ospCommit(data); ospSetObject(mesh, "vertex.position", data); ospRelease(data); // we are done using this handle data = ospNewSharedData1D(color, OSP_VEC4F, 4); ospCommit(data); ospSetObject(mesh, "vertex.color", data); ospRelease(data); // we are done using this handle data = ospNewSharedData1D(index, OSP_VEC3UI, 2); ospCommit(data); ospSetObject(mesh, "index", data); ospRelease(data); // we are done using this handle ospCommit(mesh); // put the mesh into a model OSPGeometricModel model = ospNewGeometricModel(mesh); ospCommit(model); ospRelease(mesh); // put the model into a group (collection of models) OSPGroup group = ospNewGroup(); OSPData geometricModels = ospNewSharedData1D(&model, OSP_GEOMETRIC_MODEL, 1); ospSetObject(group, "geometry", geometricModels); ospCommit(group); ospRelease(model); ospRelease(geometricModels); // put the group into an instance (give the group a world transform) OSPInstance instance = ospNewInstance(group); ospCommit(instance); ospRelease(group); // put the instance in the world OSPWorld world = ospNewWorld(); OSPData instances = ospNewSharedData1D(&instance, OSP_INSTANCE, 1); ospSetObject(world, "instance", instances); ospRelease(instance); ospRelease(instances); // In the distributed device we set a clipping region to clip to the data // owned uniquely by this rank which it should be rendering float regionBounds[] = {mpiRank, 0.f, 2.5f, 1.f * (mpiRank + 1.f), 1.f, 3.5f}; data = ospNewSharedData1D(regionBounds, OSP_BOX3F, 1); ospCommit(data); ospSetObject(world, "region", data); ospRelease(data); ospCommit(world); // create the mpi_raycast renderer (required for distributed rendering) OSPRenderer renderer = ospNewRenderer("mpiRaycast"); // create and setup light for Ambient Occlusion // TODO: Who gets the lights now? OSPLight light = ospNewLight("ambient"); ospCommit(light); OSPData lights = ospNewSharedData1D(&light, OSP_LIGHT, 1); ospCommit(lights); // complete setup of renderer ospSetFloat(renderer, "backgroundColor", 1.0f); // white, transparent ospSetObject(renderer, "light", lights); ospCommit(renderer); // create and setup framebuffer OSPFrameBuffer framebuffer = ospNewFrameBuffer(imgSizeX, imgSizeY, OSP_FB_SRGBA, OSP_FB_COLOR | /*OSP_FB_DEPTH |*/ OSP_FB_ACCUM); ospResetAccumulation(framebuffer); // render one frame OSPFuture result = ospRenderFrame(framebuffer, renderer, camera, world); int isFinished = ospIsReady(result, OSP_TASK_FINISHED); printf("status of 'result' is %i\n", isFinished); printf("waiting on frame to finish...\n"); ospWait(result, OSP_FRAME_FINISHED); printf("...done!\n"); printf("variance was %f\n", ospGetVariance(framebuffer)); ospRelease(result); // on rank 0, access framebuffer and write its content as PPM file if (mpiRank == 0) { const uint32_t *fb = (uint32_t *)ospMapFrameBuffer(framebuffer, OSP_FB_COLOR); writePPM("firstFrame.ppm", imgSizeX, imgSizeY, fb); ospUnmapFrameBuffer(fb, framebuffer); } // render 10 more frames, which are accumulated to result in a better // converged image for (int frames = 0; frames < 10; frames++) ospRenderFrameBlocking(framebuffer, renderer, camera, world); if (mpiRank == 0) { const uint32_t *fb = (uint32_t *)ospMapFrameBuffer(framebuffer, OSP_FB_COLOR); writePPM("accumulatedFrame.ppm", imgSizeX, imgSizeY, fb); ospUnmapFrameBuffer(fb, framebuffer); } // final cleanups ospRelease(renderer); ospRelease(camera); ospRelease(lights); ospRelease(light); ospRelease(framebuffer); ospRelease(world); ospDeviceRelease(mpiDevice); ospShutdown(); MPI_Finalize(); return 0; } RenderKit-ospray-f2a61c2/modules/mpi/tutorials/ospMPIDistribTutorialPartialRepl.cpp000066400000000000000000000176111456566705700307200ustar00rootroot00000000000000// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This larger example shows how to use the MPIDistributedDevice to write an * interactive rendering application, which shows a UI on rank 0 and uses * all ranks in the MPI world for data loading and rendering. This example * also shows how to leverage the support for partially replicated data * distributions in the MPIDistributedDevice, by sharing bricks of data, * and thus rendering work, between processes. Each pair of ranks will * generate the same data, thereby distributing the rendering workload * for the brick between them. */ #include #include #include #include #include #include "GLFWDistribOSPRayWindow.h" #include "ospray/ospray_cpp.h" #include "ospray/ospray_cpp/ext/rkcommon.h" #include "ospray/ospray_util.h" #include "rkcommon/utility/getEnvVar.h" using namespace ospray; using namespace rkcommon; using namespace rkcommon::math; struct VolumeBrick { // the volume data itself cpp::Volume brick; cpp::VolumetricModel model; cpp::Group group; cpp::Instance instance; // the bounds of the owned portion of data box3f bounds; // the full bounds of the owned portion + ghost voxels box3f ghostBounds; }; static box3f worldBounds; // Generate the rank's local volume brick VolumeBrick makeLocalVolume(const int mpiRank, const int mpiWorldSize); int main(int argc, char **argv) { int mpiThreadCapability = 0; MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &mpiThreadCapability); if (mpiThreadCapability != MPI_THREAD_MULTIPLE && mpiThreadCapability != MPI_THREAD_SERIALIZED) { fprintf(stderr, "OSPRay requires the MPI runtime to support thread " "multiple or thread serialized.\n"); return 1; } int mpiRank = 0; int mpiWorldSize = 0; MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); MPI_Comm_size(MPI_COMM_WORLD, &mpiWorldSize); std::cout << "OSPRay rank " << mpiRank << "/" << mpiWorldSize << "\n"; // load the MPI module, and select the MPI distributed device. Here we // do not call ospInit, as we want to explicitly pick the distributed // device auto OSPRAY_MPI_DISTRIBUTED_GPU = utility::getEnvVar("OSPRAY_MPI_DISTRIBUTED_GPU").value_or(0); if (OSPRAY_MPI_DISTRIBUTED_GPU) { ospLoadModule("mpi_distributed_gpu"); } else { ospLoadModule("mpi_distributed_cpu"); } { cpp::Device mpiDevice("mpiDistributed"); mpiDevice.commit(); mpiDevice.setCurrent(); // set an error callback to catch any OSPRay errors and exit the application ospDeviceSetErrorCallback( mpiDevice.handle(), [](void *, OSPError error, const char *errorDetails) { std::cerr << "OSPRay error: " << errorDetails << std::endl; exit(error); }, nullptr); // every two ranks will share a volume brick to render, if we have an // odd number of ranks the last one will have its own brick const int sharedWorldSize = mpiWorldSize / 2 + mpiWorldSize % 2; // all ranks specify the same rendering parameters, with the exception of // the data to be rendered, which is distributed among the ranks VolumeBrick brick = makeLocalVolume(mpiRank / 2, sharedWorldSize); // create the "world" model which will contain all of our geometries cpp::World world; world.setParam("instance", cpp::CopiedData(brick.instance)); world.setParam("region", cpp::CopiedData(brick.bounds)); world.commit(); // create OSPRay renderer cpp::Renderer renderer("mpiRaycast"); // create and setup an ambient light cpp::Light ambientLight("ambient"); ambientLight.commit(); renderer.setParam("light", cpp::CopiedData(ambientLight)); // create a GLFW OSPRay window: this object will create and manage the // OSPRay frame buffer and camera directly auto glfwOSPRayWindow = std::unique_ptr(new GLFWDistribOSPRayWindow( vec2i{1024, 768}, worldBounds, world, renderer)); int spp = 1; int currentSpp = 1; if (mpiRank == 0) { glfwOSPRayWindow->registerImGuiCallback( [&]() { ImGui::SliderInt("pixelSamples", &spp, 1, 64); }); } glfwOSPRayWindow->registerDisplayCallback( [&](GLFWDistribOSPRayWindow *win) { // Send the UI changes out to the other ranks so we can synchronize // how many samples per-pixel we're taking MPI_Bcast(&spp, 1, MPI_INT, 0, MPI_COMM_WORLD); if (spp != currentSpp) { currentSpp = spp; renderer.setParam("pixelSamples", spp); win->addObjectToCommit(renderer.handle()); } }); // start the GLFW main loop, which will continuously render glfwOSPRayWindow->mainLoop(); } // cleanly shut OSPRay down ospShutdown(); MPI_Finalize(); return 0; } bool computeDivisor(int x, int &divisor) { int upperBound = std::sqrt(x); for (int i = 2; i <= upperBound; ++i) { if (x % i == 0) { divisor = i; return true; } } return false; } // Compute an X x Y x Z grid to have 'num' grid cells, // only gives a nice grid for numbers with even factors since // we don't search for factors of the number, we just try dividing by two vec3i computeGrid(int num) { vec3i grid(1); int axis = 0; int divisor = 0; while (computeDivisor(num, divisor)) { grid[axis] *= divisor; num /= divisor; axis = (axis + 1) % 3; } if (num != 1) { grid[axis] *= num; } return grid; } VolumeBrick makeLocalVolume(const int mpiRank, const int mpiWorldSize) { const vec3i grid = computeGrid(mpiWorldSize); const vec3i brickId(mpiRank % grid.x, (mpiRank / grid.x) % grid.y, mpiRank / (grid.x * grid.y)); // The bricks are 64^3 + 1 layer of ghost voxels on each axis const vec3i brickVolumeDims = vec3i(32); const vec3i brickGhostDims = vec3i(brickVolumeDims + 2); // The grid is over the [0, grid * brickVolumeDims] box worldBounds = box3f(vec3f(0.f), vec3f(grid * brickVolumeDims)); const vec3f brickLower = brickId * brickVolumeDims; const vec3f brickUpper = brickId * brickVolumeDims + brickVolumeDims; VolumeBrick brick; brick.bounds = box3f(brickLower, brickUpper); // we just put ghost voxels on all sides here, but a real application // would change which faces of each brick have ghost voxels dependent // on the actual data brick.ghostBounds = box3f(brickLower - vec3f(1.f), brickUpper + vec3f(1.f)); brick.brick = cpp::Volume("structuredRegular"); brick.brick.setParam("dimensions", brickGhostDims); // we use the grid origin to place this brick in the right position inside // the global volume brick.brick.setParam("gridOrigin", brick.ghostBounds.lower); // generate the volume data to just be filled with this rank's id const size_t nVoxels = brickGhostDims.x * brickGhostDims.y * brickGhostDims.z; std::vector volumeData(nVoxels, static_cast(mpiRank)); brick.brick.setParam("data", cpp::CopiedData(static_cast(volumeData.data()), vec3ul(brickVolumeDims))); brick.brick.commit(); brick.model = cpp::VolumetricModel(brick.brick); cpp::TransferFunction tfn("piecewiseLinear"); std::vector colors = {vec3f(0.f, 0.f, 1.f), vec3f(1.f, 0.f, 0.f)}; std::vector opacities = {0.05f, 1.f}; tfn.setParam("color", cpp::CopiedData(colors)); tfn.setParam("opacity", cpp::CopiedData(opacities)); // color the bricks by their rank, we pad the range out a bit to keep // any brick from being completely transparent range1f valueRange = range1f(0, mpiWorldSize); tfn.setParam("value", valueRange); tfn.commit(); brick.model.setParam("transferFunction", tfn); brick.model.setParam("samplingRate", 0.5f); brick.model.commit(); brick.group = cpp::Group(); brick.group.setParam("volume", cpp::CopiedData(brick.model)); brick.group.commit(); brick.instance = cpp::Instance(brick.group); brick.instance.commit(); return brick; } RenderKit-ospray-f2a61c2/modules/mpi/tutorials/ospMPIDistribTutorialReplicated.cpp000066400000000000000000000075301456566705700305540ustar00rootroot00000000000000// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This tutorial demonstrates how MPI-parallel applications can be * written which still render replicated data using the path tracer * for secondary effects. Applications can leverage MPI parallelism for * faster file I/O and load times when compared to the offload device. * However, such applications must be written to be aware of MPI while * the offload device behaves just like local rendering from the application's * perspective. */ #include #include #include #include #include #include "GLFWDistribOSPRayWindow.h" #include "ospray/ospray_cpp.h" #include "ospray/ospray_cpp/ext/rkcommon.h" #include "ospray/ospray_util.h" #include "ospray_testing.h" #include "rkcommon/utility/getEnvVar.h" using namespace ospray; using namespace rkcommon; using namespace rkcommon::math; static std::string rendererType = "pathtracer"; static std::string builderType = "boxes"; void printHelp() { std::cout << R"description( usage: ./ospMPIDistribTutorialReplicated [-h | --help] [[-s | --scene] scene] [[r | --renderer] renderer_type] scenes: boxes cornell_box curves cylinders empty gravity_spheres_volume perlin_noise_volumes random_spheres streamlines subdivision_cube unstructured_volume )description"; } int main(int argc, char **argv) { for (int i = 1; i < argc; ++i) { std::string arg = argv[i]; if (arg == "-h" || arg == "--help") { printHelp(); return 0; } else if (arg == "-r" || arg == "--renderer") { rendererType = argv[++i]; } else if (arg == "-s" || arg == "--scene") { builderType = argv[++i]; } } int mpiThreadCapability = 0; MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &mpiThreadCapability); if (mpiThreadCapability != MPI_THREAD_MULTIPLE && mpiThreadCapability != MPI_THREAD_SERIALIZED) { fprintf(stderr, "OSPRay requires the MPI runtime to support thread " "multiple or thread serialized.\n"); return 1; } int mpiRank = 0; int mpiWorldSize = 0; MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); MPI_Comm_size(MPI_COMM_WORLD, &mpiWorldSize); std::cout << "OSPRay rank " << mpiRank << "/" << mpiWorldSize << "\n"; // load the MPI module, and select the MPI distributed device. Here we // do not call ospInit, as we want to explicitly pick the distributed // device auto OSPRAY_MPI_DISTRIBUTED_GPU = utility::getEnvVar("OSPRAY_MPI_DISTRIBUTED_GPU").value_or(0); if (OSPRAY_MPI_DISTRIBUTED_GPU) { ospLoadModule("mpi_distributed_gpu"); } else { ospLoadModule("mpi_distributed_cpu"); } { cpp::Device mpiDevice("mpiDistributed"); mpiDevice.commit(); mpiDevice.setCurrent(); // set an error callback to catch any OSPRay errors and exit the application ospDeviceSetErrorCallback( mpiDevice.handle(), [](void *, OSPError error, const char *errorDetails) { std::cerr << "OSPRay error: " << errorDetails << std::endl; exit(error); }, nullptr); auto builder = testing::newBuilder(builderType); testing::setParam(builder, "rendererType", rendererType); testing::commit(builder); auto world = testing::buildWorld(builder); testing::release(builder); world.commit(); cpp::Renderer renderer(rendererType); renderer.commit(); // create a GLFW OSPRay window: this object will create and manage the // OSPRay frame buffer and camera directly auto glfwOSPRayWindow = std::unique_ptr(new GLFWDistribOSPRayWindow( vec2i{1024, 768}, box3f(vec3f(-1.f), vec3f(1.f)), world, renderer)); // start the GLFW main loop, which will continuously render glfwOSPRayWindow->mainLoop(); } // cleanly shut OSPRay down ospShutdown(); MPI_Finalize(); return 0; } RenderKit-ospray-f2a61c2/modules/mpi/tutorials/ospMPIDistribTutorialSpheres.cpp000066400000000000000000000161751456566705700301160ustar00rootroot00000000000000// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This larger example shows how to use the MPIDistributedDevice to write an * interactive rendering application, which shows a UI on rank 0 and uses * all ranks in the MPI world for data loading and rendering. Each rank * generates a local sub-piece of spheres data, e.g., as if rendering some * large distributed dataset. */ #include #include #include #include #include #include #include "GLFWDistribOSPRayWindow.h" #include "ospray/ospray_cpp.h" #include "ospray/ospray_cpp/ext/rkcommon.h" #include "rkcommon/utility/getEnvVar.h" using namespace ospray; using namespace rkcommon; using namespace rkcommon::math; // Generate the rank's local spheres within its assigned grid cell, and // return the bounds of this grid cell cpp::Instance makeLocalSpheres( const int mpiRank, const int mpiWorldSize, box3f &bounds); int main(int argc, char **argv) { int mpiThreadCapability = 0; MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &mpiThreadCapability); if (mpiThreadCapability != MPI_THREAD_MULTIPLE && mpiThreadCapability != MPI_THREAD_SERIALIZED) { fprintf(stderr, "OSPRay requires the MPI runtime to support thread " "multiple or thread serialized.\n"); return 1; } int mpiRank = 0; int mpiWorldSize = 0; MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); MPI_Comm_size(MPI_COMM_WORLD, &mpiWorldSize); std::cout << "OSPRay rank " << mpiRank << "/" << mpiWorldSize << "\n"; // load the MPI module, and select the MPI distributed device. Here we // do not call ospInit, as we want to explicitly pick the distributed // device auto OSPRAY_MPI_DISTRIBUTED_GPU = utility::getEnvVar("OSPRAY_MPI_DISTRIBUTED_GPU").value_or(0); if (OSPRAY_MPI_DISTRIBUTED_GPU) { ospLoadModule("mpi_distributed_gpu"); } else { ospLoadModule("mpi_distributed_cpu"); } { cpp::Device mpiDevice("mpiDistributed"); mpiDevice.commit(); mpiDevice.setCurrent(); // set an error callback to catch any OSPRay errors and exit the application ospDeviceSetErrorCallback( mpiDevice.handle(), [](void *, OSPError error, const char *errorDetails) { std::cerr << "OSPRay error: " << errorDetails << std::endl; exit(error); }, nullptr); // all ranks specify the same rendering parameters, with the exception of // the data to be rendered, which is distributed among the ranks box3f regionBounds; cpp::Instance spheres = makeLocalSpheres(mpiRank, mpiWorldSize, regionBounds); // create the "world" model which will contain all of our geometries cpp::World world; world.setParam("instance", cpp::CopiedData(spheres)); /* * Note: We've taken care that all the generated spheres are completely * within the bounds, and we don't have ghost data or portions of speres * to clip off. Thus we actually don't need to set region at all in * this tutorial. Example: * world.setParam("region", cpp::CopiedData(regionBounds)); */ world.commit(); // create OSPRay renderer cpp::Renderer renderer("mpiRaycast"); // create and setup an ambient light std::array lights = { cpp::Light("ambient"), cpp::Light("distant")}; lights[0].commit(); lights[1].setParam("direction", vec3f(-1.f, -1.f, 0.5f)); lights[1].commit(); renderer.setParam("lights", cpp::CopiedData(lights)); renderer.setParam("aoSamples", 1); // create a GLFW OSPRay window: this object will create and manage the // OSPRay frame buffer and camera directly auto glfwOSPRayWindow = std::unique_ptr(new GLFWDistribOSPRayWindow( vec2i{1024, 768}, box3f(vec3f(-1.f), vec3f(1.f)), world, renderer)); int spp = 1; int currentSpp = 1; if (mpiRank == 0) { glfwOSPRayWindow->registerImGuiCallback( [&]() { ImGui::SliderInt("pixelSamples", &spp, 1, 64); }); } glfwOSPRayWindow->registerDisplayCallback( [&](GLFWDistribOSPRayWindow *win) { // Send the UI changes out to the other ranks so we can synchronize // how many samples per-pixel we're taking MPI_Bcast(&spp, 1, MPI_INT, 0, MPI_COMM_WORLD); if (spp != currentSpp) { currentSpp = spp; renderer.setParam("pixelSamples", spp); win->addObjectToCommit(renderer.handle()); } }); // start the GLFW main loop, which will continuously render glfwOSPRayWindow->mainLoop(); } // cleanly shut OSPRay down ospShutdown(); MPI_Finalize(); return 0; } bool computeDivisor(int x, int &divisor) { int upperBound = std::sqrt(x); for (int i = 2; i <= upperBound; ++i) { if (x % i == 0) { divisor = i; return true; } } return false; } // Compute an X x Y x Z grid to have 'num' grid cells, // only gives a nice grid for numbers with even factors since // we don't search for factors of the number, we just try dividing by two vec3i computeGrid(int num) { vec3i grid(1); int axis = 0; int divisor = 0; while (computeDivisor(num, divisor)) { grid[axis] *= divisor; num /= divisor; axis = (axis + 1) % 3; } if (num != 1) { grid[axis] *= num; } return grid; } cpp::Instance makeLocalSpheres( const int mpiRank, const int mpiWorldSize, box3f &bounds) { const float sphereRadius = 0.1; std::vector spheres(50); // To simulate loading a shared dataset all ranks generate the same // sphere data. std::random_device rd; std::mt19937 rng(rd()); const vec3i grid = computeGrid(mpiWorldSize); const vec3i brickId(mpiRank % grid.x, (mpiRank / grid.x) % grid.y, mpiRank / (grid.x * grid.y)); // The grid is over the [-1, 1] box const vec3f brickSize = vec3f(2.0) / vec3f(grid); const vec3f brickLower = brickSize * brickId - vec3f(1.f); const vec3f brickUpper = brickSize * brickId - vec3f(1.f) + brickSize; bounds.lower = brickLower; bounds.upper = brickUpper; // Generate spheres within the box padded by the radius, so we don't need // to worry about ghost bounds std::uniform_real_distribution distX( brickLower.x + sphereRadius, brickUpper.x - sphereRadius); std::uniform_real_distribution distY( brickLower.y + sphereRadius, brickUpper.y - sphereRadius); std::uniform_real_distribution distZ( brickLower.z + sphereRadius, brickUpper.z - sphereRadius); for (auto &s : spheres) { s.x = distX(rng); s.y = distY(rng); s.z = distZ(rng); } cpp::Geometry sphereGeom("sphere"); sphereGeom.setParam("radius", sphereRadius); sphereGeom.setParam("sphere.position", cpp::CopiedData(spheres)); sphereGeom.commit(); vec3f color(0.f, 0.f, (mpiRank + 1.f) / mpiWorldSize); cpp::Material material("obj"); material.setParam("kd", color); material.commit(); cpp::GeometricModel model(sphereGeom); model.setParam("material", material); model.commit(); cpp::Group group; group.setParam("geometry", cpp::CopiedData(model)); group.commit(); cpp::Instance instance(group); instance.commit(); return instance; } RenderKit-ospray-f2a61c2/modules/mpi/tutorials/ospMPIDistribTutorialVolume.cpp000066400000000000000000000167221456566705700277520ustar00rootroot00000000000000// Copyright 2018 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This larger example shows how to use the MPIDistributedDevice to write an * interactive rendering application, which shows a UI on rank 0 and uses * all ranks in the MPI world for data loading and rendering. Each rank * generates a local sub-brick of volume data, as if rendering some * large distributed dataset. */ #include #include #include #include #include #include "GLFWDistribOSPRayWindow.h" #include "ospray/ospray_cpp.h" #include "ospray/ospray_cpp/ext/rkcommon.h" #include "ospray/ospray_util.h" #include "rkcommon/utility/getEnvVar.h" using namespace ospray; using namespace rkcommon; using namespace rkcommon::math; struct VolumeBrick { // the volume data itself cpp::Volume brick; cpp::VolumetricModel model; cpp::Group group; cpp::Instance instance; // the bounds of the owned portion of data box3f bounds; // the full bounds of the owned portion + ghost voxels box3f ghostBounds; }; static box3f worldBounds; // Generate the rank's local volume brick VolumeBrick makeLocalVolume(const int mpiRank, const int mpiWorldSize); int main(int argc, char **argv) { int mpiThreadCapability = 0; MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &mpiThreadCapability); if (mpiThreadCapability != MPI_THREAD_MULTIPLE && mpiThreadCapability != MPI_THREAD_SERIALIZED) { fprintf(stderr, "OSPRay requires the MPI runtime to support thread " "multiple or thread serialized.\n"); return 1; } int mpiRank = 0; int mpiWorldSize = 0; MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); MPI_Comm_size(MPI_COMM_WORLD, &mpiWorldSize); std::cout << "OSPRay rank " << mpiRank << "/" << mpiWorldSize << "\n"; // load the MPI module, and select the MPI distributed device. Here we // do not call ospInit, as we want to explicitly pick the distributed // device auto OSPRAY_MPI_DISTRIBUTED_GPU = utility::getEnvVar("OSPRAY_MPI_DISTRIBUTED_GPU").value_or(0); if (OSPRAY_MPI_DISTRIBUTED_GPU) { ospLoadModule("mpi_distributed_gpu"); } else { ospLoadModule("mpi_distributed_cpu"); } { cpp::Device mpiDevice("mpiDistributed"); mpiDevice.commit(); mpiDevice.setCurrent(); // set an error callback to catch any OSPRay errors and exit the application ospDeviceSetErrorCallback( mpiDevice.handle(), [](void *, OSPError error, const char *errorDetails) { std::cerr << "OSPRay error: " << errorDetails << std::endl; exit(error); }, nullptr); // all ranks specify the same rendering parameters, with the exception of // the data to be rendered, which is distributed among the ranks VolumeBrick brick = makeLocalVolume(mpiRank, mpiWorldSize); // create the "world" model which will contain all of our geometries cpp::World world; world.setParam("instance", cpp::CopiedData(brick.instance)); world.setParam("region", cpp::CopiedData(brick.bounds)); world.commit(); // create OSPRay renderer cpp::Renderer renderer("mpiRaycast"); // create and setup an ambient light cpp::Light ambientLight("ambient"); ambientLight.commit(); renderer.setParam("light", cpp::CopiedData(ambientLight)); // create a GLFW OSPRay window: this object will create and manage the // OSPRay frame buffer and camera directly auto glfwOSPRayWindow = std::unique_ptr(new GLFWDistribOSPRayWindow( vec2i{1024, 768}, worldBounds, world, renderer)); int spp = 1; int currentSpp = 1; if (mpiRank == 0) { glfwOSPRayWindow->registerImGuiCallback( [&]() { ImGui::SliderInt("pixelSamples", &spp, 1, 64); }); } glfwOSPRayWindow->registerDisplayCallback( [&](GLFWDistribOSPRayWindow *win) { // Send the UI changes out to the other ranks so we can synchronize // how many samples per-pixel we're taking MPI_Bcast(&spp, 1, MPI_INT, 0, MPI_COMM_WORLD); if (spp != currentSpp) { currentSpp = spp; renderer.setParam("pixelSamples", spp); win->addObjectToCommit(renderer.handle()); } }); // start the GLFW main loop, which will continuously render glfwOSPRayWindow->mainLoop(); } // cleanly shut OSPRay down ospShutdown(); MPI_Finalize(); return 0; } bool computeDivisor(int x, int &divisor) { int upperBound = std::sqrt(x); for (int i = 2; i <= upperBound; ++i) { if (x % i == 0) { divisor = i; return true; } } return false; } // Compute an X x Y x Z grid to have 'num' grid cells, // only gives a nice grid for numbers with even factors since // we don't search for factors of the number, we just try dividing by two vec3i computeGrid(int num) { vec3i grid(1); int axis = 0; int divisor = 0; while (computeDivisor(num, divisor)) { grid[axis] *= divisor; num /= divisor; axis = (axis + 1) % 3; } if (num != 1) { grid[axis] *= num; } return grid; } VolumeBrick makeLocalVolume(const int mpiRank, const int mpiWorldSize) { const vec3i grid = computeGrid(mpiWorldSize); const vec3i brickId(mpiRank % grid.x, (mpiRank / grid.x) % grid.y, mpiRank / (grid.x * grid.y)); // The bricks are 64^3 + 1 layer of ghost voxels on each axis const vec3i brickVolumeDims = vec3i(32); const vec3i brickGhostDims = vec3i(brickVolumeDims + 2); // The grid is over the [0, grid * brickVolumeDims] box worldBounds = box3f(vec3f(0.f), vec3f(grid * brickVolumeDims)); const vec3f brickLower = brickId * brickVolumeDims; const vec3f brickUpper = brickId * brickVolumeDims + brickVolumeDims; VolumeBrick brick; brick.bounds = box3f(brickLower, brickUpper); // we just put ghost voxels on all sides here, but a real application // would change which faces of each brick have ghost voxels dependent // on the actual data brick.ghostBounds = box3f(brickLower - vec3f(1.f), brickUpper + vec3f(1.f)); brick.brick = cpp::Volume("structuredRegular"); brick.brick.setParam("dimensions", brickGhostDims); // we use the grid origin to place this brick in the right position inside // the global volume brick.brick.setParam("gridOrigin", brick.ghostBounds.lower); // generate the volume data to just be filled with this rank's id const size_t nVoxels = brickGhostDims.x * brickGhostDims.y * brickGhostDims.z; std::vector volumeData(nVoxels, static_cast(mpiRank)); brick.brick.setParam("data", cpp::CopiedData(static_cast(volumeData.data()), vec3ul(brickVolumeDims))); brick.brick.commit(); brick.model = cpp::VolumetricModel(brick.brick); cpp::TransferFunction tfn("piecewiseLinear"); std::vector colors = {vec3f(0.f, 0.f, 1.f), vec3f(1.f, 0.f, 0.f)}; std::vector opacities = {0.05f, 1.f}; tfn.setParam("color", cpp::CopiedData(colors)); tfn.setParam("opacity", cpp::CopiedData(opacities)); // color the bricks by their rank, we pad the range out a bit to keep // any brick from being completely transparent range1f valueRange = range1f(0, mpiWorldSize); tfn.setParam("value", valueRange); tfn.commit(); brick.model.setParam("transferFunction", tfn); brick.model.setParam("samplingRate", 0.5f); brick.model.commit(); brick.group = cpp::Group(); brick.group.setParam("volume", cpp::CopiedData(brick.model)); brick.group.commit(); brick.instance = cpp::Instance(brick.group); brick.instance.commit(); return brick; } RenderKit-ospray-f2a61c2/modules/mpi/tutorials/ospMPIDistributedExamples.cpp000066400000000000000000000130121456566705700274040ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /* This example generates the same data on each rank so that we can build * off the existing OSPRay testing data generators, however each rank * specifies a subregion as its local domain to render the data as if it was * distributed. The scene to load can be passed as an argument to the * application */ #include #include #include #include #include #include "GLFWDistribOSPRayWindow.h" #include "ospray/ospray_cpp.h" #include "ospray/ospray_cpp/ext/rkcommon.h" #include "ospray/ospray_util.h" #include "ospray_testing.h" #include "rkcommon/utility/getEnvVar.h" using namespace ospray; using namespace rkcommon; using namespace rkcommon::math; bool computeDivisor(int x, int &divisor); // Compute an X x Y x Z grid to have 'num' grid cells, // only gives a nice grid for numbers with even factors since // we don't search for factors of the number, we just try dividing by two vec3i computeGrid(int num); int main(int argc, char **argv) { int mpiThreadCapability = 0; MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &mpiThreadCapability); if (mpiThreadCapability != MPI_THREAD_MULTIPLE && mpiThreadCapability != MPI_THREAD_SERIALIZED) { fprintf(stderr, "OSPRay requires the MPI runtime to support thread " "multiple or thread serialized.\n"); return 1; } std::string sceneName = "gravity_spheres_volume"; if (argc == 2) { sceneName = argv[1]; } int mpiRank = 0; int mpiWorldSize = 0; MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); MPI_Comm_size(MPI_COMM_WORLD, &mpiWorldSize); std::cout << "OSPRay rank " << mpiRank << "/" << mpiWorldSize << "\n"; // load the MPI module, and select the MPI distributed device. Here we // do not call ospInit, as we want to explicitly pick the distributed // device auto OSPRAY_MPI_DISTRIBUTED_GPU = utility::getEnvVar("OSPRAY_MPI_DISTRIBUTED_GPU").value_or(0); if (OSPRAY_MPI_DISTRIBUTED_GPU) { ospLoadModule("mpi_distributed_gpu"); } else { ospLoadModule("mpi_distributed_cpu"); } { cpp::Device mpiDevice("mpiDistributed"); mpiDevice.commit(); mpiDevice.setCurrent(); // set an error callback to catch any OSPRay errors and exit the application mpiDevice.setErrorCallback( [](void *, OSPError error, const char *errorDetails) { std::cerr << "OSPRay error: " << errorDetails << std::endl; exit(error); }); // Regions are assigned to ranks in 3D grid, determine which brick of the // grid is owned by this rank const vec3i distribGrid = computeGrid(mpiWorldSize); const vec3i distribBrickId(mpiRank % distribGrid.x, (mpiRank / distribGrid.x) % distribGrid.y, mpiRank / (distribGrid.x * distribGrid.y)); std::cout << "scene = " << sceneName << "\n"; auto builder = testing::newBuilder(sceneName); testing::setParam(builder, "rendererType", "scivis"); testing::commit(builder); auto group = testing::buildGroup(builder); const box3f worldBounds = group.getBounds(); cpp::Instance instance(group); instance.commit(); cpp::World world; world.setParam("instance", cpp::CopiedData(instance)); cpp::Light light("ambient"); light.setParam("visible", false); light.commit(); world.setParam("light", cpp::CopiedData(light)); // Determine the bounds of this rank's region in world space const vec3f distribBrickDims = worldBounds.size() / vec3f(distribGrid); box3f localRegion(distribBrickId * distribBrickDims + worldBounds.lower, distribBrickId * distribBrickDims + distribBrickDims + worldBounds.lower); // Special case for the ospray test data: we might have geometry right at // the region bounding box which will z-fight with the clipping region. If // we have a region at the edge of the domain, apply some padding for (int i = 0; i < 3; ++i) { if (localRegion.lower[i] == worldBounds.lower[i]) { localRegion.lower[i] -= 0.001; } if (localRegion.upper[i] == worldBounds.upper[i]) { localRegion.upper[i] += 0.001; } } // Set our region that represents the bounds of the local data we own on // this rank world.setParam("region", cpp::CopiedData(localRegion)); world.commit(); testing::release(builder); // create OSPRay renderer cpp::Renderer renderer("mpiRaycast"); // create a GLFW OSPRay window: this object will create and manage the // OSPRay frame buffer and camera directly auto glfwOSPRayWindow = std::unique_ptr(new GLFWDistribOSPRayWindow( vec2i{1024, 768}, worldBounds, world, renderer)); // start the GLFW main loop, which will continuously render glfwOSPRayWindow->mainLoop(); } // cleanly shut OSPRay down ospShutdown(); MPI_Finalize(); return 0; } bool computeDivisor(int x, int &divisor) { int upperBound = std::sqrt(x); for (int i = 2; i <= upperBound; ++i) { if (x % i == 0) { divisor = i; return true; } } return false; } // Compute an X x Y x Z grid to have 'num' grid cells, // only gives a nice grid for numbers with even factors since // we don't search for factors of the number, we just try dividing by two vec3i computeGrid(int num) { vec3i grid(1); int axis = 0; int divisor = 0; while (computeDivisor(num, divisor)) { grid[axis] *= divisor; num /= divisor; axis = (axis + 1) % 3; } if (num != 1) { grid[axis] *= num; } return grid; } RenderKit-ospray-f2a61c2/modules/multiDevice/000077500000000000000000000000001456566705700212715ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/multiDevice/CMakeLists.txt000066400000000000000000000043711456566705700240360ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 cmake_dependent_option( OSPRAY_MODULE_MULTIDEVICE "Build the multidevice module" OFF OSPRAY_MODULE_CPU OFF ) if (NOT OSPRAY_MODULE_MULTIDEVICE) return() endif() rkcommon_configure_build_type() set(OSPRAY_MULTIDEVICE_CPP_SOURCES ${OSPRAY_RESOURCE} MultiDevice.cpp MultiDeviceLoadBalancer.cpp MultiDeviceModuleInit.cpp ) include_directories_ispc( ${PROJECT_SOURCE_DIR}/ospray/include ${PROJECT_SOURCE_DIR}/ospray ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${RKCOMMON_INCLUDE_DIRS} ${EMBREE_INCLUDE_DIRS} ) add_definitions_ispc( OSPRAY_BEGIN_ISPC_NAMESPACE= OSPRAY_END_ISPC_NAMESPACE= SYCL_EXTERNAL= OSPRAY_ENABLE_VOLUMES ) add_library(ospray_module_multidevice_cpu SHARED) ispc_target_add_sources(ospray_module_multidevice_cpu ${OSPRAY_MULTIDEVICE_CPP_SOURCES} ) target_link_libraries(ospray_module_multidevice_cpu PRIVATE rkcommon::rkcommon ospray_module_cpu ) target_include_directories(ospray_module_multidevice_cpu PUBLIC $ PRIVATE ${CMAKE_CURRENT_BINARY_DIR} # For ISPC module generated ispc headers ${PROJECT_BINARY_DIR}/ospray/ ) target_compile_definitions(ospray_module_multidevice_cpu PRIVATE OBJECTFACTORY_IMPORT ) ospray_install_library(ospray_module_multidevice_cpu lib) if (OSPRAY_MODULE_GPU) include(${ISPCRT_DIR}/interop.cmake) if (NOT "${CMAKE_CXX_COMPILER}" STREQUAL "${DPCPP_COMPILER}") message(FATAL_ERROR "CMAKE_CXX_COMPILER should be set to '${DPCPP_COMPILER}' for SYCL") endif() add_library(ospray_module_multidevice_gpu SHARED ${OSPRAY_MULTIDEVICE_CPP_SOURCES}) target_link_libraries(ospray_module_multidevice_gpu PRIVATE rkcommon::rkcommon ospray_module_gpu ) target_include_directories(ospray_module_multidevice_gpu PUBLIC $ $ PRIVATE ${CMAKE_CURRENT_BINARY_DIR} # For ISPC module generated ispc headers ${PROJECT_BINARY_DIR}/ospray/ ) target_compile_definitions(ospray_module_multidevice_gpu PRIVATE OBJECTFACTORY_IMPORT ) ospray_install_library(ospray_module_multidevice_gpu lib) endif() RenderKit-ospray-f2a61c2/modules/multiDevice/MultiDevice.cpp000066400000000000000000000437451456566705700242240ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "MultiDevice.h" #include "MultiDeviceFrameBuffer.h" #include "MultiDeviceRenderTask.h" #include "camera/registration.h" #include "fb/LocalFB.h" #include "fb/SparseFB.h" #include "fb/registration.h" #include "geometry/registration.h" #include "lights/registration.h" #include "render/LoadBalancer.h" #include "render/RenderTask.h" #include "render/registration.h" #include "rkcommon/tasking/parallel_for.h" #include "rkcommon/tasking/tasking_system_init.h" #include "rkcommon/utility/CodeTimer.h" #include "rkcommon/utility/getEnvVar.h" #include "rkcommon/utility/multidim_index_sequence.h" #include "texture/registration.h" #include "volume/transferFunction/registration.h" namespace ospray { namespace api { ///////////////////////////////////////////////////////////////////////// // ManagedObject Implementation ///////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// void MultiDevice::commit() { Device::commit(); // Needed for proper ISPCRT device construction hostDevice.commit(); ispcrt::Context ispcrtContext; ispcrt::Device ispcrtDevice; int numPhyDevices = 1; #ifdef OSPRAY_TARGET_SYCL numPhyDevices = ispcrtGetDeviceCount(ISPCRT_DEVICE_TYPE_GPU); ispcrtContext = ispcrt::Context(ISPCRT_DEVICE_TYPE_GPU); #else numPhyDevices = ispcrtGetDeviceCount(ISPCRT_DEVICE_TYPE_CPU); #endif if (subdevices.empty()) { auto OSPRAY_NUM_SUBDEVICES = utility::getEnvVar("OSPRAY_NUM_SUBDEVICES"); int numSubdevices = OSPRAY_NUM_SUBDEVICES.value_or(getParam("numSubdevices", 1)); std::vector deviceIndex(numSubdevices, 0); for (int i = 0; i < numSubdevices; i++) deviceIndex[i] = i % numPhyDevices; postStatusMsg(OSP_LOG_DEBUG) << "# of subdevices =" << numSubdevices; std::vector> subdeviceLoadBalancers; for (int i = 0; i < numSubdevices; ++i) { auto d = make_unique(); #ifdef OSPRAY_TARGET_SYCL if (ispcrtContext) { ispcrtDevice = ispcrt::Device(ispcrtContext, deviceIndex[i]); d->setParam("ispcrtContext", &ispcrtContext); d->setParam("ispcrtDevice", &ispcrtDevice); } #endif d->commit(); subdevices.emplace_back(std::move(d)); subdeviceLoadBalancers.push_back(subdevices.back()->loadBalancer); } loadBalancer = rkcommon::make_unique(subdeviceLoadBalancers); } } ///////////////////////////////////////////////////////////////////////// // Device Implementation //////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// int MultiDevice::loadModule(const char *name) { OSPError err = OSP_NO_ERROR; for (auto &d : subdevices) { auto e = d->loadModule(name); if (e != OSP_NO_ERROR) { err = (OSPError)e; } } return err; } // OSPRay Data Arrays /////////////////////////////////////////////////// static void multiDeviceObjectDeleter(const void *object, const void *) { memory::RefCount *o = (memory::RefCount *)object; o->refDec(); } OSPData MultiDevice::newSharedData(const void *sharedData, OSPDataType type, const vec3ul &numItems, const vec3l &byteStride, OSPDeleterCallback freeFunction, const void *userData) { MultiDeviceObject *o = new MultiDeviceObject; o->freeFunction = freeFunction; o->userData = userData; o->sharedData = sharedData; // Data arrays of OSPRay objects need to populate the corresponding subdevice // data arrays with the objects for that subdevice if (type & OSP_OBJECT) { for (size_t i = 0; i < subdevices.size(); ++i) { o->objects.push_back( (OSPObject) new Data(*subdevices[i], type, numItems)); } // A little lazy here, but using the Data object to just give me a view // + the index sequence iterator to use to step over the stride Data *multiData = new Data(hostDevice, sharedData, type, numItems, byteStride); o->sharedDataDirtyReference = multiData; index_sequence_3D seq(numItems); for (auto idx : seq) { MultiDeviceObject *mobj = *(MultiDeviceObject **)multiData->data(idx); retain((OSPObject)mobj); // Copy the subdevice object handles to the data arrays for each subdevice for (size_t i = 0; i < subdevices.size(); ++i) { Data *subdeviceData = (Data *)o->objects[i]; std::memcpy( subdeviceData->data(idx), &mobj->objects[i], sizeof(OSPObject)); } } } else { for (auto &d : subdevices) { o->refInc(); o->objects.push_back(d->newSharedData( sharedData, type, numItems, byteStride, multiDeviceObjectDeleter, o)); } } return (OSPData)o; } OSPData MultiDevice::newData(OSPDataType type, const vec3ul &numItems) { MultiDeviceObject *o = new MultiDeviceObject; for (auto &d : subdevices) { o->objects.push_back(d->newData(type, numItems)); } return (OSPData)o; } void MultiDevice::copyData( const OSPData source, OSPData destination, const vec3ul &destinationIndex) { const MultiDeviceObject *srcs = (const MultiDeviceObject *)source; MultiDeviceObject *dsts = (MultiDeviceObject *)destination; for (size_t i = 0; i < subdevices.size(); ++i) { subdevices[i]->copyData( (OSPData)srcs->objects[i], (OSPData)dsts->objects[i], destinationIndex); } } // Renderable Objects /////////////////////////////////////////////////// OSPLight MultiDevice::newLight(const char *type) { MultiDeviceObject *o = new MultiDeviceObject; for (auto &d : subdevices) { o->objects.push_back(d->newLight(type)); } return (OSPLight)o; } OSPCamera MultiDevice::newCamera(const char *type) { MultiDeviceObject *o = new MultiDeviceObject; for (auto &d : subdevices) { o->objects.push_back(d->newCamera(type)); } return (OSPCamera)o; } OSPGeometry MultiDevice::newGeometry(const char *type) { MultiDeviceObject *o = new MultiDeviceObject; for (auto &d : subdevices) { o->objects.push_back(d->newGeometry(type)); } return (OSPGeometry)o; } OSPVolume MultiDevice::newVolume(const char *type) { MultiDeviceObject *o = new MultiDeviceObject; for (auto &d : subdevices) { o->objects.push_back(d->newVolume(type)); } return (OSPVolume)o; } OSPGeometricModel MultiDevice::newGeometricModel(OSPGeometry geom) { MultiDeviceObject *g = (MultiDeviceObject *)geom; MultiDeviceObject *o = new MultiDeviceObject; for (size_t i = 0; i < subdevices.size(); ++i) { OSPGeometry subdeviceObj = g ? (OSPGeometry)g->objects[i] : (OSPGeometry) nullptr; o->objects.push_back(subdevices[i]->newGeometricModel(subdeviceObj)); } return (OSPGeometricModel)o; } OSPVolumetricModel MultiDevice::newVolumetricModel(OSPVolume volume) { MultiDeviceObject *v = (MultiDeviceObject *)volume; MultiDeviceObject *o = new MultiDeviceObject; for (size_t i = 0; i < subdevices.size(); ++i) { OSPVolume subdeviceObj = v ? (OSPVolume)v->objects[i] : (OSPVolume) nullptr; o->objects.push_back(subdevices[i]->newVolumetricModel(subdeviceObj)); } return (OSPVolumetricModel)o; } // Model Meta-Data ////////////////////////////////////////////////////// OSPMaterial MultiDevice::newMaterial(const char *material_type) { MultiDeviceObject *o = new MultiDeviceObject; for (auto &d : subdevices) { o->objects.push_back(d->newMaterial(material_type)); } return (OSPMaterial)o; } OSPTransferFunction MultiDevice::newTransferFunction(const char *type) { MultiDeviceObject *o = new MultiDeviceObject; for (auto &d : subdevices) { o->objects.push_back(d->newTransferFunction(type)); } return (OSPTransferFunction)o; } OSPTexture MultiDevice::newTexture(const char *type) { MultiDeviceObject *o = new MultiDeviceObject; for (auto &d : subdevices) { o->objects.push_back(d->newTexture(type)); } return (OSPTexture)o; } // Instancing /////////////////////////////////////////////////////////// OSPGroup MultiDevice::newGroup() { MultiDeviceObject *o = new MultiDeviceObject; for (auto &d : subdevices) { o->objects.push_back(d->newGroup()); } return (OSPGroup)o; } OSPInstance MultiDevice::newInstance(OSPGroup group) { MultiDeviceObject *g = (MultiDeviceObject *)group; MultiDeviceObject *o = new MultiDeviceObject; for (size_t i = 0; i < subdevices.size(); ++i) { OSPGroup subdeviceObj = g ? (OSPGroup)g->objects[i] : (OSPGroup) nullptr; o->objects.push_back(subdevices[i]->newInstance(subdeviceObj)); } return (OSPInstance)o; } // Top-level Worlds ///////////////////////////////////////////////////// OSPWorld MultiDevice::newWorld() { MultiDeviceObject *o = new MultiDeviceObject; for (auto &d : subdevices) { o->objects.push_back(d->newWorld()); } return (OSPWorld)o; } box3f MultiDevice::getBounds(OSPObject obj) { MultiDeviceObject *o = (MultiDeviceObject *)obj; // Everything is replicated across the subdevices, so we // can just query the bounds from one of them return subdevices[0]->getBounds(o->objects[0]); } // Object + Parameter Lifetime Management /////////////////////////////// void MultiDevice::setObjectParam( OSPObject object, const char *name, OSPDataType type, const void *mem) { // If the type is an OSPObject, we need to find the per-subdevice objects // and set them appropriately MultiDeviceObject *o = (MultiDeviceObject *)object; if (type & OSP_OBJECT) { MultiDeviceObject *p = *(MultiDeviceObject **)mem; for (size_t i = 0; i < subdevices.size(); ++i) { subdevices[i]->setObjectParam(o->objects[i], name, type, &p->objects[i]); } } else { for (size_t i = 0; i < subdevices.size(); ++i) { subdevices[i]->setObjectParam(o->objects[i], name, type, mem); } } // Handle parameters for rowmajor framebuffer MultiDeviceFrameBuffer *fb = dynamic_cast(o); if (fb) { if (type & OSP_OBJECT) { MultiDeviceObject *p = *(MultiDeviceObject **)mem; hostDevice.setObjectParam( (OSPObject)fb->rowmajorFb.ptr, name, type, &p->objects[0]); } else { hostDevice.setObjectParam((OSPObject)fb->rowmajorFb.ptr, name, type, mem); } } } void MultiDevice::removeObjectParam(OSPObject object, const char *name) { MultiDeviceObject *o = (MultiDeviceObject *)object; for (size_t i = 0; i < subdevices.size(); ++i) { subdevices[i]->removeObjectParam(o->objects[i], name); } // Handle parameters for rowmajor framebuffer MultiDeviceFrameBuffer *fb = dynamic_cast(o); if (fb) hostDevice.removeObjectParam((OSPObject)fb->rowmajorFb.ptr, name); } void MultiDevice::commit(OSPObject object) { MultiDeviceObject *o = (MultiDeviceObject *)object; // Applications can change their shared buffer contents directly, // so shared arrays of objects have to do more to ensure that the // contents are up to date. Specifically the handles have to be // translated down to the subdevice specific handles correctly. if (o->sharedDataDirtyReference) { Data *multiData = o->sharedDataDirtyReference; const vec3ul &numItems = multiData->numItems; index_sequence_3D seq(numItems); for (auto idx : seq) { MultiDeviceObject *mobj = *(MultiDeviceObject **)multiData->data(idx); retain((OSPObject)mobj); // Copy the subdevice object handles to the data arrays for each subdevice for (size_t i = 0; i < subdevices.size(); ++i) { Data *subdeviceData = (Data *)o->objects[i]; std::memcpy( subdeviceData->data(idx), &mobj->objects[i], sizeof(OSPObject)); } } } for (size_t i = 0; i < subdevices.size(); ++i) { subdevices[i]->commit(o->objects[i]); } // Handle commits for rowmajor framebuffer MultiDeviceFrameBuffer *fb = dynamic_cast(o); if (fb) hostDevice.commit((OSPObject)fb->rowmajorFb.ptr); } void MultiDevice::release(OSPObject object) { memory::RefCount *o = (memory::RefCount *)object; MultiDeviceObject *mo = dynamic_cast(o); if (mo) { if (mo->sharedDataDirtyReference) { Data *multiData = mo->sharedDataDirtyReference; const vec3ul &numItems = multiData->numItems; index_sequence_3D seq(numItems); for (auto idx : seq) { MultiDeviceObject *mobj = *(MultiDeviceObject **)multiData->data(idx); mobj->refDec(); } } for (size_t i = 0; i < mo->objects.size(); ++i) { subdevices[i]->release(mo->objects[i]); } } o->refDec(); } void MultiDevice::retain(OSPObject object) { memory::RefCount *o = (memory::RefCount *)object; MultiDeviceObject *mo = dynamic_cast(o); if (mo) { for (size_t i = 0; i < mo->objects.size(); ++i) { subdevices[i]->retain(mo->objects[i]); } } o->refInc(); } // FrameBuffer Manipulation ///////////////////////////////////////////// OSPFrameBuffer MultiDevice::frameBufferCreate( const vec2i &size, const OSPFrameBufferFormat mode, const uint32 channels) { MultiDeviceFrameBuffer *o = new MultiDeviceFrameBuffer(); o->rowmajorFb = new LocalFrameBuffer(hostDevice, size, mode, channels); // Need one refDec here for the local scope ref (see issue about Ref<>) o->rowmajorFb->refDec(); const vec2i totalTiles = divRoundUp(size, vec2i(TILE_SIZE)); for (size_t i = 0; i < subdevices.size(); ++i) { // Assign tiles round-robin among the subdevices std::vector tileIDs; for (uint32_t tid = 0; tid < totalTiles.long_product(); ++tid) { if (tid % subdevices.size() == i) { tileIDs.push_back(tid); } } FrameBuffer *fbi = new SparseFrameBuffer(*subdevices[i], size, mode, channels, tileIDs); o->objects.push_back((OSPFrameBuffer)fbi); } return (OSPFrameBuffer)o; } OSPImageOperation MultiDevice::newImageOp(const char *type) { // In principle we don't need multiple ImageOp objects, but as long as we do // not use objects reference counting in MultiDeviceObject we need them for // proper memory handling MultiDeviceObject *o = new MultiDeviceObject(); for (auto &d : subdevices) { o->objects.push_back(d->newImageOp(type)); } return (OSPImageOperation)o; } const void *MultiDevice::frameBufferMap( OSPFrameBuffer _fb, const OSPFrameBufferChannel channel) { MultiDeviceFrameBuffer *o = (MultiDeviceFrameBuffer *)_fb; return o->rowmajorFb->mapBuffer(channel); } void MultiDevice::frameBufferUnmap(const void *mapped, OSPFrameBuffer _fb) { MultiDeviceFrameBuffer *o = (MultiDeviceFrameBuffer *)_fb; o->rowmajorFb->unmap(mapped); } float MultiDevice::getVariance(OSPFrameBuffer _fb) { MultiDeviceFrameBuffer *o = (MultiDeviceFrameBuffer *)_fb; return o->rowmajorFb->getVariance(); } void MultiDevice::resetAccumulation(OSPFrameBuffer _fb) { MultiDeviceFrameBuffer *o = (MultiDeviceFrameBuffer *)_fb; o->rowmajorFb->clear(); for (size_t i = 0; i < subdevices.size(); ++i) { SparseFrameBuffer *fbi = (SparseFrameBuffer *)o->objects[i]; fbi->clear(); } } // Frame Rendering ////////////////////////////////////////////////////// OSPRenderer MultiDevice::newRenderer(const char *type) { MultiDeviceObject *o = new MultiDeviceObject; for (auto &d : subdevices) { o->objects.push_back(d->newRenderer(type)); } return (OSPRenderer)o; } OSPFuture MultiDevice::renderFrame(OSPFrameBuffer _framebuffer, OSPRenderer _renderer, OSPCamera _camera, OSPWorld _world) { MultiDeviceFrameBuffer *multiFb = (MultiDeviceFrameBuffer *)_framebuffer; multiFb->rowmajorFb->setCompletedEvent(OSP_NONE_FINISHED); for (size_t i = 0; i < multiFb->objects.size(); ++i) { SparseFrameBuffer *fbi = (SparseFrameBuffer *)multiFb->objects[i]; fbi->setCompletedEvent(OSP_NONE_FINISHED); } MultiDeviceObject *multiRenderer = (MultiDeviceObject *)_renderer; MultiDeviceObject *multiCamera = (MultiDeviceObject *)_camera; MultiDeviceObject *multiWorld = (MultiDeviceObject *)_world; retain((OSPObject)multiFb); retain((OSPObject)multiRenderer); retain((OSPObject)multiCamera); retain((OSPObject)multiWorld); auto *f = new MultiDeviceRenderTask(multiFb, [=]() { utility::CodeTimer timer; timer.start(); loadBalancer->renderFrame(multiFb, multiRenderer, multiCamera, multiWorld); timer.stop(); release((OSPObject)multiFb); release((OSPObject)multiRenderer); release((OSPObject)multiCamera); release((OSPObject)multiWorld); return timer.seconds(); }); return (OSPFuture)f; } int MultiDevice::isReady(OSPFuture _task, OSPSyncEvent event) { auto *task = (Future *)_task; return task->isFinished(event); } void MultiDevice::wait(OSPFuture _task, OSPSyncEvent event) { auto *task = (Future *)_task; task->wait(event); } void MultiDevice::cancel(OSPFuture _task) { auto *task = (Future *)_task; return task->cancel(); } float MultiDevice::getProgress(OSPFuture _task) { auto *task = (Future *)_task; return task->getProgress(); } float MultiDevice::getTaskDuration(OSPFuture _task) { auto *task = (Future *)_task; return task->getTaskDuration(); } void *MultiDevice::getPostProcessingCommandQueuePtr() { // TODO: Return appropriate command queue for post-processing here. // Either one device will be statically selected for post-processing or // dynamically load balancer will assign device based on current load // distribution return nullptr; } OSPPickResult MultiDevice::pick(OSPFrameBuffer _fb, OSPRenderer _renderer, OSPCamera _camera, OSPWorld _world, const vec2f &screenPos) { MultiDeviceObject *multiFb = (MultiDeviceObject *)_fb; FrameBuffer *fb = (FrameBuffer *)multiFb->objects[0]; MultiDeviceObject *multiRenderer = (MultiDeviceObject *)_renderer; MultiDeviceObject *multiCamera = (MultiDeviceObject *)_camera; MultiDeviceObject *multiWorld = (MultiDeviceObject *)_world; // Data in the multidevice is all replicated, so we just run the pick on the // first subdevice return subdevices[0]->pick((OSPFrameBuffer)fb, (OSPRenderer)multiRenderer->objects[0], (OSPCamera)multiCamera->objects[0], (OSPWorld)multiWorld->objects[0], screenPos); } } // namespace api } // namespace ospray RenderKit-ospray-f2a61c2/modules/multiDevice/MultiDevice.h000066400000000000000000000103701456566705700236550ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include #include "ISPCDevice.h" #include "MultiDeviceLoadBalancer.h" #include "MultiDeviceObject.h" #include "MultiDeviceRenderTask.h" // MultiDevice.h Implements the a multiplexor for other OSPRay devices which // this simply farms work out to in an image parallel fashion. namespace ospray { namespace api { struct MultiDevice : public Device { MultiDevice() = default; ///////////////////////////////////////////////////////////////////////// // ManagedObject Implementation ///////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// void commit() override; ///////////////////////////////////////////////////////////////////////// // Device Implementation //////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// int loadModule(const char *name) override; // OSPRay Data Arrays /////////////////////////////////////////////////// OSPData newSharedData(const void *sharedData, OSPDataType, const vec3ul &numItems, const vec3l &byteStride, OSPDeleterCallback, const void *userPtr) override; OSPData newData(OSPDataType, const vec3ul &numItems) override; void copyData(const OSPData source, OSPData destination, const vec3ul &destinationIndex) override; // Renderable Objects /////////////////////////////////////////////////// OSPLight newLight(const char *type) override; OSPCamera newCamera(const char *type) override; OSPGeometry newGeometry(const char *type) override; OSPVolume newVolume(const char *type) override; OSPGeometricModel newGeometricModel(OSPGeometry geom) override; OSPVolumetricModel newVolumetricModel(OSPVolume volume) override; // Model Meta-Data ////////////////////////////////////////////////////// OSPMaterial newMaterial(const char *material_type) override; OSPTransferFunction newTransferFunction(const char *type) override; OSPTexture newTexture(const char *type) override; // Instancing /////////////////////////////////////////////////////////// OSPGroup newGroup() override; OSPInstance newInstance(OSPGroup group) override; // Top-level Worlds ///////////////////////////////////////////////////// OSPWorld newWorld() override; box3f getBounds(OSPObject) override; // Object + Parameter Lifetime Management /////////////////////////////// void setObjectParam(OSPObject object, const char *name, OSPDataType type, const void *mem) override; void removeObjectParam(OSPObject object, const char *name) override; void commit(OSPObject object) override; void release(OSPObject _obj) override; void retain(OSPObject _obj) override; // FrameBuffer Manipulation ///////////////////////////////////////////// OSPFrameBuffer frameBufferCreate(const vec2i &size, const OSPFrameBufferFormat mode, const uint32 channels) override; OSPImageOperation newImageOp(const char *type) override; const void *frameBufferMap( OSPFrameBuffer fb, const OSPFrameBufferChannel) override; void frameBufferUnmap(const void *mapped, OSPFrameBuffer fb) override; float getVariance(OSPFrameBuffer) override; void resetAccumulation(OSPFrameBuffer _fb) override; // Frame Rendering ////////////////////////////////////////////////////// OSPRenderer newRenderer(const char *type) override; OSPFuture renderFrame( OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld) override; int isReady(OSPFuture, OSPSyncEvent) override; void wait(OSPFuture, OSPSyncEvent) override; void cancel(OSPFuture) override; float getProgress(OSPFuture) override; float getTaskDuration(OSPFuture) override; void *getPostProcessingCommandQueuePtr() override; OSPPickResult pick( OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld, const vec2f &) override; private: std::unique_ptr loadBalancer; ISPCDevice hostDevice; std::vector> subdevices; }; extern "C" OSPError OSPRAY_DLLEXPORT ospray_module_init_multi( int16_t versionMajor, int16_t versionMinor, int16_t /*versionPatch*/); } // namespace api } // namespace ospray RenderKit-ospray-f2a61c2/modules/multiDevice/MultiDeviceFrameBuffer.h000066400000000000000000000011551456566705700257630ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "MultiDeviceObject.h" #include "fb/LocalFB.h" namespace ospray { namespace api { /* The MultiDeviceFrameBuffer stores a SparseFB for each subdevice containing * the tiles the subdevice will render, along with a rowmajorFb that will be * exposed to the application. After rendering, the sparse framebuffers are * untiled into the rowmajorFb to return the rendered image to the app */ struct MultiDeviceFrameBuffer : MultiDeviceObject { Ref rowmajorFb; }; } // namespace api } // namespace ospray RenderKit-ospray-f2a61c2/modules/multiDevice/MultiDeviceLoadBalancer.cpp000066400000000000000000000033461456566705700264450ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "MultiDeviceLoadBalancer.h" #include "MultiDevice.h" #include "fb/LocalFB.h" #include "fb/SparseFB.h" #include #include namespace ospray { MultiDeviceLoadBalancer::MultiDeviceLoadBalancer( const std::vector> &loadBalancers) : loadBalancers(loadBalancers) {} void MultiDeviceLoadBalancer::renderFrame( api::MultiDeviceFrameBuffer *framebuffer, api::MultiDeviceObject *renderer, api::MultiDeviceObject *camera, api::MultiDeviceObject *world) { framebuffer->rowmajorFb->beginFrame(); tasking::parallel_for(framebuffer->objects.size(), [&](size_t i) { SparseFrameBuffer *fbi = (SparseFrameBuffer *)framebuffer->objects[i]; Renderer *ri = (Renderer *)renderer->objects[i]; Camera *ci = (Camera *)camera->objects[i]; World *wi = (World *)world->objects[i]; if (fbi->getTileIDs().size() != 0) { loadBalancers[i]->renderFrame(fbi, ri, ci, wi); framebuffer->rowmajorFb->writeTiles(fbi); } }); framebuffer->rowmajorFb->setCompletedEvent(OSP_WORLD_RENDERED); // We need to call post-processing operations on fully compositioned // (rowmajorFb) frame buffer and wait for it to finish framebuffer->rowmajorFb->postProcess(true); for (size_t i = 0; i < framebuffer->objects.size(); ++i) { SparseFrameBuffer *fbi = (SparseFrameBuffer *)framebuffer->objects[i]; fbi->setCompletedEvent(OSP_FRAME_FINISHED); } framebuffer->rowmajorFb->setCompletedEvent(OSP_FRAME_FINISHED); } std::string MultiDeviceLoadBalancer::toString() const { return "ospray::MultiDeviceLoadBalancer"; } } // namespace ospray RenderKit-ospray-f2a61c2/modules/multiDevice/MultiDeviceLoadBalancer.h000066400000000000000000000015051456566705700261050ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include "MultiDeviceFrameBuffer.h" #include "MultiDeviceObject.h" #include "render/LoadBalancer.h" #include "rkcommon/utility/ArrayView.h" namespace ospray { struct MultiDeviceLoadBalancer { MultiDeviceLoadBalancer( const std::vector> &loadBalancers); void renderFrame(api::MultiDeviceFrameBuffer *framebuffer, api::MultiDeviceObject *renderer, api::MultiDeviceObject *camera, api::MultiDeviceObject *world); std::string toString() const; private: // The subdevice load balancers that this multidevice load balancer will // distribute the rendering workload over std::vector> loadBalancers; }; } // namespace ospray RenderKit-ospray-f2a61c2/modules/multiDevice/MultiDeviceModuleInit.cpp000066400000000000000000000020471456566705700262040ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // We don't want an instance of ObjectFactory static table in this library // so we have to include it with import define so the table will be imported // from 'ospray' library #include "common/ObjectFactory.h" #include "MultiDevice.h" #include "MultiDeviceLoadBalancer.h" #include "common/OSPCommon.h" extern "C" OSPError OSPRAY_DLLEXPORT #ifdef OSPRAY_TARGET_SYCL ospray_module_init_multidevice_gpu( #else ospray_module_init_multidevice_cpu( #endif int16_t versionMajor, int16_t versionMinor, int16_t /*versionPatch*/) { using namespace ospray; auto status = moduleVersionCheck(versionMajor, versionMinor); if (status == OSP_NO_ERROR) { // Run the ISPC module's initialization function as well to register local // types #ifdef OSPRAY_TARGET_SYCL status = ospLoadModule("gpu"); #else status = ospLoadModule("cpu"); #endif } if (status == OSP_NO_ERROR) { api::Device::registerType("multidevice"); } return status; } RenderKit-ospray-f2a61c2/modules/multiDevice/MultiDeviceObject.h000066400000000000000000000014111456566705700250000ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/Data.h" namespace ospray { namespace api { // An object in the multidevice is just a container to hold // the handles to the actual objects of each subdevice struct MultiDeviceObject : public memory::RefCount { std::vector objects; OSPDeleterCallback freeFunction{nullptr}; const void *userData{nullptr}; const void *sharedData{nullptr}; // sharedDataDirtyReference is held temporarily to ensure consistency Data *sharedDataDirtyReference = nullptr; virtual ~MultiDeviceObject() override { delete sharedDataDirtyReference; if (freeFunction) freeFunction(userData, sharedData); } }; } // namespace api } // namespace ospray RenderKit-ospray-f2a61c2/modules/multiDevice/MultiDeviceRenderTask.h000066400000000000000000000044551456566705700256470ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include "MultiDeviceFrameBuffer.h" // ospray #include "common/Future.h" #include "fb/FrameBuffer.h" namespace ospray { namespace api { struct MultiDeviceRenderTask : public Future { MultiDeviceRenderTask(MultiDeviceFrameBuffer *fb, std::function fcn); ~MultiDeviceRenderTask() override; bool isFinished(OSPSyncEvent event = OSP_TASK_FINISHED) override; void wait(OSPSyncEvent event) override; void cancel() override; float getProgress() override; float getTaskDuration() override; private: Ref fb; std::atomic taskDuration{0.f}; std::atomic finished; std::thread thread; }; // Inlined definitions ////////////////////////////////////////////////////// inline MultiDeviceRenderTask::MultiDeviceRenderTask( MultiDeviceFrameBuffer *fb, std::function fcn) : fb(fb), finished(false) { thread = std::thread([this, fcn]() { taskDuration = fcn(); finished = true; }); } inline MultiDeviceRenderTask::~MultiDeviceRenderTask() { if (thread.joinable()) { thread.join(); } } inline bool MultiDeviceRenderTask::isFinished(OSPSyncEvent event) { return finished == true || fb->rowmajorFb->getLatestCompleteEvent() >= event; } inline void MultiDeviceRenderTask::wait(OSPSyncEvent event) { if (event == OSP_TASK_FINISHED) { while (!finished) { std::this_thread::yield(); } } else { // the rowmajorFb tracks the same events as the subdevices, so we can wait // on it fb->rowmajorFb->waitForEvent(event); } } inline void MultiDeviceRenderTask::cancel() { for (size_t i = 0; i < fb->objects.size(); ++i) { FrameBuffer *fbi = (FrameBuffer *)fb->objects[i]; fbi->cancelFrame(); } } inline float MultiDeviceRenderTask::getProgress() { // The frame is done when all the subdevices are done, so the total progress // works out to be the average float progress = 0.0; for (size_t i = 0; i < fb->objects.size(); ++i) { FrameBuffer *fbi = (FrameBuffer *)fb->objects[i]; progress += fbi->getCurrentProgress(); } return progress / fb->objects.size(); } inline float MultiDeviceRenderTask::getTaskDuration() { return taskDuration.load(); } } // namespace api } // namespace ospray RenderKit-ospray-f2a61c2/modules/pluggableGeometryExample/000077500000000000000000000000001456566705700240115ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/pluggableGeometryExample/CMakeLists.txt000066400000000000000000000014361456566705700265550ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # Define an option to enable/disable this module. # # Though not actually required we guard each module 'moduleName' with # a OSPRAY_MODULE_MODULENAME flag that enables/disables its building. # cmake_dependent_option( OSPRAY_MODULE_BILINEAR_PATCH "Build pluggable geometry example module (a Bilinear Patch)" OFF OSPRAY_MODULE_CPU OFF ) if (NOT OSPRAY_MODULE_BILINEAR_PATCH) return() endif() # build the actual new ospray geometry type. since this plug in # directly into the ospray core, we'll put it into a # '/ospray' subdirectory. # # This subdirectory will eventually build the # libospray_module_.so library that defiens the actual # core geometry type. # add_subdirectory(ospray) RenderKit-ospray-f2a61c2/modules/pluggableGeometryExample/README.md000066400000000000000000000033211456566705700252670ustar00rootroot00000000000000PluggableGeometryExample: Module that demonstrates how to use the Module Concept to extend OSPRay with a new geometry type ========================================================================================================================== This module serves as a simple example of 1) how to define a new ospray geometry type and 'plug' this into ospray. In particular, how this geometry can use its "commit()" method to query data the user has added to it. 2) how to use embree and ispc to implement this geometry type's intersect() and postIntersect() functoins 3) how to do this through a 'module' that is dynamically loadable; and 4) how to use this module - and geometry - from within your own applications Using this example you should be able to write your own modules, with your own geometry types. For the purpose of this geometry we have chosen a intentionally very simple type of geometry - a bilinear patch. Notes: - Names matter. E.g., for ospray to find the module "myModuleName" the module _has_ to build a library of name libospray_module_myModuleName.so. Similarly, a module that wants to define a new geometry type "MyGeometry" _has_ to have a OSPRAY_REGISTER_GEOMETRY(WhatEverYouCallItInYourImplementation,MyGeometry) macro invocation in one of its cpp files. - This example only demonstrates how to write a _geometry_ type. It is similarly possible to write new renderers, new camera types, new volume types, etc. Running the Example =================== Build OSPRay (make sure that OSPRAY_MODULE_BILINEAR_PATCH is on!), then in your build directory, do a ./ospExampleViewer --sg:module bilinear_patches ../modules/pluggableGeometryExample/examples/shadows.patches --renderer pt RenderKit-ospray-f2a61c2/modules/pluggableGeometryExample/examples/000077500000000000000000000000001456566705700256275ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/pluggableGeometryExample/examples/shadows.patches000066400000000000000000000003411456566705700306460ustar00rootroot00000000000000# a sample file of patches. any line that does not contain three # floats is ignored, and any set of four successive 3-float lines # form one bi-linear patch -1 -1 0 2 -1 0 -1 2 0 2 2 .1 0 0 -.02 1 0 -.02 0 1 -.02 1 1 -.1 RenderKit-ospray-f2a61c2/modules/pluggableGeometryExample/examples/test1.patches000066400000000000000000000003561456566705700302440ustar00rootroot00000000000000# a sample file of patches. any line that does not contain three # floats is ignored, and any set of four successive 3-float lines # form one bi-linear patch 0 0 0 1 0 0 0 0 .1 1 1 .1 2 2 2 2 2 3 2 3 2 2 3 3 2 0 1 2 1 0 3 1 1 3 0 0 RenderKit-ospray-f2a61c2/modules/pluggableGeometryExample/ospray/000077500000000000000000000000001456566705700253265ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/pluggableGeometryExample/ospray/CMakeLists.txt000066400000000000000000000041751456566705700300750ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # this subdirectory builds the actual ospray plugin into a library # "libospray_module_.so". # # This shared library can depend on libospray, but should _not_ assume # that it is living in the same address space as the application: When # running in MPI mode ospray will, upon encountering the # ospLoadModule(""), actually load and use this library on # every worker node (which will typically not run the application). As # such, the library should _not_ "commuincate" with the application # through global variables or globally defined functions, and instead # communicate solely through the ospNewGeometry(...), ospSet...(), # ospCommit(...) etc functionality provided by ospray. # build the actual shared library that defines the geometry. # # Note the name is important: In order for ospray to properly find and # initialize a module referenced by a call to # "ospLoadModule() this module _has_ to # # a) be called libospray_module_.so, and # b) contain a (extern C linkage) initialization routine named # OSPError ospray_module_init_(int16_t versionMajor, # int16_t versionMinor, int16_t versionPatch) # add_library(ospray_module_bilinear_patches SHARED) include_directories_ispc(${RKCOMMON_INCLUDE_DIRS}) # Required definitions for ISPC hybrid code for CPU add_definitions_ispc( -DOSPRAY_BEGIN_ISPC_NAMESPACE= -DOSPRAY_END_ISPC_NAMESPACE= -DSYCL_EXTERNAL= ) ispc_target_add_sources(ospray_module_bilinear_patches # the cpp file that contains all the plugin code - parsing # parameters in ospCommit(), creating and registering the object, # building accel structures, etc geometry/BilinearPatches.cpp # the ispc file that contains the plugins for all vector code - ie, # for ray-primitive intersection and 'postIntersect' (reporting info # on a previously computed ray-prim intersection) geometry/BilinearPatches.ispc # and finally, the module init code (not doing much, but must be there) moduleInit.cpp ) target_link_libraries(ospray_module_bilinear_patches PUBLIC ospray_module_cpu) RenderKit-ospray-f2a61c2/modules/pluggableGeometryExample/ospray/geometry/000077500000000000000000000000001456566705700271615ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/modules/pluggableGeometryExample/ospray/geometry/BilinearPatches.cpp000066400000000000000000000035011456566705700327210ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "BilinearPatches.h" // 'export'ed functions from the ispc file: #include "geometry/BilinearPatches_ispc.h" // ospray core: #include // _everything_ in the ospray core universe should _always_ be in the // 'ospray' namespace. namespace ospray { // though not required, it is good practice to put any module into // its own namespace (isnide of ospray:: ). Unlike for the naming of // library and init function, the naming for this namespace doesn't // particularlly matter. E.g., 'bilinearPatch', 'module_blp', // 'bilinar_patch' etc would all work equally well. namespace blp { BilinearPatches::BilinearPatches(api::ISPCDevice &device) : AddStructShared(device.getIspcrtContext(), device, FFG_NONE) { getSh()->super.postIntersect = ispc::BilinearPatches_postIntersect_addr(); getSh()->super.intersect = ispc::BilinearPatches_intersect_addr(); } // commit - this is the function that parses all the parameters // that the app has proivded for this geometry. In this simple // example we're looking for a single parameter named 'patches', // which is supposed to contain a data array of all the patches' // control points. void BilinearPatches::commit() { patchesData = getParamDataT("vertices", true); if (!patchesData || !patchesData->compact()) throw std::runtime_error("BilinearPatches needs compact 'vertices' data!"); createEmbreeUserGeometry((RTCBoundsFunction)&ispc::BilinearPatches_bounds); getSh()->patchArray = (ispc::Patch *)patchesData->data(); getSh()->super.numPrimitives = numPrimitives(); postCreationInfo(patchesData->size()); } size_t BilinearPatches::numPrimitives() const { return patchesData->size() * sizeOf(patchesData->type) / sizeof(ispc::Patch); } } // namespace blp } // namespace ospray RenderKit-ospray-f2a61c2/modules/pluggableGeometryExample/ospray/geometry/BilinearPatches.h000066400000000000000000000054021456566705700323700ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray/geometry/BilinearPatches.h Defines a new ospray // geometry type (of name 'bilinear_patches'). Input to the geometry is // a single data array (named 'patches') that consists of for vec3fs // per patch. // ospcomon: vec3f, box3f, etcpp - generic helper stuff #include "rkcommon/math/box.h" #include "rkcommon/math/vec.h" // ospray: everything that's related to the ospray ray tracing core #include "geometry/Geometry.h" // ispc shared: header containing structures shared with ispc #include "BilinearPatchesShared.h" // _everything_ in the ospray core universe should _always_ be in the // 'ospray' namespace. namespace ospray { // though not required, it is good practice to put any module into // its own namespace (isnide of ospray:: ). Unlike for the naming of // library and init function, the naming for this namespace doesn't // particularlly matter. E.g., 'bilinearPatch', 'module_blp', // 'bilinar_patch' etc would all work equally well. namespace blp { // import rkcommon component - vec3f etc using namespace rkcommon; // a geometry type that implements (a set of) bi-linear // patches. This implements a new ospray geometry, and as such has // to // a) derive from ospray::Geometry // b) implement a 'commit()' message that parses the // parameters/data arrays that the app has specified as inputs // c) create an actual ospray geometry instance with the // proper intersect() and postIntersect() functions. // Note that how this class is called does not particularly matter; // all that matters is under which name it is registered in the cpp // file (see comments on OSPRAY_REGISTER_GEOMETRY) struct BilinearPatches : public AddStructShared { // data layout of a single patch. note we do not actually use // this class anywhere on the c++ side of this example, it is // only for illustrative purposes. The input data should come // as a data array of N such patches (we compute N // automatically based on the size of this array) // // struct Patch // { // vec3f controlPoint[2][2]; // }; BilinearPatches(api::ISPCDevice &); virtual ~BilinearPatches() override = default; // the commit() message that gets called upon the app calling // "ospCommit()" virtual void commit() override; virtual size_t numPrimitives() const override; protected: // the input data array. the data array contains a list of // patches, each of which consists of four vec3fs. Note in this // example we do not particularly care about whether this comes // as a plain array of floats (with 12 floats per patch), or as // a array of vec3fs. Ref> patchesData; }; } // namespace blp } // namespace ospray RenderKit-ospray-f2a61c2/modules/pluggableGeometryExample/ospray/geometry/BilinearPatches.ispc000066400000000000000000000144501456566705700331020ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "common/Ray.ih" #include "geometry/Geometry.ih" #include "rkcommon/math/LinearSpace.ih" #include "rkcommon/math/box.ih" #include "rkcommon/math/vec.ih" // c++ shared #include "BilinearPatchesShared.h" void BilinearPatches_postIntersect(const Geometry *uniform geometry, varying DifferentialGeometry &dg, const varying Ray &ray, uniform int64 flags) { const BilinearPatches *uniform self = (const BilinearPatches *uniform)geometry; dg.Ng = dg.Ns = normalize(ray.Ng); } // to be able to have embree build a data structure over us we have // to be able to tell it the bounding box for each primitimve. this // is the callback embree calls for querying the (uniform) bounding // box for a single given primitmive 'primID' export void BilinearPatches_bounds( const RTCBoundsFunctionArguments *uniform args) { uniform BilinearPatches *uniform self = (uniform BilinearPatches * uniform) args->geometryUserPtr; uniform int primID = args->primID; Patch *uniform patch = self->patchArray + primID; box3fa *uniform out = (box3fa * uniform) args->bounds_o; *out = box_extend(box_extend(box_extend(box_extend(make_box3fa_empty(), make_vec3f(patch->v00)), make_vec3f(patch->v01)), make_vec3f(patch->v10)), make_vec3f(patch->v11)); } bool recursiveBisection(varying Ray &ray, const uniform bool isOcclusionTest, const varying LinearSpace3f &frame, const uniform vec3f p00, const uniform vec3f p01, const uniform vec3f p10, const uniform vec3f p11, const uniform float u0, const uniform float u1, const uniform float v0, const uniform float v1, uniform int recursionsLeft) { // compute signs to x plane const float x0 = dot(p00 - ray.org, frame.vx); const float x1 = dot(p01 - ray.org, frame.vx); const float x2 = dot(p10 - ray.org, frame.vx); const float x3 = dot(p11 - ray.org, frame.vx); const float min_x = min(min(x0, x1), min(x2, x3)); if (min_x > 0.f) return false; const float max_x = max(max(x0, x1), max(x2, x3)); if (max_x < 0.f) return false; // compute signs to y plane const float y0 = dot(p00 - ray.org, frame.vy); const float y1 = dot(p01 - ray.org, frame.vy); const float y2 = dot(p10 - ray.org, frame.vy); const float y3 = dot(p11 - ray.org, frame.vy); const float min_y = min(min(y0, y1), min(y2, y3)); if (min_y > 0.f) return false; const float max_y = max(max(y0, y1), max(y2, y3)); if (max_y < 0.f) return false; // distance test const float t0 = dot(p00 - ray.org, frame.vz); const float t1 = dot(p01 - ray.org, frame.vz); const float t2 = dot(p10 - ray.org, frame.vz); const float t3 = dot(p11 - ray.org, frame.vz); // const float min_t = min(min(t0,t1),min(t2,t3)); // if (min_t > 0.f) return false; const float max_t = max(max(t0, t1), max(t2, t3)); if (max_t < 0.f) return false; const uniform float uc = 0.5f * (u0 + u1); const uniform float vc = 0.5f * (v0 + v1); if (recursionsLeft == 0) { const float t = 0.25 * (t0 + t1 + t2 + t3); if (t <= ray.t0 || t >= ray.t) return false; if (!isOcclusionTest) { ray.t = t; ray.u = uc; ray.v = vc; const vec3f pu0 = p00 + ray.u * (p01 - p00); const vec3f pu1 = p10 + ray.u * (p11 - p10); const vec3f pv0 = p00 + ray.v * (p10 - p00); const vec3f pv1 = p01 + ray.v * (p11 - p01); ray.Ng = cross(pu1 - pu0, pv1 - pv0); } return true; } else { const uniform vec3f p0c = 0.5f * (p01 + p00); const uniform vec3f p1c = 0.5f * (p11 + p10); const uniform vec3f pc0 = 0.5f * (p10 + p00); const uniform vec3f pc1 = 0.5f * (p11 + p01); const uniform vec3f pcc = 0.25f * (p00 + p01 + p10 + p11); bool hit = false; hit |= recursiveBisection(ray, isOcclusionTest, frame, p00, p0c, pc0, pcc, u0, uc, v0, vc, recursionsLeft - 1); hit |= recursiveBisection(ray, isOcclusionTest, frame, pc0, pcc, p10, p1c, u0, uc, vc, v1, recursionsLeft - 1); hit |= recursiveBisection(ray, isOcclusionTest, frame, p0c, p01, pcc, pc1, uc, u1, v0, vc, recursionsLeft - 1); hit |= recursiveBisection(ray, isOcclusionTest, frame, pcc, pc1, p1c, p11, uc, u1, vc, v1, recursionsLeft - 1); return hit; } } // this is the function callback the embree calls to compute a single // ray-primitive intersection. For sake of simplicity we'll use a very, // very simple recursive test here - this is neither fast nor elegant, // but does show that you can do mere arbitrary stuff in a ISPC kernel, // including 'true' recursion. void BilinearPatches_intersect_kernel( const RTCIntersectFunctionNArguments *uniform args, const uniform bool isOcclusionTest) { // make sure to set the mask if (!args->valid[programIndex]) return; uniform BilinearPatches *uniform self = (uniform BilinearPatches * uniform) args->geometryUserPtr; uniform unsigned int primID = args->primID; // this assumes that the args->rayhit is actually a pointer toa varying ray! varying Ray *uniform ray = (varying Ray * uniform) args->rayhit; Patch *uniform patch = self->patchArray + primID; // create a simple coordinate system with x and y directions // orthogonal to the ray const LinearSpace3f coordSys = frame(ray->dir); bool hit = recursiveBisection(*ray, isOcclusionTest, coordSys, patch->v00, patch->v01, patch->v10, patch->v11, 0.f, 1.f, 0.f, 1.f, /* number of bisections */ 10); if (hit) { if (isOcclusionTest) { ray->t = neg_inf; } else { ray->primID = primID; ray->geomID = args->geomID; ray->instID = args->context->instID[0]; } } } export void *uniform BilinearPatches_intersect_addr() { return BilinearPatches_intersect_kernel; } export void *uniform BilinearPatches_postIntersect_addr() { return BilinearPatches_postIntersect; } RenderKit-ospray-f2a61c2/modules/pluggableGeometryExample/ospray/geometry/BilinearPatchesShared.h000066400000000000000000000013511456566705700335160ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "geometry/GeometryShared.h" #ifdef __cplusplus namespace ispc { #endif // __cplusplus // input data for a single patch struct Patch { vec3f v00, v01, v10, v11; }; struct BilinearPatches { // inherit from "Geometry" class: since ISPC doesn't support // inheritance we simply put the "parent" class as the first // member; this way any typecast to the parent class will get the // right members (including 'virtual' function pointers, etc) Geometry super; size_t numPatches; Patch *patchArray; #ifdef __cplusplus BilinearPatches() : numPatches(0), patchArray(nullptr) {} }; } // namespace ispc #else }; #endif // __cplusplus RenderKit-ospray-f2a61c2/modules/pluggableGeometryExample/ospray/moduleInit.cpp000066400000000000000000000045471456566705700301550ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 /*! \file ospray/moduleInit \brief Defines the module initialization callback */ #include "geometry/BilinearPatches.h" #include "ospray/version.h" /*! _everything_ in the ospray core universe should _always_ be in the 'ospray' namespace. */ namespace ospray { /*! though not required, it is good practice to put any module into its own namespace (isnide of ospray:: ). Unlike for the naming of library and init function, the naming for this namespace doesn't particularlly matter. E.g., 'bilinearPatch', 'module_blp', 'bilinar_patch' etc would all work equally well. */ namespace blp { /*! the actual module initialization function. This function gets called exactly once, when the module gets first loaded through 'ospLoadModule'. Notes: a) this function does _not_ get called if the application directly links to libospray_module_ (which it shouldn't!). Modules should _always_ be loaded through ospLoadModule. b) it is _not_ valid for the module to do ospray _api_ calls inside such an intiailzatoin function. Ie, you can _not_ do a ospLoadModule("anotherModule") from within this function (but you could, of course, have this module dynamically link to the other one, and call its init function) c) in order for ospray to properly resolve that symbol, it _has_ to have extern C linkage, and it _has_ to correspond to name of the module and shared library containing this module (see comments regarding library name in CMakeLists.txt) */ extern "C" OSPError OSPRAY_DLLEXPORT ospray_module_init_bilinear_patches( int16_t versionMajor, int16_t versionMinor, int16_t /*versionPatch*/) { auto status = moduleVersionCheck(versionMajor, versionMinor); if (status == OSP_NO_ERROR) { /*! maybe one of the most important parts of this example: this function 'registers' the BilinearPatches class under the ospray geometry type name of 'bilinear_patches'. It is _this_ name that one can now (assuming the module has been loaded with ospLoadModule(), of course) create geometries with; i.e., OSPGeometry geom = ospNewGeometry("bilinear_patches") ; */ Geometry::registerType("bilinear_patches"); } return status; } } // namespace blp } // namespace ospray RenderKit-ospray-f2a61c2/ospray/000077500000000000000000000000001456566705700166645ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/ospray/CMakeLists.txt000066400000000000000000000050361456566705700214300ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # ------------------------------------------------------- # Setup ospray include directories and source files # ------------------------------------------------------- set(OSPRAY_RESOURCE ${CMAKE_CURRENT_SOURCE_DIR}/ospray.rc) set(OSPRAY_RESOURCE ${OSPRAY_RESOURCE} PARENT_SCOPE) option(OSPRAY_ENABLE_PROFILING "Enable performance tracing" OFF ) set(OSPRAY_SOURCES ${OSPRAY_RESOURCE} api/API.cpp api/Device.cpp api/ospray_util_impl.cpp api/ospray_cpp_defs.cpp common/OSPCommon.cpp common/Managed.cpp fb/ImageOp.cpp include/ospray/ospray.h include/ospray/ospray_util.h include/ospray/OSPEnums.h include/ospray/ospray_cpp.h include/ospray/ospray_cpp/Camera.h include/ospray/ospray_cpp/Data.h include/ospray/ospray_cpp/FrameBuffer.h include/ospray/ospray_cpp/Geometry.h include/ospray/ospray_cpp/Light.h include/ospray/ospray_cpp/ManagedObject.h include/ospray/ospray_cpp/Material.h include/ospray/ospray_cpp/ImageOperation.h include/ospray/ospray_cpp/Renderer.h include/ospray/ospray_cpp/Texture.h include/ospray/ospray_cpp/TransferFunction.h include/ospray/ospray_cpp/Volume.h include/ospray/ospray_cpp/World.h ) # ------------------------------------------------------- # Install SDK headers # ------------------------------------------------------- get_subdirectories(SUBDIRS ${CMAKE_CURRENT_LIST_DIR}) foreach(dir ${SUBDIRS}) if (NOT "${dir}" STREQUAL include) install(DIRECTORY ${dir} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ospray/SDK COMPONENT devel FILES_MATCHING PATTERN *.h ) endif() endforeach() ############################################################## # Build the ospray library ############################################################## add_library(ospray SHARED ${OSPRAY_SOURCES}) target_link_libraries(ospray PUBLIC $) ospray_install_library(ospray lib ON) target_include_directories(ospray PUBLIC $ $ $ $ ) if (OSPRAY_ENABLE_PROFILING) target_compile_definitions(ospray PUBLIC -DRKCOMMON_ENABLE_PROFILING ) endif() ############################################################## # Configure find_package files ############################################################## include(${CMAKE_SOURCE_DIR}/cmake/ospray_cmake_config.cmake) RenderKit-ospray-f2a61c2/ospray/api/000077500000000000000000000000001456566705700174355ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/ospray/api/API.cpp000066400000000000000000000515551456566705700205650ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "rkcommon/os/library.h" #include "rkcommon/utility/OnScopeExit.h" #include "rkcommon/utility/StringManip.h" #include "rkcommon/utility/getEnvVar.h" // ospray #include "Device.h" #include "common/OSPCommon.h" #include "include/ospray/ospray.h" #ifdef _WIN32 #include // for getpid #endif using ospray::api::currentDevice; using ospray::api::Device; using ospray::api::deviceIsSet; /*! \file api.cpp implements the public ospray api functions by routing them to a respective \ref device */ #define THROW_IF_NULL(obj, name) \ if (obj == nullptr) \ throw std::runtime_error(std::string("null ") + name \ + std::string(" provided to ") + __FUNCTION__) // convenience macros for repeated use of the above #define THROW_IF_NULL_OBJECT(obj) THROW_IF_NULL(obj, "handle") #define THROW_IF_NULL_STRING(str) THROW_IF_NULL(str, "string") #define ASSERT_DEVICE() \ if (!deviceIsSet()) \ throw std::runtime_error( \ "no valid OSPRay device while calling an API function, likely" \ " either before calling ospInit() / ospNewDevice() plus ospSetCurrentDevice()," \ " or after calling ospShutdown() / ospDeviceRelease(); pid: " \ + std::to_string(getpid())) #define OSPRAY_CATCH_BEGIN \ try { \ auto *fcn_name_ = __PRETTY_FUNCTION__; \ rkcommon::utility::OnScopeExit guard([&]() { postTraceMsg(fcn_name_); }); #define OSPRAY_CATCH_END(a) \ } \ catch (const std::bad_alloc &) \ { \ handleError(OSP_OUT_OF_MEMORY, "OSPRay was unable to allocate memory"); \ return a; \ } \ catch (const std::exception &e) \ { \ handleError(OSP_UNKNOWN_ERROR, e.what()); \ return a; \ } \ catch (...) \ { \ handleError(OSP_UNKNOWN_ERROR, "an unrecognized exception was caught"); \ return a; \ } using namespace ospray; static inline void loadModulesFromEnvironmentVar() { auto OSPRAY_LOAD_MODULES = utility::getEnvVar("OSPRAY_LOAD_MODULES"); if (OSPRAY_LOAD_MODULES) { auto module_names = utility::split(OSPRAY_LOAD_MODULES.value(), ','); for (auto &name : module_names) loadLocalModule(name); } } /////////////////////////////////////////////////////////////////////////////// // OSPRay Initialization ////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// extern "C" OSPError ospInit(int *_ac, const char **_av) OSPRAY_CATCH_BEGIN { auto ¤tDevice = Device::current; if (currentDevice) { throw std::runtime_error("device already exists [ospInit() called twice?]"); } loadModulesFromEnvironmentVar(); if (_ac && _av) { for (int i = 1; i < *_ac;) { std::string av(_av[i]); if (rkcommon::utility::beginsWith(av, "--osp:load-modules")) { std::string modules = getArgString(av); if (modules == "") { throw std::runtime_error( "Invalid module name(s) provided to --osp:load-modules. Must be " "formatted as [,,...]"); } std::vector moduleList = rkcommon::utility::split(modules, ','); for (std::string &moduleName : moduleList) { loadLocalModule(moduleName); } removeArgs(*_ac, _av, i, 1); } else if (rkcommon::utility::beginsWith(av, "--osp:device=")) { // ALOK: explicitly checking with the equals sign so this does not get // clobbered by --osp:device-param std::string deviceName = getArgString(av); try { currentDevice = Device::createDevice(deviceName.c_str()); } catch (const std::runtime_error &) { throw std::runtime_error("Failed to create device of type '" + deviceName + "'! Perhaps you spelled the " "device name wrong or didn't link the " "library which defines the device?"); } removeArgs(*_ac, _av, i, 1); } else { // Ignore other arguments ++i; } } } // no device created on cmd line, yet, so default to ISPCDevice if (!deviceIsSet()) { auto OSPRAY_DEVICE = utility::getEnvVar("OSPRAY_DEVICE"); if (OSPRAY_DEVICE) { const auto &device_name = OSPRAY_DEVICE.value(); currentDevice = Device::createDevice(device_name.c_str()); } else { ospLoadModule("cpu"); currentDevice = Device::createDevice("cpu"); } } ospray::initFromCommandLine(_ac, &_av); currentDevice->commit(); currentDevice->refDec(); return OSP_NO_ERROR; } OSPRAY_CATCH_END(OSP_INVALID_OPERATION) extern "C" int64_t ospDeviceGetProperty( OSPDevice _device, OSPDeviceProperty _deviceProperty) OSPRAY_CATCH_BEGIN { auto *device = (Device *)_device; return device->getProperty(_deviceProperty); } OSPRAY_CATCH_END(0) extern "C" void ospShutdown() OSPRAY_CATCH_BEGIN { Device::current = nullptr; LibraryRepository::cleanupInstance(); } OSPRAY_CATCH_END() extern "C" OSPDevice ospNewDevice(const char *deviceType) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_STRING(deviceType); return (OSPDevice)Device::createDevice(deviceType); } OSPRAY_CATCH_END(nullptr) extern "C" void ospSetCurrentDevice(OSPDevice _device) OSPRAY_CATCH_BEGIN { auto *device = (Device *)_device; if ((device) && (!device->isCommitted())) { throw std::runtime_error("You must commit the device before using it!"); } Device::current = device; } OSPRAY_CATCH_END() extern "C" OSPDevice ospGetCurrentDevice() OSPRAY_CATCH_BEGIN { auto *ptr = Device::current.ptr; if (ptr) ptr->refInc(); return (OSPDevice)ptr; } OSPRAY_CATCH_END(nullptr) extern "C" void ospDeviceSetParam(OSPDevice _object, const char *id, OSPDataType type, const void *mem) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(_object); THROW_IF_NULL_STRING(id); Device *object = (Device *)_object; switch (type) { case OSP_STRING: object->setParam(id, std::string((const char *)mem)); break; case OSP_INT: object->setParam(id, *(int *)mem); break; case OSP_UINT: object->setParam(id, *(uint32_t *)mem); break; case OSP_BOOL: object->setParam(id, *(bool *)mem); break; case OSP_VOID_PTR: object->setParam(id, *(void **)&mem); break; default: throw std::runtime_error("parameter type not handled for OSPDevice!"); }; } OSPRAY_CATCH_END() extern "C" void ospDeviceRemoveParam( OSPDevice _object, const char *id) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(_object); THROW_IF_NULL_STRING(id); Device *object = (Device *)_object; object->removeParam(id); } OSPRAY_CATCH_END() extern "C" void ospDeviceSetStatusCallback(OSPDevice _object, OSPStatusCallback callback, void *userData) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(_object); auto *device = (Device *)_object; if (callback == nullptr) { device->msg_fcn = [](void *, const char *) {}; device->statusUserData = nullptr; } else { device->msg_fcn = callback; device->statusUserData = userData; } } OSPRAY_CATCH_END() extern "C" void ospDeviceSetErrorCallback(OSPDevice _object, OSPErrorCallback callback, void *userData) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(_object); auto *device = (Device *)_object; if (callback == nullptr) { device->error_fcn = [](void *, OSPError, const char *) {}; device->errorUserData = nullptr; } else { device->error_fcn = callback; device->errorUserData = userData; } } OSPRAY_CATCH_END() extern "C" OSPError ospDeviceGetLastErrorCode( OSPDevice _object) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(_object); auto *device = (Device *)_object; return device->lastErrorCode; } OSPRAY_CATCH_END(OSP_NO_ERROR) extern "C" const char *ospDeviceGetLastErrorMsg( OSPDevice _object) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(_object); auto *device = (Device *)_object; return device->lastErrorMsg.c_str(); } OSPRAY_CATCH_END(nullptr) extern "C" void ospDeviceCommit(OSPDevice _object) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(_object); auto *object = (Device *)_object; object->commit(); } OSPRAY_CATCH_END() extern "C" void ospDeviceRelease(OSPDevice _object) OSPRAY_CATCH_BEGIN { auto *object = (Device *)_object; if (!object) return; object->refDec(); } OSPRAY_CATCH_END() extern "C" void ospDeviceRetain(OSPDevice _object) OSPRAY_CATCH_BEGIN { auto *object = (Device *)_object; if (!object) return; object->refInc(); } OSPRAY_CATCH_END() extern "C" OSPError ospLoadModule(const char *module_name) OSPRAY_CATCH_BEGIN { if (deviceIsSet()) { return (OSPError)currentDevice().loadModule(module_name); } else { return loadLocalModule(module_name); } } OSPRAY_CATCH_END(OSP_UNKNOWN_ERROR) /////////////////////////////////////////////////////////////////////////////// // OSPRay Data Arrays ///////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// extern "C" OSPData ospNewSharedData(const void *sharedData, OSPDataType type, uint64_t numItems1, int64_t byteStride1, uint64_t numItems2, int64_t byteStride2, uint64_t numItems3, int64_t byteStride3, OSPDeleterCallback freeFunction, const void *userPtr) OSPRAY_CATCH_BEGIN { ASSERT_DEVICE(); OSPData data = currentDevice().newSharedData(sharedData, type, ospray::vec3ul(numItems1, numItems2, numItems3), ospray::vec3l(byteStride1, byteStride2, byteStride3), freeFunction, userPtr); return data; } OSPRAY_CATCH_END(nullptr) extern "C" OSPData ospNewData(OSPDataType type, uint64_t numItems1, uint64_t numItems2, uint64_t numItems3) OSPRAY_CATCH_BEGIN { ASSERT_DEVICE(); OSPData data = currentDevice().newData( type, ospray::vec3ul(numItems1, numItems2, numItems3)); return data; } OSPRAY_CATCH_END(nullptr) extern "C" void ospCopyData(const OSPData source, OSPData destination, uint64_t dstIdx1, uint64_t dstIdx2, uint64_t dstIdx3) OSPRAY_CATCH_BEGIN { ASSERT_DEVICE(); currentDevice().copyData( source, destination, ospray::vec3ul(dstIdx1, dstIdx2, dstIdx3)); } OSPRAY_CATCH_END() /////////////////////////////////////////////////////////////////////////////// // Renderable Objects ///////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// extern "C" OSPLight ospNewLight(const char *_type) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_STRING(_type); ASSERT_DEVICE(); OSPLight light = currentDevice().newLight(_type); return light; } OSPRAY_CATCH_END(nullptr) extern "C" OSPCamera ospNewCamera(const char *_type) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_STRING(_type); ASSERT_DEVICE(); OSPCamera camera = currentDevice().newCamera(_type); return camera; } OSPRAY_CATCH_END(nullptr) extern "C" OSPGeometry ospNewGeometry(const char *_type) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_STRING(_type); ASSERT_DEVICE(); OSPGeometry geometry = currentDevice().newGeometry(_type); return geometry; } OSPRAY_CATCH_END(nullptr) extern "C" OSPVolume ospNewVolume(const char *_type) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_STRING(_type); ASSERT_DEVICE(); OSPVolume volume = currentDevice().newVolume(_type); return volume; } OSPRAY_CATCH_END(nullptr) extern "C" OSPGeometricModel ospNewGeometricModel( OSPGeometry geom) OSPRAY_CATCH_BEGIN { ASSERT_DEVICE(); OSPGeometricModel instance = currentDevice().newGeometricModel(geom); return instance; } OSPRAY_CATCH_END(nullptr) extern "C" OSPVolumetricModel ospNewVolumetricModel( OSPVolume volume) OSPRAY_CATCH_BEGIN { ASSERT_DEVICE(); OSPVolumetricModel instance = currentDevice().newVolumetricModel(volume); return instance; } OSPRAY_CATCH_END(nullptr) /////////////////////////////////////////////////////////////////////////////// // Model Meta-Data //////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// extern "C" OSPMaterial ospNewMaterial( const char *material_type) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_STRING(material_type); ASSERT_DEVICE(); auto material = currentDevice().newMaterial(material_type); return material; } OSPRAY_CATCH_END(nullptr) extern "C" OSPTransferFunction ospNewTransferFunction( const char *_type) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_STRING(_type); ASSERT_DEVICE(); auto transferFunction = currentDevice().newTransferFunction(_type); return transferFunction; } OSPRAY_CATCH_END(nullptr) extern "C" OSPTexture ospNewTexture(const char *_type) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_STRING(_type); ASSERT_DEVICE(); OSPTexture texture = currentDevice().newTexture(_type); return texture; } OSPRAY_CATCH_END(nullptr) /////////////////////////////////////////////////////////////////////////////// // Instancing ///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// extern "C" OSPGroup ospNewGroup() OSPRAY_CATCH_BEGIN { ASSERT_DEVICE(); return currentDevice().newGroup(); } OSPRAY_CATCH_END(nullptr) extern "C" OSPInstance ospNewInstance(OSPGroup group) OSPRAY_CATCH_BEGIN { ASSERT_DEVICE(); return currentDevice().newInstance(group); } OSPRAY_CATCH_END(nullptr) /////////////////////////////////////////////////////////////////////////////// // Top-level Worlds /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// extern "C" OSPWorld ospNewWorld() OSPRAY_CATCH_BEGIN { ASSERT_DEVICE(); return currentDevice().newWorld(); } OSPRAY_CATCH_END(nullptr) extern "C" OSPBounds ospGetBounds(OSPObject obj) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(obj); ASSERT_DEVICE(); box3f bounds = currentDevice().getBounds(obj); return (OSPBounds &)bounds; } OSPRAY_CATCH_END({}) /////////////////////////////////////////////////////////////////////////////// // Object + Parameter Lifetime Management ///////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// extern "C" void ospSetParam(OSPObject _object, const char *id, OSPDataType type, const void *mem) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(_object); THROW_IF_NULL_STRING(id); ASSERT_DEVICE(); currentDevice().setObjectParam(_object, id, type, mem); } OSPRAY_CATCH_END() extern "C" void ospRemoveParam( OSPObject _object, const char *id) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(_object); THROW_IF_NULL_STRING(id); ASSERT_DEVICE(); currentDevice().removeObjectParam(_object, id); } OSPRAY_CATCH_END() extern "C" void ospCommit(OSPObject _object) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(_object); ASSERT_DEVICE(); currentDevice().commit(_object); } OSPRAY_CATCH_END() extern "C" void ospRelease(OSPObject _object) OSPRAY_CATCH_BEGIN { if (!_object) return; ASSERT_DEVICE(); currentDevice().release(_object); } OSPRAY_CATCH_END() extern "C" void ospRetain(OSPObject _object) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(_object); ASSERT_DEVICE(); currentDevice().retain(_object); } OSPRAY_CATCH_END() /////////////////////////////////////////////////////////////////////////////// // FrameBuffer Manipulation /////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// extern "C" OSPFrameBuffer ospNewFrameBuffer(int size_x, int size_y, OSPFrameBufferFormat mode, uint32_t channels) OSPRAY_CATCH_BEGIN { ASSERT_DEVICE(); // remove OSP_FB_VARIANCE when OSP_FB_ACCUM is not present uint32_t ch = channels; if ((channels & OSP_FB_ACCUM) == 0) ch &= ~OSP_FB_VARIANCE; return currentDevice().frameBufferCreate(vec2i(size_x, size_y), mode, ch); } OSPRAY_CATCH_END(nullptr) extern "C" OSPImageOperation ospNewImageOperation( const char *_type) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_STRING(_type); ASSERT_DEVICE(); int L = strlen(_type); char *type = STACK_BUFFER(char, L + 1); for (int i = 0; i <= L; i++) { char c = _type[i]; if (c == '-' || c == ':') c = '_'; type[i] = c; } OSPImageOperation op = currentDevice().newImageOp(type); return op; } OSPRAY_CATCH_END(nullptr) extern "C" const void *ospMapFrameBuffer( OSPFrameBuffer fb, OSPFrameBufferChannel channel) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(fb); ASSERT_DEVICE(); return currentDevice().frameBufferMap(fb, channel); } OSPRAY_CATCH_END(nullptr) extern "C" void ospUnmapFrameBuffer( const void *mapped, OSPFrameBuffer fb) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(fb); THROW_IF_NULL(mapped, "pointer"); ASSERT_DEVICE(); currentDevice().frameBufferUnmap(mapped, fb); } OSPRAY_CATCH_END() extern "C" float ospGetVariance(OSPFrameBuffer fb) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(fb); ASSERT_DEVICE(); return currentDevice().getVariance(fb); } OSPRAY_CATCH_END(inf) extern "C" void ospResetAccumulation(OSPFrameBuffer fb) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(fb); ASSERT_DEVICE(); currentDevice().resetAccumulation(fb); } OSPRAY_CATCH_END() /////////////////////////////////////////////////////////////////////////////// // Frame Rendering //////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// extern "C" OSPRenderer ospNewRenderer(const char *_type) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_STRING(_type); ASSERT_DEVICE(); std::string type(_type); for (size_t i = 0; i < type.size(); i++) { if (type[i] == '-' || type[i] == ':') type[i] = '_'; } OSPRenderer renderer = currentDevice().newRenderer(type.c_str()); return renderer; } OSPRAY_CATCH_END(nullptr) extern "C" OSPFuture ospRenderFrame(OSPFrameBuffer fb, OSPRenderer renderer, OSPCamera camera, OSPWorld world) OSPRAY_CATCH_BEGIN { THROW_IF_NULL(fb, "framebuffer"); THROW_IF_NULL(renderer, "renderer"); THROW_IF_NULL(camera, "camera"); THROW_IF_NULL(world, "world"); ASSERT_DEVICE(); return currentDevice().renderFrame(fb, renderer, camera, world); } OSPRAY_CATCH_END(nullptr) extern "C" int ospIsReady(OSPFuture f, OSPSyncEvent event) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(f); ASSERT_DEVICE(); return currentDevice().isReady(f, event); } OSPRAY_CATCH_END(1) extern "C" void ospWait(OSPFuture f, OSPSyncEvent event) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(f); ASSERT_DEVICE(); if (event == OSP_NONE_FINISHED) return; currentDevice().wait(f, event); } OSPRAY_CATCH_END() extern "C" void ospCancel(OSPFuture f) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(f); ASSERT_DEVICE(); return currentDevice().cancel(f); } OSPRAY_CATCH_END() extern "C" float ospGetProgress(OSPFuture f) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(f); ASSERT_DEVICE(); return currentDevice().getProgress(f); } OSPRAY_CATCH_END(1.f) extern "C" float ospGetTaskDuration(OSPFuture f) OSPRAY_CATCH_BEGIN { THROW_IF_NULL_OBJECT(f); ASSERT_DEVICE(); return currentDevice().getTaskDuration(f); } OSPRAY_CATCH_END(0.f) extern "C" void ospPick(OSPPickResult *result, OSPFrameBuffer fb, OSPRenderer renderer, OSPCamera camera, OSPWorld world, float screenPos_x, float screenPos_y) OSPRAY_CATCH_BEGIN { THROW_IF_NULL(fb, "framebuffer"); THROW_IF_NULL(renderer, "renderer"); THROW_IF_NULL(camera, "camera"); THROW_IF_NULL(world, "world"); ASSERT_DEVICE(); if (!result) return; *result = currentDevice().pick( fb, renderer, camera, world, vec2f(screenPos_x, screenPos_y)); } OSPRAY_CATCH_END() RenderKit-ospray-f2a61c2/ospray/api/Device.cpp000066400000000000000000000135171456566705700213470ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // ospray #include "Device.h" #include "rkcommon/os/library.h" #include "rkcommon/tasking/tasking_system_init.h" #include "rkcommon/utility/getEnvVar.h" namespace ospray { namespace api { // Helper functions /////////////////////////////////////////////////////////// template static inline void installStatusMsgFunc(Device &device, OSTREAM_T &stream) { device.msg_fcn = [&](void *, const char *msg) { stream << msg; }; } template static inline void installErrorMsgFunc(Device &device, OSTREAM_T &stream) { device.error_fcn = [&](void *, OSPError e, const char *msg) { stream << "OSPRAY ERROR [" << e << "]: " << msg << std::endl; }; } // Device definitions ///////////////////////////////////////////////////////// Device::FactoryMap Device::dfcns; Device *Device::createInstance(const char *type) { FactoryFcn fcn = dfcns[type]; if (fcn) { auto *obj = fcn(); if (obj != nullptr) return obj; } throw std::runtime_error("Could not find Device of type: '" + std::string(type) + "'. Make sure you have the correct OSPRay libraries linked and initialized."); } memory::IntrusivePtr Device::current; uint32_t Device::logLevel = OSP_LOG_NONE; Device *Device::createDevice(const char *type) { // NOTE(jda) - If a user is manually creating the device (i.e. not using // ospInit() to do it), then we need to check if there's a // valid library for core ospray in our main symbol lookup // table. auto &repo = *LibraryRepository::getInstance(); if (!repo.libraryExists("ospray_module_cpu") && type == std::string("cpu")) repo.add(reinterpret_cast(&createDevice), "ospray_module_cpu", {OSPRAY_VERSION_MAJOR, OSPRAY_VERSION_MINOR, OSPRAY_VERSION_PATCH}); return createInstance(type); } void Device::commit() { auto OSPRAY_DEBUG = utility::getEnvVar("OSPRAY_DEBUG"); debugMode = OSPRAY_DEBUG.value_or(getParam("debug", false)); auto OSPRAY_WARN = utility::getEnvVar("OSPRAY_WARN_AS_ERROR"); warningsAreErrors = OSPRAY_WARN.value_or(getParam("warnAsError", false)); auto OSPRAY_TRACE_API = utility::getEnvVar("OSPRAY_TRACE_API"); bool traceAPI = OSPRAY_TRACE_API.value_or(getParam("traceApi", false)); if (traceAPI && !apiTraceEnabled) { auto streamPtr = std::make_shared("ospray_api_trace.txt"); trace_fcn = [=](const char *message) { auto &stream = *streamPtr; stream << message << std::endl; }; } else if (!traceAPI) { trace_fcn = [](const char *) {}; } apiTraceEnabled = traceAPI; logLevel = (OSPLogLevel)getParam("logLevel", OSP_LOG_NONE); auto logLevelStr = utility::getEnvVar("OSPRAY_LOG_LEVEL").value_or(""); logLevel = logLevelFromString(logLevelStr).value_or(logLevel); auto OSPRAY_NUM_THREADS = utility::getEnvVar("OSPRAY_NUM_THREADS"); numThreads = OSPRAY_NUM_THREADS.value_or(getParam("numThreads", -1)); auto OSPRAY_LOG_OUTPUT = utility::getEnvVar("OSPRAY_LOG_OUTPUT"); auto dst = OSPRAY_LOG_OUTPUT.value_or(getParam("logOutput", "")); if (dst == "cout") installStatusMsgFunc(*this, std::cout); else if (dst == "cerr") installStatusMsgFunc(*this, std::cerr); else if (dst == "none") msg_fcn = [](void *, const char *) {}; auto OSPRAY_ERROR_OUTPUT = utility::getEnvVar("OSPRAY_ERROR_OUTPUT"); dst = OSPRAY_ERROR_OUTPUT.value_or(getParam("errorOutput", "")); if (dst == "cout") installErrorMsgFunc(*this, std::cout); else if (dst == "cerr") installErrorMsgFunc(*this, std::cerr); else if (dst == "none") error_fcn = [](void *, OSPError, const char *) {}; if (debugMode) { logLevel = OSP_LOG_DEBUG; numThreads = 1; installStatusMsgFunc(*this, std::cout); installErrorMsgFunc(*this, std::cerr); } threadAffinity = getParam("setAffinity", AUTO_DETECT); auto OSPRAY_SET_AFFINITY = utility::getEnvVar("OSPRAY_SET_AFFINITY"); if (OSPRAY_SET_AFFINITY) threadAffinity = OSPRAY_SET_AFFINITY.value(); tasking::initTaskingSystem(numThreads); committed = true; } bool Device::isCommitted() { return committed; } bool deviceIsSet() { return Device::current.ptr != nullptr; } Device ¤tDevice() { return *Device::current; } std::string generateEmbreeDeviceCfg(const Device &device) { std::stringstream embreeConfig; if (device.debugMode) embreeConfig << " verbose=2"; if (device.threadAffinity == api::Device::AFFINITIZE) embreeConfig << ",set_affinity=1"; else if (device.threadAffinity == api::Device::DEAFFINITIZE) embreeConfig << ",set_affinity=0"; return embreeConfig.str(); } int64_t Device::getProperty(const OSPDeviceProperty prop) { /* documented properties */ switch (prop) { case OSP_DEVICE_VERSION: return 10000 * OSPRAY_VERSION_MAJOR + 100 * OSPRAY_VERSION_MINOR + OSPRAY_VERSION_PATCH; case OSP_DEVICE_VERSION_MAJOR: return OSPRAY_VERSION_MAJOR; case OSP_DEVICE_VERSION_MINOR: return OSPRAY_VERSION_MINOR; case OSP_DEVICE_VERSION_PATCH: return OSPRAY_VERSION_PATCH; case OSP_DEVICE_SO_VERSION: return OSPRAY_SOVERSION; default: handleError(OSP_INVALID_ARGUMENT, "unknown readable property"); return 0; } } utility::Optional Device::logLevelFromString(const std::string &str) { utility::Optional retval; if (str == "none") retval = OSP_LOG_NONE; else if (str == "debug") retval = OSP_LOG_DEBUG; else if (str == "info") retval = OSP_LOG_INFO; else if (str == "warning") retval = OSP_LOG_WARNING; else if (str == "error") retval = OSP_LOG_ERROR; return retval; } } // namespace api OSPTYPEFOR_DEFINITION(api::Device *); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/api/Device.h000066400000000000000000000145441456566705700210150ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/memory/IntrusivePtr.h" #include "rkcommon/utility/Optional.h" #include "rkcommon/utility/ParameterizedObject.h" // ospray #include "common/OSPCommon.h" #include "ospray/version.h" // std #include /*! \file device.h Defines the abstract base class for OSPRay "devices" that implement the OSPRay API */ namespace ospray { namespace api { /*! abstract base class of all 'devices' that implement the ospray API */ struct OSPRAY_CORE_INTERFACE Device : public memory::RefCountedObject, public utility::ParameterizedObject { template static void registerType(const char *type) { dfcns[type] = &allocate_device; } static Device *createInstance(const char *type); /*! singleton that points to currently active device */ static memory::IntrusivePtr current; Device() = default; virtual ~Device() override = default; static Device *createDevice(const char *type); /*! gets a device property */ virtual int64_t getProperty(const OSPDeviceProperty prop); ///////////////////////////////////////////////////////////////////////// // Main virtual interface to accepting API calls ///////////////////////////////////////////////////////////////////////// // Modules ////////////////////////////////////////////////////////////// virtual int loadModule(const char *name) = 0; // OSPRay Data Arrays /////////////////////////////////////////////////// virtual OSPData newSharedData(const void *sharedData, OSPDataType, const vec3ul &numItems, const vec3l &byteStride, OSPDeleterCallback, const void *userPtr) = 0; virtual OSPData newData(OSPDataType, const vec3ul &numItems) = 0; virtual void copyData(const OSPData source, OSPData destination, const vec3ul &destinationIndex) = 0; // Renderable Objects /////////////////////////////////////////////////// virtual OSPLight newLight(const char *type) = 0; virtual OSPCamera newCamera(const char *type) = 0; virtual OSPGeometry newGeometry(const char *type) = 0; virtual OSPVolume newVolume(const char *type) = 0; virtual OSPGeometricModel newGeometricModel(OSPGeometry geom) = 0; virtual OSPVolumetricModel newVolumetricModel(OSPVolume volume) = 0; // Model Meta-Data ////////////////////////////////////////////////////// virtual OSPMaterial newMaterial(const char *material_type) = 0; virtual OSPTransferFunction newTransferFunction(const char *type) = 0; virtual OSPTexture newTexture(const char *type) = 0; // Instancing /////////////////////////////////////////////////////////// virtual OSPGroup newGroup() = 0; virtual OSPInstance newInstance(OSPGroup group) = 0; // Top-level Worlds ///////////////////////////////////////////////////// virtual OSPWorld newWorld() = 0; virtual box3f getBounds(OSPObject) = 0; // Object + Parameter Lifetime Management /////////////////////////////// virtual void setObjectParam(OSPObject object, const char *name, OSPDataType type, const void *mem) = 0; virtual void removeObjectParam(OSPObject object, const char *name) = 0; virtual void commit(OSPObject object) = 0; virtual void release(OSPObject _obj) = 0; virtual void retain(OSPObject _obj) = 0; // FrameBuffer Manipulation ///////////////////////////////////////////// virtual OSPFrameBuffer frameBufferCreate(const vec2i &size, const OSPFrameBufferFormat mode, const uint32 channels) = 0; virtual OSPImageOperation newImageOp(const char *type) = 0; virtual const void *frameBufferMap( OSPFrameBuffer fb, const OSPFrameBufferChannel) = 0; virtual void frameBufferUnmap(const void *mapped, OSPFrameBuffer fb) = 0; virtual float getVariance(OSPFrameBuffer) = 0; virtual void resetAccumulation(OSPFrameBuffer _fb) = 0; // Frame Rendering ////////////////////////////////////////////////////// virtual OSPRenderer newRenderer(const char *type) = 0; virtual OSPFuture renderFrame( OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld) = 0; virtual int isReady(OSPFuture, OSPSyncEvent) = 0; virtual void wait(OSPFuture, OSPSyncEvent) = 0; virtual void cancel(OSPFuture) = 0; virtual float getProgress(OSPFuture) = 0; virtual float getTaskDuration(OSPFuture) = 0; // Return pointer to command queue that is goint to be used by external // post-processing kernels (e.g. OIDN) virtual void *getPostProcessingCommandQueuePtr() = 0; virtual OSPPickResult pick( OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld, const vec2f &) { NOT_IMPLEMENTED; } ///////////////////////////////////////////////////////////////////////// // Helper/other functions and data members ///////////////////////////////////////////////////////////////////////// virtual void commit(); bool isCommitted(); static utility::Optional logLevelFromString(const std::string &str); int numThreads{-1}; bool debugMode{false}; bool apiTraceEnabled{false}; enum OSP_THREAD_AFFINITY { DEAFFINITIZE = 0, AFFINITIZE = 1, AUTO_DETECT = 2 }; int threadAffinity{AUTO_DETECT}; // NOTE(jda) - Keep logLevel static because the device factory function // needs to have a valid value for the initial Device creation static uint32_t logLevel; bool warningsAreErrors{false}; std::function msg_fcn{ [](void *, const char *) {}}; void *statusUserData{nullptr}; std::function error_fcn{ [](void *, OSPError, const char *) {}}; void *errorUserData{nullptr}; std::function trace_fcn{[](const char *) {}}; OSPError lastErrorCode = OSP_NO_ERROR; std::string lastErrorMsg = "no error"; // no braced initializer for MSVC12 private: bool committed{false}; using FactoryFcn = Device *(*)(); using FactoryMap = std::map; static FactoryMap dfcns; template static Device *allocate_device() { return new D; } }; // Shorthand functions to query current API device // OSPRAY_CORE_INTERFACE bool deviceIsSet(); OSPRAY_CORE_INTERFACE Device ¤tDevice(); OSPRAY_CORE_INTERFACE std::string generateEmbreeDeviceCfg(const Device &device); } // namespace api OSPTYPEFOR_SPECIALIZATION(api::Device *, OSP_DEVICE); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/api/ospray_cpp_defs.cpp000066400000000000000000000016051456566705700233230ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "../common/OSPCommon.h" // ospray::cpp #include "ospray/ospray_cpp.h" namespace ospray { OSPTYPEFOR_DEFINITION(cpp::Camera); OSPTYPEFOR_DEFINITION(cpp::SharedData); OSPTYPEFOR_DEFINITION(cpp::CopiedData); OSPTYPEFOR_DEFINITION(cpp::FrameBuffer); OSPTYPEFOR_DEFINITION(cpp::Future); OSPTYPEFOR_DEFINITION(cpp::GeometricModel); OSPTYPEFOR_DEFINITION(cpp::Geometry); OSPTYPEFOR_DEFINITION(cpp::Group); OSPTYPEFOR_DEFINITION(cpp::ImageOperation); OSPTYPEFOR_DEFINITION(cpp::Instance); OSPTYPEFOR_DEFINITION(cpp::Light); OSPTYPEFOR_DEFINITION(cpp::Material); OSPTYPEFOR_DEFINITION(cpp::Renderer); OSPTYPEFOR_DEFINITION(cpp::Texture); OSPTYPEFOR_DEFINITION(cpp::TransferFunction); OSPTYPEFOR_DEFINITION(cpp::Volume); OSPTYPEFOR_DEFINITION(cpp::VolumetricModel); OSPTYPEFOR_DEFINITION(cpp::World); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/api/ospray_util_impl.cpp000066400000000000000000000110421456566705700235320ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ospray/ospray_cpp.h" #include "ospray/ospray_util.h" extern "C" { // OSPData helpers //////////////////////////////////////////////////////////// OSPData ospNewSharedData1D( const void *sharedData, OSPDataType type, uint64_t numItems) { return ospNewSharedData(sharedData, type, numItems, 0, 1, 0, 1, 0); } OSPData ospNewAssignedData1D(const void *sharedData, OSPDataType type, uint64_t numItems, OSPDeleterCallback freeFunction, const void *userPtr) { return ospNewSharedData( sharedData, type, numItems, 0, 1, 0, 1, 0, freeFunction, userPtr); } OSPData ospNewSharedData1DStride(const void *sharedData, OSPDataType type, uint64_t numItems, int64_t byteStride) { return ospNewSharedData(sharedData, type, numItems, byteStride, 1, 0, 1, 0); } OSPData ospNewSharedData2D(const void *sharedData, OSPDataType type, uint64_t numItems1, uint64_t numItems2) { return ospNewSharedData(sharedData, type, numItems1, 0, numItems2, 0, 1, 0); } OSPData ospNewSharedData2DStride(const void *sharedData, OSPDataType type, uint64_t numItems1, int64_t byteStride1, uint64_t numItems2, int64_t byteStride2) { return ospNewSharedData( sharedData, type, numItems1, byteStride1, numItems2, byteStride2, 1, 0); } OSPData ospNewSharedData3D(const void *sharedData, OSPDataType type, uint64_t numItems1, uint64_t numItems2, uint64_t numItems3) { return ospNewSharedData( sharedData, type, numItems1, 0, numItems2, 0, numItems3, 0); } OSPData ospNewData1D(OSPDataType type, uint64_t numItems) { return ospNewData(type, numItems, 1, 1); } OSPData ospNewData2D(OSPDataType type, uint64_t numItems1, uint64_t numItems2) { return ospNewData(type, numItems1, numItems2, 1); } void ospCopyData1D( const OSPData source, OSPData destination, uint64_t destinationIndex) { ospCopyData(source, destination, destinationIndex, 0, 0); } void ospCopyData2D(const OSPData source, OSPData destination, uint64_t destinationIndex1, uint64_t destinationIndex2) { ospCopyData(source, destination, destinationIndex1, destinationIndex2, 0); } // Parameter helpers //////////////////////////////////////////////////////// void ospSetString(OSPObject o, const char *id, const char *s) { ospSetParam(o, id, OSP_STRING, &s); } void ospSetObject(OSPObject o, const char *id, OSPObject other) { ospSetParam(o, id, OSP_OBJECT, &other); } void ospSetBool(OSPObject o, const char *id, int x) { ospSetParam(o, id, OSP_BOOL, &x); } void ospSetFloat(OSPObject o, const char *id, float x) { ospSetParam(o, id, OSP_FLOAT, &x); } void ospSetInt(OSPObject o, const char *id, int x) { ospSetParam(o, id, OSP_INT, &x); } void ospSetUInt(OSPObject o, const char *id, unsigned int x) { ospSetParam(o, id, OSP_UINT, &x); } void ospSetBox1f(OSPObject o, const char *id, float x, float y) { float v[] = {x, y}; ospSetParam(o, id, OSP_BOX1F, v); } void ospSetLinear2f( OSPObject o, const char *id, float x, float y, float z, float w) { float v[] = {x, y, z, w}; ospSetParam(o, id, OSP_LINEAR2F, v); } void ospSetVec2f(OSPObject o, const char *id, float x, float y) { float v[] = {x, y}; ospSetParam(o, id, OSP_VEC2F, v); } void ospSetVec3f(OSPObject o, const char *id, float x, float y, float z) { float v[] = {x, y, z}; ospSetParam(o, id, OSP_VEC3F, v); } void ospSetVec4f( OSPObject o, const char *id, float x, float y, float z, float w) { float v[] = {x, y, z, w}; ospSetParam(o, id, OSP_VEC4F, v); } void ospSetVec2i(OSPObject o, const char *id, int x, int y) { int v[] = {x, y}; ospSetParam(o, id, OSP_VEC2I, v); } void ospSetVec3i(OSPObject o, const char *id, int x, int y, int z) { int v[] = {x, y, z}; ospSetParam(o, id, OSP_VEC3I, v); } void ospSetVec4i(OSPObject o, const char *id, int x, int y, int z, int w) { int v[] = {x, y, z, w}; ospSetParam(o, id, OSP_VEC4I, v); } void ospSetObjectAsData( OSPObject o, const char *n, OSPDataType type, OSPObject p) { OSPData tmp = ospNewSharedData(&p, type, 1); OSPData data = ospNewData(type, 1); ospCopyData(tmp, data); ospSetParam(o, n, OSP_DATA, &data); ospRelease(tmp); ospRelease(data); } // Rendering helpers ////////////////////////////////////////////////////////// float ospRenderFrameBlocking( OSPFrameBuffer fb, OSPRenderer renderer, OSPCamera camera, OSPWorld world) { OSPFuture f = ospRenderFrame(fb, renderer, camera, world); ospWait(f, OSP_TASK_FINISHED); ospRelease(f); return ospGetVariance(fb); } } // extern "C" RenderKit-ospray-f2a61c2/ospray/common/000077500000000000000000000000001456566705700201545ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/ospray/common/ISPCMessages.h000066400000000000000000000015471456566705700225620ustar00rootroot00000000000000// Copyright 2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ospray/OSPEnums.h" #ifndef ISPC #include #include namespace ospray { #endif typedef enum #if __cplusplus >= 201103L : uint32_t #endif { ISPC_MSG_SPHERES, ISPC_MSG_SHADING_CONTEXT, ISPC_MSG_MAX } ISPCMsgId; #ifdef ISPC extern "C" void postStatusMsg(uniform ISPCMsgId msgId, uniform OSPLogLevel postAtLogLevel = OSP_LOG_DEBUG); #else static std::array ispcMessages = { /* ISPC_MSG_SPHERES */ "#osp:Spheres_getAreas: Non-uniform scaling in instance " "transformation detected! Importance sampling for emissive " "materials and thus resulting image may be wrong.\n", /* ISPC_MSG_SHADING_CONTEXT */ "#osp:PT: out of memory for ShadingContext allocation!\n"}; } // namespace ospray #endif RenderKit-ospray-f2a61c2/ospray/common/Library.h000066400000000000000000000003371456566705700217340ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/os/library.h" namespace ospray { using rkcommon::getSymbol; using rkcommon::loadLibrary; } // namespace ospray RenderKit-ospray-f2a61c2/ospray/common/Managed.cpp000066400000000000000000000020521456566705700222130ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "Managed.h" namespace ospray { ManagedObject::~ManagedObject() { try { std::for_each(params_begin(), params_end(), [&](std::shared_ptr &p) { auto ¶m = *p; if (param.data.valid() && param.data.is()) { auto *obj = param.data.get(); if (obj != nullptr) obj->refDec(); } }); } catch (const std::exception &e) { ospray::handleError(OSP_UNKNOWN_ERROR, e.what()); } } void ManagedObject::commit() {} std::string ManagedObject::toString() const { return "ospray::ManagedObject"; } void ManagedObject::checkUnused() { for (auto p = params_begin(); p != params_end(); ++p) { if (!(*p)->query) { postStatusMsg(OSP_LOG_WARNING) << toString() << ": found unused (or of wrong data type) parameter '" << (*p)->name << "'"; } } } box3f ManagedObject::getBounds() const { return box3f(empty); } OSPTYPEFOR_DEFINITION(ManagedObject *); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/common/Managed.h000066400000000000000000000071611456566705700216660ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "rkcommon/utility/Any.h" #include "rkcommon/utility/Optional.h" #include "rkcommon/utility/ParameterizedObject.h" // ospray #include "./OSPCommon.h" // stl #include #include namespace ospray { struct Data; template struct DataT; struct OSPRAY_CORE_INTERFACE ManagedObject : public memory::RefCount, public utility::ParameterizedObject { using OSP_PTR = ManagedObject *; ManagedObject() = default; virtual ~ManagedObject() override; virtual void commit(); virtual std::string toString() const; template T getParam(const char *name, T valIfNotFound = T()); template T *getParamObject(const char *name, T *valIfNotFound = nullptr); template inline utility::Optional getOptParam(const char *name); void checkUnused(); virtual box3f getBounds() const; // Data members // OSPDataType managedObjectType{OSP_OBJECT}; private: template inline bool checkObjType(T, OSPDataType); }; OSPTYPEFOR_SPECIALIZATION(ManagedObject *, OSP_OBJECT); // Inlined ManagedObject definitions //////////////////////////////////////// template inline T ManagedObject::getParam(const char *name, T valIfNotFound) { static_assert(!std::is_convertible::value, "Use getParamObject<> for Obj parameters"); return ParameterizedObject::getParam(name, valIfNotFound); } template inline T *ManagedObject::getParamObject(const char *name, T *valIfNotFound) { static_assert(std::is_convertible::value, "Can only get objects derived from ManagedObject"); Param *const p = findParam(name); if (!p) return valIfNotFound; const bool prevQ = p->query; // objects are always set as ManagedObject*, retrieve as such auto *obj = ParameterizedObject::getParam( name, (ManagedObject *)valIfNotFound); if (obj && obj->managedObjectType == OSPTypeFor::value) return (T *)obj; // last resort, e.g. for Texture2D if (dynamic_cast(obj)) return (T *)obj; // reset query status if object is of incorrect type p->query = prevQ; return valIfNotFound; } template inline bool ManagedObject::checkObjType(T, OSPDataType) { return true; }; template <> inline bool ManagedObject::checkObjType(ManagedObject *o, OSPDataType t) { return o->managedObjectType == t; }; template inline utility::Optional ManagedObject::getOptParam(const char *name) { utility::Optional retval; Param *param = findParam(name); // objects are always set as ManagedObject*, retrieve as such using S = typename std::conditional::value, ManagedObject *, T>::type; if (param && param->data.is()) { const auto &val = param->data.get(); if (checkObjType(val, OSPTypeFor::value)) { retval = (T)val; param->query = true; } } return retval; } } // namespace ospray // Specializations for ISPCDevice ///////////////////////////////////////////// namespace rkcommon { namespace utility { template <> inline void ParameterizedObject::Param::set( const ospray::ManagedObject::OSP_PTR &object) { using OSP_PTR = ospray::ManagedObject::OSP_PTR; if (object) object->refInc(); if (data.is()) { auto *existingObj = data.get(); if (existingObj != nullptr) existingObj->refDec(); } data = object; } } // namespace utility } // namespace rkcommon RenderKit-ospray-f2a61c2/ospray/common/OSPCommon.cpp000066400000000000000000000564631456566705700225100ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // must be first #define OSPRAY_RKCOMMON_DEFINITIONS #include "ospray/ospray_cpp/ext/rkcommon.h" #include "ISPCMessages.h" #include "OSPCommon.h" #include "api/Device.h" #include "rkcommon/containers/AlignedVector.h" #include "rkcommon/utility/StringManip.h" #include #include namespace ospray { /*! 64-bit malloc. allows for alloc'ing memory larger than 4GB */ extern "C" void *malloc64(size_t size) { return alignedMalloc(size); } /*! 64-bit malloc. allows for alloc'ing memory larger than 4GB */ extern "C" void free64(void *ptr) { alignedFree(ptr); } namespace { using TLSPool = containers::AlignedVector; thread_local std::vector tlsStack; thread_local size_t topIndex = 0; // TLS stack top index } // namespace extern "C" void *pushTLS(size_t size) { // Grow stack topIndex++; if (topIndex > tlsStack.size()) tlsStack.resize(topIndex); // Grow pool TLSPool &tp = tlsStack[topIndex - 1]; tp.resize(size); return tp.data(); } extern "C" void *reallocTLS(void *ptr, size_t size) { // Silence 'unused variable' warning (void)ptr; // Grow pool TLSPool &tp = tlsStack[topIndex - 1]; assert(ptr == tp.data()); tp.resize(size); return tp.data(); } extern "C" void popTLS(void *ptr) { // Silence 'unused variable' warning (void)ptr; // Lower stack pointer assert(topIndex > 0); assert(ptr == tlsStack[topIndex - 1].data()); topIndex--; } WarnOnce::WarnOnce(const std::string &s, uint32_t postAtLogLevel) : s(s) { postStatusMsg(postAtLogLevel) << "Warning: " << s << " (only reporting first occurrence)"; } std::string getArgString(const std::string &s) { std::vector tokens = rkcommon::utility::split(s, '='); if (tokens.size() < 2) { std::stringstream ss; ss << "Invalid format for command-line argument " << s << ". Should be formatted --osp:="; postStatusMsg(ss, OSP_LOG_WARNING); return ""; } else { return tokens.back(); } } int getArgInt(const std::string &s) { std::string value = getArgString(s); try { return std::stoi(value); } catch (...) { // std::invalid_argument or std::out_of_range std::stringstream ss; ss << "Invalid value '" << value << "' in command-line argument " << s << ". Should be an integer"; postStatusMsg(ss, OSP_LOG_WARNING); return 0; } } void initFromCommandLine(int *_ac, const char ***_av) { using namespace rkcommon::utility; auto &device = ospray::api::Device::current; if (_ac && _av) { int &ac = *_ac; auto &av = *_av; // If we have any device-params those must be set first to avoid // initializing the device in an invalid or partial state bool hadDeviceParams = false; for (int i = 1; i < ac;) { if (std::strncmp(av[i], "--osp:device-params", 19) == 0) { hadDeviceParams = true; std::string parmesan = getArgString(av[i]); std::vector parmList = split(parmesan, ','); for (std::string &p : parmList) { std::vector kv = split(p, ':'); if (kv.size() != 2) { postStatusMsg( "Invalid parameters provided for --osp:device-params. " "Must be formatted as :[,:,...]"); } else { device->setParam(kv[0], kv[1]); } } removeArgs(ac, av, i, 1); } else { ++i; } } if (hadDeviceParams) { device->commit(); } for (int i = 1; i < ac;) { std::string param = av[i]; // flag-style arguments if (param == "--osp:debug") { device->setParam("debug", true); device->setParam("logOutput", std::string("cout")); device->setParam("errorOutput", std::string("cerr")); removeArgs(ac, av, i, 1); } else if (param == "--osp:warn-as-error") { device->setParam("warnAsError", true); removeArgs(ac, av, i, 1); } else if (param == "--osp:verbose") { device->setParam("logLevel", OSP_LOG_INFO); device->setParam("logOutput", std::string("cout")); device->setParam("errorOutput", std::string("cerr")); removeArgs(ac, av, i, 1); } else if (param == "--osp:vv") { device->setParam("logLevel", OSP_LOG_DEBUG); device->setParam("logOutput", std::string("cout")); device->setParam("errorOutput", std::string("cerr")); removeArgs(ac, av, i, 1); } // arguments taking required values else if (beginsWith(param, "--osp:log-level")) { std::string str = getArgString(param); auto level = api::Device::logLevelFromString(str); device->setParam("logLevel", level.value_or(0)); removeArgs(ac, av, i, 1); } else if (beginsWith(param, "--osp:log-output")) { std::string dst = getArgString(param); if (dst == "cout" || dst == "cerr") { device->setParam("logOutput", dst); } else { std::stringstream ss; ss << "Invalid output '" << dst << "' provided for --osp:log-output. Must be 'cerr' or 'cout'"; postStatusMsg(ss); } removeArgs(ac, av, i, 1); } else if (beginsWith(param, "--osp:error-output")) { std::string dst = getArgString(param); if (dst == "cout" || dst == "cerr") { device->setParam("errorOutput", dst); } else { std::stringstream ss; ss << "Invalid output '" << dst << "' provided for --osp:error-output. Must be 'cerr' or 'cout'"; postStatusMsg(ss); } removeArgs(ac, av, i, 1); } else if (beginsWith(param, "--osp:num-threads")) { int nt = std::max(1, getArgInt(param)); device->setParam("numThreads", nt); removeArgs(ac, av, i, 1); } else if (beginsWith(param, "--osp:set-affinity")) { int val = getArgInt(param); if (val == 0 || val == 1) { device->setParam("setAffinity", val); } else { postStatusMsg( "Invalid value provided for --osp:set-affinity. " "Must be 0 or 1"); } removeArgs(ac, av, i, 1); } else { // silently ignore other arguments i++; } // ALOK: apply changes so that error messages and warnings during // initialization might appear for the user. Without this, any errors in // parsing will never be shown, even if the user sets the log output // stream, log level, etc. They still may not be shown if the output is // not set, however device->commit(); } } } size_t sizeOf(OSPDataType type) { switch (type) { case OSP_VOID_PTR: case OSP_OBJECT: case OSP_CAMERA: case OSP_DATA: case OSP_DEVICE: case OSP_FRAMEBUFFER: case OSP_FUTURE: case OSP_GEOMETRIC_MODEL: case OSP_GEOMETRY: case OSP_GROUP: case OSP_IMAGE_OPERATION: case OSP_INSTANCE: case OSP_LIGHT: case OSP_MATERIAL: case OSP_RENDERER: case OSP_TEXTURE: case OSP_TRANSFER_FUNCTION: case OSP_VOLUME: case OSP_VOLUMETRIC_MODEL: case OSP_WORLD: case OSP_STRING: return sizeof(void *); case OSP_BOOL: return sizeof(bool); case OSP_CHAR: return sizeof(int8); case OSP_UCHAR: return sizeof(uint8); case OSP_VEC2UC: return sizeof(vec2uc); case OSP_VEC3UC: return sizeof(vec3uc); case OSP_VEC4UC: return sizeof(vec4uc); case OSP_VEC2C: return sizeof(vec2c); case OSP_VEC3C: return sizeof(vec3c); case OSP_VEC4C: return sizeof(vec4c); case OSP_SHORT: return sizeof(int16); case OSP_VEC2S: return sizeof(vec2s); case OSP_VEC3S: return sizeof(vec3s); case OSP_VEC4S: return sizeof(vec4s); case OSP_USHORT: return sizeof(uint16); case OSP_VEC2US: return sizeof(vec2us); case OSP_VEC3US: return sizeof(vec3us); case OSP_VEC4US: return sizeof(vec4us); case OSP_INT: return sizeof(int32); case OSP_VEC2I: return sizeof(vec2i); case OSP_VEC3I: return sizeof(vec3i); case OSP_VEC4I: return sizeof(vec4i); case OSP_UINT: return sizeof(uint32); case OSP_VEC2UI: return sizeof(vec2ui); case OSP_VEC3UI: return sizeof(vec3ui); case OSP_VEC4UI: return sizeof(vec4ui); case OSP_LONG: return sizeof(int64); case OSP_VEC2L: return sizeof(vec2l); case OSP_VEC3L: return sizeof(vec3l); case OSP_VEC4L: return sizeof(vec4l); case OSP_ULONG: return sizeof(uint64); case OSP_VEC2UL: return sizeof(vec2ul); case OSP_VEC3UL: return sizeof(vec3ul); case OSP_VEC4UL: return sizeof(vec4ul); case OSP_HALF: return sizeof(uint16); case OSP_VEC2H: return sizeof(vec2us); case OSP_VEC3H: return sizeof(vec3us); case OSP_VEC4H: return sizeof(vec4us); case OSP_FLOAT: return sizeof(float); case OSP_VEC2F: return sizeof(vec2f); case OSP_VEC3F: return sizeof(vec3f); case OSP_VEC4F: return sizeof(vec4f); case OSP_DOUBLE: return sizeof(double); case OSP_VEC2D: return sizeof(vec2d); case OSP_VEC3D: return sizeof(vec3d); case OSP_VEC4D: return sizeof(vec4d); case OSP_BOX1I: return sizeof(box1i); case OSP_BOX2I: return sizeof(box2i); case OSP_BOX3I: return sizeof(box3i); case OSP_BOX4I: return sizeof(box4i); case OSP_BOX1F: return sizeof(box1f); case OSP_BOX2F: return sizeof(box2f); case OSP_BOX3F: return sizeof(box3f); case OSP_BOX4F: return sizeof(box4f); case OSP_LINEAR2F: return sizeof(linear2f); case OSP_LINEAR3F: return sizeof(linear3f); case OSP_AFFINE2F: return sizeof(affine2f); case OSP_AFFINE3F: return sizeof(affine3f); case OSP_QUATF: return sizeof(quatf); case OSP_UNKNOWN: return 0; } std::stringstream error; error << __FILE__ << ":" << __LINE__ << ": unknown OSPDataType " << (int)type; throw std::runtime_error(error.str()); } OSPDataType typeOf(const char *string) { if (string == nullptr) return (OSP_UNKNOWN); if (strcmp(string, "bool") == 0) return (OSP_BOOL); if (strcmp(string, "char") == 0) return (OSP_CHAR); if (strcmp(string, "half") == 0) return (OSP_HALF); if (strcmp(string, "float") == 0) return (OSP_FLOAT); if (strcmp(string, "double") == 0) return (OSP_DOUBLE); if (strcmp(string, "vec2h") == 0) return (OSP_VEC2H); if (strcmp(string, "vec3h") == 0) return (OSP_VEC3H); if (strcmp(string, "vec4h") == 0) return (OSP_VEC4H); if (strcmp(string, "vec2f") == 0) return (OSP_VEC2F); if (strcmp(string, "vec3f") == 0) return (OSP_VEC3F); if (strcmp(string, "vec4f") == 0) return (OSP_VEC4F); if (strcmp(string, "vec2d") == 0) return (OSP_VEC2D); if (strcmp(string, "vec3d") == 0) return (OSP_VEC3D); if (strcmp(string, "vec4d") == 0) return (OSP_VEC4D); if (strcmp(string, "int") == 0) return (OSP_INT); if (strcmp(string, "vec2i") == 0) return (OSP_VEC2I); if (strcmp(string, "vec3i") == 0) return (OSP_VEC3I); if (strcmp(string, "vec4i") == 0) return (OSP_VEC4I); if (strcmp(string, "uchar") == 0) return (OSP_UCHAR); if (strcmp(string, "vec2uc") == 0) return (OSP_VEC2UC); if (strcmp(string, "vec3uc") == 0) return (OSP_VEC3UC); if (strcmp(string, "vec4uc") == 0) return (OSP_VEC4UC); if (strcmp(string, "vec2c") == 0) return (OSP_VEC2C); if (strcmp(string, "vec3c") == 0) return (OSP_VEC3C); if (strcmp(string, "vec4c") == 0) return (OSP_VEC4C); if (strcmp(string, "short") == 0) return (OSP_SHORT); if (strcmp(string, "vec2s") == 0) return (OSP_VEC2S); if (strcmp(string, "vec3s") == 0) return (OSP_VEC3S); if (strcmp(string, "vec4s") == 0) return (OSP_VEC4S); if (strcmp(string, "ushort") == 0) return (OSP_USHORT); if (strcmp(string, "vec2us") == 0) return (OSP_VEC2US); if (strcmp(string, "vec3us") == 0) return (OSP_VEC3US); if (strcmp(string, "vec4us") == 0) return (OSP_VEC4US); if (strcmp(string, "uint") == 0) return (OSP_UINT); if (strcmp(string, "uint2") == 0) return (OSP_VEC2UI); if (strcmp(string, "uint3") == 0) return (OSP_VEC3UI); if (strcmp(string, "uint4") == 0) return (OSP_VEC4UI); return (OSP_UNKNOWN); } std::string stringFor(OSPDataType type) { switch (type) { case OSP_VOID_PTR: return "void_ptr"; case OSP_OBJECT: return "object"; case OSP_CAMERA: return "camera"; case OSP_DATA: return "data"; case OSP_DEVICE: return "device"; case OSP_FRAMEBUFFER: return "framebuffer"; case OSP_FUTURE: return "future"; case OSP_GEOMETRIC_MODEL: return "geometric_model"; case OSP_GEOMETRY: return "geometry"; case OSP_GROUP: return "group"; case OSP_IMAGE_OPERATION: return "image_operation"; case OSP_INSTANCE: return "instance"; case OSP_LIGHT: return "light"; case OSP_MATERIAL: return "material"; case OSP_RENDERER: return "renderer"; case OSP_TEXTURE: return "texture"; case OSP_TRANSFER_FUNCTION: return "transfer_function"; case OSP_VOLUME: return "volume"; case OSP_VOLUMETRIC_MODEL: return "volumetric_model"; case OSP_WORLD: return "world"; case OSP_STRING: return "string"; case OSP_BOOL: return "bool"; case OSP_CHAR: return "char"; case OSP_UCHAR: return "uchar"; case OSP_VEC2UC: return "vec2uc"; case OSP_VEC3UC: return "vec3uc"; case OSP_VEC4UC: return "vec4uc"; case OSP_VEC2C: return "vec2c"; case OSP_VEC3C: return "vec3c"; case OSP_VEC4C: return "vec4c"; case OSP_SHORT: return "short"; case OSP_VEC2S: return "vec2s"; case OSP_VEC3S: return "vec3s"; case OSP_VEC4S: return "vec4s"; case OSP_USHORT: return "ushort"; case OSP_VEC2US: return "vec2us"; case OSP_VEC3US: return "vec3us"; case OSP_VEC4US: return "vec4us"; case OSP_INT: return "int"; case OSP_VEC2I: return "vec2i"; case OSP_VEC3I: return "vec3i"; case OSP_VEC4I: return "vec4i"; case OSP_UINT: return "uint"; case OSP_VEC2UI: return "vec2ui"; case OSP_VEC3UI: return "vec3ui"; case OSP_VEC4UI: return "vec4ui"; case OSP_LONG: return "long"; case OSP_VEC2L: return "vec2l"; case OSP_VEC3L: return "vec3l"; case OSP_VEC4L: return "vec4l"; case OSP_ULONG: return "ulong"; case OSP_VEC2UL: return "vec2ul"; case OSP_VEC3UL: return "vec3ul"; case OSP_VEC4UL: return "vec4ul"; case OSP_HALF: return "half"; case OSP_VEC2H: return "vec2h"; case OSP_VEC3H: return "vec3h"; case OSP_VEC4H: return "vec4h"; case OSP_FLOAT: return "float"; case OSP_VEC2F: return "vec2f"; case OSP_VEC3F: return "vec3f"; case OSP_VEC4F: return "vec4f"; case OSP_VEC2D: return "vec2d"; case OSP_VEC3D: return "vec3d"; case OSP_VEC4D: return "vec4d"; case OSP_DOUBLE: return "double"; case OSP_BOX1I: return "box1i"; case OSP_BOX2I: return "box2i"; case OSP_BOX3I: return "box3i"; case OSP_BOX4I: return "box4i"; case OSP_BOX1F: return "box1f"; case OSP_BOX2F: return "box2f"; case OSP_BOX3F: return "box3f"; case OSP_BOX4F: return "box4f"; case OSP_LINEAR2F: return "linear2f"; case OSP_LINEAR3F: return "linear3f"; case OSP_AFFINE2F: return "affine2f"; case OSP_AFFINE3F: return "affine3f"; case OSP_QUATF: return "quatf"; case OSP_UNKNOWN: return "unknown"; } std::stringstream error; error << __FILE__ << ":" << __LINE__ << ": undefined OSPDataType " << (int)type; throw std::runtime_error(error.str()); } std::string stringFor(OSPTextureFormat format) { switch (format) { case OSP_TEXTURE_RGBA8: return "rgba8"; case OSP_TEXTURE_SRGBA: return "srgba"; case OSP_TEXTURE_RGBA32F: return "rgba32f"; case OSP_TEXTURE_RGB8: return "rgb8"; case OSP_TEXTURE_SRGB: return "srgb"; case OSP_TEXTURE_RGB32F: return "rgb32f"; case OSP_TEXTURE_R8: return "r8"; case OSP_TEXTURE_L8: return "l8"; case OSP_TEXTURE_RA8: return "ra8"; case OSP_TEXTURE_LA8: return "la8"; case OSP_TEXTURE_R32F: return "r32f"; case OSP_TEXTURE_RGBA16: return "rgba16"; case OSP_TEXTURE_RGB16: return "rgb16"; case OSP_TEXTURE_RA16: return "ra16"; case OSP_TEXTURE_R16: return "r16"; case OSP_TEXTURE_FORMAT_INVALID: return "invalid"; } std::stringstream error; error << __FILE__ << ":" << __LINE__ << ": undefined OSPTextureFormat " << (int)format; throw std::runtime_error(error.str()); } size_t sizeOf(OSPTextureFormat format) { switch (format) { case OSP_TEXTURE_RGBA8: case OSP_TEXTURE_SRGBA: return sizeof(uint32); case OSP_TEXTURE_RGBA32F: return sizeof(vec4f); case OSP_TEXTURE_RGB8: case OSP_TEXTURE_SRGB: return sizeof(vec3uc); case OSP_TEXTURE_RGB32F: return sizeof(vec3f); case OSP_TEXTURE_R8: case OSP_TEXTURE_L8: return sizeof(uint8); case OSP_TEXTURE_RA8: case OSP_TEXTURE_LA8: return sizeof(vec2uc); case OSP_TEXTURE_R32F: return sizeof(float); case OSP_TEXTURE_RGBA16: return sizeof(vec4us); case OSP_TEXTURE_RGB16: return sizeof(vec3us); case OSP_TEXTURE_RA16: return sizeof(vec2us); case OSP_TEXTURE_R16: return sizeof(uint16); case OSP_TEXTURE_FORMAT_INVALID: return 0; } std::stringstream error; error << __FILE__ << ":" << __LINE__ << ": unknown OSPTextureFormat " << (int)format; throw std::runtime_error(error.str()); } size_t sizeOf(OSPFrameBufferFormat format) { size_t bytes = 0; switch (format) { case OSP_FB_RGBA8: case OSP_FB_SRGBA: bytes = sizeof(uint32_t); break; case OSP_FB_RGBA32F: bytes = sizeof(vec4f); break; default: break; } return bytes; } uint32_t logLevel() { return ospray::api::Device::current->logLevel; } OSPError loadLocalModule(const std::string &name) { std::string libName = "ospray_module_" + name; try { loadLibrary(reinterpret_cast(&loadLocalModule), libName, {OSPRAY_VERSION_MAJOR, OSPRAY_VERSION_MINOR, OSPRAY_VERSION_PATCH}); } catch (const std::exception &e) { handleError(OSP_INVALID_OPERATION, e.what()); return OSP_INVALID_OPERATION; } catch (...) { return OSP_INVALID_OPERATION; } std::string initSymName = "ospray_module_init_" + name; void *initSym = getSymbol(initSymName); if (!initSym) { handleError(OSP_INVALID_OPERATION, "Could not find module initializer " + initSymName); unloadLibrary(libName); return OSP_INVALID_OPERATION; } auto initMethod = (OSPError(*)(int16_t, int16_t, int16_t))initSym; auto err = initMethod( OSPRAY_VERSION_MAJOR, OSPRAY_VERSION_MINOR, OSPRAY_VERSION_PATCH); if (err != OSP_NO_ERROR) { handleError(err, "Initialization of module " + name + " failed"); unloadLibrary(libName); } return err; } StatusMsgStream postStatusMsg(uint32_t postAtLogLevel) { return StatusMsgStream(postAtLogLevel); } extern "C" void postStatusMsg(uint32_t msgId, uint32_t postAtLogLevel) { assert(msgId < ISPC_MSG_MAX); postStatusMsg(ispcMessages[msgId], postAtLogLevel); } void postStatusMsg(const std::stringstream &msg, uint32_t postAtLogLevel) { postStatusMsg(msg.str(), postAtLogLevel); } void postStatusMsg(const std::string &msg, uint32_t postAtLogLevel) { if (!api::deviceIsSet()) return; auto level = logLevel(); if (level == OSP_LOG_NONE) return; auto &device = *api::Device::current; if (level <= postAtLogLevel) { bool logAsError = (device.warningsAreErrors && postAtLogLevel == OSP_LOG_WARNING) || postAtLogLevel == OSP_LOG_ERROR; if (logAsError) handleError(OSP_UNKNOWN_ERROR, msg + '\n'); else api::Device::current->msg_fcn( api::Device::current->statusUserData, (msg + '\n').c_str()); } } void handleError(OSPError e, const std::string &message) { if (api::deviceIsSet()) { auto &device = api::currentDevice(); device.lastErrorCode = e; device.lastErrorMsg = "#ospray: " + message; device.error_fcn(device.errorUserData, e, message.c_str()); } else { // NOTE: No device, but something should still get printed for the user to // debug the calling application. std::cerr << "#ospray: INVALID device --> " << message << std::endl; } } void postTraceMsg(const std::string &message) { if (api::deviceIsSet()) { auto &device = api::currentDevice(); device.trace_fcn(message.c_str()); } } size_t translatedHash(size_t v) { static std::map id_translation; auto itr = id_translation.find(v); if (itr == id_translation.end()) { static size_t newIndex = 0; id_translation[v] = newIndex; return newIndex++; } else { return id_translation[v]; } } OSPTYPEFOR_DEFINITION(void *); OSPTYPEFOR_DEFINITION(char *); OSPTYPEFOR_DEFINITION(const char *); OSPTYPEFOR_DEFINITION(const char[]); OSPTYPEFOR_DEFINITION(bool); OSPTYPEFOR_DEFINITION(char); OSPTYPEFOR_DEFINITION(unsigned char); OSPTYPEFOR_DEFINITION(short); OSPTYPEFOR_DEFINITION(unsigned short); OSPTYPEFOR_DEFINITION(int); OSPTYPEFOR_DEFINITION(unsigned int); OSPTYPEFOR_DEFINITION(long); OSPTYPEFOR_DEFINITION(unsigned long); OSPTYPEFOR_DEFINITION(long long); OSPTYPEFOR_DEFINITION(unsigned long long); OSPTYPEFOR_DEFINITION(float); OSPTYPEFOR_DEFINITION(double); OSPTYPEFOR_DEFINITION(OSPObject); OSPTYPEFOR_DEFINITION(OSPCamera); OSPTYPEFOR_DEFINITION(OSPData); OSPTYPEFOR_DEFINITION(OSPFrameBuffer); OSPTYPEFOR_DEFINITION(OSPFuture); OSPTYPEFOR_DEFINITION(OSPGeometricModel); OSPTYPEFOR_DEFINITION(OSPGeometry); OSPTYPEFOR_DEFINITION(OSPGroup); OSPTYPEFOR_DEFINITION(OSPImageOperation); OSPTYPEFOR_DEFINITION(OSPInstance); OSPTYPEFOR_DEFINITION(OSPLight); OSPTYPEFOR_DEFINITION(OSPMaterial); OSPTYPEFOR_DEFINITION(OSPRenderer); OSPTYPEFOR_DEFINITION(OSPTexture); OSPTYPEFOR_DEFINITION(OSPTransferFunction); OSPTYPEFOR_DEFINITION(OSPVolume); OSPTYPEFOR_DEFINITION(OSPVolumetricModel); OSPTYPEFOR_DEFINITION(OSPWorld); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC2UC); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC3UC); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC4UC); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC2C); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC3C); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC4C); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC2I); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC3I); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC4I); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC2UI); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC3UI); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC4UI); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC2L); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC3L); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC4L); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC2UL); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC3UL); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC4UL); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC2H); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC3H); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC4H); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC2F); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC3F); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC4F); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC2D); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC3D); OSPDIMENSIONALITYOF_DEFINITION(OSP_VEC4D); OSPDIMENSIONALITYOF_DEFINITION(OSP_BOX1I); OSPDIMENSIONALITYOF_DEFINITION(OSP_BOX2I); OSPDIMENSIONALITYOF_DEFINITION(OSP_BOX3I); OSPDIMENSIONALITYOF_DEFINITION(OSP_BOX4I); OSPDIMENSIONALITYOF_DEFINITION(OSP_BOX1F); OSPDIMENSIONALITYOF_DEFINITION(OSP_BOX2F); OSPDIMENSIONALITYOF_DEFINITION(OSP_BOX3F); OSPDIMENSIONALITYOF_DEFINITION(OSP_BOX4F); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/common/OSPCommon.h000066400000000000000000000164451456566705700221510ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifdef _WIN32 // ----------- windows only ----------- typedef unsigned long long id_t; #ifndef _USE_MATH_DEFINES #define _USE_MATH_DEFINES #endif #include #include #ifdef _M_X64 typedef long long ssize_t; #else typedef int ssize_t; #endif #else // ----------- NOT windows ----------- #include "unistd.h" #endif #include "rkcommon/math/AffineSpace.h" #include "rkcommon/memory/RefCount.h" #include "rkcommon/memory/malloc.h" // ospray #include "ospray/ospray.h" #include "ospray/ospray_cpp/ext/rkcommon.h" #include "ospray/version.h" // std #include // for int64_t etc #include #include // NOTE(jda) - This one file is shared between the core OSPRay library and the // ispc module...thus we have to define 2 different EXPORTS macros // here. This needs to be split between the libraries! #ifdef _WIN32 #ifdef ospray_EXPORTS #define OSPRAY_INTERFACE __declspec(dllexport) #else #define OSPRAY_INTERFACE __declspec(dllimport) #endif #define OSPRAY_DLLEXPORT __declspec(dllexport) #else #define OSPRAY_INTERFACE #define OSPRAY_DLLEXPORT #endif #define OSPRAY_CORE_INTERFACE OSPRAY_INTERFACE #ifdef _WIN32 #if defined(ospray_module_cpu_EXPORTS) || defined(ospray_module_gpu_EXPORTS) #define OSPRAY_MODULE_ISPC_INTERFACE __declspec(dllexport) #else #define OSPRAY_MODULE_ISPC_INTERFACE __declspec(dllimport) #endif #define OSPRAY_MODULE_ISPC_DLLEXPORT __declspec(dllexport) #else #define OSPRAY_MODULE_ISPC_INTERFACE #define OSPRAY_MODULE_ISPC_DLLEXPORT #endif #define OSPRAY_SDK_INTERFACE OSPRAY_MODULE_ISPC_INTERFACE //! main namespace for all things ospray (for internal code) namespace ospray { using namespace rkcommon; using namespace rkcommon::math; using namespace rkcommon::memory; /*! basic types */ using int64 = std::int64_t; using uint64 = std::uint64_t; using int32 = std::int32_t; using uint32 = std::uint32_t; using int16 = std::int16_t; using uint16 = std::uint16_t; using int8 = std::int8_t; using uint8 = std::uint8_t; using index_t = std::int64_t; // Argument parsing functions std::string getArgString(const std::string &s); int getArgInt(const std::string &s); void initFromCommandLine(int *ac = nullptr, const char ***av = nullptr); extern "C" { /*! 64-bit malloc. allows for alloc'ing memory larger than 4GB */ OSPRAY_CORE_INTERFACE void *malloc64(size_t size); /*! 64-bit malloc. allows for alloc'ing memory larger than 4GB */ OSPRAY_CORE_INTERFACE void free64(void *ptr); /*! Thread Local Storage functions */ OSPRAY_CORE_INTERFACE void *pushTLS(size_t size); OSPRAY_CORE_INTERFACE void *reallocTLS(void *ptr, size_t size); OSPRAY_CORE_INTERFACE void popTLS(void *ptr); } OSPRAY_CORE_INTERFACE OSPDataType typeOf(const char *string); inline OSPDataType typeOf(const std::string &s) { return typeOf(s.c_str()); } OSPRAY_CORE_INTERFACE std::string stringFor(OSPDataType); OSPRAY_CORE_INTERFACE std::string stringFor(OSPTextureFormat); inline bool isObjectType(OSPDataType type) { return type & OSP_OBJECT; } OSPRAY_CORE_INTERFACE size_t sizeOf(OSPDataType); OSPRAY_CORE_INTERFACE size_t sizeOf(OSPTextureFormat); OSPRAY_CORE_INTERFACE size_t sizeOf(OSPFrameBufferFormat); OSPRAY_CORE_INTERFACE OSPError loadLocalModule(const std::string &name); inline OSPError moduleVersionCheck(int16_t versionMajor, int16_t versionMinor) { if ((OSPRAY_VERSION_MAJOR == versionMajor) && (OSPRAY_VERSION_MINOR == versionMinor)) { return OSP_NO_ERROR; } else return OSP_VERSION_MISMATCH; } /*! little helper class that prints out a warning string upon the first time it is encountered. Usage: if (someThisBadHappens) { static WarnOnce warning("something bad happened, at least once!"); ... } */ struct OSPRAY_CORE_INTERFACE WarnOnce { WarnOnce( const std::string &message, uint32_t postAtLogLevel = OSP_LOG_WARNING); private: const std::string s; }; OSPRAY_CORE_INTERFACE uint32_t logLevel(); extern "C" OSPRAY_CORE_INTERFACE void postStatusMsg( uint32_t msgId, uint32_t postAtLogLevel); OSPRAY_CORE_INTERFACE void postStatusMsg( const std::stringstream &msg, uint32_t postAtLogLevel = OSP_LOG_DEBUG); OSPRAY_CORE_INTERFACE void postStatusMsg( const std::string &msg, uint32_t postAtLogLevel = OSP_LOG_DEBUG); // use postStatusMsg to output any information, which will use OSPRay's // internal infrastructure, optionally at a given loglevel // a newline is added implicitly ////////////////////////////////////////////////////////////////////////////// struct StatusMsgStream : public std::stringstream { StatusMsgStream(uint32_t postAtLogLevel = OSP_LOG_DEBUG); StatusMsgStream(const StatusMsgStream ©) = delete; StatusMsgStream(StatusMsgStream &&move); StatusMsgStream &operator=(const StatusMsgStream ©) = delete; StatusMsgStream &operator=(StatusMsgStream &&move) = default; ~StatusMsgStream() override; private: uint32_t logLevel{OSP_LOG_DEBUG}; }; inline StatusMsgStream::StatusMsgStream(uint32_t postAtLogLevel) : logLevel(postAtLogLevel) {} inline StatusMsgStream::~StatusMsgStream() { auto msg = str(); if (!msg.empty()) postStatusMsg(msg, logLevel); } inline StatusMsgStream::StatusMsgStream(StatusMsgStream &&move) { this->str(move.str()); } OSPRAY_CORE_INTERFACE StatusMsgStream postStatusMsg( uint32_t postAtLogLevel = OSP_LOG_DEBUG); ///////////////////////////////////////////////////////////////////////////// OSPRAY_CORE_INTERFACE void handleError(OSPError e, const std::string &message); OSPRAY_CORE_INTERFACE void postTraceMsg(const std::string &message); //! log status message at loglevel x #define ospLog(x) StatusMsgStream(x) << "(" << x << "): " //! log status message at loglevel x with function name #define ospLogF(x) StatusMsgStream(x) << __FUNCTION__ << ": " //! log status message at loglevel x with function, file, and line number #define ospLogL(x) \ StatusMsgStream(x) << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ \ << "): " // RTTI hash ID lookup helper functions /////////////////////////////////// OSPRAY_CORE_INTERFACE size_t translatedHash(size_t v); template inline size_t typeIdOf() { return translatedHash(typeid(T).hash_code()); } template inline size_t typeIdOf(T *v) { return translatedHash(typeid(*v).hash_code()); } template inline size_t typeIdOf(const T &v) { return translatedHash(typeid(v).hash_code()); } template inline size_t typeIdOf(const std::unique_ptr &v) { return translatedHash(typeid(*v).hash_code()); } template inline size_t typeIdOf(const std::shared_ptr &v) { return translatedHash(typeid(*v).hash_code()); } // RTTI string name lookup helper functions /////////////////////////////// template inline std::string typeString() { return typeid(T).name(); } template inline std::string typeString(T *v) { return typeid(*v).name(); } template inline std::string typeString(const T &v) { return typeid(v).name(); } template inline std::string typeString(const std::unique_ptr &v) { return typeid(*v).name(); } template inline std::string typeString(const std::shared_ptr &v) { return typeid(*v).name(); } } // namespace ospray RenderKit-ospray-f2a61c2/ospray/common/ObjectFactory.h000066400000000000000000000035171456566705700230710ustar00rootroot00000000000000// Copyright 2022 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "OSPCommon.h" #include #include #include #ifdef _WIN32 #ifdef OBJECTFACTORY_IMPORT #define OF_DECLSPEC __declspec(dllimport) #else #define OF_DECLSPEC __declspec(dllexport) #endif #else #define OF_DECLSPEC #endif // 'fcns' member is not defined when imported from other library #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wundefined-var-template" namespace ospray { template struct OF_DECLSPEC ObjectFactory { // Register a new type to instantiate template static void registerType(const char *type) { fcns[type] = &allocate_object; } // Instantiate provided type class static T *createInstance(const char *type, Args &&...args) { // Find constructor pointer and call it FactoryFcn fcn = fcns[type]; if (fcn) { auto *obj = fcn(std::forward(args)...); if (obj != nullptr) return obj; } const auto type_string = stringFor(OSPTypeFor::value); throw std::runtime_error("Could not find '" + type_string + "' of type: '" + type + "'. Make sure you have the correct OSPRay libraries linked and initialized."); } private: using FactoryFcn = T *(*)(Args &&...args); using FactoryMap = std::map; // Map of constructor pointers, preferably use 'inline static' since C++17 static FactoryMap fcns; template static T *allocate_object(Args &&...args) { return new D(std::forward(args)...); } }; #ifndef OBJECTFACTORY_IMPORT template typename ObjectFactory::FactoryMap ObjectFactory::fcns; #endif } // namespace ospray #pragma clang diagnostic pop #undef OF_DECLSPEC RenderKit-ospray-f2a61c2/ospray/fb/000077500000000000000000000000001456566705700172535ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/ospray/fb/FrameBufferView.h000066400000000000000000000002161456566705700224420ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once namespace ospray { #include "FrameBufferViewDef.h" }RenderKit-ospray-f2a61c2/ospray/fb/FrameBufferViewDef.h000066400000000000000000000024571456566705700230720ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // No pragma once because this struct is defined twice, both in `ospray` and // `ispc` namespace // A view into a portion of the framebuffer to run the frame operation on // TODO: Change name struct FrameBufferView { vec2ui fbDims; // the total dimensions of the global framebuffer vec2ui viewDims; // the dimensions of this view of the framebuffer // Color buffer pointers being input/output to FrameOp const vec4f *colorBufferInput; vec4f *colorBufferOutput; // Other buffers that can used as well in FrameOp const float *depthBuffer; // one float per pixel, may be NULL const vec3f *normalBuffer; // accumulated world-space normal per pixel const vec3f *albedoBuffer; // accumulated albedo, one RGBF32 per pixel #ifdef __cplusplus FrameBufferView() = default; FrameBufferView(const vec2ui &dims, const vec4f *colorBufferInput, const float *depthBuffer = nullptr, const vec3f *normalBuffer = nullptr, const vec3f *albedoBuffer = nullptr) : fbDims(dims), viewDims(dims), colorBufferInput(colorBufferInput), colorBufferOutput(nullptr), depthBuffer(depthBuffer), normalBuffer(normalBuffer), albedoBuffer(albedoBuffer) {} #endif // __cplusplus }; RenderKit-ospray-f2a61c2/ospray/fb/ImageOp.cpp000066400000000000000000000014031456566705700212760ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ImageOp.h" namespace ospray { // ImageOp definitions //////////////////////////////////////////////////////// ImageOp *ImageOp::createImageOp(const char *type, api::Device &device) { return createInstance(type, device); } ImageOp::ImageOp() { managedObjectType = OSP_IMAGE_OPERATION; } std::string ImageOp::toString() const { return "ospray::ImageOp(base class)"; } // explicitly create a key function to merge typeinfo from dynamically loaded // modules (to reliably dynamic_cast<> for the denoiser) // see https://github.com/android/ndk/issues/533#issuecomment-335977747 FrameOpInterface::~FrameOpInterface() {}; OSPTYPEFOR_DEFINITION(ImageOp *); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/fb/ImageOp.h000066400000000000000000000032531456566705700207500ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "common/Managed.h" #include "common/ObjectFactory.h" #include namespace ospray { namespace api { struct Device; } struct FrameBufferView; // An instance of an image op that is actually attached to a framebuffer struct OSPRAY_CORE_INTERFACE LiveImageOp { virtual ~LiveImageOp() = default; }; // Base abstraction for a "Image Op" to be performed for // every image that gets written into a frame buffer. // A ImageOp is basically a "hook" that allows to inject arbitrary // code, such as postprocessing, filtering, blending, tone mapping, // sending tiles to a display wall, etc. struct OSPRAY_CORE_INTERFACE ImageOp : public ManagedObject, public ObjectFactory { static ImageOp *createImageOp(const char *type, api::Device &device); ImageOp(); ~ImageOp() override = default; std::string toString() const override; }; OSPTYPEFOR_SPECIALIZATION(ImageOp *, OSP_IMAGE_OPERATION); struct Camera; struct OSPRAY_CORE_INTERFACE LiveFrameOpInterface : public LiveImageOp { ~LiveFrameOpInterface() override = default; // Execute FrameOp kernel virtual void process(void *waitEvent) = 0; }; struct OSPRAY_CORE_INTERFACE FrameOpInterface : public ImageOp { ~FrameOpInterface() override; // no =default! // Attach an image op to an existing framebuffer. Use this // to pass the params from the API to the instance of the image op // which will actually be run on the framebuffer view or tiles of the // framebuffer passed virtual std::unique_ptr attach( FrameBufferView &fbView) = 0; }; } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/000077500000000000000000000000001456566705700203075ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/ospray/include/ospray/000077500000000000000000000000001456566705700216245ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/ospray/include/ospray/OSPEnums.h000066400000000000000000000215621456566705700234540ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // This header is shared with ISPC #pragma once // Log levels which can be set on a device via "logLevel" parameter typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_LOG_DEBUG = 1, OSP_LOG_INFO = 2, OSP_LOG_WARNING = 3, OSP_LOG_ERROR = 4, OSP_LOG_NONE = 5 } OSPLogLevel; typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_DEVICE_VERSION = 0, OSP_DEVICE_VERSION_MAJOR = 1, OSP_DEVICE_VERSION_MINOR = 2, OSP_DEVICE_VERSION_PATCH = 3, OSP_DEVICE_SO_VERSION = 4 } OSPDeviceProperty; // An enum type that represensts the different data types represented in OSPRay typedef enum #if __cplusplus >= 201103L : uint32_t #endif { // Object reference type. OSP_DEVICE = 100, // Void pointer type. OSP_VOID_PTR = 200, // Booleans, same size as OSP_INT. OSP_BOOL = 250, // highest bit to represent objects/handles OSP_OBJECT = 0x8000000, // object subtypes OSP_DATA = 0x8000000 + 100, OSP_CAMERA, OSP_FRAMEBUFFER, OSP_FUTURE, OSP_GEOMETRIC_MODEL, OSP_GEOMETRY, OSP_GROUP, OSP_IMAGE_OPERATION, OSP_INSTANCE, OSP_LIGHT, OSP_MATERIAL, OSP_RENDERER, OSP_TEXTURE, OSP_TRANSFER_FUNCTION, OSP_VOLUME, OSP_VOLUMETRIC_MODEL, OSP_WORLD, // Pointer to a C-style NULL-terminated character string. OSP_STRING = 1500, // Character scalar type. OSP_CHAR = 2000, OSP_VEC2C, OSP_VEC3C, OSP_VEC4C, // Unsigned character scalar and vector types. OSP_UCHAR = 2500, OSP_VEC2UC, OSP_VEC3UC, OSP_VEC4UC, OSP_BYTE = 2500, // XXX OSP_UCHAR, ISPC issue #1246 OSP_RAW = 2500, // XXX OSP_UCHAR, ISPC issue #1246 // Signed 16-bit integer scalar. OSP_SHORT = 3000, OSP_VEC2S, OSP_VEC3S, OSP_VEC4S, // Unsigned 16-bit integer scalar. OSP_USHORT = 3500, OSP_VEC2US, OSP_VEC3US, OSP_VEC4US, // Signed 32-bit integer scalar and vector types. OSP_INT = 4000, OSP_VEC2I, OSP_VEC3I, OSP_VEC4I, // Unsigned 32-bit integer scalar and vector types. OSP_UINT = 4500, OSP_VEC2UI, OSP_VEC3UI, OSP_VEC4UI, // Signed 64-bit integer scalar and vector types. OSP_LONG = 5000, OSP_VEC2L, OSP_VEC3L, OSP_VEC4L, // Unsigned 64-bit integer scalar and vector types. OSP_ULONG = 5550, OSP_VEC2UL, OSP_VEC3UL, OSP_VEC4UL, // Half precision floating point scalar and vector types (IEEE 754 // `binary16`). OSP_HALF = 5800, OSP_VEC2H, OSP_VEC3H, OSP_VEC4H, // Single precision floating point scalar and vector types. OSP_FLOAT = 6000, OSP_VEC2F, OSP_VEC3F, OSP_VEC4F, // Double precision floating point scalar type. OSP_DOUBLE = 7000, OSP_VEC2D, OSP_VEC3D, OSP_VEC4D, // Signed 32-bit integer N-dimensional box types OSP_BOX1I = 8000, OSP_BOX2I, OSP_BOX3I, OSP_BOX4I, // Single precision floating point N-dimensional box types OSP_BOX1F = 10000, OSP_BOX2F, OSP_BOX3F, OSP_BOX4F, // Transformation types OSP_LINEAR2F = 12000, OSP_LINEAR3F, OSP_AFFINE2F, OSP_AFFINE3F, OSP_QUATF, // Guard value. OSP_UNKNOWN = 9999999 } OSPDataType; // OSPRay format constants for Texture creation typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_TEXTURE_RGBA8, OSP_TEXTURE_SRGBA, OSP_TEXTURE_RGBA32F, OSP_TEXTURE_RGB8, OSP_TEXTURE_SRGB, OSP_TEXTURE_RGB32F, OSP_TEXTURE_R8, OSP_TEXTURE_R32F, OSP_TEXTURE_L8, OSP_TEXTURE_RA8, OSP_TEXTURE_LA8, OSP_TEXTURE_RGBA16, OSP_TEXTURE_RGB16, OSP_TEXTURE_RA16, OSP_TEXTURE_R16, // Denotes an unknown texture format, so we can properly initialize parameters OSP_TEXTURE_FORMAT_INVALID = 255, } OSPTextureFormat; // Filter modes that can be set on 'texture2d' type OSPTexture typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_TEXTURE_FILTER_LINEAR = 0, // default bilinear interpolation OSP_TEXTURE_FILTER_NEAREST // use nearest-neighbor interpolation } OSPTextureFilter; // Wrap modes that can be set on 'texture2d' type OSPTexture typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_TEXTURE_WRAP_REPEAT, OSP_TEXTURE_WRAP_MIRRORED_REPEAT, OSP_TEXTURE_WRAP_CLAMP_TO_EDGE } OSPTextureWrapMode; // Error codes returned by various API and callback functions typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_NO_ERROR = 0, // No error has been recorded OSP_UNKNOWN_ERROR = 1, // An unknown error has occurred OSP_INVALID_ARGUMENT = 2, // An invalid argument is specified OSP_INVALID_OPERATION = 3, // The operation is not allowed for the specified object OSP_OUT_OF_MEMORY = 4, // There is not enough memory left to execute the command OSP_UNSUPPORTED_CPU = 5, // The CPU is not supported as it does not support SSE4.1 OSP_VERSION_MISMATCH = 6, // A module could not be loaded due to mismatching version } OSPError; // OSPRay format constants for Frame Buffer creation typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_FB_NONE, // framebuffer will not be mapped by application OSP_FB_RGBA8, // one dword per pixel: rgb+alpha, each one byte OSP_FB_SRGBA, // one dword per pixel: rgb (in sRGB space) + alpha, each one // byte OSP_FB_RGBA32F, // one float4 per pixel: rgb+alpha, each one float } OSPFrameBufferFormat; // OSPRay channel constants for Frame Buffer (can be OR'ed together) typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_FB_COLOR = (1 << 0), OSP_FB_DEPTH = (1 << 1), OSP_FB_ACCUM = (1 << 2), OSP_FB_VARIANCE = (1 << 3), OSP_FB_NORMAL = (1 << 4), // in world-space OSP_FB_ALBEDO = (1 << 5), OSP_FB_ID_PRIMITIVE = (1 << 6), OSP_FB_ID_OBJECT = (1 << 7), OSP_FB_ID_INSTANCE = (1 << 8) } OSPFrameBufferChannel; // OSPRay events which can be waited on via ospWait() typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_NONE_FINISHED = 0, OSP_WORLD_RENDERED = 10, OSP_WORLD_COMMITTED = 20, OSP_FRAME_FINISHED = 30, OSP_TASK_FINISHED = 100000 } OSPSyncEvent; // OSPRay cell types definition for unstructured volumes, values are set to // match VTK typedef enum #if __cplusplus >= 201103L : uint8_t #endif { OSP_TETRAHEDRON = 10, OSP_HEXAHEDRON = 12, OSP_WEDGE = 13, OSP_PYRAMID = 14, OSP_UNKNOWN_CELL_TYPE = 255 } OSPUnstructuredCellType; // OSPRay camera stereo image modes typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_STEREO_NONE, OSP_STEREO_LEFT, OSP_STEREO_RIGHT, OSP_STEREO_SIDE_BY_SIDE, OSP_STEREO_TOP_BOTTOM, OSP_STEREO_UNKNOWN = 255 } OSPStereoMode; typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_SHUTTER_GLOBAL, OSP_SHUTTER_ROLLING_RIGHT, OSP_SHUTTER_ROLLING_LEFT, OSP_SHUTTER_ROLLING_DOWN, OSP_SHUTTER_ROLLING_UP, OSP_SHUTTER_UNKNOWN = 255 } OSPShutterType; typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_ROUND, OSP_FLAT, OSP_RIBBON, OSP_DISJOINT, OSP_UNKNOWN_CURVE_TYPE = 255 } OSPCurveType; typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_SPHERE = 50, OSP_DISC = 51, OSP_ORIENTED_DISC = 52, OSP_UNKNOWN_SPHERE_TYPE = 255 } OSPSphereType; typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_LINEAR, OSP_BEZIER, OSP_BSPLINE, OSP_HERMITE, OSP_CATMULL_ROM, OSP_UNKNOWN_CURVE_BASIS = 255 } OSPCurveBasis; typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_SUBDIVISION_NO_BOUNDARY, OSP_SUBDIVISION_SMOOTH_BOUNDARY, OSP_SUBDIVISION_PIN_CORNERS, OSP_SUBDIVISION_PIN_BOUNDARY, OSP_SUBDIVISION_PIN_ALL } OSPSubdivisionMode; // AMR Volume rendering methods typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_AMR_CURRENT, OSP_AMR_FINEST, OSP_AMR_OCTANT } OSPAMRMethod; // Filter modes for VDB and structured volumes, compatible with VKL typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_VOLUME_FILTER_NEAREST = 0, // treating voxel cell as constant OSP_VOLUME_FILTER_LINEAR = 100, // default trilinear interpolation OSP_VOLUME_FILTER_CUBIC = 200 // tricubic interpolation } OSPVolumeFilter; // VDB node data format typedef enum #if __cplusplus > 201103L : uint32_t #endif { OSP_VOLUME_FORMAT_TILE = 0, // node with no spatial variation. OSP_VOLUME_FORMAT_DENSE_ZYX // a dense grid of voxels in zyx layout } OSPVolumeFormat; // OSPRay pixel filter types typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_PIXELFILTER_POINT, OSP_PIXELFILTER_BOX, OSP_PIXELFILTER_GAUSS, OSP_PIXELFILTER_MITCHELL, OSP_PIXELFILTER_BLACKMAN_HARRIS } OSPPixelFilterType; // OSPRay light quantity types typedef enum #if __cplusplus >= 201103L : uint32_t #endif { OSP_INTENSITY_QUANTITY_RADIANCE, // unit W/sr/m^2 OSP_INTENSITY_QUANTITY_IRRADIANCE, // unit W/m^2 OSP_INTENSITY_QUANTITY_INTENSITY, // radiant intensity, unit W/sr OSP_INTENSITY_QUANTITY_POWER, // radiant flux, unit W OSP_INTENSITY_QUANTITY_SCALE, // linear scaling factor for the built-in type OSP_INTENSITY_QUANTITY_UNKNOWN } OSPIntensityQuantity; RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray.h000066400000000000000000000247631456566705700233260ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #ifndef NULL #if __cplusplus >= 201103L #define NULL nullptr #else #define NULL 0 #endif #endif #include #include #include "OSPEnums.h" #ifdef _WIN32 #ifdef ospray_EXPORTS #define OSPRAY_INTERFACE __declspec(dllexport) #else #define OSPRAY_INTERFACE __declspec(dllimport) #endif #else #define OSPRAY_INTERFACE #endif #ifdef __GNUC__ #define OSP_DEPRECATED __attribute__((deprecated)) #elif defined(_MSC_VER) #define OSP_DEPRECATED __declspec(deprecated) #else #define OSP_DEPRECATED #endif #ifdef __cplusplus // C++ DOES support default initializers #define OSP_DEFAULT_VAL(a) = a #else /* C99 does NOT support default initializers, so we use this macro to define them away */ #define OSP_DEFAULT_VAL(a) #endif // Give OSPRay handle types a concrete definition to enable C++ type checking #ifdef __cplusplus namespace osp { struct Device; struct ManagedObject { }; struct Camera : public ManagedObject { }; struct Data : public ManagedObject { }; struct FrameBuffer : public ManagedObject { }; struct Future : public ManagedObject { }; struct GeometricModel : public ManagedObject { }; struct Geometry : public ManagedObject { }; struct Group : public ManagedObject { }; struct ImageOperation : public ManagedObject { }; struct Instance : public ManagedObject { }; struct Light : public ManagedObject { }; struct Material : public ManagedObject { }; struct Renderer : public ManagedObject { }; struct Texture : public ManagedObject { }; struct TransferFunction : public ManagedObject { }; struct Volume : public ManagedObject { }; struct VolumetricModel : public ManagedObject { }; struct World : public ManagedObject { }; } // namespace osp typedef osp::Device *OSPDevice; typedef osp::Camera *OSPCamera; typedef osp::Data *OSPData; typedef osp::FrameBuffer *OSPFrameBuffer; typedef osp::Future *OSPFuture; typedef osp::GeometricModel *OSPGeometricModel; typedef osp::Geometry *OSPGeometry; typedef osp::Group *OSPGroup; typedef osp::ImageOperation *OSPImageOperation; typedef osp::Instance *OSPInstance; typedef osp::Light *OSPLight; typedef osp::ManagedObject *OSPObject; typedef osp::Material *OSPMaterial; typedef osp::Renderer *OSPRenderer; typedef osp::Texture *OSPTexture; typedef osp::TransferFunction *OSPTransferFunction; typedef osp::Volume *OSPVolume; typedef osp::VolumetricModel *OSPVolumetricModel; typedef osp::World *OSPWorld; #else typedef void *OSPDevice; typedef void _OSPManagedObject; /* Abstract object types. in C99, those are all the same because C99 doesn't know inheritance, and we want to make sure that a OSPGeometry can still be passed to a function that expects a OSPObject, etc. */ typedef _OSPManagedObject *OSPManagedObject, *OSPCamera, *OSPData, *OSPFrameBuffer, *OSPFuture, *OSPGeometricModel, *OSPGeometry, *OSPGroup, *OSPImageOperation, *OSPInstance, *OSPLight, *OSPMaterial, *OSPObject, *OSPRenderer, *OSPTexture, *OSPTransferFunction, *OSPVolume, *OSPVolumetricModel, *OSPWorld; #endif #ifdef __cplusplus extern "C" { #endif // OSPRay Initialization //////////////////////////////////////////////////// /* Initialize OSPRay using commandline arguments. equivalent to doing ospNewDevice() followed by ospSetCurrentDevice() returns OSPError value to report any errors during initialization */ OSPRAY_INTERFACE OSPError ospInit( int *argc OSP_DEFAULT_VAL(NULL), const char **argv OSP_DEFAULT_VAL(NULL)); // returns the OSPRay Version in use by the device OSPRAY_INTERFACE int64_t ospDeviceGetProperty(OSPDevice, OSPDeviceProperty); // Shutdown the OSPRay engine...effectively deletes whatever device is currently // set. OSPRAY_INTERFACE void ospShutdown(); // Create an OSPRay engine backend using explicit device string. OSPRAY_INTERFACE OSPDevice ospNewDevice( const char *deviceType OSP_DEFAULT_VAL("cpu")); // Set current device the API responds to OSPRAY_INTERFACE void ospSetCurrentDevice(OSPDevice); // Get the currently set device OSPRAY_INTERFACE OSPDevice ospGetCurrentDevice(); OSPRAY_INTERFACE void ospDeviceSetParam( OSPDevice, const char *id, OSPDataType, const void *mem); OSPRAY_INTERFACE void ospDeviceRemoveParam(OSPDevice, const char *id); // Status message callback function type typedef void (*OSPStatusCallback)(void *userData, const char *messageText); // Set callback for given Device to call when a status message occurs OSPRAY_INTERFACE void ospDeviceSetStatusCallback( OSPDevice, OSPStatusCallback, void *userData); // Error message callback function type typedef void (*OSPErrorCallback)( void *userData, OSPError, const char *errorDetails); // Set callback for given Device to call when an error occurs OSPRAY_INTERFACE void ospDeviceSetErrorCallback( OSPDevice, OSPErrorCallback, void *userData); // Get the OSPError code for the last error that has occurred on the device OSPRAY_INTERFACE OSPError ospDeviceGetLastErrorCode(OSPDevice); // Get the message for the last error that has occurred on the device OSPRAY_INTERFACE const char *ospDeviceGetLastErrorMsg(OSPDevice); // Commit parameters on a given device OSPRAY_INTERFACE void ospDeviceCommit(OSPDevice); // OSPDevice handle lifetimes OSPRAY_INTERFACE void ospDeviceRelease(OSPDevice); OSPRAY_INTERFACE void ospDeviceRetain(OSPDevice); /* Load module 'name' from shard lib libospray_module_.so returns OSPError value to report any errors during initialization */ OSPRAY_INTERFACE OSPError ospLoadModule(const char *name); // OSPRay Data Arrays /////////////////////////////////////////////////////// // Memory deleter callback function type typedef void (*OSPDeleterCallback)( const void *userData, const void *sharedData); OSPRAY_INTERFACE OSPData ospNewSharedData(const void *sharedData, OSPDataType, uint64_t numItems1, int64_t byteStride1 OSP_DEFAULT_VAL(0), uint64_t numItems2 OSP_DEFAULT_VAL(1), int64_t byteStride2 OSP_DEFAULT_VAL(0), uint64_t numItems3 OSP_DEFAULT_VAL(1), int64_t byteStride3 OSP_DEFAULT_VAL(0), OSPDeleterCallback OSP_DEFAULT_VAL(NULL), const void *userPtr OSP_DEFAULT_VAL(NULL)); OSPRAY_INTERFACE OSPData ospNewData(OSPDataType, uint64_t numItems1, uint64_t numItems2 OSP_DEFAULT_VAL(1), uint64_t numItems3 OSP_DEFAULT_VAL(1)); OSPRAY_INTERFACE void ospCopyData(const OSPData source, OSPData destination, uint64_t destinationIndex1 OSP_DEFAULT_VAL(0), uint64_t destinationIndex2 OSP_DEFAULT_VAL(0), uint64_t destinationIndex3 OSP_DEFAULT_VAL(0)); // Renderable Objects /////////////////////////////////////////////////////// OSPRAY_INTERFACE OSPLight ospNewLight(const char *type); OSPRAY_INTERFACE OSPCamera ospNewCamera(const char *type); OSPRAY_INTERFACE OSPGeometry ospNewGeometry(const char *type); OSPRAY_INTERFACE OSPVolume ospNewVolume(const char *type); OSPRAY_INTERFACE OSPGeometricModel ospNewGeometricModel( OSPGeometry OSP_DEFAULT_VAL(NULL)); OSPRAY_INTERFACE OSPVolumetricModel ospNewVolumetricModel( OSPVolume OSP_DEFAULT_VAL(NULL)); // Model Meta-Data ////////////////////////////////////////////////////////// OSPRAY_INTERFACE OSPMaterial ospNewMaterial(const char *materialType); OSPRAY_INTERFACE OSPTransferFunction ospNewTransferFunction(const char *type); OSPRAY_INTERFACE OSPTexture ospNewTexture(const char *type); // Instancing /////////////////////////////////////////////////////////////// OSPRAY_INTERFACE OSPGroup ospNewGroup(); OSPRAY_INTERFACE OSPInstance ospNewInstance(OSPGroup OSP_DEFAULT_VAL(NULL)); // Top-level Worlds ///////////////////////////////////////////////////////// OSPRAY_INTERFACE OSPWorld ospNewWorld(); typedef struct { float lower[3]; float upper[3]; } OSPBounds; // Return bounds if the object is able (OSPWorld, OSPInstance, and OSPGroup) OSPRAY_INTERFACE OSPBounds ospGetBounds(OSPObject); // Object + Parameter Lifetime Management /////////////////////////////////// // Set a parameter, where 'mem' points the address of the type specified OSPRAY_INTERFACE void ospSetParam( OSPObject, const char *id, OSPDataType, const void *mem); OSPRAY_INTERFACE void ospRemoveParam(OSPObject, const char *id); // Make parameters which have been set visible to the object OSPRAY_INTERFACE void ospCommit(OSPObject); // Reduce the application-side object ref count by 1 OSPRAY_INTERFACE void ospRelease(OSPObject); // Increace the application-side object ref count by 1 OSPRAY_INTERFACE void ospRetain(OSPObject); // FrameBuffer Manipulation ///////////////////////////////////////////////// OSPRAY_INTERFACE OSPFrameBuffer ospNewFrameBuffer(int size_x, int size_y, OSPFrameBufferFormat format OSP_DEFAULT_VAL(OSP_FB_SRGBA), uint32_t frameBufferChannels OSP_DEFAULT_VAL(OSP_FB_COLOR)); OSPRAY_INTERFACE OSPImageOperation ospNewImageOperation(const char *type); // Pointer access (read-only) to the memory of the given frame buffer channel OSPRAY_INTERFACE const void *ospMapFrameBuffer( OSPFrameBuffer, OSPFrameBufferChannel OSP_DEFAULT_VAL(OSP_FB_COLOR)); // Unmap a previously mapped frame buffer pointer OSPRAY_INTERFACE void ospUnmapFrameBuffer(const void *mapped, OSPFrameBuffer); // Get variance from last rendered frame OSPRAY_INTERFACE float ospGetVariance(OSPFrameBuffer); // Reset frame buffer accumulation for next render frame call OSPRAY_INTERFACE void ospResetAccumulation(OSPFrameBuffer); // Frame Rendering ////////////////////////////////////////////////////////// OSPRAY_INTERFACE OSPRenderer ospNewRenderer(const char *type); // Render a frame (non-blocking), return a future to the task executed by OSPRay OSPRAY_INTERFACE OSPFuture ospRenderFrame( OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld); // Ask if all events tracked by an OSPFuture handle have been completed OSPRAY_INTERFACE int ospIsReady( OSPFuture, OSPSyncEvent OSP_DEFAULT_VAL(OSP_TASK_FINISHED)); // Wait on a specific event OSPRAY_INTERFACE void ospWait( OSPFuture, OSPSyncEvent OSP_DEFAULT_VAL(OSP_TASK_FINISHED)); // Cancel the given task (may block calling thread) OSPRAY_INTERFACE void ospCancel(OSPFuture); // Get the completion state of the given task [0.f-1.f] OSPRAY_INTERFACE float ospGetProgress(OSPFuture); // Get the execution duration (in seconds) state of the given task OSPRAY_INTERFACE float ospGetTaskDuration(OSPFuture); typedef struct { int hasHit; float worldPosition[3]; OSPInstance instance; OSPGeometricModel model; uint32_t primID; } OSPPickResult; OSPRAY_INTERFACE void ospPick(OSPPickResult *result, OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld, float screenPos_x, float screenPos_y); #ifdef __cplusplus } // extern "C" #endif RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp.h000066400000000000000000000013571456566705700241620ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // \file ospray/ospray.h Defines the external OSPRay API */ // NOTE: this is a single include for all the C++ wrappers around ospray.h #include "ospray_cpp/Camera.h" #include "ospray_cpp/Data.h" #include "ospray_cpp/Device.h" #include "ospray_cpp/FrameBuffer.h" #include "ospray_cpp/Future.h" #include "ospray_cpp/GeometricModel.h" #include "ospray_cpp/Group.h" #include "ospray_cpp/ImageOperation.h" #include "ospray_cpp/Instance.h" #include "ospray_cpp/Light.h" #include "ospray_cpp/Material.h" #include "ospray_cpp/Renderer.h" #include "ospray_cpp/Texture.h" #include "ospray_cpp/TransferFunction.h" #include "ospray_cpp/VolumetricModel.h" #include "ospray_cpp/World.h" RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/000077500000000000000000000000001456566705700240035ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/Camera.h000066400000000000000000000013751456566705700253520ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ManagedObject.h" namespace ospray { namespace cpp { class Camera : public ManagedObject { public: Camera(const std::string &type); Camera(OSPCamera existing = nullptr); }; static_assert(sizeof(Camera) == sizeof(OSPCamera), "cpp::Camera can't have data members!"); // Inlined function definitions /////////////////////////////////////////// inline Camera::Camera(const std::string &type) { ospObject = ospNewCamera(type.c_str()); } inline Camera::Camera(OSPCamera existing) : ManagedObject(existing) {} } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::Camera, OSP_CAMERA); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/Data.h000066400000000000000000000162201456566705700250260ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ManagedObject.h" #include "Traits.h" // stl #include #include namespace ospray { namespace cpp { template class Data : public ManagedObject { public: // Construction from an existing array (explicit element type and size/stride) template Data(const void *init, OSPDataType type, const DIM_T &numItems); template Data(const void *init, OSPDataType type, const DIM_T &numItems, const DIM_T &byteStride); // Construction from an existing array (infer element type and size/stride) template Data(const T *init, const DIM_T &numItems); template Data(const T *init, const DIM_T &numItems, const DIM_T &byteStride); // Adapters to work with existing STL containers template Data(const std::array &arr); template Data(const std::vector &arr); // Set a single object as a 1-item data array template Data(const T &obj); // Construct from an existing OSPData handle (cpp::Data then owns handle) Data(OSPData existing = nullptr); protected: template void validate_element_type(); private: template void validate_dimension_type(); void constructArray(const void *init, OSPDataType type, uint64_t numItems1, int64_t byteStride1 = 0, uint64_t numItems2 = 1, int64_t byteStride2 = 0, uint64_t numItems3 = 1, int64_t byteStride3 = 0); }; using SharedData = Data; using CopiedData = Data; class MovedData : public SharedData { public: template MovedData(std::vector &arr); private: template static void vectorDeleter(const void *vec, const void *addr); }; static_assert( sizeof(Data<>) == sizeof(OSPData), "cpp::Data can't have data members!"); // Inlined function definitions /////////////////////////////////////////// template template inline Data::Data( const void *init, OSPDataType type, const DIM_T &numItems) : Data(init, type, numItems, DIM_T(0)) {} template template inline Data::Data(const void *init, OSPDataType format, const DIM_T &numItems, const DIM_T &byteStride) { validate_dimension_type(); constexpr auto dim_t = OSPTypeFor::value; constexpr auto nDims = OSPDimensionalityOf::value; using vec_element_t = typename OSPVecElementOf::type; const auto *d = (const vec_element_t *)&numItems; const auto *s = (const vec_element_t *)&byteStride; switch (nDims) { case 1: constructArray(init, format, d[0], s[0]); break; case 2: constructArray(init, format, d[0], s[0], d[1], s[1]); break; case 3: constructArray(init, format, d[0], s[0], d[1], s[1], d[2], s[2]); break; default: throw std::runtime_error("invalid dimension type constructing cpp::Data"); } } template template inline Data::Data(const T *init, const DIM_T &numItems) : Data(init, numItems, DIM_T(0)) {} template template inline Data::Data( const T *init, const DIM_T &numItems, const DIM_T &byteStride) { validate_element_type(); validate_dimension_type(); constexpr auto format = OSPTypeFor::value; constexpr auto dim_t = OSPTypeFor::value; constexpr auto nDims = OSPDimensionalityOf::value; using vec_element_t = typename OSPVecElementOf::type; const auto *d = (const vec_element_t *)&numItems; const auto *s = (const vec_element_t *)&byteStride; switch (nDims) { case 1: constructArray(init, format, d[0], s[0]); break; case 2: constructArray(init, format, d[0], s[0], d[1], s[1]); break; case 3: constructArray(init, format, d[0], s[0], d[1], s[1], d[2], s[2]); break; default: throw std::runtime_error("invalid dimension type constructing cpp::Data"); } } template template inline Data::Data(const std::array &arr) : Data(arr.data(), N) {} template template inline Data::Data(const std::vector &arr) : Data(arr.data(), arr.size()) {} template template inline Data::Data(const T &obj) : Data(&obj, size_t(1)) {} template inline Data::Data(OSPData existing) : ManagedObject(existing) {} template template inline void Data::validate_element_type() { static_assert(OSPTypeFor::value != OSP_UNKNOWN, "Only types corresponding to OSPDataType values can be set " "as elements in OSPRay Data arrays. NOTE: Math types (vec, " "box, linear, affine) must be inferable as OSP_* enums, which are " "defined by the OSPTYPEFOR_SPECIALIZATION() macro."); } template template inline void Data::validate_dimension_type() { static_assert(OSPTypeFor::value == OSP_INT || OSPTypeFor::value == OSP_VEC2I || OSPTypeFor::value == OSP_VEC3I || OSPTypeFor::value == OSP_ULONG || OSPTypeFor::value == OSP_VEC2UL || OSPTypeFor::value == OSP_VEC3UL, "The type used to describe an OSPData array dimensions must infer to " "OSP_INT, OSP_ULONG, OSP_VEC2UL, or OSP_VEC3UL. These type inferences " "are defined by using the OSPTYPEFOR_SPECIALIZATION() macro."); } template inline void Data::constructArray(const void *data, OSPDataType format, uint64_t numItems1, int64_t byteStride1, uint64_t numItems2, int64_t byteStride2, uint64_t numItems3, int64_t byteStride3) { OSPData tmp = ospNewSharedData(data, format, numItems1, byteStride1, numItems2, byteStride2, numItems3, byteStride3); if (SHARED) { ospObject = tmp; } else { ospObject = ospNewData(format, numItems1, numItems2, numItems3); ospCopyData(tmp, ospObject); ospRelease(tmp); } } template void MovedData::vectorDeleter(const void *vec, const void *addr) { auto *v = (std::vector *)vec; assert(v->data() == addr); (void)addr; delete v; } template inline MovedData::MovedData(std::vector &arr) { validate_element_type(); auto *donee = new std::vector(std::move(arr)); ospObject = ospNewSharedData(donee->data(), OSPTypeFor::value, donee->size(), 0, 1, 0, 1, 0, vectorDeleter, donee); } } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::SharedData, OSP_DATA); OSPTYPEFOR_SPECIALIZATION(cpp::CopiedData, OSP_DATA); OSPTYPEFOR_SPECIALIZATION(cpp::MovedData, OSP_DATA); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/Device.h000066400000000000000000000070531456566705700253600ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ospray/ospray.h" #include #include namespace ospray { namespace cpp { class Device { public: Device(const std::string &type = "cpu"); Device(const Device ©); Device(Device &&move); Device(OSPDevice existing = nullptr); ~Device(); Device &operator=(const Device ©); Device &operator=(Device &&move); template void setErrorCallback(FCN_T &&fcn); template void setStatusCallback(FCN_T &&fcn); template void setParam(const std::string &name, const T &v) const; void setParam(const std::string &name, const char *v) const; void setParam(const std::string &name, const std::string &v) const; void setParam(const std::string &name, OSPDataType, const void *) const; void removeParam(const std::string &name) const; void commit() const; void setCurrent() const; static Device current(); OSPDevice handle() const; private: OSPDevice ospHandle; }; // Inlined function definitions /////////////////////////////////////////// inline Device::Device(const std::string &type) { ospHandle = ospNewDevice(type.c_str()); } inline Device::Device(const Device ©) : ospHandle(copy.ospHandle) { ospDeviceRetain(copy.handle()); } inline Device::Device(Device &&move) { ospHandle = move.handle(); move.ospHandle = nullptr; } inline Device::Device(OSPDevice existing) : ospHandle(existing) {} inline Device::~Device() { ospDeviceRelease(ospHandle); } inline Device &Device::operator=(const Device ©) { ospDeviceRelease(ospHandle); ospHandle = copy.handle(); ospDeviceRetain(copy.handle()); return *this; } inline Device &Device::operator=(Device &&move) { ospDeviceRelease(ospHandle); ospHandle = move.handle(); move.ospHandle = nullptr; return *this; } template inline void Device::setErrorCallback(FCN_T &&fcn) { ospDeviceSetErrorCallback(ospHandle, std::forward(fcn), nullptr); } template inline void Device::setStatusCallback(FCN_T &&fcn) { ospDeviceSetStatusCallback(ospHandle, std::forward(fcn), nullptr); } template inline void Device::setParam(const std::string &name, const T &v) const { static_assert(OSPTypeFor::value != OSP_UNKNOWN, "Only types corresponding to OSPDataType values can be set " "as parameters on OSPRay objects. NOTE: Math types (vec, " "box, linear, affine) are " "expected to come from rkcommon::math."); ospDeviceSetParam(ospHandle, name.c_str(), OSPTypeFor::value, &v); } inline void Device::setParam(const std::string &name, const char *v) const { ospDeviceSetParam(ospHandle, name.c_str(), OSP_STRING, v); } inline void Device::setParam( const std::string &name, const std::string &v) const { ospDeviceSetParam(ospHandle, name.c_str(), OSP_STRING, v.c_str()); } inline void Device::setParam( const std::string &name, OSPDataType type, const void *mem) const { ospDeviceSetParam(ospHandle, name.c_str(), type, mem); } inline void Device::removeParam(const std::string &name) const { ospDeviceRemoveParam(ospHandle, name.c_str()); } inline void Device::commit() const { ospDeviceCommit(ospHandle); } inline void Device::setCurrent() const { ospSetCurrentDevice(ospHandle); } inline Device Device::current() { return Device(ospGetCurrentDevice()); } inline OSPDevice Device::handle() const { return ospHandle; } } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::Device, OSP_DEVICE); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/FrameBuffer.h000066400000000000000000000062501456566705700263430ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include "Camera.h" #include "Future.h" #include "GeometricModel.h" #include "Instance.h" #include "Renderer.h" #include "World.h" namespace ospray { namespace cpp { struct PickResult { bool hasHit{false}; float worldPosition[3]; Instance instance{(OSPInstance) nullptr}; GeometricModel model{(OSPGeometricModel) nullptr}; uint32_t primID{0}; }; class FrameBuffer : public ManagedObject { public: // NOTE(jda) - this does *not* create the underlying OSP object FrameBuffer() = default; FrameBuffer(int size_x, int size_y, OSPFrameBufferFormat format = OSP_FB_SRGBA, int channels = OSP_FB_COLOR); FrameBuffer(OSPFrameBuffer existing); void resetAccumulation() const; Future renderFrame( const Renderer &renderer, const Camera &camera, const World &world) const; PickResult pick(const Renderer &renderer, const Camera &camera, const World &world, float screenPos_x, float screenPos_y) const; void *map(OSPFrameBufferChannel channel) const; void unmap(void *ptr) const; void clear() const; float variance() const; }; static_assert(sizeof(FrameBuffer) == sizeof(OSPFrameBuffer), "cpp::FrameBuffer can't have data members!"); // Inlined function definitions /////////////////////////////////////////// inline FrameBuffer::FrameBuffer( int size_x, int size_y, OSPFrameBufferFormat format, int channels) { ospObject = ospNewFrameBuffer(size_x, size_y, format, channels); } inline FrameBuffer::FrameBuffer(OSPFrameBuffer existing) : ManagedObject(existing) {} inline void FrameBuffer::resetAccumulation() const { ospResetAccumulation(handle()); } inline Future FrameBuffer::renderFrame( const Renderer &renderer, const Camera &camera, const World &world) const { return ospRenderFrame( handle(), renderer.handle(), camera.handle(), world.handle()); } inline PickResult FrameBuffer::pick(const Renderer &renderer, const Camera &camera, const World &world, float screenPos_x, float screenPos_y) const { PickResult res; OSPPickResult pick; ospPick((OSPPickResult *)&pick, handle(), renderer.handle(), camera.handle(), world.handle(), screenPos_x, screenPos_y); if (pick.hasHit) { res.hasHit = true; res.instance = Instance(pick.instance); res.model = GeometricModel(pick.model); res.primID = pick.primID; res.worldPosition[0] = pick.worldPosition[0]; res.worldPosition[1] = pick.worldPosition[1]; res.worldPosition[2] = pick.worldPosition[2]; } return res; } inline void *FrameBuffer::map(OSPFrameBufferChannel channel) const { return const_cast(ospMapFrameBuffer(handle(), channel)); } inline void FrameBuffer::unmap(void *ptr) const { ospUnmapFrameBuffer(ptr, handle()); } inline void FrameBuffer::clear() const { ospResetAccumulation(handle()); } inline float FrameBuffer::variance() const { return ospGetVariance(handle()); } } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::FrameBuffer, OSP_FRAMEBUFFER); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/Future.h000066400000000000000000000021751456566705700254330ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ManagedObject.h" namespace ospray { namespace cpp { class Future : public ManagedObject { public: Future(OSPFuture existing = nullptr); bool isReady(OSPSyncEvent = OSP_TASK_FINISHED); void wait(OSPSyncEvent = OSP_TASK_FINISHED); void cancel(); float progress(); float duration(); }; static_assert(sizeof(Future) == sizeof(OSPFuture), "cpp::Future can't have data members!"); // Inlined function definitions /////////////////////////////////////////// inline Future::Future(OSPFuture existing) : ManagedObject(existing) {} inline bool Future::isReady(OSPSyncEvent e) { return ospIsReady(handle(), e); } inline void Future::wait(OSPSyncEvent e) { ospWait(handle(), e); } inline void Future::cancel() { ospCancel(handle()); } inline float Future::progress() { return ospGetProgress(handle()); } inline float Future::duration() { return ospGetTaskDuration(handle()); } } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::Future, OSP_FUTURE); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/GeometricModel.h000066400000000000000000000020321456566705700270500ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Geometry.h" #include "Material.h" namespace ospray { namespace cpp { class GeometricModel : public ManagedObject { public: GeometricModel(const Geometry &); GeometricModel(OSPGeometry); GeometricModel(OSPGeometricModel existing = nullptr); }; static_assert(sizeof(GeometricModel) == sizeof(OSPGeometricModel), "cpp::GeometricModel can't have data members!"); // Inlined function definitions /////////////////////////////////////////// inline GeometricModel::GeometricModel(const Geometry &geom) : GeometricModel(geom.handle()) {} inline GeometricModel::GeometricModel(OSPGeometry geom) { ospObject = ospNewGeometricModel(geom); } inline GeometricModel::GeometricModel(OSPGeometricModel existing) : ManagedObject(existing) {} } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::GeometricModel, OSP_GEOMETRIC_MODEL); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/Geometry.h000066400000000000000000000014431456566705700257510ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ManagedObject.h" namespace ospray { namespace cpp { class Geometry : public ManagedObject { public: Geometry(const std::string &type); Geometry(OSPGeometry existing = nullptr); }; static_assert(sizeof(Geometry) == sizeof(OSPGeometry), "cpp::Geometry can't have data members!"); // Inlined function definitions /////////////////////////////////////////// inline Geometry::Geometry(const std::string &type) { ospObject = ospNewGeometry(type.c_str()); } inline Geometry::Geometry(OSPGeometry existing) : ManagedObject(existing) {} } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::Geometry, OSP_GEOMETRY); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/Group.h000066400000000000000000000012471456566705700252540ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ManagedObject.h" namespace ospray { namespace cpp { class Group : public ManagedObject { public: Group(); Group(OSPGroup existing); }; static_assert( sizeof(Group) == sizeof(OSPGroup), "cpp::Group can't have data members!"); // Inlined function definitions /////////////////////////////////////////// inline Group::Group() { ospObject = ospNewGroup(); } inline Group::Group(OSPGroup existing) : ManagedObject(existing) {} } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::Group, OSP_GROUP); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/ImageOperation.h000066400000000000000000000016341456566705700270630ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ManagedObject.h" namespace ospray { namespace cpp { class ImageOperation : public ManagedObject { public: ImageOperation(const std::string &type); ImageOperation(OSPImageOperation existing = nullptr); }; static_assert(sizeof(ImageOperation) == sizeof(OSPImageOperation), "cpp::ImageOperation can't have data members!"); // Inlined function definitions /////////////////////////////////////////// inline ImageOperation::ImageOperation(const std::string &type) { ospObject = ospNewImageOperation(type.c_str()); } inline ImageOperation::ImageOperation(OSPImageOperation existing) : ManagedObject(existing) {} } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::ImageOperation, OSP_IMAGE_OPERATION); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/Instance.h000066400000000000000000000015431456566705700257230ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Group.h" namespace ospray { namespace cpp { class Instance : public ManagedObject { public: Instance(Group &group); Instance(OSPGroup group); Instance(OSPInstance existing = nullptr); }; static_assert(sizeof(Instance) == sizeof(OSPInstance), "cpp::Instance can't have data members!"); // Inlined function definitions /////////////////////////////////////////// inline Instance::Instance(Group &group) : Instance(group.handle()) {} inline Instance::Instance(OSPGroup group) { ospObject = ospNewInstance(group); } inline Instance::Instance(OSPInstance existing) : ManagedObject(existing) {} } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::Instance, OSP_INSTANCE); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/Light.h000066400000000000000000000013751456566705700252310ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ManagedObject.h" namespace ospray { namespace cpp { class Light : public ManagedObject { public: Light(const std::string &light_type); Light(OSPLight existing = nullptr); }; static_assert( sizeof(Light) == sizeof(OSPLight), "cpp::Light can't have data members!"); // Inlined function definitions /////////////////////////////////////////// inline Light::Light(const std::string &light_type) { ospObject = ospNewLight(light_type.c_str()); } inline Light::Light(OSPLight existing) : ManagedObject(existing) {} } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::Light, OSP_LIGHT); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/ManagedObject.h000066400000000000000000000124121456566705700266370ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // stl #include #include #include // ospray #include "ospray/ospray.h" // ospray::cpp #include "Traits.h" namespace ospray { namespace cpp { template class ManagedObject { public: static constexpr OSPDataType type = TYPE; ManagedObject(HANDLE_T object = nullptr); ~ManagedObject(); ManagedObject(const ManagedObject ©); ManagedObject(ManagedObject &&move); ManagedObject &operator=(const ManagedObject ©); ManagedObject &operator=(ManagedObject &&move); template void setParam(const std::string &name, const T &v) const; void setParam(const std::string &name, const char *v) const; void setParam(const std::string &name, const std::string &v) const; void setParam(const std::string &name, OSPDataType, const void *) const; void removeParam(const std::string &name) const; template BOX3F_T getBounds() const; void commit() const; //! Get the underlying specific OSP* handle HANDLE_T handle() const; //! return whether the given object is valid, or NULL operator bool() const; protected: HANDLE_T ospObject; }; // Inlined function definitions /////////////////////////////////////////// template inline ManagedObject::ManagedObject(HANDLE_T object) : ospObject(object) { using OSPObject_T = typename std::remove_pointer::type; using OtherOSP_T = typename std::remove_pointer::type; static_assert(std::is_same::value || std::is_base_of::value, "ManagedObject can only be instantiated with " "OSPObject (a.k.a. osp::ManagedObject*) or one of its" "descendants (a.k.a. the OSP* family of types)."); } template inline ManagedObject::~ManagedObject() { ospRelease(ospObject); } template inline ManagedObject::ManagedObject( const ManagedObject ©) : ospObject(copy.ospObject) { if (copy.handle()) ospRetain(copy.handle()); } template inline ManagedObject::ManagedObject( ManagedObject &&move) { ospObject = move.handle(); move.ospObject = nullptr; } template inline ManagedObject &ManagedObject::operator=( const ManagedObject ©) { ospRelease(ospObject); ospObject = copy.handle(); if (copy.handle()) ospRetain(copy.handle()); return *this; } template inline ManagedObject &ManagedObject::operator=( ManagedObject &&move) { ospRelease(ospObject); ospObject = move.handle(); move.ospObject = nullptr; return *this; } template template inline void ManagedObject::setParam( const std::string &name, const T &v) const { static_assert(OSPTypeFor::value != OSP_UNKNOWN, "Only types corresponding to OSPDataType values can be set " "as parameters on OSPRay objects. NOTE: Math types (vec, " "box, linear, affine) are " "expected to come from rkcommon::math."); ospSetParam(ospObject, name.c_str(), OSPTypeFor::value, &v); } template inline void ManagedObject::setParam( const std::string &name, const char *v) const { ospSetParam(ospObject, name.c_str(), OSP_STRING, v); } template inline void ManagedObject::setParam( const std::string &name, const std::string &v) const { ospSetParam(ospObject, name.c_str(), OSP_STRING, v.c_str()); } template inline void ManagedObject::setParam( const std::string &name, OSPDataType type, const void *mem) const { ospSetParam(ospObject, name.c_str(), type, mem); } template inline void ManagedObject::removeParam( const std::string &name) const { ospRemoveParam(ospObject, name.c_str()); } template template BOX3F_T ManagedObject::getBounds() const { static_assert(OSPTypeFor::value == OSP_BOX3F, "Your type for BOX3F_T must convert to OSP_BOX3F. You need to define" " this conversion via the OSPTYPEFOR_SPECIALIZATION macro."); auto b = ospGetBounds(ospObject); return *((BOX3F_T *)&b); } template inline void ManagedObject::commit() const { ospCommit(ospObject); } template inline HANDLE_T ManagedObject::handle() const { return ospObject; } template inline ManagedObject::operator bool() const { return handle() != nullptr; } } // namespace cpp } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/Material.h000066400000000000000000000014571456566705700257210ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ManagedObject.h" namespace ospray { namespace cpp { class Material : public ManagedObject { public: Material(const std::string &mat_type); Material(OSPMaterial existing = nullptr); }; static_assert(sizeof(Material) == sizeof(OSPMaterial), "cpp::Material can't have data members!"); // Inlined function definitions /////////////////////////////////////////// inline Material::Material(const std::string &mat_type) { ospObject = ospNewMaterial(mat_type.c_str()); } inline Material::Material(OSPMaterial existing) : ManagedObject(existing) {} } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::Material, OSP_MATERIAL); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/Renderer.h000066400000000000000000000014431456566705700257240ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ManagedObject.h" namespace ospray { namespace cpp { class Renderer : public ManagedObject { public: Renderer(const std::string &type); Renderer(OSPRenderer existing = nullptr); }; static_assert(sizeof(Renderer) == sizeof(OSPRenderer), "cpp::Renderer can't have data members!"); // Inlined function definitions /////////////////////////////////////////// inline Renderer::Renderer(const std::string &type) { ospObject = ospNewRenderer(type.c_str()); } inline Renderer::Renderer(OSPRenderer existing) : ManagedObject(existing) {} } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::Renderer, OSP_RENDERER); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/Texture.h000066400000000000000000000014201456566705700256110ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ManagedObject.h" namespace ospray { namespace cpp { class Texture : public ManagedObject { public: Texture(const std::string &type); Texture(OSPTexture existing = nullptr); }; static_assert(sizeof(Texture) == sizeof(OSPTexture), "cpp::Texture can't have data members!"); // Inlined function definitions /////////////////////////////////////////// inline Texture::Texture(const std::string &type) { ospObject = ospNewTexture(type.c_str()); } inline Texture::Texture(OSPTexture existing) : ManagedObject(existing) {} } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::Texture, OSP_TEXTURE); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/Traits.h000066400000000000000000000225461456566705700254330ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // ospray #include "ospray/ospray.h" namespace ospray { // Infer (compile time) OSP_DATA_TYPE from input type ///////////////////////// template struct OSPTypeFor { static constexpr OSPDataType value = OSP_UNKNOWN; }; #define OSPTYPEFOR_SPECIALIZATION(type, osp_type) \ template <> \ struct OSPTypeFor \ { \ static constexpr OSPDataType value = osp_type; \ }; OSPTYPEFOR_SPECIALIZATION(void *, OSP_VOID_PTR); OSPTYPEFOR_SPECIALIZATION(char *, OSP_STRING); OSPTYPEFOR_SPECIALIZATION(const char *, OSP_STRING); OSPTYPEFOR_SPECIALIZATION(const char[], OSP_STRING); OSPTYPEFOR_SPECIALIZATION(bool, OSP_BOOL); OSPTYPEFOR_SPECIALIZATION(char, OSP_CHAR); OSPTYPEFOR_SPECIALIZATION(unsigned char, OSP_UCHAR); OSPTYPEFOR_SPECIALIZATION(short, OSP_SHORT); OSPTYPEFOR_SPECIALIZATION(unsigned short, OSP_USHORT); OSPTYPEFOR_SPECIALIZATION(int, OSP_INT); OSPTYPEFOR_SPECIALIZATION(unsigned int, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(long, OSP_LONG); OSPTYPEFOR_SPECIALIZATION(unsigned long, OSP_ULONG); OSPTYPEFOR_SPECIALIZATION(long long, OSP_LONG); OSPTYPEFOR_SPECIALIZATION(unsigned long long, OSP_ULONG); OSPTYPEFOR_SPECIALIZATION(float, OSP_FLOAT); OSPTYPEFOR_SPECIALIZATION(double, OSP_DOUBLE); OSPTYPEFOR_SPECIALIZATION(OSPObject, OSP_OBJECT); OSPTYPEFOR_SPECIALIZATION(OSPCamera, OSP_CAMERA); OSPTYPEFOR_SPECIALIZATION(OSPData, OSP_DATA); OSPTYPEFOR_SPECIALIZATION(OSPFrameBuffer, OSP_FRAMEBUFFER); OSPTYPEFOR_SPECIALIZATION(OSPFuture, OSP_FUTURE); OSPTYPEFOR_SPECIALIZATION(OSPGeometricModel, OSP_GEOMETRIC_MODEL); OSPTYPEFOR_SPECIALIZATION(OSPGeometry, OSP_GEOMETRY); OSPTYPEFOR_SPECIALIZATION(OSPGroup, OSP_GROUP); OSPTYPEFOR_SPECIALIZATION(OSPImageOperation, OSP_IMAGE_OPERATION); OSPTYPEFOR_SPECIALIZATION(OSPInstance, OSP_INSTANCE); OSPTYPEFOR_SPECIALIZATION(OSPLight, OSP_LIGHT); OSPTYPEFOR_SPECIALIZATION(OSPMaterial, OSP_MATERIAL); OSPTYPEFOR_SPECIALIZATION(OSPRenderer, OSP_RENDERER); OSPTYPEFOR_SPECIALIZATION(OSPTexture, OSP_TEXTURE); OSPTYPEFOR_SPECIALIZATION(OSPTransferFunction, OSP_TRANSFER_FUNCTION); OSPTYPEFOR_SPECIALIZATION(OSPVolume, OSP_VOLUME); OSPTYPEFOR_SPECIALIZATION(OSPVolumetricModel, OSP_VOLUMETRIC_MODEL); OSPTYPEFOR_SPECIALIZATION(OSPWorld, OSP_WORLD); OSPTYPEFOR_SPECIALIZATION(OSPLogLevel, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPDeviceProperty, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPDataType, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPTextureFormat, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPTextureFilter, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPTextureWrapMode, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPError, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPFrameBufferFormat, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPFrameBufferChannel, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPSyncEvent, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPUnstructuredCellType, OSP_UCHAR); OSPTYPEFOR_SPECIALIZATION(OSPStereoMode, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPShutterType, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPCurveType, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPCurveBasis, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPSubdivisionMode, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPAMRMethod, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPVolumeFilter, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPVolumeFormat, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPPixelFilterType, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPIntensityQuantity, OSP_UINT); OSPTYPEFOR_SPECIALIZATION(OSPSphereType, OSP_UINT); #define OSPTYPEFOR_DEFINITION(type) \ constexpr OSPDataType OSPTypeFor::value // Infer element type from OSP_* vec types input type ///////////////////////// template struct OSPVecElementOf { using type = void; }; #define OSPVECELEMENTOF_SPECIALIZATION(osp_type, out_type) \ template <> \ struct OSPVecElementOf \ { \ using type = out_type; \ }; OSPVECELEMENTOF_SPECIALIZATION(OSP_UCHAR, unsigned char); OSPVECELEMENTOF_SPECIALIZATION(OSP_INT, int32_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_UINT, uint32_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_LONG, int64_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_ULONG, uint64_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_FLOAT, float); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC2UC, unsigned char); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC3UC, unsigned char); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC4UC, unsigned char); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC2C, char); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC3C, char); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC4C, char); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC2S, short); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC3S, short); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC4S, short); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC2US, unsigned short); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC3US, unsigned short); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC4US, unsigned short); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC2I, int32_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC3I, int32_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC4I, int32_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC2UI, uint32_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC3UI, uint32_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC4UI, uint32_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC2L, int64_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC3L, int64_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC4L, int64_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC2UL, uint64_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC3UL, uint64_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC4UL, uint64_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC2F, float); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC3F, float); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC4F, float); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC2D, double); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC3D, double); OSPVECELEMENTOF_SPECIALIZATION(OSP_VEC4D, double); OSPVECELEMENTOF_SPECIALIZATION(OSP_BOX1I, int32_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_BOX2I, int32_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_BOX3I, int32_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_BOX4I, int32_t); OSPVECELEMENTOF_SPECIALIZATION(OSP_BOX1F, float); OSPVECELEMENTOF_SPECIALIZATION(OSP_BOX2F, float); OSPVECELEMENTOF_SPECIALIZATION(OSP_BOX3F, float); OSPVECELEMENTOF_SPECIALIZATION(OSP_BOX4F, float); // Infer OSPDataType dimensionality /////////////////////////////////////////// template struct OSPDimensionalityOf { static constexpr int value = 1; }; #define OSPDIMENSIONALITYOF_SPECIALIZATION(osp_type, out_value) \ template <> \ struct OSPDimensionalityOf \ { \ static constexpr int value = out_value; \ }; OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC2UC, 2); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC3UC, 3); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC4UC, 4); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC2C, 2); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC3C, 3); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC4C, 4); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC2S, 2); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC3S, 3); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC4S, 4); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC2US, 2); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC3US, 3); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC4US, 4); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC2I, 2); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC3I, 3); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC4I, 4); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC2UI, 2); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC3UI, 3); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC4UI, 4); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC2L, 2); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC3L, 3); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC4L, 4); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC2UL, 2); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC3UL, 3); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC4UL, 4); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC2H, 2); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC3H, 3); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC4H, 4); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC2F, 2); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC3F, 3); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC4F, 4); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC2D, 2); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC3D, 3); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_VEC4D, 4); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_BOX1I, 1); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_BOX2I, 2); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_BOX3I, 3); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_BOX4I, 4); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_BOX1F, 1); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_BOX2F, 2); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_BOX3F, 3); OSPDIMENSIONALITYOF_SPECIALIZATION(OSP_BOX4F, 4); #define OSPDIMENSIONALITYOF_DEFINITION(type) \ constexpr int OSPDimensionalityOf::value } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/TransferFunction.h000066400000000000000000000017021456566705700274460ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ManagedObject.h" namespace ospray { namespace cpp { class TransferFunction : public ManagedObject { public: TransferFunction(const std::string &type); TransferFunction(OSPTransferFunction existing = nullptr); }; static_assert(sizeof(TransferFunction) == sizeof(OSPTransferFunction), "cpp::TransferFunction can't have data members!"); // Inlined function definitions /////////////////////////////////////////// inline TransferFunction::TransferFunction(const std::string &type) { ospObject = ospNewTransferFunction(type.c_str()); } inline TransferFunction::TransferFunction(OSPTransferFunction existing) : ManagedObject(existing) {} } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::TransferFunction, OSP_TRANSFER_FUNCTION); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/Volume.h000066400000000000000000000014171456566705700254260ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include #include "ManagedObject.h" namespace ospray { namespace cpp { class Volume : public ManagedObject { public: Volume(const std::string &type); Volume(OSPVolume existing = nullptr); }; static_assert(sizeof(Volume) == sizeof(OSPVolume), "cpp::Volume can't have data members!"); // Inlined function definitions /////////////////////////////////////////// inline Volume::Volume(const std::string &type) { ospObject = ospNewVolume(type.c_str()); } inline Volume::Volume(OSPVolume existing) : ManagedObject(existing) {} } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::Volume, OSP_VOLUME); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/VolumetricModel.h000066400000000000000000000020531456566705700272660ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "TransferFunction.h" #include "Volume.h" namespace ospray { namespace cpp { class VolumetricModel : public ManagedObject { public: VolumetricModel(const Volume &); VolumetricModel(OSPVolume); VolumetricModel(OSPVolumetricModel existing = nullptr); }; static_assert(sizeof(VolumetricModel) == sizeof(OSPVolumetricModel), "cpp::VolumetricModel can't have data members!"); // Inlined function definitions /////////////////////////////////////////// inline VolumetricModel::VolumetricModel(const Volume &vol) : VolumetricModel(vol.handle()) {} inline VolumetricModel::VolumetricModel(OSPVolume vol) { ospObject = ospNewVolumetricModel(vol); } inline VolumetricModel::VolumetricModel(OSPVolumetricModel existing) : ManagedObject(existing) {} } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::VolumetricModel, OSP_VOLUMETRIC_MODEL); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/World.h000066400000000000000000000012751456566705700252500ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Instance.h" #include "ManagedObject.h" namespace ospray { namespace cpp { class World : public ManagedObject { public: World(); World(OSPWorld existing); }; static_assert( sizeof(World) == sizeof(OSPWorld), "cpp::World can't have data members!"); // Inlined function definitions /////////////////////////////////////////// inline World::World() { ospObject = ospNewWorld(); } inline World::World(OSPWorld existing) : ManagedObject(existing) {} } // namespace cpp OSPTYPEFOR_SPECIALIZATION(cpp::World, OSP_WORLD); } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/ext/000077500000000000000000000000001456566705700246035ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/ext/glm.h000066400000000000000000000027461456566705700255440ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // glm #include "glm/vec2.hpp" #include "glm/vec3.hpp" #include "glm/vec4.hpp" #include "glm/mat2x2.hpp" #include "glm/mat3x2.hpp" #include "glm/mat3x3.hpp" #include "glm/mat4x3.hpp" // ospray #include "../Traits.h" namespace ospray { OSPTYPEFOR_SPECIALIZATION(glm::vec2, OSP_VEC2F); OSPTYPEFOR_SPECIALIZATION(glm::vec3, OSP_VEC3F); OSPTYPEFOR_SPECIALIZATION(glm::vec4, OSP_VEC4F); OSPTYPEFOR_SPECIALIZATION(glm::ivec2, OSP_VEC2I); OSPTYPEFOR_SPECIALIZATION(glm::ivec3, OSP_VEC3I); OSPTYPEFOR_SPECIALIZATION(glm::ivec4, OSP_VEC4I); OSPTYPEFOR_SPECIALIZATION(glm::uvec2, OSP_VEC2UI); OSPTYPEFOR_SPECIALIZATION(glm::uvec3, OSP_VEC3UI); OSPTYPEFOR_SPECIALIZATION(glm::uvec4, OSP_VEC4UI); OSPTYPEFOR_SPECIALIZATION(glm::mat2x2, OSP_LINEAR2F); OSPTYPEFOR_SPECIALIZATION(glm::mat3x3, OSP_LINEAR3F); OSPTYPEFOR_SPECIALIZATION(glm::mat3x2, OSP_AFFINE2F); OSPTYPEFOR_SPECIALIZATION(glm::mat4x3, OSP_AFFINE3F); #ifdef OSPRAY_GLM_DEFINITIONS OSPTYPEFOR_DEFINITION(glm::vec2); OSPTYPEFOR_DEFINITION(glm::vec3); OSPTYPEFOR_DEFINITION(glm::vec4); OSPTYPEFOR_DEFINITION(glm::ivec2); OSPTYPEFOR_DEFINITION(glm::ivec3); OSPTYPEFOR_DEFINITION(glm::ivec4); OSPTYPEFOR_DEFINITION(glm::uvec2); OSPTYPEFOR_DEFINITION(glm::uvec3); OSPTYPEFOR_DEFINITION(glm::uvec4); OSPTYPEFOR_DEFINITION(glm::mat2x2); OSPTYPEFOR_DEFINITION(glm::mat3x3); OSPTYPEFOR_DEFINITION(glm::mat3x2); OSPTYPEFOR_DEFINITION(glm::mat4x3); #endif } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_cpp/ext/rkcommon.h000066400000000000000000000115451456566705700266070ustar00rootroot00000000000000// Copyright 2020 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once // rkcommon #include "rkcommon/math/AffineSpace.h" #include "rkcommon/math/box.h" // ospray #include "../Traits.h" namespace ospray { OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec2uc, OSP_VEC2UC); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec3uc, OSP_VEC3UC); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec4uc, OSP_VEC4UC); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec2c, OSP_VEC2C); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec3c, OSP_VEC3C); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec4c, OSP_VEC4C); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec2us, OSP_VEC2US); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec3us, OSP_VEC3US); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec4us, OSP_VEC4US); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec2s, OSP_VEC2S); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec3s, OSP_VEC3S); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec4s, OSP_VEC4S); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec2i, OSP_VEC2I); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec3i, OSP_VEC3I); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec4i, OSP_VEC4I); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec2ui, OSP_VEC2UI); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec3ui, OSP_VEC3UI); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec4ui, OSP_VEC4UI); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec2l, OSP_VEC2L); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec3l, OSP_VEC3L); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec4l, OSP_VEC4L); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec2ul, OSP_VEC2UL); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec3ul, OSP_VEC3UL); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec4ul, OSP_VEC4UL); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec2f, OSP_VEC2F); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec3f, OSP_VEC3F); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec4f, OSP_VEC4F); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec2d, OSP_VEC2D); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec3d, OSP_VEC3D); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::vec4d, OSP_VEC4D); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::box1i, OSP_BOX1I); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::box2i, OSP_BOX2I); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::box3i, OSP_BOX3I); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::box4i, OSP_BOX4I); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::box1f, OSP_BOX1F); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::box2f, OSP_BOX2F); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::box3f, OSP_BOX3F); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::box4f, OSP_BOX4F); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::linear2f, OSP_LINEAR2F); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::linear3f, OSP_LINEAR3F); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::affine2f, OSP_AFFINE2F); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::affine3f, OSP_AFFINE3F); OSPTYPEFOR_SPECIALIZATION(rkcommon::math::quatf, OSP_QUATF); #ifdef OSPRAY_RKCOMMON_DEFINITIONS OSPTYPEFOR_DEFINITION(rkcommon::math::vec2uc); OSPTYPEFOR_DEFINITION(rkcommon::math::vec3uc); OSPTYPEFOR_DEFINITION(rkcommon::math::vec4uc); OSPTYPEFOR_DEFINITION(rkcommon::math::vec2c); OSPTYPEFOR_DEFINITION(rkcommon::math::vec3c); OSPTYPEFOR_DEFINITION(rkcommon::math::vec4c); OSPTYPEFOR_DEFINITION(rkcommon::math::vec2us); OSPTYPEFOR_DEFINITION(rkcommon::math::vec3us); OSPTYPEFOR_DEFINITION(rkcommon::math::vec4us); OSPTYPEFOR_DEFINITION(rkcommon::math::vec2s); OSPTYPEFOR_DEFINITION(rkcommon::math::vec3s); OSPTYPEFOR_DEFINITION(rkcommon::math::vec4s); OSPTYPEFOR_DEFINITION(rkcommon::math::vec2i); OSPTYPEFOR_DEFINITION(rkcommon::math::vec3i); OSPTYPEFOR_DEFINITION(rkcommon::math::vec4i); OSPTYPEFOR_DEFINITION(rkcommon::math::vec2ui); OSPTYPEFOR_DEFINITION(rkcommon::math::vec3ui); OSPTYPEFOR_DEFINITION(rkcommon::math::vec4ui); OSPTYPEFOR_DEFINITION(rkcommon::math::vec2l); OSPTYPEFOR_DEFINITION(rkcommon::math::vec3l); OSPTYPEFOR_DEFINITION(rkcommon::math::vec4l); OSPTYPEFOR_DEFINITION(rkcommon::math::vec2ul); OSPTYPEFOR_DEFINITION(rkcommon::math::vec3ul); OSPTYPEFOR_DEFINITION(rkcommon::math::vec4ul); OSPTYPEFOR_DEFINITION(rkcommon::math::vec2f); OSPTYPEFOR_DEFINITION(rkcommon::math::vec3f); OSPTYPEFOR_DEFINITION(rkcommon::math::vec4f); OSPTYPEFOR_DEFINITION(rkcommon::math::vec2d); OSPTYPEFOR_DEFINITION(rkcommon::math::vec3d); OSPTYPEFOR_DEFINITION(rkcommon::math::vec4d); OSPTYPEFOR_DEFINITION(rkcommon::math::box1i); OSPTYPEFOR_DEFINITION(rkcommon::math::box2i); OSPTYPEFOR_DEFINITION(rkcommon::math::box3i); OSPTYPEFOR_DEFINITION(rkcommon::math::box4i); OSPTYPEFOR_DEFINITION(rkcommon::math::box1f); OSPTYPEFOR_DEFINITION(rkcommon::math::box2f); OSPTYPEFOR_DEFINITION(rkcommon::math::box3f); OSPTYPEFOR_DEFINITION(rkcommon::math::box4f); OSPTYPEFOR_DEFINITION(rkcommon::math::linear2f); OSPTYPEFOR_DEFINITION(rkcommon::math::linear3f); OSPTYPEFOR_DEFINITION(rkcommon::math::affine2f); OSPTYPEFOR_DEFINITION(rkcommon::math::affine3f); OSPTYPEFOR_DEFINITION(rkcommon::math::quatf); #endif } // namespace ospray RenderKit-ospray-f2a61c2/ospray/include/ospray/ospray_util.h000066400000000000000000000065421456566705700243560ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #pragma once #include "ospray.h" #ifdef __cplusplus extern "C" { #endif // OSPData helpers ////////////////////////////////////////////////////////// OSPRAY_INTERFACE OSPData ospNewSharedData1D( const void *sharedData, OSPDataType, uint64_t numItems); OSPRAY_INTERFACE OSPData ospNewAssignedData1D(const void *sharedData, OSPDataType, uint64_t numItems, OSPDeleterCallback, const void *userPtr); OSPRAY_INTERFACE OSPData ospNewSharedData1DStride( const void *sharedData, OSPDataType, uint64_t numItems, int64_t byteStride); OSPRAY_INTERFACE OSPData ospNewSharedData2D(const void *sharedData, OSPDataType, uint64_t numItems1, uint64_t numItems2); OSPRAY_INTERFACE OSPData ospNewSharedData2DStride(const void *sharedData, OSPDataType, uint64_t numItems1, int64_t byteStride1, uint64_t numItems2, int64_t byteStride2); OSPRAY_INTERFACE OSPData ospNewSharedData3D(const void *sharedData, OSPDataType, uint64_t numItems1, uint64_t numItems2, uint64_t numItems3); OSPRAY_INTERFACE OSPData ospNewData1D(OSPDataType, uint64_t numItems); OSPRAY_INTERFACE OSPData ospNewData2D( OSPDataType, uint64_t numItems1, uint64_t numItems2); OSPRAY_INTERFACE void ospCopyData1D( const OSPData source, OSPData destination, uint64_t destinationIndex); OSPRAY_INTERFACE void ospCopyData2D(const OSPData source, OSPData destination, uint64_t destinationIndex1, uint64_t destinationIndex2); // Parameter helpers ////////////////////////////////////////////////////////// OSPRAY_INTERFACE void ospSetString(OSPObject, const char *n, const char *s); OSPRAY_INTERFACE void ospSetObject(OSPObject, const char *n, OSPObject obj); OSPRAY_INTERFACE void ospSetBool(OSPObject, const char *n, int x); OSPRAY_INTERFACE void ospSetFloat(OSPObject, const char *n, float x); OSPRAY_INTERFACE void ospSetInt(OSPObject, const char *n, int x); OSPRAY_INTERFACE void ospSetUInt(OSPObject, const char *n, unsigned int x); OSPRAY_INTERFACE void ospSetBox1f(OSPObject, const char *n, float x, float y); // clang-format off OSPRAY_INTERFACE void ospSetLinear2f(OSPObject, const char *n, float x, float y, float z, float w); OSPRAY_INTERFACE void ospSetVec2f(OSPObject, const char *n, float x, float y); OSPRAY_INTERFACE void ospSetVec3f(OSPObject, const char *n, float x, float y, float z); OSPRAY_INTERFACE void ospSetVec4f(OSPObject, const char *n, float x, float y, float z, float w); OSPRAY_INTERFACE void ospSetVec2i(OSPObject, const char *n, int x, int y); OSPRAY_INTERFACE void ospSetVec3i(OSPObject, const char *n, int x, int y, int z); OSPRAY_INTERFACE void ospSetVec4i(OSPObject, const char *n, int x, int y, int z, int w); // Take 'obj' and put it in an opaque OSPData array with given element type, then set on 'target' OSPRAY_INTERFACE void ospSetObjectAsData(OSPObject target, const char *n, OSPDataType, OSPObject obj); // clang-format on // Rendering helpers ////////////////////////////////////////////////////////// // Start a frame task and immediately wait on it, return frame buffer varaince OSPRAY_INTERFACE float ospRenderFrameBlocking( OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld); #ifdef __cplusplus } // extern "C" #endif RenderKit-ospray-f2a61c2/ospray/ospray.rc000066400000000000000000000036201456566705700205300ustar00rootroot00000000000000ÿþ// Copyright 2016 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #include "ospray/version.h" 1 VERSIONINFO FILEVERSION OSPRAY_VERSION_MAJOR,OSPRAY_VERSION_MINOR,OSPRAY_VERSION_PATCH,0 PRODUCTVERSION OSPRAY_VERSION_MAJOR,OSPRAY_VERSION_MINOR,OSPRAY_VERSION_PATCH,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x40004L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Intel" VALUE "FileDescription", "OSPRay Ray Tracing Rendering Engine" VALUE "FileVersion", OSPRAY_VERSION VALUE "ProductVersion", OSPRAY_VERSION VALUE "LegalCopyright", "© 2009 Intel Corporation" VALUE "InternalName", "OSPRay" VALUE "ProductName", "Intel® OSPRay" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END RenderKit-ospray-f2a61c2/ospray/version.h.in000066400000000000000000000006541456566705700211340ustar00rootroot00000000000000// Copyright 2009 Intel Corporation // SPDX-License-Identifier: Apache-2.0 #define OSPRAY_VERSION_MAJOR @OSPRAY_VERSION_MAJOR@ #define OSPRAY_VERSION_MINOR @OSPRAY_VERSION_MINOR@ #define OSPRAY_VERSION_PATCH @OSPRAY_VERSION_PATCH@ #define OSPRAY_SOVERSION @OSPRAY_SOVERSION@ #define OSPRAY_VERSION_GITHASH "@OSPRAY_VERSION_GITHASH@" #define OSPRAY_VERSION_NOTE "@OSPRAY_VERSION_NOTE@" #define OSPRAY_VERSION "@OSPRAY_VERSION@" RenderKit-ospray-f2a61c2/scripts/000077500000000000000000000000001456566705700170365ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/scripts/build/000077500000000000000000000000001456566705700201355ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/scripts/build/linux.sh000077500000000000000000000003541456566705700216350ustar00rootroot00000000000000#!/usr/bin/env bash ## Copyright 2015 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set -ex mkdir build cd build cmake --version cmake -L \ -D CMAKE_INSTALL_LIBDIR=lib \ "$@" \ ../scripts/superbuild cmake --build . RenderKit-ospray-f2a61c2/scripts/build/macosx.sh000077700000000000000000000000001456566705700234512linux.shustar00rootroot00000000000000RenderKit-ospray-f2a61c2/scripts/build/win.ps1000077500000000000000000000006451456566705700213670ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 Param( [string] $G = 'Ninja', [ValidateSet('Release', 'RelWithDebInfo', 'Debug')][string] $buildType = 'Release' ) md build cd build cmake --version cmake -L ` -G $G ` $args ` -D CMAKE_BUILD_TYPE=$buildType ` -D DEPENDENCIES_BUILD_TYPE=$buildType ` ../scripts/superbuild cmake --build . --config $buildType exit $LASTEXITCODE RenderKit-ospray-f2a61c2/scripts/files-to-md5.sh000077500000000000000000000030311456566705700215770ustar00rootroot00000000000000#!/bin/bash ## Copyright 2017 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # This script should be called from build directory (OSPRay root should be in ../) # # Usage: # export BASELINE_OUTPUT_DIR=user@machine-name:/target/path # export BASELINE_MD5_OUTPUT_DIR=/dir/with/md5/hashes # export BASELINE_INPUT_IMAGES_DIR=/dir/with/files/to/be/synced # ../scripts/files-to-md5.sh md5 () { md5sum $1 | awk '{print $1 }' } if [[ ! $BASELINE_OUTPUT_DIR ]] then echo "Please set BASELINE_OUTPUT_DIR env variable" exit 1 fi if [[ ! $BASELINE_MD5_OUTPUT_DIR ]] then echo "Please set BASELINE_MD5_OUTPUT_DIR env variable" exit 1 fi if [[ ! $BASELINE_INPUT_IMAGES_DIR ]] then echo "Please set BASELINE_INPUT_IMAGES_DIR env variable" exit 1 fi LOCAL_TMP_DIR=/tmp/ospray-tmp-data # Remove any old files (whole directory) rm -rf $LOCAL_TMP_DIR # Create this directory again mkdir $LOCAL_TMP_DIR # From now on any command should stop executing script set -e for FILE in $BASELINE_INPUT_IMAGES_DIR/*; do # Copy file to local tmp directory with new name (based on md5 from this img) cp $FILE $LOCAL_TMP_DIR/`md5 $FILE` # Create/Filll metadata file in ospray repo # so we can link img in remote repo by this md5 string md5 $FILE > $BASELINE_MD5_OUTPUT_DIR/`basename $FILE`.md5 done # Copy all files (only when there is need to update) to target CI machine rsync --progress -au --no-o --no-g $LOCAL_TMP_DIR/* $BASELINE_OUTPUT_DIR # Another cleanup - we don't want to leave any files locally rm -rf $LOCAL_TMP_DIR/* RenderKit-ospray-f2a61c2/scripts/install_linux_gcc.sh000077500000000000000000000023441456566705700231010ustar00rootroot00000000000000#!/bin/bash ## Copyright 2014 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 dest=$HOME/devtools-2 arch=`arch` major=`rpm -q --qf "%{VERSION}" $(rpm -q --whatprovides redhat-release)` source_url=http://people.centos.org/tru/devtools-2/$major/$arch/RPMS usr_path="$HOME/devtools-2/opt/rh/devtoolset-2/root/usr" packages="\ devtoolset-2-binutils \ devtoolset-2-gcc \ devtoolset-2-libstdc++-devel \ devtoolset-2-gcc-c++ \ " echo Installing gcc in $dest pushd . > /dev/null mkdir -p $dest cd $dest echo .fetching RPM list wget -cq $source_url/repodata/primary.xml.gz gunzip -c primary.xml.gz > primary.xml for package in $packages ; do echo .looking for $package p=`grep -A 29 "^$package" primary.xml | grep -B 29 '' | sed -e "s@.*.*@\1@;ty;d;:y" | sort -g | tail -n 1` echo ...fetching $p wget -cq $source_url/$p echo ...installing $p rpm2cpio $p | cpio -idu --quiet done popd > /dev/null export PATH="$usr_path/bin":$PATH export LD_LIBRARY_PATH="$usr_path/lib64":$LD_LIBRARY_PATH echo Installation finished. To use gcc of devtoolset-2 be sure to keep \""$usr_path/bin"\" in your \$PATH and \""$usr_path/lib64"\" in your \$LD_LIBRARY_PATH. RenderKit-ospray-f2a61c2/scripts/release/000077500000000000000000000000001456566705700204565ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/scripts/release/linux.sh000077500000000000000000000073451456566705700221650ustar00rootroot00000000000000#!/bin/bash ## Copyright 2014 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 #### Helper functions #### function check_symbols { for sym in `nm $1 | grep $2_` do version=(`echo $sym | sed 's/.*@@\(.*\)$/\1/g' | grep -E -o "[0-9]+"`) if [ ${#version[@]} -ne 0 ]; then if [ ${#version[@]} -eq 1 ]; then version[1]=0; fi if [ ${#version[@]} -eq 2 ]; then version[2]=0; fi if [ ${version[0]} -gt $3 ]; then echo "Error: problematic $2 symbol " $sym exit 1 fi if [ ${version[0]} -lt $3 ]; then continue; fi if [ ${version[1]} -gt $4 ]; then echo "Error: problematic $2 symbol " $sym exit 1 fi if [ ${version[1]} -lt $4 ]; then continue; fi if [ ${version[2]} -gt $5 ]; then echo "Error: problematic $2 symbol " $sym exit 1 fi fi done } function check_lib_dependency_error { for lib in "$1" do if [ -n "`ldd $lib | fgrep $2`" ]; then echo "Error: dependency to '$2' found" exit 3 fi done } function get_so_version { local version=`ldd $1 | fgrep $2 | sed "s/.*\.so\.\([0-9\.]\+\).*/\1/"` echo "$version" } #### Set variables for script #### ROOT_DIR=$PWD DEP_DIR=$ROOT_DIR/deps DEP_BUILD_DIR=$ROOT_DIR/build_deps THREADS=`nproc` if [ `uname -m` == aarch64 ]; then GPU=OFF else GPU=ON SYM_TEST=true # FIXME: currently building ARM on Ubuntu fi #### Build dependencies #### mkdir $DEP_BUILD_DIR cd $DEP_BUILD_DIR # NOTE(jda) - Some Linux OSs need to have lib/ on LD_LIBRARY_PATH at build time export LD_LIBRARY_PATH=$DEP_DIR/lib:${LD_LIBRARY_PATH} cmake --version cmake \ "$@" \ -D BUILD_JOBS=$THREADS \ -D BUILD_DEPENDENCIES_ONLY=ON \ -D CMAKE_INSTALL_PREFIX=$DEP_DIR \ -D CMAKE_INSTALL_LIBDIR=lib \ -D BUILD_OSPRAY_MODULE_MPI=ON \ -D BUILD_GPU_SUPPORT=$GPU \ -D INSTALL_IN_SEPARATE_DIRECTORIES=OFF \ ../scripts/superbuild cmake --build . cd $ROOT_DIR #### Build OSPRay #### mkdir -p build_release cd build_release # Clean out build directory to be sure we are doing a fresh build rm -rf * # Setup environment for dependencies export CMAKE_PREFIX_PATH=$DEP_DIR # set release settings cmake -L \ "$@" \ -D TBB_ROOT=$DEP_DIR \ -D OSPRAY_ZIP_MODE=ON \ -D OSPRAY_BUILD_ISA=ALL \ -D OSPRAY_INSTALL_DEPENDENCIES=ON \ -D OSPRAY_MODULE_DENOISER=ON \ -D OSPRAY_MODULE_MPI=ON \ -D OSPRAY_MODULE_GPU=$GPU \ -D CMAKE_INSTALL_INCLUDEDIR=include \ -D CMAKE_INSTALL_LIBDIR=lib \ -D CMAKE_INSTALL_DOCDIR=doc \ -D CMAKE_INSTALL_BINDIR=bin \ -D CMAKE_BUILD_WITH_INSTALL_RPATH=ON \ .. # create tar.gz make -j $THREADS preinstall if [ $SYM_TEST ] ; then # verify libs for lib in libospray.so libospray_module_cpu.so libospray_module_mpi_offload.so libospray_module_mpi_distributed_cpu.so ; do echo "checking $lib..." check_symbols $lib GLIBC 2 28 0 check_symbols $lib GLIBCXX 3 4 22 check_symbols $lib CXXABI 1 3 11 check_lib_dependency_error $lib libimf.so check_lib_dependency_error $lib libsvml.so done for lib in libospray_module_mpi_offload.so libospray_module_mpi_distributed_cpu.so ; do echo "checking $lib..." check_lib_dependency_error $lib libmpifort.so MPICH_ABI_VER=12 mpi_so_ver=$(get_so_version $lib libmpi.so) mpicxx_so_ver=$(get_so_version $lib libmpicxx.so) if [ -z "$mpi_so_ver" ] || [ -z "$mpicxx_so_ver" ]; then echo "MPI module is not linked against libmpi.so or libmpicxx.so" exit 3 fi if [ "$mpi_so_ver" != "$MPICH_ABI_VER" ]; then echo "MPI module is linked against the wrong MPICH ABI: libmpi.so.$mpi_so_ver" exit 3 fi if [ "$mpicxx_so_ver" != "$MPICH_ABI_VER" ]; then echo "MPI module is linked against the wrong MPICH ABI: libmpicxx.so.$mpi_so_ver" exit 3 fi done fi cmake --build . --target package || exit 2 RenderKit-ospray-f2a61c2/scripts/release/macosx.sh000077500000000000000000000033631456566705700223140ustar00rootroot00000000000000#!/bin/bash ## Copyright 2014 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 #### Helper functions #### umask=`umask` function onexit { umask $umask } trap onexit EXIT umask 002 #### Set variables for script #### ROOT_DIR=$PWD DEP_DIR=$ROOT_DIR/deps DEP_BUILD_DIR=$ROOT_DIR/build_deps THREADS=`sysctl -n hw.logicalcpu` # set compiler if the user hasn't explicitly set CC and CXX if [ -z $CC ]; then echo "***NOTE: Defaulting to use clang!" echo -n " Please set env variables 'CC' and 'CXX' to" echo " a different supported compiler (gcc/icc) if desired." export CC=clang export CXX=clang++ fi # to make sure we do not include nor link against wrong TBB unset CPATH unset LIBRARY_PATH unset DYLD_LIBRARY_PATH #### Build dependencies #### mkdir $DEP_BUILD_DIR cd $DEP_BUILD_DIR cmake --version cmake \ "$@" \ -D BUILD_JOBS=$THREADS \ -D BUILD_DEPENDENCIES_ONLY=ON \ -D CMAKE_INSTALL_PREFIX=$DEP_DIR \ -D CMAKE_INSTALL_LIBDIR=lib \ -D INSTALL_IN_SEPARATE_DIRECTORIES=OFF \ ../scripts/superbuild cmake --build . cd $ROOT_DIR #### Build OSPRay #### mkdir -p build_release cd build_release # Clean out build directory to be sure we are doing a fresh build rm -rf * # Setup environment for dependencies export CMAKE_PREFIX_PATH=$DEP_DIR # set release and installer settings cmake -L \ "$@" \ -D OSPRAY_BUILD_ISA=ALL \ -D TBB_ROOT=$DEP_DIR \ -D OSPRAY_ZIP_MODE=ON \ -D OSPRAY_MODULE_DENOISER=ON \ -D OSPRAY_INSTALL_DEPENDENCIES=ON \ -D CMAKE_INSTALL_INCLUDEDIR=include \ -D CMAKE_INSTALL_LIBDIR=lib \ -D CMAKE_INSTALL_DOCDIR=doc \ -D CMAKE_INSTALL_BINDIR=bin \ -D CMAKE_BUILD_WITH_INSTALL_RPATH=ON \ -D CPACK_PRE_BUILD_SCRIPTS=$CPACK_PRE_BUILD_SIGNING_SCRIPT \ .. make -j $THREADS package || exit 2 RenderKit-ospray-f2a61c2/scripts/release/win.ps1000077500000000000000000000037141456566705700217100ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 Param( [string] $G = 'Ninja' ) $ROOT_DIR = pwd $DEP_DIR = "$ROOT_DIR\deps" ## Build dependencies ## mkdir deps_build cd deps_build cmake --version cmake -L ` -G $G ` $args ` -D CMAKE_BUILD_TYPE=Release ` -D DEPENDENCIES_BUILD_TYPE=Release ` -D BUILD_DEPENDENCIES_ONLY=ON ` -D CMAKE_INSTALL_PREFIX=$DEP_DIR ` -D CMAKE_INSTALL_LIBDIR=lib ` -D BUILD_OSPRAY_MODULE_MPI=ON ` -D BUILD_GPU_SUPPORT=ON ` -D INSTALL_IN_SEPARATE_DIRECTORIES=OFF ` ../scripts/superbuild cmake --build . --config Release cd $ROOT_DIR #### Build OSPRay #### md build_release cd build_release # Clean out build directory to be sure we are doing a fresh build rm -r -fo * # Setup environment for dependencies $env:CMAKE_PREFIX_PATH = $DEP_DIR if ($G -eq 'Ninja') { $package = 'package' # FIXME WA for OSPRay to build with GNU-style options $cxx_compiler = '-DCMAKE_CXX_COMPILER=clang++' $c_compiler = '-DCMAKE_C_COMPILER=clang' } else { $package = 'PACKAGE' } # set release settings cmake -L ` -G $G ` $args ` $cxx_compiler ` $c_compiler ` -D CMAKE_BUILD_TYPE=Release ` -D USE_STATIC_RUNTIME=OFF ` -D CMAKE_PREFIX_PATH="$DEP_DIR\lib\cmake" ` -D OSPRAY_MODULE_PATH="$ROOT_DIR\deps_build" ` -D TBB_ROOT=$DEP_DIR ` -D OSPRAY_ZIP_MODE=OFF ` -D OSPRAY_BUILD_ISA=ALL ` -D OSPRAY_INSTALL_DEPENDENCIES=ON ` -D OSPRAY_MODULE_DENOISER=ON ` -D OSPRAY_MODULE_MPI=ON ` -D OSPRAY_MODULE_GPU=ON ` -D CMAKE_INSTALL_INCLUDEDIR=include ` -D CMAKE_INSTALL_LIBDIR=lib ` -D CMAKE_INSTALL_DOCDIR=doc ` -D CMAKE_INSTALL_BINDIR=bin ` -D CMAKE_INSTALL_DATAROOTDIR= ` -D OSPRAY_SIGN_FILE=$env:SIGN_FILE_WINDOWS ` .. # compile and create installers cmake --build . --config Release --target sign_files cmake --build . --config Release --target $package # create ZIP files cmake -L ` -D OSPRAY_ZIP_MODE=ON ` .. cmake --build . --config Release --target $package exit $LASTEXITCODE RenderKit-ospray-f2a61c2/scripts/scan/000077500000000000000000000000001456566705700177625ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/scripts/scan/bdba.sh000077500000000000000000000043261456566705700212160ustar00rootroot00000000000000#!/bin/bash ## Copyright 2019 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 files=$1 jq_tool="$SHARED_TOOLS_PATH/jq-linux64" logfile="bdba.log" failed=0 for file_path in $files ; do echo -e "\n" >> $logfile #upload file upload_response=`curl -k -H "Authorization: Bearer $BDBA_TOKEN" -H "Group: $BDBA_GROUP" -T $file_path "$BDBA_SERVER/api/upload/"` product_id=`echo "$upload_response" | $jq_tool -r '.results.product_id'` if [ $product_id == "null" ]; then echo "Cannot upload file $file_path" >> $logfile failed=1 continue fi report_url=`echo "$upload_response" | $jq_tool -r '.results.report_url'` echo "Scan upload of $file_path completed - product id: $product_id ($report_url)" >> $logfile set +e MAX_RETRY=600 RETRY_COUNTER="0" while [ $RETRY_COUNTER -lt $MAX_RETRY ]; do response=`curl -s -X GET -H "Authorization: Bearer $BDBA_TOKEN" -k $BDBA_SERVER/api/product/$product_id/` CMD_RETURN_CODE=$? status=`echo "$response" | $jq_tool -r '.results.status'` verdict=`echo "$response" | $jq_tool -r '.results.summary.verdict.short'` if [ $CMD_RETURN_CODE == 0 ] && [[ $status == "R" ]]; then echo $response | python -m json.tool echo "Verdict: $verdict" >> $logfile if [ $verdict != "Pass" ] && [ $verdict != "null" ]; then echo "There is a problem - please check report $report_url" >> $logfile failed=1 fi # Download pdf report & components list file_name=`basename "$file_path"` echo "File name: $file_name" curl -H "Authorization: Bearer $BDBA_TOKEN" -k $BDBA_SERVER/api/product/$product_id/pdf-report?cvss_version=3 -o ${file_name}_report.pdf curl -H "Authorization: Bearer $BDBA_TOKEN" -k $BDBA_SERVER/api/product/$product_id/csv-libs -o ${file_name}_components.csv break fi RETRY_COUNTER=$[$RETRY_COUNTER+1] echo "Scan not finished yet, [$RETRY_COUNTER/$MAX_RETRY] - checking again ... " sleep 20 done set -e if [ $RETRY_COUNTER -ge $MAX_RETRY ]; then failed=62 continue fi done cat $logfile exit $failed RenderKit-ospray-f2a61c2/scripts/scan/kw-check-issues.sh000077500000000000000000000015471456566705700233350ustar00rootroot00000000000000#!/bin/bash -xe ## Copyright 2020 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 KW_ISSUES_FILE=/tmp/issues KW_SERVER_API_URL=http://$KW_SERVER_IP:$KW_SERVER_PORT/review/api KW_BUILD_NAME=$(cat $CI_PROJECT_DIR/klocwork/build_name) echo "Checking for issues in $KW_BUILD_NAME ..." curl -f --data "action=search&project=$KW_PROJECT_NAME&query=build:'$KW_BUILD_NAME'%20status:Analyze,Fix,Fix%20in%20Next%20Release,Fix%20in%20Later%20Release,Defer,Filter&user=$KW_USER<oken=$KW_LTOKEN" $KW_SERVER_API_URL -o $KW_ISSUES_FILE getCriticalCount() { cat $KW_ISSUES_FILE | wc -l } if [ -f $KW_ISSUES_FILE ]; then echo "Issues found - $(getCriticalCount) in $KW_BUILD_NAME"; while IFS= read -r line; do echo $line | python -m json.tool; done < $KW_ISSUES_FILE exit 1; else echo "There are no issues which should be take care in $KW_BUILD_NAME" fi RenderKit-ospray-f2a61c2/scripts/scan/kw-gen-report.sh000077500000000000000000000033251456566705700230250ustar00rootroot00000000000000#!/bin/bash -xe ## Copyright 2020 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 KW_SERVER_API_URL=http://$KW_SERVER_IP:$KW_SERVER_PORT/review/api KW_BUILD_NAME=$(cat $CI_PROJECT_DIR/klocwork/build_name) KW_BUILD_LOG_FILE=$CI_PROJECT_DIR/klocwork/build.log export PATH="$SHARED_TOOLS_PATH:$PATH" [ -f $KW_BUILD_LOG_FILE ] || (echo "Build log file not found. Expected to be in: $KW_BUILD_LOG_FILE." ; exit 1;) mkdir -p $CI_PROJECT_DIR/klocwork report_file=$CI_PROJECT_DIR/klocwork/report.log echo "------------------" >> $report_file echo "Report generated at: "$(date '+%d/%m/%Y %H:%M:%S') >> $report_file echo "Project source code url: $CI_PROJECT_URL" >> $report_file echo "Project source code sha: $CI_COMMIT_SHA" >> $report_file echo "Klocwork server: http://$KW_SERVER_IP:$KW_SERVER_PORT" >> $report_file echo "------------------" >> $report_file echo -e "\n\n\n" >> $report_file # Get all issues list and put to report file column_list=".id, .code, .severity, .state, .status, .taxonomyName, .owner, .url, .file, .line" echo "------------------" >> $report_file echo "Issues list:" >> $report_file echo "------------------" >> $report_file echo $column_list | sed 's/\\t/ ,/g' | column -t -s, >> $report_file echo "------------------" >> $report_file curl -f --data "action=search&project=$KW_PROJECT_NAME&query=build:'$KW_BUILD_NAME'&user=$KW_USER<oken=$KW_LTOKEN" $KW_SERVER_API_URL | jq-linux64 "[${column_list}] | @tsv" | sed 's/\\t/|/g' | column -t -s'|' | cut -d'"' -f2 >> $report_file echo -e "\n\n\n" >> $report_file # Attach build log to report file echo "------------------" >> $report_file echo "Build & scan log:" >> $report_file echo "------------------" >> $report_file cat $KW_BUILD_LOG_FILE >> $report_file RenderKit-ospray-f2a61c2/scripts/scan/store-files.sh000077500000000000000000000003741456566705700225610ustar00rootroot00000000000000#!/bin/bash -xe ## Copyright 2019 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 project_name=$1 build_id=$2 group_name=$3 files=$4 STORAGE_DIR=$STORAGE_PATH/$project_name/$build_id/$group_name/ mkdir -p $STORAGE_DIR cp $files $STORAGE_DIR/ RenderKit-ospray-f2a61c2/scripts/superbuild/000077500000000000000000000000001456566705700212145ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/scripts/superbuild/CMakeLists.txt000066400000000000000000000244641456566705700237660ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 ## Global settings ## cmake_minimum_required(VERSION 3.7) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/dependencies) if(NOT CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE STRING "Final install location." FORCE) endif() if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the build type." FORCE) endif() set(CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo") if (WIN32) if (NOT OSPRAY_DEFAULT_CMAKE_CONFIGURATION_TYPES_SET) set(CMAKE_CONFIGURATION_TYPES "${CONFIGURATION_TYPES}" CACHE STRING "List of generated configurations." FORCE) set(OSPRAY_DEFAULT_CMAKE_CONFIGURATION_TYPES_SET ON CACHE INTERNAL "Default CMake configuration types set.") endif() else() set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CONFIGURATION_TYPES}) endif() if (NOT DEPENDENCIES_BUILD_TYPE) set(DEPENDENCIES_BUILD_TYPE Release) endif() ## Establish project ## project(OSPRay_superbuild) if(CMAKE_SIZEOF_VOID_P EQUAL 4) message(FATAL_ERROR "OSPRay can only be built on 64-bit platforms. This problem most commonly happens on Windows, where the right solution is to switch to a 64-bit generator: retry running CMake with '-G \"Visual Studio 15 2017 Win64\"'") else() message(STATUS "Proceeding with a 64-bit generator. (${CMAKE_SIZEOF_VOID_P})") endif() if (POLICY CMP0114) # allow old CMake behavior: NO_DEPENDS for ExternalProject_Add_StepTargets cmake_policy(SET CMP0114 OLD) # 3.19 endif () if (POLICY CMP0135) # use timestamp of extraction of downloaded archives cmake_policy(SET CMP0135 NEW) # 3.24 endif () include(ExternalProject) include(GNUInstallDirs) include(ProcessorCount) include(CMakeDependentOption) ## Superbuild options ## ProcessorCount(PROCESSOR_COUNT) if(NOT PROCESSOR_COUNT EQUAL 0) set(BUILD_JOBS ${PROCESSOR_COUNT} CACHE STRING "Number of build jobs '-j '") else() set(BUILD_JOBS 4 CACHE STRING "Number of build jobs '-j '") endif() option(ALWAYS_REBUILD "Force every project to always be rebuilt?" OFF) option(DOWNLOAD_ISPC "Download ISPC or use the one found in the system environment?" ON) if (DOWNLOAD_ISPC) set(ISPC_VERSION "1.23.0" CACHE STRING "Which version of ISPC to download?") mark_as_advanced(CLEAR ISPC_VERSION) option(BUILD_ISPCRT_FROM_SOURCE "Build ISPCRT or use pre-built version?" OFF) mark_as_advanced(CLEAR BUILD_ISPCRT_FROM_SOURCE) if (ISPC_VERSION STREQUAL "1.23.0") set(ISPC_SOURCE_HASH "d665f0d4160a8777cf478e5f806478bb817daa40b3111f366e07dc6615b0ebe7") if (APPLE) if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64|aarch64") set(ISPC_HASH "2cf144aaa6d8117e3a9e0782984fa4cb45127387dd4fb385b187115d6c1a0d68") else() set(ISPC_HASH "b9e6dcc045f5a2e29a6c43354b6a747c4486a341608d785f5f99eca8ac207a72") endif() elseif (WIN32) set(ISPC_HASH "709350902381968ee58fd67e9aed63df99b1313bc55a94195977bcc8d90bdced") else() if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64|aarch64") set(ISPC_HASH "f82a0464b8d172c2c015f4252154651c6a25061f7a47ffb7f7f5b785eddfc9cc") else() set(ISPC_HASH "9183b2dd128fa5ca30ab24ca2cf6730a11572e4efd82fd284d167109f9c9d077") endif() endif() endif() else() mark_as_advanced(FORCE ISPC_VERSION) endif() set(RKCOMMON_VERSION "1.13.0" CACHE STRING "Which version of rkcommon to build?") if (RKCOMMON_VERSION STREQUAL "1.13.0") set(RKCOMMON_HASH "9d360ce89de1842d4ae81b561ce150efd4fd812bd9e8b1d42d3934c528de637c") endif() option(DOWNLOAD_TBB "Download TBB or use the one found in the system environment?" ON) if (DOWNLOAD_TBB) set(TBB_VERSION "2021.11.0" CACHE STRING "Which version of TBB to download?") mark_as_advanced(CLEAR TBB_VERSION) option(BUILD_TBB_FROM_SOURCE "Build TBB from source or use pre-built version?" OFF) mark_as_advanced(CLEAR BUILD_TBB_FROM_SOURCE) if (TBB_VERSION STREQUAL "2021.11.0") if (BUILD_TBB_FROM_SOURCE) set(TBB_HASH "2f0bfce641d238e80798fc48397d43821bd977d49c4e03bc785be363b7ab4742") else() if (APPLE) set(TBB_HASH "360bcb20bcdcd01e8492c32bba6d5d5baf4bc83f77fb9dbf1ff701ac816e3b44") elseif (WIN32) set(TBB_HASH "02f0e93600fba69bb1c00e5dd3f66ae58f56e5410342f6155455a95ba373b1b6") else() set(TBB_HASH "95659f4d7b1711c41ffa190561d4e5b6841efc8091549661c7a2e6207e0fa79b") endif() endif() endif() else() mark_as_advanced(FORCE TBB_VERSION) mark_as_advanced(FORCE BUILD_TBB_FROM_SOURCE) endif() option(BUILD_EMBREE_FROM_SOURCE "Build Embree or use pre-built version?" OFF) set(EMBREE_VERSION "4.3.1" CACHE STRING "Which version of Embree to build?") if (EMBREE_VERSION STREQUAL "4.3.1") if (BUILD_EMBREE_FROM_SOURCE) set(EMBREE_HASH "bdab87b285efa1a9f1f57fe74b2743c659c487fee7e32221db43a6b8f5e36e5f") else() if (APPLE) if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64|aarch64") set(EMBREE_HASH "adfb26b8ae37618cea09dc3a63ac710dd96b665991218ed79d2733a6c0aa65b3") else() set(EMBREE_HASH "ffb446c5a688d961f4219f42446147632f5704374c5b2b148a1e2a20b7c99975") endif() elseif (WIN32) set(EMBREE_HASH "6e2b968d45c0895cda98fb44c42e214e8d382bcd08b0a548fe086b0864563c6a") set(EMBREE_SYCL_HASH "c03735ee4801b11bf8b191f521527a57e9d77d6a2b7dd4439fef801748814984") else() set(EMBREE_HASH "375e829dc31ac5c6c579de34e0b1527e088a3b296fb9d3f90ed892d29592f845") set(EMBREE_SYCL_HASH "f4e5d36be8b3cd2d3f57fab885ffb769e071f5ce7d2a9ddfba61dae69c18693b") endif() endif() endif() option(BUILD_OPENVKL "Build Open VKL as a part of the superbuild." ON) if (BUILD_OPENVKL) set(OPENVKL_VERSION "2.0.1" CACHE STRING "Which version of OpenVKL to build?") if (OPENVKL_VERSION STREQUAL "2.0.1") set(OPENVKL_HASH "6676f2171f9d61844ef2a417df79275226026bc4210a4afc61da2160ecaaf5ed") endif() else() mark_as_advanced(FORCE OPENVKL_VERSION) endif() option(BUILD_OIDN "Build OpenImageDenoise as a part of the superbuild." ON) if (BUILD_OIDN) set(OIDN_VERSION "2.2.0" CACHE STRING "Which version of OpenImageDenoise to build?") mark_as_advanced(CLEAR OIDN_VERSION) option(BUILD_OIDN_FROM_SOURCE "Build OpenImageDenoise or use pre-built version?" OFF) mark_as_advanced(CLEAR BUILD_OIDN_FROM_SOURCE) if (OIDN_VERSION STREQUAL "2.2.0") if (BUILD_OIDN_FROM_SOURCE) set(OIDN_HASH "5864386628d35d2b555380969ac957dc52c714d01866f557d9d1400ee01e61f1") else() if (APPLE) if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64|aarch64") set(OIDN_HASH "16cdaddabeb0f2af22fc8e466317c1a14a54b6ec03db2ac343e17fad40c70f3f") else() set(OIDN_HASH "eafef2feb1f622f1fd1985673407598ba8746257cbd6f3ba55c470e6e92ebf6c") endif() elseif (WIN32) set(OIDN_HASH "f570b95c023f71d453f11bd0b53066e7f147b6b191512e044fe4a68df2806afc") else() set(OIDN_HASH "d9a67ed99840a19333213981850db09e843443cce658f3643ed17990518ce8d9") endif() endif() endif() else() mark_as_advanced(FORCE OIDN_VERSION) mark_as_advanced(FORCE BUILD_OIDN_FROM_SOURCE) endif() option(BUILD_GLFW "Build glfw for OSPRay examples or use one in existing environment?" ON) option(BUILD_DEPENDENCIES_ONLY "Don't build OSPRay itself, only its dependencies" OFF) option(BUILD_OSPRAY_CI_EXTRAS "Enable OSPRay's extra compiler checks." OFF) option(BUILD_OSPRAY_APPS "Enable building OSPRay apps" ON) option(BUILD_OSPRAY_MODULE_MPI "Enable building module_mpi" OFF) option(BUILD_OSPRAY_MODULE_MULTIDEVICE "Enable building module_multidevice" OFF) if (NOT APPLE) option(BUILD_GPU_SUPPORT "Enable beta GPU support and building module_gpu" OFF) endif() if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64|aarch64") set(ISA_X86 OFF) if (APPLE) set(ISA_NEON OFF) set(ISA_NEON2X ON) else() set(ISA_NEON ON) set(ISA_NEON2X OFF) endif() else() set(ISA_X86 ON) set(ISA_NEON OFF) set(ISA_NEON2X OFF) endif() option(BUILD_ISA_SSE4 "Build for SSE4" ${ISA_X86}) mark_as_advanced(BUILD_ISA_SSE4) option(BUILD_ISA_AVX "Build for AVX" ${ISA_X86}) mark_as_advanced(BUILD_ISA_AVX) option(BUILD_ISA_AVX2 "Build for AVX2" ${ISA_X86}) mark_as_advanced(BUILD_ISA_AVX2) option(BUILD_ISA_AVX512 "Build for AVX512" ${ISA_X86}) mark_as_advanced(BUILD_ISA_AVX512) option(BUILD_ISA_NEON "Build for NEON" ${ISA_NEON}) mark_as_advanced(BUILD_ISA_NEON) option(BUILD_ISA_NEON2X "Build for double pumped NEON" ${ISA_NEON2X}) mark_as_advanced(BUILD_ISA_NEON2X) if (BUILD_ISA_NEON AND BUILD_ISA_NEON2X) message(FATAL_ERROR "Only one Neon ISA may be enabled; choose either NEON or NEON2X") endif() option(INSTALL_IN_SEPARATE_DIRECTORIES "Install libraries into their own directories under CMAKE_INSTALL_PREFIX" ON ) option(INSTALL_DEPENDENCIES "Install OSPRay dependencies" ON) ## Setup top-level variables ## set(installDir ${CMAKE_INSTALL_PREFIX}) get_filename_component(INSTALL_DIR_ABSOLUTE ${installDir} ABSOLUTE BASE_DIR ${CMAKE_CURRENT_BINARY_DIR}) if (${CMAKE_VERSION} VERSION_GREATER 3.11.4) set(PARALLEL_JOBS_OPTS -j ${BUILD_JOBS}) endif() ## Build dependencies ## set(DEFAULT_BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${DEPENDENCIES_BUILD_TYPE} ${PARALLEL_JOBS_OPTS}) if (DOWNLOAD_ISPC) include(dep_ispc) endif() if (DOWNLOAD_TBB) include(dep_tbb) endif() include(dep_rkcommon) include(dep_embree) if (BUILD_GLFW) include(dep_glfw) endif() if (BUILD_OIDN) include(dep_oidn) endif() include(dep_glm) if (BUILD_OSPRAY_APPS) include(dep_gtest) include(dep_benchmark) endif() if (BUILD_OSPRAY_MODULE_MPI) set(OSPRAY_MODULE_MPI ON) include(dep_snappy) endif() ##### FIXME WA for VKL and OSPRay to build with GNU-style options if (WIN32 AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")) # remember CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS before switching to GNU-style # frontend, which won't look for MSVCRT anymore set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE) include(InstallRequiredSystemLibraries) file(CONFIGURE OUTPUT ospray_system_runtime.cmake CONTENT "set(OSPRAY_INSTALL_SYSTEM_RUNTIME_LIBS \"@CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS@\")" @ONLY NEWLINE_STYLE WIN32) set(CMAKE_C_COMPILER clang) set(CMAKE_CXX_COMPILER clang++) endif() if (BUILD_OPENVKL) include(dep_openvkl) endif() ## Build main projects ## set(DEFAULT_BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE} ${PARALLEL_JOBS_OPTS}) if (NOT BUILD_DEPENDENCIES_ONLY) include(build_ospray.cmake) endif() RenderKit-ospray-f2a61c2/scripts/superbuild/README.md000066400000000000000000000065341456566705700225030ustar00rootroot00000000000000## CMake Superbuild For convenience, OSPRay provides a CMake Superbuild script which will pull down OSPRay’s dependencies and build OSPRay itself. By default, the result is an install directory, with each dependency in its own directory. Run with: ```sh mkdir build cd build cmake [/scripts/superbuild] cmake --build . ``` On Windows make sure to select a 64bit generator, e.g. ```sh cmake -G "Visual Studio 17 2022" [/scripts/superbuild] ``` The resulting `install` directory (or the one set with `CMAKE_INSTALL_PREFIX`) will have everything in it, with one subdirectory per dependency. CMake options to note (all have sensible defaults): CMAKE_INSTALL_PREFIX : will be the root directory where everything gets installed. BUILD_JOBS : sets the number given to `make -j` for parallel builds. INSTALL_IN_SEPARATE_DIRECTORIES : toggles installation of all libraries in separate or the same directory. BUILD_OPENVKL : whether to enable volume rendering via Open VKL BUILD_EMBREE_FROM_SOURCE : set to OFF will download a pre-built version of Embree. BUILD_OIDN_FROM_SOURCE : set to OFF will download a pre-built version of Open Image Denoise. OIDN_VERSION : determines which version of Open Image Denoise to pull down. BUILD_OSPRAY_MODULE_MPI : set to ON to build OSPRay’s MPI module for data-replicated and distributed parallel rendering on multiple nodes. BUILD_GPU_SUPPORT : enables beta GPU support, fetching the SYCL variants of the dependencies and builds `OSPRAY_MODULE_GPU` BUILD_TBB_FROM_SOURCE : set to ON to build TBB from source (required for ARM support). The default setting is OFF. For the full set of options, run: ```sh ccmake [/scripts/superbuild] ``` or ```sh cmake-gui [/scripts/superbuild] ``` ### Cross-Compilation with the Superbuild The superbuild can be passed a [CMake Toolchain file](https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html) to configure for cross-compilation. This is done by passing the toolchain file when running cmake. When cross compiling it is also likely that you’ll want to build TBB and Embree from source to ensure they’re built for the correct target, rather than the target the Github binaries are built for. It may also be necessary to disable specific ISAs for the target by passing `BUILD_ISA_=OFF` as well. ```sh mkdir build cd build cmake --toolchain [toolchain_file.cmake] [path/to/this/directory] -DBUILD_TBB_FROM_SOURCE=ON \ -DBUILD_EMBREE_FROM_SOURCE=ON \ ``` While OSPRay supports ARM natively, it may be desirable to cross-compile it for `x86_64` to run in Rosetta depending on the application integrating OSPRay. This can be done using the toolchain file `toolchains/macos-rosetta.cmake`, and by disabling all non-SSE ISAs when building. This can also be done by launching an `x86_64` bash shell and then compiling as usual in this environment, which will cause the compilation chain to target `x86_64`. The `BUILD_ISA_=OFF` flags should be passed to disable all ISAs besides SSE4 for Rosetta: ```sh arch -x86_64 bash mkdir build cd build cmake [path/to/this/directory] -DBUILD_TBB_FROM_SOURCE=ON \ -DBUILD_EMBREE_FROM_SOURCE=ON \ -DBUILD_ISA_AVX=OFF \ -DBUILD_ISA_AVX2=OFF \ -DBUILD_ISA_AVX512=OFF \ ``` RenderKit-ospray-f2a61c2/scripts/superbuild/build_ospray.cmake000066400000000000000000000051261456566705700247160ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME ospray) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}) if (INSTALL_IN_SEPARATE_DIRECTORIES) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/${COMPONENT_NAME}) endif() if (NOT DEFINED BUILD_OSPRAY_GLM) set(BUILD_OSPRAY_GLM ${BUILD_OSPRAY_APPS}) endif() ExternalProject_Add(${COMPONENT_NAME} PREFIX ${COMPONENT_NAME} DOWNLOAD_COMMAND "" STAMP_DIR ${COMPONENT_NAME}/stamp SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../.. BINARY_DIR ${COMPONENT_NAME}/build LIST_SEPARATOR | # Use the alternate list separator CMAKE_ARGS -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_INSTALL_PREFIX:PATH=${COMPONENT_PATH} -DCMAKE_INSTALL_INCLUDEDIR=${CMAKE_INSTALL_INCLUDEDIR} -DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR} -DCMAKE_INSTALL_DOCDIR=${CMAKE_INSTALL_DOCDIR} -DCMAKE_INSTALL_BINDIR=${CMAKE_INSTALL_BINDIR} -DOSPRAY_ENABLE_APPS=${BUILD_OSPRAY_APPS} -DOSPRAY_APPS_ENABLE_GLM=${BUILD_OSPRAY_GLM} -DOSPRAY_BUILD_ISA=ALL -DOSPRAY_ENABLE_VOLUMES=${BUILD_OPENVKL} -DOSPRAY_MODULE_BILINEAR_PATCH=${BUILD_OSPRAY_CI_EXTRAS} -DOSPRAY_MODULE_DENOISER=${BUILD_OIDN} -DOSPRAY_INSTALL_DEPENDENCIES=${INSTALL_DEPENDENCIES} -DOSPRAY_STRICT_BUILD=${BUILD_OSPRAY_CI_EXTRAS} -DOSPRAY_WARN_AS_ERRORS=${BUILD_OSPRAY_CI_EXTRAS} -DOSPRAY_MODULE_MPI=${BUILD_OSPRAY_MODULE_MPI} -DOSPRAY_MODULE_GPU=${BUILD_GPU_SUPPORT} -DOSPRAY_MODULE_MULTIDEVICE=${BUILD_OSPRAY_MODULE_MULTIDEVICE} $<$:-DRKCOMMON_TBB_ROOT=${TBB_PATH}> $<$:-Dispcrt_DIR=${ispcrt_DIR}> -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} -DOSPRAY_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR} # FIXME WA for OSPRay to build with GNU-style options BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} BUILD_ALWAYS OFF ) ExternalProject_Add_StepDependencies(${COMPONENT_NAME} configure glm rkcommon embree $<$:openvkl> $<$:benchmark> $<$:gtest> $<$:snappy> $<$:glfw> $<$:ispc> $<$:ispcrt> $<$:oidn> ) list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") RenderKit-ospray-f2a61c2/scripts/superbuild/dependencies/000077500000000000000000000000001456566705700236425ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/scripts/superbuild/dependencies/dep_benchmark.cmake000066400000000000000000000016551456566705700274350ustar00rootroot00000000000000## Copyright 2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME benchmark) if (INSTALL_IN_SEPARATE_DIRECTORIES) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/${COMPONENT_NAME}) else() set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}) endif() ExternalProject_Add(${COMPONENT_NAME} URL "https://github.com/google/benchmark/archive/refs/tags/v1.8.3.zip" URL_HASH "SHA256=abfc22e33e3594d0edf8eaddaf4d84a2ffc491ad74b6a7edc6e7a608f690e691" # Skip updating on subsequent builds (faster) UPDATE_COMMAND "" DEPENDS gtest CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_INSTALL_PREFIX:PATH=${COMPONENT_PATH} -DBENCHMARK_ENABLE_TESTING=OFF -DBENCHMARK_ENABLE_GTEST_TESTS=OFF -DBENCHMARK_ENABLE_WERROR=OFF -DCMAKE_BUILD_TYPE=${DEPENDENCIES_BUILD_TYPE} ) list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") RenderKit-ospray-f2a61c2/scripts/superbuild/dependencies/dep_embree.cmake000066400000000000000000000071151456566705700267370ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME embree) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}) if (INSTALL_IN_SEPARATE_DIRECTORIES) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/${COMPONENT_NAME}) endif() if (EMBREE_HASH) set(EMBREE_URL_HASH URL_HASH SHA256=${EMBREE_HASH}) endif() if (BUILD_EMBREE_FROM_SOURCE) string(REGEX REPLACE "(^[0-9]+\.[0-9]+\.[0-9]+$)" "v\\1" EMBREE_ARCHIVE ${EMBREE_VERSION}) set(EMBREE_URL "https://github.com/embree/embree/archive/${EMBREE_ARCHIVE}.zip" CACHE STRING "Location to get Embree source from") if (${EMBREE_URL} MATCHES ".*\.zip$") set(EMBREE_CLONE_URL URL ${EMBREE_URL}) else() set(EMBREE_CLONE_URL GIT_REPOSITORY ${EMBREE_URL} GIT_TAG ${EMBREE_VERSION}) endif() ExternalProject_Add(${COMPONENT_NAME} PREFIX ${COMPONENT_NAME} DOWNLOAD_DIR ${COMPONENT_NAME} STAMP_DIR ${COMPONENT_NAME}/stamp SOURCE_DIR ${COMPONENT_NAME}/src BINARY_DIR ${COMPONENT_NAME}/build LIST_SEPARATOR | # Use the alternate list separator ${EMBREE_CLONE_URL} ${EMBREE_URL_HASH} CMAKE_ARGS -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_INSTALL_PREFIX:PATH=${COMPONENT_PATH} -DCMAKE_INSTALL_INCLUDEDIR=${CMAKE_INSTALL_INCLUDEDIR} -DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR} -DCMAKE_INSTALL_DOCDIR=${CMAKE_INSTALL_DOCDIR} -DCMAKE_INSTALL_BINDIR=${CMAKE_INSTALL_BINDIR} $<$:-DEMBREE_TBB_ROOT=${TBB_PATH}> $<$:-DEMBREE_ISPC_EXECUTABLE=${ISPC_PATH}> -DCMAKE_BUILD_TYPE=${DEPENDENCIES_BUILD_TYPE} -DEMBREE_TUTORIALS=OFF -DBUILD_TESTING=OFF -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} -DEMBREE_ISA_SSE42=${BUILD_ISA_SSE4} -DEMBREE_ISA_AVX=${BUILD_ISA_AVX} -DEMBREE_ISA_AVX2=${BUILD_ISA_AVX2} -DEMBREE_ISA_AVX512=${BUILD_ISA_AVX512} -DEMBREE_ISA_NEON=${BUILD_ISA_NEON} -DEMBREE_ISA_NEON2X=${BUILD_ISA_NEON2X} -DEMBREE_ISPC_SUPPORT=ON -DEMBREE_SYCL_SUPPORT=${BUILD_GPU_SUPPORT} BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} BUILD_ALWAYS ${ALWAYS_REBUILD} ) if (DOWNLOAD_TBB) ExternalProject_Add_StepDependencies(${COMPONENT_NAME} configure tbb) endif() if (DOWNLOAD_ISPC) ExternalProject_Add_StepDependencies(${COMPONENT_NAME} configure ispc) endif() else() if (APPLE) set(EMBREE_OSSUFFIX "${CMAKE_SYSTEM_PROCESSOR}.macosx.zip") elseif (WIN32) set(EMBREE_OSSUFFIX "x64.windows.zip") else() set(EMBREE_OSSUFFIX "x86_64.linux.tar.gz") endif() if (BUILD_GPU_SUPPORT) set(EMBREE_TAG ".sycl") if (EMBREE_SYCL_HASH) set(EMBREE_URL_HASH URL_HASH SHA256=${EMBREE_SYCL_HASH}) endif() endif() set(EMBREE_URL "https://github.com/embree/embree/releases/download/v${EMBREE_VERSION}/embree-${EMBREE_VERSION}${EMBREE_TAG}.${EMBREE_OSSUFFIX}") ExternalProject_Add(${COMPONENT_NAME} PREFIX ${COMPONENT_NAME} DOWNLOAD_DIR ${COMPONENT_NAME} STAMP_DIR ${COMPONENT_NAME}/stamp SOURCE_DIR ${COMPONENT_NAME}/src BINARY_DIR ${COMPONENT_NAME} URL ${EMBREE_URL} ${EMBREE_URL_HASH} CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "${CMAKE_COMMAND}" -E copy_directory / ${COMPONENT_PATH} BUILD_ALWAYS OFF ) endif() list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") RenderKit-ospray-f2a61c2/scripts/superbuild/dependencies/dep_glfw.cmake000066400000000000000000000036621456566705700264420ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME glfw) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}) if (INSTALL_IN_SEPARATE_DIRECTORIES) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/${COMPONENT_NAME}) endif() ExternalProject_Add(${COMPONENT_NAME} PREFIX ${COMPONENT_NAME} DOWNLOAD_DIR ${COMPONENT_NAME} STAMP_DIR ${COMPONENT_NAME}/stamp SOURCE_DIR ${COMPONENT_NAME}/src BINARY_DIR ${COMPONENT_NAME}/build URL "https://github.com/glfw/glfw/archive/refs/tags/3.3.9.zip" URL_HASH "SHA256=c49d895b1f32fa3e072626f6dc928887fc814f445d3ba1fbb97598fea8e48933" # `patch` is not available on all systems, so use `git apply` instead. Note # that we initialize a Git repo in the GLFW download directory to allow the # Git patching approach to work. Also note that we don't want to actually # check out the GLFW Git repo, since we want our GLFW_HASH security checks # to still function correctly. PATCH_COMMAND git init -q . && git apply -v -p1 < ${CMAKE_CURRENT_SOURCE_DIR}/dependencies/glfw.patch CMAKE_ARGS -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_INSTALL_PREFIX:PATH=${COMPONENT_PATH} -DCMAKE_INSTALL_INCLUDEDIR=${CMAKE_INSTALL_INCLUDEDIR} -DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR} -DCMAKE_INSTALL_DOCDIR=${CMAKE_INSTALL_DOCDIR} -DCMAKE_INSTALL_BINDIR=${CMAKE_INSTALL_BINDIR} -DCMAKE_BUILD_TYPE=${DEPENDENCIES_BUILD_TYPE} -DBUILD_SHARED_LIBS:BOOL=OFF -D_GLFW_BUILD_DLL:BOOL=ON # merge into ospray_imgui.dll -DGLFW_BUILD_DOCS=OFF -DGLFW_BUILD_EXAMPLES=OFF -DGLFW_BUILD_TESTS=OFF -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} BUILD_ALWAYS ${ALWAYS_REBUILD} ) list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") RenderKit-ospray-f2a61c2/scripts/superbuild/dependencies/dep_glm.cmake000066400000000000000000000017741456566705700262640ustar00rootroot00000000000000## Copyright 2020 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME glm) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}) if (INSTALL_IN_SEPARATE_DIRECTORIES) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/${COMPONENT_NAME}) endif() ExternalProject_Add(${COMPONENT_NAME} PREFIX ${COMPONENT_NAME} DOWNLOAD_DIR ${COMPONENT_NAME} STAMP_DIR ${COMPONENT_NAME}/stamp SOURCE_DIR ${COMPONENT_NAME}/src BINARY_DIR ${COMPONENT_NAME}/build LIST_SEPARATOR | # Use the alternate list separator URL "https://github.com/g-truc/glm/archive/refs/tags/1.0.0.zip" URL_HASH "SHA256=66b3604366466c1674736cfec7c334d2d0b79b6c23096d1377637f4b71579c59" CMAKE_ARGS -DBUILD_TESTING=OFF -DCMAKE_INSTALL_PREFIX:PATH=${COMPONENT_PATH} -DGLM_BUILD_LIBRARY=OFF -DGLM_BUILD_TESTS=OFF -DGLM_TEST_ENABLE=OFF BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} BUILD_ALWAYS OFF ) list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}/share/glm) string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") RenderKit-ospray-f2a61c2/scripts/superbuild/dependencies/dep_gtest.cmake000066400000000000000000000017171456566705700266300ustar00rootroot00000000000000## Copyright 2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME gtest) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}) if (INSTALL_IN_SEPARATE_DIRECTORIES) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/${COMPONENT_NAME}) endif() # Google Test follows the "Live Head" philosophy and therefore recommends # using the latest commit to 'master' ExternalProject_Add(${COMPONENT_NAME} URL "https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip" URL_HASH "SHA256=1f357c27ca988c3f7c6b4bf68a9395005ac6761f034046e9dde0896e3aba00e4" # # Skip updating on subsequent builds (faster) UPDATE_COMMAND "" CMAKE_ARGS -Dgtest_force_shared_crt=ON -DCMAKE_INSTALL_PREFIX:PATH=${COMPONENT_PATH} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_BUILD_TYPE=${DEPENDENCIES_BUILD_TYPE} -DBUILD_GMOCK=OFF ) list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") RenderKit-ospray-f2a61c2/scripts/superbuild/dependencies/dep_ispc.cmake000066400000000000000000000070011456566705700264300ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME ispc) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}) if (INSTALL_IN_SEPARATE_DIRECTORIES) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/${COMPONENT_NAME}) endif() set(ISPCRT_LIBDIR "lib") if (APPLE) set(ISPC_OSSUFFIX "macOS.${CMAKE_SYSTEM_PROCESSOR}.tar.gz") elseif(WIN32) set(ISPC_OSSUFFIX "windows.zip") else() if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64|aarch64") set(ISPC_OSSUFFIX "linux.aarch64.tar.gz") else() set(ISPC_OSSUFFIX "linux-oneapi.tar.gz") set(ISPCRT_LIBDIR "lib64") endif() endif() set(ISPC_URL "https://github.com/ispc/ispc/releases/download/v${ISPC_VERSION}/ispc-v${ISPC_VERSION}-${ISPC_OSSUFFIX}") if (ISPC_HASH) set(ISPC_URL_HASH URL_HASH SHA256=${ISPC_HASH}) endif() set(ISPC_PATH "${COMPONENT_PATH}/bin/ispc${CMAKE_EXECUTABLE_SUFFIX}") if (BUILD_ISPCRT_FROM_SOURCE) set(ISPC_INSTALL copy_if_different /bin/ispc${CMAKE_EXECUTABLE_SUFFIX} ${ISPC_PATH}) else() set(ISPC_INSTALL copy_directory / ${COMPONENT_PATH}) endif() ExternalProject_Add(${COMPONENT_NAME} PREFIX ${COMPONENT_NAME} STAMP_DIR ${COMPONENT_NAME}/stamp SOURCE_DIR ${COMPONENT_NAME}/src BINARY_DIR ${COMPONENT_NAME} URL ${ISPC_URL} ${ISPC_URL_HASH} CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "${CMAKE_COMMAND}" -E ${ISPC_INSTALL} BUILD_ALWAYS OFF ) if (BUILD_ISPCRT_FROM_SOURCE) set(COMPONENT_NAME ispcrt) string(REGEX REPLACE "(^[0-9]+\.[0-9]+\.[0-9]+$)" "v\\1" ISPCRT_ARCHIVE ${ISPC_VERSION}) set(ISPCRT_BRANCH "${ISPCRT_ARCHIVE}" CACHE STRING "Which branch of ISPCRT to build" ) set(ISPCRT_URL "https://github.com/ispc/ispc/archive/refs/tags/${ISPCRT_ARCHIVE}.zip" CACHE STRING "Location to clone ISPCRT source from") string(REGEX MATCH ".*\.zip$" ZIP_FILENAME ${ISPCRT_URL}) if (ZIP_FILENAME) set(ISPCRT_CLONE_URL URL ${ISPCRT_URL}) if (ISPC_SOURCE_HASH) set(ISPCRT_URL_HASH URL_HASH SHA256=${ISPC_SOURCE_HASH}) endif() else() set(ISPCRT_CLONE_URL GIT_REPOSITORY ${ISPCRT_URL} GIT_TAG ${ISPCRT_BRANCH}) endif() ExternalProject_Add(${COMPONENT_NAME} PREFIX ${COMPONENT_NAME} STAMP_DIR ${COMPONENT_NAME}/stamp SOURCE_DIR ${COMPONENT_NAME}/src BINARY_DIR ${COMPONENT_NAME}/build LIST_SEPARATOR | SOURCE_SUBDIR "ispcrt" ${ISPCRT_CLONE_URL} ${ISPCRT_URL_HASH} CMAKE_ARGS -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_INSTALL_PREFIX:PATH=${COMPONENT_PATH} -DCMAKE_INSTALL_INCLUDEDIR=${CMAKE_INSTALL_INCLUDEDIR} -DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR} -DCMAKE_INSTALL_DOCDIR=${CMAKE_INSTALL_DOCDIR} -DCMAKE_INSTALL_BINDIR=${CMAKE_INSTALL_BINDIR} -DCMAKE_BUILD_TYPE=${DEPENDENCIES_BUILD_TYPE} -DISPCRT_BUILD_TASKING=OFF -DISPCRT_BUILD_GPU=${BUILD_GPU_SUPPORT} -DISPCRT_BUILD_TESTS=OFF -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} BUILD_ALWAYS ${ALWAYS_REBUILD} ) set(ISPCRT_LIBDIR ${CMAKE_INSTALL_LIBDIR}) add_dependencies(${COMPONENT_NAME} ispc) ExternalProject_Add_StepTargets(${COMPONENT_NAME} configure ispc) endif() set(ispcrt_DIR "${COMPONENT_PATH}/${ISPCRT_LIBDIR}/cmake/ispcrt-${ISPC_VERSION}") list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") RenderKit-ospray-f2a61c2/scripts/superbuild/dependencies/dep_oidn.cmake000066400000000000000000000064451456566705700264360ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME oidn) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}) if (INSTALL_IN_SEPARATE_DIRECTORIES) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/${COMPONENT_NAME}) endif() if (OIDN_HASH) set(OIDN_URL_HASH URL_HASH SHA256=${OIDN_HASH}) endif() if (BUILD_OIDN_FROM_SOURCE) if(${OIDN_VERSION} MATCHES "(^[0-9]+\.[0-9]+\.[0-9]+$)") set(OIDN_DEFAULT_URL "https://github.com/OpenImageDenoise/oidn/releases/download/v${OIDN_VERSION}/oidn-${OIDN_VERSION}.src.tar.gz") else() set(OIDN_DEFAULT_URL "https://www.github.com/OpenImageDenoise/oidn.git") endif() set(OIDN_URL ${OIDN_DEFAULT_URL} CACHE STRING "Location to get OpenImageDenoise source from") if (${OIDN_URL} MATCHES ".*\.src\.tar\.gz$") set(OIDN_CLONE_URL URL ${OIDN_URL}) else() set(OIDN_CLONE_URL GIT_REPOSITORY ${OIDN_URL} GIT_TAG ${OIDN_VERSION}) endif() ExternalProject_Add(${COMPONENT_NAME} PREFIX ${COMPONENT_NAME} DOWNLOAD_DIR ${COMPONENT_NAME} STAMP_DIR ${COMPONENT_NAME}/stamp SOURCE_DIR ${COMPONENT_NAME}/src BINARY_DIR ${COMPONENT_NAME}/build LIST_SEPARATOR | # Use the alternate list separator ${OIDN_CLONE_URL} ${OIDN_URL_HASH} GIT_SHALLOW ON CMAKE_ARGS -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_INSTALL_PREFIX:PATH=${COMPONENT_PATH} -DCMAKE_INSTALL_INCLUDEDIR=${CMAKE_INSTALL_INCLUDEDIR} -DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR} -DCMAKE_INSTALL_DOCDIR=${CMAKE_INSTALL_DOCDIR} -DCMAKE_INSTALL_BINDIR=${CMAKE_INSTALL_BINDIR} $<$:-DTBB_ROOT=${TBB_PATH}> $<$:-DISPC_EXECUTABLE=${ISPC_PATH}> -DCMAKE_BUILD_TYPE=Release # XXX debug builds are currently broken -DOIDN_APPS=OFF -DOIDN_ZIP_MODE=ON # to set install RPATH -DOIDN_DEVICE_SYCL=${BUILD_GPU_SUPPORT} -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} BUILD_ALWAYS ${ALWAYS_REBUILD} ) if (DOWNLOAD_TBB) ExternalProject_Add_StepDependencies(${COMPONENT_NAME} configure tbb) endif() if (DOWNLOAD_ISPC) ExternalProject_Add_StepDependencies(${COMPONENT_NAME} configure ispc) endif() else() if (APPLE) set(OIDN_OSSUFFIX "${CMAKE_SYSTEM_PROCESSOR}.macos.tar.gz") elseif (WIN32) set(OIDN_OSSUFFIX "x64.windows.zip") else() set(OIDN_OSSUFFIX "x86_64.linux.tar.gz") endif() set(OIDN_URL "https://github.com/OpenImageDenoise/oidn/releases/download/v${OIDN_VERSION}/oidn-${OIDN_VERSION}.${OIDN_OSSUFFIX}") ExternalProject_Add(${COMPONENT_NAME} PREFIX ${COMPONENT_NAME} DOWNLOAD_DIR ${COMPONENT_NAME} STAMP_DIR ${COMPONENT_NAME}/stamp SOURCE_DIR ${COMPONENT_NAME}/src BINARY_DIR ${COMPONENT_NAME} URL ${OIDN_URL} ${OIDN_URL_HASH} CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "${CMAKE_COMMAND}" -E copy_directory / ${COMPONENT_PATH} BUILD_ALWAYS OFF ) endif() list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") RenderKit-ospray-f2a61c2/scripts/superbuild/dependencies/dep_openvkl.cmake000066400000000000000000000053131456566705700271540ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME openvkl) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}) if (INSTALL_IN_SEPARATE_DIRECTORIES) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/${COMPONENT_NAME}) endif() if (OPENVKL_HASH) set(OPENVKL_URL_HASH URL_HASH SHA256=${OPENVKL_HASH}) endif() string(REGEX REPLACE "(^[0-9]+\.[0-9]+\.[0-9]+$)" "v\\1" OPENVKL_ARCHIVE ${OPENVKL_VERSION}) set(OPENVKL_BRANCH "${OPENVKL_ARCHIVE}" CACHE STRING "Which branch of OpenVKL to build" ) set(OPENVKL_URL "https://github.com/openvkl/openvkl/archive/${OPENVKL_ARCHIVE}.zip" CACHE STRING "Location to clone OpenVKL source from") string(REGEX MATCH ".*\.zip$" ZIP_FILENAME ${OPENVKL_URL}) if (ZIP_FILENAME) set(OPENVKL_CLONE_URL URL ${OPENVKL_URL}) else() set(OPENVKL_CLONE_URL GIT_REPOSITORY ${OPENVKL_URL} GIT_TAG ${OPENVKL_BRANCH}) endif() ExternalProject_Add(${COMPONENT_NAME} PREFIX ${COMPONENT_NAME} DOWNLOAD_DIR ${COMPONENT_NAME} STAMP_DIR ${COMPONENT_NAME}/stamp SOURCE_DIR ${COMPONENT_NAME}/src BINARY_DIR ${COMPONENT_NAME}/build LIST_SEPARATOR | # Use the alternate list separator ${OPENVKL_CLONE_URL} ${OPENVKL_URL_HASH} CMAKE_ARGS -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_INSTALL_PREFIX:PATH=${COMPONENT_PATH} -DCMAKE_INSTALL_INCLUDEDIR=${CMAKE_INSTALL_INCLUDEDIR} -DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR} -DCMAKE_INSTALL_DOCDIR=${CMAKE_INSTALL_DOCDIR} -DCMAKE_INSTALL_BINDIR=${CMAKE_INSTALL_BINDIR} -DCMAKE_BUILD_TYPE=${DEPENDENCIES_BUILD_TYPE} $<$:-DRKCOMMON_TBB_ROOT=${TBB_PATH}> $<$:-DISPC_EXECUTABLE=${ISPC_PATH}> $<$:-Dispcrt_DIR=${ispcrt_DIR}> -DBUILD_BENCHMARKS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} -DOPENVKL_ISA_SSE4=${BUILD_ISA_SSE4} -DOPENVKL_ISA_AVX=${BUILD_ISA_AVX} -DOPENVKL_ISA_AVX2=${BUILD_ISA_AVX2} -DOPENVKL_ISA_AVX512SKX=${BUILD_ISA_AVX512} -DOPENVKL_ISA_NEON=${BUILD_ISA_NEON} -DOPENVKL_ISA_NEON2X=${BUILD_ISA_NEON2X} -DOPENVKL_ENABLE_DEVICE_GPU=${BUILD_GPU_SUPPORT} BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} BUILD_ALWAYS ${ALWAYS_REBUILD} ) list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") ExternalProject_Add_StepDependencies(${COMPONENT_NAME} configure rkcommon embree $<$:ispc> $<$:ispcrt> ) RenderKit-ospray-f2a61c2/scripts/superbuild/dependencies/dep_rkcommon.cmake000066400000000000000000000040111456566705700273150ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME rkcommon) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}) if (INSTALL_IN_SEPARATE_DIRECTORIES) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/${COMPONENT_NAME}) endif() if (RKCOMMON_HASH) set(RKCOMMON_URL_HASH URL_HASH SHA256=${RKCOMMON_HASH}) endif() string(REGEX REPLACE "(^[0-9]+\.[0-9]+\.[0-9]+$)" "v\\1" RKCOMMON_ARCHIVE ${RKCOMMON_VERSION}) set(RKCOMMON_URL "https://github.com/ospray/rkcommon/archive/${RKCOMMON_ARCHIVE}.zip" CACHE STRING "Location to get rkcommon source from") if (${RKCOMMON_URL} MATCHES ".*\.zip$") set(RKCOMMON_CLONE_URL URL ${RKCOMMON_URL}) else() set(RKCOMMON_CLONE_URL GIT_REPOSITORY ${RKCOMMON_URL} GIT_TAG ${RKCOMMON_VERSION}) endif() ExternalProject_Add(${COMPONENT_NAME} PREFIX ${COMPONENT_NAME} DOWNLOAD_DIR ${COMPONENT_NAME} STAMP_DIR ${COMPONENT_NAME}/stamp SOURCE_DIR ${COMPONENT_NAME}/src BINARY_DIR ${COMPONENT_NAME}/build LIST_SEPARATOR | ${RKCOMMON_CLONE_URL} ${RKCOMMON_URL_HASH} CMAKE_ARGS -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_INSTALL_PREFIX:PATH=${COMPONENT_PATH} -DCMAKE_INSTALL_INCLUDEDIR=${CMAKE_INSTALL_INCLUDEDIR} -DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR} -DCMAKE_INSTALL_DOCDIR=${CMAKE_INSTALL_DOCDIR} -DCMAKE_INSTALL_BINDIR=${CMAKE_INSTALL_BINDIR} -DCMAKE_BUILD_TYPE=${DEPENDENCIES_BUILD_TYPE} -DINSTALL_DEPS=OFF -DBUILD_TESTING=OFF $<$:-DRKCOMMON_TBB_ROOT=${TBB_PATH}> -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} BUILD_ALWAYS ${ALWAYS_REBUILD} ) ExternalProject_Add_StepTargets(${COMPONENT_NAME} NO_DEPENDS download) list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") if (DOWNLOAD_TBB) ExternalProject_Add_StepDependencies(${COMPONENT_NAME} configure tbb) endif() RenderKit-ospray-f2a61c2/scripts/superbuild/dependencies/dep_snappy.cmake000066400000000000000000000022031456566705700270030ustar00rootroot00000000000000## Copyright 2021 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME snappy) if (INSTALL_IN_SEPARATE_DIRECTORIES) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/${COMPONENT_NAME}) else() set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}) endif() ExternalProject_Add(${COMPONENT_NAME} URL "https://github.com/google/snappy/archive/refs/tags/1.1.10.zip" URL_HASH "SHA256=3c6f7b07f92120ebbba5f7742f2cc2386fd46c53f5730322b7b90d4afc126fca" # `patch` is not available on all systems, so use `git apply` instead PATCH_COMMAND git init -q . && git apply -v -p1 < ${CMAKE_CURRENT_SOURCE_DIR}/dependencies/snappy-sign-compare.patch # Skip updating on subsequent builds (faster) UPDATE_COMMAND "" CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${COMPONENT_PATH} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DBUILD_SHARED_LIBS:BOOL=OFF -DSNAPPY_BUILD_TESTS:BOOL=OFF -DSNAPPY_BUILD_BENCHMARKS:BOOL=OFF -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON -DCMAKE_BUILD_TYPE=${DEPENDENCIES_BUILD_TYPE} ) list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") RenderKit-ospray-f2a61c2/scripts/superbuild/dependencies/dep_tbb.cmake000066400000000000000000000050471456566705700262510ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 set(COMPONENT_NAME tbb) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}) if (INSTALL_IN_SEPARATE_DIRECTORIES) set(COMPONENT_PATH ${INSTALL_DIR_ABSOLUTE}/${COMPONENT_NAME}) endif() if (TBB_HASH) set(TBB_URL_HASH URL_HASH SHA256=${TBB_HASH}) endif() if (BUILD_TBB_FROM_SOURCE) string(REGEX REPLACE "(^[0-9]+\.[0-9]+\.[0-9]+$)" "v\\1" TBB_ARCHIVE ${TBB_VERSION}) ExternalProject_Add(${COMPONENT_NAME} PREFIX ${COMPONENT_NAME} DOWNLOAD_DIR ${COMPONENT_NAME} STAMP_DIR ${COMPONENT_NAME}/stamp SOURCE_DIR ${COMPONENT_NAME}/src BINARY_DIR ${COMPONENT_NAME}/build LIST_SEPARATOR | # Use the alternate list separator URL "https://github.com/oneapi-src/oneTBB/archive/refs/tags/${TBB_ARCHIVE}.zip" ${TBB_URL_HASH} CMAKE_ARGS -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_INSTALL_PREFIX:PATH=${COMPONENT_PATH} -DCMAKE_INSTALL_INCLUDEDIR=${CMAKE_INSTALL_INCLUDEDIR} -DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR} -DCMAKE_INSTALL_DOCDIR=${CMAKE_INSTALL_DOCDIR} -DCMAKE_INSTALL_BINDIR=${CMAKE_INSTALL_BINDIR} -DCMAKE_BUILD_TYPE=${DEPENDENCIES_BUILD_TYPE} -DTBB_TEST=OFF -DTBB_STRICT=OFF -DCMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} BUILD_COMMAND ${DEFAULT_BUILD_COMMAND} BUILD_ALWAYS ${ALWAYS_REBUILD} ) else() if (TBB_VERSION VERSION_LESS 2021) set(TBB_FOLDER "tbb") else() set(TBB_PREFIX "oneapi-") endif() if (APPLE) set(TBB_OSSUFFIX "mac.tgz") elseif (WIN32) set(TBB_OSSUFFIX "win.zip") else() set(TBB_OSSUFFIX "lin.tgz") endif() set(TBB_URL "https://github.com/oneapi-src/oneTBB/releases/download/v${TBB_VERSION}/${TBB_PREFIX}tbb-${TBB_VERSION}-${TBB_OSSUFFIX}") ExternalProject_Add(${COMPONENT_NAME} PREFIX ${COMPONENT_NAME} DOWNLOAD_DIR ${COMPONENT_NAME} STAMP_DIR ${COMPONENT_NAME}/stamp SOURCE_DIR ${COMPONENT_NAME}/src BINARY_DIR ${COMPONENT_NAME} URL ${TBB_URL} ${TBB_URL_HASH} CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "${CMAKE_COMMAND}" -E copy_directory /${TBB_FOLDER} ${COMPONENT_PATH} BUILD_ALWAYS OFF ) endif() set(TBB_PATH "${COMPONENT_PATH}") list(APPEND CMAKE_PREFIX_PATH ${COMPONENT_PATH}) string(REPLACE ";" "|" CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH}") RenderKit-ospray-f2a61c2/scripts/superbuild/dependencies/glfw.patch000066400000000000000000000100521456566705700256200ustar00rootroot00000000000000diff --git a/src/null_platform.h b/src/null_platform.h index 708975d1..d916b922 100644 --- a/src/null_platform.h +++ b/src/null_platform.h @@ -43,7 +43,7 @@ #include "null_joystick.h" #if defined(_GLFW_WIN32) - #define _glfw_dlopen(name) LoadLibraryA(name) + #define _glfw_dlopen(name) LoadLibraryExA(name,NULL,LOAD_LIBRARY_SEARCH_SYSTEM32) #define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle) #define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name) #else diff --git a/src/wgl_context.c b/src/wgl_context.c index eebf6cd5..8a72d676 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c @@ -405,7 +405,7 @@ GLFWbool _glfwInitWGL(void) if (_glfw.wgl.instance) return GLFW_TRUE; - _glfw.wgl.instance = LoadLibraryA("opengl32.dll"); + _glfw.wgl.instance = LoadLibraryExA("opengl32.dll",NULL,LOAD_LIBRARY_SEARCH_SYSTEM32); if (!_glfw.wgl.instance) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, diff --git a/src/win32_init.c b/src/win32_init.c index 885f32fa..5e698cc2 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -82,7 +82,7 @@ static GLFWbool loadLibraries(void) return GLFW_FALSE; } - _glfw.win32.user32.instance = LoadLibraryA("user32.dll"); + _glfw.win32.user32.instance = LoadLibraryExA("user32.dll",NULL,LOAD_LIBRARY_SEARCH_SYSTEM32); if (!_glfw.win32.user32.instance) { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, @@ -105,7 +105,7 @@ static GLFWbool loadLibraries(void) _glfw.win32.user32.GetSystemMetricsForDpi_ = (PFN_GetSystemMetricsForDpi) GetProcAddress(_glfw.win32.user32.instance, "GetSystemMetricsForDpi"); - _glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll"); + _glfw.win32.dinput8.instance = LoadLibraryExA("dinput8.dll",NULL,LOAD_LIBRARY_SEARCH_SYSTEM32); if (_glfw.win32.dinput8.instance) { _glfw.win32.dinput8.Create = (PFN_DirectInput8Create) @@ -126,7 +126,7 @@ static GLFWbool loadLibraries(void) for (i = 0; names[i]; i++) { - _glfw.win32.xinput.instance = LoadLibraryA(names[i]); + _glfw.win32.xinput.instance = LoadLibraryExA(names[i],NULL,LOAD_LIBRARY_SEARCH_SYSTEM32); if (_glfw.win32.xinput.instance) { _glfw.win32.xinput.GetCapabilities = (PFN_XInputGetCapabilities) @@ -139,7 +139,7 @@ static GLFWbool loadLibraries(void) } } - _glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll"); + _glfw.win32.dwmapi.instance = LoadLibraryExA("dwmapi.dll",NULL,LOAD_LIBRARY_SEARCH_SYSTEM32); if (_glfw.win32.dwmapi.instance) { _glfw.win32.dwmapi.IsCompositionEnabled = (PFN_DwmIsCompositionEnabled) @@ -152,7 +152,7 @@ static GLFWbool loadLibraries(void) GetProcAddress(_glfw.win32.dwmapi.instance, "DwmGetColorizationColor"); } - _glfw.win32.shcore.instance = LoadLibraryA("shcore.dll"); + _glfw.win32.shcore.instance = LoadLibraryExA("shcore.dll",NULL,LOAD_LIBRARY_SEARCH_SYSTEM32); if (_glfw.win32.shcore.instance) { _glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness) @@ -161,7 +161,7 @@ static GLFWbool loadLibraries(void) GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor"); } - _glfw.win32.ntdll.instance = LoadLibraryA("ntdll.dll"); + _glfw.win32.ntdll.instance = LoadLibraryExA("ntdll.dll",NULL,LOAD_LIBRARY_SEARCH_SYSTEM32); if (_glfw.win32.ntdll.instance) { _glfw.win32.ntdll.RtlVerifyVersionInfo_ = (PFN_RtlVerifyVersionInfo) diff --git a/src/win32_platform.h b/src/win32_platform.h index e729709f..4a7d8068 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -289,7 +289,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)( #define _GLFW_WNDCLASSNAME L"GLFW30" #endif -#define _glfw_dlopen(name) LoadLibraryA(name) +#define _glfw_dlopen(name) LoadLibraryExA(name,NULL,LOAD_LIBRARY_SEARCH_SYSTEM32) #define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle) #define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name) RenderKit-ospray-f2a61c2/scripts/superbuild/dependencies/snappy-sign-compare.patch000066400000000000000000000012511456566705700305560ustar00rootroot00000000000000commit 27f34a580be4a3becf5f8c0cba13433f53c21337 Author: Richard O'Grady Date: Wed Jul 12 19:12:01 2023 Fix -Wsign-compare warning PiperOrigin-RevId: 547529709 diff --git a/snappy.cc b/snappy.cc index 688065b..6473123 100644 --- a/snappy.cc +++ b/snappy.cc @@ -1289,7 +1289,7 @@ std::pair DecompressBranchless( DeferMemCopy(&deferred_src, &deferred_length, from, len); } } while (ip < ip_limit_min_slop && - (op + deferred_length) < op_limit_min_slop); + static_cast(op + deferred_length) < op_limit_min_slop); exit: ip--; assert(ip <= ip_limit); RenderKit-ospray-f2a61c2/scripts/superbuild/toolchains/000077500000000000000000000000001456566705700233575ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/scripts/superbuild/toolchains/macos-rosetta.cmake000066400000000000000000000012201456566705700271350ustar00rootroot00000000000000## Copyright 2022 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # This toolchain file is used to cross-compile OSPRay for x86_64 on ARM-based # MacOS systems (i.e., to run in Rosetta). Although OSPRay itself builds a # native ARM/M1 binary by default, compiling for x86_64 can be useful on such # systems when integrating OSPRay with applications that do not run natively on # ARM yet. set(CMAKE_SYSTEM_NAME Darwin) set(CMAKE_SYSTEM_PROCESSOR x86_64) set(CLANG_TRIPLE x86_64-apple-darwin) set(CMAKE_C_COMPILER clang) set(CMAKE_C_COMPILER_TARGET ${CLANG_TRIPLE}) set(CMAKE_CXX_COMPILER clang++) set(CMAKE_CXX_COMPILER_TARGET ${CLANG_TRIPLE}) RenderKit-ospray-f2a61c2/scripts/tests/000077500000000000000000000000001456566705700202005ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/scripts/tests/README000066400000000000000000000042471456566705700210670ustar00rootroot00000000000000Running Tests ------------- notes for all items: ${OSPRAY_SOURCE_DIR} is the ospray source root. PATH and LD_LIBRARY_PATH should contain ${OSPRAY_BUILD_DIR}. 1. Build OSPRay Compile OSPRay in a build directory of your choosing. We will refer to this directory as ${OSPRAY_BUILD_DIR}. 2. Generate baseline images (OPTIONAL) Build OSPRay with OSPRAY_TESTING on. Only generate new images for a test that has changed. To generate new images for a specific test run ./ospTestSuite --gtest_filter="*TESTNAME*" --dump-img --baseline-dir=test_image_data/ which will create images in a folder called test_image_data. To make new images for all tests, In ${OSPRAY_BUILD_DIR}, run the "generate_baseline.sh" script: % ${OSPRAY_SOURCE_DIR}/scripts/tests/generate_baseline.sh This will output generated images in a folder named generated_test_images. These images will not automatically be used as baseline images for the tests unless put into the correct folder (/build_regression_tests/regression_test_baseline/) or the update script is used (5). 3. Run regression tests To verify whether a change to the codebase broke anything, run % ${OSPRAY_SOURCE_DIR}/scripts/tests/run_tests.sh ${OSPRAY_SOURCE_DIR} * where ISA is empty if using own generated images, or "AVX2" or "AVX512SKX" to * download golden images for that ISA target This will download golden baseline images into a folder named build_regression_tests/regression_test_baseline in the current working directory (OSPRAY_BUILD_DIR) and run tests to compare them. 4. To run an individual test ./ospTestSuite --gtest_list_tests this will output a list of test names ./ospTestSuite --gest_filter="*NAME*" will run a single test 5. Add or update generated test images to ospray Use the included update_test_baseline.sh script and then send the resulting files to ospray developers or do the following steps: call md5sum on the resulting .png files. Add a .png.md5 file to tests/baseling/TESTNAME.png.md5 with the value of the checksum. rename the .png file to be the checksum value, and then send this to OSPRay Devs who will add it to https://github.com/ospray/ospray-test-data / https://www.ospray.org/ospray-test-data/. RenderKit-ospray-f2a61c2/scripts/tests/generate_baseline.bat000066400000000000000000000003311456566705700243210ustar00rootroot00000000000000@echo off rem Copyright 2016 Intel Corporation rem SPDX-License-Identifier: Apache-2.0 setlocal md generated_test_images ospTestSuite --dump-img --baseline-dir=generated_test_images exit /B %ERRORLEBEL% endlocal RenderKit-ospray-f2a61c2/scripts/tests/generate_baseline.sh000077500000000000000000000004601456566705700241730ustar00rootroot00000000000000#!/bin/bash ## Copyright 2016 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # results are put in a new folder called generated_test_images rm -rf generated_test_images mkdir generated_test_images ospTestSuite --dump-img --baseline-dir=generated_test_images/ FAILED=$(echo $?) exit $FAILED RenderKit-ospray-f2a61c2/scripts/tests/run-benchmarks.sh000077500000000000000000000112511456566705700234560ustar00rootroot00000000000000#!/bin/bash -xe ## Copyright 2020 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # benchmark configuration SOURCE_ROOT=`pwd` PROJECT_NAME="OSPRay" BENCHMARK_FLAGS="--benchmark_min_time=${BENCHMARK_MIN_TIME_SECONDS:-10s}" if [ "$1" = "GPU" ] ; then BENCHMARK_FLAGS="$BENCHMARK_FLAGS --benchmark_time_unit=s --benchmark_min_warmup_time=2 --osp:load-modules=gpu --osp:device=gpu" export ONEAPI_DEVICE_SELECTOR=level_zero:* export SYCL_CACHE_PERSISTENT=1 export OIDN_VERBOSE=2 export ZE_FLAT_DEVICE_HIERARCHY=COMPOSITE # WA for PVC fi export LD_LIBRARY_PATH=`pwd`/build/install/ospray/lib:${LD_LIBRARY_PATH} cd build/install/ospray/bin rm -f *.json ################################# PLEASE READ ################################## # # Note that suites and subsuites must exist in the database _before_ attempting # insertion of results. This is intentional! You should think carefully about # your [suite -> subsuite -> benchmark] hierarchy and definitions. These should # be stable over time (especially for suites and subsuites) to facilitate # long-term comparisons. # # These can be inserted using the benchmark client, through the "insert suite" # and "insert subsuite" commands. Ask for help if you have questions. # ################################# PLEASE READ ################################### ###################### # Example benchmarks # ###################### SUITE_NAME="Examples" SUBSUITE_NAME="BoxesAO" SUBSUITE_REGEX="^boxes" ./ospBenchmark ${BENCHMARK_FLAGS} --benchmark_filter=${SUBSUITE_REGEX} --benchmark_out=results-${SUITE_NAME}-${SUBSUITE_NAME}.json # wait to insert contexts (which will be reused for all subsequent benchmark runs) # until first benchmark successfully finishes. benny insert code_context "${PROJECT_NAME}" ${SOURCE_ROOT} --save-json code_context.json benny insert run_context ${BENNY_SYSTEM_TOKEN} ./code_context.json --save-json run_context.json benny insert googlebenchmark ./run_context.json ${SUITE_NAME} ${SUBSUITE_NAME} ./results-${SUITE_NAME}-${SUBSUITE_NAME}.json # subsequent subsuite runs... SUBSUITE_NAME="CornellBoxSPP" SUBSUITE_REGEX="^cornell_box" ./ospBenchmark ${BENCHMARK_FLAGS} --benchmark_filter=${SUBSUITE_REGEX} --benchmark_out=results-${SUITE_NAME}-${SUBSUITE_NAME}.json benny insert googlebenchmark ./run_context.json ${SUITE_NAME} ${SUBSUITE_NAME} ./results-${SUITE_NAME}-${SUBSUITE_NAME}.json SUBSUITE_NAME="GravitySpheresVolumeDIM" SUBSUITE_REGEX="^gravity_spheres_volume" ./ospBenchmark ${BENCHMARK_FLAGS} --benchmark_filter=${SUBSUITE_REGEX} --benchmark_out=results-${SUITE_NAME}-${SUBSUITE_NAME}.json benny insert googlebenchmark ./run_context.json ${SUITE_NAME} ${SUBSUITE_NAME} ./results-${SUITE_NAME}-${SUBSUITE_NAME}.json SUBSUITE_NAME="PerlinNoiseVolumes" SUBSUITE_REGEX="^perlin_noise_volumes" ./ospBenchmark ${BENCHMARK_FLAGS} --benchmark_filter=${SUBSUITE_REGEX} --benchmark_out=results-${SUITE_NAME}-${SUBSUITE_NAME}.json benny insert googlebenchmark ./run_context.json ${SUITE_NAME} ${SUBSUITE_NAME} ./results-${SUITE_NAME}-${SUBSUITE_NAME}.json SUBSUITE_NAME="ParticleVolumes" SUBSUITE_REGEX="^particle_volume" ./ospBenchmark ${BENCHMARK_FLAGS} --benchmark_filter=${SUBSUITE_REGEX} --benchmark_out=results-${SUITE_NAME}-${SUBSUITE_NAME}.json benny insert googlebenchmark ./run_context.json ${SUITE_NAME} ${SUBSUITE_NAME} ./results-${SUITE_NAME}-${SUBSUITE_NAME}.json SUBSUITE_NAME="UnstructuredVolumes" SUBSUITE_REGEX="^unstructured_volume" ./ospBenchmark ${BENCHMARK_FLAGS} --benchmark_filter=${SUBSUITE_REGEX} --benchmark_out=results-${SUITE_NAME}-${SUBSUITE_NAME}.json benny insert googlebenchmark ./run_context.json ${SUITE_NAME} ${SUBSUITE_NAME} ./results-${SUITE_NAME}-${SUBSUITE_NAME}.json SUBSUITE_NAME="Clipping" SUBSUITE_REGEX="^clip" ./ospBenchmark ${BENCHMARK_FLAGS} --benchmark_filter=${SUBSUITE_REGEX} --benchmark_out=results-${SUITE_NAME}-${SUBSUITE_NAME}.json benny insert googlebenchmark ./run_context.json ${SUITE_NAME} ${SUBSUITE_NAME} ./results-${SUITE_NAME}-${SUBSUITE_NAME}.json SUBSUITE_NAME="Other" SUBSUITE_REGEX="^(random_spheres|streamlines|planes|vdb_volume|gravity_spheres_amr)" ./ospBenchmark ${BENCHMARK_FLAGS} --benchmark_filter=${SUBSUITE_REGEX} --benchmark_out=results-${SUITE_NAME}-${SUBSUITE_NAME}.json benny insert googlebenchmark ./run_context.json ${SUITE_NAME} ${SUBSUITE_NAME} ./results-${SUITE_NAME}-${SUBSUITE_NAME}.json ################### # Microbenchmarks # ################### SUITE_NAME="Microbenchmarks" SUBSUITE_NAME="Setup" SUBSUITE_REGEX="^setup" ./ospBenchmark ${BENCHMARK_FLAGS} --benchmark_filter=${SUBSUITE_REGEX} --benchmark_out=results-${SUITE_NAME}-${SUBSUITE_NAME}.json benny insert googlebenchmark ./run_context.json ${SUITE_NAME} ${SUBSUITE_NAME} ./results-${SUITE_NAME}-${SUBSUITE_NAME}.json RenderKit-ospray-f2a61c2/scripts/tests/run_gpu_tests.ps1000077500000000000000000000123101456566705700235260ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # to run: ./run_tests.ps1 [SKIP_GPU] [TEST_MPI] [TEST_MULTIDEVICE] # a new folder is created called build_regression_tests with results $osprayDir=$args[0] $testGPU = $TRUE $testMPI = $FALSE $testMultiDevice = $FALSE foreach ($arg in $args) { if ($arg -eq "SKIP_GPU") { $testGPU = $FALSE } if ($arg -eq "TEST_MPI") { $testMPI = $TRUE } if ($arg -eq "TEST_MULTIDEVICE") { $testMultiDevice = $TRUE } } md build_regression_tests cd build_regression_tests $exitCode = 0 # try Ninja first cmake -G Ninja -D OSPRAY_TEST_ISA=AVX512SKX $osprayDir/test_image_data if ($LastExitCode) { cmake -D OSPRAY_TEST_ISA=AVX512SKX $osprayDir/test_image_data if ($LastExitCode) { $exitCode++ } } cmake --build . --config Release --target ospray_test_data if ($LastExitCode) { $exitCode++ } ### Excluded tests on GPU ######################### # Clipping unsupported $test_filters="ClippingParallel.planes" $test_filters+=":TestScenesClipping/FromOsprayTesting.*" $test_filters+=":TestScenesMaxDepth/FromOsprayTestingMaxDepth.test_scenes/1" $test_filters+=":TestScenesMaxDepth/FromOsprayTestingMaxDepth.test_scenes/2" $test_filters+=":TestMotionBlur/MotionBlurBoxes.*" $test_filters+=":CameraRollingShutter/MotionBlurBoxes.*" $test_filters+=":CameraStereoRollingShutter/MotionBlurBoxes.*" # Subdivision surfaces unsupported $test_filters+=":TestScenesGeometry/FromOsprayTesting.test_scenes/15" $test_filters+=":TestScenesGeometry/FromOsprayTesting.test_scenes/16" $test_filters+=":TestScenesGeometry/FromOsprayTesting.test_scenes/17" $test_filters+=":Color/Interpolation.Interpolation/4" $test_filters+=":Color/Interpolation.Interpolation/5" $test_filters+=":Color/Interpolation.Interpolation/6" $test_filters+=":Color/Interpolation.Interpolation/7" $test_filters+=":Texcoord/Interpolation.Interpolation/2" $test_filters+=":Texcoord/Interpolation.Interpolation/3" # Multiple volumes unsupported $test_filters+=":TestScenesVolumes/FromOsprayTesting.test_scenes/3" $test_filters+=":TestScenesVolumes/FromOsprayTesting.test_scenes/4" $test_filters+=":TestScenesVolumes/FromOsprayTesting.test_scenes/5" $test_filters+=":TestScenesVolumesStrictParams/FromOsprayTesting.*" # Requires non-overlapping multiple volume support on GPU $test_filters+=":ObjectInstance/IDBuffer.*" # Instancing test includes multiple volumes $test_filters+=":TestScenesGeometry/FromOsprayTesting.test_scenes/24" $test_filters+=":TestScenesGeometry/FromOsprayTesting.test_scenes/25" $test_filters+=":TestScenesGeometry/FromOsprayTesting.test_scenes/26" # 'mix' material not supported on GPU (not practical to implement without fn ptr) $test_filters+=":TestScenesPtMaterials/FromOsprayTesting.test_scenes/8" # Crashing FIXME $test_filters+=":Primitive/IDBuffer.*" # Different noise $test_filters+=":TestScenesVolumes/FromOsprayTesting.test_scenes/1" # Artifacts $test_filters+=":TestScenesPtMaterials/FromOsprayTesting.test_scenes/5" ## Windows only (driver?) # Artifacts $test_filters+=":TestScenesPtMaterials/FromOsprayTesting.test_scenes/4" # Artifacts with dpcpp (icx is fine) $test_filters+=":TestScenesGeometry/FromOsprayTesting.test_scenes/23" $test_filters+=":TestScenesVolumes/FromOsprayTesting.test_scenes/7" # Artifacts with icx (dpcpp is fine) $test_filters+=":Light/GeometricLight.parameter/2" $test_filters+=":LightTexture/GeometricLight.parameter/0" $test_filters+=":LightTexture/GeometricLight.parameter/1" $env:ONEAPI_DEVICE_SELECTOR="level_zero:*" $env:SYCL_CACHE_PERSISTENT="1" $env:OIDN_VERBOSE="2" if ($testGPU) { md failed-gpu ospTestSuite.exe --gtest_output=xml:tests.xml --baseline-dir=regression_test_baseline\ --failed-dir=failed-gpu --osp:load-modules=gpu --osp:device=gpu --gtest_filter="-$test_filters" --own-SYCL if ($LastExitCode) { $exitCode++ } $env:OSPRAY_ALLOW_DEVICE_MEMORY = "1" ospTestSuite.exe --gtest_output=xml:tests.xml --baseline-dir=regression_test_baseline\ --failed-dir=failed-gpu --osp:load-modules=gpu --osp:device=gpu --gtest_filter=SharedData/TestUSMSharing.structured_regular/2 --own-SYCL if ($LastExitCode) { $exitCode++ } $env:OSPRAY_ALLOW_DEVICE_MEMORY = "0" } if ($testMultiDevice) { md failed-multidevice $env:OSPRAY_NUM_SUBDEVICES=2 ospTestSuite.exe --osp:load-modules=multidevice_cpu --osp:device=multidevice --gtest_output=xml:tests-multidevice.xml --baseline-dir=regression_test_baseline\ --failed-dir=failed-multidevice --gtest_filter="-$test_filters" if ($LastExitCode) { $exitCode++ } } if ($testMPI) { md failed-mpi-gpu $env:OSPRAY_MPI_DISTRIBUTED_GPU=1 mpiexec.exe -np 1 ospTestSuite.exe --osp:load-modules=mpi_offload --osp:device=mpiOffload --gtest_output=xml:tests-mpi.xml --baseline-dir=regression_test_baseline\ --failed-dir=failed-mpi-gpu --gtest_filter="-$test_filters" : -np 2 ospray_mpi_worker.exe if ($LastExitCode) { $exitCode++ } md failed-mpi-gpu-data-parallel $test_filters="MPIDistribTestScenesVolumes/MPIFromOsprayTesting.test_scenes/1" # FIXME mpiexec.exe -np 3 -prepend-rank ospMPIDistribTestSuite.exe --gtest_output=xml:tests-mpi.xml --baseline-dir=regression_test_baseline\ --failed-dir=failed-mpi-gpu-data-parallel --gtest_filter="-$test_filters" if ($LastExitCode) { $exitCode++ } } exit $exitCode RenderKit-ospray-f2a61c2/scripts/tests/run_gpu_tests.sh000077500000000000000000000127041456566705700234440ustar00rootroot00000000000000#!/bin/bash ## Copyright 2022 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # to run: ./run_tests.sh [SKIP_GPU] [TEST_MPI] [TEST_MULTIDEVICE] # a new folder is created called build_regression_tests with results SOURCEDIR=$([[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}") if [ -z "$MPI_ROOT_CONFIG" ]; then MPI_ROOT_CONFIG="-np 1" fi if [ -z "$MPI_WORKER_CONFIG" ]; then MPI_WORKER_CONFIG="-np 2" fi # optional command line arguments TEST_GPU=true while [[ $# -gt 0 ]] do key="$1" case $key in SKIP_GPU) unset TEST_GPU shift ;; TEST_MPI) TEST_MPI=true shift ;; TEST_MULTIDEVICE) TEST_MULTIDEVICE=true shift ;; *) shift ;; esac done mkdir build_regression_tests cd build_regression_tests exitCode=0 cmake -D OSPRAY_TEST_ISA=AVX512SKX "${SOURCEDIR}/test_image_data" let exitCode+=$? export CMAKE_BUILD_PARALLEL_LEVEL=32 cmake --build . --target ospray_test_data let exitCode+=$? ### Excluded tests on GPU ######################### # Clipping unsupported test_filters="ClippingParallel.planes" test_filters+=":TestScenesClipping/FromOsprayTesting.*" test_filters+=":TestScenesMaxDepth/FromOsprayTestingMaxDepth.test_scenes/1" test_filters+=":TestScenesMaxDepth/FromOsprayTestingMaxDepth.test_scenes/2" test_filters+=":TestMotionBlur/MotionBlurBoxes.*" test_filters+=":CameraRollingShutter/MotionBlurBoxes.*" test_filters+=":CameraStereoRollingShutter/MotionBlurBoxes.*" # Subdivision surfaces unsupported test_filters+=":TestScenesGeometry/FromOsprayTesting.test_scenes/15" test_filters+=":TestScenesGeometry/FromOsprayTesting.test_scenes/16" test_filters+=":TestScenesGeometry/FromOsprayTesting.test_scenes/17" test_filters+=":Color/Interpolation.Interpolation/4" test_filters+=":Color/Interpolation.Interpolation/5" test_filters+=":Color/Interpolation.Interpolation/6" test_filters+=":Color/Interpolation.Interpolation/7" test_filters+=":Texcoord/Interpolation.Interpolation/2" test_filters+=":Texcoord/Interpolation.Interpolation/3" # Multiple volumes unsupported test_filters+=":TestScenesVolumes/FromOsprayTesting.test_scenes/3" test_filters+=":TestScenesVolumes/FromOsprayTesting.test_scenes/4" test_filters+=":TestScenesVolumes/FromOsprayTesting.test_scenes/5" test_filters+=":TestScenesVolumesStrictParams/FromOsprayTesting.*" # Requires non-overlapping multiple volume support on GPU test_filters+=":ObjectInstance/IDBuffer.*" # Instancing test includes multiple volumes test_filters+=":TestScenesGeometry/FromOsprayTesting.test_scenes/24" test_filters+=":TestScenesGeometry/FromOsprayTesting.test_scenes/25" test_filters+=":TestScenesGeometry/FromOsprayTesting.test_scenes/26" # 'mix' material not supported on GPU (not practical to implement without fn ptr) test_filters+=":TestScenesPtMaterials/FromOsprayTesting.test_scenes/8" # Crashing FIXME test_filters+=":Primitive/IDBuffer.*" # Different noise test_filters+=":TestScenesVolumes/FromOsprayTesting.test_scenes/1" # Artifacts test_filters+=":TestScenesPtMaterials/FromOsprayTesting.test_scenes/5" ## Linux only (driver?) # Artifacts test_filters+=":Renderers/TextureVolumeTransform.simple/0" test_filters+=":Appearance/Texture2D.filter/*" test_filters+=":Texcoord/Interpolation.Interpolation/0" test_filters+=":Texcoord/Interpolation.Interpolation/1" # Artifacts on PVC only (DG2 is fine) test_filters+=":Appearance/Texture2DTransform.simple/0" test_filters+=":Appearance/Texture2DWrapMode.wrap/*" export ONEAPI_DEVICE_SELECTOR=level_zero:* export SYCL_CACHE_PERSISTENT=1 export OIDN_VERBOSE=2 export ZE_FLAT_DEVICE_HIERARCHY=COMPOSITE # WA for PVC if [ $TEST_GPU ]; then mkdir failed-gpu ospTestSuite --gtest_output=xml:tests.xml --baseline-dir=regression_test_baseline/ --failed-dir=failed-gpu --osp:load-modules=gpu --osp:device=gpu --gtest_filter="-$test_filters" --own-SYCL let exitCode+=$? OSPRAY_ALLOW_DEVICE_MEMORY=1 ospTestSuite --baseline-dir=regression_test_baseline/ --failed-dir=failed-gpu --osp:load-modules=gpu --osp:device=gpu --gtest_filter=SharedData/TestUSMSharing.structured_regular/2 --own-SYCL let exitCode+=$? fi if [ $TEST_MULTIDEVICE ]; then mkdir failed-multidevice OSPRAY_NUM_SUBDEVICES=2 ospTestSuite --gtest_output=xml:tests.xml --baseline-dir=regression_test_baseline/ --failed-dir=failed-multidevice --gtest_filter="-$test_filters" --osp:load-modules=multidevice_gpu --osp:device=multidevice --own-SYCL let exitCode+=$? OSPRAY_ALLOW_DEVICE_MEMORY=1 OSPRAY_NUM_SUBDEVICES=2 ospTestSuite --gtest_output=xml:tests.xml --baseline-dir=regression_test_baseline/ --failed-dir=failed-multidevice --gtest_filter=SharedData/TestUSMSharing.structured_regular/2 --osp:load-modules=multidevice_gpu --osp:device=multidevice --own-SYCL let exitCode+=$? fi if [ $TEST_MPI ]; then mkdir failed-mpi-gpu # Need to export, not just set for MPI to pick it up export OSPRAY_MPI_DISTRIBUTED_GPU=1 mpiexec $MPI_ROOT_CONFIG ospTestSuite --gtest_output=xml:tests-mpi-offload.xml --baseline-dir=regression_test_baseline/ --failed-dir=failed-mpi-gpu --osp:load-modules=mpi_offload --osp:device=mpiOffload --gtest_filter="-$test_filters" : $MPI_WORKER_CONFIG ospray_mpi_worker let exitCode+=$? mkdir failed-mpi-gpu-data-parallel test_filters="MPIDistribTestScenesVolumes/MPIFromOsprayTesting.test_scenes/1" # FIXME mpiexec -np 3 ospMPIDistribTestSuite --gtest_output=xml:tests-mpi-distrib.xml --baseline-dir=regression_test_baseline/ --failed-dir=failed-mpi-gpu-data-parallel --gtest_filter="-$test_filters" let exitCode+=$? fi exit $exitCode RenderKit-ospray-f2a61c2/scripts/tests/run_tests.ps1000077500000000000000000000040471456566705700226630ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # to run: ./run_tests.ps1 [SKIP_CPU] [TEST_MPI] [TEST_MULTIDEVICE] # a new folder is created called build_regression_tests with results $osprayDir=$args[0] $testISA=$args[1] $testCPU = $TRUE $testMPI = $FALSE $testMultiDevice = $FALSE foreach ($arg in $args) { if ($arg -eq "SKIP_CPU") { $testCPU = $FALSE } if ($arg -eq "TEST_MPI") { $testMPI = $TRUE } if ($arg -eq "TEST_MULTIDEVICE") { $testMultiDevice = $TRUE } } md build_regression_tests cd build_regression_tests $exitCode = 0 # try Ninja first cmake -G Ninja -D OSPRAY_TEST_ISA=$testISA $osprayDir/test_image_data if ($LastExitCode) { cmake -D OSPRAY_TEST_ISA=$testISA $osprayDir/test_image_data if ($LastExitCode) { $exitCode++ } } cmake --build . --config Release --target ospray_test_data if ($LastExitCode) { $exitCode++ } if ($testCPU) { md failed ospTestSuite.exe --gtest_output=xml:tests.xml --baseline-dir=regression_test_baseline\ --failed-dir=failed if ($LastExitCode) { $exitCode++ } } if ($testMultiDevice) { md failed-multidevice $env:OSPRAY_NUM_SUBDEVICES=2 ospTestSuite.exe --osp:load-modules=multidevice_cpu --osp:device=multidevice --gtest_output=xml:tests-multidevice.xml --baseline-dir=regression_test_baseline\ --failed-dir=failed-multidevice --gtest_filter="-$test_filters" if ($LastExitCode) { $exitCode++ } } if ($testMPI) { md failed-mpi $test_filters += ":TestScenesVariance/*" mpiexec.exe -np 1 ospTestSuite.exe --osp:load-modules=mpi_offload --osp:device=mpiOffload --gtest_output=xml:tests-mpi.xml --baseline-dir=regression_test_baseline\ --failed-dir=failed-mpi --gtest_filter="-$test_filters" : -np 2 ospray_mpi_worker.exe if ($LastExitCode) { $exitCode++ } md failed-mpi-data-parallel mpiexec.exe -np 3 -prepend-rank ospMPIDistribTestSuite.exe --gtest_output=xml:tests-mpi.xml --baseline-dir=regression_test_baseline\ --failed-dir=failed-mpi-data-parallel if ($LastExitCode) { $exitCode++ } } exit $exitCode RenderKit-ospray-f2a61c2/scripts/tests/run_tests.sh000077500000000000000000000043511456566705700225700ustar00rootroot00000000000000#!/bin/bash ## Copyright 2016 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 # to run: ./run_tests.sh [SKIP_CPU] [TEST_MPI] [TEST_MULTIDEVICE] # a new folder is created called build_regression_tests with results if [ -z "$MPI_ROOT_CONFIG" ]; then MPI_ROOT_CONFIG="-np 1" fi if [ -z "$MPI_WORKER_CONFIG" ]; then MPI_WORKER_CONFIG="-np 2" fi if [ -z "$1" ]; then echo "usage: run_tests.sh [TEST_MPI] [TEST_MULTIDEVICE]" exit -1 fi # Expand relative paths. SOURCEDIR=$([[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}") TESTISA=$2 # optional command line arguments TEST_CPU=true while [[ $# -gt 0 ]] do key="$1" case $key in SKIP_CPU) unset TEST_CPU shift ;; TEST_MPI) TEST_MPI=true shift ;; TEST_MULTIDEVICE) TEST_MULTIDEVICE=true shift ;; *) shift ;; esac done mkdir build_regression_tests cd build_regression_tests exitCode=0 cmake -D OSPRAY_TEST_ISA=$TESTISA ${SOURCEDIR}/test_image_data let exitCode+=$? export CMAKE_BUILD_PARALLEL_LEVEL=32 cmake --build . --target ospray_test_data let exitCode+=$? export OIDN_VERBOSE=2 if [ $TEST_CPU ]; then mkdir failed ospTestSuite --gtest_output=xml:tests.xml --baseline-dir=regression_test_baseline/ --failed-dir=failed let exitCode+=$? fi if [ $TEST_MULTIDEVICE ]; then mkdir failed-multidevice OSPRAY_NUM_SUBDEVICES=2 ospTestSuite --gtest_output=xml:tests.xml --baseline-dir=regression_test_baseline/ --failed-dir=failed-multidevice --gtest_filter="-$test_filters" --osp:load-modules=multidevice_cpu --osp:device=multidevice let exitCode+=$? fi if [ $TEST_MPI ]; then mkdir failed-mpi test_filters="TestScenesVariance/*" mpiexec $MPI_ROOT_CONFIG ospTestSuite --gtest_output=xml:tests-mpi-offload.xml --baseline-dir=regression_test_baseline/ --failed-dir=failed-mpi --gtest_filter="-$test_filters" --osp:load-modules=mpi_offload --osp:device=mpiOffload : $MPI_WORKER_CONFIG ospray_mpi_worker let exitCode+=$? mkdir failed-mpi-data-parallel mpiexec -np 3 ospMPIDistribTestSuite --gtest_output=xml:tests-mpi-distrib.xml --baseline-dir=regression_test_baseline/ --failed-dir=failed-mpi-data-parallel let exitCode+=$? fi exit $exitCode RenderKit-ospray-f2a61c2/scripts/tests/run_tutorials.sh000077500000000000000000000012541456566705700234530ustar00rootroot00000000000000#!/bin/bash ## Copyright 2016 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 export LD_LIBRARY_PATH=`pwd`/build/install/ospray/lib:$LD_LIBRARY_PATH export DYLD_LIBRARY_PATH=`pwd`/build/install/ospray/lib:$DYLD_LIBRARY_PATH export PATH=`pwd`/build/install/ospray/bin:$PATH exitCode=0 echo -e "\n\nRunning 'ospTutorial'..." ospTutorial let exitCode+=$? echo -e "\n\nRunning 'ospTutorialCpp'..." ospTutorialCpp let exitCode+=$? echo -e "\n\nRunning 'ospTutorialAsync'..." ospTutorialAsync let exitCode+=$? if [[ -x `pwd`/build/install/ospray/bin/ospTutorialGLM ]] ; then echo -e "\n\nRunning 'ospTutorialGLM'..." ospTutorialGLM let exitCode+=$? fi exit $exitCode RenderKit-ospray-f2a61c2/scripts/tests/sanitize_ignore.txt000066400000000000000000000001421456566705700241270ustar00rootroot00000000000000# Ignore TBB memory leaks as TBB worker threads may terminate after # the main thread leak:libtbb RenderKit-ospray-f2a61c2/scripts/tests/update_test_baseline.sh000077500000000000000000000013251456566705700247230ustar00rootroot00000000000000#!/bin/bash ## Copyright 2016 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 #author=Carson Brownlee #generates md5 checksums for generated regression test image # and uploads checksum and image to sdvis server # # argument 1: name of test # argument 2: directory of test result images # argument 3: path of ospray source # argument 4: path to ospray-test-data # argument 5: ISA (optional) # isas="AVX2 AVX512SKX" md5=`md5sum $2/$1.png | awk '{print $1 }'` echo $md5 if [ -n "$5" ]; then # if ISA specified place reference image only in the ISA specific directories isas=$5 fi for isa in $isas do echo $md5 > $3/test_image_data/baseline/$isa/$1.png.md5 done cp $2/$1.png $4/MD5/$md5 cd $4 git add MD5/$md5 RenderKit-ospray-f2a61c2/test_image_data/000077500000000000000000000000001456566705700204615ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/CMakeLists.txt000066400000000000000000000022201456566705700232150ustar00rootroot00000000000000## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 cmake_minimum_required(VERSION 3.1) project(ospray_test_data NONE) # Baseline images for tests and benchmarks include(ExternalData) # Variable determines which reference images will be used for testing set(OSPRAY_TEST_ISA "AVX512SKX" CACHE STRING "Reference images ISA") set_property(CACHE OSPRAY_TEST_ISA PROPERTY STRINGS AVX2 AVX512SKX) set(ExternalData_URL_TEMPLATES "https://www.ospray.org/ospray-test-data/%(algo)/%(hash)" "https://www.ospray.org/ospray-test-data/%(algo)/%(hash)" # retry on error ) file(TO_CMAKE_PATH "$ENV{STORAGE_PATH}" STORAGE_PATH) set(ExternalData_OBJECT_STORES "${CMAKE_BINARY_DIR}/regression_test_baseline" "${STORAGE_PATH}/projects/OSPRay/test-data" ) set(ExternalData_BINARY_ROOT ${CMAKE_BINARY_DIR}/regression_test_baseline) set(ExternalData_SOURCE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/baseline/${OSPRAY_TEST_ISA}) ExternalData_Expand_Arguments(ospray_test_data ospray_test_suite DATA{${ExternalData_SOURCE_ROOT}/,REGEX:.*} ) ExternalData_Add_Target(ospray_test_data) set_target_properties(ospray_test_data PROPERTIES EXCLUDE_FROM_ALL TRUE) RenderKit-ospray-f2a61c2/test_image_data/README000066400000000000000000000000571456566705700213430ustar00rootroot00000000000000for tests information see scripts/tests/README RenderKit-ospray-f2a61c2/test_image_data/baseline/000077500000000000000000000000001456566705700222435ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/000077500000000000000000000000001456566705700227635ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/AmbientLight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700321250ustar00rootroot0000000000000067daf471b763cf03d3b0d17226f5a166 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/AmbientLight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700321260ustar00rootroot00000000000000aa59d7082ec8cb93dfc9b95cb01cf37d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/ClippingParallel_planes.png.md5000066400000000000000000000000411456566705700307340ustar00rootroot0000000000000024936b121705fd9cc9fdc59c216a1c53 Curves_TestScenesGeometry_test_scenes_0.png.md5000066400000000000000000000000411456566705700340320ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2882ba977f68b0815293c44d604618fb8 Curves_TestScenesGeometry_test_scenes_1.png.md5000066400000000000000000000000411456566705700340330ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2a22b984373be41e86feff5b2a4121b49 Curves_TestScenesGeometry_test_scenes_10.png.md5000066400000000000000000000000411456566705700341130ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX27441623be7aafd6b19f70fbc69d89fc1 Curves_TestScenesGeometry_test_scenes_11.png.md5000066400000000000000000000000411456566705700341140ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX20fc866fc4291ff9f79a1f64571cd134a Curves_TestScenesGeometry_test_scenes_12.png.md5000066400000000000000000000000411456566705700341150ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2a2e926faa3c76d63aaa1aef9dede7ec0 Curves_TestScenesGeometry_test_scenes_13.png.md5000066400000000000000000000000411456566705700341160ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2422f6f8d2a4805b7e3b42e2cdae8eeea Curves_TestScenesGeometry_test_scenes_14.png.md5000066400000000000000000000000411456566705700341170ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX22a7cf802e75f7efb90fbaf7f8457c1d8 Curves_TestScenesGeometry_test_scenes_15.png.md5000066400000000000000000000000411456566705700341200ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX24dcd72951efa109e66baf42d74326654 Curves_TestScenesGeometry_test_scenes_16.png.md5000066400000000000000000000000411456566705700341210ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2a1d1028d099c8cf32ab813c826058b32 Curves_TestScenesGeometry_test_scenes_17.png.md5000066400000000000000000000000411456566705700341220ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2fc3e7ad06241fc50d397870252d495ae Curves_TestScenesGeometry_test_scenes_2.png.md5000066400000000000000000000000411456566705700340340ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2a1e97368016cd291e17e4e1cac325234 Curves_TestScenesGeometry_test_scenes_3.png.md5000066400000000000000000000000411456566705700340350ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2448c61a8278f76a94c2ae633b3f2359b Curves_TestScenesGeometry_test_scenes_4.png.md5000066400000000000000000000000411456566705700340360ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2c6309ef9c9ebcae988e05694dc05c2e7 Curves_TestScenesGeometry_test_scenes_5.png.md5000066400000000000000000000000411456566705700340370ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2b5ffc718870ba5359b30c7aaa4ea9382 Curves_TestScenesGeometry_test_scenes_6.png.md5000066400000000000000000000000411456566705700340400ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX238c517740d03a70167bea3951d53ab30 Curves_TestScenesGeometry_test_scenes_7.png.md5000066400000000000000000000000411456566705700340410ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2f427e56260493351bba7e022486a1587 Curves_TestScenesGeometry_test_scenes_8.png.md5000066400000000000000000000000411456566705700340420ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2a7c662a4681783bd466a6e864d538d55 Curves_TestScenesGeometry_test_scenes_9.png.md5000066400000000000000000000000411456566705700340430ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2f70f5b320125c2b5363e7783ab4a8b06 CylinderLight_LightIntensityQuantity_parameter_0.png.md5000066400000000000000000000000411456566705700357060ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX273ed3d47eeac3a9b6fc673060c1c5328 CylinderLight_LightIntensityQuantity_parameter_1.png.md5000066400000000000000000000000411456566705700357070ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX24a7ebb5f6043f46912d9b1c4f35499bf CylinderLight_LightIntensityQuantity_parameter_2.png.md5000066400000000000000000000000411456566705700357100ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX23ea087abfcc25b0ae4c7be49462e4c78 CylinderLight_LightIntensityQuantity_parameter_3.png.md5000066400000000000000000000000411456566705700357110ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2e4ed1ed1f60faca8502105cbe2291a95 CylinderLight_LightMotionBlur_parameter_0.png.md5000066400000000000000000000000411456566705700342530ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2dac74a13cc7f155a14b31ad33ec9b3c4 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/CylinderLight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700323170ustar00rootroot0000000000000011b1e39e738a027d748ed001602cf13d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/CylinderLight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700323200ustar00rootroot0000000000000084a7c4de39de086a654eda24ea5a141d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/CylinderLight_Light_parameter_2.png.md5000066400000000000000000000000411456566705700323210ustar00rootroot000000000000000e5e30af1a3e4c3e352e2af2996697be RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/CylinderLight_Light_parameter_3.png.md5000066400000000000000000000000411456566705700323220ustar00rootroot00000000000000a600e9c329322c20bd93995c4cf2ce9e RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/DenoiserOp_DenoiserOp.png.md5000066400000000000000000000000411456566705700303460ustar00rootroot000000000000001bcc8a9e3c2fa3553552380db52edce7 DepthCompositeVolume_Renderers_simple_0.png.md5000066400000000000000000000000411456566705700340110ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2642603a3031518fe9f21bf6d07835528 DepthCompositeVolume_Renderers_simple_1.png.md5000066400000000000000000000000411456566705700340120ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2a48a2b26a51f0ccab651ef1dfa48c061 DepthCompositeVolume_Renderers_simple_2.png.md5000066400000000000000000000000411456566705700340130ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX256089ffe487951c01a12eb629198ed8e DepthCompositeVolume_Renderers_simple_3.png.md5000066400000000000000000000000411456566705700340140ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2ff857fab1a8f9325760f08851316501b DistantLight_LightMotionBlur_parameter_0.png.md5000066400000000000000000000000411456566705700341100ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2323173a42d4f374d660cffaf5ec2df44 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/DistantLight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700321540ustar00rootroot0000000000000012c66430113874ba4d795c2a5335f897 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/DistantLight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700321550ustar00rootroot00000000000000d2851bae6777011ed87fa5b6d64ff7c8 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/DistantLight_Light_parameter_2.png.md5000066400000000000000000000000411456566705700321560ustar00rootroot00000000000000368189c68d2e689d830a566c6880a839 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/DistantLight_Light_parameter_3.png.md5000066400000000000000000000000411456566705700321570ustar00rootroot000000000000004cb53696a83b0c7326c6888c002828a3 FromOsprayTestingLightSamples_TestScenesLightSamples_testScenes_0.png.md5000066400000000000000000000000411456566705700411410ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX245adc210402a9215cf0cf77cb85f3039 FromOsprayTestingLightSamples_TestScenesLightSamples_testScenes_1.png.md5000066400000000000000000000000411456566705700411420ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2bc066e888df6097b89150cd631700ca9 FromOsprayTestingMaxDepth_TestScenesMaxDepth_test_scenes_0.png.md5000066400000000000000000000000411456566705700375740ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX27b145567101fa685ef4fd3d9318e0ab8 FromOsprayTestingMaxDepth_TestScenesMaxDepth_test_scenes_1.png.md5000066400000000000000000000000411456566705700375750ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2fdfdeaf9cf2b46b75164a382d1392a24 FromOsprayTestingMaxDepth_TestScenesMaxDepth_test_scenes_2.png.md5000066400000000000000000000000411456566705700375760ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX20ca1c6949e3509a4c0286a1cb0935446 FromOsprayTestingVariance_TestScenesVariance_testScenes_0.png.md5000066400000000000000000000000411456566705700374310ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX27f2868db0487194db7cf7a8d945680f9 FromOsprayTesting_TestScenesClipping_test_scenes_0.png.md5000066400000000000000000000000411456566705700361740ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX20296157028674dc93d72d85d0e965818 FromOsprayTesting_TestScenesClipping_test_scenes_1.png.md5000066400000000000000000000000411456566705700361750ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX20fd1877c94ac8514b0dfbd9e30726421 FromOsprayTesting_TestScenesClipping_test_scenes_10.png.md5000066400000000000000000000000411456566705700362550ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2fc569947d28c532f62adc96ec4785828 FromOsprayTesting_TestScenesClipping_test_scenes_11.png.md5000066400000000000000000000000411456566705700362560ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2888d98f1dd39afaecb178993b0d746ad FromOsprayTesting_TestScenesClipping_test_scenes_12.png.md5000066400000000000000000000000411456566705700362570ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX26fdf5191f445f07d244e8e6d082f84bf FromOsprayTesting_TestScenesClipping_test_scenes_13.png.md5000066400000000000000000000000411456566705700362600ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2f8327560ec76960ec4446d80b88a1145 FromOsprayTesting_TestScenesClipping_test_scenes_14.png.md5000066400000000000000000000000411456566705700362610ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX29ff00941883291ec044226779055cef2 FromOsprayTesting_TestScenesClipping_test_scenes_15.png.md5000066400000000000000000000000411456566705700362620ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX282791520206ee937d3cc1b7c2e196cb5 FromOsprayTesting_TestScenesClipping_test_scenes_16.png.md5000066400000000000000000000000411456566705700362630ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2b49014c001b9bcccc647809993fece68 FromOsprayTesting_TestScenesClipping_test_scenes_17.png.md5000066400000000000000000000000411456566705700362640ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX20f9fb5b8cc9667e4dece6fc4a43de759 FromOsprayTesting_TestScenesClipping_test_scenes_18.png.md5000066400000000000000000000000411456566705700362650ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX229796dae1e53914c740c14d130005f81 FromOsprayTesting_TestScenesClipping_test_scenes_19.png.md5000066400000000000000000000000411456566705700362660ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2e016efcd24a7f94c326ff1e3fcf4f36c FromOsprayTesting_TestScenesClipping_test_scenes_2.png.md5000066400000000000000000000000411456566705700361760ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX23941e408aef3ce9f87d8cacf1ebe9504 FromOsprayTesting_TestScenesClipping_test_scenes_20.png.md5000066400000000000000000000000411456566705700362560ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX287174ee15065c15b9687ad1b8713ef92 FromOsprayTesting_TestScenesClipping_test_scenes_21.png.md5000066400000000000000000000000411456566705700362570ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX29c746c040621f1889075118e35fe2b7d FromOsprayTesting_TestScenesClipping_test_scenes_22.png.md5000066400000000000000000000000411456566705700362600ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2579ed715d50e8dcdc8cb767748c74ff2 FromOsprayTesting_TestScenesClipping_test_scenes_23.png.md5000066400000000000000000000000411456566705700362610ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX200674517ea25290fefdb1eb341a122b0 FromOsprayTesting_TestScenesClipping_test_scenes_24.png.md5000066400000000000000000000000411456566705700362620ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX243adbf11389d8ad144d2b36f2a25470a FromOsprayTesting_TestScenesClipping_test_scenes_25.png.md5000066400000000000000000000000411456566705700362630ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2624927edc30ebe2e71865990b07428ec FromOsprayTesting_TestScenesClipping_test_scenes_26.png.md5000066400000000000000000000000411456566705700362640ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX21b5caed59b3f0331dc480dc001195e27 FromOsprayTesting_TestScenesClipping_test_scenes_3.png.md5000066400000000000000000000000411456566705700361770ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2a5ad0f0c20eafe1b6403062357bce181 FromOsprayTesting_TestScenesClipping_test_scenes_4.png.md5000066400000000000000000000000411456566705700362000ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX263c25bcdce8bf29d63dd94fe8fad3a72 FromOsprayTesting_TestScenesClipping_test_scenes_5.png.md5000066400000000000000000000000411456566705700362010ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2bc95c3ddc66b3e79f6c8e982f2eac8a7 FromOsprayTesting_TestScenesClipping_test_scenes_6.png.md5000066400000000000000000000000411456566705700362020ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2b32fe5c7b0f6eeb98a00d2cd8b13cd47 FromOsprayTesting_TestScenesClipping_test_scenes_7.png.md5000066400000000000000000000000411456566705700362030ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX21dd830d508709c52000290579fd7b3e7 FromOsprayTesting_TestScenesClipping_test_scenes_8.png.md5000066400000000000000000000000411456566705700362040ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2bd891b1b29e6e755589bf4429f43f57b FromOsprayTesting_TestScenesClipping_test_scenes_9.png.md5000066400000000000000000000000411456566705700362050ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX293e2b97821c1899ca87143f4006f6f10 FromOsprayTesting_TestScenesGeometry_test_scenes_0.png.md5000066400000000000000000000000411456566705700362220ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2005fedac323e30b07b476741459fe6a1 FromOsprayTesting_TestScenesGeometry_test_scenes_1.png.md5000066400000000000000000000000411456566705700362230ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX27617c01f530413c30407133bf21fe1d0 FromOsprayTesting_TestScenesGeometry_test_scenes_10.png.md5000066400000000000000000000000411456566705700363030ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2ea89a0c952bb99600620660db1bbeed2 FromOsprayTesting_TestScenesGeometry_test_scenes_11.png.md5000066400000000000000000000000411456566705700363040ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX220517dbc5ff845a99c3b29c5784c49b4 FromOsprayTesting_TestScenesGeometry_test_scenes_12.png.md5000066400000000000000000000000411456566705700363050ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2c28ddf5f3311ee65d7ff407f805b8102 FromOsprayTesting_TestScenesGeometry_test_scenes_13.png.md5000066400000000000000000000000411456566705700363060ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX21ac1f2a6c498298c406b484b9dbfa899 FromOsprayTesting_TestScenesGeometry_test_scenes_14.png.md5000066400000000000000000000000411456566705700363070ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2a8c24f4c3842e40d51bc949fa399c77e FromOsprayTesting_TestScenesGeometry_test_scenes_15.png.md5000066400000000000000000000000411456566705700363100ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX20dfc97c10a8a792e3ef01ca74c178b37 FromOsprayTesting_TestScenesGeometry_test_scenes_16.png.md5000066400000000000000000000000411456566705700363110ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX258ba677634ec1377713746c59ad2f0fd FromOsprayTesting_TestScenesGeometry_test_scenes_17.png.md5000066400000000000000000000000411456566705700363120ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2b2623af89221f26ffc0e011c5fd3872b FromOsprayTesting_TestScenesGeometry_test_scenes_18.png.md5000066400000000000000000000000411456566705700363130ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2eaa20d7198d250f7524d875075c65523 FromOsprayTesting_TestScenesGeometry_test_scenes_19.png.md5000066400000000000000000000000411456566705700363140ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX293f2910c461f8d4a65578de41d888414 FromOsprayTesting_TestScenesGeometry_test_scenes_2.png.md5000066400000000000000000000000411456566705700362240ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX29495604bd4f1d826adefafae768ad9ed FromOsprayTesting_TestScenesGeometry_test_scenes_20.png.md5000066400000000000000000000000411456566705700363040ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX21fce83c5e8a8e32884de61f06ef189fb FromOsprayTesting_TestScenesGeometry_test_scenes_21.png.md5000066400000000000000000000000411456566705700363050ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX22784c3a40b4c304f2dd67a0d226de309 FromOsprayTesting_TestScenesGeometry_test_scenes_22.png.md5000066400000000000000000000000411456566705700363060ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX20ee84a9176088792016e39e64ac96105 FromOsprayTesting_TestScenesGeometry_test_scenes_23.png.md5000066400000000000000000000000411456566705700363070ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX20597b0908477057233b26fdac50f8c30 FromOsprayTesting_TestScenesGeometry_test_scenes_24.png.md5000066400000000000000000000000411456566705700363100ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2ca864845643d098c79e7df59405ebc91 FromOsprayTesting_TestScenesGeometry_test_scenes_25.png.md5000066400000000000000000000000411456566705700363110ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX224108e99275920eb6abc2b4ca7f9b3f5 FromOsprayTesting_TestScenesGeometry_test_scenes_26.png.md5000066400000000000000000000000411456566705700363120ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2c97734d3966425576e1c42efd57e8f95 FromOsprayTesting_TestScenesGeometry_test_scenes_27.png.md5000066400000000000000000000000411456566705700363130ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX25104654864fd04fa6ba385c8467f3810 FromOsprayTesting_TestScenesGeometry_test_scenes_28.png.md5000066400000000000000000000000411456566705700363140ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX25104654864fd04fa6ba385c8467f3810 FromOsprayTesting_TestScenesGeometry_test_scenes_29.png.md5000066400000000000000000000000411456566705700363150ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX25104654864fd04fa6ba385c8467f3810 FromOsprayTesting_TestScenesGeometry_test_scenes_3.png.md5000066400000000000000000000000411456566705700362250ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2b529a4853c8e6481d25d47e15089614f FromOsprayTesting_TestScenesGeometry_test_scenes_30.png.md5000066400000000000000000000000411456566705700363050ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2726c140b625aad18f6d1b287a55c6340 FromOsprayTesting_TestScenesGeometry_test_scenes_31.png.md5000066400000000000000000000000411456566705700363060ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX29129cebceccb69ae64697d391b735d09 FromOsprayTesting_TestScenesGeometry_test_scenes_32.png.md5000066400000000000000000000000411456566705700363070ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX231385985c9ee9f55aa87089f474ad60c FromOsprayTesting_TestScenesGeometry_test_scenes_33.png.md5000066400000000000000000000000411456566705700363100ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2d1b38a834f0f3bdd0522d98d81f127d9 FromOsprayTesting_TestScenesGeometry_test_scenes_34.png.md5000066400000000000000000000000411456566705700363110ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX281ac931116d29b98475e903006d4714a FromOsprayTesting_TestScenesGeometry_test_scenes_35.png.md5000066400000000000000000000000411456566705700363120ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX209979f3ae2f9fb1dd7288f58b3e17d64 FromOsprayTesting_TestScenesGeometry_test_scenes_4.png.md5000066400000000000000000000000411456566705700362260ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2449624037e1ef5de3c21708ab9f5adde FromOsprayTesting_TestScenesGeometry_test_scenes_5.png.md5000066400000000000000000000000411456566705700362270ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2d51688c1af06a8e5c99234e43660a8c1 FromOsprayTesting_TestScenesGeometry_test_scenes_6.png.md5000066400000000000000000000000411456566705700362300ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX268978d538ec04f4c4d16f6875cca9028 FromOsprayTesting_TestScenesGeometry_test_scenes_7.png.md5000066400000000000000000000000411456566705700362310ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX268978d538ec04f4c4d16f6875cca9028 FromOsprayTesting_TestScenesGeometry_test_scenes_8.png.md5000066400000000000000000000000411456566705700362320ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX268978d538ec04f4c4d16f6875cca9028 FromOsprayTesting_TestScenesGeometry_test_scenes_9.png.md5000066400000000000000000000000411456566705700362330ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2d61e4794d9dd832af6ac97069eba2152 FromOsprayTesting_TestScenesPtMaterials_test_scenes_0.png.md5000066400000000000000000000000411456566705700366540ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX28cab6629d696874271f40b6aeef16c2f FromOsprayTesting_TestScenesPtMaterials_test_scenes_1.png.md5000066400000000000000000000000411456566705700366550ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX24dcd848b9983daf3c767e5deafbf9f4d FromOsprayTesting_TestScenesPtMaterials_test_scenes_10.png.md5000066400000000000000000000000411456566705700367350ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2526abce1184fef470d4fbbc88a819af3 FromOsprayTesting_TestScenesPtMaterials_test_scenes_11.png.md5000066400000000000000000000000411456566705700367360ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2dd5f24a7f1cca4df0f0aeacff6f7f8f2 FromOsprayTesting_TestScenesPtMaterials_test_scenes_12.png.md5000066400000000000000000000000411456566705700367370ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2ba2076c08fe9c04c9811703f0113e40b FromOsprayTesting_TestScenesPtMaterials_test_scenes_13.png.md5000066400000000000000000000000411456566705700367400ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2ede14f22d0bb44aa9b45d760c2f2db5f FromOsprayTesting_TestScenesPtMaterials_test_scenes_14.png.md5000066400000000000000000000000411456566705700367410ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX287a2eff0c9ec4aeb40263168aa2c1d81 FromOsprayTesting_TestScenesPtMaterials_test_scenes_15.png.md5000066400000000000000000000000411456566705700367420ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX297b3c16126913a972af4021d729a0f6c FromOsprayTesting_TestScenesPtMaterials_test_scenes_2.png.md5000066400000000000000000000000411456566705700366560ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2e76c8d0f5acf92bfff4c1ade75113f7d FromOsprayTesting_TestScenesPtMaterials_test_scenes_3.png.md5000066400000000000000000000000411456566705700366570ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2f288be1d0a1d78e13994c2cd21514c07 FromOsprayTesting_TestScenesPtMaterials_test_scenes_4.png.md5000066400000000000000000000000411456566705700366600ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX27152970e8ef0d9f69798d0d4b11de4e7 FromOsprayTesting_TestScenesPtMaterials_test_scenes_5.png.md5000066400000000000000000000000411456566705700366610ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2b1eae3b5638b160aa9ab8d9fc1342ea2 FromOsprayTesting_TestScenesPtMaterials_test_scenes_6.png.md5000066400000000000000000000000411456566705700366620ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX24357f8d3b44d73ecf49425354092239a FromOsprayTesting_TestScenesPtMaterials_test_scenes_7.png.md5000066400000000000000000000000411456566705700366630ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX25f5e4418047852b8be5270816e745fd8 FromOsprayTesting_TestScenesPtMaterials_test_scenes_8.png.md5000066400000000000000000000000411456566705700366640ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2d8ec5e5c746ef2cf57f6e15b12665807 FromOsprayTesting_TestScenesPtMaterials_test_scenes_9.png.md5000066400000000000000000000000411456566705700366650ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX20667d0c04af94a41f6d2fc9fdcddf860 FromOsprayTesting_TestScenesVolumesStrictParams_test_scenes_0.png.md5000066400000000000000000000000411456566705700404160ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2b061e43c1f11a436cb2679f76369cfe6 FromOsprayTesting_TestScenesVolumesStrictParams_test_scenes_1.png.md5000066400000000000000000000000411456566705700404170ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX24fb76cea0db1d0ea4347c06d0f6f5cb1 FromOsprayTesting_TestScenesVolumesStrictParams_test_scenes_2.png.md5000066400000000000000000000000411456566705700404200ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2f1ec979e88d9b97b38efeb8d702577f4 FromOsprayTesting_TestScenesVolumes_test_scenes_0.png.md5000066400000000000000000000000411456566705700360610ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX261007e9e7617dc49a8c2a2c69a5e27c9 FromOsprayTesting_TestScenesVolumes_test_scenes_1.png.md5000066400000000000000000000000411456566705700360620ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX211aadc4a516ee56a359e364d094bfc74 FromOsprayTesting_TestScenesVolumes_test_scenes_10.png.md5000066400000000000000000000000411456566705700361420ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2314c55cc9ce1d2208c9ec9a95d98229e FromOsprayTesting_TestScenesVolumes_test_scenes_11.png.md5000066400000000000000000000000411456566705700361430ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2bc80d51afd2d942022b1820dbc7f84e2 FromOsprayTesting_TestScenesVolumes_test_scenes_12.png.md5000066400000000000000000000000411456566705700361440ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2e9255f5d5978373819db855bfbaacd6e FromOsprayTesting_TestScenesVolumes_test_scenes_13.png.md5000066400000000000000000000000411456566705700361450ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX282be5440fee696ba8b6a9116e15cc570 FromOsprayTesting_TestScenesVolumes_test_scenes_14.png.md5000066400000000000000000000000411456566705700361460ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX27b861d9ded7e810b8411ff5bf208bc30 FromOsprayTesting_TestScenesVolumes_test_scenes_15.png.md5000066400000000000000000000000411456566705700361470ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2e9255f5d5978373819db855bfbaacd6e FromOsprayTesting_TestScenesVolumes_test_scenes_16.png.md5000066400000000000000000000000411456566705700361500ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX282be5440fee696ba8b6a9116e15cc570 FromOsprayTesting_TestScenesVolumes_test_scenes_17.png.md5000066400000000000000000000000411456566705700361510ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX27b861d9ded7e810b8411ff5bf208bc30 FromOsprayTesting_TestScenesVolumes_test_scenes_18.png.md5000066400000000000000000000000411456566705700361520ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX29e6bfa920c7579632fd07ae633fde44a FromOsprayTesting_TestScenesVolumes_test_scenes_19.png.md5000066400000000000000000000000411456566705700361530ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX23c048787d428ac005188bc2c5153cf71 FromOsprayTesting_TestScenesVolumes_test_scenes_2.png.md5000066400000000000000000000000411456566705700360630ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX258aaddd509d364794807a2ffe2d058e5 FromOsprayTesting_TestScenesVolumes_test_scenes_20.png.md5000066400000000000000000000000411456566705700361430ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX211d2216fd034fd9babfa629a935bf9f7 FromOsprayTesting_TestScenesVolumes_test_scenes_3.png.md5000066400000000000000000000000411456566705700360640ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX244413ed71090df5f96d4cb12c0c95a43 FromOsprayTesting_TestScenesVolumes_test_scenes_4.png.md5000066400000000000000000000000411456566705700360650ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX24f728b7a363ee049508fba6aa60fd4d6 FromOsprayTesting_TestScenesVolumes_test_scenes_5.png.md5000066400000000000000000000000411456566705700360660ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2f89eae18f4cb2a962a4d56f1dea8d28a FromOsprayTesting_TestScenesVolumes_test_scenes_6.png.md5000066400000000000000000000000411456566705700360670ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2df3ff32830e74a7b3a8c43f3ea7f3c74 FromOsprayTesting_TestScenesVolumes_test_scenes_7.png.md5000066400000000000000000000000411456566705700360700ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX255a63f481cc4d16d3e8168e57f2b6df4 FromOsprayTesting_TestScenesVolumes_test_scenes_8.png.md5000066400000000000000000000000411456566705700360710ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX23ae4d676399496d32187fa45a65f36d1 FromOsprayTesting_TestScenesVolumes_test_scenes_9.png.md5000066400000000000000000000000411456566705700360720ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX24acc73d6c90c381efafe80e17251be54 FromOsprayTesting_Transparency_test_scenes_0.png.md5000066400000000000000000000000411456566705700350770ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2fb91084d1376b9c4b30a18a55365acd3 FromOsprayTesting_Transparency_test_scenes_1.png.md5000066400000000000000000000000411456566705700351000ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2d8e757ebe2e1342121c5bc111f238fd4 FromOsprayTesting_Transparency_test_scenes_2.png.md5000066400000000000000000000000411456566705700351010ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX24865efcd3563cd954cdcdc887e1bead8 GeometricLight_LightMotionBlur_parameter_0.png.md5000066400000000000000000000000411456566705700344200ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2d890634b6f26ef2c69b8201c300785ec GeometricLight_LightMotionBlur_parameter_1.png.md5000066400000000000000000000000411456566705700344210ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2d890634b6f26ef2c69b8201c300785ec GeometricLight_LightTexture_parameter_0.png.md5000066400000000000000000000000411456566705700337660ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2868c54b1fcc596278039874ece92e95e GeometricLight_LightTexture_parameter_1.png.md5000066400000000000000000000000411456566705700337670ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2868c54b1fcc596278039874ece92e95e RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/GeometricLight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700324640ustar00rootroot00000000000000e3dc72cf23fd9f39a0a341016a5d4b6a RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/GeometricLight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700324650ustar00rootroot00000000000000e3dc72cf23fd9f39a0a341016a5d4b6a RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/GeometricLight_Light_parameter_2.png.md5000066400000000000000000000000411456566705700324660ustar00rootroot00000000000000bcf2e967bdc255d6007ec23237e65efd RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/GeometricLight_Light_parameter_3.png.md5000066400000000000000000000000411456566705700324670ustar00rootroot00000000000000bcf2e967bdc255d6007ec23237e65efd RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/HDRILight_LightMotionBlur_parameter_0.png.md5000066400000000000000000000000411456566705700333070ustar00rootroot0000000000000010546525c7860739cfb7b02dab3603c4 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/HDRILight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700312740ustar00rootroot000000000000001ced2b13d85f1759f41fa08af148ac64 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/HDRILight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700312750ustar00rootroot00000000000000b908fa2b10882cf56cb1f67375a3528c RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_0.png.md5000066400000000000000000000000411456566705700324760ustar00rootroot00000000000000b4044d633a97f8082c16f1ec71c4f92d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_1.png.md5000066400000000000000000000000411456566705700324770ustar00rootroot00000000000000c48599e72fbe1331151cd49ccf8fe854 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_2.png.md5000066400000000000000000000000411456566705700325000ustar00rootroot00000000000000c0964106cdfe0c4a236d432f15171a42 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_3.png.md5000066400000000000000000000000411456566705700325010ustar00rootroot000000000000004d3a8443c55123c36865c04da7bdd5cb RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_4.png.md5000066400000000000000000000000411456566705700325020ustar00rootroot00000000000000989d7dc347986fa62921e29fd280d974 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_5.png.md5000066400000000000000000000000411456566705700325030ustar00rootroot00000000000000fab70791d21ecb20d9f838d73027fb53 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_6.png.md5000066400000000000000000000000411456566705700325040ustar00rootroot000000000000005978b85b0934aef6d01794607eec538a RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/IDBuffer_ObjectInstance_IDBuffer_7.png.md5000066400000000000000000000000411456566705700325050ustar00rootroot000000000000001686ff030f2491b5d646bf6590405a58 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/IDBuffer_Primitive_IDBuffer_0.png.md5000066400000000000000000000000411456566705700315530ustar00rootroot00000000000000a635c7fdb9cb0394917fa7d5369722a6 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/IDBuffer_Primitive_IDBuffer_1.png.md5000066400000000000000000000000411456566705700315540ustar00rootroot00000000000000abcd7ceac1d7bd3a537e238411df0007 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/ImageOp_DebugOp_ImageOp_0.png.md5000066400000000000000000000000411456566705700307160ustar00rootroot000000000000007aeef0681bcfc1072d64962701642860 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_0.png.md5000066400000000000000000000000411456566705700332630ustar00rootroot000000000000005ac362cb64845079f85d60c53237a30c RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_1.png.md5000066400000000000000000000000411456566705700332640ustar00rootroot00000000000000600f9a78e23df4b21ef1cb3576c41293 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_2.png.md5000066400000000000000000000000411456566705700332650ustar00rootroot00000000000000b96e5ad22db82abfd7a96bb718b39d2c RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_3.png.md5000066400000000000000000000000411456566705700332660ustar00rootroot0000000000000037bb390a60b0bfcfa5eefd11c5417400 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_4.png.md5000066400000000000000000000000411456566705700332670ustar00rootroot000000000000002dcf960bb59871a4576a24a6fa313875 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_5.png.md5000066400000000000000000000000411456566705700332700ustar00rootroot000000000000002219c6429c336540493059ba4dd21a5b RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_6.png.md5000066400000000000000000000000411456566705700332710ustar00rootroot00000000000000b96e5ad22db82abfd7a96bb718b39d2c RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Interpolation_Color_Interpolation_7.png.md5000066400000000000000000000000411456566705700332720ustar00rootroot0000000000000037bb390a60b0bfcfa5eefd11c5417400 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Interpolation_Normal_Interpolation_0.png.md5000066400000000000000000000000411456566705700334350ustar00rootroot00000000000000b46e1e25fabdba9962cdb1fa797ead04 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Interpolation_Normal_Interpolation_1.png.md5000066400000000000000000000000411456566705700334360ustar00rootroot0000000000000073b536d10b031c419a7f3acde81851df Interpolation_Texcoord_Interpolation_0.png.md5000066400000000000000000000000411456566705700337150ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2a5952191d40359ec2caef22b16dd59e9 Interpolation_Texcoord_Interpolation_1.png.md5000066400000000000000000000000411456566705700337160ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2b74cb26446f638d39b4395fcc3cc761a Interpolation_Texcoord_Interpolation_2.png.md5000066400000000000000000000000411456566705700337170ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX25791e0b989fba970b48521d80f3d997a Interpolation_Texcoord_Interpolation_3.png.md5000066400000000000000000000000411456566705700337200ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2a7f87e630b9b82e8e44eca2d6d6798f5 MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_0.png.md5000066400000000000000000000000411456566705700404570ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2c11af06b7ed875a6b87d1a5de0427d91 MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_1.png.md5000066400000000000000000000000411456566705700404600ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX23da593a811d23760b111dc55c6fd93d6 MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_2.png.md5000066400000000000000000000000411456566705700404610ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2a67563d886598cc3ac2be9fdf494308a MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_0.png.md5000066400000000000000000000000411456566705700403160ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX256338fcff16d21ad86271e3f85052436 MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_1.png.md5000066400000000000000000000000411456566705700403170ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2e5c2467727ae66a9744b8cbb517d606e MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_2.png.md5000066400000000000000000000000411456566705700403200ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX25776518b2bec1f324f15c2ae3ef504a1 MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_3.png.md5000066400000000000000000000000411456566705700403210ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2c76793fe11e0bfdb7f43fd0e8999b63e MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_4.png.md5000066400000000000000000000000411456566705700403220ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2fcf630625ed9a4645b6937030b802c73 MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_5.png.md5000066400000000000000000000000411456566705700403230ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2ce646854a5c595b1f7b009c40c256684 MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_6.png.md5000066400000000000000000000000411456566705700403240ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX201b17a8669d5be94696470962fcd1389 MotionBlurBoxes_CameraRollingShutter_instance_mb_0.png.md5000066400000000000000000000000411456566705700361230ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2e09a7f947946e09944af1c0ee8eb3225 MotionBlurBoxes_CameraRollingShutter_instance_mb_1.png.md5000066400000000000000000000000411456566705700361240ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX284a327f24353d9c16b1f57cdf8738c52 MotionBlurBoxes_CameraRollingShutter_instance_mb_2.png.md5000066400000000000000000000000411456566705700361250ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2c1a6af91c50b68c06f8d97b4316f1279 MotionBlurBoxes_CameraRollingShutter_instance_mb_3.png.md5000066400000000000000000000000411456566705700361260ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX224b27522f08c8d46b384b0c3ac834133 MotionBlurBoxes_CameraRollingShutter_instance_mb_4.png.md5000066400000000000000000000000411456566705700361270ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX27f1ca47683d8f2a8398e66e2a9a78dde MotionBlurBoxes_CameraRollingShutter_instance_mb_5.png.md5000066400000000000000000000000411456566705700361300ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX24e17234519beab039e833d481d74cf1f MotionBlurBoxes_CameraRollingShutter_instance_mb_6.png.md5000066400000000000000000000000411456566705700361310ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2abe391f40c73fd61fee52307bbb1ff6c MotionBlurBoxes_CameraRollingShutter_instance_mb_7.png.md5000066400000000000000000000000411456566705700361320ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2bd05dcc671fe72f741659d8438901ac6 MotionBlurBoxes_CameraStereoRollingShutter_instance_mb_0.png.md5000066400000000000000000000000411456566705700373050ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX24f9858dff7a78b5ae508fcaf272d3795 MotionBlurBoxes_TestMotionBlur_instance_mb_0.png.md5000066400000000000000000000000411456566705700347570ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX220fdf05b9a77272b90133e3f2e177dce MotionBlurBoxes_TestMotionBlur_instance_mb_1.png.md5000066400000000000000000000000411456566705700347600ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX21d093c1334f74362931d235a587b86c2 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/MotionCamera_CameraOrtho_camera_mb_0.png.md5000066400000000000000000000000411456566705700332170ustar00rootroot00000000000000f21af1f2c408a2359254f34dc9fba77f MotionCamera_CameraStereoRollingShutter_camera_mb_0.png.md5000066400000000000000000000000411456566705700362140ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX21ae7ba722d04dbb8c319d8018173fa1d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/MotionCamera_Camera_camera_mb_0.png.md5000066400000000000000000000000411456566705700322030ustar00rootroot000000000000008b08da5bd0636a80a526846d2b6f51c9 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/MotionCamera_Camera_camera_mb_1.png.md5000066400000000000000000000000411456566705700322040ustar00rootroot00000000000000a3757e91aeffc07c32406ff4ae930530 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/MotionCamera_Camera_camera_mb_2.png.md5000066400000000000000000000000411456566705700322050ustar00rootroot000000000000006f5072460b8a2d60c4081de05e422347 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/MotionCamera_Camera_camera_mb_3.png.md5000066400000000000000000000000411456566705700322060ustar00rootroot000000000000007140a6437c7ddf9a7939f31bfd2ed11f RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/MotionCamera_Camera_camera_mb_4.png.md5000066400000000000000000000000411456566705700322070ustar00rootroot00000000000000a73fc912b5de42ebaa66d13169353591 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/MotionCamera_Camera_camera_mb_5.png.md5000066400000000000000000000000411456566705700322100ustar00rootroot0000000000000067559d0c14af7c4fd2cd392fc29f9b13 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/MotionCamera_Camera_camera_mb_6.png.md5000066400000000000000000000000411456566705700322110ustar00rootroot0000000000000021ca5f70a74e4209e6707f02da1896b8 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/MotionCamera_Camera_camera_mb_7.png.md5000066400000000000000000000000411456566705700322120ustar00rootroot000000000000009d42974498897ad5936846ceb6ebafe1 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/MotionCamera_Camera_camera_mb_8.png.md5000066400000000000000000000000411456566705700322130ustar00rootroot000000000000002f2a9890c1cb8fd9d72689814e64ea68 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/MotionCamera_Camera_camera_mb_9.png.md5000066400000000000000000000000411456566705700322140ustar00rootroot00000000000000405361d8e6cde7f8278a2466b101a990 PTBackgroundRefraction_Appearance_backgroundRefraction_0.png.md5000066400000000000000000000000411456566705700372030ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX24ff8f25e4eb2e84c0b469a5d43e18b44 PTBackgroundRefraction_Appearance_backgroundRefraction_1.png.md5000066400000000000000000000000411456566705700372040ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX283fd955d6b4d2e213aec962d761218cd RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PhotometricLight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700330430ustar00rootroot00000000000000e3b9cc2abb4828e6183db2717a282b05 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PhotometricLight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700330440ustar00rootroot0000000000000055009c40fefcd4eb6ebf0c5467d1e6f5 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PhotometricLight_Light_parameter_10.png.md5000066400000000000000000000000411456566705700331240ustar00rootroot00000000000000897322dcba60a3738bb35a161f68a266 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PhotometricLight_Light_parameter_11.png.md5000066400000000000000000000000411456566705700331250ustar00rootroot000000000000007c7ebd0441e73b86455662920b3f5a04 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PhotometricLight_Light_parameter_2.png.md5000066400000000000000000000000411456566705700330450ustar00rootroot0000000000000042f7b6f0bb4b17ebd2d6e2d6dfeb5a52 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PhotometricLight_Light_parameter_3.png.md5000066400000000000000000000000411456566705700330460ustar00rootroot000000000000009122d64d2343b2ebcc7aeba86a1d3086 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PhotometricLight_Light_parameter_4.png.md5000066400000000000000000000000411456566705700330470ustar00rootroot0000000000000097fe194b2dcbd54d45e391449c514b4d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PhotometricLight_Light_parameter_5.png.md5000066400000000000000000000000411456566705700330500ustar00rootroot0000000000000044328cc612a40a65c2a8e37db15d3e32 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PhotometricLight_Light_parameter_6.png.md5000066400000000000000000000000411456566705700330510ustar00rootroot0000000000000063b0136d8b074c034affacc4b7545f45 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PhotometricLight_Light_parameter_7.png.md5000066400000000000000000000000411456566705700330520ustar00rootroot000000000000007de1516a92e6baaa83a47efd60a53086 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PhotometricLight_Light_parameter_8.png.md5000066400000000000000000000000411456566705700330530ustar00rootroot000000000000002c562fee621fe1043fed6bc04d187d5d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PhotometricLight_Light_parameter_9.png.md5000066400000000000000000000000411456566705700330540ustar00rootroot00000000000000089632b7f534d6b787f719c935c55a36 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PixelFilter_Camera_test_0.png.md5000066400000000000000000000000411456566705700311250ustar00rootroot000000000000002c04102ec0eb17bb823b00d08929f03c RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PixelFilter_Camera_test_1.png.md5000066400000000000000000000000411456566705700311260ustar00rootroot000000000000002c5faba08250fdf541f4ad032e55711e RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PixelFilter_Camera_test_2.png.md5000066400000000000000000000000411456566705700311270ustar00rootroot00000000000000fe60964b25a399e4e814fcf64493e229 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PixelFilter_Camera_test_3.png.md5000066400000000000000000000000411456566705700311300ustar00rootroot000000000000003c7c73b43d9567f30beac9654ec6381f RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PixelFilter_Camera_test_4.png.md5000066400000000000000000000000411456566705700311310ustar00rootroot00000000000000e4563a35246501e98b85e2e6d831423b RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PixelFilter_Camera_test_5.png.md5000066400000000000000000000000411456566705700311320ustar00rootroot000000000000002c04102ec0eb17bb823b00d08929f03c RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PixelFilter_Camera_test_6.png.md5000066400000000000000000000000411456566705700311330ustar00rootroot0000000000000086303288b32012914d863b574fcd9a51 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PixelFilter_Camera_test_7.png.md5000066400000000000000000000000411456566705700311340ustar00rootroot00000000000000ccc308475b73ebc0349ae629db5943d4 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PixelFilter_Camera_test_8.png.md5000066400000000000000000000000411456566705700311350ustar00rootroot00000000000000fcf34a104c3e1089edee4d4c0e89f9f4 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/PixelFilter_Camera_test_9.png.md5000066400000000000000000000000411456566705700311360ustar00rootroot00000000000000f6d563602fc4d9fef040044d93bd7e07 QuadLight_LightIntensityQuantity_parameter_0.png.md5000066400000000000000000000000411456566705700350270ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX27a4647314d9e9fe52cc60f0cd88e7cc5 QuadLight_LightIntensityQuantity_parameter_1.png.md5000066400000000000000000000000411456566705700350300ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX290428918977c596a76589c7e8f514b44 QuadLight_LightIntensityQuantity_parameter_2.png.md5000066400000000000000000000000411456566705700350310ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX20557938f2fb0111a3d89c6f18ea91cc9 QuadLight_LightIntensityQuantity_parameter_3.png.md5000066400000000000000000000000411456566705700350320ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2d702aa0664374d07a45294a61df22e57 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/QuadLight_LightMotionBlur_parameter_0.png.md5000066400000000000000000000000411456566705700334530ustar00rootroot00000000000000c14d9428c60f7f525590d4d84bfabf02 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/QuadLight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700314400ustar00rootroot00000000000000d2e25a08e5f62467fff8017df239e7de RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/QuadLight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700314410ustar00rootroot00000000000000d6dda669082cf67864c7408e7a81ec9c RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/QuadLight_Light_parameter_2.png.md5000066400000000000000000000000411456566705700314420ustar00rootroot0000000000000075bc399da6fce8ceb64cab63777bd52d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/QuadLight_Light_parameter_3.png.md5000066400000000000000000000000411456566705700314430ustar00rootroot00000000000000933a54ee091711fcd8f39ef32605cea8 RendererMaterialList_MaterialLists_material_list_0.png.md5000066400000000000000000000000411456566705700361370ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX26c47ba3fd337d73f44ac05ef4767e046 RendererMaterialList_MaterialLists_material_list_1.png.md5000066400000000000000000000000411456566705700361400ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2616d58357cf8ad2a950296ad7c81106d SphereLight_LightIntensityQuantity_parameter_0.png.md5000066400000000000000000000000411456566705700353630ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2a591333c14e5cb8ebe2b4ac8ef0e1a94 SphereLight_LightIntensityQuantity_parameter_1.png.md5000066400000000000000000000000411456566705700353640ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX21435a54d9a9511b4ee4a435166d11c8a SphereLight_LightIntensityQuantity_parameter_2.png.md5000066400000000000000000000000411456566705700353650ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2b22ea36cd0e4cdba968936a19f7883d6 SphereLight_LightIntensityQuantity_parameter_3.png.md5000066400000000000000000000000411456566705700353660ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX25fd4b0854345dfba7ecc4879cb78dc8f SphereLight_LightIntensityQuantity_parameter_4.png.md5000066400000000000000000000000411456566705700353670ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX240d43cba12b84988edaa4b5996593ff1 SphereLight_LightIntensityQuantity_parameter_5.png.md5000066400000000000000000000000411456566705700353700ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2887aa3ac4e41aadce524615e6987a3f0 SphereLight_LightMotionBlur_parameter_0.png.md5000066400000000000000000000000411456566705700337300ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2eac49e507d0881385bf51e8f65e6dafa RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SphereLight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700317740ustar00rootroot0000000000000058a17cd519c8b5b62b1040d7f5c5f177 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SphereLight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700317750ustar00rootroot00000000000000e61c3cac8839e449c1b0b9c8b430020a RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SphereLight_Light_parameter_2.png.md5000066400000000000000000000000411456566705700317760ustar00rootroot00000000000000112f3bac4b5b2f01e8fc45c3ac9d182b RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SphereLight_Light_parameter_3.png.md5000066400000000000000000000000411456566705700317770ustar00rootroot000000000000009c63f65a1905e6c14064f9ab1282b662 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SphereLight_Light_parameter_4.png.md5000066400000000000000000000000411456566705700320000ustar00rootroot00000000000000ab51df87fb122cd035dbc171e375b92f RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SphereLight_Light_parameter_5.png.md5000066400000000000000000000000411456566705700320010ustar00rootroot00000000000000f6916b40a6519526299b5524ad9f0d99 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_0.png.md5000066400000000000000000000000411456566705700335650ustar00rootroot00000000000000247ddc74d65ed8fac9fed9b0bf0d6654 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_1.png.md5000066400000000000000000000000411456566705700335660ustar00rootroot000000000000006ef1519f3e152fa90fab6f331563a8ca SpherePrecision_Intersection_sphere_10.png.md5000066400000000000000000000000411456566705700335670ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX200713111673fbd1ce152eb9012669cb0 SpherePrecision_Intersection_sphere_11.png.md5000066400000000000000000000000411456566705700335700ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX22b81f2fc2ac6de5c73f65561e17c057c SpherePrecision_Intersection_sphere_12.png.md5000066400000000000000000000000411456566705700335710ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX220e20ace063e3344eda60e844851f79c SpherePrecision_Intersection_sphere_13.png.md5000066400000000000000000000000411456566705700335720ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX24594ca2ff268ef351a3a59d7e0ea1886 SpherePrecision_Intersection_sphere_14.png.md5000066400000000000000000000000411456566705700335730ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX28634d6c2195dfa036378d9431f78b813 SpherePrecision_Intersection_sphere_15.png.md5000066400000000000000000000000411456566705700335740ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2bc09ff74ff3f256e1f7dabbb9d8c181f SpherePrecision_Intersection_sphere_16.png.md5000066400000000000000000000000411456566705700335750ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2debc5740bb229586592099eaaeae74d8 SpherePrecision_Intersection_sphere_17.png.md5000066400000000000000000000000411456566705700335760ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2ba802dd2427997b1fa27db1c1fb25b00 SpherePrecision_Intersection_sphere_18.png.md5000066400000000000000000000000411456566705700335770ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2f0425bbc4b5ec65d55ce9c5093de5826 SpherePrecision_Intersection_sphere_19.png.md5000066400000000000000000000000411456566705700336000ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2ce97d3ecd5fdcaf71ef7dc08d13980a7 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_2.png.md5000066400000000000000000000000411456566705700335670ustar00rootroot000000000000003f7a6f51e50dab15e6148a821ce14099 SpherePrecision_Intersection_sphere_20.png.md5000066400000000000000000000000411456566705700335700ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2c743fb20030a7c9668024a94f7f7fbf1 SpherePrecision_Intersection_sphere_21.png.md5000066400000000000000000000000411456566705700335710ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX29494d5f0c1af83c8274371e13fdb1430 SpherePrecision_Intersection_sphere_22.png.md5000066400000000000000000000000411456566705700335720ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX22f4e2ba960bced69fc42e10bda27ac82 SpherePrecision_Intersection_sphere_23.png.md5000066400000000000000000000000411456566705700335730ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX26a9cd39cb0d33b09cd07134a8d21730c RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_3.png.md5000066400000000000000000000000411456566705700335700ustar00rootroot0000000000000098acdf8a7d6e42921685f8ca979ffca9 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_4.png.md5000066400000000000000000000000411456566705700335710ustar00rootroot0000000000000097423b29895c7436bdde98aef741d90c RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_5.png.md5000066400000000000000000000000411456566705700335720ustar00rootroot00000000000000c265eea80094b81827992c46dfca9b40 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_6.png.md5000066400000000000000000000000411456566705700335730ustar00rootroot000000000000004df08169693b761983b00113253e13ad RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_7.png.md5000066400000000000000000000000411456566705700335740ustar00rootroot00000000000000805160e724a3a845e232ad47f43c7f7b RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_8.png.md5000066400000000000000000000000411456566705700335750ustar00rootroot0000000000000031a20e7c86887729f4c6fc91c193befb RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpherePrecision_Intersection_sphere_9.png.md5000066400000000000000000000000411456566705700335760ustar00rootroot00000000000000c2891de2526c66bc9dc2a0839698e873 SpotLight_LightIntensityQuantity_parameter_0.png.md5000066400000000000000000000000411456566705700350620ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2a591333c14e5cb8ebe2b4ac8ef0e1a94 SpotLight_LightIntensityQuantity_parameter_1.png.md5000066400000000000000000000000411456566705700350630ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2544c09110ab45a7ac602286c55e621c6 SpotLight_LightIntensityQuantity_parameter_2.png.md5000066400000000000000000000000411456566705700350640ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2a95f3f3e5b327efe5eea3380b3fb6716 SpotLight_LightIntensityQuantity_parameter_3.png.md5000066400000000000000000000000411456566705700350650ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2d86e673c6d967180a1e3688f7284a2b5 SpotLight_LightIntensityQuantity_parameter_4.png.md5000066400000000000000000000000411456566705700350660ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2e94f91ea9687e4229507a1798e135970 SpotLight_LightIntensityQuantity_parameter_5.png.md5000066400000000000000000000000411456566705700350670ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX20088dfe601ea100002424d3b2714ad68 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpotLight_LightMotionBlur_parameter_0.png.md5000066400000000000000000000000411456566705700335060ustar00rootroot000000000000008a0f558e1f3e271d171bc1a63a5505bd RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpotLight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700314730ustar00rootroot000000000000006e69c875527b92cc344b2255d49aa543 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpotLight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700314740ustar00rootroot00000000000000fdc115503b6f13ded13d1700d530387a RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpotLight_Light_parameter_2.png.md5000066400000000000000000000000411456566705700314750ustar00rootroot000000000000002071ed754e6ced5c6d7c858700c90a96 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpotLight_Light_parameter_3.png.md5000066400000000000000000000000411456566705700314760ustar00rootroot000000000000003958644d7bf8e575f2f98b5dcfc04e57 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpotLight_Light_parameter_4.png.md5000066400000000000000000000000411456566705700314770ustar00rootroot00000000000000c2ab237527996decfee4c902281c8a7d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpotLight_Light_parameter_5.png.md5000066400000000000000000000000411456566705700315000ustar00rootroot000000000000007f4f37bd2a26afa9fbe4fad121c6a8a3 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpotLight_Light_parameter_6.png.md5000066400000000000000000000000411456566705700315010ustar00rootroot000000000000004f874be7c445cf60f39330914d2492b2 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpotLight_Light_parameter_7.png.md5000066400000000000000000000000411456566705700315020ustar00rootroot00000000000000815dbb36620ce3d9fb67af16bc45c9b8 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpotLight_Light_parameter_8.png.md5000066400000000000000000000000411456566705700315030ustar00rootroot00000000000000926746861e6dd78f7d5a9f03d670f617 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SpotLight_Light_parameter_9.png.md5000066400000000000000000000000411456566705700315040ustar00rootroot000000000000007e6d93e0b068f62197441d61aa42eaf6 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Stereo_Camera_stereo_0.png.md5000066400000000000000000000000411456566705700304610ustar00rootroot00000000000000a101b64cd3f63170e00890b65c8a5499 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Stereo_Camera_stereo_1.png.md5000066400000000000000000000000411456566705700304620ustar00rootroot0000000000000085bf732703518cfc9af270da6c5531c1 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Stereo_Camera_stereo_2.png.md5000066400000000000000000000000411456566705700304630ustar00rootroot00000000000000814b7d3d8e2e8fbc6ed539f0de1acf91 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Stereo_Camera_stereo_3.png.md5000066400000000000000000000000411456566705700304640ustar00rootroot000000000000006d15e4bcbdd9037dd5b72e442dc6cf93 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Stereo_Camera_stereo_4.png.md5000066400000000000000000000000411456566705700304650ustar00rootroot00000000000000216abc0d5abdfaa56b236bc2aaecf1bd RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Stereo_Camera_stereo_5.png.md5000066400000000000000000000000411456566705700304660ustar00rootroot0000000000000006e33d2badc11d81a02a6dda018f7e72 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Stereo_Camera_stereo_6.png.md5000066400000000000000000000000411456566705700304670ustar00rootroot00000000000000ffdbe2cb2e7a3b5cc958906ad8391021 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Stereo_Camera_stereo_7.png.md5000066400000000000000000000000411456566705700304700ustar00rootroot000000000000006aafd5dac141de5d94be9936c6f598be RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light2_parameter_0.png.md5000066400000000000000000000000411456566705700310740ustar00rootroot00000000000000d3d1f71a73213e21c0853cd2fb81ea14 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light2_parameter_1.png.md5000066400000000000000000000000411456566705700310750ustar00rootroot0000000000000030f6a8fed556c2144e82d6af3bf38413 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light2_parameter_2.png.md5000066400000000000000000000000411456566705700310760ustar00rootroot0000000000000003aada0ffd5f4d08794c04676b487c4b RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light2_parameter_3.png.md5000066400000000000000000000000411456566705700310770ustar00rootroot00000000000000d4524ef0043c8b30d2d400305e40f555 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_LightMotionBlur_parameter_0.png.md5000066400000000000000000000000411456566705700330250ustar00rootroot000000000000008c5be184c4e0b903b37914cd522fe53d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light_parameter_0.png.md5000066400000000000000000000000411456566705700310120ustar00rootroot000000000000003e5b56f70cbfd4b75d06c58dae33318b RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light_parameter_1.png.md5000066400000000000000000000000411456566705700310130ustar00rootroot00000000000000e761d9960abbcc86d6b56cc59a488e23 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light_parameter_10.png.md5000066400000000000000000000000411456566705700310730ustar00rootroot00000000000000542f88cea0156ffeffe12bf2fdb4e624 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light_parameter_11.png.md5000066400000000000000000000000411456566705700310740ustar00rootroot000000000000008bd2c59521aabd1b8fafb2aead66d5d0 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light_parameter_12.png.md5000066400000000000000000000000411456566705700310750ustar00rootroot0000000000000010532d993fa72bbc1bdd55cbfa9d3bc3 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light_parameter_13.png.md5000066400000000000000000000000411456566705700310760ustar00rootroot00000000000000aecfc8c25556df822ecd47353b9d4f66 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light_parameter_14.png.md5000066400000000000000000000000411456566705700310770ustar00rootroot0000000000000001f1dc126f663ad542eb6ba2384945e7 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light_parameter_2.png.md5000066400000000000000000000000411456566705700310140ustar00rootroot00000000000000156f6d2141cc34bf7e917d621ddcb333 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light_parameter_3.png.md5000066400000000000000000000000411456566705700310150ustar00rootroot0000000000000030350a0d29420a0d0c8a295a05ca5c3a RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light_parameter_4.png.md5000066400000000000000000000000411456566705700310160ustar00rootroot00000000000000e5c1dae4027b9620f3345fe074974e4c RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light_parameter_5.png.md5000066400000000000000000000000411456566705700310170ustar00rootroot00000000000000e7092c6f33a9236be32d9dabce7b5c85 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light_parameter_6.png.md5000066400000000000000000000000411456566705700310200ustar00rootroot00000000000000e6bf2e10e28c4d5a5688464199904442 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light_parameter_7.png.md5000066400000000000000000000000411456566705700310210ustar00rootroot00000000000000cab3383424c3cdc30688548e2e0f4ee7 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light_parameter_8.png.md5000066400000000000000000000000411456566705700310220ustar00rootroot0000000000000092eec847bfceba0cb9a9d6683e4d2728 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/SunSky_Light_parameter_9.png.md5000066400000000000000000000000411456566705700310230ustar00rootroot00000000000000fa33379b0fa06fedb530f7189e06b780 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/TestAssignedCopy_deleterCallbacks.png.md5000066400000000000000000000000411456566705700327040ustar00rootroot00000000000000c38d798d36f03061d5a9fc0a0a3a3e6d TestUSMSharing_SharedData_structured_regular_0.png.md5000066400000000000000000000000411456566705700352150ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2b19ecf9ed96fa82be56387b70909b261 TestUSMSharing_SharedData_structured_regular_1.png.md5000066400000000000000000000000411456566705700352160ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2b19ecf9ed96fa82be56387b70909b261 TestUSMSharing_SharedData_structured_regular_2.png.md5000066400000000000000000000000411456566705700352170ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2b19ecf9ed96fa82be56387b70909b261 Texture2DTransform_Appearance_simple_0.png.md5000066400000000000000000000000411456566705700335220ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX23614ce01a214ecd1e4ff942ebe51162f RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Texture2DWrapMode_Appearance_wrap_0.png.md5000066400000000000000000000000401456566705700330230ustar00rootroot0000000000000097731c498a8be29419817d89b04f2dbfRenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Texture2DWrapMode_Appearance_wrap_1.png.md5000066400000000000000000000000401456566705700330240ustar00rootroot00000000000000878d5bb7e434080a24a9c284068041dbRenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Texture2D_Appearance_filter_0.png.md5000066400000000000000000000000411456566705700317010ustar00rootroot0000000000000063fbdd1930e798c300bd79b82610e81d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Texture2D_Appearance_filter_1.png.md5000066400000000000000000000000411456566705700317020ustar00rootroot0000000000000063fbdd1930e798c300bd79b82610e81d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Texture2D_Appearance_filter_2.png.md5000066400000000000000000000000411456566705700317030ustar00rootroot00000000000000fca8c20343f635fbdcf8a4c22e7ed321 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Texture2D_Appearance_filter_3.png.md5000066400000000000000000000000411456566705700317040ustar00rootroot00000000000000fca8c20343f635fbdcf8a4c22e7ed321 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Texture2D_Appearance_filter_4.png.md5000066400000000000000000000000411456566705700317050ustar00rootroot0000000000000036940553e0c1e6dca734757515a85f78 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Texture2D_Appearance_filter_5.png.md5000066400000000000000000000000411456566705700317060ustar00rootroot0000000000000036940553e0c1e6dca734757515a85f78 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Texture2D_Appearance_filter_6.png.md5000066400000000000000000000000411456566705700317070ustar00rootroot00000000000000a6783400c29e566af1f9ef45a3ca1836 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2/Texture2D_Appearance_filter_7.png.md5000066400000000000000000000000411456566705700317100ustar00rootroot00000000000000a6783400c29e566af1f9ef45a3ca1836 TextureVolumeTransform_Renderers_simple_0.png.md5000066400000000000000000000000411456566705700344160ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX25ca76f28d3cca6fdf5b3037ac1da64fc TextureVolumeTransform_deprecated_Renderers_simple_0.png.md5000066400000000000000000000000411456566705700365760ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX25ca76f28d3cca6fdf5b3037ac1da64fc UnstructuredVolume_TestScenesVolumes_simple_0.png.md5000066400000000000000000000000411456566705700352730ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2e84d5badebebaab3d5c24c5706707e91 UnstructuredVolume_TestScenesVolumes_simple_1.png.md5000066400000000000000000000000411456566705700352740ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX2eb6da5c259860fabfa92fcbd5fbb485d UnstructuredVolume_TestScenesVolumes_simple_2.png.md5000066400000000000000000000000411456566705700352750ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX21b67de46978eb87e9896b5eddf6d816d UnstructuredVolume_TestScenesVolumes_simple_3.png.md5000066400000000000000000000000411456566705700352760ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX245f9c3bb677494082f97375c96bfef35 UnstructuredVolume_TestScenesVolumes_simple_4.png.md5000066400000000000000000000000411456566705700352770ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX26572ac88ba74b7b4ac97ea8fc0e7469f UnstructuredVolume_TestScenesVolumes_simple_5.png.md5000066400000000000000000000000411456566705700353000ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX217b401041701dcab5f54440efebc797f RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/000077500000000000000000000000001456566705700235175ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/AmbientLight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700326610ustar00rootroot0000000000000067daf471b763cf03d3b0d17226f5a166 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/AmbientLight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700326620ustar00rootroot00000000000000aa59d7082ec8cb93dfc9b95cb01cf37d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/ClippingParallel_planes.png.md5000066400000000000000000000000411456566705700314700ustar00rootroot0000000000000024936b121705fd9cc9fdc59c216a1c53 Curves_TestScenesGeometry_test_scenes_0.png.md5000066400000000000000000000000411456566705700345660ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX882ba977f68b0815293c44d604618fb8 Curves_TestScenesGeometry_test_scenes_1.png.md5000066400000000000000000000000411456566705700345670ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXa22b984373be41e86feff5b2a4121b49 Curves_TestScenesGeometry_test_scenes_10.png.md5000066400000000000000000000000411456566705700346470ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX7441623be7aafd6b19f70fbc69d89fc1 Curves_TestScenesGeometry_test_scenes_11.png.md5000066400000000000000000000000411456566705700346500ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX0fc866fc4291ff9f79a1f64571cd134a Curves_TestScenesGeometry_test_scenes_12.png.md5000066400000000000000000000000411456566705700346510ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXa2e926faa3c76d63aaa1aef9dede7ec0 Curves_TestScenesGeometry_test_scenes_13.png.md5000066400000000000000000000000411456566705700346520ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX422f6f8d2a4805b7e3b42e2cdae8eeea Curves_TestScenesGeometry_test_scenes_14.png.md5000066400000000000000000000000411456566705700346530ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX2a7cf802e75f7efb90fbaf7f8457c1d8 Curves_TestScenesGeometry_test_scenes_15.png.md5000066400000000000000000000000411456566705700346540ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX4dcd72951efa109e66baf42d74326654 Curves_TestScenesGeometry_test_scenes_16.png.md5000066400000000000000000000000411456566705700346550ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXa1d1028d099c8cf32ab813c826058b32 Curves_TestScenesGeometry_test_scenes_17.png.md5000066400000000000000000000000411456566705700346560ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXfc3e7ad06241fc50d397870252d495ae Curves_TestScenesGeometry_test_scenes_2.png.md5000066400000000000000000000000411456566705700345700ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXa1e97368016cd291e17e4e1cac325234 Curves_TestScenesGeometry_test_scenes_3.png.md5000066400000000000000000000000411456566705700345710ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX448c61a8278f76a94c2ae633b3f2359b Curves_TestScenesGeometry_test_scenes_4.png.md5000066400000000000000000000000411456566705700345720ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXc6309ef9c9ebcae988e05694dc05c2e7 Curves_TestScenesGeometry_test_scenes_5.png.md5000066400000000000000000000000411456566705700345730ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXb5ffc718870ba5359b30c7aaa4ea9382 Curves_TestScenesGeometry_test_scenes_6.png.md5000066400000000000000000000000411456566705700345740ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX38c517740d03a70167bea3951d53ab30 Curves_TestScenesGeometry_test_scenes_7.png.md5000066400000000000000000000000411456566705700345750ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXf427e56260493351bba7e022486a1587 Curves_TestScenesGeometry_test_scenes_8.png.md5000066400000000000000000000000411456566705700345760ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXa7c662a4681783bd466a6e864d538d55 Curves_TestScenesGeometry_test_scenes_9.png.md5000066400000000000000000000000411456566705700345770ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXf70f5b320125c2b5363e7783ab4a8b06 CylinderLight_LightIntensityQuantity_parameter_0.png.md5000066400000000000000000000000411456566705700364420ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX73ed3d47eeac3a9b6fc673060c1c5328 CylinderLight_LightIntensityQuantity_parameter_1.png.md5000066400000000000000000000000411456566705700364430ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX4a7ebb5f6043f46912d9b1c4f35499bf CylinderLight_LightIntensityQuantity_parameter_2.png.md5000066400000000000000000000000411456566705700364440ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX3ea087abfcc25b0ae4c7be49462e4c78 CylinderLight_LightIntensityQuantity_parameter_3.png.md5000066400000000000000000000000411456566705700364450ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXe4ed1ed1f60faca8502105cbe2291a95 CylinderLight_LightMotionBlur_parameter_0.png.md5000066400000000000000000000000411456566705700350070ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXdac74a13cc7f155a14b31ad33ec9b3c4 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/CylinderLight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700330530ustar00rootroot0000000000000011b1e39e738a027d748ed001602cf13d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/CylinderLight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700330540ustar00rootroot0000000000000084a7c4de39de086a654eda24ea5a141d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/CylinderLight_Light_parameter_2.png.md5000066400000000000000000000000411456566705700330550ustar00rootroot000000000000000e5e30af1a3e4c3e352e2af2996697be RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/CylinderLight_Light_parameter_3.png.md5000066400000000000000000000000411456566705700330560ustar00rootroot00000000000000a600e9c329322c20bd93995c4cf2ce9e RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/DenoiserOp_DenoiserOp.png.md5000066400000000000000000000000411456566705700311020ustar00rootroot000000000000001bcc8a9e3c2fa3553552380db52edce7 DepthCompositeVolume_Renderers_simple_0.png.md5000066400000000000000000000000411456566705700345450ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX642603a3031518fe9f21bf6d07835528 DepthCompositeVolume_Renderers_simple_1.png.md5000066400000000000000000000000411456566705700345460ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXa48a2b26a51f0ccab651ef1dfa48c061 DepthCompositeVolume_Renderers_simple_2.png.md5000066400000000000000000000000411456566705700345470ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX56089ffe487951c01a12eb629198ed8e DepthCompositeVolume_Renderers_simple_3.png.md5000066400000000000000000000000411456566705700345500ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXff857fab1a8f9325760f08851316501b DistantLight_LightMotionBlur_parameter_0.png.md5000066400000000000000000000000411456566705700346440ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX323173a42d4f374d660cffaf5ec2df44 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/DistantLight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700327100ustar00rootroot0000000000000012c66430113874ba4d795c2a5335f897 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/DistantLight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700327110ustar00rootroot00000000000000d2851bae6777011ed87fa5b6d64ff7c8 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/DistantLight_Light_parameter_2.png.md5000066400000000000000000000000411456566705700327120ustar00rootroot00000000000000368189c68d2e689d830a566c6880a839 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/DistantLight_Light_parameter_3.png.md5000066400000000000000000000000411456566705700327130ustar00rootroot000000000000004cb53696a83b0c7326c6888c002828a3 FromOsprayTestingLightSamples_TestScenesLightSamples_testScenes_0.png.md5000066400000000000000000000000411456566705700416750ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX45adc210402a9215cf0cf77cb85f3039 FromOsprayTestingLightSamples_TestScenesLightSamples_testScenes_1.png.md5000066400000000000000000000000411456566705700416760ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXbc066e888df6097b89150cd631700ca9 FromOsprayTestingMaxDepth_TestScenesMaxDepth_test_scenes_0.png.md5000066400000000000000000000000411456566705700403300ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX7b145567101fa685ef4fd3d9318e0ab8 FromOsprayTestingMaxDepth_TestScenesMaxDepth_test_scenes_1.png.md5000066400000000000000000000000411456566705700403310ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXfdfdeaf9cf2b46b75164a382d1392a24 FromOsprayTestingMaxDepth_TestScenesMaxDepth_test_scenes_2.png.md5000066400000000000000000000000411456566705700403320ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX0ca1c6949e3509a4c0286a1cb0935446 FromOsprayTestingVariance_TestScenesVariance_testScenes_0.png.md5000066400000000000000000000000411456566705700401650ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX7f2868db0487194db7cf7a8d945680f9 FromOsprayTesting_TestScenesClipping_test_scenes_0.png.md5000066400000000000000000000000411456566705700367300ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX0296157028674dc93d72d85d0e965818 FromOsprayTesting_TestScenesClipping_test_scenes_1.png.md5000066400000000000000000000000411456566705700367310ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX0fd1877c94ac8514b0dfbd9e30726421 FromOsprayTesting_TestScenesClipping_test_scenes_10.png.md5000066400000000000000000000000411456566705700370110ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXfc569947d28c532f62adc96ec4785828 FromOsprayTesting_TestScenesClipping_test_scenes_11.png.md5000066400000000000000000000000411456566705700370120ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX888d98f1dd39afaecb178993b0d746ad FromOsprayTesting_TestScenesClipping_test_scenes_12.png.md5000066400000000000000000000000411456566705700370130ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX6fdf5191f445f07d244e8e6d082f84bf FromOsprayTesting_TestScenesClipping_test_scenes_13.png.md5000066400000000000000000000000411456566705700370140ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXf8327560ec76960ec4446d80b88a1145 FromOsprayTesting_TestScenesClipping_test_scenes_14.png.md5000066400000000000000000000000411456566705700370150ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX9ff00941883291ec044226779055cef2 FromOsprayTesting_TestScenesClipping_test_scenes_15.png.md5000066400000000000000000000000411456566705700370160ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX82791520206ee937d3cc1b7c2e196cb5 FromOsprayTesting_TestScenesClipping_test_scenes_16.png.md5000066400000000000000000000000411456566705700370170ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXb49014c001b9bcccc647809993fece68 FromOsprayTesting_TestScenesClipping_test_scenes_17.png.md5000066400000000000000000000000411456566705700370200ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX0f9fb5b8cc9667e4dece6fc4a43de759 FromOsprayTesting_TestScenesClipping_test_scenes_18.png.md5000066400000000000000000000000411456566705700370210ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX29796dae1e53914c740c14d130005f81 FromOsprayTesting_TestScenesClipping_test_scenes_19.png.md5000066400000000000000000000000411456566705700370220ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXe016efcd24a7f94c326ff1e3fcf4f36c FromOsprayTesting_TestScenesClipping_test_scenes_2.png.md5000066400000000000000000000000411456566705700367320ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX3941e408aef3ce9f87d8cacf1ebe9504 FromOsprayTesting_TestScenesClipping_test_scenes_20.png.md5000066400000000000000000000000411456566705700370120ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX87174ee15065c15b9687ad1b8713ef92 FromOsprayTesting_TestScenesClipping_test_scenes_21.png.md5000066400000000000000000000000411456566705700370130ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX9c746c040621f1889075118e35fe2b7d FromOsprayTesting_TestScenesClipping_test_scenes_22.png.md5000066400000000000000000000000411456566705700370140ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX579ed715d50e8dcdc8cb767748c74ff2 FromOsprayTesting_TestScenesClipping_test_scenes_23.png.md5000066400000000000000000000000411456566705700370150ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX00674517ea25290fefdb1eb341a122b0 FromOsprayTesting_TestScenesClipping_test_scenes_24.png.md5000066400000000000000000000000411456566705700370160ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX43adbf11389d8ad144d2b36f2a25470a FromOsprayTesting_TestScenesClipping_test_scenes_25.png.md5000066400000000000000000000000411456566705700370170ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX624927edc30ebe2e71865990b07428ec FromOsprayTesting_TestScenesClipping_test_scenes_26.png.md5000066400000000000000000000000411456566705700370200ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX1b5caed59b3f0331dc480dc001195e27 FromOsprayTesting_TestScenesClipping_test_scenes_3.png.md5000066400000000000000000000000411456566705700367330ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXa5ad0f0c20eafe1b6403062357bce181 FromOsprayTesting_TestScenesClipping_test_scenes_4.png.md5000066400000000000000000000000411456566705700367340ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX63c25bcdce8bf29d63dd94fe8fad3a72 FromOsprayTesting_TestScenesClipping_test_scenes_5.png.md5000066400000000000000000000000411456566705700367350ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXbc95c3ddc66b3e79f6c8e982f2eac8a7 FromOsprayTesting_TestScenesClipping_test_scenes_6.png.md5000066400000000000000000000000411456566705700367360ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXb32fe5c7b0f6eeb98a00d2cd8b13cd47 FromOsprayTesting_TestScenesClipping_test_scenes_7.png.md5000066400000000000000000000000411456566705700367370ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX1dd830d508709c52000290579fd7b3e7 FromOsprayTesting_TestScenesClipping_test_scenes_8.png.md5000066400000000000000000000000411456566705700367400ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXbd891b1b29e6e755589bf4429f43f57b FromOsprayTesting_TestScenesClipping_test_scenes_9.png.md5000066400000000000000000000000411456566705700367410ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX93e2b97821c1899ca87143f4006f6f10 FromOsprayTesting_TestScenesGeometry_test_scenes_0.png.md5000066400000000000000000000000411456566705700367560ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX005fedac323e30b07b476741459fe6a1 FromOsprayTesting_TestScenesGeometry_test_scenes_1.png.md5000066400000000000000000000000411456566705700367570ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX7617c01f530413c30407133bf21fe1d0 FromOsprayTesting_TestScenesGeometry_test_scenes_10.png.md5000066400000000000000000000000411456566705700370370ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXea89a0c952bb99600620660db1bbeed2 FromOsprayTesting_TestScenesGeometry_test_scenes_11.png.md5000066400000000000000000000000411456566705700370400ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX20517dbc5ff845a99c3b29c5784c49b4 FromOsprayTesting_TestScenesGeometry_test_scenes_12.png.md5000066400000000000000000000000411456566705700370410ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXc28ddf5f3311ee65d7ff407f805b8102 FromOsprayTesting_TestScenesGeometry_test_scenes_13.png.md5000066400000000000000000000000411456566705700370420ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX1ac1f2a6c498298c406b484b9dbfa899 FromOsprayTesting_TestScenesGeometry_test_scenes_14.png.md5000066400000000000000000000000411456566705700370430ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXa8c24f4c3842e40d51bc949fa399c77e FromOsprayTesting_TestScenesGeometry_test_scenes_15.png.md5000066400000000000000000000000411456566705700370440ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX0dfc97c10a8a792e3ef01ca74c178b37 FromOsprayTesting_TestScenesGeometry_test_scenes_16.png.md5000066400000000000000000000000411456566705700370450ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX58ba677634ec1377713746c59ad2f0fd FromOsprayTesting_TestScenesGeometry_test_scenes_17.png.md5000066400000000000000000000000411456566705700370460ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXb2623af89221f26ffc0e011c5fd3872b FromOsprayTesting_TestScenesGeometry_test_scenes_18.png.md5000066400000000000000000000000411456566705700370470ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXeaa20d7198d250f7524d875075c65523 FromOsprayTesting_TestScenesGeometry_test_scenes_19.png.md5000066400000000000000000000000411456566705700370500ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX93f2910c461f8d4a65578de41d888414 FromOsprayTesting_TestScenesGeometry_test_scenes_2.png.md5000066400000000000000000000000411456566705700367600ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX9495604bd4f1d826adefafae768ad9ed FromOsprayTesting_TestScenesGeometry_test_scenes_20.png.md5000066400000000000000000000000411456566705700370400ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX1fce83c5e8a8e32884de61f06ef189fb FromOsprayTesting_TestScenesGeometry_test_scenes_21.png.md5000066400000000000000000000000411456566705700370410ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX2784c3a40b4c304f2dd67a0d226de309 FromOsprayTesting_TestScenesGeometry_test_scenes_22.png.md5000066400000000000000000000000411456566705700370420ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX0ee84a9176088792016e39e64ac96105 FromOsprayTesting_TestScenesGeometry_test_scenes_23.png.md5000066400000000000000000000000411456566705700370430ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX0597b0908477057233b26fdac50f8c30 FromOsprayTesting_TestScenesGeometry_test_scenes_24.png.md5000066400000000000000000000000411456566705700370440ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXca864845643d098c79e7df59405ebc91 FromOsprayTesting_TestScenesGeometry_test_scenes_25.png.md5000066400000000000000000000000411456566705700370450ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX24108e99275920eb6abc2b4ca7f9b3f5 FromOsprayTesting_TestScenesGeometry_test_scenes_26.png.md5000066400000000000000000000000411456566705700370460ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXc97734d3966425576e1c42efd57e8f95 FromOsprayTesting_TestScenesGeometry_test_scenes_27.png.md5000066400000000000000000000000411456566705700370470ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX5104654864fd04fa6ba385c8467f3810 FromOsprayTesting_TestScenesGeometry_test_scenes_28.png.md5000066400000000000000000000000411456566705700370500ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX5104654864fd04fa6ba385c8467f3810 FromOsprayTesting_TestScenesGeometry_test_scenes_29.png.md5000066400000000000000000000000411456566705700370510ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX5104654864fd04fa6ba385c8467f3810 FromOsprayTesting_TestScenesGeometry_test_scenes_3.png.md5000066400000000000000000000000411456566705700367610ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXb529a4853c8e6481d25d47e15089614f FromOsprayTesting_TestScenesGeometry_test_scenes_30.png.md5000066400000000000000000000000411456566705700370410ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX726c140b625aad18f6d1b287a55c6340 FromOsprayTesting_TestScenesGeometry_test_scenes_31.png.md5000066400000000000000000000000411456566705700370420ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX9129cebceccb69ae64697d391b735d09 FromOsprayTesting_TestScenesGeometry_test_scenes_32.png.md5000066400000000000000000000000411456566705700370430ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX31385985c9ee9f55aa87089f474ad60c FromOsprayTesting_TestScenesGeometry_test_scenes_33.png.md5000066400000000000000000000000411456566705700370440ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXd1b38a834f0f3bdd0522d98d81f127d9 FromOsprayTesting_TestScenesGeometry_test_scenes_34.png.md5000066400000000000000000000000411456566705700370450ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX81ac931116d29b98475e903006d4714a FromOsprayTesting_TestScenesGeometry_test_scenes_35.png.md5000066400000000000000000000000411456566705700370460ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX09979f3ae2f9fb1dd7288f58b3e17d64 FromOsprayTesting_TestScenesGeometry_test_scenes_4.png.md5000066400000000000000000000000411456566705700367620ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX449624037e1ef5de3c21708ab9f5adde FromOsprayTesting_TestScenesGeometry_test_scenes_5.png.md5000066400000000000000000000000411456566705700367630ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXd51688c1af06a8e5c99234e43660a8c1 FromOsprayTesting_TestScenesGeometry_test_scenes_6.png.md5000066400000000000000000000000411456566705700367640ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX68978d538ec04f4c4d16f6875cca9028 FromOsprayTesting_TestScenesGeometry_test_scenes_7.png.md5000066400000000000000000000000411456566705700367650ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX68978d538ec04f4c4d16f6875cca9028 FromOsprayTesting_TestScenesGeometry_test_scenes_8.png.md5000066400000000000000000000000411456566705700367660ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX68978d538ec04f4c4d16f6875cca9028 FromOsprayTesting_TestScenesGeometry_test_scenes_9.png.md5000066400000000000000000000000411456566705700367670ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXd61e4794d9dd832af6ac97069eba2152 FromOsprayTesting_TestScenesPtMaterials_test_scenes_0.png.md5000066400000000000000000000000411456566705700374100ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX8cab6629d696874271f40b6aeef16c2f FromOsprayTesting_TestScenesPtMaterials_test_scenes_1.png.md5000066400000000000000000000000411456566705700374110ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX4dcd848b9983daf3c767e5deafbf9f4d FromOsprayTesting_TestScenesPtMaterials_test_scenes_10.png.md5000066400000000000000000000000411456566705700374710ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX526abce1184fef470d4fbbc88a819af3 FromOsprayTesting_TestScenesPtMaterials_test_scenes_11.png.md5000066400000000000000000000000411456566705700374720ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXdd5f24a7f1cca4df0f0aeacff6f7f8f2 FromOsprayTesting_TestScenesPtMaterials_test_scenes_12.png.md5000066400000000000000000000000411456566705700374730ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXba2076c08fe9c04c9811703f0113e40b FromOsprayTesting_TestScenesPtMaterials_test_scenes_13.png.md5000066400000000000000000000000411456566705700374740ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXede14f22d0bb44aa9b45d760c2f2db5f FromOsprayTesting_TestScenesPtMaterials_test_scenes_14.png.md5000066400000000000000000000000411456566705700374750ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX87a2eff0c9ec4aeb40263168aa2c1d81 FromOsprayTesting_TestScenesPtMaterials_test_scenes_15.png.md5000066400000000000000000000000411456566705700374760ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX97b3c16126913a972af4021d729a0f6c FromOsprayTesting_TestScenesPtMaterials_test_scenes_2.png.md5000066400000000000000000000000411456566705700374120ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXe76c8d0f5acf92bfff4c1ade75113f7d FromOsprayTesting_TestScenesPtMaterials_test_scenes_3.png.md5000066400000000000000000000000411456566705700374130ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXf288be1d0a1d78e13994c2cd21514c07 FromOsprayTesting_TestScenesPtMaterials_test_scenes_4.png.md5000066400000000000000000000000411456566705700374140ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX7152970e8ef0d9f69798d0d4b11de4e7 FromOsprayTesting_TestScenesPtMaterials_test_scenes_5.png.md5000066400000000000000000000000411456566705700374150ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXb1eae3b5638b160aa9ab8d9fc1342ea2 FromOsprayTesting_TestScenesPtMaterials_test_scenes_6.png.md5000066400000000000000000000000411456566705700374160ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX4357f8d3b44d73ecf49425354092239a FromOsprayTesting_TestScenesPtMaterials_test_scenes_7.png.md5000066400000000000000000000000411456566705700374170ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX5f5e4418047852b8be5270816e745fd8 FromOsprayTesting_TestScenesPtMaterials_test_scenes_8.png.md5000066400000000000000000000000411456566705700374200ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXd8ec5e5c746ef2cf57f6e15b12665807 FromOsprayTesting_TestScenesPtMaterials_test_scenes_9.png.md5000066400000000000000000000000411456566705700374210ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX0667d0c04af94a41f6d2fc9fdcddf860 FromOsprayTesting_TestScenesVolumesStrictParams_test_scenes_0.png.md5000066400000000000000000000000411456566705700411520ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXb061e43c1f11a436cb2679f76369cfe6 FromOsprayTesting_TestScenesVolumesStrictParams_test_scenes_1.png.md5000066400000000000000000000000411456566705700411530ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXccaa0df440231f0138f17e8d44a9d51e FromOsprayTesting_TestScenesVolumesStrictParams_test_scenes_2.png.md5000066400000000000000000000000411456566705700411540ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXf1ec979e88d9b97b38efeb8d702577f4 FromOsprayTesting_TestScenesVolumes_test_scenes_0.png.md5000066400000000000000000000000411456566705700366150ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX61007e9e7617dc49a8c2a2c69a5e27c9 FromOsprayTesting_TestScenesVolumes_test_scenes_1.png.md5000066400000000000000000000000411456566705700366160ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX11aadc4a516ee56a359e364d094bfc74 FromOsprayTesting_TestScenesVolumes_test_scenes_10.png.md5000066400000000000000000000000411456566705700366760ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX314c55cc9ce1d2208c9ec9a95d98229e FromOsprayTesting_TestScenesVolumes_test_scenes_11.png.md5000066400000000000000000000000411456566705700366770ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXbc80d51afd2d942022b1820dbc7f84e2 FromOsprayTesting_TestScenesVolumes_test_scenes_12.png.md5000066400000000000000000000000411456566705700367000ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXe9255f5d5978373819db855bfbaacd6e FromOsprayTesting_TestScenesVolumes_test_scenes_13.png.md5000066400000000000000000000000411456566705700367010ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXd4cdb84bbaed157348a23d6c1c980898 FromOsprayTesting_TestScenesVolumes_test_scenes_14.png.md5000066400000000000000000000000411456566705700367020ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX7b861d9ded7e810b8411ff5bf208bc30 FromOsprayTesting_TestScenesVolumes_test_scenes_15.png.md5000066400000000000000000000000411456566705700367030ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXe9255f5d5978373819db855bfbaacd6e FromOsprayTesting_TestScenesVolumes_test_scenes_16.png.md5000066400000000000000000000000411456566705700367040ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXd4cdb84bbaed157348a23d6c1c980898 FromOsprayTesting_TestScenesVolumes_test_scenes_17.png.md5000066400000000000000000000000411456566705700367050ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX7b861d9ded7e810b8411ff5bf208bc30 FromOsprayTesting_TestScenesVolumes_test_scenes_18.png.md5000066400000000000000000000000411456566705700367060ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX9e6bfa920c7579632fd07ae633fde44a FromOsprayTesting_TestScenesVolumes_test_scenes_19.png.md5000066400000000000000000000000411456566705700367070ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX3c048787d428ac005188bc2c5153cf71 FromOsprayTesting_TestScenesVolumes_test_scenes_2.png.md5000066400000000000000000000000411456566705700366170ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX58aaddd509d364794807a2ffe2d058e5 FromOsprayTesting_TestScenesVolumes_test_scenes_20.png.md5000066400000000000000000000000411456566705700366770ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX11d2216fd034fd9babfa629a935bf9f7 FromOsprayTesting_TestScenesVolumes_test_scenes_3.png.md5000066400000000000000000000000411456566705700366200ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX44413ed71090df5f96d4cb12c0c95a43 FromOsprayTesting_TestScenesVolumes_test_scenes_4.png.md5000066400000000000000000000000411456566705700366210ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX4f728b7a363ee049508fba6aa60fd4d6 FromOsprayTesting_TestScenesVolumes_test_scenes_5.png.md5000066400000000000000000000000411456566705700366220ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXf89eae18f4cb2a962a4d56f1dea8d28a FromOsprayTesting_TestScenesVolumes_test_scenes_6.png.md5000066400000000000000000000000411456566705700366230ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXdf3ff32830e74a7b3a8c43f3ea7f3c74 FromOsprayTesting_TestScenesVolumes_test_scenes_7.png.md5000066400000000000000000000000411456566705700366240ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX55a63f481cc4d16d3e8168e57f2b6df4 FromOsprayTesting_TestScenesVolumes_test_scenes_8.png.md5000066400000000000000000000000411456566705700366250ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX3ae4d676399496d32187fa45a65f36d1 FromOsprayTesting_TestScenesVolumes_test_scenes_9.png.md5000066400000000000000000000000411456566705700366260ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX4acc73d6c90c381efafe80e17251be54 FromOsprayTesting_Transparency_test_scenes_0.png.md5000066400000000000000000000000411456566705700356330ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXfb91084d1376b9c4b30a18a55365acd3 FromOsprayTesting_Transparency_test_scenes_1.png.md5000066400000000000000000000000411456566705700356340ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXa127284045b24abb5476feba16115fff FromOsprayTesting_Transparency_test_scenes_2.png.md5000066400000000000000000000000411456566705700356350ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX4865efcd3563cd954cdcdc887e1bead8 GeometricLight_LightMotionBlur_parameter_0.png.md5000066400000000000000000000000411456566705700351540ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXd890634b6f26ef2c69b8201c300785ec GeometricLight_LightMotionBlur_parameter_1.png.md5000066400000000000000000000000411456566705700351550ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXd890634b6f26ef2c69b8201c300785ec GeometricLight_LightTexture_parameter_0.png.md5000066400000000000000000000000411456566705700345220ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX868c54b1fcc596278039874ece92e95e GeometricLight_LightTexture_parameter_1.png.md5000066400000000000000000000000411456566705700345230ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX868c54b1fcc596278039874ece92e95e RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/GeometricLight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700332200ustar00rootroot00000000000000e3dc72cf23fd9f39a0a341016a5d4b6a RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/GeometricLight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700332210ustar00rootroot00000000000000e3dc72cf23fd9f39a0a341016a5d4b6a RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/GeometricLight_Light_parameter_2.png.md5000066400000000000000000000000411456566705700332220ustar00rootroot00000000000000bcf2e967bdc255d6007ec23237e65efd RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/GeometricLight_Light_parameter_3.png.md5000066400000000000000000000000411456566705700332230ustar00rootroot00000000000000bcf2e967bdc255d6007ec23237e65efd HDRILight_LightMotionBlur_parameter_0.png.md5000066400000000000000000000000411456566705700337640ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX10546525c7860739cfb7b02dab3603c4 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/HDRILight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700320300ustar00rootroot000000000000001ced2b13d85f1759f41fa08af148ac64 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/HDRILight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700320310ustar00rootroot00000000000000b908fa2b10882cf56cb1f67375a3528c IDBuffer_ObjectInstance_IDBuffer_0.png.md5000066400000000000000000000000411456566705700331530ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXb4044d633a97f8082c16f1ec71c4f92d IDBuffer_ObjectInstance_IDBuffer_1.png.md5000066400000000000000000000000411456566705700331540ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXc48599e72fbe1331151cd49ccf8fe854 IDBuffer_ObjectInstance_IDBuffer_2.png.md5000066400000000000000000000000411456566705700331550ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXc0964106cdfe0c4a236d432f15171a42 IDBuffer_ObjectInstance_IDBuffer_3.png.md5000066400000000000000000000000411456566705700331560ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX4d3a8443c55123c36865c04da7bdd5cb IDBuffer_ObjectInstance_IDBuffer_4.png.md5000066400000000000000000000000411456566705700331570ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX989d7dc347986fa62921e29fd280d974 IDBuffer_ObjectInstance_IDBuffer_5.png.md5000066400000000000000000000000411456566705700331600ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXfab70791d21ecb20d9f838d73027fb53 IDBuffer_ObjectInstance_IDBuffer_6.png.md5000066400000000000000000000000411456566705700331610ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX5978b85b0934aef6d01794607eec538a IDBuffer_ObjectInstance_IDBuffer_7.png.md5000066400000000000000000000000411456566705700331620ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX1686ff030f2491b5d646bf6590405a58 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/IDBuffer_Primitive_IDBuffer_0.png.md5000066400000000000000000000000411456566705700323070ustar00rootroot00000000000000a635c7fdb9cb0394917fa7d5369722a6 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/IDBuffer_Primitive_IDBuffer_1.png.md5000066400000000000000000000000411456566705700323100ustar00rootroot00000000000000abcd7ceac1d7bd3a537e238411df0007 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/ImageOp_DebugOp_ImageOp_0.png.md5000066400000000000000000000000411456566705700314520ustar00rootroot000000000000007aeef0681bcfc1072d64962701642860 Interpolation_Color_Interpolation_0.png.md5000066400000000000000000000000411456566705700337400ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX5ac362cb64845079f85d60c53237a30c Interpolation_Color_Interpolation_1.png.md5000066400000000000000000000000411456566705700337410ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX600f9a78e23df4b21ef1cb3576c41293 Interpolation_Color_Interpolation_2.png.md5000066400000000000000000000000411456566705700337420ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXb96e5ad22db82abfd7a96bb718b39d2c Interpolation_Color_Interpolation_3.png.md5000066400000000000000000000000411456566705700337430ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX37bb390a60b0bfcfa5eefd11c5417400 Interpolation_Color_Interpolation_4.png.md5000066400000000000000000000000411456566705700337440ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX2dcf960bb59871a4576a24a6fa313875 Interpolation_Color_Interpolation_5.png.md5000066400000000000000000000000411456566705700337450ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX2219c6429c336540493059ba4dd21a5b Interpolation_Color_Interpolation_6.png.md5000066400000000000000000000000411456566705700337460ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXb96e5ad22db82abfd7a96bb718b39d2c Interpolation_Color_Interpolation_7.png.md5000066400000000000000000000000411456566705700337470ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX37bb390a60b0bfcfa5eefd11c5417400 Interpolation_Normal_Interpolation_0.png.md5000066400000000000000000000000411456566705700341120ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXb46e1e25fabdba9962cdb1fa797ead04 Interpolation_Normal_Interpolation_1.png.md5000066400000000000000000000000411456566705700341130ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX73b536d10b031c419a7f3acde81851df Interpolation_Texcoord_Interpolation_0.png.md5000066400000000000000000000000411456566705700344510ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXa5952191d40359ec2caef22b16dd59e9 Interpolation_Texcoord_Interpolation_1.png.md5000066400000000000000000000000411456566705700344520ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXb74cb26446f638d39b4395fcc3cc761a Interpolation_Texcoord_Interpolation_2.png.md5000066400000000000000000000000411456566705700344530ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX5791e0b989fba970b48521d80f3d997a Interpolation_Texcoord_Interpolation_3.png.md5000066400000000000000000000000411456566705700344540ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXa7f87e630b9b82e8e44eca2d6d6798f5 MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_0.png.md5000066400000000000000000000000411456566705700412130ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXc11af06b7ed875a6b87d1a5de0427d91 MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_1.png.md5000066400000000000000000000000411456566705700412140ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX3da593a811d23760b111dc55c6fd93d6 MPIFromOsprayTesting_MPIDistribTestScenesGeometry_test_scenes_2.png.md5000066400000000000000000000000411456566705700412150ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXa67563d886598cc3ac2be9fdf494308a MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_0.png.md5000066400000000000000000000000411456566705700410520ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX56338fcff16d21ad86271e3f85052436 MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_1.png.md5000066400000000000000000000000411456566705700410530ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXe5c2467727ae66a9744b8cbb517d606e MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_2.png.md5000066400000000000000000000000411456566705700410540ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX5776518b2bec1f324f15c2ae3ef504a1 MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_3.png.md5000066400000000000000000000000411456566705700410550ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXc76793fe11e0bfdb7f43fd0e8999b63e MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_4.png.md5000066400000000000000000000000411456566705700410560ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXfcf630625ed9a4645b6937030b802c73 MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_5.png.md5000066400000000000000000000000411456566705700410570ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXce646854a5c595b1f7b009c40c256684 MPIFromOsprayTesting_MPIDistribTestScenesVolumes_test_scenes_6.png.md5000066400000000000000000000000411456566705700410600ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX01b17a8669d5be94696470962fcd1389 MotionBlurBoxes_CameraRollingShutter_instance_mb_0.png.md5000066400000000000000000000000411456566705700366570ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXe09a7f947946e09944af1c0ee8eb3225 MotionBlurBoxes_CameraRollingShutter_instance_mb_1.png.md5000066400000000000000000000000411456566705700366600ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX84a327f24353d9c16b1f57cdf8738c52 MotionBlurBoxes_CameraRollingShutter_instance_mb_2.png.md5000066400000000000000000000000411456566705700366610ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXc1a6af91c50b68c06f8d97b4316f1279 MotionBlurBoxes_CameraRollingShutter_instance_mb_3.png.md5000066400000000000000000000000411456566705700366620ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX24b27522f08c8d46b384b0c3ac834133 MotionBlurBoxes_CameraRollingShutter_instance_mb_4.png.md5000066400000000000000000000000411456566705700366630ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX7f1ca47683d8f2a8398e66e2a9a78dde MotionBlurBoxes_CameraRollingShutter_instance_mb_5.png.md5000066400000000000000000000000411456566705700366640ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX4e17234519beab039e833d481d74cf1f MotionBlurBoxes_CameraRollingShutter_instance_mb_6.png.md5000066400000000000000000000000411456566705700366650ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXabe391f40c73fd61fee52307bbb1ff6c MotionBlurBoxes_CameraRollingShutter_instance_mb_7.png.md5000066400000000000000000000000411456566705700366660ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXbd05dcc671fe72f741659d8438901ac6 MotionBlurBoxes_CameraStereoRollingShutter_instance_mb_0.png.md5000066400000000000000000000000411456566705700400410ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX4f9858dff7a78b5ae508fcaf272d3795 MotionBlurBoxes_TestMotionBlur_instance_mb_0.png.md5000066400000000000000000000000411456566705700355130ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX20fdf05b9a77272b90133e3f2e177dce MotionBlurBoxes_TestMotionBlur_instance_mb_1.png.md5000066400000000000000000000000411456566705700355140ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX1d093c1334f74362931d235a587b86c2 MotionCamera_CameraOrtho_camera_mb_0.png.md5000066400000000000000000000000411456566705700336740ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXf21af1f2c408a2359254f34dc9fba77f MotionCamera_CameraStereoRollingShutter_camera_mb_0.png.md5000066400000000000000000000000411456566705700367500ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX1ae7ba722d04dbb8c319d8018173fa1d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/MotionCamera_Camera_camera_mb_0.png.md5000066400000000000000000000000411456566705700327370ustar00rootroot000000000000008b08da5bd0636a80a526846d2b6f51c9 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/MotionCamera_Camera_camera_mb_1.png.md5000066400000000000000000000000411456566705700327400ustar00rootroot00000000000000a3757e91aeffc07c32406ff4ae930530 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/MotionCamera_Camera_camera_mb_2.png.md5000066400000000000000000000000411456566705700327410ustar00rootroot000000000000006f5072460b8a2d60c4081de05e422347 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/MotionCamera_Camera_camera_mb_3.png.md5000066400000000000000000000000411456566705700327420ustar00rootroot000000000000007140a6437c7ddf9a7939f31bfd2ed11f RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/MotionCamera_Camera_camera_mb_4.png.md5000066400000000000000000000000411456566705700327430ustar00rootroot00000000000000a73fc912b5de42ebaa66d13169353591 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/MotionCamera_Camera_camera_mb_5.png.md5000066400000000000000000000000411456566705700327440ustar00rootroot0000000000000067559d0c14af7c4fd2cd392fc29f9b13 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/MotionCamera_Camera_camera_mb_6.png.md5000066400000000000000000000000411456566705700327450ustar00rootroot0000000000000021ca5f70a74e4209e6707f02da1896b8 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/MotionCamera_Camera_camera_mb_7.png.md5000066400000000000000000000000411456566705700327460ustar00rootroot000000000000009d42974498897ad5936846ceb6ebafe1 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/MotionCamera_Camera_camera_mb_8.png.md5000066400000000000000000000000411456566705700327470ustar00rootroot000000000000002f2a9890c1cb8fd9d72689814e64ea68 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/MotionCamera_Camera_camera_mb_9.png.md5000066400000000000000000000000411456566705700327500ustar00rootroot00000000000000405361d8e6cde7f8278a2466b101a990 PTBackgroundRefraction_Appearance_backgroundRefraction_0.png.md5000066400000000000000000000000411456566705700377370ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX4ff8f25e4eb2e84c0b469a5d43e18b44 PTBackgroundRefraction_Appearance_backgroundRefraction_1.png.md5000066400000000000000000000000411456566705700377400ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX83fd955d6b4d2e213aec962d761218cd PhotometricLight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700335200ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXe3b9cc2abb4828e6183db2717a282b05 PhotometricLight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700335210ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX55009c40fefcd4eb6ebf0c5467d1e6f5 PhotometricLight_Light_parameter_10.png.md5000066400000000000000000000000411456566705700336010ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX897322dcba60a3738bb35a161f68a266 PhotometricLight_Light_parameter_11.png.md5000066400000000000000000000000411456566705700336020ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX7c7ebd0441e73b86455662920b3f5a04 PhotometricLight_Light_parameter_2.png.md5000066400000000000000000000000411456566705700335220ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX42f7b6f0bb4b17ebd2d6e2d6dfeb5a52 PhotometricLight_Light_parameter_3.png.md5000066400000000000000000000000411456566705700335230ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX9122d64d2343b2ebcc7aeba86a1d3086 PhotometricLight_Light_parameter_4.png.md5000066400000000000000000000000411456566705700335240ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX97fe194b2dcbd54d45e391449c514b4d PhotometricLight_Light_parameter_5.png.md5000066400000000000000000000000411456566705700335250ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX44328cc612a40a65c2a8e37db15d3e32 PhotometricLight_Light_parameter_6.png.md5000066400000000000000000000000411456566705700335260ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX63b0136d8b074c034affacc4b7545f45 PhotometricLight_Light_parameter_7.png.md5000066400000000000000000000000411456566705700335270ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX7de1516a92e6baaa83a47efd60a53086 PhotometricLight_Light_parameter_8.png.md5000066400000000000000000000000411456566705700335300ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX2c562fee621fe1043fed6bc04d187d5d PhotometricLight_Light_parameter_9.png.md5000066400000000000000000000000411456566705700335310ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX089632b7f534d6b787f719c935c55a36 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/PixelFilter_Camera_test_0.png.md5000066400000000000000000000000411456566705700316610ustar00rootroot000000000000002c04102ec0eb17bb823b00d08929f03c RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/PixelFilter_Camera_test_1.png.md5000066400000000000000000000000411456566705700316620ustar00rootroot000000000000002c5faba08250fdf541f4ad032e55711e RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/PixelFilter_Camera_test_2.png.md5000066400000000000000000000000411456566705700316630ustar00rootroot00000000000000fe60964b25a399e4e814fcf64493e229 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/PixelFilter_Camera_test_3.png.md5000066400000000000000000000000411456566705700316640ustar00rootroot000000000000003c7c73b43d9567f30beac9654ec6381f RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/PixelFilter_Camera_test_4.png.md5000066400000000000000000000000411456566705700316650ustar00rootroot00000000000000e4563a35246501e98b85e2e6d831423b RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/PixelFilter_Camera_test_5.png.md5000066400000000000000000000000411456566705700316660ustar00rootroot000000000000002c04102ec0eb17bb823b00d08929f03c RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/PixelFilter_Camera_test_6.png.md5000066400000000000000000000000411456566705700316670ustar00rootroot0000000000000086303288b32012914d863b574fcd9a51 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/PixelFilter_Camera_test_7.png.md5000066400000000000000000000000411456566705700316700ustar00rootroot00000000000000ccc308475b73ebc0349ae629db5943d4 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/PixelFilter_Camera_test_8.png.md5000066400000000000000000000000411456566705700316710ustar00rootroot00000000000000fcf34a104c3e1089edee4d4c0e89f9f4 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/PixelFilter_Camera_test_9.png.md5000066400000000000000000000000411456566705700316720ustar00rootroot00000000000000f6d563602fc4d9fef040044d93bd7e07 QuadLight_LightIntensityQuantity_parameter_0.png.md5000066400000000000000000000000411456566705700355630ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX7a4647314d9e9fe52cc60f0cd88e7cc5 QuadLight_LightIntensityQuantity_parameter_1.png.md5000066400000000000000000000000411456566705700355640ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX90428918977c596a76589c7e8f514b44 QuadLight_LightIntensityQuantity_parameter_2.png.md5000066400000000000000000000000411456566705700355650ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX0557938f2fb0111a3d89c6f18ea91cc9 QuadLight_LightIntensityQuantity_parameter_3.png.md5000066400000000000000000000000411456566705700355660ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXd702aa0664374d07a45294a61df22e57 QuadLight_LightMotionBlur_parameter_0.png.md5000066400000000000000000000000411456566705700341300ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXc14d9428c60f7f525590d4d84bfabf02 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/QuadLight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700321740ustar00rootroot00000000000000d2e25a08e5f62467fff8017df239e7de RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/QuadLight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700321750ustar00rootroot00000000000000d6dda669082cf67864c7408e7a81ec9c RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/QuadLight_Light_parameter_2.png.md5000066400000000000000000000000411456566705700321760ustar00rootroot0000000000000075bc399da6fce8ceb64cab63777bd52d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/QuadLight_Light_parameter_3.png.md5000066400000000000000000000000411456566705700321770ustar00rootroot00000000000000933a54ee091711fcd8f39ef32605cea8 RendererMaterialList_MaterialLists_material_list_0.png.md5000066400000000000000000000000411456566705700366730ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX6c47ba3fd337d73f44ac05ef4767e046 RendererMaterialList_MaterialLists_material_list_1.png.md5000066400000000000000000000000411456566705700366740ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX616d58357cf8ad2a950296ad7c81106d SphereLight_LightIntensityQuantity_parameter_0.png.md5000066400000000000000000000000411456566705700361170ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXa591333c14e5cb8ebe2b4ac8ef0e1a94 SphereLight_LightIntensityQuantity_parameter_1.png.md5000066400000000000000000000000411456566705700361200ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX1435a54d9a9511b4ee4a435166d11c8a SphereLight_LightIntensityQuantity_parameter_2.png.md5000066400000000000000000000000411456566705700361210ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXb22ea36cd0e4cdba968936a19f7883d6 SphereLight_LightIntensityQuantity_parameter_3.png.md5000066400000000000000000000000411456566705700361220ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX5fd4b0854345dfba7ecc4879cb78dc8f SphereLight_LightIntensityQuantity_parameter_4.png.md5000066400000000000000000000000411456566705700361230ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX40d43cba12b84988edaa4b5996593ff1 SphereLight_LightIntensityQuantity_parameter_5.png.md5000066400000000000000000000000411456566705700361240ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX887aa3ac4e41aadce524615e6987a3f0 SphereLight_LightMotionBlur_parameter_0.png.md5000066400000000000000000000000411456566705700344640ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXeac49e507d0881385bf51e8f65e6dafa RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SphereLight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700325300ustar00rootroot0000000000000058a17cd519c8b5b62b1040d7f5c5f177 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SphereLight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700325310ustar00rootroot00000000000000e61c3cac8839e449c1b0b9c8b430020a RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SphereLight_Light_parameter_2.png.md5000066400000000000000000000000411456566705700325320ustar00rootroot00000000000000112f3bac4b5b2f01e8fc45c3ac9d182b RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SphereLight_Light_parameter_3.png.md5000066400000000000000000000000411456566705700325330ustar00rootroot000000000000009c63f65a1905e6c14064f9ab1282b662 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SphereLight_Light_parameter_4.png.md5000066400000000000000000000000411456566705700325340ustar00rootroot00000000000000ab51df87fb122cd035dbc171e375b92f RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SphereLight_Light_parameter_5.png.md5000066400000000000000000000000411456566705700325350ustar00rootroot00000000000000f6916b40a6519526299b5524ad9f0d99 SpherePrecision_Intersection_sphere_0.png.md5000066400000000000000000000000411456566705700342420ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX247ddc74d65ed8fac9fed9b0bf0d6654 SpherePrecision_Intersection_sphere_1.png.md5000066400000000000000000000000411456566705700342430ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX6ef1519f3e152fa90fab6f331563a8ca SpherePrecision_Intersection_sphere_10.png.md5000066400000000000000000000000411456566705700343230ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXc4f3b4d179efcc9a72ca9954ee89d1a3 SpherePrecision_Intersection_sphere_11.png.md5000066400000000000000000000000411456566705700343240ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX09c211f89d2220d98b94742fccb37a14 SpherePrecision_Intersection_sphere_12.png.md5000066400000000000000000000000411456566705700343250ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX20e20ace063e3344eda60e844851f79c SpherePrecision_Intersection_sphere_13.png.md5000066400000000000000000000000411456566705700343260ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX4594ca2ff268ef351a3a59d7e0ea1886 SpherePrecision_Intersection_sphere_14.png.md5000066400000000000000000000000411456566705700343270ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX8634d6c2195dfa036378d9431f78b813 SpherePrecision_Intersection_sphere_15.png.md5000066400000000000000000000000411456566705700343300ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXbc09ff74ff3f256e1f7dabbb9d8c181f SpherePrecision_Intersection_sphere_16.png.md5000066400000000000000000000000411456566705700343310ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX60c4c0f0cf5e03ad5e96205edfc200b7 SpherePrecision_Intersection_sphere_17.png.md5000066400000000000000000000000411456566705700343320ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXba802dd2427997b1fa27db1c1fb25b00 SpherePrecision_Intersection_sphere_18.png.md5000066400000000000000000000000411456566705700343330ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXe758302f17774ba7acd5dbf9997d36ea SpherePrecision_Intersection_sphere_19.png.md5000066400000000000000000000000411456566705700343340ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXce97d3ecd5fdcaf71ef7dc08d13980a7 SpherePrecision_Intersection_sphere_2.png.md5000066400000000000000000000000411456566705700342440ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX3f7a6f51e50dab15e6148a821ce14099 SpherePrecision_Intersection_sphere_20.png.md5000066400000000000000000000000411456566705700343240ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX5ec0317b36e1b7df997f4632b9cb7039 SpherePrecision_Intersection_sphere_21.png.md5000066400000000000000000000000411456566705700343250ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXdf52f755ff1538b0762908a0d4c31fbe SpherePrecision_Intersection_sphere_22.png.md5000066400000000000000000000000411456566705700343260ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXa612389a72e432c4892f816e0ac9d6af SpherePrecision_Intersection_sphere_23.png.md5000066400000000000000000000000411456566705700343270ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXf698ef0dad8597604c7d3181a4b35b27 SpherePrecision_Intersection_sphere_3.png.md5000066400000000000000000000000411456566705700342450ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX98acdf8a7d6e42921685f8ca979ffca9 SpherePrecision_Intersection_sphere_4.png.md5000066400000000000000000000000411456566705700342460ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX8e3d357fed8c4069badb6e90218676f3 SpherePrecision_Intersection_sphere_5.png.md5000066400000000000000000000000411456566705700342470ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXc265eea80094b81827992c46dfca9b40 SpherePrecision_Intersection_sphere_6.png.md5000066400000000000000000000000411456566705700342500ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX2693fd8082f4746e14228d14823c8215 SpherePrecision_Intersection_sphere_7.png.md5000066400000000000000000000000411456566705700342510ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX805160e724a3a845e232ad47f43c7f7b SpherePrecision_Intersection_sphere_8.png.md5000066400000000000000000000000411456566705700342520ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX7378847974ba02f14ed1c07484d20d93 SpherePrecision_Intersection_sphere_9.png.md5000066400000000000000000000000411456566705700342530ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXf1cd4a263206986e534d5151958b90af SpotLight_LightIntensityQuantity_parameter_0.png.md5000066400000000000000000000000411456566705700356160ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXa591333c14e5cb8ebe2b4ac8ef0e1a94 SpotLight_LightIntensityQuantity_parameter_1.png.md5000066400000000000000000000000411456566705700356170ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX544c09110ab45a7ac602286c55e621c6 SpotLight_LightIntensityQuantity_parameter_2.png.md5000066400000000000000000000000411456566705700356200ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXa95f3f3e5b327efe5eea3380b3fb6716 SpotLight_LightIntensityQuantity_parameter_3.png.md5000066400000000000000000000000411456566705700356210ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXd86e673c6d967180a1e3688f7284a2b5 SpotLight_LightIntensityQuantity_parameter_4.png.md5000066400000000000000000000000411456566705700356220ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXe94f91ea9687e4229507a1798e135970 SpotLight_LightIntensityQuantity_parameter_5.png.md5000066400000000000000000000000411456566705700356230ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX0088dfe601ea100002424d3b2714ad68 SpotLight_LightMotionBlur_parameter_0.png.md5000066400000000000000000000000411456566705700341630ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX8a0f558e1f3e271d171bc1a63a5505bd RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SpotLight_Light_parameter_0.png.md5000066400000000000000000000000411456566705700322270ustar00rootroot000000000000006e69c875527b92cc344b2255d49aa543 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SpotLight_Light_parameter_1.png.md5000066400000000000000000000000411456566705700322300ustar00rootroot00000000000000fdc115503b6f13ded13d1700d530387a RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SpotLight_Light_parameter_2.png.md5000066400000000000000000000000411456566705700322310ustar00rootroot000000000000002071ed754e6ced5c6d7c858700c90a96 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SpotLight_Light_parameter_3.png.md5000066400000000000000000000000411456566705700322320ustar00rootroot000000000000003958644d7bf8e575f2f98b5dcfc04e57 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SpotLight_Light_parameter_4.png.md5000066400000000000000000000000411456566705700322330ustar00rootroot00000000000000c2ab237527996decfee4c902281c8a7d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SpotLight_Light_parameter_5.png.md5000066400000000000000000000000411456566705700322340ustar00rootroot000000000000007f4f37bd2a26afa9fbe4fad121c6a8a3 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SpotLight_Light_parameter_6.png.md5000066400000000000000000000000411456566705700322350ustar00rootroot000000000000004f874be7c445cf60f39330914d2492b2 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SpotLight_Light_parameter_7.png.md5000066400000000000000000000000411456566705700322360ustar00rootroot00000000000000815dbb36620ce3d9fb67af16bc45c9b8 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SpotLight_Light_parameter_8.png.md5000066400000000000000000000000411456566705700322370ustar00rootroot00000000000000926746861e6dd78f7d5a9f03d670f617 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SpotLight_Light_parameter_9.png.md5000066400000000000000000000000411456566705700322400ustar00rootroot000000000000007e6d93e0b068f62197441d61aa42eaf6 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/Stereo_Camera_stereo_0.png.md5000066400000000000000000000000411456566705700312150ustar00rootroot00000000000000a101b64cd3f63170e00890b65c8a5499 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/Stereo_Camera_stereo_1.png.md5000066400000000000000000000000411456566705700312160ustar00rootroot0000000000000085bf732703518cfc9af270da6c5531c1 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/Stereo_Camera_stereo_2.png.md5000066400000000000000000000000411456566705700312170ustar00rootroot00000000000000814b7d3d8e2e8fbc6ed539f0de1acf91 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/Stereo_Camera_stereo_3.png.md5000066400000000000000000000000411456566705700312200ustar00rootroot000000000000006d15e4bcbdd9037dd5b72e442dc6cf93 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/Stereo_Camera_stereo_4.png.md5000066400000000000000000000000411456566705700312210ustar00rootroot00000000000000216abc0d5abdfaa56b236bc2aaecf1bd RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/Stereo_Camera_stereo_5.png.md5000066400000000000000000000000411456566705700312220ustar00rootroot0000000000000006e33d2badc11d81a02a6dda018f7e72 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/Stereo_Camera_stereo_6.png.md5000066400000000000000000000000411456566705700312230ustar00rootroot00000000000000ffdbe2cb2e7a3b5cc958906ad8391021 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/Stereo_Camera_stereo_7.png.md5000066400000000000000000000000411456566705700312240ustar00rootroot000000000000006aafd5dac141de5d94be9936c6f598be RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light2_parameter_0.png.md5000066400000000000000000000000411456566705700316300ustar00rootroot00000000000000d3d1f71a73213e21c0853cd2fb81ea14 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light2_parameter_1.png.md5000066400000000000000000000000411456566705700316310ustar00rootroot0000000000000030f6a8fed556c2144e82d6af3bf38413 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light2_parameter_2.png.md5000066400000000000000000000000411456566705700316320ustar00rootroot0000000000000003aada0ffd5f4d08794c04676b487c4b RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light2_parameter_3.png.md5000066400000000000000000000000411456566705700316330ustar00rootroot00000000000000d4524ef0043c8b30d2d400305e40f555 SunSky_LightMotionBlur_parameter_0.png.md5000066400000000000000000000000411456566705700335020ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX8c5be184c4e0b903b37914cd522fe53d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light_parameter_0.png.md5000066400000000000000000000000411456566705700315460ustar00rootroot000000000000003e5b56f70cbfd4b75d06c58dae33318b RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light_parameter_1.png.md5000066400000000000000000000000411456566705700315470ustar00rootroot00000000000000e761d9960abbcc86d6b56cc59a488e23 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light_parameter_10.png.md5000066400000000000000000000000411456566705700316270ustar00rootroot00000000000000542f88cea0156ffeffe12bf2fdb4e624 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light_parameter_11.png.md5000066400000000000000000000000411456566705700316300ustar00rootroot000000000000008bd2c59521aabd1b8fafb2aead66d5d0 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light_parameter_12.png.md5000066400000000000000000000000411456566705700316310ustar00rootroot0000000000000010532d993fa72bbc1bdd55cbfa9d3bc3 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light_parameter_13.png.md5000066400000000000000000000000411456566705700316320ustar00rootroot00000000000000aecfc8c25556df822ecd47353b9d4f66 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light_parameter_14.png.md5000066400000000000000000000000411456566705700316330ustar00rootroot0000000000000001f1dc126f663ad542eb6ba2384945e7 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light_parameter_2.png.md5000066400000000000000000000000411456566705700315500ustar00rootroot00000000000000156f6d2141cc34bf7e917d621ddcb333 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light_parameter_3.png.md5000066400000000000000000000000411456566705700315510ustar00rootroot0000000000000030350a0d29420a0d0c8a295a05ca5c3a RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light_parameter_4.png.md5000066400000000000000000000000411456566705700315520ustar00rootroot00000000000000e5c1dae4027b9620f3345fe074974e4c RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light_parameter_5.png.md5000066400000000000000000000000411456566705700315530ustar00rootroot00000000000000e7092c6f33a9236be32d9dabce7b5c85 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light_parameter_6.png.md5000066400000000000000000000000411456566705700315540ustar00rootroot00000000000000e6bf2e10e28c4d5a5688464199904442 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light_parameter_7.png.md5000066400000000000000000000000411456566705700315550ustar00rootroot00000000000000cab3383424c3cdc30688548e2e0f4ee7 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light_parameter_8.png.md5000066400000000000000000000000411456566705700315560ustar00rootroot0000000000000092eec847bfceba0cb9a9d6683e4d2728 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/SunSky_Light_parameter_9.png.md5000066400000000000000000000000411456566705700315570ustar00rootroot00000000000000fa33379b0fa06fedb530f7189e06b780 TestAssignedCopy_deleterCallbacks.png.md5000066400000000000000000000000411456566705700333610ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXc38d798d36f03061d5a9fc0a0a3a3e6d TestUSMSharing_SharedData_structured_regular_0.png.md5000066400000000000000000000000411456566705700357510ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXb19ecf9ed96fa82be56387b70909b261 TestUSMSharing_SharedData_structured_regular_1.png.md5000066400000000000000000000000411456566705700357520ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXb19ecf9ed96fa82be56387b70909b261 TestUSMSharing_SharedData_structured_regular_2.png.md5000066400000000000000000000000411456566705700357530ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXb19ecf9ed96fa82be56387b70909b261 Texture2DTransform_Appearance_simple_0.png.md5000066400000000000000000000000411456566705700342560ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX3614ce01a214ecd1e4ff942ebe51162f Texture2DWrapMode_Appearance_wrap_0.png.md5000066400000000000000000000000401456566705700335000ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX97731c498a8be29419817d89b04f2dbfTexture2DWrapMode_Appearance_wrap_1.png.md5000066400000000000000000000000401456566705700335010ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX878d5bb7e434080a24a9c284068041dbRenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/Texture2D_Appearance_filter_0.png.md5000066400000000000000000000000411456566705700324350ustar00rootroot0000000000000063fbdd1930e798c300bd79b82610e81d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/Texture2D_Appearance_filter_1.png.md5000066400000000000000000000000411456566705700324360ustar00rootroot0000000000000063fbdd1930e798c300bd79b82610e81d RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/Texture2D_Appearance_filter_2.png.md5000066400000000000000000000000411456566705700324370ustar00rootroot00000000000000fca8c20343f635fbdcf8a4c22e7ed321 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/Texture2D_Appearance_filter_3.png.md5000066400000000000000000000000411456566705700324400ustar00rootroot00000000000000fca8c20343f635fbdcf8a4c22e7ed321 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/Texture2D_Appearance_filter_4.png.md5000066400000000000000000000000411456566705700324410ustar00rootroot0000000000000036940553e0c1e6dca734757515a85f78 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/Texture2D_Appearance_filter_5.png.md5000066400000000000000000000000411456566705700324420ustar00rootroot0000000000000036940553e0c1e6dca734757515a85f78 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/Texture2D_Appearance_filter_6.png.md5000066400000000000000000000000411456566705700324430ustar00rootroot00000000000000a6783400c29e566af1f9ef45a3ca1836 RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX/Texture2D_Appearance_filter_7.png.md5000066400000000000000000000000411456566705700324440ustar00rootroot00000000000000a6783400c29e566af1f9ef45a3ca1836 TextureVolumeTransform_Renderers_simple_0.png.md5000066400000000000000000000000411456566705700351520ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX5ca76f28d3cca6fdf5b3037ac1da64fc TextureVolumeTransform_deprecated_Renderers_simple_0.png.md5000066400000000000000000000000411456566705700373320ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX5ca76f28d3cca6fdf5b3037ac1da64fc UnstructuredVolume_TestScenesVolumes_simple_0.png.md5000066400000000000000000000000411456566705700360270ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXe84d5badebebaab3d5c24c5706707e91 UnstructuredVolume_TestScenesVolumes_simple_1.png.md5000066400000000000000000000000411456566705700360300ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKXeb6da5c259860fabfa92fcbd5fbb485d UnstructuredVolume_TestScenesVolumes_simple_2.png.md5000066400000000000000000000000411456566705700360310ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX1b67de46978eb87e9896b5eddf6d816d UnstructuredVolume_TestScenesVolumes_simple_3.png.md5000066400000000000000000000000411456566705700360320ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX45f9c3bb677494082f97375c96bfef35 UnstructuredVolume_TestScenesVolumes_simple_4.png.md5000066400000000000000000000000411456566705700360330ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX6572ac88ba74b7b4ac97ea8fc0e7469f UnstructuredVolume_TestScenesVolumes_simple_5.png.md5000066400000000000000000000000411456566705700360340ustar00rootroot00000000000000RenderKit-ospray-f2a61c2/test_image_data/baseline/AVX512SKX17b401041701dcab5f54440efebc797f RenderKit-ospray-f2a61c2/third-party-programs-DPCPP.txt000066400000000000000000000135661456566705700230660ustar00rootroot00000000000000 The oneAPI DPC++ Compiler can be found here: https://github.com/intel/llvm It uses various components with following licenses: https://github.com/intel/llvm/blob/master/flang/LICENSE.TXT https://github.com/intel/llvm/blob/master/compiler-rt/LICENSE.TXT https://github.com/intel/llvm/blob/master/mlir/LICENSE.TXT https://github.com/intel/llvm/blob/master/libclc/LICENSE.TXT https://github.com/intel/llvm/blob/master/libcxxabi/LICENSE.TXT https://github.com/intel/llvm/blob/master/lld/LICENSE.TXT https://github.com/intel/llvm/blob/master/cross-project-tests/debuginfo-tests/dexter/LICENSE.txt https://github.com/intel/llvm/blob/master/libc/LICENSE.TXT https://github.com/intel/llvm/blob/master/clang-tools-extra/LICENSE.TXT https://github.com/intel/llvm/blob/master/clang-tools-extra/clang-tidy/cert/LICENSE.TXT https://github.com/intel/llvm/blob/master/clang-tools-extra/clang-tidy/hicpp/LICENSE.TXT https://github.com/intel/llvm/blob/master/lldb/LICENSE.TXT https://github.com/intel/llvm/blob/master/lldb/third_party/Python/module/ptyprocess-0.6.0/LICENSE https://github.com/intel/llvm/blob/master/lldb/third_party/Python/module/six/LICENSE https://github.com/intel/llvm/blob/master/lldb/third_party/Python/module/pexpect-4.6/LICENSE https://github.com/intel/llvm/blob/master/polly/LICENSE.TXT https://github.com/intel/llvm/blob/master/polly/lib/External/isl/LICENSE https://github.com/intel/llvm/blob/master/polly/lib/External/isl/imath/LICENSE https://github.com/intel/llvm/blob/master/polly/tools/GPURuntime/LICENSE.TXT https://github.com/intel/llvm/blob/master/sycl/LICENSE.TXT https://github.com/intel/llvm/blob/master/llvm-spirv/LICENSE.TXT https://github.com/intel/llvm/blob/master/bolt/LICENSE.TXT https://github.com/intel/llvm/blob/master/pstl/LICENSE.TXT https://github.com/intel/llvm/blob/master/clang/LICENSE.TXT https://github.com/intel/llvm/blob/master/llvm/utils/lit/LICENSE.TXT https://github.com/intel/llvm/blob/master/llvm/utils/unittest/googletest/LICENSE.TXT https://github.com/intel/llvm/blob/master/llvm/utils/unittest/googlemock/LICENSE.txt https://github.com/intel/llvm/blob/master/llvm/LICENSE.TXT https://github.com/intel/llvm/blob/master/llvm/include/llvm/Support/LICENSE.TXT https://github.com/intel/llvm/blob/master/llvm/lib/Support/BLAKE3/LICENSE https://github.com/intel/llvm/blob/master/llvm/test/YAMLParser/LICENSE.txt https://github.com/intel/llvm/blob/master/libunwind/LICENSE.TXT https://github.com/intel/llvm/blob/master/openmp/LICENSE.TXT https://github.com/intel/llvm/blob/master/openmp/runtime/src/thirdparty/ittnotify/LICENSE.txt https://github.com/intel/llvm/blob/master/third-party/benchmark/LICENSE https://github.com/intel/llvm/blob/master/libcxx/LICENSE.TXT The following people and companies contributed to the LLVM project: https://github.com/intel/llvm/blob/master/compiler-rt/CREDITS.TXT https://github.com/intel/llvm/blob/master/libclc/CREDITS.TXT https://github.com/intel/llvm/blob/master/libcxxabi/CREDITS.TXT https://github.com/intel/llvm/blob/master/polly/CREDITS.txt https://github.com/intel/llvm/blob/master/pstl/CREDITS.txt https://github.com/intel/llvm/blob/master/llvm/CREDITS.TXT https://github.com/intel/llvm/blob/master/openmp/CREDITS.txt https://github.com/intel/llvm/blob/master/libcxx/CREDITS.TXT ============================================================================== Software from third parties included in the LLVM Project: ============================================================================== The LLVM Project contains third party software which is under different license terms. All such code will be identified clearly using at least one of two mechanisms: 1) It will be in a separate directory tree with its own `LICENSE.txt` or `LICENSE` file at the top containing the specific license and restrictions which apply to that software, or 2) It will contain specific license and restriction terms at the top of every file. ============================================================================== Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy): ============================================================================== University of Illinois/NCSA Open Source License Copyright (c) 2003-2020 University of Illinois at Urbana-Champaign. All rights reserved. Developed by: LLVM Team University of Illinois at Urbana-Champaign http://llvm.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. * Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. RenderKit-ospray-f2a61c2/third-party-programs-Embree.txt000066400000000000000000003312451456566705700234140ustar00rootroot00000000000000Intel(R) Embree Third Party Programs File This file contains the list of third party software (third party programs) contained in the Intel software and their required notices and/or license terms. This third party software, even if included with the distribution of the Intel software, may be governed by separate license terms, including without limitation, third party license terms, other Intel software license terms, and open source software license terms. These separate license terms govern your use of the third party programs as set forth in the third-party-programs.txt or other similarly-named text file. Third party programs and their corresponding required notices and/or license terms are listed below. 1. Apache License 2.0 ------------------------------------------------------------- 1.1. Intel(R) oneAPI Threading Building Blocks (TBB) https://github.com/oneapi-src/oneTBB Copyright Intel 1.2. Intel(R) Open Image Denoise (OIDN) https://github.com/OpenImageDenoise/oidn Copyright Intel Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 2. Apache License 2.0 with LLVM Exceptions ------------------------------------------------------------- 2.1. oneAPI DPC++ Compiler https://github.com/intel/llvm/ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ---- LLVM Exceptions to the Apache 2.0 License ---- As an exception, if, as a result of your compiling your source code, portions of this Software are embedded into an Object form of such source code, you may redistribute such embedded portions in such Object form without complying with the conditions of Sections 4(a), 4(b) and 4(d) of the License. In addition, if you combine or link compiled forms of this Software with software that is licensed under the GPLv2 ("Combined Software") and if a court of competent jurisdiction determines that the patent provision (Section 3), the indemnity provision (Section 9) or other Section of the License conflicts with the conditions of the GPLv2, you may retroactively and prospectively choose to deem waived or otherwise exclude such Section(s) of the License, but only in their entirety and only with respect to the Combined Software. 3. Pixar Modified Apache License 2.0 ------------------------------------------------------------- 3.1 OpenSubdiv https://github.com/PixarAnimationStudios/OpenSubdiv Copyright 2013 Pixar All rights reserved. This product includes software developed at: Pixar (http://www.pixar.com/). Dreamworks Animation (http://www.dreamworksanimation.com/) Autodesk, Inc. (http://www.autodesk.com/). Google, Inc. (http://www.google.com/). DigitalFish (http://digitalfish.com/). This product includes software developed at: Pixar (http://www.pixar.com/). Modified Apache 2.0 License TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor and its affiliates, except as required to comply with Section 4(c) of the License and to reproduce the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 4. zLib License ------------------------------------------------------------- 4.1. GLFW https://github.com/glfw/glfw Copyright (c) 2002-2006 Marcus Geelnard Copyright (c) 2006-2019 Camilla Loewy This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. This notice may not be removed or altered from any source distribution. You can find this license in the file LICENSE.md of the GLFW source tree and in the comment header of each source file. 5. MIT License ------------------------------------------------------------- 5.1. Gruenschloss Halton https://gruenschloss.org/halton/halton.zip Copyright (c) 2012 Leonhard Gruenschloss (leonhard@gruenschloss.org) 5.2. ImGui https://github.com/ocornut/imgui Copyright (c) 2014-2020 Omar Cornut 5.3. PCG Random Number Generation, C++ Edition https://github.com/imneme/pcg-cpp Copyright (c) 2014-2017 Melissa O'Neill and PCG Project contributors 5.4. SSE2NEON https://github.com/DLTcollab/sse2neon 5.5. stb single-file libraries for C/C++ https://github.com/nothings/stb Copyright (c) 2017 Sean Barrett 5.6. A GPU Optimizer for Blue-Noise Screen-Space Sampler https://github.com/unity-grenoble/sampling_bluenoise_sig21 Copyright (c) 2020 Sylvain Durand The MIT License (MIT) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 6. BSD 3-clause License ------------------------------------------------------------- 6.1. OpenEXR https://github.com/AcademySoftwareFoundation/openexr Copyright (c) Contributors to the OpenEXR Project. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 7. BSD 3-clause License + Dependencies ------------------------------------------------------------- 7.1. TinyEXR https://github.com/syoyo/tinyexr Copyright (c) 2014 - 2021, Syoyo Fujita and many contributors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Syoyo Fujita nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. TinyEXR contains some OpenEXR code, which is licensed under: /////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC // // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // /////////////////////////////////////////////////////////////////////////// 8. Customized BSD 3-clause License ------------------------------------------------------------- 8.1. Syrah https://github.com/boulos/syrah Copyright (c) 2009, Stanford University, and authors listed below. All rights reserved. Original authors: Solomon Boulos Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of Stanford University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9. Boost Software License - Version 1.0 ------------------------------------------------------------- 9.1. Catch2 https://github.com/catchorg/Catch2 Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10. Visual C++ Redistributables for Visual Studio ------------------------------------------------------------- 1. License. This software package from Intel (the “Software Packageâ€) contains code from Microsoft (the “Distributable Codeâ€). You are provided a non-transferable, non-exclusive, non-sublicensable, limited right and license only to use and redistribute the Distributable Code as part of this Software Package. You are not allowed to copy, modify, remove the Distributable Code from the Software Package or redistribute the Distributable Code on a stand-alone basis. 2. Restrictions. The Distributable Code is licensed, not sold. You are only provided the above rights to use the Distributable Code. Intel and Microsoft reserve all other rights. Unless applicable law gives you more rights, you may use the Distributable Code only as expressly permitted in these terms. In using the Distributable Code, you must comply with any technical limitations in the Distributable Code that only allow you to use it in certain ways. You may not: • work around any technical limitations in the Distributable Code; • reverse engineer, decompile or disassemble the software, or otherwise attempt to derive the source code for the Distributable Code, except and to the extent required by third party licensing terms governing use of certain open source components that may be included in the Distributable Code; • remove, minimize, block or modify any notices of Intel, Microsoft or its suppliers in the Distributable Code; • use the Distributable Code in any way that is against the law; or • share, publish, rent or lease the software, or provide the Distributable Code as a stand-alone offering for others to use. 3. NO WARRANTY. THE DISTRIBUTABLE CODE IS PROVIDED “AS IS†WITHOUT ANY EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, OR FITNESS FOR A PARTICULAR PURPOSE. 4. LIMITATION ON AND EXCLUSION OF DAMAGES. YOU CAN RECOVER FROM INTEL, MICROSOFT OR THEIR SUPPLIERS ONLY DIRECT DAMAGES UP TO $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES. This limitation applies to (a) anything related to the Distributable Code; and (b) claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law. It also applies even if Intel or Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state or country may not allow the exclusion or limitation of incidental, consequential or other damages. 5. Export Restrictions. You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit www.microsoft.com/exporting. 11. Pixar Modified Apache 2.0 ------------------------------------------------------------- 11.1 Universal Scene Description https://github.com/PixarAnimationStudios/USD Copyright 2016 Pixar All rights reserved. Modified Apache 2.0 License TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor and its affiliates, except as required to comply with Section 4(c) of the License and to reproduce the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. ============================================================ RapidJSON ============================================================ Tencent is pleased to support the open source community by making RapidJSON available. Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License. If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. To avoid the problematic JSON license in your own projects, it's sufficient to exclude the bin/jsonchecker/ directory, as it's the only code under the JSON license. A copy of the MIT License is included in this file. Other dependencies and licenses: Open Source Software Licensed Under the BSD License: -------------------------------------------------------------------- The msinttypes r29 Copyright (c) 2006-2013 Alexander Chemeris All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Open Source Software Licensed Under the JSON License: -------------------------------------------------------------------- json.org Copyright (c) 2002 JSON.org All Rights Reserved. JSON_checker Copyright (c) 2002 JSON.org All Rights Reserved. Terms of the JSON License: --------------------------------------------------- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The Software shall be used for Good, not Evil. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Terms of the MIT License: -------------------------------------------------------------------- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ============================================================ pygilstate_check ============================================================ The MIT License (MIT) Copyright (c) 2014, Pankaj Pandey Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ============================================================ double-conversion ============================================================ Copyright 2006-2011, the V8 project authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ============================================================ OpenEXR/IlmBase/Half ============================================================ /////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC // // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // /////////////////////////////////////////////////////////////////////////// ============================================================ Apple Technical Q&A QA1361 - Detecting the Debugger https://developer.apple.com/library/content/qa/qa1361/_index.html ============================================================ Sample code project: Detecting the Debugger Version: 1.0 Abstract: Shows how to determine if code is being run under the debugger. IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ============================================================ LZ4 ============================================================ LZ4 - Fast LZ compression algorithm Copyright (C) 2011-present, Yann Collet. BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You can contact the author at : - LZ4 homepage : http://www.lz4.org - LZ4 source repository : https://github.com/lz4/lz4 ============================================================ stb ============================================================ stb_image - v2.19 - public domain image loader - http://nothings.org/stb no warranty implied; use at your own risk stb_image_resize - v0.95 - public domain image resizing by Jorge L Rodriguez (@VinoBS) - 2014 http://github.com/nothings/stb stb_image_write - v1.09 - public domain - http://nothings.org/stb/stb_image_write.h writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 no warranty implied; use at your own risk ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ============================================================ pugixml ============================================================ MIT License Copyright (c) 2006-2019 Arseny Kapoulkine Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ============================================================ Vulkan C++ examples and demos (dome light texture filtering) ============================================================ The MIT License (MIT) Copyright (c) 2016 Sascha Willems Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ============================================================ pbrt (Hammersley Low-Discrepancy Sampling Sequence) ============================================================ Copyright (c) 1998-2015, Matt Pharr, Greg Humphreys, and Wenzel Jakob. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ============================================================ Draco ============================================================ USD bundles Draco, which is available under the Apache 2.0 license. For details, see https://github.com/google/draco/blob/master/README.md. ============================================================ Roboto Fonts ============================================================ USD bundles Roboto fonts, which is available under the Apache 2.0 license. For details, see https://fonts.google.com/specimen/Roboto#license ============================================================ Roboto Mono Fonts ============================================================ USD bundles Roboto Mono fonts, which is available under the Apache 2.0 license. For details, see https://fonts.google.com/specimen/Roboto+Mono#license ============================================================ Vulkan Memory Allocator ============================================================ Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ============================================================ Spirv Reflect ============================================================ Copyright 2017-2018 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ============================================================ khrplatform.h ============================================================ Copyright (c) 2008-2018 The Khronos Group Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and/or associated documentation files (the "Materials"), to deal in the Materials without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Materials, and to permit persons to whom the Materials are furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Materials. THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. ============================================================ surfgrad-bump-standalone-demo ============================================================ MIT License Copyright (c) 2020 mmikk Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================================ Tessil robin-map ================================================================ MIT License Copyright (c) 2017 Thibaut Goetghebuer-Planchon Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 11. Intel End User License Agreement for Developer Tools (Version October 2021) ------------------------------------------------------------------------------- 11.1 Intel(R) oneAPI DPC++/C++ Compiler Intel End User License Agreement for Developer Tools (Version October 2021) IMPORTANT NOTICE - PLEASE READ AND AGREE BEFORE DOWNLOADING, INSTALLING, COPYING OR USING This Agreement is between you, or the company or other legal entity that you represent and warrant you have the legal authority to bind, (each, "You" or "Your") and Intel Corporation and its subsidiaries (collectively, "Intel") regarding Your use of the Materials. By downloading, installing, copying or using the Materials, You agree to be bound by the terms of this Agreement. If You do not agree to the terms of this Agreement, or do not have legal authority or required age to agree to them, do not download, install, copy or use the Materials. LICENSE DEFINITIONS. A. "Cloud Provider" means a third party service provider offering a cloud-based platform, infrastructure, application or storage services, such as Microsoft Azure or Amazon Web Services, which You may only utilize to host the Materials subject to the restrictions set forth in Section 2.3 B. B. "Derivative Work" means a derivative work, as defined in 17 U.S.C. § 101, of the Source Code. C. "Executable Code" means computer programming code in binary form suitable for machine execution by a processor without the intervening steps of interpretation or compilation. D. "Materials" mean the software, documentation, the software product serial number, and other collateral, including any updates, made available to You by Intel under this Agreement. Materials include Redistributables, Executable Code, Source Code, Sample Source Code, and Pre-Release Materials, but do not include Third Party Software. E. "Pre-Release Materials" mean the Materials, or portions of the Materials, that are identified (in the product release notes, on Intel's download website for the Materials or elsewhere) or labeled as pre-release, prototype, alpha or beta code and, as such, are deemed to be pre-release code (i) which may not be fully functional or tested and may contain bugs or errors; (ii) which Intel may substantially modify in its development of a production version; or (iii) for which Intel makes no assurances that it will ever develop or make a production version generally available. Pre-Release Materials are subject to the terms of Section 3.2. F. "Reciprocal Open Source Software" means any software that is subject to a license which requires that (i) it must be distributed in source code form; (ii) it must be licensed under the same open source license terms; and (iii) its derivative works must be licensed under the same open source license terms. Examples of this type of license are the GNU General Public License or the Mozilla Public License. G. "Redistributables" mean the files (if any) listed in the "redist.txt," "redist-rt.txt" or similarlynamed text files that may be included in the Materials. Redistributables include Sample Source Code. H. "Sample Source Code" means those portions of the Materials that are Source Code and are identified as sample code. Sample Source Code may not have been tested or validated by Intel and is provided purely as a programming example. I. "Source Code" means the software portion of the Materials provided in human readable format. J. "Third Party Software" mean the files (if any) listed in the "third-party-software.txt" or other similarly-named text file that may be included in the Materials for the applicable software. Third Party Software is subject to the terms of Section 2.2. K. "Your Product" means one or more applications, products or projects developed by or for You using the Materials. 2. LICENSE GRANTS. 2.1 License to the Materials. Subject to the terms and conditions of this Agreement, Intel grants You a non-exclusive, worldwide, non-assignable, non-sublicensable, limited right and license under its copyrights, to: A. reproduce internally a reasonable number of copies of the Materials for Your personal or business use; B. use the Materials solely for Your personal or business use to develop Your Product, in accordance with the documentation included as part of the Materials; C. modify or create Derivative Works only of the Redistributables, or any portions, that are provided to You in Source Code; D. distribute (directly and through Your distributors, resellers, and other channel partners, if applicable), the Redistributables, including any modifications to or Derivative Works of the Redistributables or any portions made pursuant to Section 2.1.C subject to the following conditions: (1) Any distribution of the Redistributables must only be as part of Your Product which must add significant primary functionality different than that of the Redistributables themselves; (2) You must only distribute the Redistributables originally provided to You by Intel only in Executable Code subject to a license agreement that prohibits reverse engineering, decompiling or disassembling the Redistributables; (3) This distribution right includes a limited right to sublicense only the Intel copyrights in the Redistributables and only to the extent necessary to perform, display, and distribute the Redistributables (including Your modifications and Derivative Works of the Redistributables provided in Source Code) solely as incorporated in Your Product; and (4) You: (i) will be solely responsible to Your customers for any update, support obligation or other obligation or liability which may arise from the distribution of Your Product, (ii) will not make any statement that Your Product is "certified" or that its performance is guaranteed by Intel or its suppliers, (iii) will not use Intel's or its suppliers' names or trademarks to market Your Product, (iv) will comply with any additional restrictions which are included in the text files with the Redistributables and in Section 3 below, (v) will indemnify, hold harmless, and defend Intel and its suppliers from and against any claims or lawsuits, costs, damages, and expenses, including attorney's fees, that arise or result from (a) Your modifications or Derivative Works of the Materials or (b) Your distribution of Your Product. 2.2 Third Party Software. Third Party Software, even if included with the distribution of the Materials, may be governed by separate license terms, including without limitation, third party license terms, open source software notices and terms, and/or other Intel software license terms. These separate license terms solely govern Your use of the Third Party Software. 2.3 Third Party Use. A. If You are an entity, Your contractors may use the Materials under the license specified in Section 2, provided: (i) their use of the Materials is solely on behalf of and in support of Your business, (ii) they agree to the terms and conditions of this Agreement, and (iii) You are solely responsible for their use, misuse or disclosure of the Materials. B. You may utilize a Cloud Provider to host the Materials for You, provided: (i) the Cloud Provider may only host the Materials for Your exclusive use and may not use the Materials for any other purpose whatsoever, including the restriction set forth in Section 3.1(xi); (ii) the Cloud Provider's use of the Materials must be solely on behalf of and in support of Your Product, and (iii) You will indemnify, hold harmless, and defend Intel and its suppliers from and against any claims or lawsuits, costs, damages, and expenses, including attorney's fees, that arise or result from Your Cloud Provider's use, misuse or disclosure of the Materials. 3. LICENSE CONDITIONS. 3.1 Restrictions. Except as expressly provided in this Agreement, You may NOT: (i) use, reproduce, disclose, distribute, or publicly display the Materials; (ii) share, publish, rent or lease the Materials to any third party; (iii) assign this Agreement or transfer the Materials; (iv) modify, adapt, or translate the Materials in whole or in part; (v) reverse engineer, decompile, or disassemble the Materials, or otherwise attempt to derive the source code for the software; (vi) work around any technical limitations in the Materials; (vii) distribute, sublicense or transfer any Source Code, modifications or Derivative Works of any Source Code to any third party; (viii) remove, minimize, block or modify any notices of Intel or its suppliers in the Materials; (ix) include the Redistributables in malicious, deceptive, or unlawful programs or products or use the Materials in any way that is against the law; (x) modify, create a Derivative Work, link, or distribute the Materials so that any part of it becomes Reciprocal Open Source Software; (xi) use the Materials directly or indirectly for SaaS services or service bureau purposes (i.e., a service that allows use of or access to the Materials by a third party as part of that service, such as the salesforce.com service business model). 3.2 Pre-Release Materials. If You receive Pre-Release Materials, You may reproduce a reasonable number of copies and use the Pre-Release Materials for evaluation and testing purposes only. You may not (i) modify or incorporate the Pre-Release Materials into Your Product; (ii) continue to use the Pre-Release Materials once a commercial version is released; or (iii) disclose to any third party any benchmarks, performance results, or other information relating to the Pre-Release Materials. Intel may waive these restrictions in writing at its sole discretion; however, if You decide to use the Pre-Release Materials in Your Product (even with Intel's waiver), You acknowledge and agree that You are fully responsible for any and all issues that result from such use. 3.3 Safety-Critical, and Life-Saving Applications; Indemnity. The Materials may provide information relevant to safety-critical applications ("Safety-Critical Applications") to allow compliance with functional safety standards or requirements. You acknowledge and agree that safety is Your responsibility. To the extent You use the Materials to create, or as part of, products used in Safety-Critical Applications, it is Your responsibility to design, manage, and ensure that there are system-level safeguards to anticipate, monitor, and control system failures, and You agree that You are solely responsible for all applicable regulatory standards and safety-related requirements concerning Your use of the Materials in Safety Critical Applications. Should You use the Materials for Safety-Critical Applications or in any type of a system or application in which the failure of the Materials could create a situation where personal injury or death may occur (e.g., medical systems, life-sustaining or life-saving systems) ("Life-Saving Applications"), You agree to indemnify, defend, and hold Intel and its representatives harmless against any claims or lawsuits, costs, damages, and expenses, including reasonable attorney fees, arising in any way out of Your use of the Materials in Safety-Critical Applications or Life-Saving Applications and claims of product liability, personal injury or death associated with those applications; even if such claims allege that Intel was negligent or strictly liable regarding the design or manufacture of the Materials or its failure to warn regarding the Materials. 3.4 Media Format Codecs and Digital Rights Management. You acknowledge and agree that Your use of the Materials or distribution of the Redistributables with Your Product as permitted by this Agreement may require You to procure license(s) from third parties that may hold intellectual property rights applicable to any media decoding, encoding or transcoding technology (e.g., the use of an audio or video codec) and/or digital rights management capabilities of the Materials, if any. Should any such additional licenses be required, You are solely responsible for obtaining any such licenses and agree to obtain any such licenses at Your own expense. 4. DATA COLLECTION AND PRIVACY. 4.1 Data Collection. The Materials may generate and collect anonymous data and/or provisioning data about the Materials and/or the development environment and transmit the data to Intel as a one-time event during installation. Optional data may also be collected by the Materials, however, You will be provided notice of the request to collect optional data and no optional data will be collected without Your consent. All data collection by Intel is performed pursuant to relevant privacy laws, including notice and consent requirements. 4.2 Intel's Privacy Notice. Intel is committed to respecting Your privacy. To learn more about Intel's privacy practices, please visit http://www.intel.com/privacy. 5. OWNERSHIP. Title to the Materials and all copies remain with Intel or its suppliers. The Materials are protected by intellectual property rights, including without limitation, United States copyright laws and international treaty provisions. You will not remove any copyright or other proprietary notices from the Materials. Except as expressly provided herein, no license or right is granted to You directly or by implication, inducement, estoppel or otherwise; specifically, Intel does not grant any express or implied right to You under Intel patents, copyrights, trademarks, or trade secrets. 6. NO WARRANTY AND NO SUPPORT. 6.1 No Warranty. Disclaimer. Intel disclaims all warranties of any kind and the terms and remedies provided in this Agreement are instead of any other warranty or condition, express, implied or statutory, including those regarding merchantability, fitness for any particular purpose, non-infringement or any warranty arising out of any course of dealing, usage of trade, proposal, specification or sample. Intel does not assume (and does not authorize any person to assume on its behalf) any liability. 6.2 No Support; Priority Support. Intel may make changes to the Materials, or to items referenced therein, at any time without notice, but is not obligated to support, update or provide training for the Materials under the terms of this Agreement. Intel offers free community and paid priority support options. More information on these support options can be found at: https://software.intel.com/content/www/us/en/develop/support/priority-support.html. 7. LIMITATION OF LIABILITY. 7.1 Intel will not be liable for any of the following losses or damages (whether such losses or damages were foreseen, foreseeable, known or otherwise): (i) loss of revenue; (ii) loss of actual or anticipated profits; (iii) loss of the use of money; (iv) loss of anticipated savings; (v) loss of business; (vi) loss of opportunity; (vii) loss of goodwill; (viii) loss of use of the Materials; (ix) loss of reputation; (x) loss of, damage to, or corruption of data; or (xi) any indirect, incidental, special or consequential loss of damage however caused (including loss or damage of the type specified in this Section 7). 7.2 Intel's total cumulative liability to You, including for direct damages for claims relating to this Agreement, and whether for breach of contract, negligence, or for any other reason, will not exceed $100. 7.3 You acknowledge that the limitations of liability provided in this Section 7 are an essential part of this Agreement. You agree that the limitations of liability provided in this Agreement with respect to Intel will be conveyed to and made binding upon any customer of Yours that acquires the Redistributables. 8. USER SUBMISSIONS. Should you provide Intel with comments, modifications, corrections, enhancements or other input ("Feedback") related to the Materials, Intel will be free to use, disclose, reproduce, license or otherwise distribute or exploit the Feedback in its sole discretion without any obligations or restrictions of any kind, including without limitation, intellectual property rights or licensing obligations. If You wish to provide Intel with information that You intend to be treated as confidential information, Intel requires that such confidential information be provided pursuant to a non-disclosure agreement ("NDA"); please contact Your Intel representative to ensure the proper NDA is in place. 9. NON-DISCLOSURE. Information provided by Intel to You may include information marked as confidential. You must treat such information as confidential under the terms of the applicable NDA between Intel and You. If You have not entered into an NDA with Intel, You must not disclose, distribute or make use of any information marked as confidential, except as expressly authorized in writing by Intel. Intel retains all rights in and to its confidential information specifications, designs, engineering details, discoveries, inventions, patents, copyrights, trademarks, trade secrets, and other proprietary rights relating to the Materials. Any breach by You of the confidentiality obligations provided for in this Section 9 will cause irreparable injury to Intel for which money damages may be inadequate to compensate Intel for losses arising from such a breach. Intel may obtain equitable relief, including injunctive relief, if You breach or threaten to breach Your confidentiality obligations. 10. TERM AND TERMINATION. This Agreement becomes effective on the date You accept this Agreement and will continue until terminated as provided for in this Agreement. The term for any Pre-Release Materials terminates upon release of a commercial version. This Agreement will terminate if You are in breach of any of its terms and conditions. Upon termination, You will promptly destroy the Materials and all copies. In the event of termination of this Agreement, Your license to any Redistributables distributed by You in accordance with the terms and conditions of this Agreement, prior to the effective date of such termination, will survive any such termination of this Agreement. Sections 1, 2.1.D(4)(v), 2.2, 2.3.A(iii), 2.3.B(iii), 3.3, 5, 6, 7, 8, 9, 10 (with respect to these survival provisions in the last sentence), and 12 will survive expiration or termination of this Agreement. 11. U.S. GOVERNMENT RESTRICTED RIGHTS. The technical data and computer software covered by this license is a "Commercial Item," as such term is defined by the FAR 2.101 (48 C.F.R. 2.101) and is "commercial computer software" and "commercial computer software documentation" as specified under FAR 12.212 (48 C.F.R. 12.212) or DFARS 227.7202 (48 C.F.R. 227.7202), as applicable. This commercial computer software and related documentation is provided to end users for use by and on behalf of the U.S. Government with only those rights as are granted to all other end users pursuant to the terms and conditions of this Agreement. 12. GENERAL PROVISIONS. 12.1 ENTIRE AGREEMENT. This Agreement contains the complete and exclusive agreement and understanding between the parties concerning the subject matter of this Agreement, and supersedes all prior and contemporaneous proposals, agreements, understanding, negotiations, representations, warranties, conditions, and communications, oral or written, between the parties relating to the same subject matter. Each party acknowledges and agrees that in entering into this Agreement it has not relied on, and will not be entitled to rely on, any oral or written representations, warranties, conditions, understanding, or communications between the parties that are not expressly set forth in this Agreement. The express provisions of this Agreement control over any course of performance, course of dealing, or usage of the trade inconsistent with any of the provisions of this Agreement. The provisions of this Agreement will prevail notwithstanding any different, conflicting, or additional provisions that may appear on any purchase order, acknowledgement, invoice, or other writing issued by either party in connection with this Agreement. No modification or amendment to this Agreement will be effective unless in writing and signed by authorized representatives of each party, and must specifically identify this Agreement by its title and version (e.g., "Intel End User License Agreement for Developer Tools (Version October 2021)"); except that Intel may make changes to this Agreement as it distributes new versions of the Materials. When changes are made, Intel will make a new version of the Agreement available on its website. If You received a copy of this Agreement translated into another language, the English language version of this Agreement will prevail in the event of any conflict between versions. 12.2 EXPORT. You acknowledge that the Materials and all related technical information are subject to export controls and you agree to comply with all laws and regulations of the United States and other applicable governments governing export, re-export, import, transfer, distribution, and use of the Materials. In particular, but without limitation, the Materials may not be exported or re-exported (i) into any U.S. embargoed countries or (ii) to any person or entity listed on a denial order published by the U.S. government or any other applicable governments. By using the Materials, You represent and warrant that You are not located in any such country or on any such list. You also agree that You will not use the Materials for, or sell or transfer them to a third party who is known or suspected to be involved in, any purposes prohibited by the U.S. government or other applicable governments, including, without limitation, the development, design, manufacture, or production of nuclear, missile, chemical or biological weapons. 12.3 GOVERNING LAW, JURISDICTION, AND VENUE. All disputes arising out of or related to this Agreement, whether based on contract, tort, or any other legal or equitable theory, will in all respects be governed by, and construed and interpreted under, the laws of the United States of America and the State of Delaware, without reference to conflict of laws principles. The parties agree that the United Nations Convention on Contracts for the International Sale of Goods (1980) is specifically excluded from and will not apply to this Agreement. All disputes arising out of or related to this Agreement, whether based on contract, tort, or any other legal or equitable theory, will be subject to the exclusive jurisdiction of the courts of the State of Delaware or of the Federal courts sitting in that State. Each party submits to the personal jurisdiction of those courts and waives all objections to that jurisdiction and venue for those disputes. 12.4 SEVERABILITY. The parties intend that if a court holds that any provision or part of this Agreement is invalid or unenforceable under applicable law, the court will modify the provision to the minimum extent necessary to make it valid and enforceable, or if it cannot be made valid and enforceable, the parties intend that the court will sever and delete the provision or part from this Agreement. Any change to or deletion of a provision or part of this Agreement under this Section will not affect the validity or enforceability of the remainder of this Agreement, which will continue in full force and effect. 12. Additional Third Party Program Files ------------------------------------------------------------- The following third party programs have their own third party program files. These additional third party program files are as follows: 12.1. Intel(R) oneAPI Threading Building Blocks (TBB) third-party-programs-oneTBB.txt 12.2. Intel(R) Open Image Denoise (OIDN) third-party-programs-OIDN.txt file. 12.3. oneAPI DPC++ Compiler third-party-programs-DPCPP.txt file. 12.4. Intel(R) oneAPI DPC++/C++ Compiler third-party-programs-oneAPI-DPCPP.txt file. RenderKit-ospray-f2a61c2/third-party-programs-ISPC.txt000066400000000000000000002742101456566705700227510ustar00rootroot00000000000000Intel(R) Implicit SPMD Program Compiler (Intel(R) ISPC) Third Party Programs File. This file contains the list of third party software ("third party programs") contained in the Intel software and their required notices and/or license terms. This third party software, even if included with the distribution of the Intel software, may be governed by separate license terms, including without limitation, third party license terms, other Intel software license terms, and open source software license terms. These separate license terms govern your use of the third party programs as set forth in the “third-party-programs.txt†or other similarly named text file. Third party programs and their corresponding required notices and/or license terms are listed below. -------------------------------------------------------------------------------- 1. LLVM Project. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ---- LLVM Exceptions to the Apache 2.0 License ---- As an exception, if, as a result of your compiling your source code, portions of this Software are embedded into an Object form of such source code, you may redistribute such embedded portions in such Object form without complying with the conditions of Sections 4(a), 4(b) and 4(d) of the License. In addition, if you combine or link compiled forms of this Software with software that is licensed under the GPLv2 ("Combined Software") and if a court of competent jurisdiction determines that the patent provision (Section 3), the indemnity provision (Section 9) or other Section of the License conflicts with the conditions of the GPLv2, you may retroactively and prospectively choose to deem waived or otherwise exclude such Section(s) of the License, but only in their entirety and only with respect to the Combined Software. ============================================================================== Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy): ============================================================================== University of Illinois/NCSA Open Source License Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign. All rights reserved. Developed by: LLVM Team University of Illinois at Urbana-Champaign http://llvm.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. * Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. -------------------------------------------------------------------------------- 2. Syrah library. Copyright (c) 2009, Stanford University, and authors listed below. All rights reserved. Original authors: Solomon Boulos Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of Stanford University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- 3. IEEE 754r Half Precision Floating Point Converter. (c) 2009 by James Tursa, All Rights Reserved Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- 4. libncurses libtinfo Copyright 2018-2021,2022 Thomas E. Dickey Copyright 1998-2017,2018 Free Software Foundation, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, distribute with modifications, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name(s) of the above copyright holders shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization. -------------------------------------------------------------------------------- 5. GNU libstdc++ libgcc GCC is Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 Free Software Foundation, Inc. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Files that have exception clauses are licensed under the terms of the GNU General Public License; either version 3, or (at your option) any later version. On Debian GNU/Linux systems, the complete text of the GNU General Public License is in `/usr/share/common-licenses/GPL', version 3 of this license in `/usr/share/common-licenses/GPL-3'. The following runtime libraries are licensed under the terms of the GNU General Public License (v3 or later) with version 3.1 of the GCC Runtime Library Exception (included in this file): - libgcc (libgcc/, gcc/libgcc2.[ch], gcc/unwind*, gcc/gthr*, gcc/coretypes.h, gcc/crtstuff.c, gcc/defaults.h, gcc/dwarf2.h, gcc/emults.c, gcc/gbl-ctors.h, gcc/gcov-io.h, gcc/libgcov.c, gcc/tsystem.h, gcc/typeclass.h). - libatomic - libdecnumber - libgomp - libitm - libssp - libstdc++-v3 - libobjc - libgfortran - The libgnat-9 Ada support library and libgnatvsn library. - Various config files in gcc/config/ used in runtime libraries. - libvtv The libbacktrace library is licensed under the following terms: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. (3) The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The libsanitizer libraries (libasan, liblsan, libtsan, libubsan) are licensed under the following terms: Copyright (c) 2009-2014 by the LLVM contributors. All rights reserved. Developed by: LLVM Team University of Illinois at Urbana-Champaign http://llvm.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. * Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The libffi library is licensed under the following terms: libffi - Copyright (c) 1996-2003 Red Hat, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ``Software''), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. The documentation is licensed under the GNU Free Documentation License (v1.2). On Debian GNU/Linux systems, the complete text of this license is in `/usr/share/common-licenses/GFDL-1.2'. GCC RUNTIME LIBRARY EXCEPTION Version 3.1, 31 March 2009 Copyright (C) 2009 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This GCC Runtime Library Exception ("Exception") is an additional permission under section 7 of the GNU General Public License, version 3 ("GPLv3"). It applies to a given file (the "Runtime Library") that bears a notice placed by the copyright holder of the file stating that the file is governed by GPLv3 along with this Exception. When you use GCC to compile a program, GCC may combine portions of certain GCC header files and runtime libraries with the compiled program. The purpose of this Exception is to allow compilation of non-GPL (including proprietary) programs to use, in this way, the header files and runtime libraries covered by this Exception. 0. Definitions. A file is an "Independent Module" if it either requires the Runtime Library for execution after a Compilation Process, or makes use of an interface provided by the Runtime Library, but is not otherwise based on the Runtime Library. "GCC" means a version of the GNU Compiler Collection, with or without modifications, governed by version 3 (or a specified later version) of the GNU General Public License (GPL) with the option of using any subsequent versions published by the FSF. "GPL-compatible Software" is software whose conditions of propagation, modification and use would permit combination with GCC in accord with the license of GCC. "Target Code" refers to output from any compiler for a real or virtual target processor architecture, in executable form or suitable for input to an assembler, loader, linker and/or execution phase. Notwithstanding that, Target Code does not include data in any format that is used as a compiler intermediate representation, or used for producing a compiler intermediate representation. The "Compilation Process" transforms code entirely represented in non-intermediate languages designed for human-written code, and/or in Java Virtual Machine byte code, into Target Code. Thus, for example, use of source code generators and preprocessors need not be considered part of the Compilation Process, since the Compilation Process can be understood as starting with the output of the generators or preprocessors. A Compilation Process is "Eligible" if it is done using GCC, alone or with other GPL-compatible software, or if it is done without using any work based on GCC. For example, using non-GPL-compatible Software to optimize any GCC intermediate representations would not qualify as an Eligible Compilation Process. 1. Grant of Additional Permission. You have permission to propagate a work of Target Code formed by combining the Runtime Library with Independent Modules, even if such propagation would otherwise violate the terms of GPLv3, provided that all Target Code was generated by Eligible Compilation Processes. You may then convey such a combination under terms of your choice, consistent with the licensing of the Independent Modules. 2. No Weakening of GCC Copyleft. The availability of this Exception does not imply any general presumption that third-party software is unaffected by the copyleft requirements of the license of GCC. libquadmath/*.[hc]: Copyright (C) 2010 Free Software Foundation, Inc. Written by Francois-Xavier Coudert Written by Tobias Burnus This file is part of the libiberty library. Libiberty is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Libiberty is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. libquadmath/math: atanq.c, expm1q.c, j0q.c, j1q.c, log1pq.c, logq.c: Copyright 2001 by Stephen L. Moshier This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. coshq.c, erfq.c, jnq.c, lgammaq.c, powq.c, roundq.c: Changes for 128-bit __float128 are Copyright (C) 2001 Stephen L. Moshier and are incorporated herein by permission of the author. The author reserves the right to distribute this material elsewhere under different copying permissions. These modifications are distributed here under the following terms: This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. ldexpq.c: * Conversion to long double by Ulrich Drepper, * Cygnus Support, drepper@cygnus.com. cosq_kernel.c, expq.c, sincos_table.c, sincosq.c, sincosq_kernel.c, sinq_kernel.c, truncq.c: Copyright (C) 1997, 1999 Free Software Foundation, Inc. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. isinfq.c: * Written by J.T. Conklin . * Change for long double by Jakub Jelinek * Public domain. llroundq.c, lroundq.c, tgammaq.c: Copyright (C) 1997, 1999, 2002, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1997 and Jakub Jelinek , 1999. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. log10q.c: Cephes Math Library Release 2.2: January, 1991 Copyright 1984, 1991 by Stephen L. Moshier Adapted for glibc November, 2001 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. remaining files: * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. * * Developed at SunPro, a Sun Microsystems, Inc. business. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. gcc/go/gofrontend, libgo: Copyright (c) 2009 The Go Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. D: gdc-9 GNU D Compiler libphobos-9-dev D standard runtime library The D source package is made up of the following components. The D front-end for GCC: - d/* Copyright (C) 2004-2007 David Friedman Modified by Vincenzo Ampolo, Michael Parrot, Iain Buclaw, (C) 2009, 2010 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. On Debian GNU/Linux systems, the complete text of the GNU General Public License is in `/usr/share/common-licenses/GPL', version 2 of this license in `/usr/share/common-licenses/GPL-2'. The DMD Compiler implementation of the D programming language: - d/dmd/* Copyright (c) 1999-2010 by Digital Mars All Rights Reserved written by Walter Bright http://www.digitalmars.com License for redistribution is by either the Artistic License or the GNU General Public License (v1). On Debian GNU/Linux systems, the complete text of the GNU General Public License is in `/usr/share/common-licenses/GPL', the Artistic license in `/usr/share/common-licenses/Artistic'. The Zlib data compression library: - d/phobos/etc/c/zlib/* (C) 1995-2004 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. The Phobos standard runtime library: - d/phobos/* Unless otherwise marked within the file, each file in the source is under the following licenses: Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com Written by Walter Bright This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, in both source and binary form, subject to the following restrictions: o The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. o Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. o This notice may not be removed or altered from any source distribution. By plainly marking modifications, something along the lines of adding to each file that has been changed a "Modified by Foo Bar" line underneath the "Written by" line would be adequate. The libhsail-rt library is licensed under the following terms: Copyright (C) 2015-2017 Free Software Foundation, Inc. Contributed by Pekka Jaaskelainen for General Processor Tech. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. libhsail-rt/rt/fp16.c is licensed under the following terms: Copyright (C) 2008-2017 Free Software Foundation, Inc. Contributed by CodeSourcery. This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Under Section 7 of GPL version 3, you are granted additional permissions described in the GCC Runtime Library Exception, version 3.1, as published by the Free Software Foundation. You should have received a copy of the GNU General Public License and a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . gcc/gm2: Copyright (C) 2007-2019 Free Software Foundation, Inc. Contributed by Gaius Mulley . This file is part of GNU Modula-2. GNU Modula-2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. gcc/gm2/**/*.texi: Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2012, 2013 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. gcc/gm2/gm2-coroutines: Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. gcc/gm2/ulm-lib-gm2: Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. GNU Modula-2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. This file was originally part of the University of Ulm library Ulm's Modula-2 Library Copyright (C) 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 by University of Ulm, SAI, D-89069 Ulm, Germany gcc/gm2/ulm-lib-gm2/std/M2RTS.mod: gcc/gm2/ulm-lib-gm2/std/Storage.mod: gcc/gm2/ulm-lib-gm2/std/RTExceptions.mod: Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. gcc/gm2/gm2-libs: Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. ./gm2-libs/cbuiltin.def: ./gm2-libs/MathLib0.def: ./gm2-libs/SYSTEM.def: ./gm2-libs/sckt.def: ./gm2-libs/Indexing.def: ./gm2-libs/Builtins.mod: ./gm2-libs/SFIO.mod: ./gm2-libs/MathLib0.mod: ./gm2-libs/gdbif.mod: ./gm2-libs/M2EXCEPTION.mod: ./gm2-libs/SFIO.def: ./gm2-libs/StringConvert.mod: ./gm2-libs/StringConvert.def: ./gm2-libs/config-host.in: ./gm2-libs/Indexing.mod: ./gm2-libs/errno.def: Copyright (C) 2001-2019 Free Software Foundation, Inc. Contributed by Gaius Mulley . GNU Modula-2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ./gm2-libs/M2EXCEPTION.def: Library module defined by the International Standard Information technology - programming languages BS ISO/IEC 10514-1:1996E Part 1: Modula-2, Base Language. Copyright ISO/IEC (International Organization for Standardization and International Electrotechnical Commission) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 gcc/gm2/gm2-libiberty/: Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. GNU Modula-2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. gcc/gm2/gm2-libs-iso/: This has a mix of licenses, both LGPL-2.1 and GPL-3.0, plus the apparently unmodified definition modules from ISO/IEC. gcc/gm2/gm2-libs-iso/*.def: Library module defined by the International Standard Information technology - programming languages BS ISO/IEC 10514-1:1996E Part 1: Modula-2, Base Language. Copyright ISO/IEC (International Organization for Standardization and International Electrotechnical Commission) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 gcc/gm2/gm2-libs-iso/*.def: Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. gcc/gm2/gm2-libs-iso/*.def: This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. gcc/gm2/gm2-libs-iso/*.mod: Copyright (C) 2012 Free Software Foundation, Inc. GNU Modula-2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. gcc/gm2/gm2-libs-iso/*.mod: Copyright (C) 2009, 2010 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. gcc/gm2/gm2-libs-min/*: Copyright (C) 2001-2019 Free Software Foundation, Inc. mix of GPL-3.0 and LGPL-3.0 gcc/gm2/gm2-libs-pim/*: Copyright (C) 2001-2019 Free Software Foundation, Inc. mix of GPL-3.0 and LGPL-2.1/3 gcc/gm2/gm2-libs-ch/*: Copyright (C) 2001-2019 Free Software Foundation, Inc. mix of GPL-3.0 and LGPL-2.1/3 gcc/gm2/examples: Copyright (C) 2005-2015 Free Software Foundation, Inc. Mix of LGPL-2.1 and GPL-3.0. gcc/gm2/images: GPL-3+ gcc/gm2/el/gm2-mode.el: ;; Everyone is granted permission to copy, modify and redistribute ;; GNU Emacs, but only under the conditions described in the ;; GNU Emacs General Public License. A copy of this license is ;; supposed to have been given to you along with GNU Emacs so you ;; can know your rights and responsibilities. It should be in a ;; file named COPYING. Among other things, the copyright notice ;; and this notice must be preserved on all copies. gcc/gm2/mc-boot/: Copyright (C) 2001-2018 Free Software Foundation, Inc. Contributed by Gaius Mulley . Mix of GPL-3 and LGPL-2.1. gcc/testsuite/gm2/: Copyright (C) 2001-2019 Free Software Foundation, Inc. Mix of GPL-2+ and GPL-3+ libgm2: libgm2/libiso/: Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. libgm2/libpim/: Copyright (C) 2005-2014 Free Software Foundation, Inc. Mix of LGPL-2.1, LGPL-3 and GPL-3. libgm2/liblog/: Copyright (C) 2005-2018 Free Software Foundation, Inc. Mix of LGPL-2.1 and LGPL-3. libgm2/libpth/: Copyright: (C) 1999-2006 Ralf S. Engelschall License: LGPL-2.1+ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. . This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. libgm2/libulm/: Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. GNU Modula-2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. libgm2/libcor/: Copyright (C) 2005-2019 Free Software Foundation, Inc. Contributed by Gaius Mulley . GNU Modula-2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. libgm2/libmin/: Copyright (C) 2010, 2011, 2012, 2013 Free Software Foundation, Inc. GNU Modula-2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. libgm2/p2c/: Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. GNU Modula-2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. newlib-X.Y.Z/: Upstream Authors: newlib@sources.redhat.com Jeff Johnston Tom Fitzsimmons The newlib subdirectory is a collection of software from several sources. Each file may have its own copyright/license that is embedded in the source file. This list documents those licenses which are more restrictive than a BSD-like license or require the copyright notice to be duplicated in documentation and/or other materials associated with the distribution. Certain licenses documented here only apply to specific targets. Certain clauses only apply if you are building the code as part of your binary. Note that this list may omit certain licenses that only pertain to the copying/modifying of the individual source code. If you are distributing the source code, then you do not need to worry about these omitted licenses, so long as you do not modify the copyright information already in place. Parts of this work are licensed under the terms of the GNU General Public License. On Debian systems, the complete text of this license can be found in /usr/share/common-licenses/GPL. Parts of this work are licensed under the terms of the GNU Library General Public License. On Debian systems, the complete text of this license be found in /usr/share/common-licenses/LGPL. (1) University of California, Berkeley [1a] Copyright (c) 1990 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms are permitted provided that the above copyright notice and this paragraph are duplicated in all such forms and that any documentation, and other materials related to such distribution and use acknowledge that the software was developed by the University of California, Berkeley. The name of the University may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. [1b] Copyright (c) 1990 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms are permitted provided that the above copyright notice and this paragraph are duplicated in all such forms and that any documentation, advertising materials, and other materials related to such distribution and use acknowledge that the software was developed by the University of California, Berkeley. The name of the University may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. [1c] Copyright (c) 1981, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the University of California, Berkeley and its contributors. 4. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [1d] Copyright (c) 1988, 1990, 1993 Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [1e] Copyright (c) 1982, 1986, 1989, 1991, 1993, 1994 The Regents of the University of California. All rights reserved. (c) UNIX System Laboratories, Inc. All or some portions of this file are derived from material licensed to the University of California by American Telephone and Telegraph Co. or Unix System Laboratories, Inc. and are reproduced herein with the permission of UNIX System Laboratories, Inc. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the University of California, Berkeley and its contributors. 4. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [1f] Copyright (c) 1987, 1988, 2000 Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms are permitted provided that: (1) source distributions retain this entire copyright notice and comment, and (2) distributions including binaries display the following acknowledgement: ``This product includes software developed by the University of California, Berkeley and its contributors'' in the documentation or other materials provided with the distribution and in all advertising materials mentioning features or use of this software. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ------------------------------------------------------------- Please note that in some of the above alternate licenses, there is a statement regarding that acknowledgement must be made in any advertising materials for products using the code. This restriction no longer applies due to the following license change: ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change In some cases the defunct clause has been removed in modified newlib code and in some cases, the clause has been left as-is. ------------------------------------------------------------- (2) Cygwin (cygwin targets only) Copyright 2001 Red Hat, Inc. This software is a copyrighted work licensed under the terms of the Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. (3) David M. Gay at AT&T The author of this software is David M. Gay. Copyright (c) 1991 by AT&T. Permission to use, copy, modify, and distribute this software for any purpose without fee is hereby granted, provided that this entire notice is included in all copies of any software which is or includes a copy or modification of this software and in all copies of the supporting documentation for such software. THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. (4) Advanced Micro Devices Copyright 1989, 1990 Advanced Micro Devices, Inc. This software is the property of Advanced Micro Devices, Inc (AMD) which specifically grants the user the right to modify, use and distribute this software provided this notice is not removed or altered. All other rights are reserved by AMD. AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE. IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR USE OF THIS SOFTWARE. So that all may benefit from your experience, please report any problems or suggestions about this software to the 29K Technical Support Center at 800-29-29-AMD (800-292-9263) in the USA, or 0800-89-1131 in the UK, or 0031-11-1129 in Japan, toll free. The direct dial number is 512-462-4118. Advanced Micro Devices, Inc. 29K Support Products Mail Stop 573 5900 E. Ben White Blvd. Austin, TX 78741 800-292-9263 (5) C.W. Sandmann Copyright (C) 1993 C.W. Sandmann This file may be freely distributed as long as the author's name remains. (6) Eric Backus (C) Copyright 1992 Eric Backus This software may be used freely so long as this copyright notice is left intact. There is no warrantee on this software. (7) Sun Microsystems Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. Developed at SunPro, a Sun Microsystems, Inc. business. Permission to use, copy, modify, and distribute this software is freely granted, provided that this notice is preserved. (8) Hewlett Packard (c) Copyright 1986 HEWLETT-PACKARD COMPANY To anyone who acknowledges that this file is provided "AS IS" without any express or implied warranty: permission to use, copy, modify, and distribute this file for any purpose is hereby granted without fee, provided that the above copyright notice and this notice appears in all copies, and that the name of Hewlett-Packard Company not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Hewlett-Packard Company makes no representations about the suitability of this software for any purpose. (9) Hans-Peter Nilsson Copyright (C) 2001 Hans-Peter Nilsson Permission to use, copy, modify, and distribute this software is freely granted, provided that the above copyright notice, this notice and the following disclaimer are preserved with no changes. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. (10) Stephane Carrez (m68hc11-elf/m68hc12-elf targets only) Copyright (C) 1999, 2000, 2001, 2002 Stephane Carrez (stcarrez@nerim.fr) The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided that existing copyright notices are retained in all copies and that this notice is included verbatim in any distributions. No written agreement, license, or royalty fee is required for any of the authorized uses. Modifications to this software may be copyrighted by their authors and need not follow the licensing terms described here, provided that the new terms are clearly indicated on the first page of each file where they apply. (11) Christopher G. Demetriou Copyright (c) 2001 Christopher G. Demetriou All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (12) SuperH, Inc. Copyright 2002 SuperH, Inc. All rights reserved This software is the property of SuperH, Inc (SuperH) which specifically grants the user the right to modify, use and distribute this software provided this notice is not removed or altered. All other rights are reserved by SuperH. SUPERH MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE. IN NO EVENT SHALL SUPERH BE LIABLE FOR INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR USE OF THIS SOFTWARE. So that all may benefit from your experience, please report any problems or suggestions about this software to the SuperH Support Center via e-mail at softwaresupport@superh.com . SuperH, Inc. 405 River Oaks Parkway San Jose CA 95134 USA (13) Royal Institute of Technology Copyright (c) 1999 Kungliga Tekniska Hgskolan (Royal Institute of Technology, Stockholm, Sweden). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of KTH nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (14) Alexey Zelkin Copyright (c) 2000, 2001 Alexey Zelkin All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (15) Andrey A. Chernov Copyright (C) 1997 by Andrey A. Chernov, Moscow, Russia. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (16) FreeBSD Copyright (c) 1997-2002 FreeBSD Project. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (17) S. L. Moshier Author: S. L. Moshier. Copyright (c) 1984,2000 S.L. Moshier Permission to use, copy, modify, and distribute this software for any purpose without fee is hereby granted, provided that this entire notice is included in all copies of any software which is or includes a copy or modification of this software and in all copies of the supporting documentation for such software. THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. (18) Citrus Project Copyright (c)1999 Citrus Project, All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (19) Todd C. Miller Copyright (c) 1998 Todd C. Miller All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (20) DJ Delorie (i386) Copyright (C) 1991 DJ Delorie All rights reserved. Redistribution and use in source and binary forms is permitted provided that the above copyright notice and following paragraph are duplicated in all such forms. This file is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. (21) Free Software Foundation LGPL License (*-linux* targets only) Copyright (C) 1990-1999, 2000, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Mark Kettenis , 1997. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA (22) Xavier Leroy LGPL License (i[3456]86-*-linux* targets only) Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. (23) Intel (i960) Copyright (c) 1993 Intel Corporation Intel hereby grants you permission to copy, modify, and distribute this software and its documentation. Intel grants this permission provided that the above copyright notice appears in all copies and that both the copyright notice and this permission notice appear in supporting documentation. In addition, Intel grants this permission provided that you prominently mark as "not part of the original" any modifications made to this software or documentation, and that the name of Intel Corporation not be used in advertising or publicity pertaining to distribution of the software or the documentation without specific, written prior permission. Intel Corporation provides this AS IS, WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Intel makes no guarantee or representations regarding the use of, or the results of the use of, the software and documentation in terms of correctness, accuracy, reliability, currentness, or otherwise; and you rely on the software, documentation and results solely at your own risk. IN NO EVENT SHALL INTEL BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS, LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES OF ANY KIND. IN NO EVENT SHALL INTEL'S TOTAL LIABILITY EXCEED THE SUM PAID TO INTEL FOR THE PRODUCT LICENSED HEREUNDER. (24) Hewlett-Packard (hppa targets only) (c) Copyright 1986 HEWLETT-PACKARD COMPANY To anyone who acknowledges that this file is provided "AS IS" without any express or implied warranty: permission to use, copy, modify, and distribute this file for any purpose is hereby granted without fee, provided that the above copyright notice and this notice appears in all copies, and that the name of Hewlett-Packard Company not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Hewlett-Packard Company makes no representations about the suitability of this software for any purpose. (25) Henry Spencer (only *-linux targets) Copyright 1992, 1993, 1994 Henry Spencer. All rights reserved. This software is not subject to any license of the American Telephone and Telegraph Company or of the Regents of the University of California. Permission is granted to anyone to use this software for any purpose on any computer system, and to alter it and redistribute it, subject to the following restrictions: 1. The author is not responsible for the consequences of use of this software, no matter how awful, even if they arise from flaws in it. 2. The origin of this software must not be misrepresented, either by explicit claim or by omission. Since few users ever read sources, credits must appear in the documentation. 3. Altered versions must be plainly marked as such, and must not be misrepresented as being the original software. Since few users ever read sources, credits must appear in the documentation. 4. This notice may not be removed or altered. (26) Mike Barcroft Copyright (c) 2001 Mike Barcroft All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (27) Konstantin Chuguev (--enable-newlib-iconv) Copyright (c) 1999, 2000 Konstantin Chuguev. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. iconv (Charset Conversion Library) v2.0 (27) Artem Bityuckiy (--enable-newlib-iconv) Copyright (c) 2003, Artem B. Bityuckiy, SoftMine Corporation. Rights transferred to Franklin Electronic Publishers. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. (28) Red Hat Incorporated Unless otherwise stated in each remaining newlib file, the remaining files in the newlib subdirectory default to the following copyright. It should be noted that Red Hat Incorporated now owns copyrights belonging to Cygnus Solutions and Cygnus Support. Copyright (c) 1994, 1997, 2001, 2002, 2003, 2004 Red Hat Incorporated. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. The name of Red Hat Incorporated may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- 6. libLLVMGenXIntrinsics MIT License Copyright (c) 2020 Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- 7. libLLVMSPIRVLib ============================================================================== LLVM Release License ============================================================================== University of Illinois/NCSA Open Source License Copyright (c) 2003-2014 University of Illinois at Urbana-Champaign. All rights reserved. Developed by: LLVM Team University of Illinois at Urbana-Champaign http://llvm.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. * Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. ============================================================================== Copyrights and Licenses for Third Party Software Distributed with LLVM: ============================================================================== The LLVM software contains code written by third parties. Such software will have its own individual LICENSE.TXT file in the directory in which it appears. This file will describe the copyrights, license, and restrictions which apply to that code. The disclaimer of warranty in the University of Illinois Open Source License applies to all code in the LLVM Distribution, and nothing in any of the other licenses gives permission to use the names of the LLVM Team or the University of Illinois to endorse or promote products derived from this Software. The following pieces of software have additional or alternate copyrights, licenses, and/or restrictions: Program Directory ------- --------- Autoconf llvm/autoconf llvm/projects/ModuleMaker/autoconf Google Test llvm/utils/unittest/googletest OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT} ARM contributions llvm/lib/Target/ARM/LICENSE.TXT md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h -------------------------------------------------------------------------------- Other names and brands may be claimed as the property of others. RenderKit-ospray-f2a61c2/third-party-programs-OIDN.txt000066400000000000000000001025331456566705700227420ustar00rootroot00000000000000Intel(R) Open Image Denoise Third Party Programs File This file contains the list of third party software ("third party programs") contained in the Intel software and their required notices and/or license terms. This third party software, even if included with the distribution of the Intel software, may be governed by separate license terms, including without limitation, third party license terms, other Intel software license terms, and open source software license terms. These separate license terms govern your use of the third party programs as set forth in the "third-party-programs.txt" or other similarly named text file. Third party programs and their corresponding required notices and/or license terms are listed below. -------------------------------------------------------------------------------- 1. Intel(R) oneAPI Deep Neural Network Library (oneDNN) Copyright 2016-2023 Intel Corporation Intel(R) oneAPI Threading Building Blocks (oneTBB) Copyright 2005-2023 Intel Corporation Intel® Embree (snippets) Copyright Intel Corporation Intel® OSPRay (snippets) Copyright Intel Corporation Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -------------------------------------------------------------------------------- 2. PyTorch From PyTorch: Copyright (c) 2016- Facebook, Inc (Adam Paszke) Copyright (c) 2014- Facebook, Inc (Soumith Chintala) Copyright (c) 2011-2014 Idiap Research Institute (Ronan Collobert) Copyright (c) 2012-2014 Deepmind Technologies (Koray Kavukcuoglu) Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu) Copyright (c) 2011-2013 NYU (Clement Farabet) Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou, Iain Melvin, Jason Weston) Copyright (c) 2006 Idiap Research Institute (Samy Bengio) Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert, Samy Bengio, Johnny Mariethoz) From Caffe2: Copyright (c) 2016-present, Facebook Inc. All rights reserved. All contributions by Facebook: Copyright (c) 2016 Facebook Inc. All contributions by Google: Copyright (c) 2015 Google Inc. All rights reserved. All contributions by Yangqing Jia: Copyright (c) 2015 Yangqing Jia All rights reserved. All contributions from Caffe: Copyright(c) 2013, 2014, 2015, the respective contributors All rights reserved. All other contributions: Copyright(c) 2015, 2016 the respective contributors All rights reserved. Caffe2 uses a copyright model similar to Caffe: each contributor holds copyright over their contributions to Caffe2. The project versioning records all such contribution and copyright details. If a contributor wants to further mark their specific copyright on a particular contribution, they should indicate their copyright solely in the commit message of the change when it is committed. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the names of Facebook, Deepmind Technologies, NYU, NEC Laboratories America and IDIAP Research Institute nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- 3. pytorch-msssim Copyright (c) 2019 Gongfan Fang ROCmSoftwarePlatform/composable_kernel Copyright (c) 2018- , Advanced Micro Devices, Inc. (Chao Liu, Jing Zhang) Copyright (c) 2019- , Advanced Micro Devices, Inc. (Letao Qin, Qianfeng Zhang, Liang Huang, Shaojie Wang) Copyright (c) 2022- , Advanced Micro Devices, Inc. (Anthony Chang, Chunyu Lai, Illia Silin, Adam Osewski, Poyen Chen, Jehandad Khan) Copyright (c) 2019-2021, Advanced Micro Devices, Inc. (Hanwen Chang) Copyright (c) 2019-2020, Advanced Micro Devices, Inc. (Tejash Shah) Copyright (c) 2020 , Advanced Micro Devices, Inc. (Xiaoyan Zhou) Copyright (c) 2021-2022, Advanced Micro Devices, Inc. (Jianfeng Yan) Copyright (c) 2018-2022, Advanced Micro Devices, Inc. All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- 4. Catch2 Copyright (c) 2021 Two Blue Cubes Ltd. All rights reserved. Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- 5. CUTLASS Copyright (c) 2017 - 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. SPDX-License-Identifier: BSD-3-Clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- 6. oneAPI Data Parallel C++ Compiler Copyright Intel Corporation ============================================================================== The LLVM Project is under the Apache License v2.0 with LLVM Exceptions: ============================================================================== Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ---- LLVM Exceptions to the Apache 2.0 License ---- As an exception, if, as a result of your compiling your source code, portions of this Software are embedded into an Object form of such source code, you may redistribute such embedded portions in such Object form without complying with the conditions of Sections 4(a), 4(b) and 4(d) of the License. In addition, if you combine or link compiled forms of this Software with software that is licensed under the GPLv2 ("Combined Software") and if a court of competent jurisdiction determines that the patent provision (Section 3), the indemnity provision (Section 9) or other Section of the License conflicts with the conditions of the GPLv2, you may retroactively and prospectively choose to deem waived or otherwise exclude such Section(s) of the License, but only in their entirety and only with respect to the Combined Software. -------------------------------------------------------------------------------- The following third party programs have their own third party programs. These additional third party program files are as follows: 1. Intel(R) oneAPI Deep Neural Network Library (oneDNN) ./third-party-programs-oneDNN.txt 2. Intel(R) oneAPI Threading Building Blocks (oneTBB) ./third-party-programs-oneTBB.txt 3. oneAPI DPC++ Compiler ./third-party-programs-DPCPP.txt --------------------------------------------------------------------------------RenderKit-ospray-f2a61c2/third-party-programs-OpenVKL.txt000066400000000000000000001062411456566705700234670ustar00rootroot00000000000000Intel(R) Open Volume Kernel Library Third Party Programs File This file contains the list of third party software ("third party programs") contained in the Intel software and their required notices and/or license terms. This third party software, even if included with the distribution of the Intel software, may be governed by separate license terms, including without limitation, third party license terms, other Intel software license terms, and open source software license terms. These separate license terms govern your use of the third party programs as set forth in the "third-party-programs.txt" or other similarly- named text file. Third party programs and their corresponding required notices and/or license terms are listed below. -------------------------------------------------------------------------------- 1. Boost C++ Libraries Copyright Beman Dawes, David Abrahams, 1998-2005. Copyright Rene Rivera 2004-2005. Catch2 Copyright 2010 Two Blue Cubes Ltd Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- 2. IlmBase (part of OpenEXR) Copyright (c) 2006-2019 OpenEXR a Series of LF Projects, LLC. All rights reserved. BSD 3-Clause "New" or "Revised" License Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- 3. Dear ImGui Copyright (c) 2014-2020 Omar Cornut half Copyright (c) 2012-2021 Christian Rau SSE2NEON The MIT License (MIT) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- 4. Embree Copyright 2009 Intel Corporation Google Benchmark Copyright 2014 Google Inc. All rights reserved. OSPRay Copyright 2009 Intel Corporation Threading Building Blocks (oneTBB) Copyright 2005 Intel Corporation Apache License Version 2.0 January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -------------------------------------------------------------------------------- 5. GLFW Copyright (c) 2002-2006 Marcus Geelnard Copyright (c) 2006-2019 Camilla Löwy zlib Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler zlib License This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------------- 6. OpenVDB Copyright Contributors to the OpenVDB Project Mozilla Public License Version 2.0 1. Definitions 1.1. "Contributor" means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. 1.2. "Contributor Version" means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor's Contribution. 1.3. "Contribution" means Covered Software of a particular Contributor. 1.4. "Covered Software" means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. 1.5. "Incompatible With Secondary Licenses" means (a) that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or (b) that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License. 1.6. "Executable Form" means any form of the work other than Source Code Form. 1.7. "Larger Work" means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. 1.8. "License" means this document. 1.9. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License. 1.10. "Modifications" means any of the following: (a) any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or (b) any new file in Source Code Form that contains any Covered Software. 1.11. "Patent Claims" of a Contributor means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version. 1.12. "Secondary License" means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. 1.13. "Source Code Form" means the form of the work preferred for making modifications. 1.14. "You" (or "Your") means an individual or a legal entity exercising rights under this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. License Grants and Conditions 2.1. Grants Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: (a) under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and (b) under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version. 2.2. Effective Date The licenses granted in Section 2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution. 2.3. Limitations on Grant Scope The licenses granted in this Section 2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: (a) for any code that a Contributor has removed from Covered Software; or (b) for infringements caused by: (i) Your and any other third party's modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or (c) under Patent Claims infringed by Covered Software in the absence of its Contributions. This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section 3.4). 2.4. Subsequent Licenses No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary License (if permitted under the terms of Section 3.3). 2.5. Representation Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. 2.6. Fair Use This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents. 2.7. Conditions Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. 3. Responsibilities 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients' rights in the Source Code Form. 3.2. Distribution of Executable Form If You distribute Covered Software in Executable Form then: (a) such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and (b) You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients' rights in the Source Code Form under this License. 3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s). 3.4. Notices You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies. 3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction. 4. Inability to Comply Due to Statute or Regulation If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5. Termination 5.1. The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice. 5.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination. 6. Disclaimer of Warranty Covered Software is provided under this License on an "as is" basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the Covered Software is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire risk as to the quality and performance of the Covered Software is with You. Should any Covered Software prove defective in any respect, You (not any Contributor) assume the cost of any necessary servicing, repair, or correction. This disclaimer of warranty constitutes an essential part of this License. No use of any Covered Software is authorized under this License except under this disclaimer. 7. Limitation of Liability Under no circumstances and under no legal theory, whether tort (including negligence), contract, or otherwise, shall any Contributor, or anyone who distributes Covered Software as permitted above, be liable to You for any direct, indirect, special, incidental, or consequential damages of any character including, without limitation, damages for lost profits, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses, even if such party shall have been informed of the possibility of such damages. This limitation of liability shall not apply to liability for death or personal injury resulting from such party's negligence to the extent applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so this exclusion and limitation may not apply to You. 8. Litigation Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party's ability to bring cross-claims or counter-claims. 9. Miscellaneous This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor. 10. Versions of the License 10.1. New Versions Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number. 10.2. Effect of New Versions You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward. 10.3. Modified Versions If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License). 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached. Exhibit A - Source Code Form License Notice This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. You may add additional accurate notices of copyright ownership. Exhibit B - "Incompatible With Secondary Licenses" Notice This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. -------------------------------------------------------------------------------- 7. C-Blosc Copyright (C) 2009-2018 Francesc Alted Copyright (C) 2019-present Blosc Development team BSD-3-Clause (modified) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name Francesc Alted nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- The following third party programs have their own third party programs. These additional third party program files are as follows: 1. Embree: ./third-party-programs-Embree.txt 2. OSPRay: ./third-party-programs.txt 3. Threading Building Blocks (TBB): ./third-party-programs-oneTBB.txt -------------------------------------------------------------------------------- Other names and brands may be claimed as the property of others. RenderKit-ospray-f2a61c2/third-party-programs-oneAPI-DPCPP.txt000066400000000000000000002120101456566705700241600ustar00rootroot00000000000000Intel(R) 2023.0 oneAPI DPC++/C++/Fortran Compiler Third Party Programs File This file is the "third-party-programs.txt" file specified in the associated Intel end user license agreement for the Intel software you are licensing. Third party programs and their corresponding required notices and/or license terms are listed below. ----------------------------------------------------------------- 1. Khronos Group - OpenCL header Copyright (c) 2008-2020 The Khronos Group Inc. Khronos OpenCL ICD Loader Copyright (c) 2020 The Khronos Group Inc. Threading Building Blocks Copyright 2020 Intel Corporation Mentor Graphics Algorithmic C Types Copyright 2008-2016, Mentor Graphics Corporation Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: You must give any other recipients of the Work or Derivative Works a copy of this License; and You must cause any modified files to carry prominent notices stating that You changed the files; and You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS ----------------------------------------------------------------- 2. Khronos Group - SPIRV-LLVM-Translator ============================================================================== LLVM Release License ============================================================================== University of Illinois/NCSA Open Source License Copyright (c) 2003-2014 University of Illinois at Urbana-Champaign. All rights reserved. Developed by: LLVM Team University of Illinois at Urbana-Champaign http://llvm.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. * Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. ============================================================================== Copyrights and Licenses for Third Party Software Distributed with LLVM: ============================================================================== The LLVM software contains code written by third parties. Such software will have its own individual LICENSE.TXT file in the directory in which it appears. This file will describe the copyrights, license, and restrictions which apply to that code. The disclaimer of warranty in the University of Illinois Open Source License applies to all code in the LLVM Distribution, and nothing in any of the other licenses gives permission to use the names of the LLVM Team or the University of Illinois to endorse or promote products derived from this Software. The following pieces of software have additional or alternate copyrights, licenses, and/or restrictions: Program Directory ------- --------- Autoconf llvm/autoconf llvm/projects/ModuleMaker/autoconf Google Test llvm/utils/unittest/googletest OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT} ARM contributions llvm/lib/Target/ARM/LICENSE.TXT md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h ----------------------------------------------------------------- 3. llvm-project llvm-project ============================================================================== The LLVM Project is under the Apache License v2.0 with LLVM Exceptions: ============================================================================== Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ---- LLVM Exceptions to the Apache 2.0 License ---- As an exception, if, as a result of your compiling your source code, portions of this Software are embedded into an Object form of such source code, you may redistribute such embedded portions in such Object form without complying with the conditions of Sections 4(a), 4(b) and 4(d) of the License. In addition, if you combine or link compiled forms of this Software with software that is licensed under the GPLv2 ("Combined Software") and if a court of competent jurisdiction determines that the patent provision (Section 3), the indemnity provision (Section 9) or other Section of the License conflicts with the conditions of the GPLv2, you may retroactively and prospectively choose to deem waived or otherwise exclude such Section(s) of the License, but only in their entirety and only with respect to the Combined Software. ============================================================================== Software from third parties included in the LLVM Project: ============================================================================== The LLVM Project contains third party software which is under different license terms. All such code will be identified clearly using at least one of two mechanisms: 1) It will be in a separate directory tree with its own `LICENSE.txt` or `LICENSE` file at the top containing the specific license and restrictions which apply to that software, or 2) It will contain specific license and restriction terms at the top of every file. ============================================================================== Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy): ============================================================================== University of Illinois/NCSA Open Source License Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign. All rights reserved. Developed by: LLVM Team University of Illinois at Urbana-Champaign http://llvm.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. * Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. ----------------------------------------------------------------- 4. fpp - Fortran PreProcessor Copyright (C) 2002-2020 Intel Corporation. All rights reserved. Portions Copyright (C) 1995 by Sun Microsystems, Inc. All rights reserved. Developed at SunSoft, a Sun Microsystems, Inc. business. Permission to use, copy, modify, and distribute this software is freely granted, provided that this notice is preserved. ----------------------------------------------------------------- 5. Intel compute-runtime Copyright 2019 Intel Corporation. Intel vc-intrinsics Copyright 2021 Intel Corporation. libffi Copyright (c) 1996-2021 Anthony Green, Red Hat, Inc and others. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------- 6. protobuf Copyright 2008 Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Code generated by the Protocol Buffer compiler is owned by the owner of the input file used when generating it. This code is not standalone and requires a support library to be linked with it. This support library is itself covered by the above license. ----------------------------------------------------------------- 7. MP11 Copyright 2021 Intel Corporation. Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------- 8. Unicode Data Files UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE See Terms of Use for definitions of Unicode Inc.’s Data Files and Software. NOTICE TO USER: Carefully read the following legal agreement. BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE. COPYRIGHT AND PERMISSION NOTICE Copyright © 1991-2022 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in https://www.unicode.org/copyright.html. Permission is hereby granted, free of charge, to any person obtaining a copy of the Unicode data files and any associated documentation (the "Data Files") or Unicode software and any associated documentation (the "Software") to deal in the Data Files or Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Data Files or Software, and to permit persons to whom the Data Files or Software are furnished to do so, provided that either (a) this copyright and permission notice appear with all copies of the Data Files or Software, or (b) this copyright and permission notice appear in associated Documentation. THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA FILES OR SOFTWARE. Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in these Data Files or Software without prior written authorization of the copyright holder. ----------------------------------------------------------------- The following third party programs have their own third party program files. These additional third party program files can be found as follows: 1. Threading Building Blocks: /tbb/licensing/third-party-programs.txt ----------------------------------------------------------------- Intel(R) 2021.8 C/C++/Fortran Compiler Classic Third Party Programs File This file is the "third-party-programs.txt" file specified in the associated Intel end user license agreement for the Intel software you are licensing. Third party programs and their corresponding required notices and/or license terms are listed below. ----------------------------------------------------------------- 1. libdwarf Copyright 2020 Intel Corporatio LIBDWARF Copyright To enable use of the DWARF2 libdwarf interface, the following copyright and notice must be included in this document. Note this notice is for libdwarf only. All other source and documentation are copyright by Intel Corp. LIBDWARF permission notice: Copyright (c) 1994 Silicon Graphics, Inc. Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that (i) the above copyright notice and this permission notice appear in all copies of the software and related documentation, and (ii) the name "Silicon Graphics" or any other trademark of Silicon Graphics, Inc. may not be used in any advertising or publicity relating to the software without the specific, prior written permission of Silicon Graphics, Inc. THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ----------------------------------------------------------------- 2. Alladin Enterprises MD5 Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. L. Peter Deutsch ghost@aladdin.com ----------------------------------------------------------------- 3. ATL Server Library and Tools Microsoft Limited Permissive License (Ms-LPL) Published: October 18, 2005 This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. 1. Definitions o The terms "reproduce," "reproduction" and "distribution" have the same meaning here as under U.S. copyright law. o "You" means the licensee of the software. o "Licensed patents" means any Microsoft patent claims which read directly on the software as distributed by Microsoft under this license. 2. Grant of Rights a. Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, Microsoft grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce the software, prepare derivative works of the software and distribute the software or any derivative works that you create. b. Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, Microsoft grants you a non-exclusive, worldwide, royalty-free patent license under licensed patents to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the software or derivative works of the software. 3. Conditions and Limitations . No Trademark License- This license does not grant you any rights to use Microsoft's name, logo, or trademarks. a. If you begin patent litigation against Microsoft over patents that you think may apply to the software (including a cross-claim or counterclaim in a lawsuit), your license to the software ends automatically. b. If you distribute copies of the software or derivative works, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. c. If you distribute the software or derivative works in source code form you may do so only under this license (i.e., you must include a complete copy of this license with your distribution), and if you distribute the software or derivative works in compiled or object code form you may only do so under a license that complies with this license. d. The software is licensed "as-is." You bear the risk of using it. Microsoft gives no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, Microsoft excludes the implied warranties of merchantability, fitness for a particular purpose and non-infringement. e. Platform Limitation- The licenses granted in sections 2(A) & 2(B) extend only to the software or derivative works that you create that run on a Microsoft Windows operating system product. ----------------------------------------------------------------- 5. llvm-project llvm-project Copyright 2020 Intel Corporation Intel Open Source Compiler Header Files Copyright 2020 Intel Corporation Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, “control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems,and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of,publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and condition for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --- LLVM Exceptions to the Apache 2.0 License ---- As an exception, if, as a result of your compiling your source code, portions of this Software are embedded into an Object form of such source code, you may redistribute such embedded portions in such Object form without complying with the conditions of Sections 4(a), 4(b) and 4(d) of the License. In addition, if you combine or link compiled forms of this Software with software that is licensed under the GPLv2 ("Combined Software") and if a court of competent jurisdiction determines that the patent provision (Section 3), the indemnity provision (Section 9) or other Section of the License conflicts with the conditions of the GPLv2, you may retroactively and prospectively choose to deem waived or otherwise exclude such Section(s) of the License, but only in their entirety and only with respect to the Combined Software. ----------------------------------------------------------------- 6. Intel® Threading Building Blocks (Intel® TBB) Copyright Intel Corporation Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ----------------------------------------------------------------- 7. Visual Studio Autogenerated Code Copyright Microsoft Corporation Terms for Microsoft “Distributable Code” provided as part of Microsoft’s Visual Studio Enterprise and Professional software. 1. License. This software package from Intel (the “Software Package”) contains code from Microsoft (the “Distributable Code”). You are provided a non-transferable, non-exclusive, non-sublicensable, limited right and license only to use the Distributable Code as part of this Software Package. You are not allowed to copy, modify, remove the Distributable Code from the Software Package or redistribute the Distributable Code. 2. Restrictions. The Distributable Code is licensed, not sold. You are only provided the above rights to use the Distributable Code. Intel and Microsoft reserve all other rights. Unless applicable law gives you more rights, you may use the Distributable Code only as expressly permitted in these terms. In using the Distributable Code, you must comply with any technical limitations in the Distributable Code that only allow you to use it in certain ways. You may not: • work around any technical limitations in the Distributable Code; • reverse engineer, decompile or disassemble the software, or otherwise attempt to derive the source code for the Distributable Code, except and to the extent required by third party licensing terms governing use of certain open source components that may be included in the Distributable Code; • remove, minimize, block or modify any notices of Intel, Microsoft or its suppliers in the Distributable Code; • use the Distributable Code in any way that is against the law; or • share, publish, rent or lease the software, or provide the Distributable Code as a stand-alone offering for others to use. 3. NO WARRANTY. THE DISTRIBUTABLE CODE IS PROVIDED “AS IS” WITHOUT ANY EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, OR FITNESS FOR A PARTICULAR PURPOSE. 4. LIMITATION ON AND EXCLUSION OF DAMAGES. YOU CAN RECOVER FROM INTEL, MICROSOFT OR THEIR SUPPLIERS ONLY DIRECT DAMAGES UP TO $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES. This limitation applies to (a) anything related to the Distributable Code; and (b) claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law. It also applies even if Intel or Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state or country may not allow the exclusion or limitation of incidental, consequential or other damages. 5. Export Restrictions. You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit www.microsoft.com/exporting. ----------------------------------------------------------------- 8. fpp - Fortran PreProcessor Copyright (C) 2002-2018 Intel Corporation. All rights reserved. Portions Copyright (C) 1995 by Sun Microsystems, Inc. All rights reserved. Developed at SunSoft, a Sun Microsystems, Inc. business. Permission to use, copy, modify, and distribute this software is freely granted, provided that this notice is preserved. ----------------------------------------------------------------- 9. Intel Decimal Floating-Point Math Library Copyright (c) 2018, Intel Corp. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, his list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ----------------------------------------------------------------- The following third party programs have their own third party program files. These additional third party program files are as follows: Third-party-program.txt file for Intel(R) TBB is located here: /tbb/licensing/third-party-programs.txt ------------------------------------------------------------- Other names and brands may be claimed as the property of others. RenderKit-ospray-f2a61c2/third-party-programs-oneDNN.txt000066400000000000000000000722011456566705700233300ustar00rootroot00000000000000oneAPI Deep Neural Network Library (oneDNN) Third Party Programs File This file contains the list of third party software ("third party programs") contained in the Intel software and their required notices and/or license terms. This third party software, even if included with the distribution of the Intel software, may be governed by separate license terms, including without limitation, third party license terms, other Intel software license terms, and open source software license terms. These separate license terms govern your use of the third party programs as set forth in in the "THIRD-PARTY-PROGRAMS" file. Third party programs and their corresponding required notices and/or license terms are listed below. -------------------------------------------------------------------------------- 1. XByak (src/cpu/xbyak/) Copyright (c) 2007 MITSUNARI Shigeo All rights reserved. 3-Clause BSD License Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the copyright owner nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ソースコード形å¼ã‹ãƒã‚¤ãƒŠãƒªå½¢å¼ã‹ã€å¤‰æ›´ã™ã‚‹ã‹ã—ãªã„ã‹ã‚’å•ã‚ãšã€ä»¥ä¸‹ã®æ¡ä»¶ã‚’満㟠ã™å ´åˆã«é™ã‚Šã€å†é ’布ãŠã‚ˆã³ä½¿ç”¨ãŒè¨±å¯ã•れã¾ã™ã€‚ ソースコードをå†é ’布ã™ã‚‹å ´åˆã€ä¸Šè¨˜ã®è‘—ä½œæ¨©è¡¨ç¤ºã€æœ¬æ¡ä»¶ä¸€è¦§ã€ãŠã‚ˆã³ä¸‹è¨˜å…責æ¡é … ã‚’å«ã‚ã‚‹ã“ã¨ã€‚ ãƒã‚¤ãƒŠãƒªå½¢å¼ã§å†é ’布ã™ã‚‹å ´åˆã€é ’布物ã«ä»˜å±žã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆç­‰ã®è³‡æ–™ã«ã€ä¸Šè¨˜ã®è‘—作 æ¨©è¡¨ç¤ºã€æœ¬æ¡ä»¶ä¸€è¦§ã€ãŠã‚ˆã³ä¸‹è¨˜å…責æ¡é …ã‚’å«ã‚ã‚‹ã“ã¨ã€‚ 書é¢ã«ã‚ˆã‚‹ç‰¹åˆ¥ã®è¨±å¯ãªã—ã«ã€æœ¬ã‚½ãƒ•トウェアã‹ã‚‰æ´¾ç”Ÿã—ãŸè£½å“ã®å®£ä¼ã¾ãŸã¯è²©å£²ä¿ƒé€² ã«ã€è‘—作権者ã®åå‰ã¾ãŸã¯ã‚³ãƒ³ãƒˆãƒªãƒ“ューターã®åå‰ã‚’使用ã—ã¦ã¯ãªã‚‰ãªã„。 本ソフトウェアã¯ã€è‘—作権者ãŠã‚ˆã³ã‚³ãƒ³ãƒˆãƒªãƒ“ューターã«ã‚ˆã£ã¦ã€Œç¾çжã®ã¾ã¾ã€æä¾›ã• れã¦ãŠã‚Šã€æ˜Žç¤ºé»™ç¤ºã‚’å•ã‚ãšã€å•†æ¥­çš„ãªä½¿ç”¨å¯èƒ½æ€§ã€ãŠã‚ˆã³ç‰¹å®šã®ç›®çš„ã«å¯¾ã™ã‚‹é©åˆæ€§ ã«é–¢ã™ã‚‹æš—é»™ã®ä¿è¨¼ã‚‚å«ã‚ã€ã¾ãŸãれã«é™å®šã•れãªã„ã€ã„ã‹ãªã‚‹ä¿è¨¼ã‚‚ã‚りã¾ã›ã‚“。 著作権者もコントリビューターもã€äº‹ç”±ã®ã„ã‹ã‚“ã‚’å•ã‚ãšã€ æå®³ç™ºç”Ÿã®åŽŸå› ã„ã‹ã‚“ã‚’ å•ã‚ãšã€ã‹ã¤è²¬ä»»ã®æ ¹æ‹ ãŒå¥‘ç´„ã§ã‚ã‚‹ã‹åŽ³æ ¼è²¬ä»»ã§ã‚ã‚‹ã‹ï¼ˆéŽå¤±ãã®ä»–ã®ï¼‰ä¸æ³•行為㧠ã‚ã‚‹ã‹ã‚’å•ã‚ãšã€ä»®ã«ãã®ã‚ˆã†ãªæå®³ãŒç™ºç”Ÿã™ã‚‹å¯èƒ½æ€§ã‚’知らã•れã¦ã„ãŸã¨ã—ã¦ã‚‚〠本ソフトウェアã®ä½¿ç”¨ã«ã‚ˆã£ã¦ç™ºç”Ÿã—ãŸï¼ˆä»£æ›¿å“ã¾ãŸã¯ä»£ç”¨ã‚µãƒ¼ãƒ“スã®èª¿é”ã€ä½¿ç”¨ã® 喪失ã€ãƒ‡ãƒ¼ã‚¿ã®å–ªå¤±ã€åˆ©ç›Šã®å–ªå¤±ã€æ¥­å‹™ã®ä¸­æ–­ã‚‚å«ã‚ã€ã¾ãŸãれã«é™å®šã•れãªã„)直接 æå®³ã€é–“接æå®³ã€å¶ç™ºçš„ãªæå®³ã€ç‰¹åˆ¥æå®³ã€æ‡²ç½°çš„æå®³ã€ã¾ãŸã¯çµæžœæå®³ã«ã¤ã„ã¦ã€ 一切責任を負ã‚ãªã„ã‚‚ã®ã¨ã—ã¾ã™ã€‚ -------------------------------------------------------------------------------- 2. Googletest (tests/gtests/gtest/) Copyright 2005, Google Inc. Copyright 2006, Google Inc. Copyright 2007, Google Inc. Copyright 2008, Google Inc. Copyright 2015, Google Inc. All rights reserved. 3-Clause BSD License Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- 3. Instrumentation and Tracing Technology API (src/common/ittnotify/) Copyright (c) 2011, Intel Corporation. All rights reserved. Copyright (c) 2005-2014 Intel Corporation. All rights reserved. 3-Clause BSD License Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- 4. CMake (cmake/FindOpenCL.cmake, cmake/FindBLAS.cmake, cmake/FindACL.cmake) CMake - Cross Platform Makefile Generator Copyright 2000-2020 Kitware, Inc. and Contributors All rights reserved. 3-Clause BSD License Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Kitware, Inc. nor the names of Contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ The following individuals and institutions are among the Contributors: * Aaron C. Meadows * Adriaan de Groot * Aleksey Avdeev * Alexander Neundorf * Alexander Smorkalov * Alexey Sokolov * Alex Merry * Alex Turbov * Andreas Pakulat * Andreas Schneider * André Rigland Brodtkorb * Axel Huebl, Helmholtz-Zentrum Dresden - Rossendorf * Benjamin Eikel * Bjoern Ricks * Brad Hards * Christopher Harvey * Christoph Grüninger * Clement Creusot * Daniel Blezek * Daniel Pfeifer * Enrico Scholz * Eran Ifrah * Esben Mose Hansen, Ange Optimization ApS * Geoffrey Viola * Google Inc * Gregor Jasny * Helio Chissini de Castro * Ilya Lavrenov * Insight Software Consortium * Jan Woetzel * Julien Schueller * Kelly Thompson * Konstantin Podsvirov * Laurent Montel * Mario Bensi * Martin Gräßlin * Mathieu Malaterre * Matthaeus G. Chajdas * Matthias Kretz * Matthias Maennich * Michael Hirsch, Ph.D. * Michael Stürmer * Miguel A. Figueroa-Villanueva * Mike Jackson * Mike McQuaid * Nicolas Bock * Nicolas Despres * Nikita Krupen'ko * NVIDIA Corporation * OpenGamma Ltd. * Patrick Stotko * Per Øyvind Karlsen * Peter Collingbourne * Petr Gotthard * Philip Lowman * Philippe Proulx * Raffi Enficiaud, Max Planck Society * Raumfeld * Roger Leigh * Rolf Eike Beer * Roman Donchenko * Roman Kharitonov * Ruslan Baratov * Sebastian Holtermann * Stephen Kelly * Sylvain Joubert * The Qt Company Ltd. * Thomas Sondergaard * Tobias Hunger * Todd Gamblin * Tristan Carel * University of Dundee * Vadim Zhukov * Will Dicharry See version control history for details of individual contributions. The above copyright and license notice applies to distributions of CMake in source and binary form. Third-party software packages supplied with CMake under compatible licenses provide their own copyright notices documented in corresponding subdirectories or source files. ------------------------------------------------------------------------------ CMake was initially developed by Kitware with the following sponsorship: * National Library of Medicine at the National Institutes of Health as part of the Insight Segmentation and Registration Toolkit (ITK). * US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel Visualization Initiative. * National Alliance for Medical Image Computing (NAMIC) is funded by the National Institutes of Health through the NIH Roadmap for Medical Research, Grant U54 EB005149. * Kitware, Inc. -------------------------------------------------------------------------------- 5. Xbyak_aarch64 (src/cpu/aarch64/xbyak_aarch64/) Copyright 2019-2020 FUJITSU LIMITED Apache License, Version 2.0 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS -------------------------------------------------------------------------------- 6. Boost C++ Libraries (src/common/primitive_hashing.hpp) Copyright 2005-2014 Daniel James. Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- 7. Intel(R) Graphics Compute Runtime for oneAPI Level Zero and OpenCL(TM) Driver (src/gpu/jit/ngen/npack/{elf_structs,hash}.hpp) Copyright (c) 2018 Intel Corporation Intel(R) Graphics Compiler (src/gpu/jit/ngen/npack/neo_structs.hpp) Copyright (c) 2019 Intel Corporation oneAPI Level Zero (src/sycl/level_zero) Copyright (C) 2019-2021 Intel Corporation Doxyrest toolkit (doc/doxyrest/*) Copyright (c) 2016, Tibbo Technology Inc Copyright (c) 2016, Vladimir Gladkov Copyright (c) 2016, Doxyrest maintainers MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8. Sphinx (doc/sphinx/conf/py) Copyright (c) 2007-2021 by the Sphinx team (see AUTHORS file). All rights reserved. 2-Clause BSD License Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- 9. Intel(R) Metrics Discovery Application Programming Interface (src/gpu/ocl/mdapi/metrics_discovery_api.h) MIT License Copyright (c) 2019, Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. RenderKit-ospray-f2a61c2/third-party-programs-oneTBB.txt000066400000000000000000001336031456566705700233240ustar00rootroot00000000000000oneAPI Threading Building Blocks (oneTBB) Third Party Programs File This file contains the list of third party software ("third party programs") contained in the Intel software and their required notices and/or license terms. This third party software, even if included with the distribution of the Intel software, may be governed by separate license terms, including without limitation, third party license terms, other Intel software license terms, and open source software license terms. These separate license terms govern your use of the third party programs as set forth in the "third-party-programs.txt" or other similarlynamed text file. The third party programs and their corresponding required notices and/or license terms are listed below. _______________________________________________________________________________________________________ 1. Intel(R) Instrumentation and Tracing Technology (ITT) Copyright (c) 2022 Intel Corporation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _______________________________________________________________________________________________________ 2. ActiveState Thread pool with same API as (multi) processing.Pool (Python recipe): Copyright (c) 2008,2016 david decotigny (this file) Copyright (c) 2006-2008, R Oudkerk (multiprocessing.Pool) Portable Hardware Locality (hwloc) Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana University Research and Technology Corporation. All rights reserved. Copyright (c) 2004-2005 The University of Tennessee and The University of Tennessee Research Foundation. All rights reserved. Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, University of Stuttgart. All rights reserved. Copyright (c) 2004-2005 The Regents of the University of California. All rights reserved. Copyright (c) 2009 CNRS Copyright (c) 2009-2016 Inria. All rights reserved. Copyright (c) 2009-2015 Université Bordeaux Copyright (c) 2009-2015 Cisco Systems, Inc. All rights reserved. Copyright (c) 2009-2012 Oracle and/or its affiliates. All rights reserved. Copyright (c) 2010 IBM Copyright (c) 2010 Jirka Hladky Copyright (c) 2012 Aleksej Saushev, The NetBSD Foundation Copyright (c) 2012 Blue Brain Project, EPFL. All rights reserved. Copyright (c) 2013-2014 University of Wisconsin-La Crosse. All rights reserved. Copyright (c) 2015 Research Organization for Information Science and Technology (RIST). All rights reserved. Copyright (c) 2015-2016 Intel, Inc. All rights reserved. BSD 3-clause "New" or "Revised" License Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _______________________________________________________________________________________________________ 3. gperftools: Copyright (c) 2011, Google Inc. Tachyon: Copyright (c) 1994-2008 John E. Stone. All rights reserved. BSD 3-Clause "New" or "Revised" License Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _______________________________________________________________________________________________________ 4. Mateusz Kwiatkowski Workaround for bug 62258 in libstdc++ GPL 3.0 with GCC Runtime Library Exception 3.1 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (c) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . GCC RUNTIME LIBRARY EXCEPTION Version 3.1, 31 March 2009 Copyright (c) 2009 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This GCC Runtime Library Exception ("Exception") is an additional permission under section 7 of the GNU General Public License, version 3 ("GPLv3"). It applies to a given file (the "Runtime Library") that bears a notice placed by the copyright holder of the file stating that the file is governed by GPLv3 along with this Exception. When you use GCC to compile a program, GCC may combine portions of certain GCC header files and runtime libraries with the compiled program. The purpose of this Exception is to allow compilation of non-GPL (including proprietary) programs to use, in this way, the header files and runtime libraries covered by this Exception. 0. Definitions. A file is an "Independent Module" if it either requires the Runtime Library for execution after a Compilation Process, or makes use of an interface provided by the Runtime Library, but is not otherwise based on the Runtime Library. "GCC" means a version of the GNU Compiler Collection, with or without modifications, governed by version 3 (or a specified later version) of the GNU General Public License (GPL) with the option of using any subsequent versions published by the FSF. "GPL-compatible Software" is software whose conditions of propagation, modification and use would permit combination with GCC in accord with the license of GCC. "Target Code" refers to output from any compiler for a real or virtual target processor architecture, in executable form or suitable for input to an assembler, loader, linker and/or execution phase. Notwithstanding that, Target Code does not include data in any format that is used as a compiler intermediate representation, or used for producing a compiler intermediate representation. The "Compilation Process" transforms code entirely represented in non-intermediate languages designed for human-written code, and/or in Java Virtual Machine byte code, into Target Code. Thus, for example, use of source code generators and preprocessors need not be considered part of the Compilation Process, since the Compilation Process can be understood as starting with the output of the generators or preprocessors. A Compilation Process is "Eligible" if it is done using GCC, alone or with other GPL-compatible software, or if it is done without using any work based on GCC. For example, using non-GPL-compatible Software to optimize any GCC intermediate representations would not qualify as an Eligible Compilation Process. 1. Grant of Additional Permission. You have permission to propagate a work of Target Code formed by combining the Runtime Library with Independent Modules, even if such propagation would otherwise violate the terms of GPLv3, provided that all Target Code was generated by Eligible Compilation Processes. You may then convey such a combination under terms of your choice, consistent with the licensing of the Independent Modules. 2. No Weakening of GCC Copyleft. The availability of this Exception does not imply any general presumption that third-party software is unaffected by the copyleft requirements of the license of GCC. _______________________________________________________________________________________________________ 5. Doctest Copyright (c) 2016-2021 Viktor Kirilov The MIT License (MIT) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. _______________________________________________________________________________________________________ *Other names and brands may be claimed as the property of others. RenderKit-ospray-f2a61c2/third-party-programs.txt000066400000000000000000001640011456566705700222110ustar00rootroot00000000000000Intel(R) OSPRay Third Party Programs File This file contains the list of third party software ("third party programs") contained in the Intel software and their required notices and/or license terms. This third party software, even if included with the distribution of the Intel software, may be governed by separate license terms, including without limitation, third party license terms, other Intel software license terms, and open source software license terms. These separate license terms govern your use of the third party programs as set forth in the "third-party-programs.txt" or other similarly named text file. Third party programs and their corresponding required notices and/or license terms are listed below. -------------------------------------------------------------------------------- 1. Intel(R) Embree Copyright 2009 Intel Corporation Google Benchmark Copyright 2014 Google Inc. All rights reserved. Intel(R) Open Image Denoise Copyright 2009 Intel Corporation Intel(R) Open VKL Copyright 2019 Intel Corporation Intel(R) oneAPI Threading Building Blocks (oneTBB) Copyright 2005 Intel Corporation Intel(R) Implicit SPMD Program Compiler (ISPC) Copyright 2011 Intel Corporation Apache License Version 2.0 January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. -------------------------------------------------------------------------------- 2. Dear ImGui Copyright 2014-2020 Omar Cornut Twinklebear pico-bench Copyright 2015 Will Usher Gruenschloss Halton Copyright 2012 Leonhard Gruenschloss (leonhard@gruenschloss.org) Imneme pcg-cpp Copyright 2014-2017 Melissa O'Neill and PCG Project contributors glm (OpenGL Mathematics) Copyright 2005 - G-Truc Creation SSE2NEON The MIT License (MIT) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- 3. GLFW Copyright 2002-2006 Marcus Geelnard Copyright 2006-2019 Camilla Löwy zlib Copyright 1995-2017 Jean-loup Gailly and Mark Adler enkiTS Copyright (c) 2013 Doug Binks zlib License This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------------- 4. Google Test Copyright 2008, Google Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- 5. Skylight model Copyright 2012-2013, Lukas Hosek and Alexander Wilkie This source is published under the following 3-clause BSD license. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * None of the names of the contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- 6. Visual C++ Redistributables for Visual Studio 1. License. This software package from Intel (the Software Package) contains code from Microsoft (the Distributable Code). You are provided a non-transferable, non-exclusive, non-sublicensable, limited right and license only to use the Distributable Code as part of this Software Package. You are not allowed to copy, modify, remove the Distributable Code from the Software Package or redistribute the Distributable Code. 2. Restrictions. The Distributable Code is licensed, not sold. You are only provided the above rights to use the Distributable Code. Intel and Microsoft reserve all other rights. Unless applicable law gives you more rights, you may use the Distributable Code only as expressly permitted in these terms. In using the Distributable Code, you must comply with any technical limitations in the Distributable Code that only allow you to use it in certain ways. You may not: work around any technical limitations in the Distributable Code; reverse engineer, decompile or disassemble the software, or otherwise attempt to derive the source code for the Distributable Code, except and to the extent required by third party licensing terms governing use of certain open source components that may be included in the Distributable Code; remove, minimize, block or modify any notices of Intel, Microsoft or its suppliers in the Distributable Code; use the Distributable Code in any way that is against the law; or share, publish, rent or lease the software, or provide the Distributable Code as a stand-alone offering for others to use. 3. NO WARRANTY. THE DISTRIBUTABLE CODE IS PROVIDED AS IS WITHOUT ANY EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, OR FITNESS FOR A PARTICULAR PURPOSE. 4. LIMITATION ON AND EXCLUSION OF DAMAGES. YOU CAN RECOVER FROM INTEL, MICROSOFT OR THEIR SUPPLIERS ONLY DIRECT DAMAGES UP TO $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES. This limitation applies to (a) anything related to the Distributable Code; and (b) claims for breach of contract, breach of warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by applicable law. It also applies even if Intel or Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state or country may not allow the exclusion or limitation of incidental, consequential or other damages. 5. Export Restrictions. You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit www.microsoft.com/exporting. -------------------------------------------------------------------------------- 7. Google Snappy Copyright 2011, Google Inc. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. === Some of the benchmark data in testdata/ is licensed differently: - fireworks.jpeg is Copyright 2013 Steinar H. Gunderson, and is licensed under the Creative Commons Attribution 3.0 license (CC-BY-3.0). See https://creativecommons.org/licenses/by/3.0/ for more information. - kppkn.gtb is taken from the Gaviota chess tablebase set, and is licensed under the MIT License. See https://sites.google.com/site/gaviotachessengine/Home/endgame-tablebases-1 for more information. - paper-100k.pdf is an excerpt (bytes 92160 to 194560) from the paper "Combinatorial Modeling of Chromatin Features Quantitatively Predicts DNA Replication Timing in _Drosophila_" by Federico Comoglio and Renato Paro, which is licensed under the CC-BY license. See http://www.ploscompbiol.org/static/license for more ifnormation. - alice29.txt, asyoulik.txt, plrabn12.txt and lcet10.txt are from Project Gutenberg. The first three have expired copyrights and are in the public domain; the latter does not have expired copyright, but is still in the public domain according to the license information (http://www.gutenberg.org/ebooks/53). -------------------------------------------------------------------------------- 8. oneAPI DPC++ Compiler https://github.com/intel/llvm/ Apache License 2.0 with LLVM Exceptions Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ---- LLVM Exceptions to the Apache 2.0 License ---- As an exception, if, as a result of your compiling your source code, portions of this Software are embedded into an Object form of such source code, you may redistribute such embedded portions in such Object form without complying with the conditions of Sections 4(a), 4(b) and 4(d) of the License. In addition, if you combine or link compiled forms of this Software with software that is licensed under the GPLv2 ("Combined Software") and if a court of competent jurisdiction determines that the patent provision (Section 3), the indemnity provision (Section 9) or other Section of the License conflicts with the conditions of the GPLv2, you may retroactively and prospectively choose to deem waived or otherwise exclude such Section(s) of the License, but only in their entirety and only with respect to the Combined Software. -------------------------------------------------------------------------------- 9. Intel(R) oneAPI DPC++/C++ Compiler Intel End User License Agreement for Developer Tools (Version October 2021) IMPORTANT NOTICE - PLEASE READ AND AGREE BEFORE DOWNLOADING, INSTALLING, COPYING OR USING This Agreement is between you, or the company or other legal entity that you represent and warrant you have the legal authority to bind, (each, "You" or "Your") and Intel Corporation and its subsidiaries (collectively, "Intel") regarding Your use of the Materials. By downloading, installing, copying or using the Materials, You agree to be bound by the terms of this Agreement. If You do not agree to the terms of this Agreement, or do not have legal authority or required age to agree to them, do not download, install, copy or use the Materials. LICENSE DEFINITIONS. A. "Cloud Provider" means a third party service provider offering a cloud-based platform, infrastructure, application or storage services, such as Microsoft Azure or Amazon Web Services, which You may only utilize to host the Materials subject to the restrictions set forth in Section 2.3 B. B. "Derivative Work" means a derivative work, as defined in 17 U.S.C. § 101, of the Source Code. C. "Executable Code" means computer programming code in binary form suitable for machine execution by a processor without the intervening steps of interpretation or compilation. D. "Materials" mean the software, documentation, the software product serial number, and other collateral, including any updates, made available to You by Intel under this Agreement. Materials include Redistributables, Executable Code, Source Code, Sample Source Code, and Pre-Release Materials, but do not include Third Party Software. E. "Pre-Release Materials" mean the Materials, or portions of the Materials, that are identified (in the product release notes, on Intel's download website for the Materials or elsewhere) or labeled as pre-release, prototype, alpha or beta code and, as such, are deemed to be pre-release code (i) which may not be fully functional or tested and may contain bugs or errors; (ii) which Intel may substantially modify in its development of a production version; or (iii) for which Intel makes no assurances that it will ever develop or make a production version generally available. Pre-Release Materials are subject to the terms of Section 3.2. F. "Reciprocal Open Source Software" means any software that is subject to a license which requires that (i) it must be distributed in source code form; (ii) it must be licensed under the same open source license terms; and (iii) its derivative works must be licensed under the same open source license terms. Examples of this type of license are the GNU General Public License or the Mozilla Public License. G. "Redistributables" mean the files (if any) listed in the "redist.txt," "redist-rt.txt" or similarlynamed text files that may be included in the Materials. Redistributables include Sample Source Code. H. "Sample Source Code" means those portions of the Materials that are Source Code and are identified as sample code. Sample Source Code may not have been tested or validated by Intel and is provided purely as a programming example. I. "Source Code" means the software portion of the Materials provided in human readable format. J. "Third Party Software" mean the files (if any) listed in the "third-party-software.txt" or other similarly-named text file that may be included in the Materials for the applicable software. Third Party Software is subject to the terms of Section 2.2. K. "Your Product" means one or more applications, products or projects developed by or for You using the Materials. 2. LICENSE GRANTS. 2.1 License to the Materials. Subject to the terms and conditions of this Agreement, Intel grants You a non-exclusive, worldwide, non-assignable, non-sublicensable, limited right and license under its copyrights, to: A. reproduce internally a reasonable number of copies of the Materials for Your personal or business use; B. use the Materials solely for Your personal or business use to develop Your Product, in accordance with the documentation included as part of the Materials; C. modify or create Derivative Works only of the Redistributables, or any portions, that are provided to You in Source Code; D. distribute (directly and through Your distributors, resellers, and other channel partners, if applicable), the Redistributables, including any modifications to or Derivative Works of the Redistributables or any portions made pursuant to Section 2.1.C subject to the following conditions: (1) Any distribution of the Redistributables must only be as part of Your Product which must add significant primary functionality different than that of the Redistributables themselves; (2) You must only distribute the Redistributables originally provided to You by Intel only in Executable Code subject to a license agreement that prohibits reverse engineering, decompiling or disassembling the Redistributables; (3) This distribution right includes a limited right to sublicense only the Intel copyrights in the Redistributables and only to the extent necessary to perform, display, and distribute the Redistributables (including Your modifications and Derivative Works of the Redistributables provided in Source Code) solely as incorporated in Your Product; and (4) You: (i) will be solely responsible to Your customers for any update, support obligation or other obligation or liability which may arise from the distribution of Your Product, (ii) will not make any statement that Your Product is "certified" or that its performance is guaranteed by Intel or its suppliers, (iii) will not use Intel's or its suppliers' names or trademarks to market Your Product, (iv) will comply with any additional restrictions which are included in the text files with the Redistributables and in Section 3 below, (v) will indemnify, hold harmless, and defend Intel and its suppliers from and against any claims or lawsuits, costs, damages, and expenses, including attorney's fees, that arise or result from (a) Your modifications or Derivative Works of the Materials or (b) Your distribution of Your Product. 2.2 Third Party Software. Third Party Software, even if included with the distribution of the Materials, may be governed by separate license terms, including without limitation, third party license terms, open source software notices and terms, and/or other Intel software license terms. These separate license terms solely govern Your use of the Third Party Software. 2.3 Third Party Use. A. If You are an entity, Your contractors may use the Materials under the license specified in Section 2, provided: (i) their use of the Materials is solely on behalf of and in support of Your business, (ii) they agree to the terms and conditions of this Agreement, and (iii) You are solely responsible for their use, misuse or disclosure of the Materials. B. You may utilize a Cloud Provider to host the Materials for You, provided: (i) the Cloud Provider may only host the Materials for Your exclusive use and may not use the Materials for any other purpose whatsoever, including the restriction set forth in Section 3.1(xi); (ii) the Cloud Provider's use of the Materials must be solely on behalf of and in support of Your Product, and (iii) You will indemnify, hold harmless, and defend Intel and its suppliers from and against any claims or lawsuits, costs, damages, and expenses, including attorney's fees, that arise or result from Your Cloud Provider's use, misuse or disclosure of the Materials. 3. LICENSE CONDITIONS. 3.1 Restrictions. Except as expressly provided in this Agreement, You may NOT: (i) use, reproduce, disclose, distribute, or publicly display the Materials; (ii) share, publish, rent or lease the Materials to any third party; (iii) assign this Agreement or transfer the Materials; (iv) modify, adapt, or translate the Materials in whole or in part; (v) reverse engineer, decompile, or disassemble the Materials, or otherwise attempt to derive the source code for the software; (vi) work around any technical limitations in the Materials; (vii) distribute, sublicense or transfer any Source Code, modifications or Derivative Works of any Source Code to any third party; (viii) remove, minimize, block or modify any notices of Intel or its suppliers in the Materials; (ix) include the Redistributables in malicious, deceptive, or unlawful programs or products or use the Materials in any way that is against the law; (x) modify, create a Derivative Work, link, or distribute the Materials so that any part of it becomes Reciprocal Open Source Software; (xi) use the Materials directly or indirectly for SaaS services or service bureau purposes (i.e., a service that allows use of or access to the Materials by a third party as part of that service, such as the salesforce.com service business model). 3.2 Pre-Release Materials. If You receive Pre-Release Materials, You may reproduce a reasonable number of copies and use the Pre-Release Materials for evaluation and testing purposes only. You may not (i) modify or incorporate the Pre-Release Materials into Your Product; (ii) continue to use the Pre-Release Materials once a commercial version is released; or (iii) disclose to any third party any benchmarks, performance results, or other information relating to the Pre-Release Materials. Intel may waive these restrictions in writing at its sole discretion; however, if You decide to use the Pre-Release Materials in Your Product (even with Intel's waiver), You acknowledge and agree that You are fully responsible for any and all issues that result from such use. 3.3 Safety-Critical, and Life-Saving Applications; Indemnity. The Materials may provide information relevant to safety-critical applications ("Safety-Critical Applications") to allow compliance with functional safety standards or requirements. You acknowledge and agree that safety is Your responsibility. To the extent You use the Materials to create, or as part of, products used in Safety-Critical Applications, it is Your responsibility to design, manage, and ensure that there are system-level safeguards to anticipate, monitor, and control system failures, and You agree that You are solely responsible for all applicable regulatory standards and safety-related requirements concerning Your use of the Materials in Safety Critical Applications. Should You use the Materials for Safety-Critical Applications or in any type of a system or application in which the failure of the Materials could create a situation where personal injury or death may occur (e.g., medical systems, life-sustaining or life-saving systems) ("Life-Saving Applications"), You agree to indemnify, defend, and hold Intel and its representatives harmless against any claims or lawsuits, costs, damages, and expenses, including reasonable attorney fees, arising in any way out of Your use of the Materials in Safety-Critical Applications or Life-Saving Applications and claims of product liability, personal injury or death associated with those applications; even if such claims allege that Intel was negligent or strictly liable regarding the design or manufacture of the Materials or its failure to warn regarding the Materials. 3.4 Media Format Codecs and Digital Rights Management. You acknowledge and agree that Your use of the Materials or distribution of the Redistributables with Your Product as permitted by this Agreement may require You to procure license(s) from third parties that may hold intellectual property rights applicable to any media decoding, encoding or transcoding technology (e.g., the use of an audio or video codec) and/or digital rights management capabilities of the Materials, if any. Should any such additional licenses be required, You are solely responsible for obtaining any such licenses and agree to obtain any such licenses at Your own expense. 4. DATA COLLECTION AND PRIVACY. 4.1 Data Collection. The Materials may generate and collect anonymous data and/or provisioning data about the Materials and/or the development environment and transmit the data to Intel as a one-time event during installation. Optional data may also be collected by the Materials, however, You will be provided notice of the request to collect optional data and no optional data will be collected without Your consent. All data collection by Intel is performed pursuant to relevant privacy laws, including notice and consent requirements. 4.2 Intel's Privacy Notice. Intel is committed to respecting Your privacy. To learn more about Intel's privacy practices, please visit http://www.intel.com/privacy. 5. OWNERSHIP. Title to the Materials and all copies remain with Intel or its suppliers. The Materials are protected by intellectual property rights, including without limitation, United States copyright laws and international treaty provisions. You will not remove any copyright or other proprietary notices from the Materials. Except as expressly provided herein, no license or right is granted to You directly or by implication, inducement, estoppel or otherwise; specifically, Intel does not grant any express or implied right to You under Intel patents, copyrights, trademarks, or trade secrets. 6. NO WARRANTY AND NO SUPPORT. 6.1 No Warranty. Disclaimer. Intel disclaims all warranties of any kind and the terms and remedies provided in this Agreement are instead of any other warranty or condition, express, implied or statutory, including those regarding merchantability, fitness for any particular purpose, non-infringement or any warranty arising out of any course of dealing, usage of trade, proposal, specification or sample. Intel does not assume (and does not authorize any person to assume on its behalf) any liability. 6.2 No Support; Priority Support. Intel may make changes to the Materials, or to items referenced therein, at any time without notice, but is not obligated to support, update or provide training for the Materials under the terms of this Agreement. Intel offers free community and paid priority support options. More information on these support options can be found at: https://software.intel.com/content/www/us/en/develop/support/priority-support.html. 7. LIMITATION OF LIABILITY. 7.1 Intel will not be liable for any of the following losses or damages (whether such losses or damages were foreseen, foreseeable, known or otherwise): (i) loss of revenue; (ii) loss of actual or anticipated profits; (iii) loss of the use of money; (iv) loss of anticipated savings; (v) loss of business; (vi) loss of opportunity; (vii) loss of goodwill; (viii) loss of use of the Materials; (ix) loss of reputation; (x) loss of, damage to, or corruption of data; or (xi) any indirect, incidental, special or consequential loss of damage however caused (including loss or damage of the type specified in this Section 7). 7.2 Intel's total cumulative liability to You, including for direct damages for claims relating to this Agreement, and whether for breach of contract, negligence, or for any other reason, will not exceed $100. 7.3 You acknowledge that the limitations of liability provided in this Section 7 are an essential part of this Agreement. You agree that the limitations of liability provided in this Agreement with respect to Intel will be conveyed to and made binding upon any customer of Yours that acquires the Redistributables. 8. USER SUBMISSIONS. Should you provide Intel with comments, modifications, corrections, enhancements or other input ("Feedback") related to the Materials, Intel will be free to use, disclose, reproduce, license or otherwise distribute or exploit the Feedback in its sole discretion without any obligations or restrictions of any kind, including without limitation, intellectual property rights or licensing obligations. If You wish to provide Intel with information that You intend to be treated as confidential information, Intel requires that such confidential information be provided pursuant to a non-disclosure agreement ("NDA"); please contact Your Intel representative to ensure the proper NDA is in place. 9. NON-DISCLOSURE. Information provided by Intel to You may include information marked as confidential. You must treat such information as confidential under the terms of the applicable NDA between Intel and You. If You have not entered into an NDA with Intel, You must not disclose, distribute or make use of any information marked as confidential, except as expressly authorized in writing by Intel. Intel retains all rights in and to its confidential information specifications, designs, engineering details, discoveries, inventions, patents, copyrights, trademarks, trade secrets, and other proprietary rights relating to the Materials. Any breach by You of the confidentiality obligations provided for in this Section 9 will cause irreparable injury to Intel for which money damages may be inadequate to compensate Intel for losses arising from such a breach. Intel may obtain equitable relief, including injunctive relief, if You breach or threaten to breach Your confidentiality obligations. 10. TERM AND TERMINATION. This Agreement becomes effective on the date You accept this Agreement and will continue until terminated as provided for in this Agreement. The term for any Pre-Release Materials terminates upon release of a commercial version. This Agreement will terminate if You are in breach of any of its terms and conditions. Upon termination, You will promptly destroy the Materials and all copies. In the event of termination of this Agreement, Your license to any Redistributables distributed by You in accordance with the terms and conditions of this Agreement, prior to the effective date of such termination, will survive any such termination of this Agreement. Sections 1, 2.1.D(4)(v), 2.2, 2.3.A(iii), 2.3.B(iii), 3.3, 5, 6, 7, 8, 9, 10 (with respect to these survival provisions in the last sentence), and 12 will survive expiration or termination of this Agreement. 11. U.S. GOVERNMENT RESTRICTED RIGHTS. The technical data and computer software covered by this license is a "Commercial Item," as such term is defined by the FAR 2.101 (48 C.F.R. 2.101) and is "commercial computer software" and "commercial computer software documentation" as specified under FAR 12.212 (48 C.F.R. 12.212) or DFARS 227.7202 (48 C.F.R. 227.7202), as applicable. This commercial computer software and related documentation is provided to end users for use by and on behalf of the U.S. Government with only those rights as are granted to all other end users pursuant to the terms and conditions of this Agreement. 12. GENERAL PROVISIONS. 12.1 ENTIRE AGREEMENT. This Agreement contains the complete and exclusive agreement and understanding between the parties concerning the subject matter of this Agreement, and supersedes all prior and contemporaneous proposals, agreements, understanding, negotiations, representations, warranties, conditions, and communications, oral or written, between the parties relating to the same subject matter. Each party acknowledges and agrees that in entering into this Agreement it has not relied on, and will not be entitled to rely on, any oral or written representations, warranties, conditions, understanding, or communications between the parties that are not expressly set forth in this Agreement. The express provisions of this Agreement control over any course of performance, course of dealing, or usage of the trade inconsistent with any of the provisions of this Agreement. The provisions of this Agreement will prevail notwithstanding any different, conflicting, or additional provisions that may appear on any purchase order, acknowledgement, invoice, or other writing issued by either party in connection with this Agreement. No modification or amendment to this Agreement will be effective unless in writing and signed by authorized representatives of each party, and must specifically identify this Agreement by its title and version (e.g., "Intel End User License Agreement for Developer Tools (Version October 2021)"); except that Intel may make changes to this Agreement as it distributes new versions of the Materials. When changes are made, Intel will make a new version of the Agreement available on its website. If You received a copy of this Agreement translated into another language, the English language version of this Agreement will prevail in the event of any conflict between versions. 12.2 EXPORT. You acknowledge that the Materials and all related technical information are subject to export controls and you agree to comply with all laws and regulations of the United States and other applicable governments governing export, re-export, import, transfer, distribution, and use of the Materials. In particular, but without limitation, the Materials may not be exported or re-exported (i) into any U.S. embargoed countries or (ii) to any person or entity listed on a denial order published by the U.S. government or any other applicable governments. By using the Materials, You represent and warrant that You are not located in any such country or on any such list. You also agree that You will not use the Materials for, or sell or transfer them to a third party who is known or suspected to be involved in, any purposes prohibited by the U.S. government or other applicable governments, including, without limitation, the development, design, manufacture, or production of nuclear, missile, chemical or biological weapons. 12.3 GOVERNING LAW, JURISDICTION, AND VENUE. All disputes arising out of or related to this Agreement, whether based on contract, tort, or any other legal or equitable theory, will in all respects be governed by, and construed and interpreted under, the laws of the United States of America and the State of Delaware, without reference to conflict of laws principles. The parties agree that the United Nations Convention on Contracts for the International Sale of Goods (1980) is specifically excluded from and will not apply to this Agreement. All disputes arising out of or related to this Agreement, whether based on contract, tort, or any other legal or equitable theory, will be subject to the exclusive jurisdiction of the courts of the State of Delaware or of the Federal courts sitting in that State. Each party submits to the personal jurisdiction of those courts and waives all objections to that jurisdiction and venue for those disputes. 12.4 SEVERABILITY. The parties intend that if a court holds that any provision or part of this Agreement is invalid or unenforceable under applicable law, the court will modify the provision to the minimum extent necessary to make it valid and enforceable, or if it cannot be made valid and enforceable, the parties intend that the court will sever and delete the provision or part from this Agreement. Any change to or deletion of a provision or part of this Agreement under this Section will not affect the validity or enforceability of the remainder of this Agreement, which will continue in full force and effect. -------------------------------------------------------------------------------- The following third party programs have their own third party programs. These additional third party program files are as follows: 1. Embree: ./third-party-programs-Embree.txt 2. Open Image Denoise: ./third-party-programs-OIDN.txt 3. Open VKL: ./third-party-programs-OpenVKL.txt 4. oneAPI Threading Building Blocks: ./third-party-programs-oneTBB.txt 5. Implicit SPMD Program Compiler: ./third-party-programs-ISPC.txt 6. oneAPI DPC++ Compiler: ./third-party-programs-DPCPP.txt 7. Intel(R) oneAPI DPC++/C++ Compiler: ./third-party-programs-oneAPI-DPCPP.txt -------------------------------------------------------------------------------- Other names and brands may be claimed as the property of others.